# Як відкрити dApp у мобільних гаманцях Solana

2026-08-10

React-dApp, побудований на `@solana/wallet-adapter-react`, без проблем
під'єднує десктопні гаманці, але на телефоні той самий потік розсипається:
гаманець має відкрити dApp у власному вбудованому браузері, а deeplinks, які
мали б це зробити, просто мовчки не спрацьовують. Backpack виводить на
сторінку «завантажте застосунок»; Solflare відкриває застосунок, але ніколи —
сайт; здається, що не працює жоден варіант. Ми розібрали проблему на частини,
і виявилося, що це чотири окремі проблеми з одним спільним симптомом.

## Чотири проблеми

- **Посилання для Backpack було сформоване неправильно.** Єдиний
  задокументований формат —
  `https://backpack.app/ul/v1/browse/<url>?ref=<ref>`: універсальне посилання
  із цільовим URL у шляху та обов'язковим `ref`. Здогадка з власною схемою на
  кшталт `backpack://ul/v1/browse?url=...` не збігається з жодним маршрутом,
  який реєструє застосунок, тож користувач опиняється на сторінці встановлення
  гаманця.
- **Solflare теж потребує свого універсального посилання:**
  `https://solflare.com/ul/v1/browse/<url>?ref=<ref>`, а не голої схеми
  `solflare://`. Гола схема може запустити застосунок, не спрямувавши його —
  а це саме те, що «застосунок відкривається, але вкладку із сайтом
  доводиться відкривати вручну».
- **Обидва параметри мають бути закодовані.** `url` — це повна абсолютна
  адреса dApp, а `ref` — origin, який робить запит; кожен проходить через
  `encodeURIComponent`. Незакодований `?` або `&` у цілі псує розбір, і
  гаманець відкривається на своєму головному екрані замість вкладки браузера.
- **Спосіб запуску важить не менше за саме посилання.** Універсальні посилання
  перемикають застосунки лише під час навігації, якій довіряє операційна
  система — і вони навмисно не роблять нічого, коли їх вставляють в адресний
  рядок, і саме так цілком коректне посилання «не працює» під час тестування.

## Задокументовані формати

- Phantom: `https://phantom.app/ul/browse/<url>?ref=<ref>` — саме тут без
  `/v1`.
- Solflare: `https://solflare.com/ul/v1/browse/<url>?ref=<ref>`
- Backpack: `https://backpack.app/ul/v1/browse/<url>?ref=<ref>`

Один шаблон покриває всі три:

```
const WALLET_BROWSE = {
  phantom: (url, ref) =>
    `https://phantom.app/ul/browse/${url}?ref=${ref}`,
  solflare: (url, ref) =>
    `https://solflare.com/ul/v1/browse/${url}?ref=${ref}`,
  backpack: (url, ref) =>
    `https://backpack.app/ul/v1/browse/${url}?ref=${ref}`,
};

function walletBrowseLink(
  walletName,
  targetUrl = window.location.href,
) {
  const build = WALLET_BROWSE[walletName.toLowerCase()];
  if (!build) return null;
  return build(
    encodeURIComponent(targetUrl),
    encodeURIComponent(window.location.origin),
  );
}
```

## Як запустити посилання, щоб iOS та Android його прийняли

- **Рендерте справжній якір, обчислений заздалегідь.** Звичайний
  `<a href={walletBrowseLink('phantom')}>` — найнадійніший спосіб запуску на
  обох платформах.
- **Якщо це має бути програмно**, присвоюйте `window.location.href` синхронно
  всередині обробника натискання — без `await`, без `fetch`, без `setTimeout`
  перед цим. Після асинхронної роботи контекст жесту втрачено, і iOS
  відкочується до вебсайту гаманця. Ніколи не використовуйте `window.open`.
- **Ніколи не тестуйте вставлянням в адресний рядок.** Універсальні посилання
  навмисно там не спрацьовують; тестуйте посиланням, на яке натискають, або
  QR-кодом, який сканує камера.
- **Зважайте на webview месенджерів.** Відкриті у вбудованому браузері
  Telegram або Instagram, універсальні посилання часто просто поглинаються, і
  натомість завантажується звичайний вебсайт гаманця. Визначення за
  user-agent — у кращому разі евристика, тож дайте користувачам ще й видимий
  запасний вихід: «відкрийте в Safari чи Chrome, а тоді під'єднайтеся».

## Ґрунтовніше виправлення на Android

Саморобні deeplinks — це історія про iOS. На Android Mobile Wallet Adapter від
Solana Mobile дає dApp, що працює в мобільному браузері, під'єднатися прямо до
встановленого застосунку гаманця, узагалі без гаку через вбудований браузер.
Свіжі версії `@solana/wallet-adapter-react` реєструють мобільний адаптер
автоматично, тож оновлення пакетів wallet-adapter може полагодити Android саме
собою. Цільова архітектура: Mobile Wallet Adapter на Android, універсальні
browse-посилання на iOS, де Apple не дозволяє нічого рівноцінного.

## Перевірка на пристрої

1. Справжній пристрій, встановлений гаманець, посилання відкрито із системного
   браузера — не з месенджера.
2. Натисніть відрендерене посилання або відскануйте QR-код; ніколи не
   вставляйте в адресний рядок.
3. Переконайтеся, що гаманець відкривається і dApp завантажується у вкладці
   його вбудованого браузера — саме друга половина і ламається.
4. Повторіть без встановленого гаманця: універсальне посилання має деградувати
   до вебсайту гаманця. Якщо ця сторінка з'являється, коли застосунок
   встановлено, — посилання або спосіб запуску все ще неправильні.
5. Потім перевірте шлях через месенджер і додайте підказку «відкрийте у
   браузері», якщо там не спрацьовує.

## Джерела

- [Phantom: deeplinks на iOS та Android](https://docs.phantom.com/phantom-deeplinks/deeplinks-ios-and-android)
- [Solflare: Browse-deeplink](https://docs.solflare.com/solflare/technical/deeplinks/other-methods/browse)
- [Backpack: Browse-deeplink](https://docs.backpack.app/deeplinks/other-methods/browse)
- [Solana Mobile: Mobile Wallet Adapter](https://docs.solanamobile.com/mobile-wallet-adapter/mobile-apps)

<https://engineer.company/uk/notes/solana-mobile-wallet-deeplinks/>
