Я пытаюсь создать приложение на Kotlin, которое будет взаимодействовать с блокчейном Solana. Я следовал официальным руководствам, но все еще сталкиваюсь с проблемой. Каждый раз, когда я пытаюсь вызвать эту функцию, нажав кнопку, она выполняется до этой строки val txResult = walletAdapter.transact(sender) { authResult ->
. Мне кажется, что проблема может быть не связана с Solana, но у меня недостаточно знаний о WebSocket, и я не могу найти решение где-либо.
suspend fun onBuyTicket(ticket: Ticket, sender: ActivityResultSender) {
val programId = SolanaPublicKey.from("FtyTxEhxtMcrzwag97cfabBCLzfdi5K6dhc81ybLqNqh")
// Логирование ID программы
Log.d("Juraj", "Program ID: $programId")
// Счетчик аккаунта имеет единственное семя 'counter'
val seeds = listOf("ticket".encodeToByteArray())
Log.d("Juraj", "Seeds: $seeds")
// Вычисляем PDA
val result = ProgramDerivedAddress.find(seeds, programId)
val counterAccountPDA = result.getOrNull()
Log.d("Juraj", "Calculated counterAccountPDA: $counterAccountPDA")
// Проверяем, успешно ли был рассчитан PDA
if (counterAccountPDA == null) {
Log.e("Juraj", "Не удалось рассчитать PDA")
return
}
// Распаковываем результат
val rpcClient = SolanaRpcClient("https://api.devnet.solana.com", KtorNetworkDriver())
val solanaUri = Uri.parse("https://jurajapp.com") // Заполнитель или общее URL
val iconUri = Uri.parse("https://example.com/icon.png") // Заполнитель или общий значок
val identityName = "Мое dApp" // Название вашего dApp
Log.d("Juraj", "Настройка адаптера кошелька с URI: $solanaUri, значок: $iconUri, название: $identityName")
val walletAdapter = MobileWalletAdapter(connectionIdentity = ConnectionIdentity(
identityUri = solanaUri,
iconUri = iconUri,
identityName = identityName
))
val encodedInstructionData = Borsh.encodeToByteArray(
AnchorInstructionSerializer("create_ticket"),
Args_ticket(ticket.id, ticket.name, ticket.departureTime, ticket.arrivalTime, ticket.price)
)
Log.d("Juraj", "Закодированные данные инструкции: ${encodedInstructionData.joinToString(",") { "%02x".format(it) }}")
val ticketInstruction = TransactionInstruction(
SolanaPublicKey.from("FtyTxEhxtMcrzwag97cfabBCLzfdi5K6dhc81ybLqNqh"),
listOf(AccountMeta(counterAccountPDA, false, true)),
encodedInstructionData
)
Log.d("Juraj", "Инструкция по билету: $ticketInstruction")
val blockhashResponse = rpcClient.getLatestBlockhash()
Log.d("Juraj", "Ответ на блокхэш: ${blockhashResponse.result?.blockhash}")
val buyTicketMessage = Message.Builder()
.addInstruction(ticketInstruction)
.setRecentBlockhash(blockhashResponse.result!!.blockhash)
.build()
Log.d("Juraj", "Сообщение о покупке билета собрано")
val unsignedIncrementTx = Transaction(buyTicketMessage)
Log.d("Juraj", "Несигнальная транзакция: ${unsignedIncrementTx.serialize().joinToString(",") { "%02x".format(it) }}")
val txResult = walletAdapter.transact(sender) { authResult ->
Log.d("Juraj", "Запрос транзакции выполнен")
val account = SolanaPublicKey(authResult.accounts.first().publicKey)
Log.d("Juraj", "Подписание и отправка транзакции для аккаунта: $account")
signAndSendTransactions(arrayOf(unsignedIncrementTx.serialize()))
}
when (txResult) {
is TransactionResult.Success -> {
Log.d("Juraj", "Транзакция успешна. Подпись:")
}
is TransactionResult.NoWalletFound -> {
Log.e("Juraj", "Кошелек не найден")
println("На устройстве не найдено совместимого приложения для кошельков MWA.")
}
is TransactionResult.Failure -> {
Log.e("Juraj", "Транзакция не удалась. Ошибка: ${txResult.e.message}")
println("Ошибка при подписании и отправке транзакций: ${txResult.e.message}")
}
}
}
Это происходит, когда я выбираю один из вариантов Phantom или Solflare
Ответ
Ошибка com.neovisionaries.ws.client.WebSocketException: Failed to connect
указывает на проблему с подключением к WebSocket-серверу, когда ваше приложение Kotlin пытается взаимодействовать с блокчейном Solana. Давайте разберем несколько возможных причин этой ошибки и предложим решения.
Возможные причины проблемы:
-
Неправильный URL WebSocket:
Убедитесь, что адрес, к которому вы пытаетесь подключиться, верный и поддерживает WebSocket-соединения. Часто WebSocket-адреса имеют форматwss://...
для защищенного соединения. Проверьте документацию Solana для получения актуального URL. -
Сетевые проблемы:
Проверьте ваше интернет-соединение. Если вы используете эмулятор, убедитесь, что он настроен на использование правильного сетевого интерфейса и имеет доступ к интернету. -
Брандмауэры и прокси-серверы:
Если вы находитесь в корпоративной сети или используете VPN, это может блокировать подключение к WebSocket. Попробуйте отключить VPN или протестируйте на другой сети. -
Настройки вашего устройства:
Проверьте настройки вашего устройства или эмулятора. Убедитесь, что они позволяют соединения через WebSocket. - Некорректные параметры подключения:
Возможно, в объектеMobileWalletAdapter
есть некорректные параметры, которые влияют на установление соединения с WebSocket. Убедитесь, чтоidentityUri
,iconUri
иidentityName
указаны корректно.
Решение проблемы:
-
Проверьте WebSocket URL:
Убедитесь, что вы подключаетесь к правильному адресу WebSocket. Например, проверьте, нужно ли использоватьwss://
. -
Тестирование с помощью других инструментов:
Проверьте, работает ли тот же WebSocket URL с помощью популярных инструментов (например, Postman или online WebSocket тестеры). Это поможет убедиться в том, что проблема не на стороне вашего кода. -
Логи и отладка:
Включите дополнительное логирование в вашем коде, чтобы понять, когда и почему именно возникает ошибка. Например, вы можете логировать параметры подключения перед попыткой установить соединение. - Utilize Async Code:
Убедитесь, что вы используете асинхронный код корректно. Если ваш методonBuyTicket
вызывается из асинхронного контекста, он может быть заблокирован, если вызываются блокирующие вызовы.
Вот пример, как изменить вас код для улучшения отладки:
try {
val txResult = walletAdapter.transact(sender) { authResult ->
Log.d("Juraj", "Transaction request made")
val account = SolanaPublicKey(authResult.accounts.first().publicKey)
Log.d("Juraj", "Signing and sending transaction for account: $account")
signAndSendTransactions(arrayOf(unsignedIncrementTx.serialize()))
}
when (txResult) {
is TransactionResult.Success -> {
Log.d("Juraj", "Transaction successful. Signature:")
}
is TransactionResult.NoWalletFound -> {
Log.e("Juraj", "No wallet found")
println("No MWA compatible wallet app found on device.")
}
is TransactionResult.Failure -> {
Log.e("Juraj", "Transaction failed. Error: ${txResult.e.message}")
println("Error during signing and sending transactions: ${txResult.e.message}")
}
}
} catch (e: WebSocketException) {
Log.e("Juraj", "WebSocket exception occurred: ${e.message}")
println("Failed to connect to the WebSocket: ${e.message}")
} catch (e: Exception) {
Log.e("Juraj", "An error occurred: ${e.message}")
println("An unexpected error occurred: ${e.message}")
}
Заключение
Если ни одно из предложенных решений не помогает, рекомендую обратиться в сообщество разработчиков Solana или просмотреть форумы для получения дополнительной информации. Иногда проблемы могут быть связаны с временными сбоями на стороне сервера или изменениям в API, о которых не упоминается в документации.