Merge pull request #886 from cypherstack/arti

Bump arti to 1.2.4 and enable onion nodes
This commit is contained in:
Diego Salazar 2024-06-24 19:32:51 -06:00 committed by GitHub
commit fc3239ce0f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 152 additions and 76 deletions

View file

@ -9,7 +9,6 @@
*/
import 'package:decimal/decimal.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import 'package:isar/isar.dart';
import 'package:tuple/tuple.dart';
@ -21,6 +20,7 @@ import '../../models/isar/models/isar_models.dart';
import '../../models/isar/ordinal.dart';
import '../../models/isar/stack_theme.dart';
import '../../utilities/amount/amount.dart';
import '../../utilities/extensions/extensions.dart';
import '../../utilities/stack_file_system.dart';
import '../../wallets/crypto_currency/crypto_currency.dart';
import '../../wallets/isar/models/frost_wallet_info.dart';

View file

@ -208,7 +208,7 @@ class ElectrumXClient {
await getElectrumAdapter()?.close();
}
Future<void> _checkElectrumAdapter() async {
Future<void> checkElectrumAdapter() async {
({InternetAddress host, int port})? proxyInfo;
// If we're supposed to use Tor...
@ -311,9 +311,9 @@ class ElectrumXClient {
if (_requireMutex) {
await _torConnectingLock
.protect(() async => await _checkElectrumAdapter());
.protect(() async => await checkElectrumAdapter());
} else {
await _checkElectrumAdapter();
await checkElectrumAdapter();
}
try {
@ -397,9 +397,9 @@ class ElectrumXClient {
if (_requireMutex) {
await _torConnectingLock
.protect(() async => await _checkElectrumAdapter());
.protect(() async => await checkElectrumAdapter());
} else {
await _checkElectrumAdapter();
await checkElectrumAdapter();
}
try {
@ -780,7 +780,7 @@ class ElectrumXClient {
"attempting to fetch blockchain.transaction.get...",
level: LogLevel.Info,
);
await _checkElectrumAdapter();
await checkElectrumAdapter();
final dynamic response = await getElectrumAdapter()!.getTransaction(txHash);
Logging.instance.log(
"Fetching blockchain.transaction.get finished",
@ -817,7 +817,7 @@ class ElectrumXClient {
"attempting to fetch lelantus.getanonymityset...",
level: LogLevel.Info,
);
await _checkElectrumAdapter();
await checkElectrumAdapter();
final Map<String, dynamic> response =
await (getElectrumAdapter() as FiroElectrumClient)
.getLelantusAnonymitySet(groupId: groupId, blockHash: blockhash);
@ -840,7 +840,7 @@ class ElectrumXClient {
"attempting to fetch lelantus.getmintmetadata...",
level: LogLevel.Info,
);
await _checkElectrumAdapter();
await checkElectrumAdapter();
final dynamic response = await (getElectrumAdapter() as FiroElectrumClient)
.getLelantusMintData(mints: mints);
Logging.instance.log(
@ -860,7 +860,7 @@ class ElectrumXClient {
"attempting to fetch lelantus.getusedcoinserials...",
level: LogLevel.Info,
);
await _checkElectrumAdapter();
await checkElectrumAdapter();
int retryCount = 3;
dynamic response;
@ -888,7 +888,7 @@ class ElectrumXClient {
"attempting to fetch lelantus.getlatestcoinid...",
level: LogLevel.Info,
);
await _checkElectrumAdapter();
await checkElectrumAdapter();
final int response =
await (getElectrumAdapter() as FiroElectrumClient).getLatestCoinId();
Logging.instance.log(
@ -920,7 +920,7 @@ class ElectrumXClient {
}) async {
try {
final start = DateTime.now();
await _checkElectrumAdapter();
await checkElectrumAdapter();
final Map<String, dynamic> response =
await (getElectrumAdapter() as FiroElectrumClient)
.getSparkAnonymitySet(
@ -995,7 +995,7 @@ class ElectrumXClient {
"attempting to fetch spark.getsparkmintmetadata...",
level: LogLevel.Info,
);
await _checkElectrumAdapter();
await checkElectrumAdapter();
final List<dynamic> response =
await (getElectrumAdapter() as FiroElectrumClient)
.getSparkMintMetaData(sparkCoinHashes: sparkCoinHashes);
@ -1021,7 +1021,7 @@ class ElectrumXClient {
"attempting to fetch spark.getsparklatestcoinid...",
level: LogLevel.Info,
);
await _checkElectrumAdapter();
await checkElectrumAdapter();
final int response = await (getElectrumAdapter() as FiroElectrumClient)
.getSparkLatestCoinId();
Logging.instance.log(
@ -1150,7 +1150,7 @@ class ElectrumXClient {
/// "rate": 1000,
/// }
Future<Map<String, dynamic>> getFeeRate({String? requestID}) async {
await _checkElectrumAdapter();
await checkElectrumAdapter();
return await getElectrumAdapter()!.getFeeRate();
}

View file

@ -12,7 +12,6 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -22,6 +21,7 @@ import '../../providers/global/wallets_provider.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/assets.dart';
import '../../utilities/constants.dart';
import '../../utilities/extensions/extensions.dart';
import '../../utilities/text_styles.dart';
import '../../wallets/crypto_currency/crypto_currency.dart';
import '../../wallets/isar/providers/wallet_info_provider.dart';

View file

@ -10,9 +10,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/constants.dart';
import '../../utilities/extensions/extensions.dart';
import '../../utilities/text_styles.dart';
enum FusionOption {

View file

@ -9,9 +9,10 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/constants.dart';
import '../../utilities/extensions/extensions.dart';
import '../../utilities/text_styles.dart';
import '../../utilities/util.dart';
import '../../widgets/background.dart';

View file

@ -9,8 +9,9 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import '../../../themes/stack_colors.dart';
import '../../../utilities/extensions/extensions.dart';
import '../../../utilities/text_styles.dart';
import '../../../widgets/rounded_container.dart';

View file

@ -15,7 +15,6 @@ import 'package:cw_core/monero_transaction_priority.dart';
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:tuple/tuple.dart';
@ -40,6 +39,7 @@ import '../../utilities/barcode_scanner_interface.dart';
import '../../utilities/clipboard_interface.dart';
import '../../utilities/constants.dart';
import '../../utilities/enums/fee_rate_type_enum.dart';
import '../../utilities/extensions/extensions.dart';
import '../../utilities/logger.dart';
import '../../utilities/prefs.dart';
import '../../utilities/text_styles.dart';

View file

@ -12,11 +12,9 @@ import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'wallet_balance_toggle_sheet.dart';
import 'wallet_refresh_button.dart';
import '../../../providers/providers.dart';
import '../../../providers/wallet/public_private_balance_state_provider.dart';
import '../../../providers/wallet/wallet_balance_toggle_state_provider.dart';
@ -27,12 +25,15 @@ import '../../../utilities/amount/amount.dart';
import '../../../utilities/amount/amount_formatter.dart';
import '../../../utilities/assets.dart';
import '../../../utilities/enums/wallet_balance_toggle_state.dart';
import '../../../utilities/extensions/extensions.dart';
import '../../../utilities/text_styles.dart';
import '../../../wallets/crypto_currency/coins/banano.dart';
import '../../../wallets/crypto_currency/coins/firo.dart';
import '../../../wallets/isar/providers/wallet_info_provider.dart';
import '../../../wallets/wallet/impl/banano_wallet.dart';
import '../../../widgets/conditional_parent.dart';
import 'wallet_balance_toggle_sheet.dart';
import 'wallet_refresh_button.dart';
class WalletSummaryInfo extends ConsumerWidget {
const WalletSummaryInfo({

View file

@ -14,7 +14,6 @@ import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -25,6 +24,7 @@ import '../../providers/global/wallets_provider.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/assets.dart';
import '../../utilities/constants.dart';
import '../../utilities/extensions/extensions.dart';
import '../../utilities/text_styles.dart';
import '../../wallets/crypto_currency/crypto_currency.dart';
import '../../wallets/isar/providers/wallet_info_provider.dart';

View file

@ -10,7 +10,6 @@
import 'dart:convert';
import 'package:http/http.dart';
import 'package:tuple/tuple.dart';
import '../../dto/ethereum/eth_token_tx_dto.dart';
@ -120,8 +119,8 @@ abstract class EthereumAPI {
String txid,
) async {
try {
final response = await post(
Uri.parse(
final response = await client.post(
url: Uri.parse(
"$stackBaseServer/v1/mainnet",
),
headers: {'Content-Type': 'application/json'},
@ -133,9 +132,12 @@ abstract class EthereumAPI {
],
"id": DateTime.now().millisecondsSinceEpoch,
}),
proxyInfo: Prefs.instance.useTor
? TorService.sharedInstance.getProxyInfo()
: null,
);
if (response.statusCode == 200) {
if (response.code == 200) {
if (response.body.isNotEmpty) {
try {
final json = jsonDecode(response.body) as Map;
@ -153,13 +155,13 @@ abstract class EthereumAPI {
} else {
throw EthApiException(
"getEthTransactionByHash($txid) response is empty but status code is "
"${response.statusCode}",
"${response.code}",
);
}
} else {
throw EthApiException(
"getEthTransactionByHash($txid) failed with status code: "
"${response.statusCode}",
"${response.code}",
);
}
} on EthApiException catch (e) {

View file

@ -11,17 +11,18 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import '../../../exceptions/exchange/exchange_exception.dart';
import '../../../networking/http.dart';
import '../../../utilities/extensions/extensions.dart';
import '../../../utilities/logger.dart';
import '../../../utilities/prefs.dart';
import '../../tor_service.dart';
import '../exchange_response.dart';
import 'response_objects/trocador_coin.dart';
import 'response_objects/trocador_rate.dart';
import 'response_objects/trocador_trade.dart';
import 'response_objects/trocador_trade_new.dart';
import '../../tor_service.dart';
import '../../../utilities/logger.dart';
import '../../../utilities/prefs.dart';
const kTrocadorApiKey = "8rFqf7QLxX1mUBiNPEMaLUpV2biz6n";
const kTrocadorRefCode = "9eHm9BkQfS";

View file

@ -1,10 +1,11 @@
import 'dart:io';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:tor_ffi_plugin/tor_ffi_plugin.dart';
import '../utilities/logger.dart';
import 'event_bus/events/global/tor_connection_status_changed_event.dart';
import 'event_bus/global_event_bus.dart';
import '../utilities/logger.dart';
import 'package:tor_ffi_plugin/tor_ffi_plugin.dart';
final pTorService = Provider((_) => TorService.sharedInstance);
@ -99,17 +100,20 @@ class TorService {
}
}
/// disable tor
/// Disable Tor.
Future<void> disable() async {
if (_tor == null) {
throw Exception("TorService.init has not been called!");
}
// no need to update status and fire event if status won't change
// No need to update status and fire event if status won't change.
if (_status == TorConnectionStatus.disconnected) {
return;
}
_tor!.disable();
await _tor?.stop();
_updateStatusAndFireEvent(
status: TorConnectionStatus.disconnected,
message: "TorService.disable call success",

View file

@ -47,16 +47,18 @@ Future<bool> checkElectrumServer({
final client = await ElectrumClient.connect(
host: host,
port: port,
useSSL: useSSL,
useSSL: useSSL && !host.endsWith('.onion'),
proxyInfo: proxyInfo,
).timeout(
const Duration(seconds: 5),
Duration(seconds: (proxyInfo == null ? 5 : 30)),
onTimeout: () => throw Exception(
"The checkElectrumServer connect() call timed out.",
),
);
await client.ping().timeout(const Duration(seconds: 5));
await client
.ping()
.timeout(Duration(seconds: (proxyInfo == null ? 5 : 30)));
return true;
} catch (_) {

View file

@ -9,6 +9,7 @@
*/
import 'dart:convert';
import 'dart:core';
import 'dart:typed_data';
import 'package:dart_bs58/dart_bs58.dart';
@ -38,4 +39,9 @@ extension StringExtensions on String {
.reversed
.map((e) => e.toRadixString(16).padLeft(2, '0'))
.join();
/// Capitalize the first letter of a string.
String capitalize() {
return isEmpty ? this : "${this[0].toUpperCase()}${substring(1)}";
}
}

View file

@ -13,6 +13,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:socks5_proxy/socks.dart';
import 'package:tor_ffi_plugin/socks_socket.dart';
import '../widgets/desktop/primary_button.dart';
import '../widgets/desktop/secondary_button.dart';
@ -64,34 +65,79 @@ Future<MoneroNodeConnectionResponse> testMoneroNodeConnection(
return false;
};
final request = await httpClient.postUrl(uri);
if (!uri.host.endsWith('.onion')) {
final request = await httpClient.postUrl(uri);
final body = utf8.encode(
jsonEncode({
"jsonrpc": "2.0",
"id": "0",
"method": "get_info",
}),
);
final body = utf8.encode(
jsonEncode({
"jsonrpc": "2.0",
"id": "0",
"method": "get_info",
}),
);
request.headers.add(
'Content-Length',
body.length.toString(),
preserveHeaderCase: true,
);
request.headers.set(
'Content-Type',
'application/json',
preserveHeaderCase: true,
);
request.headers.add(
'Content-Length',
body.length.toString(),
preserveHeaderCase: true,
);
request.headers.set(
'Content-Type',
'application/json',
preserveHeaderCase: true,
);
request.add(body);
request.add(body);
final response = await request.close();
final result = await response.transform(utf8.decoder).join();
// TODO: json decoded without error so assume connection exists?
// or we can check for certain values in the response to decide
return MoneroNodeConnectionResponse(null, null, null, true);
final response = await request.close();
final result = await response.transform(utf8.decoder).join();
// TODO: json decoded without error so assume connection exists?
// or we can check for certain values in the response to decide
return MoneroNodeConnectionResponse(null, null, null, true);
} else {
// If the URL ends in .onion, we can't use an httpClient to connect to it.
//
// The SOCKSSocket class from the tor_ffi_plugin package can be used to
// connect to .onion addresses. We'll do the same things as above but
// with SOCKSSocket instead of httpClient.
final socket = await SOCKSSocket.create(
proxyHost: proxyInfo!.host.address,
proxyPort: proxyInfo.port,
sslEnabled: false,
);
await socket.connect();
await socket.connectTo(uri.host, uri.port);
final body = utf8.encode(
jsonEncode({
"jsonrpc": "2.0",
"id": "0",
"method": "get_info",
}),
);
// Write the request body to the socket.
socket.write(body);
// Read the response.
final response = await socket.inputStream.first;
final result = utf8.decode(response);
// Close the socket.
await socket.close();
return MoneroNodeConnectionResponse(null, null, null, true);
// Parse the response.
//
// This is commented because any issues should throw.
// final Map<String, dynamic> jsonResponse = jsonDecode(result);
// print(jsonResponse);
// if (jsonResponse.containsKey('result')) {
// return MoneroNodeConnectionResponse(null, null, null, true);
// } else {
// return MoneroNodeConnectionResponse(null, null, null, false);
// }
}
} catch (e, s) {
if (badCertResponse != null) {
return badCertResponse!;

View file

@ -810,12 +810,17 @@ mixin ElectrumXInterface<T extends ElectrumXCurrencyInterface>
);
}
Future<int> fetchChainHeight() async {
Future<int> fetchChainHeight({int retries = 1}) async {
try {
return await ClientManager.sharedInstance.getChainHeightFor(
cryptoCurrency,
);
} catch (e, s) {
if (retries > 0) {
retries--;
await electrumXClient.checkElectrumAdapter();
return await fetchChainHeight(retries: retries);
}
Logging.instance.log(
"Exception rethrown in fetchChainHeight\nError: $e\nStack trace: $s",
level: LogLevel.Error,

View file

@ -2,15 +2,16 @@ import 'dart:async';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/cli_commands.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../../pages_desktop_specific/desktop_menu_item.dart';
import '../../services/event_bus/events/global/tor_connection_status_changed_event.dart';
import '../../services/event_bus/global_event_bus.dart';
import '../../services/tor_service.dart';
import '../../themes/stack_colors.dart';
import '../../utilities/assets.dart';
import '../../utilities/extensions/extensions.dart';
import '../../utilities/text_styles.dart';
class DesktopTorStatusButton extends ConsumerStatefulWidget {

View file

@ -543,8 +543,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "9e9441fc1e9ace8907256fff05fe2c607b0933b6"
resolved-ref: "9e9441fc1e9ace8907256fff05fe2c607b0933b6"
ref: "6bf385b2e1e18c8aa23783cb8afeabace299cf68"
resolved-ref: "6bf385b2e1e18c8aa23783cb8afeabace299cf68"
url: "https://github.com/cypherstack/electrum_adapter.git"
source: git
version: "3.0.0"
@ -1197,9 +1197,9 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "6a17a405a1a260fa228b2f4fc94044088a4335ac"
resolved-ref: "6a17a405a1a260fa228b2f4fc94044088a4335ac"
url: "https://www.github.com/mrcyjanek/monero.dart"
ref: d46753eca865e9e56c2f0ef6fe485c42e11982c5
resolved-ref: d46753eca865e9e56c2f0ef6fe485c42e11982c5
url: "https://github.com/mrcyjanek/monero.dart"
source: git
version: "0.0.0"
mutex:
@ -1807,8 +1807,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: e37dc4e22f7acb2746b70bdc935f0eb3c50b8b71
resolved-ref: e37dc4e22f7acb2746b70bdc935f0eb3c50b8b71
ref: f1d02f7ad489df3119a540a7f31485db6d837843
resolved-ref: f1d02f7ad489df3119a540a7f31485db6d837843
url: "https://github.com/cypherstack/tor.git"
source: git
version: "0.0.1"

View file

@ -73,7 +73,7 @@ dependencies:
tor_ffi_plugin:
git:
url: https://github.com/cypherstack/tor.git
ref: e37dc4e22f7acb2746b70bdc935f0eb3c50b8b71
ref: 647cadc3c82c276dc07915b02d24538fd610f220
fusiondart:
git:
@ -175,7 +175,7 @@ dependencies:
electrum_adapter:
git:
url: https://github.com/cypherstack/electrum_adapter.git
ref: 9e9441fc1e9ace8907256fff05fe2c607b0933b6
ref: 6bf385b2e1e18c8aa23783cb8afeabace299cf68
stream_channel: ^2.1.0
solana:
git: # TODO [prio=low]: Revert to official package once Tor support is merged upstream.
@ -210,6 +210,11 @@ flutter_native_splash:
android_disable_fullscreen: true
dependency_overrides:
# adding here due to pure laziness
tor_ffi_plugin:
git:
url: https://github.com/cypherstack/tor.git
ref: 647cadc3c82c276dc07915b02d24538fd610f220
monero:
git: