diff --git a/lib/pages/paynym/subwidgets/paynym_bot.dart b/lib/pages/paynym/subwidgets/paynym_bot.dart index d8f645da3..082f7034e 100644 --- a/lib/pages/paynym/subwidgets/paynym_bot.dart +++ b/lib/pages/paynym/subwidgets/paynym_bot.dart @@ -8,8 +8,12 @@ * */ +import 'dart:typed_data'; + import 'package:flutter/material.dart'; -import 'package:stackwallet/widgets/loading_indicator.dart'; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; +import 'package:stackwallet/utilities/prefs.dart'; class PayNymBot extends StatelessWidget { const PayNymBot({ @@ -28,16 +32,37 @@ class PayNymBot extends StatelessWidget { child: SizedBox( width: size, height: size, - child: Image.network( - "https://paynym.is/$paymentCodeString/avatar", - loadingBuilder: (context, child, loadingProgress) => - loadingProgress == null - ? child - : const Center( - child: LoadingIndicator(), - ), + child: FutureBuilder( + future: _fetchImage(), + builder: (context, snapshot) { + if (snapshot.hasData) { + return Image.memory(snapshot.data!); + } else if (snapshot.hasError) { + return const Center(child: Icon(Icons.error)); + } else { + return const Center(); // TODO [prio=low]: Make better loading indicator. + } + }, ), ), ); } + + Future _fetchImage() async { + final HTTP client = HTTP(); + final Uri uri = Uri.parse("https://paynym.is/$paymentCodeString/avatar"); + + final response = await client.get( + url: uri, + proxyInfo: Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, + ); + + if (response.code == 200) { + return Uint8List.fromList(response.bodyBytes); + } else { + throw Exception('Failed to load image'); + } + } } diff --git a/lib/wallets/crypto_currency/coins/solana.dart b/lib/wallets/crypto_currency/coins/solana.dart index 0307d6bde..6b01b5b6d 100644 --- a/lib/wallets/crypto_currency/coins/solana.dart +++ b/lib/wallets/crypto_currency/coins/solana.dart @@ -39,6 +39,9 @@ class Solana extends Bip39Currency { @override int get minConfirms => 21; + @override + bool get torSupport => true; + @override bool validateAddress(String address) { return isPointOnEd25519Curve( diff --git a/lib/wallets/crypto_currency/coins/stellar.dart b/lib/wallets/crypto_currency/coins/stellar.dart index aa5f9ce4d..e9a7e605b 100644 --- a/lib/wallets/crypto_currency/coins/stellar.dart +++ b/lib/wallets/crypto_currency/coins/stellar.dart @@ -19,6 +19,9 @@ class Stellar extends Bip39Currency { @override int get minConfirms => 1; + @override + bool get torSupport => true; + @override String get genesisHash => throw UnimplementedError( "Not used for stellar", diff --git a/lib/wallets/crypto_currency/coins/tezos.dart b/lib/wallets/crypto_currency/coins/tezos.dart index ef0937da6..efb982867 100644 --- a/lib/wallets/crypto_currency/coins/tezos.dart +++ b/lib/wallets/crypto_currency/coins/tezos.dart @@ -70,6 +70,9 @@ class Tezos extends Bip39Currency { @override int get minConfirms => 1; + @override + bool get torSupport => true; + @override bool validateAddress(String address) { return RegExp(r"^tz[1-9A-HJ-NP-Za-km-z]{34}$").hasMatch(address); diff --git a/lib/wallets/wallet/impl/stellar_wallet.dart b/lib/wallets/wallet/impl/stellar_wallet.dart index d078dd98e..edea60fe5 100644 --- a/lib/wallets/wallet/impl/stellar_wallet.dart +++ b/lib/wallets/wallet/impl/stellar_wallet.dart @@ -1,7 +1,9 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'package:isar/isar.dart'; +import 'package:socks5_proxy/socks.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/address.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart'; @@ -9,6 +11,7 @@ import 'package:stackwallet/models/isar/models/blockchain_data/v2/input_v2.dart' import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; import 'package:stackwallet/utilities/logger.dart'; @@ -43,6 +46,7 @@ class StellarWallet extends Bip39Wallet { // ============== Private ==================================================== stellar.StellarSDK? _stellarSdk; + HttpClient? _httpClient; Future _getBaseFee() async { final fees = await stellarSdk.feeStats.execute(); @@ -51,7 +55,21 @@ class StellarWallet extends Bip39Wallet { void _updateSdk() { final currentNode = getCurrentNode(); - _stellarSdk = stellar.StellarSDK("${currentNode.host}:${currentNode.port}"); + + // TODO [prio=med]: refactor out and call before requests in case Tor is enabled/disabled, listen to prefs change, or similar. + if (prefs.useTor) { + final ({InternetAddress host, int port}) proxyInfo = + TorService.sharedInstance.getProxyInfo(); + + _httpClient = HttpClient(); + SocksTCPClient.assignToHttpClient( + _httpClient!, [ProxySettings(proxyInfo.host, proxyInfo.port)]); + } else { + _httpClient = null; + } + + _stellarSdk = stellar.StellarSDK("${currentNode.host}:${currentNode.port}", + httpClient: _httpClient); } Future _accountExists(String accountId) async { diff --git a/lib/widgets/wallet_card.dart b/lib/widgets/wallet_card.dart index 31a29fb68..bc1c80aa4 100644 --- a/lib/widgets/wallet_card.dart +++ b/lib/widgets/wallet_card.dart @@ -30,7 +30,6 @@ import 'package:stackwallet/wallets/wallet/wallet.dart'; import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; -import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/dialogs/basic_dialog.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/wallet_info_row/wallet_info_row.dart'; @@ -95,37 +94,6 @@ class SimpleWalletCard extends ConsumerWidget { final wallet = ref.read(pWallets).getWallet(walletId); - // If Tor enabled, show a warning if opening a wallet incompatible with Tor. - if (ref.read(prefsChangeNotifierProvider).useTor) { - if (!wallet.cryptoCurrency.torSupport) { - final shouldContinue = await showDialog( - context: context, - builder: (context) => BasicDialog( - title: "Warning! Tor not supported.", - message: "Stacky is not compatible with Tor." - "\n\nBy using it, you will leak your IP address. Are you sure you " - "want to continue?", - // A PrimaryButton widget: - leftButton: PrimaryButton( - label: "Cancel", - onPressed: () { - Navigator.of(context).pop(false); - }, - ), - rightButton: SecondaryButton( - label: "Continue", - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - )) ?? - false; - if (!shouldContinue) { - return; - } - } - } - if (context.mounted) { final Future loadFuture; if (wallet is CwBasedInterface) { diff --git a/pubspec.lock b/pubspec.lock index 25ba923a0..bb9486dd4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1574,7 +1574,7 @@ packages: source: hosted version: "1.0.4" socks_socket: - dependency: "direct main" + dependency: transitive description: path: "." ref: master @@ -1586,8 +1586,8 @@ packages: dependency: "direct main" description: path: "packages/solana" - ref: "0ada1f775c2a2c815de640424270a229f5e91e2f" - resolved-ref: "0ada1f775c2a2c815de640424270a229f5e91e2f" + ref: a83e375678eb22fe544dc125d29bbec0fb833882 + resolved-ref: a83e375678eb22fe544dc125d29bbec0fb833882 url: "https://github.com/cypherstack/espresso-cash-public.git" source: git version: "0.30.4" @@ -1659,10 +1659,11 @@ packages: stellar_flutter_sdk: dependency: "direct main" description: - name: stellar_flutter_sdk - sha256: "4c55b1b6dfbde7f89bba59a422754280715fa3b5726cff5e7eeaed454d2c4b89" - url: "https://pub.dev" - source: hosted + path: "." + ref: eca1d730e952cf6a6d64502f977cfc03876b75d4 + resolved-ref: eca1d730e952cf6a6d64502f977cfc03876b75d4 + url: "https://github.com/cypherstack/stellar_flutter_sdk.git" + source: git version: "1.5.3" stream_channel: dependency: "direct main" diff --git a/pubspec.yaml b/pubspec.yaml index 723f2aae2..fb5a9f31c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -156,11 +156,10 @@ dependencies: desktop_drop: ^0.4.1 nanodart: ^2.0.0 basic_utils: ^5.5.4 - stellar_flutter_sdk: ^1.5.3 - socks_socket: - git: - url: https://github.com/cypherstack/socks_socket.git - ref: master + stellar_flutter_sdk: # ^1.5.3 + git: # TODO [prio=low]: Revert to official package once Tor support is merged upstream. + url: https://github.com/cypherstack/stellar_flutter_sdk.git + ref: eca1d730e952cf6a6d64502f977cfc03876b75d4 # tor-backport branch (based on 1.5.3). bip340: ^0.2.0 # tezart: ^2.0.5 tezart: @@ -180,7 +179,7 @@ dependencies: solana: git: # TODO [prio=low]: Revert to official package once Tor support is merged upstream. url: https://github.com/cypherstack/espresso-cash-public.git - ref: 0ada1f775c2a2c815de640424270a229f5e91e2f + ref: a83e375678eb22fe544dc125d29bbec0fb833882 path: packages/solana dev_dependencies: