stack_wallet/lib/utilities/test_node_connection.dart

283 lines
7.5 KiB
Dart
Raw Normal View History

2024-05-15 21:20:45 +00:00
import 'dart:async';
import 'dart:convert';
import 'dart:io';
2024-05-15 21:20:45 +00:00
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
2024-08-26 17:38:58 +00:00
import 'package:on_chain/ada/ada.dart';
import 'package:on_chain/ada/src/provider/provider/provider.dart';
2024-09-01 13:19:46 +00:00
import 'package:socks5_proxy/socks.dart';
import '../networking/http.dart';
import '../pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart';
import '../providers/global/prefs_provider.dart';
import '../services/tor_service.dart';
2024-08-26 17:38:58 +00:00
import '../wallets/api/cardano/blockfrost_http_provider.dart';
import '../wallets/api/tezos/tezos_rpc_api.dart';
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';
2024-06-28 22:05:20 +00:00
import '../wallets/wallet/impl/solana_wallet.dart';
import 'connection_check/electrum_connection_check.dart';
import 'logger.dart';
import 'test_epic_box_connection.dart';
import 'test_eth_node_connection.dart';
import 'test_monero_node_connection.dart';
import 'test_stellar_node_connection.dart';
2024-05-15 21:20:45 +00:00
Future<bool> _xmrHelper(
NodeFormData nodeFormData,
BuildContext context,
void Function(NodeFormData)? onSuccess,
({
InternetAddress host,
int port,
})? proxyInfo,
2024-05-15 21:20:45 +00:00
) async {
final data = nodeFormData;
final url = data.host!;
final port = data.port;
final uri = Uri.parse(url);
final String path = uri.path.isEmpty ? "/json_rpc" : uri.path;
final uriString = "${uri.scheme}://${uri.host}:${port ?? 0}$path";
if (proxyInfo == null && uri.host.endsWith(".onion")) {
return false;
}
2024-05-15 21:20:45 +00:00
final response = await testMoneroNodeConnection(
Uri.parse(uriString),
false,
proxyInfo: proxyInfo,
).timeout(Duration(seconds: proxyInfo != null ? 30 : 10));
2024-05-15 21:20:45 +00:00
if (response.cert != null) {
if (context.mounted) {
final shouldAllowBadCert = await showBadX509CertificateDialog(
response.cert!,
response.url!,
response.port!,
context,
);
if (shouldAllowBadCert) {
final response = await testMoneroNodeConnection(
Uri.parse(uriString),
true,
proxyInfo: proxyInfo,
);
2024-05-15 21:20:45 +00:00
onSuccess?.call(data..host = url);
return response.success;
}
}
} else {
onSuccess?.call(data..host = url);
return response.success;
}
return false;
}
// TODO: probably pull this into each coin's functionality otherwise updating this separately will get irritating
Future<bool> testNodeConnection({
required BuildContext context,
required NodeFormData nodeFormData,
required CryptoCurrency cryptoCurrency,
required WidgetRef ref,
void Function(NodeFormData)? onSuccess,
}) async {
final formData = nodeFormData;
bool testPassed = false;
switch (cryptoCurrency) {
case Epiccash():
try {
final data = await testEpicNodeConnection(formData);
if (data != null) {
testPassed = true;
onSuccess?.call(data);
}
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning);
}
break;
case CryptonoteCurrency():
try {
2024-08-26 17:38:58 +00:00
final proxyInfo = ref
.read(prefsChangeNotifierProvider)
.useTor
? ref.read(pTorService).getProxyInfo()
: null;
2024-05-15 21:20:45 +00:00
final url = formData.host!;
final uri = Uri.tryParse(url);
if (uri != null) {
2024-08-08 21:37:20 +00:00
if (!uri.hasScheme && !uri.host.endsWith(".onion")) {
2024-05-15 21:20:45 +00:00
// try https first
testPassed = await _xmrHelper(
formData
..host = "https://$url"
..useSSL = true,
context,
onSuccess,
proxyInfo,
2024-05-15 21:20:45 +00:00
);
if (testPassed == false && context.mounted) {
2024-05-15 21:20:45 +00:00
// try http
testPassed = await _xmrHelper(
formData
..host = "http://$url"
..useSSL = false,
context,
onSuccess,
proxyInfo,
2024-05-15 21:20:45 +00:00
);
}
} else {
testPassed = await _xmrHelper(
formData
..host = url
..useSSL = true,
context,
onSuccess,
proxyInfo,
2024-05-15 21:20:45 +00:00
);
}
}
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning);
}
break;
case ElectrumXCurrencyInterface():
case BitcoinFrost():
try {
testPassed = await checkElectrumServer(
host: formData.host!,
port: formData.port!,
useSSL: formData.useSSL!,
overridePrefs: ref.read(prefsChangeNotifierProvider),
overrideTorService: ref.read(pTorService),
);
} catch (_) {
testPassed = false;
}
break;
case Ethereum():
try {
testPassed = await testEthNodeConnection(formData.host!);
} catch (_) {
testPassed = false;
}
break;
case Stellar():
try {
testPassed =
2024-08-26 17:38:58 +00:00
await testStellarNodeConnection(formData.host!, formData.port!);
2024-05-15 21:20:45 +00:00
} catch (_) {}
break;
case NanoCurrency():
2024-06-12 21:13:34 +00:00
try {
final uri = Uri.parse(formData.host!);
final response = await HTTP().post(
url: uri,
headers: {"Content-Type": "application/json"},
body: jsonEncode(
{
"action": "version",
},
),
2024-08-26 17:38:58 +00:00
proxyInfo: ref
.read(prefsChangeNotifierProvider)
.useTor
2024-06-12 21:13:34 +00:00
? ref.read(pTorService).getProxyInfo()
: null,
);
testPassed = response.code == 200;
} catch (_) {}
break;
2024-05-15 21:20:45 +00:00
case Tezos():
try {
testPassed = await TezosRpcAPI.testNetworkConnection(
nodeInfo: (host: formData.host!, port: formData.port!),
);
} catch (_) {}
break;
case Solana():
try {
2024-06-28 22:05:20 +00:00
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;
2024-05-15 21:20:45 +00:00
} catch (_) {
testPassed = false;
}
break;
2024-08-26 17:38:58 +00:00
case Cardano():
try {
2024-09-01 13:19:46 +00:00
final client = HttpClient();
if (ref
.read(prefsChangeNotifierProvider)
.useTor) {
final proxyInfo = TorService.sharedInstance.getProxyInfo();
final proxySettings = ProxySettings(
proxyInfo.host,
proxyInfo.port,
);
SocksTCPClient.assignToHttpClient(client, [proxySettings]);
}
2024-08-26 17:38:58 +00:00
final blockfrostProvider = BlockforestProvider(
BlockfrostHttpProvider(
url: "${formData.host!}:${formData.port!}/api/v0",
2024-09-01 13:19:46 +00:00
client: client,
2024-08-26 17:38:58 +00:00
),
);
final health = await blockfrostProvider.request(
BlockfrostRequestBackendHealthStatus(),
);
Logging.instance.log(
"Cardano testNodeConnection \"health=$health\"",
level: LogLevel.Info,
);
return health;
} catch (_) {
testPassed = false;
}
break;
2024-05-15 21:20:45 +00:00
}
return testPassed;
}