Solana Mobile SDK дозволяє Android-застосункам взаємодіяти з мобільними гаманцями безпосередньо на пристрої, оминаючи веб-мости та зовнішні браузери. Це зменшує затримку підписання, усуває клас векторів атак, пов'язаних із перехопленням дип-лінків, і дає змогу працювати з локальними фічами пристрою — біометрією, secure enclave, push-сповіщеннями. Нижче — покрокова інженерна інструкція з ініціалізації SDK, підписання транзакцій, роботи з дип-лінками та обмежень, з якими ви зіткнетеся в production.

Встановлення та ініціалізація SDK

Передумови та середовище

  • Android Studio з актуальними інструментами збірки (перевірте вимоги у репозиторії SDK перед початком).
  • Мінімальний рівень Android API — перевірте актуальне значення в документації до версії SDK, яку плануєте використовувати.
  • Фізичний Android-пристрій або емулятор із встановленим гаманцем, що підтримує Mobile Wallet Adapter (MWA) — наприклад, Phantom або Solflare для Android.
  • Базове розуміння протоколу MWA та життєвого циклу Activity у Android.

Підключення залежності

Додайте залежність до файлу build.gradle на рівні модуля. Конкретну версію вказуйте з офіційного репозиторію — на момент читання цього матеріалу вона могла оновитися:

Уникайте вказування версії LATEST або + у production-збірках. Це непередбачувано змінює бінарник між деплоями та ускладнює відтворення інцидентів.

Ініціалізація

SDK ініціалізується через створення екземпляра MobileWalletAdapter у контексті Activity. Ключовий момент — життєвий цикл: об'єкт прив'язується до Activity і повинен коректно звільняти ресурси при знищенні.

Базовий патерн ініціалізації виглядає так: ви створюєте екземпляр адаптера, передаєте контекст Activity та реєструєте колбеки для результатів авторизації та підписання. Усі операції з SDK є асинхронними і повертають результат через ці колбеки.

Очікуваний результат: після ініціалізації адаптер готовий до виклику authorize(), але ще не встановив з'єднання з гаманцем — це станиться лише за явного запиту користувача.

Перевірка: додайте логування на етап створення адаптера та перевірте, що об'єкт не є null і колбеки зареєстровані до виклику будь-яких методів.

План відкату: якщо ініціалізація завершується помилкою, перевірте сумісність версії SDK з вашим мінімальним API-рівнем. Відкат — видалення залежності та повернення до попередньої стабільної версії з build.gradle.

Підписання транзакцій через мобільний гаманець

Життєвий цикл підписання

Підписання через MWA складається з двох основних етапів: авторизації та безпосереднього підписання.

1. Авторизація (authorize). Ваш застосунок запитує у гаманця публічний ключ та токен сесії. На цьому етапі користувач бачить системний UI з вибором гаманця (якщо встановлено кілька) та підтвердженням доступу. Успішна авторизація повертає публічна адреса та об'єкт сесії, який використовується для подальших запитів без повторного підтвердження — доки сесія активна.

2. Підписання транзакцій (signTransactions). Ви передаєте масив серіалізованих транзакцій (у форматі byte[]). Гаманець розкриває їх, показує користувачу деталі (відправник, одержувач, суми, інструкції) і за підтвердження підписує відповідними приватними ключами. Ваш застосунок отримує масив підписаних транзакцій.

Критичне зауваження: ваш застосунок ніколи не отримує доступ до приватних ключів. Підписання відбувається повністю в процесі гаманця. Це архітектурна властивість протоколу MWA, а не просто обмеження SDK.

Типові помилки та їхні фактичні причини

  • Помилка підписання з кодом, що вказує на невідповідність підписувача. Фактична причина: транзакція сформована з одним публічним ключем (наприклад, з бекенду), а авторизований гаманець повернув інший. Перевірте, що адрес у authorize збігається з тим, який ви вказуєте як signer у транзакції.
  • Гаманець повертає порожній масив підписів. Фактична причина: користувач відхилив підписання в UI гаманця, але SDK не прокинув це як явну помилку відхилення. Обробляйте як user-reject, а не як технічну помилку.
  • Транзакція серіалізована некоректно, гаманець не може її десеріалізувати. Фактична причина: передача об'єкта замість byte[], або використання формату, несумісного з поточною версією гаманця. Перевірте байтове представлення транзакції до передачі в SDK.

Ризики в production: якщо гаманець зависає або крашиться під час підписання, SDK може не повернути колбек. Реалізуйте таймаут на рівні вашого застосунку (рекомендовано перевірити актуальне значення в документації) і показуйте користувачу діалог із можливістю повторити спробу.

Перевірка: після отримання підписаної транзакції валідуйте підпис стандартним способом (наприклад, через ed25519_verify) перед відправкою в мережу. Не довіряйте підписам «на слово» — це захист від malformed-відповідей гаманця.

Робота з мобільними дип-лінками

Схема URI та призначення

Solana використовує URI-схему solana: для дип-лінків. Вона дозволяє веб-застосункам та іншим нативним застосункам передавати транзакційні дані в мобільний гаманець або ваш mPOS-застосунок. У контексті Solana Mobile SDK дип-лінки використовуються для двох сценаріїв:

  • Вхідний дип-лінк: ваш застосунок отримує транзакцію ззовні (наприклад, з десктопного веб-застосунку) і повинен її обробити.
  • Вихідний дип-лінк: ваш застосунок формує посилання для передачі даних у гаманець, коли MWA-протокол недоступний (fallback-сценарій).

Налаштування в Android Manifest

Для обробки вхідних дип-лінків додайте intent-filter до відповідної Activity у AndroidManifest.xml. Фільтр має перехоплювати URI зі схемою solana:. Обов'язково вкажіть android:exported="true" — без цього Android не доставить інтент із зовнішнього джерела.

Очікуваний результат: при натисканні на solana:... посилання в браузері або іншому застосунку відкривається ваша Activity і ви отримуєте URI через getIntent().getData().

Парсинг та валідація дип-лінків

URI містить серіалізовану транзакцію в параметрі (зазвичай у кодуванні base64 або base58). Порядок обробки:

  1. Извлечіть рядок URI.
  2. Валідуйте схему (solana:) та наявність обов'язкових параметрів.
  3. Декодуйте транзакцію з відповідного кодування.
  4. Валідуйте мінімальну структуру транзакції (наявність заголовка, кількість інструкцій не нульова).
  5. Передайте на підписання через MWA або обробіть відповідно до бізнес-логіки.

Типова помилка: довіряти вмісту дип-лінку без валідації. Фактична причина — будь-який застосунок на пристрої може сформувати solana: URI. Без перевірки структури ви можете передати некоректні дані в гаманець або спробувати десеріалізувати довільні байти.

Fallback-механізм

Якщо на пристрої немає гаманця з підтримкою MWA, ваш застосунок може сформувати дип-лінк і передати його в системний вибір застосунку (Intent.ACTION_VIEW). Це дозволяє користувачу обрати будь-який встановлений гаманець, що підтримує solana: схему, навіть без нативної інтеграції через MWA.

Обмеження fallback: ви не отримаєте структуровану відповідь назад. Користувач повернеться у ваш застосунок без контексту підписання — вам доведеться перевіряти статус транзакції через RPC самостійно.

Обмеження та відомі проблеми SDK

Платформні обмеження

  • Solana Mobile SDK орієнтований виключно на Android. Для iOS наявний окремий підхід через Mobile Wallet Adapter для iOS, але це інша кодова база з іншим API. Не намагайтеся портувати Android-код безпосередньо.
  • Підтримка емуляторів обмежена. Деякі гаманці не встановлюються на емулятори або не реєструють себе як MWA-провайдери в цьому середовищі. Для повноцінного тестування потрібен фізичний пристрій.

Проблеми сумісності гаманців

Різні гаманці реалізують MWA-протокол з нюансами. Відомі категорії проблем:

  • Різне поводження з багатопідписними транзакціями. Деякі гаманці показують кожен підпис окремо, інші — усі разом. Це впливає на UX, але не на технічний результат.
  • Обмеження розміру транзакції. Гаманець може відхилити транзакцію, що перевищує певний розмір у байтах, навіть якщо мережа Solana технічно її прийме. Перевірте ліміти конкретного гаманця, з яким інтегруєтеся.
  • Нестабільність сесій. Деякі гаманці термінують сесію раніше, ніж очікує ваш застосунок. Реалізуйте повторну авторизацію як частину стандартного потоку, а не як виняткову ситуацію.

Відомі проблеми SDK

  • Колбеки, що не викликаються при специфічних станах Activity. Якщо користувач перемикає застосунок під час процесу підписання (наприклад, натискає кнопку «Home»), колбек може не спрацювати на деяких версіях SDK. Мітігція — таймаут на рівні застосунку та моніторинг стану Activity.
  • Витоки пам'яті при повторному створенні адаптера. Якщо ви створюєте новий екземпляр MobileWalletAdapter при кожному повороті екрана без звільнення попереднього, це призводить до накопичення об'єктів. Рішення — прив'язувати життєвий цикл адаптера до ViewModel або використовувати патерн singleton у межах Activity.

Межі застосування

Solana Mobile SDK підходить для застосунків, де користувач взаємодіє з блокчейном безпосередньо з мобільного пристрою: mPOS-термінали, мобільні NFT-маркетплейси, DeFi-клієнти, gaming-застосунки з токен-економікою. Якщо ваш сценарій передбачає виключно серверне підписання або batch-обробку транзакцій без участі користувача, SDK не потрібен — використовуйте серверні інструменти та RPC безпосередньо.

Для діагностики проблем у production логуйте етапи життєвого циклу MWA-сесії (створення, авторизація, підписання, завершення) з унікальними ідентифікаторами сесії. Це дозволить корелювати логи вашого застосунку з поведінкою гаманця при розслідуванні інцидентів. Якщо вам потрібна системна observability для бекенду, що обслуговує мобільних клієнтів, перейдіть до наступного матеріалу — Як налаштувати observability для Solana-бекенду.

Джерела