diff --git a/lib/utilities/test_node_connection.dart b/lib/utilities/test_node_connection.dart index 5578d5fd0..2160671db 100644 --- a/lib/utilities/test_node_connection.dart +++ b/lib/utilities/test_node_connection.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:solana/solana.dart'; import '../networking/http.dart'; import '../pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart'; @@ -15,6 +14,7 @@ import '../wallets/crypto_currency/crypto_currency.dart'; import '../wallets/crypto_currency/interfaces/electrumx_currency_interface.dart'; import '../wallets/crypto_currency/intermediate/cryptonote_currency.dart'; import '../wallets/crypto_currency/intermediate/nano_currency.dart'; +import '../wallets/wallet/impl/solana_wallet.dart'; import 'connection_check/electrum_connection_check.dart'; import 'logger.dart'; import 'test_epic_box_connection.dart'; @@ -210,14 +210,20 @@ Future testNodeConnection({ case Solana(): try { - RpcClient rpcClient; - if (formData.host!.startsWith("http") || - formData.host!.startsWith("https")) { - rpcClient = RpcClient("${formData.host}:${formData.port}"); - } else { - rpcClient = RpcClient("http://${formData.host}:${formData.port}"); - } - await rpcClient.getEpochInfo().then((value) => testPassed = true); + final rpcClient = SolanaWallet.createRpcClient( + formData.host!, + formData.port!, + formData.useSSL ?? false, + ref.read(prefsChangeNotifierProvider), + ref.read(pTorService), + ); + + final health = await rpcClient.getHealth(); + Logging.instance.log( + "Solana testNodeConnection \"health=$health\"", + level: LogLevel.Info, + ); + return true; } catch (_) { testPassed = false; } diff --git a/lib/wallets/crypto_currency/coins/solana.dart b/lib/wallets/crypto_currency/coins/solana.dart index 1505abead..6cfc185e1 100644 --- a/lib/wallets/crypto_currency/coins/solana.dart +++ b/lib/wallets/crypto_currency/coins/solana.dart @@ -46,8 +46,7 @@ class Solana extends Bip39Currency { switch (network) { case CryptoCurrencyNetwork.main: return NodeModel( - host: - "https://api.mainnet-beta.solana.com/", // TODO: Change this to stack wallet one + host: "https://solana.stackwallet.com", port: 443, name: DefaultNodes.defaultName, id: DefaultNodes.buildId(this), @@ -70,9 +69,13 @@ class Solana extends Bip39Currency { @override bool validateAddress(String address) { - return isPointOnEd25519Curve( - Ed25519HDPublicKey.fromBase58(address).toByteArray(), - ); + try { + return isPointOnEd25519Curve( + Ed25519HDPublicKey.fromBase58(address).toByteArray(), + ); + } catch (_) { + return false; + } } @override diff --git a/lib/wallets/wallet/impl/solana_wallet.dart b/lib/wallets/wallet/impl/solana_wallet.dart index 50ff0b31a..5cbfda157 100644 --- a/lib/wallets/wallet/impl/solana_wallet.dart +++ b/lib/wallets/wallet/impl/solana_wallet.dart @@ -18,6 +18,7 @@ import '../../../services/node_service.dart'; import '../../../services/tor_service.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/logger.dart'; +import '../../../utilities/prefs.dart'; import '../../crypto_currency/crypto_currency.dart'; import '../../models/tx_data.dart'; import '../intermediate/bip39_wallet.dart'; @@ -245,14 +246,15 @@ class SolanaWallet extends Bip39Wallet { } @override - Future pingCheck() { + Future pingCheck() async { + String? health; try { _checkClient(); - _rpcClient?.getHealth(); - return Future.value(true); + health = await _rpcClient?.getHealth(); + return health != null; } catch (e, s) { Logging.instance.log( - "$runtimeType Solana pingCheck failed: $e\n$s", + "$runtimeType Solana pingCheck failed \"health=$health\": $e\n$s", level: LogLevel.Error, ); return Future.value(false); @@ -453,32 +455,67 @@ class SolanaWallet extends Bip39Wallet { } @override - Future updateUTXOs() { + Future updateUTXOs() async { // No UTXOs in Solana - return Future.value(false); + return false; } /// Make sure the Solana RpcClient uses Tor if it's enabled. /// - void _checkClient() async { + void _checkClient() { + final node = getCurrentNode(); + _rpcClient = createRpcClient( + node.host, + node.port, + node.useSSL, + prefs, + TorService.sharedInstance, + ); + } + + // static helper function for building a sol rpc client + static RpcClient createRpcClient( + final String host, + final int port, + final bool useSSL, + final Prefs prefs, + final TorService torService, + ) { HttpClient? httpClient; if (prefs.useTor) { // Make proxied HttpClient. - final ({InternetAddress host, int port}) proxyInfo = - TorService.sharedInstance.getProxyInfo(); + final proxyInfo = torService.getProxyInfo(); final proxySettings = ProxySettings(proxyInfo.host, proxyInfo.port); httpClient = HttpClient(); SocksTCPClient.assignToHttpClient(httpClient, [proxySettings]); } - _rpcClient = RpcClient( - "${getCurrentNode().host}:${getCurrentNode().port}", + final regex = RegExp("^(http|https)://"); + + String editedHost; + if (host.startsWith(regex)) { + editedHost = host.replaceFirst(regex, ""); + } else { + editedHost = host; + } + + while (editedHost.endsWith("/")) { + editedHost = editedHost.substring(0, editedHost.length - 1); + } + + final uri = Uri( + scheme: useSSL ? "https" : "http", + host: editedHost, + port: port, + ); + + return RpcClient( + uri.toString(), timeout: const Duration(seconds: 30), customHeaders: {}, httpClient: httpClient, ); - return; } }