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). Порядок обробки:
- Извлечіть рядок URI.
- Валідуйте схему (
solana:) та наявність обов'язкових параметрів. - Декодуйте транзакцію з відповідного кодування.
- Валідуйте мінімальну структуру транзакції (наявність заголовка, кількість інструкцій не нульова).
- Передайте на підписання через 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-бекенду.