From e940ad8e71dd2561379fb208a04ea8e1a3053c9f Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 27 Apr 2023 16:35:16 -0600 Subject: [PATCH 001/237] WIP: sample stub for possible tor integration --- lib/networking/http.dart | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 lib/networking/http.dart diff --git a/lib/networking/http.dart b/lib/networking/http.dart new file mode 100644 index 000000000..ddda3e7e6 --- /dev/null +++ b/lib/networking/http.dart @@ -0,0 +1,40 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; + +// WIP wrapper layer + +abstract class HTTP { + static Future get({ + required Uri url, + Map? headers, + required bool routeOverTor, + }) async { + if (routeOverTor) { + // TODO + throw UnimplementedError(); + } else { + return http.get(url, headers: headers); + } + } + + static Future post({ + required Uri url, + Map? headers, + Object? body, + Encoding? encoding, + required bool routeOverTor, + }) async { + if (routeOverTor) { + // TODO + throw UnimplementedError(); + } else { + return http.post( + url, + headers: headers, + body: body, + encoding: encoding, + ); + } + } +} From 88cb2f782e50d8e59b8975db9d106340e166a8f3 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 3 May 2023 18:55:12 -0500 Subject: [PATCH 002/237] added sneurlax/tor submodule, TODO migrate to cypherstack/tor after completion --- .gitmodules | 3 +++ crypto_plugins/tor | 1 + 2 files changed, 4 insertions(+) create mode 160000 crypto_plugins/tor diff --git a/.gitmodules b/.gitmodules index 7474c8a54..a68bc16a0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "crypto_plugins/flutter_liblelantus"] path = crypto_plugins/flutter_liblelantus url = https://github.com/cypherstack/flutter_liblelantus.git +[submodule "crypto_plugins/tor"] + path = crypto_plugins/tor + url = https://github.com/sneurlax/tor diff --git a/crypto_plugins/tor b/crypto_plugins/tor new file mode 160000 index 000000000..6086caaf4 --- /dev/null +++ b/crypto_plugins/tor @@ -0,0 +1 @@ +Subproject commit 6086caaf4437150fff21322b36451828e15827f1 From 097ea6e92ecb81b774d6fe6e9b237ad582d184b6 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Thu, 11 May 2023 16:43:00 -0500 Subject: [PATCH 003/237] use sneurlax/tor#ffi-plugin --- .gitmodules | 2 +- crypto_plugins/tor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index a68bc16a0..c56eb8eee 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,4 +9,4 @@ url = https://github.com/cypherstack/flutter_liblelantus.git [submodule "crypto_plugins/tor"] path = crypto_plugins/tor - url = https://github.com/sneurlax/tor + url = https://github.com/sneurlax/tor.git diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 6086caaf4..4b2a89699 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 6086caaf4437150fff21322b36451828e15827f1 +Subproject commit 4b2a89699c2032451cc1f60d1020d00784896325 From 4f97f8fbb403e5c947b468608af08aad31546ef7 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Thu, 11 May 2023 16:47:02 -0500 Subject: [PATCH 004/237] update linux and android build_all scripts to also run tor's scripts TODO windows --- scripts/android/build_all.sh | 1 + scripts/linux/build_all.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/scripts/android/build_all.sh b/scripts/android/build_all.sh index a0050dc9e..111fea934 100755 --- a/scripts/android/build_all.sh +++ b/scripts/android/build_all.sh @@ -7,6 +7,7 @@ mkdir build (cd ../../crypto_plugins/flutter_liblelantus/scripts/android && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/android && ./install_ndk.sh && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/android/ && ./build_all.sh ) & +(cd ../../crypto_plugins/tor/scripts/android && ./install_ndk.sh && ./build_all.sh ) & wait echo "Done building" diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh index 31edfb872..9a119d0d6 100755 --- a/scripts/linux/build_all.sh +++ b/scripts/linux/build_all.sh @@ -9,6 +9,7 @@ mkdir -p build (cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_monero_all.sh && ./build_sharedfile.sh ) & +(cd ../../crypto_plugins/tor/scripts/linux && ./build_all.sh ) & wait echo "Done building" From 9065e9598583d315e41cb2385f1c961196c21e86 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Thu, 11 May 2023 16:48:20 -0500 Subject: [PATCH 005/237] chmod +x scripts --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 4b2a89699..1f65e2c39 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 4b2a89699c2032451cc1f60d1020d00784896325 +Subproject commit 1f65e2c394650abdca80b2b0ec49295d4072d6dc From 556facda1a3d8fa1ef224e740b598364ebdf521c Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Thu, 11 May 2023 17:56:33 -0500 Subject: [PATCH 006/237] add more config variables --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 1f65e2c39..7d70fdcd7 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 1f65e2c394650abdca80b2b0ec49295d4072d6dc +Subproject commit 7d70fdcd75f77b877f3c278ab964c8ce589ae8e4 From 7ec294e61ef8719903bccbf415a9d6c35122677e Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Tue, 16 May 2023 16:47:45 -0500 Subject: [PATCH 007/237] update tor submodule --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 7d70fdcd7..4f013aa27 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 7d70fdcd75f77b877f3c278ab964c8ce589ae8e4 +Subproject commit 4f013aa27620ff0563210077cfdb37090e9dc17e From 23a14efb1482bfc51ab387c61e5741a4322075ab Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 17 May 2023 15:44:18 -0500 Subject: [PATCH 008/237] remove files from /src (they're in /native) --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 4f013aa27..4b3b6c815 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 4f013aa27620ff0563210077cfdb37090e9dc17e +Subproject commit 4b3b6c815d0a7d32efb3100b0fcacea9cc766680 From ac72168625ce899932916af4c925f9da2208715f Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 17 May 2023 16:26:41 -0500 Subject: [PATCH 009/237] update build script to copy lib for bundling by flutter --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 4b3b6c815..b5802faff 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 4b3b6c815d0a7d32efb3100b0fcacea9cc766680 +Subproject commit b5802faffeb6a3f78c0f7494655bf5ea78411596 From c46505c20d3b7e911be62a62b637f21402cf935a Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 17 May 2023 16:27:13 -0500 Subject: [PATCH 010/237] add tor to pubspec --- pubspec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pubspec.yaml b/pubspec.yaml index 1aaeb2d57..b189b6fa0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,6 +62,9 @@ dependencies: url: https://github.com/cypherstack/bip47.git ref: 38847255d035c0f6ec5bc93d19130ec804cf90e9 + tor: + path: ./crypto_plugins/tor + # Utility plugins # provider: ^6.0.1 http: ^0.13.4 From c2965841fd01997727a9d556d24de29a8f0ae7d4 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 17 May 2023 16:27:25 -0500 Subject: [PATCH 011/237] add tor to pubspec --- pubspec.lock | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index b021401bd..484245463 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1699,6 +1699,13 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.5" + tor: + dependency: "direct main" + description: + path: "crypto_plugins/tor" + relative: true + source: path + version: "0.0.1" tuple: dependency: "direct main" description: @@ -1957,5 +1964,5 @@ packages: source: hosted version: "1.0.0" sdks: - dart: ">=2.18.5 <3.0.0" + dart: ">=2.19.4 <3.0.0" flutter: ">=3.3.0" From d2224b274fc4c50e0279a30416e25eb16ae15af8 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 17 May 2023 17:07:40 -0500 Subject: [PATCH 012/237] gitignore libtor libs --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index ed66fa960..c38882323 100644 --- a/.gitignore +++ b/.gitignore @@ -55,4 +55,6 @@ libcw_monero.dll libcw_wownero.dll libepic_cash_wallet.dll libmobileliblelantus.dll +libtor_ffi.dll /libisar.so +libtor_ffi.so From 844e05a42b0dcc2daf5112d182a06e680b0ef93e Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 17 May 2023 17:16:38 -0500 Subject: [PATCH 013/237] update tor plugin --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index b5802faff..6216e459e 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit b5802faffeb6a3f78c0f7494655bf5ea78411596 +Subproject commit 6216e459eb359edd64c44d26bc5d6afed6d3ce44 From 354f26794280214ed4b70d0a0eaa1c189c176c31 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 17 May 2023 17:21:45 -0500 Subject: [PATCH 014/237] start tor with app in main --- lib/main.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index 60026022f..5083dfdb2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,6 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_libmonero/monero/monero.dart'; import 'package:flutter_libmonero/wownero/wownero.dart'; +import 'package:tor/tor.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -181,6 +182,9 @@ void main() async { monero.onStartup(); wownero.onStartup(); + dynamic tor = Tor(); + tor.start(); + // SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, // overlays: [SystemUiOverlay.bottom]); await NotificationApi.init(); From 4559f37cc841961c365e97a7e9c208312ed2245b Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Mon, 29 May 2023 16:54:05 -0500 Subject: [PATCH 015/237] add tor lib to linux cmakelists --- linux/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 53391e7ad..1fa44c9b7 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -146,6 +146,9 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/linux/build/libmobileliblelantus.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/tor/scripts/linux/build/native/target/x86_64-unknown-linux-gnu/release/libtor_ffi.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1.7.4" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" From f43aeadc3f8ed5296e320ed97d572c5558d29646 Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Mon, 12 Jun 2023 22:03:32 +0300 Subject: [PATCH 016/237] feat: add xtz --- lib/models/isar/stack_theme.dart | 9 + .../add_edit_node_view.dart | 1 + lib/services/coins/coin_service.dart | 10 + lib/services/coins/tezos/tezos_wallet.dart | 314 ++++++++++++++++++ lib/themes/coin_icon_provider.dart | 2 + lib/themes/coin_image_provider.dart | 4 + lib/themes/color_theme.dart | 3 + lib/themes/stack_colors.dart | 2 + lib/utilities/address_utils.dart | 2 + lib/utilities/block_explorers.dart | 2 + lib/utilities/constants.dart | 11 + lib/utilities/default_nodes.dart | 18 +- lib/utilities/enums/coin_enum.dart | 21 ++ .../enums/derive_path_type_enum.dart | 1 + pubspec.lock | 80 ++++- pubspec.yaml | 2 + 16 files changed, 477 insertions(+), 5 deletions(-) create mode 100644 lib/services/coins/tezos/tezos_wallet.dart diff --git a/lib/models/isar/stack_theme.dart b/lib/models/isar/stack_theme.dart index 5809e4443..67fbb0ab7 100644 --- a/lib/models/isar/stack_theme.dart +++ b/lib/models/isar/stack_theme.dart @@ -1902,6 +1902,7 @@ class ThemeAssets implements IThemeAssets { late final String wownero; late final String namecoin; late final String particl; + late final String tezos; late final String bitcoinImage; late final String bitcoincashImage; late final String dogecoinImage; @@ -1913,6 +1914,7 @@ class ThemeAssets implements IThemeAssets { late final String wowneroImage; late final String namecoinImage; late final String particlImage; + late final String tezosImage; late final String bitcoinImageSecondary; late final String bitcoincashImageSecondary; late final String dogecoinImageSecondary; @@ -1924,6 +1926,7 @@ class ThemeAssets implements IThemeAssets { late final String wowneroImageSecondary; late final String namecoinImageSecondary; late final String particlImageSecondary; + late final String tezosImageSecondary; @override late final String? loadingGif; @override @@ -1997,6 +2000,8 @@ class ThemeAssets implements IThemeAssets { "$applicationThemesDirectoryPath/$themeId/assets/${json["namecoin"] as String}" ..particl = "$applicationThemesDirectoryPath/$themeId/assets/${json["particl"] as String}" + ..tezos = + "$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin"] as String}" // TODO: change to tezos ..bitcoinImage = "$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin_image"] as String}" ..bitcoincashImage = @@ -2019,6 +2024,8 @@ class ThemeAssets implements IThemeAssets { "$applicationThemesDirectoryPath/$themeId/assets/${json["namecoin_image"] as String}" ..particlImage = "$applicationThemesDirectoryPath/$themeId/assets/${json["particl_image"] as String}" + ..tezosImage = + "$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin_image"] as String}" // TODO: change to tezos ..bitcoinImageSecondary = "$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin_image_secondary"] as String}" ..bitcoincashImageSecondary = @@ -2041,6 +2048,8 @@ class ThemeAssets implements IThemeAssets { "$applicationThemesDirectoryPath/$themeId/assets/${json["namecoin_image_secondary"] as String}" ..particlImageSecondary = "$applicationThemesDirectoryPath/$themeId/assets/${json["particl_image_secondary"] as String}" + ..tezosImageSecondary = + "$applicationThemesDirectoryPath/$themeId/assets/${json["bitcoin_image_secondary"] as String}" // TODO: change to tezos ..loadingGif = json["loading_gif"] is String ? "$applicationThemesDirectoryPath/$themeId/assets/${json["loading_gif"] as String}" : null diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 1ff1a1359..b29f4718c 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -711,6 +711,7 @@ class _NodeFormState extends ConsumerState { case Coin.namecoin: case Coin.bitcoincash: case Coin.particl: + case Coin.tezos: case Coin.bitcoinTestNet: case Coin.litecoinTestNet: case Coin.bitcoincashTestnet: diff --git a/lib/services/coins/coin_service.dart b/lib/services/coins/coin_service.dart index 48fa59630..a6d1b023b 100644 --- a/lib/services/coins/coin_service.dart +++ b/lib/services/coins/coin_service.dart @@ -15,6 +15,7 @@ import 'package:stackwallet/services/coins/litecoin/litecoin_wallet.dart'; import 'package:stackwallet/services/coins/monero/monero_wallet.dart'; import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'; import 'package:stackwallet/services/coins/particl/particl_wallet.dart'; +import 'package:stackwallet/services/coins/tezos/tezos_wallet.dart'; import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; @@ -204,6 +205,15 @@ abstract class CoinServiceAPI { cachedClient: cachedClient, tracker: tracker); + case Coin.tezos: + return TezosWallet( + walletId: walletId, + walletName: walletName, + coin: coin, + secureStore: secureStorageInterface, + tracker: tracker, + ); + case Coin.wownero: return WowneroWallet( walletId: walletId, diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart new file mode 100644 index 000000000..fca4eabc2 --- /dev/null +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -0,0 +1,314 @@ +import 'dart:async'; + +import 'package:http/http.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'; +import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; +import 'package:stackwallet/models/paymint/fee_object_model.dart'; +import 'package:stackwallet/services/coins/coin_service.dart'; +import 'package:stackwallet/services/node_service.dart'; +import 'package:stackwallet/utilities/amount/amount.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/default_nodes.dart'; + +import 'package:tezart/tezart.dart'; + +import '../../../db/isar/main_db.dart'; +import '../../../models/node_model.dart'; +import '../../../utilities/flutter_secure_storage_interface.dart'; +import '../../../utilities/logger.dart'; +import '../../../utilities/prefs.dart'; +import '../../mixins/wallet_cache.dart'; +import '../../mixins/wallet_db.dart'; +import '../../transaction_notification_tracker.dart'; + +const int MINIMUM_CONFIRMATIONS = 1; + +class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { + TezosWallet({ + required String walletId, + required String walletName, + required Coin coin, + required SecureStorageInterface secureStore, + required TransactionNotificationTracker tracker, + MainDB? mockableOverride, + }) { + txTracker = tracker; + _walletId = walletId; + _walletName = walletName; + _coin = coin; + _secureStore = secureStore; + initCache(walletId, coin); + initWalletDB(mockableOverride: mockableOverride); + } + + NodeModel? _xtzNode; + + NodeModel getCurrentNode() { + return _xtzNode ?? NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: Coin.tezos) ?? DefaultNodes.getNodeFor(Coin.tezos); + } + + @override + String get walletId => _walletId; + late String _walletId; + + @override + String get walletName => _walletName; + late String _walletName; + + @override + set walletName(String name) => _walletName = name; + + @override + set isFavorite(bool markFavorite) { + _isFavorite = markFavorite; + updateCachedIsFavorite(markFavorite); + } + + @override + bool get isFavorite => _isFavorite ??= getCachedIsFavorite(); + bool? _isFavorite; + + @override + Coin get coin => _coin; + late Coin _coin; + + late SecureStorageInterface _secureStore; + late final TransactionNotificationTracker txTracker; + final _prefs = Prefs.instance; + + Timer? timer; + bool _shouldAutoSync = false; + + @override + bool get shouldAutoSync => _shouldAutoSync; + + @override + set shouldAutoSync(bool shouldAutoSync) { + if (_shouldAutoSync != shouldAutoSync) { + _shouldAutoSync = shouldAutoSync; + if (!shouldAutoSync) { + timer?.cancel(); + timer = null; + } else { + refresh(); + } + } + } + + @override + Balance get balance => _balance ??= getCachedBalance(); + Balance? _balance; + + @override + Future confirmSend({required Map txData}) { + // TODO: implement confirmSend, + // NOTE FROM DETHERMINAL: I couldnt write this function because I dont have any tezos to test with + throw UnimplementedError(); + } + + @override + Future get currentReceivingAddress async { + var mneString = await mnemonicString; + if (mneString == null) { + throw Exception("No mnemonic found!"); + } + return Future.value(Keystore.fromMnemonic(mneString).address); + } + + @override + Future estimateFeeFor(Amount amount, int feeRate) { + // TODO: implement estimateFeeFor + throw UnimplementedError(); + } + + @override + Future exit() { + _hasCalledExit = true; + return Future.value(); + } + + @override + // TODO: implement fees + Future get fees => throw UnimplementedError(); + + @override + Future fullRescan(int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) { + // TODO: implement fullRescan + throw UnimplementedError(); + } + + @override + Future generateNewAddress() { + // TODO: implement generateNewAddress + throw UnimplementedError(); + } + + @override + bool get hasCalledExit => _hasCalledExit; + bool _hasCalledExit = false; + + @override + Future initializeExisting() async { + await _prefs.init(); + } + + @override + Future initializeNew() async { + var newKeystore = Keystore.random(); + await _secureStore.write( + key: '${_walletId}_mnemonic', + value: newKeystore.mnemonic, + ); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: "", + ); + + final address = Address( + walletId: walletId, + value: newKeystore.address, + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + + await db.putAddress(address); + + await Future.wait([ + updateCachedId(walletId), + updateCachedIsFavorite(false), + ]); + } + + @override + bool get isConnected => _isConnected; + bool _isConnected = false; + + @override + bool get isRefreshing => refreshMutex; + bool refreshMutex = false; + + @override + // TODO: implement maxFee + Future get maxFee => throw UnimplementedError(); + + @override + Future> get mnemonic async { + final mnemonic = await mnemonicString; + final mnemonicPassphrase = await this.mnemonicPassphrase; + if (mnemonic == null) { + throw Exception("No mnemonic found!"); + } + if (mnemonicPassphrase == null) { + throw Exception("No mnemonic passphrase found!"); + } + return mnemonic.split(" "); + } + + @override + Future get mnemonicPassphrase => _secureStore.read(key: '${_walletId}_mnemonicPassphrase'); + + @override + Future get mnemonicString => _secureStore.read(key: '${_walletId}_mnemonic'); + + @override + Future> prepareSend({required String address, required Amount amount, Map? args}) { + // TODO: implement prepareSend + // NOTE FROM DETHERMINAL: I couldnt write this function because I dont have any tezos to test with + throw UnimplementedError(); + } + + @override + Future recoverFromMnemonic({required String mnemonic, String? mnemonicPassphrase, required int maxUnusedAddressGap, required int maxNumberOfIndexesToCheck, required int height}) async { + if ((await mnemonicString) != null || + (await this.mnemonicPassphrase) != null) { + throw Exception("Attempted to overwrite mnemonic on restore!"); + } + await _secureStore.write( + key: '${_walletId}_mnemonic', value: mnemonic.trim()); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: mnemonicPassphrase ?? "", + ); + + final address = Address( + walletId: walletId, + value: Keystore.fromMnemonic(mnemonic).address, + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + + await db.putAddress(address); + + await Future.wait([ + updateCachedId(walletId), + updateCachedIsFavorite(false), + ]); + } + + Future updateBalance() async { + var api = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance"; // TODO: Can we use current node instead of this? + var theBalance = await get(Uri.parse(api)).then((value) => value.body); + Logging.instance.log("Balance for ${await currentReceivingAddress}: $theBalance", level: LogLevel.Info); + var balanceInAmount = Amount(rawValue: BigInt.parse(theBalance.toString()), fractionDigits: 6); + _balance = Balance( + total: balanceInAmount, + spendable: balanceInAmount, + blockedTotal: Amount(rawValue: BigInt.parse("0"), fractionDigits: 6), + pendingSpendable: Amount(rawValue: BigInt.parse("0"), fractionDigits: 6), + ); + await updateCachedBalance(_balance!); + } + + @override + Future refresh() { + updateBalance(); + return Future.value(); + } + + @override + int get storedChainHeight => getCachedChainHeight(); + + @override + Future testNetworkConnection() { + // TODO: implement testNetworkConnection + throw UnimplementedError(); + } + + @override + // TODO: implement transactions + Future> get transactions async { + // TODO: Maybe we can use this -> https://api.tzkt.io/#operation/Accounts_GetBalanceHistory + } + + @override + Future updateNode(bool shouldRefresh) async { + _xtzNode = NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: coin) ?? DefaultNodes.getNodeFor(coin); + + if (shouldRefresh) { + await refresh(); + } + } + + @override + Future updateSentCachedTxData(Map txData) { + // TODO: implement updateSentCachedTxData + throw UnimplementedError(); + } + + @override + // TODO: implement utxos + Future> get utxos => throw UnimplementedError(); + + @override + bool validateAddress(String address) { + return RegExp(r"^tz[1-9A-HJ-NP-Za-km-z]{34}$").hasMatch(address); + } +} diff --git a/lib/themes/coin_icon_provider.dart b/lib/themes/coin_icon_provider.dart index 6c17969e6..3792560e6 100644 --- a/lib/themes/coin_icon_provider.dart +++ b/lib/themes/coin_icon_provider.dart @@ -35,6 +35,8 @@ final coinIconProvider = Provider.family((ref, coin) { return assets.namecoin; case Coin.particl: return assets.particl; + case Coin.tezos: + return assets.tezos; case Coin.ethereum: return assets.ethereum; } diff --git a/lib/themes/coin_image_provider.dart b/lib/themes/coin_image_provider.dart index 239e1d1cb..3de9ab40a 100644 --- a/lib/themes/coin_image_provider.dart +++ b/lib/themes/coin_image_provider.dart @@ -31,6 +31,8 @@ final coinImageProvider = Provider.family((ref, coin) { return assets.namecoinImage; case Coin.particl: return assets.particlImage; + case Coin.tezos: + return assets.tezosImage; case Coin.bitcoinTestNet: return assets.bitcoinImage; case Coin.bitcoincashTestnet: @@ -75,6 +77,8 @@ final coinImageSecondaryProvider = Provider.family((ref, coin) { return assets.namecoinImageSecondary; case Coin.particl: return assets.particlImageSecondary; + case Coin.tezos: + return assets.tezosImageSecondary; case Coin.bitcoinTestNet: return assets.bitcoinImageSecondary; case Coin.bitcoincashTestnet: diff --git a/lib/themes/color_theme.dart b/lib/themes/color_theme.dart index b4f00adcf..7946139c3 100644 --- a/lib/themes/color_theme.dart +++ b/lib/themes/color_theme.dart @@ -18,6 +18,7 @@ class CoinThemeColorDefault { Color get namecoin => const Color(0xFF91B1E1); Color get wownero => const Color(0xFFED80C1); Color get particl => const Color(0xFF8175BD); + Color get tezos => const Color(0xFF0F61FF); Color forCoin(Coin coin) { switch (coin) { @@ -50,6 +51,8 @@ class CoinThemeColorDefault { return wownero; case Coin.particl: return particl; + case Coin.tezos: + return tezos; } } } diff --git a/lib/themes/stack_colors.dart b/lib/themes/stack_colors.dart index 6717615b1..8f5dbbe15 100644 --- a/lib/themes/stack_colors.dart +++ b/lib/themes/stack_colors.dart @@ -1697,6 +1697,8 @@ class StackColors extends ThemeExtension { return _coin.wownero; case Coin.particl: return _coin.particl; + case Coin.tezos: + return _coin.tezos; } } diff --git a/lib/utilities/address_utils.dart b/lib/utilities/address_utils.dart index 44850bc65..a151abbdf 100644 --- a/lib/utilities/address_utils.dart +++ b/lib/utilities/address_utils.dart @@ -74,6 +74,8 @@ class AddressUtils { return Address.validateAddress(address, namecoin, namecoin.bech32!); case Coin.particl: return Address.validateAddress(address, particl); + case Coin.tezos: + return RegExp(r"^tz[1-9A-HJ-NP-Za-km-z]{34}$").hasMatch(address); case Coin.bitcoinTestNet: return Address.validateAddress(address, testnet); case Coin.litecoinTestNet: diff --git a/lib/utilities/block_explorers.dart b/lib/utilities/block_explorers.dart index cf0628fd2..4f4228e27 100644 --- a/lib/utilities/block_explorers.dart +++ b/lib/utilities/block_explorers.dart @@ -43,6 +43,8 @@ Uri getDefaultBlockExplorerUrlFor({ return Uri.parse("https://chainz.cryptoid.info/nmc/tx.dws?$txid.htm"); case Coin.particl: return Uri.parse("https://chainz.cryptoid.info/part/tx.dws?$txid.htm"); + case Coin.tezos: + return Uri.parse("https://tzstats.com/$txid"); } } diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index b3295b3c8..2fdacc64b 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -29,12 +29,14 @@ abstract class Constants { static const int _satsPerCoinECash = 100; static const int _satsPerCoinMonero = 1000000000000; static const int _satsPerCoinWownero = 100000000000; + static const int _satsPerCoinTezos = 1000000; static const int _satsPerCoin = 100000000; static const int _decimalPlaces = 8; static const int _decimalPlacesWownero = 11; static const int _decimalPlacesMonero = 12; static const int _decimalPlacesEthereum = 18; static const int _decimalPlacesECash = 2; + static const int _decimalPlacesTezos = 6; static const int notificationsMax = 0xFFFFFFFF; static const Duration networkAliveTimerDuration = Duration(seconds: 10); @@ -76,6 +78,9 @@ abstract class Constants { case Coin.eCash: return _satsPerCoinECash; + + case Coin.tezos: + return _satsPerCoinTezos; } } @@ -107,6 +112,9 @@ abstract class Constants { case Coin.eCash: return _decimalPlacesECash; + + case Coin.tezos: + return _decimalPlacesTezos; } } @@ -180,6 +188,9 @@ abstract class Constants { case Coin.particl: return 600; + + case Coin.tezos: + return 60; } } diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index 0f8425c88..8c48f5340 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -169,7 +169,20 @@ abstract class DefaultNodes { enabled: true, coinName: Coin.particl.name, isFailover: true, - isDown: false); + isDown: false + ); + + static NodeModel get tezos => NodeModel( // TODO: Change this to original one + host: "https://mainnet.api.tez.ie", + port: 443, + name: defaultName, + id: _nodeId(Coin.tezos), + useSSL: true, + enabled: true, + coinName: Coin.tezos.name, + isFailover: true, + isDown: false + ); static NodeModel get bitcoinTestnet => NodeModel( host: "bitcoin-testnet.stackwallet.com", @@ -269,6 +282,9 @@ abstract class DefaultNodes { case Coin.particl: return particl; + case Coin.tezos: + return tezos; + case Coin.bitcoinTestNet: return bitcoinTestnet; diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index f1109a626..096e26db5 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -16,6 +16,7 @@ import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart' as nmc; import 'package:stackwallet/services/coins/particl/particl_wallet.dart' as particl; +import 'package:stackwallet/services/coins/tezos/tezos_wallet.dart' as tezos; import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow; import 'package:stackwallet/utilities/constants.dart'; @@ -31,6 +32,7 @@ enum Coin { monero, namecoin, particl, + tezos, wownero, /// @@ -71,6 +73,8 @@ extension CoinExt on Coin { return "Monero"; case Coin.particl: return "Particl"; + case Coin.tezos: + return "Tezos"; case Coin.wownero: return "Wownero"; case Coin.namecoin: @@ -110,6 +114,8 @@ extension CoinExt on Coin { return "XMR"; case Coin.particl: return "PART"; + case Coin.tezos: + return "XTZ"; case Coin.wownero: return "WOW"; case Coin.namecoin: @@ -150,6 +156,8 @@ extension CoinExt on Coin { return "monero"; case Coin.particl: return "particl"; + case Coin.tezos: + return "tezos"; case Coin.wownero: return "wownero"; case Coin.namecoin: @@ -187,6 +195,7 @@ extension CoinExt on Coin { case Coin.epicCash: case Coin.ethereum: case Coin.monero: + case Coin.tezos: case Coin.wownero: return false; } @@ -207,6 +216,7 @@ extension CoinExt on Coin { case Coin.eCash: case Coin.epicCash: case Coin.monero: + case Coin.tezos: case Coin.wownero: case Coin.dogecoinTestNet: case Coin.bitcoinTestNet: @@ -229,6 +239,7 @@ extension CoinExt on Coin { case Coin.epicCash: case Coin.ethereum: case Coin.monero: + case Coin.tezos: case Coin.wownero: case Coin.eCash: return false; @@ -254,6 +265,7 @@ extension CoinExt on Coin { case Coin.epicCash: case Coin.ethereum: case Coin.monero: + case Coin.tezos: case Coin.wownero: case Coin.eCash: return this; @@ -312,6 +324,9 @@ extension CoinExt on Coin { case Coin.particl: return particl.MINIMUM_CONFIRMATIONS; + case Coin.tezos: + return tezos.MINIMUM_CONFIRMATIONS; + case Coin.wownero: return wow.MINIMUM_CONFIRMATIONS; @@ -367,6 +382,10 @@ Coin coinFromPrettyName(String name) { case "particl": return Coin.particl; + case "Tezos": + case "tezos": + return Coin.tezos; + case "Namecoin": case "namecoin": return Coin.namecoin; @@ -436,6 +455,8 @@ Coin coinFromTickerCaseInsensitive(String ticker) { return Coin.namecoin; case "part": return Coin.particl; + case "xtz": + return Coin.tezos; case "tltc": return Coin.litecoinTestNet; case "tbtc": diff --git a/lib/utilities/enums/derive_path_type_enum.dart b/lib/utilities/enums/derive_path_type_enum.dart index 72899f5bd..315a355db 100644 --- a/lib/utilities/enums/derive_path_type_enum.dart +++ b/lib/utilities/enums/derive_path_type_enum.dart @@ -37,6 +37,7 @@ extension DerivePathTypeExt on DerivePathType { case Coin.epicCash: case Coin.monero: case Coin.wownero: + case Coin.tezos: // TODO: Is this true? throw UnsupportedError( "$coin does not use bitcoin style derivation paths"); } diff --git a/pubspec.lock b/pubspec.lock index 600a92d67..14c0aca59 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a url: "https://pub.dev" source: hosted - version: "47.0.0" + version: "61.0.0" analyzer: dependency: "direct dev" description: name: analyzer - sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "5.13.0" animations: dependency: "direct main" description: @@ -33,6 +33,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.29" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a" + url: "https://pub.dev" + source: hosted + version: "2.0.1" app_settings: dependency: "direct main" description: @@ -490,6 +498,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.5" + dio: + dependency: transitive + description: + name: dio + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" + url: "https://pub.dev" + source: hosted + version: "4.0.6" dropdown_button2: dependency: "direct main" description: @@ -966,6 +982,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + json_serializable: + dependency: transitive + description: + name: json_serializable + sha256: dadc08bd61f72559f938dd08ec20dbfec6c709bba83515085ea943d2078d187a + url: "https://pub.dev" + source: hosted + version: "6.6.1" jsonrpc2: dependency: "direct main" description: @@ -1037,6 +1061,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" + memoize: + dependency: transitive + description: + name: memoize + sha256: "51481d328c86cbdc59711369179bac88551ca0556569249be5317e66fc796cac" + url: "https://pub.dev" + source: hosted + version: "3.0.0" meta: dependency: transitive description: @@ -1285,6 +1317,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.0" + pinenacl: + dependency: transitive + description: + name: pinenacl + sha256: e5fb0bce1717b7f136f35ee98b5c02b3e6383211f8a77ca882fa7812232a07b9 + url: "https://pub.dev" + source: hosted + version: "0.3.4" platform: dependency: transitive description: @@ -1317,6 +1357,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + pretty_dio_logger: + dependency: transitive + description: + name: pretty_dio_logger + sha256: "948f7eeb36e7aa0760b51c1a8e3331d4b21e36fabd39efca81f585ed93893544" + url: "https://pub.dev" + source: hosted + version: "1.2.0-beta-1" process: dependency: transitive description: @@ -1365,6 +1413,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + quiver: + dependency: transitive + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" rational: dependency: "direct main" description: @@ -1373,6 +1429,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + retry: + dependency: transitive + description: + name: retry + sha256: a8a1e475a100a0bdc73f529ca8ea1e9c9c76bec8ad86a1f47780139a34ce7aea + url: "https://pub.dev" + source: hosted + version: "3.1.1" riverpod: dependency: transitive description: @@ -1659,6 +1723,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.20" + tezart: + dependency: "direct main" + description: + name: tezart + sha256: "35d526f2e6ca250c64461ebfb4fa9f64b6599fab8c4242c8e89ae27d4ac2e15a" + url: "https://pub.dev" + source: hosted + version: "2.0.5" time: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3533282bf..25cd1e354 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -153,6 +153,7 @@ dependencies: rational: ^2.2.2 archive: ^3.3.2 desktop_drop: ^0.4.1 + tezart: ^2.0.5 dev_dependencies: flutter_test: @@ -198,6 +199,7 @@ dependency_overrides: url: https://github.com/cypherstack/stack-bip39.git ref: 3bef5acc21340f3cc78df0ad1dce5868a3ed68a5 crypto: 3.0.2 + analyzer: ^5.2.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From d04df00691dd71acae9261e18d831a5f2b08b0df Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Wed, 21 Jun 2023 14:29:28 +0300 Subject: [PATCH 017/237] feat: update xtz --- lib/services/coins/tezos/tezos_wallet.dart | 146 +++++++++++++++++---- lib/utilities/constants.dart | 1 + lib/utilities/default_nodes.dart | 2 +- 3 files changed, 123 insertions(+), 26 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index fca4eabc2..9048c1d04 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -1,6 +1,9 @@ import 'dart:async'; +import 'dart:convert'; +import 'dart:ffi'; import 'package:http/http.dart'; +import 'package:isar/isar.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'; @@ -11,8 +14,10 @@ import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/default_nodes.dart'; +import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; import 'package:tezart/tezart.dart'; +import 'package:tuple/tuple.dart'; import '../../../db/isar/main_db.dart'; import '../../../models/node_model.dart'; @@ -49,6 +54,10 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { return _xtzNode ?? NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: Coin.tezos) ?? DefaultNodes.getNodeFor(Coin.tezos); } + Future getKeystore() async { + return Keystore.fromMnemonic((await mnemonicString).toString()); + } + @override String get walletId => _walletId; late String _walletId; @@ -102,10 +111,36 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Balance? _balance; @override - Future confirmSend({required Map txData}) { - // TODO: implement confirmSend, - // NOTE FROM DETHERMINAL: I couldnt write this function because I dont have any tezos to test with - throw UnimplementedError(); + Future> prepareSend({required String address, required Amount amount, Map? args}) async { + try { + if (amount.decimals != coin.decimals) { + throw Exception("Amount decimals do not match coin decimals!"); + } + var fee = int.parse((await estimateFeeFor(amount, (args!["feeRate"] as FeeRateType).index)).raw.toString()); + Map txData = { + "fee": fee, + "address": address, + "recipientAmt": amount, + }; + return Future.value(txData); + } catch (e) { + return Future.error(e); + } + } + + @override + Future confirmSend({required Map txData}) async { + try { + final node = getCurrentNode().host + getCurrentNode().port.toString(); + final int amountInMicroTez = ((int.parse((txData["recipientAmt"] as Amount).raw.toString()) * 1000000)).round(); + final int feeInMicroTez = int.parse(txData["fee"].toString()); + final String destinationAddress = txData["address"] as String; + final String sourceAddress = await currentReceivingAddress; + return Future.value(""); // TODO: return tx hash + } catch (e) { + Logging.instance.log(e.toString(), level: LogLevel.Error); + return Future.error(e); + } } @override @@ -114,13 +149,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { if (mneString == null) { throw Exception("No mnemonic found!"); } - return Future.value(Keystore.fromMnemonic(mneString).address); + return Future.value((Keystore.fromMnemonic(mneString)).address); } @override Future estimateFeeFor(Amount amount, int feeRate) { - // TODO: implement estimateFeeFor - throw UnimplementedError(); + return Future.value( + Amount(rawValue: BigInt.parse(100000.toString()), fractionDigits: coin.decimals), + ); } @override @@ -130,13 +166,22 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - // TODO: implement fees - Future get fees => throw UnimplementedError(); + Future get fees async { + // TODO: Change this to get fees from node and fix numberOfBlocks + return FeeObject( + numberOfBlocksFast: 1, + numberOfBlocksAverage: 1, + numberOfBlocksSlow: 1, + fast: 1000000, + medium: 100000, + slow: 10000, + ); + } @override Future fullRescan(int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) { - // TODO: implement fullRescan - throw UnimplementedError(); + refresh(); + return Future.value(); } @override @@ -215,13 +260,6 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future get mnemonicString => _secureStore.read(key: '${_walletId}_mnemonic'); - @override - Future> prepareSend({required String address, required Amount amount, Map? args}) { - // TODO: implement prepareSend - // NOTE FROM DETHERMINAL: I couldnt write this function because I dont have any tezos to test with - throw UnimplementedError(); - } - @override Future recoverFromMnemonic({required String mnemonic, String? mnemonicPassphrase, required int maxUnusedAddressGap, required int maxNumberOfIndexesToCheck, required int height}) async { if ((await mnemonicString) != null || @@ -267,9 +305,66 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { await updateCachedBalance(_balance!); } + Future updateTransactions() async { + var api = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance_history"; // TODO: Can we use current node instead of this? + var returnedTxs = await get(Uri.parse(api)).then((value) => value.body); + Logging.instance.log( + "Transactions for ${await currentReceivingAddress}: $returnedTxs", + level: LogLevel.Info); + List> txs = []; + Object? jsonTxs = jsonDecode(returnedTxs); + if (jsonTxs == null) { + await db.addNewTransactionData(txs, walletId); + } else { + for (var tx in jsonTxs as List) { + var theTx = Transaction( + walletId: walletId, + txid: "", + timestamp: DateTime.parse(tx["timestamp"].toString()).toUtc().millisecondsSinceEpoch ~/ 1000, + type: TransactionType.unknown, + subType: TransactionSubType.none, + amount: int.parse(tx["balance"].toString()), + amountString: Amount( + rawValue: BigInt.parse(tx["balance"].toString()), + fractionDigits: 6 + ).toJsonString(), + fee: 0, + height: int.parse(tx["level"].toString()), + isCancelled: false, + isLelantus: false, + slateId: "", + otherData: "", + inputs: [], + outputs: [], + nonce: 0 + ); + var theAddress = Address( + walletId: walletId, + value: await currentReceivingAddress, + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + txs.add(Tuple2(theTx, theAddress)); + } + await db.addNewTransactionData(txs, walletId); + } + } + + Future updateChainHeight() async { + var api = "https://api.tzkt.io/v1/blocks/count"; // TODO: Can we use current node instead of this? + var returnedHeight = await get(Uri.parse(api)).then((value) => value.body); + final int intHeight = int.parse(returnedHeight.toString()); + await updateCachedChainHeight(intHeight); + } + @override Future refresh() { + updateChainHeight(); updateBalance(); + updateTransactions(); return Future.value(); } @@ -277,16 +372,17 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { int get storedChainHeight => getCachedChainHeight(); @override - Future testNetworkConnection() { - // TODO: implement testNetworkConnection - throw UnimplementedError(); + Future testNetworkConnection() async{ + try { + await get(Uri.parse("https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance")); + return true; + } catch (e) { + return false; + } } @override - // TODO: implement transactions - Future> get transactions async { - // TODO: Maybe we can use this -> https://api.tzkt.io/#operation/Accounts_GetBalanceHistory - } + Future> get transactions => db.getTransactions(walletId).findAll(); @override Future updateNode(bool shouldRefresh) async { diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 2fdacc64b..b74de5b98 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -136,6 +136,7 @@ abstract class Constants { case Coin.ethereum: case Coin.namecoin: case Coin.particl: + case Coin.tezos: values.addAll([24, 21, 18, 15, 12]); break; diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index 8c48f5340..ad9310c3d 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -173,7 +173,7 @@ abstract class DefaultNodes { ); static NodeModel get tezos => NodeModel( // TODO: Change this to original one - host: "https://mainnet.api.tez.ie", + host: "mainnet.api.tez.ie", port: 443, name: defaultName, id: _nodeId(Coin.tezos), From bedbc99cbb48cd7baa2199dc8b2ea41c68ab4de5 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 12 Jul 2023 16:52:56 -0500 Subject: [PATCH 018/237] update tor plugin submodule --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 6216e459e..e49d0ee27 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 6216e459eb359edd64c44d26bc5d6afed6d3ce44 +Subproject commit e49d0ee273622e488553f1f715f88b4b82df5cbd From d45a156f2fb6392c07c57da7c4a24e338d3e20dd Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 12 Jul 2023 16:53:04 -0500 Subject: [PATCH 019/237] update monero plugin submodule --- crypto_plugins/flutter_libmonero | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_libmonero b/crypto_plugins/flutter_libmonero index 26a152fea..13f19022e 160000 --- a/crypto_plugins/flutter_libmonero +++ b/crypto_plugins/flutter_libmonero @@ -1 +1 @@ -Subproject commit 26a152fea3ca4b8c3f1130392a02f579c2ff218c +Subproject commit 13f19022e8d929b215a65f775b0dda7a5881608c From eb7d210770cb5e4d9ef46ef6dace0019a5bcd468 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 12 Jul 2023 16:53:12 -0500 Subject: [PATCH 020/237] update epic cash plugin submodule --- crypto_plugins/flutter_libepiccash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_libepiccash b/crypto_plugins/flutter_libepiccash index e1df08873..cd12741de 160000 --- a/crypto_plugins/flutter_libepiccash +++ b/crypto_plugins/flutter_libepiccash @@ -1 +1 @@ -Subproject commit e1df088733695ad06d377087d069eae1746d55a7 +Subproject commit cd12741de19e4faef39a23b7d543a2452524990a From 24e8abfa62eedac20b7e1261e9e3b91fd27c0b96 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Thu, 13 Jul 2023 16:28:03 -0500 Subject: [PATCH 021/237] runnable tor example --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index e49d0ee27..fcb283ec6 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit e49d0ee273622e488553f1f715f88b4b82df5cbd +Subproject commit fcb283ec619a480093a15c51ec9f719e1f35f9fb From a916f17425f9c5fbe3299748e6508b57b0fd3119 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Fri, 14 Jul 2023 11:19:08 -0500 Subject: [PATCH 022/237] updated generated registrants --- linux/flutter/generated_plugins.cmake | 1 + windows/flutter/generated_plugins.cmake | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 38eed0699..397cac07d 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -15,6 +15,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + tor ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 324c950be..934f038bc 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -16,6 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + tor ) set(PLUGIN_BUNDLED_LIBRARIES) From 2139f5ba6f58fe08ec77c411e21a2e5cc06f2cfa Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Fri, 14 Jul 2023 11:27:50 -0500 Subject: [PATCH 023/237] flutter pub add flutter_socks_proxy --- pubspec.lock | 16 ++++++++-------- pubspec.yaml | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index a1569c04d..28518fb0a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -722,6 +722,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + flutter_socks_proxy: + dependency: "direct main" + description: + name: flutter_socks_proxy + sha256: be3a9fb6d32ec983e944c5735406262e941d154d52ec3ca4ee1e54a72126ec8f + url: "https://pub.dev" + source: hosted + version: "0.0.2" flutter_svg: dependency: "direct main" description: @@ -1611,14 +1619,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" - toast: - dependency: "direct main" - description: - name: toast - sha256: bedb96d37030acf9c4c06a7ac2ffd1f1f365e780cda9458c9e24e6a1e1ab6fd9 - url: "https://pub.dev" - source: hosted - version: "0.1.5" tor: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2d0b502f3..6bb379512 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -141,6 +141,7 @@ dependencies: desktop_drop: ^0.4.1 nanodart: ^2.0.0 basic_utils: ^5.5.4 + flutter_socks_proxy: ^0.0.2 dev_dependencies: flutter_test: From 73888057d79574e68f4f3bb45b1181b71dec0171 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Fri, 14 Jul 2023 12:13:21 -0500 Subject: [PATCH 024/237] WIP flutter_socks_proxy example, need to authenticate --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index fcb283ec6..a43128b13 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit fcb283ec619a480093a15c51ec9f719e1f35f9fb +Subproject commit a43128b131933ad75267dd31061ed6c6690864ef From a6bbc913eb3d1d0244a10b21261c67fcded29bb2 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Fri, 14 Jul 2023 11:27:50 -0500 Subject: [PATCH 025/237] Revert "flutter pub add flutter_socks_proxy" This reverts commit 2139f5ba6f58fe08ec77c411e21a2e5cc06f2cfa. --- pubspec.lock | 16 ++++++++-------- pubspec.yaml | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 28518fb0a..a1569c04d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -722,14 +722,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" - flutter_socks_proxy: - dependency: "direct main" - description: - name: flutter_socks_proxy - sha256: be3a9fb6d32ec983e944c5735406262e941d154d52ec3ca4ee1e54a72126ec8f - url: "https://pub.dev" - source: hosted - version: "0.0.2" flutter_svg: dependency: "direct main" description: @@ -1619,6 +1611,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + toast: + dependency: "direct main" + description: + name: toast + sha256: bedb96d37030acf9c4c06a7ac2ffd1f1f365e780cda9458c9e24e6a1e1ab6fd9 + url: "https://pub.dev" + source: hosted + version: "0.1.5" tor: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 6bb379512..2d0b502f3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -141,7 +141,6 @@ dependencies: desktop_drop: ^0.4.1 nanodart: ^2.0.0 basic_utils: ^5.5.4 - flutter_socks_proxy: ^0.0.2 dev_dependencies: flutter_test: From b3d3ffbd251d33f232bd86c4cfcfa1676f4fe002 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Fri, 14 Jul 2023 16:15:21 -0500 Subject: [PATCH 026/237] use socks5_proxy package for example --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index a43128b13..7320a896e 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit a43128b131933ad75267dd31061ed6c6690864ef +Subproject commit 7320a896e3b641b31bc606f4830d40622e528153 From 5311fc227c34d98abf838b1415f332d63f51b20b Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Fri, 14 Jul 2023 16:30:41 -0500 Subject: [PATCH 027/237] use working tor example --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 7320a896e..887bc69bf 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 7320a896e3b641b31bc606f4830d40622e528153 +Subproject commit 887bc69bf6c937ca861d3746e22a2f295a8b0f08 From 544df2c882052223d38afb024bddc2036d36d43e Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Fri, 14 Jul 2023 16:45:18 -0500 Subject: [PATCH 028/237] add host input for testing the onion service of your choice --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 887bc69bf..43fd95976 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 887bc69bf6c937ca861d3746e22a2f295a8b0f08 +Subproject commit 43fd95976281e4e205c35f34881749ade22b5234 From 0ae747aebc48ade08b02ad2e9b22a1a809099b1a Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Mon, 12 Jun 2023 22:03:32 +0300 Subject: [PATCH 029/237] feat: add xtz --- lib/models/isar/stack_theme.dart | 9 + .../add_edit_node_view.dart | 1 + lib/services/coins/coin_service.dart | 10 + lib/services/coins/tezos/tezos_wallet.dart | 314 ++++++++++++++++++ lib/themes/coin_icon_provider.dart | 2 + lib/themes/coin_image_provider.dart | 4 + lib/themes/color_theme.dart | 3 + lib/themes/stack_colors.dart | 2 + lib/utilities/address_utils.dart | 2 + lib/utilities/block_explorers.dart | 2 + lib/utilities/constants.dart | 14 + lib/utilities/default_nodes.dart | 18 +- lib/utilities/enums/coin_enum.dart | 21 ++ .../enums/derive_path_type_enum.dart | 1 + pubspec.lock | 260 +++++++++------ pubspec.yaml | 6 +- 16 files changed, 571 insertions(+), 98 deletions(-) create mode 100644 lib/services/coins/tezos/tezos_wallet.dart diff --git a/lib/models/isar/stack_theme.dart b/lib/models/isar/stack_theme.dart index 557090584..f6f7c351d 100644 --- a/lib/models/isar/stack_theme.dart +++ b/lib/models/isar/stack_theme.dart @@ -1921,6 +1921,7 @@ class ThemeAssets implements IThemeAssets { late final String wownero; late final String namecoin; late final String particl; + late final String tezos; late final String bitcoinImage; late final String bitcoincashImage; late final String dogecoinImage; @@ -1932,6 +1933,7 @@ class ThemeAssets implements IThemeAssets { late final String wowneroImage; late final String namecoinImage; late final String particlImage; + late final String tezosImage; late final String bitcoinImageSecondary; late final String bitcoincashImageSecondary; late final String dogecoinImageSecondary; @@ -1943,6 +1945,7 @@ class ThemeAssets implements IThemeAssets { late final String wowneroImageSecondary; late final String namecoinImageSecondary; late final String particlImageSecondary; + late final String tezosImageSecondary; @override late final String? loadingGif; @override @@ -1988,6 +1991,8 @@ class ThemeAssets implements IThemeAssets { ..wownero = "$themeId/assets/${json["wownero"] as String}" ..namecoin = "$themeId/assets/${json["namecoin"] as String}" ..particl = "$themeId/assets/${json["particl"] as String}" + ..tezos = + "$themeId/assets/${json["bitcoin"] as String}" ..bitcoinImage = "$themeId/assets/${json["bitcoin_image"] as String}" ..bitcoincashImage = "$themeId/assets/${json["bitcoincash_image"] as String}" @@ -2000,6 +2005,8 @@ class ThemeAssets implements IThemeAssets { ..wowneroImage = "$themeId/assets/${json["wownero_image"] as String}" ..namecoinImage = "$themeId/assets/${json["namecoin_image"] as String}" ..particlImage = "$themeId/assets/${json["particl_image"] as String}" + ..tezosImage = + "$themeId/assets/${json["bitcoin_image"] as String}" ..bitcoinImageSecondary = "$themeId/assets/${json["bitcoin_image_secondary"] as String}" ..bitcoincashImageSecondary = @@ -2022,6 +2029,8 @@ class ThemeAssets implements IThemeAssets { "$themeId/assets/${json["namecoin_image_secondary"] as String}" ..particlImageSecondary = "$themeId/assets/${json["particl_image_secondary"] as String}" + ..tezosImageSecondary = + "$themeId/assets/${json["bitcoin_image_secondary"] as String}" // TODO: change to tezos ..loadingGif = json["loading_gif"] is String ? "$themeId/assets/${json["loading_gif"] as String}" : null diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 3e5d3e3e4..c2543088d 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -727,6 +727,7 @@ class _NodeFormState extends ConsumerState { case Coin.namecoin: case Coin.bitcoincash: case Coin.particl: + case Coin.tezos: case Coin.bitcoinTestNet: case Coin.litecoinTestNet: case Coin.bitcoincashTestnet: diff --git a/lib/services/coins/coin_service.dart b/lib/services/coins/coin_service.dart index 00a52eba5..3c1542805 100644 --- a/lib/services/coins/coin_service.dart +++ b/lib/services/coins/coin_service.dart @@ -27,6 +27,7 @@ import 'package:stackwallet/services/coins/monero/monero_wallet.dart'; import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'; import 'package:stackwallet/services/coins/nano/nano_wallet.dart'; import 'package:stackwallet/services/coins/particl/particl_wallet.dart'; +import 'package:stackwallet/services/coins/tezos/tezos_wallet.dart'; import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; @@ -218,6 +219,15 @@ abstract class CoinServiceAPI { cachedClient: cachedClient, tracker: tracker); + case Coin.tezos: + return TezosWallet( + walletId: walletId, + walletName: walletName, + coin: coin, + secureStore: secureStorageInterface, + tracker: tracker, + ); + case Coin.wownero: return WowneroWallet( walletId: walletId, diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart new file mode 100644 index 000000000..fca4eabc2 --- /dev/null +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -0,0 +1,314 @@ +import 'dart:async'; + +import 'package:http/http.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'; +import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; +import 'package:stackwallet/models/paymint/fee_object_model.dart'; +import 'package:stackwallet/services/coins/coin_service.dart'; +import 'package:stackwallet/services/node_service.dart'; +import 'package:stackwallet/utilities/amount/amount.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/default_nodes.dart'; + +import 'package:tezart/tezart.dart'; + +import '../../../db/isar/main_db.dart'; +import '../../../models/node_model.dart'; +import '../../../utilities/flutter_secure_storage_interface.dart'; +import '../../../utilities/logger.dart'; +import '../../../utilities/prefs.dart'; +import '../../mixins/wallet_cache.dart'; +import '../../mixins/wallet_db.dart'; +import '../../transaction_notification_tracker.dart'; + +const int MINIMUM_CONFIRMATIONS = 1; + +class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { + TezosWallet({ + required String walletId, + required String walletName, + required Coin coin, + required SecureStorageInterface secureStore, + required TransactionNotificationTracker tracker, + MainDB? mockableOverride, + }) { + txTracker = tracker; + _walletId = walletId; + _walletName = walletName; + _coin = coin; + _secureStore = secureStore; + initCache(walletId, coin); + initWalletDB(mockableOverride: mockableOverride); + } + + NodeModel? _xtzNode; + + NodeModel getCurrentNode() { + return _xtzNode ?? NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: Coin.tezos) ?? DefaultNodes.getNodeFor(Coin.tezos); + } + + @override + String get walletId => _walletId; + late String _walletId; + + @override + String get walletName => _walletName; + late String _walletName; + + @override + set walletName(String name) => _walletName = name; + + @override + set isFavorite(bool markFavorite) { + _isFavorite = markFavorite; + updateCachedIsFavorite(markFavorite); + } + + @override + bool get isFavorite => _isFavorite ??= getCachedIsFavorite(); + bool? _isFavorite; + + @override + Coin get coin => _coin; + late Coin _coin; + + late SecureStorageInterface _secureStore; + late final TransactionNotificationTracker txTracker; + final _prefs = Prefs.instance; + + Timer? timer; + bool _shouldAutoSync = false; + + @override + bool get shouldAutoSync => _shouldAutoSync; + + @override + set shouldAutoSync(bool shouldAutoSync) { + if (_shouldAutoSync != shouldAutoSync) { + _shouldAutoSync = shouldAutoSync; + if (!shouldAutoSync) { + timer?.cancel(); + timer = null; + } else { + refresh(); + } + } + } + + @override + Balance get balance => _balance ??= getCachedBalance(); + Balance? _balance; + + @override + Future confirmSend({required Map txData}) { + // TODO: implement confirmSend, + // NOTE FROM DETHERMINAL: I couldnt write this function because I dont have any tezos to test with + throw UnimplementedError(); + } + + @override + Future get currentReceivingAddress async { + var mneString = await mnemonicString; + if (mneString == null) { + throw Exception("No mnemonic found!"); + } + return Future.value(Keystore.fromMnemonic(mneString).address); + } + + @override + Future estimateFeeFor(Amount amount, int feeRate) { + // TODO: implement estimateFeeFor + throw UnimplementedError(); + } + + @override + Future exit() { + _hasCalledExit = true; + return Future.value(); + } + + @override + // TODO: implement fees + Future get fees => throw UnimplementedError(); + + @override + Future fullRescan(int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) { + // TODO: implement fullRescan + throw UnimplementedError(); + } + + @override + Future generateNewAddress() { + // TODO: implement generateNewAddress + throw UnimplementedError(); + } + + @override + bool get hasCalledExit => _hasCalledExit; + bool _hasCalledExit = false; + + @override + Future initializeExisting() async { + await _prefs.init(); + } + + @override + Future initializeNew() async { + var newKeystore = Keystore.random(); + await _secureStore.write( + key: '${_walletId}_mnemonic', + value: newKeystore.mnemonic, + ); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: "", + ); + + final address = Address( + walletId: walletId, + value: newKeystore.address, + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + + await db.putAddress(address); + + await Future.wait([ + updateCachedId(walletId), + updateCachedIsFavorite(false), + ]); + } + + @override + bool get isConnected => _isConnected; + bool _isConnected = false; + + @override + bool get isRefreshing => refreshMutex; + bool refreshMutex = false; + + @override + // TODO: implement maxFee + Future get maxFee => throw UnimplementedError(); + + @override + Future> get mnemonic async { + final mnemonic = await mnemonicString; + final mnemonicPassphrase = await this.mnemonicPassphrase; + if (mnemonic == null) { + throw Exception("No mnemonic found!"); + } + if (mnemonicPassphrase == null) { + throw Exception("No mnemonic passphrase found!"); + } + return mnemonic.split(" "); + } + + @override + Future get mnemonicPassphrase => _secureStore.read(key: '${_walletId}_mnemonicPassphrase'); + + @override + Future get mnemonicString => _secureStore.read(key: '${_walletId}_mnemonic'); + + @override + Future> prepareSend({required String address, required Amount amount, Map? args}) { + // TODO: implement prepareSend + // NOTE FROM DETHERMINAL: I couldnt write this function because I dont have any tezos to test with + throw UnimplementedError(); + } + + @override + Future recoverFromMnemonic({required String mnemonic, String? mnemonicPassphrase, required int maxUnusedAddressGap, required int maxNumberOfIndexesToCheck, required int height}) async { + if ((await mnemonicString) != null || + (await this.mnemonicPassphrase) != null) { + throw Exception("Attempted to overwrite mnemonic on restore!"); + } + await _secureStore.write( + key: '${_walletId}_mnemonic', value: mnemonic.trim()); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: mnemonicPassphrase ?? "", + ); + + final address = Address( + walletId: walletId, + value: Keystore.fromMnemonic(mnemonic).address, + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + + await db.putAddress(address); + + await Future.wait([ + updateCachedId(walletId), + updateCachedIsFavorite(false), + ]); + } + + Future updateBalance() async { + var api = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance"; // TODO: Can we use current node instead of this? + var theBalance = await get(Uri.parse(api)).then((value) => value.body); + Logging.instance.log("Balance for ${await currentReceivingAddress}: $theBalance", level: LogLevel.Info); + var balanceInAmount = Amount(rawValue: BigInt.parse(theBalance.toString()), fractionDigits: 6); + _balance = Balance( + total: balanceInAmount, + spendable: balanceInAmount, + blockedTotal: Amount(rawValue: BigInt.parse("0"), fractionDigits: 6), + pendingSpendable: Amount(rawValue: BigInt.parse("0"), fractionDigits: 6), + ); + await updateCachedBalance(_balance!); + } + + @override + Future refresh() { + updateBalance(); + return Future.value(); + } + + @override + int get storedChainHeight => getCachedChainHeight(); + + @override + Future testNetworkConnection() { + // TODO: implement testNetworkConnection + throw UnimplementedError(); + } + + @override + // TODO: implement transactions + Future> get transactions async { + // TODO: Maybe we can use this -> https://api.tzkt.io/#operation/Accounts_GetBalanceHistory + } + + @override + Future updateNode(bool shouldRefresh) async { + _xtzNode = NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: coin) ?? DefaultNodes.getNodeFor(coin); + + if (shouldRefresh) { + await refresh(); + } + } + + @override + Future updateSentCachedTxData(Map txData) { + // TODO: implement updateSentCachedTxData + throw UnimplementedError(); + } + + @override + // TODO: implement utxos + Future> get utxos => throw UnimplementedError(); + + @override + bool validateAddress(String address) { + return RegExp(r"^tz[1-9A-HJ-NP-Za-km-z]{34}$").hasMatch(address); + } +} diff --git a/lib/themes/coin_icon_provider.dart b/lib/themes/coin_icon_provider.dart index 9bd3990bb..acbfaed3f 100644 --- a/lib/themes/coin_icon_provider.dart +++ b/lib/themes/coin_icon_provider.dart @@ -43,6 +43,8 @@ final coinIconProvider = Provider.family((ref, coin) { return assets.namecoin; case Coin.particl: return assets.particl; + case Coin.tezos: + return assets.tezos; case Coin.ethereum: return assets.ethereum; default: diff --git a/lib/themes/coin_image_provider.dart b/lib/themes/coin_image_provider.dart index 6ca839fb9..d72e7b778 100644 --- a/lib/themes/coin_image_provider.dart +++ b/lib/themes/coin_image_provider.dart @@ -41,6 +41,8 @@ final coinImageProvider = Provider.family((ref, coin) { return assets.namecoinImage; case Coin.particl: return assets.particlImage; + case Coin.tezos: + return assets.tezosImage; case Coin.bitcoinTestNet: return assets.bitcoinImage; case Coin.bitcoincashTestnet: @@ -89,6 +91,8 @@ final coinImageSecondaryProvider = Provider.family((ref, coin) { return assets.namecoinImageSecondary; case Coin.particl: return assets.particlImageSecondary; + case Coin.tezos: + return assets.tezosImageSecondary; case Coin.bitcoinTestNet: return assets.bitcoinImageSecondary; case Coin.bitcoincashTestnet: diff --git a/lib/themes/color_theme.dart b/lib/themes/color_theme.dart index bcfa45ac9..1ea9253a4 100644 --- a/lib/themes/color_theme.dart +++ b/lib/themes/color_theme.dart @@ -30,6 +30,7 @@ class CoinThemeColorDefault { Color get particl => const Color(0xFF8175BD); Color get nano => const Color(0xFF209CE9); Color get banano => const Color(0xFFFBDD11); + Color get tezos => const Color(0xFF0F61FF); Color forCoin(Coin coin) { switch (coin) { @@ -66,6 +67,8 @@ class CoinThemeColorDefault { return nano; case Coin.banano: return banano; + case Coin.tezos: + return tezos; } } } diff --git a/lib/themes/stack_colors.dart b/lib/themes/stack_colors.dart index b9e58a5ca..4c3362b95 100644 --- a/lib/themes/stack_colors.dart +++ b/lib/themes/stack_colors.dart @@ -1711,6 +1711,8 @@ class StackColors extends ThemeExtension { return _coin.nano; case Coin.banano: return _coin.banano; + case Coin.tezos: + return _coin.tezos; } } diff --git a/lib/utilities/address_utils.dart b/lib/utilities/address_utils.dart index 0093e1d00..77cff70ab 100644 --- a/lib/utilities/address_utils.dart +++ b/lib/utilities/address_utils.dart @@ -109,6 +109,8 @@ class AddressUtils { return NanoAccounts.isValid(NanoAccountType.NANO, address); case Coin.banano: return NanoAccounts.isValid(NanoAccountType.BANANO, address); + case Coin.tezos: + return RegExp(r"^tz[1-9A-HJ-NP-Za-km-z]{34}$").hasMatch(address); case Coin.bitcoinTestNet: return Address.validateAddress(address, testnet); case Coin.litecoinTestNet: diff --git a/lib/utilities/block_explorers.dart b/lib/utilities/block_explorers.dart index 7ff0cf349..bcca709e6 100644 --- a/lib/utilities/block_explorers.dart +++ b/lib/utilities/block_explorers.dart @@ -58,6 +58,8 @@ Uri getDefaultBlockExplorerUrlFor({ return Uri.parse("https://www.nanolooker.com/block/$txid"); case Coin.banano: return Uri.parse("https://www.bananolooker.com/block/$txid"); + case Coin.tezos: + return Uri.parse("https://tzstats.com/$txid"); } } diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 2dd7be287..f23c1827a 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -44,6 +44,7 @@ abstract class Constants { static final BigInt _satsPerCoinBanano = BigInt.parse("100000000000000000000000000000"); // 1*10^29 static final BigInt _satsPerCoin = BigInt.from(100000000); + static final BigInt _satsPerCoinTezos = BigInt.from(1000000); static const int _decimalPlaces = 8; static const int _decimalPlacesNano = 30; static const int _decimalPlacesBanano = 29; @@ -51,6 +52,7 @@ abstract class Constants { static const int _decimalPlacesMonero = 12; static const int _decimalPlacesEthereum = 18; static const int _decimalPlacesECash = 2; + static const int _decimalPlacesTezos = 6; static const int notificationsMax = 0xFFFFFFFF; static const Duration networkAliveTimerDuration = Duration(seconds: 10); @@ -96,6 +98,9 @@ abstract class Constants { case Coin.eCash: return _satsPerCoinECash; + + case Coin.tezos: + return _satsPerCoinTezos; } } @@ -133,6 +138,9 @@ abstract class Constants { case Coin.eCash: return _decimalPlacesECash; + + case Coin.tezos: + return _decimalPlacesTezos; } } @@ -160,6 +168,8 @@ abstract class Constants { case Coin.banano: values.addAll([24, 12]); break; + case Coin.tezos: + values.addAll([24, 12]); case Coin.monero: values.addAll([25]); @@ -214,6 +224,9 @@ abstract class Constants { case Coin.nano: // TODO: Verify this case Coin.banano: // TODO: Verify this return 1; + + case Coin.tezos: + return 60; } } @@ -241,6 +254,7 @@ abstract class Constants { case Coin.nano: case Coin.banano: + case Coin.tezos: return 24; case Coin.monero: diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index c8ff94120..05e192f77 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -179,7 +179,20 @@ abstract class DefaultNodes { enabled: true, coinName: Coin.particl.name, isFailover: true, - isDown: false); + isDown: false + ); + + static NodeModel get tezos => NodeModel( // TODO: Change this to original one + host: "https://mainnet.api.tez.ie", + port: 443, + name: defaultName, + id: _nodeId(Coin.tezos), + useSSL: true, + enabled: true, + coinName: Coin.tezos.name, + isFailover: true, + isDown: false + ); static NodeModel get nano => NodeModel( host: "https://rainstorm.city/api", @@ -300,12 +313,13 @@ abstract class DefaultNodes { case Coin.particl: return particl; - case Coin.nano: return nano; case Coin.banano: return banano; + case Coin.tezos: + return tezos; case Coin.bitcoinTestNet: return bitcoinTestnet; diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index c656b2c62..f4a1eebbb 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -27,6 +27,7 @@ import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart' import 'package:stackwallet/services/coins/nano/nano_wallet.dart' as nano; import 'package:stackwallet/services/coins/particl/particl_wallet.dart' as particl; +import 'package:stackwallet/services/coins/tezos/tezos_wallet.dart' as tezos; import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow; import 'package:stackwallet/utilities/constants.dart'; @@ -44,6 +45,7 @@ enum Coin { namecoin, nano, particl, + tezos, wownero, /// @@ -84,6 +86,8 @@ extension CoinExt on Coin { return "Monero"; case Coin.particl: return "Particl"; + case Coin.tezos: + return "Tezos"; case Coin.wownero: return "Wownero"; case Coin.namecoin: @@ -127,6 +131,8 @@ extension CoinExt on Coin { return "XMR"; case Coin.particl: return "PART"; + case Coin.tezos: + return "XTZ"; case Coin.wownero: return "WOW"; case Coin.namecoin: @@ -171,6 +177,8 @@ extension CoinExt on Coin { return "monero"; case Coin.particl: return "particl"; + case Coin.tezos: + return "tezos"; case Coin.wownero: return "wownero"; case Coin.namecoin: @@ -212,6 +220,7 @@ extension CoinExt on Coin { case Coin.epicCash: case Coin.ethereum: case Coin.monero: + case Coin.tezos: case Coin.wownero: case Coin.nano: case Coin.banano: @@ -234,6 +243,7 @@ extension CoinExt on Coin { case Coin.eCash: case Coin.epicCash: case Coin.monero: + case Coin.tezos: case Coin.wownero: case Coin.dogecoinTestNet: case Coin.bitcoinTestNet: @@ -258,6 +268,7 @@ extension CoinExt on Coin { case Coin.epicCash: case Coin.ethereum: case Coin.monero: + case Coin.tezos: case Coin.wownero: case Coin.nano: case Coin.banano: @@ -285,6 +296,7 @@ extension CoinExt on Coin { case Coin.epicCash: case Coin.ethereum: case Coin.monero: + case Coin.tezos: case Coin.wownero: case Coin.nano: case Coin.banano: @@ -345,6 +357,9 @@ extension CoinExt on Coin { case Coin.particl: return particl.MINIMUM_CONFIRMATIONS; + case Coin.tezos: + return tezos.MINIMUM_CONFIRMATIONS; + case Coin.wownero: return wow.MINIMUM_CONFIRMATIONS; @@ -404,6 +419,10 @@ Coin coinFromPrettyName(String name) { case "particl": return Coin.particl; + case "Tezos": + case "tezos": + return Coin.tezos; + case "Namecoin": case "namecoin": return Coin.namecoin; @@ -481,6 +500,8 @@ Coin coinFromTickerCaseInsensitive(String ticker) { return Coin.namecoin; case "part": return Coin.particl; + case "xtz": + return Coin.tezos; case "tltc": return Coin.litecoinTestNet; case "tbtc": diff --git a/lib/utilities/enums/derive_path_type_enum.dart b/lib/utilities/enums/derive_path_type_enum.dart index f3e7f86df..99d26e24c 100644 --- a/lib/utilities/enums/derive_path_type_enum.dart +++ b/lib/utilities/enums/derive_path_type_enum.dart @@ -49,6 +49,7 @@ extension DerivePathTypeExt on DerivePathType { case Coin.wownero: case Coin.nano: case Coin.banano: + case Coin.tezos: // TODO: Is this true? throw UnsupportedError( "$coin does not use bitcoin style derivation paths"); } diff --git a/pubspec.lock b/pubspec.lock index 2dcd3c598..4bcb94925 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.30" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a" + url: "https://pub.dev" + source: hosted + version: "2.0.1" archive: dependency: "direct main" description: @@ -37,18 +45,18 @@ packages: dependency: transitive description: name: args - sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" asn1lib: dependency: transitive description: name: asn1lib - sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 + sha256: b74e3842a52c61f8819a1ec8444b4de5419b41a7465e69d4aa681445377398b0 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" async: dependency: "direct main" description: @@ -146,10 +154,10 @@ packages: dependency: transitive description: name: build - sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" build_config: dependency: transitive description: @@ -170,26 +178,26 @@ packages: dependency: transitive description: name: build_resolvers - sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 + sha256: "6c4dd11d05d056e76320b828a1db0fc01ccd376922526f8e9d6c796a5adbac20" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "220ae4553e50d7c21a17c051afc7b183d28a24a420502e842f303f8e4e6edced" + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.6" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "88a57f2ac99849362e73878334caa9f06ee25f31d2adced882b8337838c84e1e" + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" url: "https://pub.dev" source: hosted - version: "7.2.9" + version: "7.2.10" built_collection: dependency: transitive description: @@ -202,10 +210,10 @@ packages: dependency: transitive description: name: built_value - sha256: "7dd62d9faf105c434f3d829bbe9c4be02ec67f5ed94832222116122df67c5452" + sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" url: "https://pub.dev" source: hosted - version: "8.6.0" + version: "8.6.1" characters: dependency: transitive description: @@ -242,10 +250,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.5.0" collection: dependency: transitive description: @@ -298,10 +306,10 @@ packages: dependency: "direct main" description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" cryptography: dependency: transitive description: @@ -314,10 +322,10 @@ packages: dependency: transitive description: name: csslib - sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" url: "https://pub.dev" source: hosted - version: "0.17.3" + version: "1.0.0" cw_core: dependency: "direct main" description: @@ -382,18 +390,18 @@ packages: dependency: transitive description: name: dart_style - sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" dartx: dependency: transitive description: name: dartx - sha256: "45d7176701f16c5a5e00a4798791c1964bc231491b879369c818dd9a9c764871" + sha256: "8b25435617027257d43e6508b5fe061012880ddfdaa75a71d607c3de2a13d244" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" dbus: dependency: transitive description: @@ -406,10 +414,10 @@ packages: dependency: "direct main" description: name: decimal - sha256: eece91944f523657c75a3a008a90ec7f7eb3986191153a78570c7d0ac8ef3d01 + sha256: "24a261d5d5c87e86c7651c417a5dbdf8bcd7080dd592533910e8d0505a279f21" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" dependency_validator: dependency: "direct dev" description: @@ -450,14 +458,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" + dio: + dependency: transitive + description: + name: dio + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" + url: "https://pub.dev" + source: hosted + version: "4.0.6" dropdown_button2: dependency: "direct main" description: name: dropdown_button2 - sha256: "374f2390161bf782b4896f0b1b24cbb2b5daaa1cfb11047c3307461dcdf44e07" + sha256: "83c54a5022f898d63e3abe21240b64b937e676103207287e6705d3f9bb04d654" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.3.6" eip1559: dependency: transitive description: @@ -542,10 +558,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "9d6e95ec73abbd31ec54d0e0df8a961017e165aba1395e462e5b31ea0c165daf" + sha256: b1729fc96627dd44012d0a901558177418818d6bd428df59dcfeb594e5f66432 url: "https://pub.dev" source: hosted - version: "5.3.1" + version: "5.3.2" fixnum: dependency: transitive description: @@ -606,10 +622,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" flutter_local_notifications: dependency: "direct main" description: @@ -670,10 +686,10 @@ packages: dependency: "direct main" description: name: flutter_rounded_date_picker - sha256: e7143cc5cbf3aec1536286653e38b0809abc99fb76c91bd910dbd98ae003d890 + sha256: e6aa2dc5d3b44e8bbe85ef901be69eac59ba4136427f11f4c8b2a303e1e774e7 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" flutter_secure_storage: dependency: "direct main" description: @@ -821,10 +837,10 @@ packages: dependency: transitive description: name: html - sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" url: "https://pub.dev" source: hosted - version: "0.15.3" + version: "0.15.4" http: dependency: "direct main" description: @@ -934,6 +950,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + json_serializable: + dependency: transitive + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.dev" + source: hosted + version: "6.7.1" keyboard_dismisser: dependency: "direct main" description: @@ -953,10 +977,10 @@ packages: dependency: transitive description: name: lints - sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" local_auth: dependency: "direct main" description: @@ -977,10 +1001,10 @@ packages: dependency: "direct main" description: name: lottie - sha256: "23522951540d20a57a60202ed7022e6376bed206a4eee1c347a91f58bd57eb9f" + sha256: "0793a5866062e5cc8a8b24892fa94c3095953ea914a7fdf790f550dd7537fe60" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.5.0" matcher: dependency: transitive description: @@ -997,6 +1021,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" + memoize: + dependency: transitive + description: + name: memoize + sha256: "51481d328c86cbdc59711369179bac88551ca0556569249be5317e66fc796cac" + url: "https://pub.dev" + source: hosted + version: "3.0.0" meta: dependency: transitive description: @@ -1033,10 +1065,10 @@ packages: dependency: "direct dev" description: name: mockito - sha256: "8b46d7eb40abdda92d62edd01546051f0c27365e65608c284de336dccfef88cc" + sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616" url: "https://pub.dev" source: hosted - version: "5.4.1" + version: "5.4.2" mocktail: dependency: transitive description: @@ -1145,10 +1177,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" + sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.4" path_provider_linux: dependency: transitive description: @@ -1169,50 +1201,50 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6 + sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" permission_handler: dependency: "direct main" description: name: permission_handler - sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8" + sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81" url: "https://pub.dev" source: hosted - version: "10.2.0" + version: "10.4.3" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: d8cc6a62ded6d0f49c6eac337e080b066ee3bce4d405bd9439a61e1f1927bfe8 + sha256: c0c9754479a4c4b1c1f3862ddc11930c9b3f03bef2816bb4ea6eed1e13551d6f url: "https://pub.dev" source: hosted - version: "10.2.1" + version: "10.3.2" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: ee96ac32f5a8e6f80756e25b25b9f8e535816c8e6665a96b6d70681f8c4f7e85 + sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" url: "https://pub.dev" source: hosted - version: "9.0.8" + version: "9.1.4" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84" + sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.11.3" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b + sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 url: "https://pub.dev" source: hosted - version: "0.1.2" + version: "0.1.3" petitparser: dependency: transitive description: @@ -1221,6 +1253,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.4.0" + pinenacl: + dependency: transitive + description: + name: pinenacl + sha256: e5fb0bce1717b7f136f35ee98b5c02b3e6383211f8a77ca882fa7812232a07b9 + url: "https://pub.dev" + source: hosted + version: "0.3.4" platform: dependency: transitive description: @@ -1253,6 +1293,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + pretty_dio_logger: + dependency: transitive + description: + name: pretty_dio_logger + sha256: "948f7eeb36e7aa0760b51c1a8e3331d4b21e36fabd39efca81f585ed93893544" + url: "https://pub.dev" + source: hosted + version: "1.2.0-beta-1" process: dependency: transitive description: @@ -1301,6 +1349,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + quiver: + dependency: transitive + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" rational: dependency: transitive description: @@ -1309,6 +1365,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + retry: + dependency: transitive + description: + name: retry + sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc" + url: "https://pub.dev" + source: hosted + version: "3.1.2" riverpod: dependency: transitive description: @@ -1353,58 +1417,58 @@ packages: dependency: transitive description: name: shared_preferences - sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022" + sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.2.0" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749" + sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb + sha256: f39696b83e844923b642ce9dd4bd31736c17e697f6731a5adf445b1274cf3cd4 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.2" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" + sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d + sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" + sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" + sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" shelf: dependency: transitive description: @@ -1446,18 +1510,18 @@ packages: dependency: transitive description: name: source_gen - sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33" + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" source_helper: dependency: transitive description: name: source_helper - sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" url: "https://pub.dev" source: hosted - version: "1.3.3" + version: "1.3.4" source_map_stack_trace: dependency: transitive description: @@ -1579,6 +1643,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" + tezart: + dependency: "direct main" + description: + name: tezart + sha256: "35d526f2e6ca250c64461ebfb4fa9f64b6599fab8c4242c8e89ae27d4ac2e15a" + url: "https://pub.dev" + source: hosted + version: "2.0.5" time: dependency: transitive description: @@ -1615,10 +1687,10 @@ packages: dependency: "direct main" description: name: tuple - sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" typed_data: dependency: transitive description: @@ -1631,26 +1703,26 @@ packages: dependency: transitive description: name: universal_io - sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d" + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.2" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e" url: "https://pub.dev" source: hosted - version: "6.1.11" + version: "6.1.12" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51 + sha256: "15f5acbf0dce90146a0f5a2c4a002b1814a6303c4c5c075aa2623b2d16156f03" url: "https://pub.dev" source: hosted - version: "6.0.35" + version: "6.0.36" url_launcher_ios: dependency: transitive description: @@ -1671,34 +1743,34 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab" + sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.18" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" uuid: dependency: "direct main" description: @@ -1824,18 +1896,18 @@ packages: dependency: transitive description: name: win32 - sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + sha256: dfdf0136e0aa7a1b474ea133e67cb0154a0acd2599c4f3ada3b49d38d38793ee url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "5.0.5" win32_registry: dependency: transitive description: name: win32_registry - sha256: "1c52f994bdccb77103a6231ad4ea331a244dbcef5d1f37d8462f713143b0bfae" + sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" window_size: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index fd5eac1dc..000ecd8a0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -138,6 +138,7 @@ dependencies: desktop_drop: ^0.4.1 nanodart: ^2.0.0 basic_utils: ^5.5.4 + tezart: ^2.0.5 dev_dependencies: flutter_test: @@ -196,9 +197,10 @@ dependency_overrides: bip39: git: url: https://github.com/cypherstack/stack-bip39.git + ref: 0cd6d54e2860bea68fc50c801cb9db2a760192fb - - + crypto: ^3.0.2 + analyzer: ^5.2.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From d387fcc7b9a916e3c3ef74cdefa3ab7357f6e334 Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Wed, 21 Jun 2023 14:29:28 +0300 Subject: [PATCH 030/237] feat: update xtz --- lib/services/coins/tezos/tezos_wallet.dart | 146 +++++++++++++++++---- lib/utilities/constants.dart | 1 - lib/utilities/default_nodes.dart | 2 +- 3 files changed, 122 insertions(+), 27 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index fca4eabc2..9048c1d04 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -1,6 +1,9 @@ import 'dart:async'; +import 'dart:convert'; +import 'dart:ffi'; import 'package:http/http.dart'; +import 'package:isar/isar.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'; @@ -11,8 +14,10 @@ import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/default_nodes.dart'; +import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; import 'package:tezart/tezart.dart'; +import 'package:tuple/tuple.dart'; import '../../../db/isar/main_db.dart'; import '../../../models/node_model.dart'; @@ -49,6 +54,10 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { return _xtzNode ?? NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: Coin.tezos) ?? DefaultNodes.getNodeFor(Coin.tezos); } + Future getKeystore() async { + return Keystore.fromMnemonic((await mnemonicString).toString()); + } + @override String get walletId => _walletId; late String _walletId; @@ -102,10 +111,36 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Balance? _balance; @override - Future confirmSend({required Map txData}) { - // TODO: implement confirmSend, - // NOTE FROM DETHERMINAL: I couldnt write this function because I dont have any tezos to test with - throw UnimplementedError(); + Future> prepareSend({required String address, required Amount amount, Map? args}) async { + try { + if (amount.decimals != coin.decimals) { + throw Exception("Amount decimals do not match coin decimals!"); + } + var fee = int.parse((await estimateFeeFor(amount, (args!["feeRate"] as FeeRateType).index)).raw.toString()); + Map txData = { + "fee": fee, + "address": address, + "recipientAmt": amount, + }; + return Future.value(txData); + } catch (e) { + return Future.error(e); + } + } + + @override + Future confirmSend({required Map txData}) async { + try { + final node = getCurrentNode().host + getCurrentNode().port.toString(); + final int amountInMicroTez = ((int.parse((txData["recipientAmt"] as Amount).raw.toString()) * 1000000)).round(); + final int feeInMicroTez = int.parse(txData["fee"].toString()); + final String destinationAddress = txData["address"] as String; + final String sourceAddress = await currentReceivingAddress; + return Future.value(""); // TODO: return tx hash + } catch (e) { + Logging.instance.log(e.toString(), level: LogLevel.Error); + return Future.error(e); + } } @override @@ -114,13 +149,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { if (mneString == null) { throw Exception("No mnemonic found!"); } - return Future.value(Keystore.fromMnemonic(mneString).address); + return Future.value((Keystore.fromMnemonic(mneString)).address); } @override Future estimateFeeFor(Amount amount, int feeRate) { - // TODO: implement estimateFeeFor - throw UnimplementedError(); + return Future.value( + Amount(rawValue: BigInt.parse(100000.toString()), fractionDigits: coin.decimals), + ); } @override @@ -130,13 +166,22 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - // TODO: implement fees - Future get fees => throw UnimplementedError(); + Future get fees async { + // TODO: Change this to get fees from node and fix numberOfBlocks + return FeeObject( + numberOfBlocksFast: 1, + numberOfBlocksAverage: 1, + numberOfBlocksSlow: 1, + fast: 1000000, + medium: 100000, + slow: 10000, + ); + } @override Future fullRescan(int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) { - // TODO: implement fullRescan - throw UnimplementedError(); + refresh(); + return Future.value(); } @override @@ -215,13 +260,6 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future get mnemonicString => _secureStore.read(key: '${_walletId}_mnemonic'); - @override - Future> prepareSend({required String address, required Amount amount, Map? args}) { - // TODO: implement prepareSend - // NOTE FROM DETHERMINAL: I couldnt write this function because I dont have any tezos to test with - throw UnimplementedError(); - } - @override Future recoverFromMnemonic({required String mnemonic, String? mnemonicPassphrase, required int maxUnusedAddressGap, required int maxNumberOfIndexesToCheck, required int height}) async { if ((await mnemonicString) != null || @@ -267,9 +305,66 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { await updateCachedBalance(_balance!); } + Future updateTransactions() async { + var api = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance_history"; // TODO: Can we use current node instead of this? + var returnedTxs = await get(Uri.parse(api)).then((value) => value.body); + Logging.instance.log( + "Transactions for ${await currentReceivingAddress}: $returnedTxs", + level: LogLevel.Info); + List> txs = []; + Object? jsonTxs = jsonDecode(returnedTxs); + if (jsonTxs == null) { + await db.addNewTransactionData(txs, walletId); + } else { + for (var tx in jsonTxs as List) { + var theTx = Transaction( + walletId: walletId, + txid: "", + timestamp: DateTime.parse(tx["timestamp"].toString()).toUtc().millisecondsSinceEpoch ~/ 1000, + type: TransactionType.unknown, + subType: TransactionSubType.none, + amount: int.parse(tx["balance"].toString()), + amountString: Amount( + rawValue: BigInt.parse(tx["balance"].toString()), + fractionDigits: 6 + ).toJsonString(), + fee: 0, + height: int.parse(tx["level"].toString()), + isCancelled: false, + isLelantus: false, + slateId: "", + otherData: "", + inputs: [], + outputs: [], + nonce: 0 + ); + var theAddress = Address( + walletId: walletId, + value: await currentReceivingAddress, + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + txs.add(Tuple2(theTx, theAddress)); + } + await db.addNewTransactionData(txs, walletId); + } + } + + Future updateChainHeight() async { + var api = "https://api.tzkt.io/v1/blocks/count"; // TODO: Can we use current node instead of this? + var returnedHeight = await get(Uri.parse(api)).then((value) => value.body); + final int intHeight = int.parse(returnedHeight.toString()); + await updateCachedChainHeight(intHeight); + } + @override Future refresh() { + updateChainHeight(); updateBalance(); + updateTransactions(); return Future.value(); } @@ -277,16 +372,17 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { int get storedChainHeight => getCachedChainHeight(); @override - Future testNetworkConnection() { - // TODO: implement testNetworkConnection - throw UnimplementedError(); + Future testNetworkConnection() async{ + try { + await get(Uri.parse("https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance")); + return true; + } catch (e) { + return false; + } } @override - // TODO: implement transactions - Future> get transactions async { - // TODO: Maybe we can use this -> https://api.tzkt.io/#operation/Accounts_GetBalanceHistory - } + Future> get transactions => db.getTransactions(walletId).findAll(); @override Future updateNode(bool shouldRefresh) async { diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index f23c1827a..1a285cc41 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -167,7 +167,6 @@ abstract class Constants { break; case Coin.banano: values.addAll([24, 12]); - break; case Coin.tezos: values.addAll([24, 12]); diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index 05e192f77..ac2edb482 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -183,7 +183,7 @@ abstract class DefaultNodes { ); static NodeModel get tezos => NodeModel( // TODO: Change this to original one - host: "https://mainnet.api.tez.ie", + host: "mainnet.api.tez.ie", port: 443, name: defaultName, id: _nodeId(Coin.tezos), From 45af21dc270a2814a4ca953d76dac1adcbdaed53 Mon Sep 17 00:00:00 2001 From: likho Date: Wed, 19 Jul 2023 16:37:54 +0200 Subject: [PATCH 031/237] Fix merge conflicts with staging --- .../manage_nodes_views/add_edit_node_view.dart | 1 + .../manage_nodes_views/node_details_view.dart | 1 + lib/services/coins/tezos/tezos_wallet.dart | 3 ++- lib/utilities/amount/amount_unit.dart | 2 ++ lib/widgets/node_card.dart | 1 + lib/widgets/node_options_sheet.dart | 1 + 6 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index c2543088d..5702c9740 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -196,6 +196,7 @@ class _AddEditNodeViewState extends ConsumerState { case Coin.nano: case Coin.banano: + case Coin.tezos: //TODO: check network/node } diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index fa69871cb..3e10b9240 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -172,6 +172,7 @@ class _NodeDetailsViewState extends ConsumerState { case Coin.nano: case Coin.banano: + case Coin.tezos: //TODO: check network/node } diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 9048c1d04..e5576741c 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -336,7 +336,8 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { otherData: "", inputs: [], outputs: [], - nonce: 0 + nonce: 0, + numberOfMessages: null, ); var theAddress = Address( walletId: walletId, diff --git a/lib/utilities/amount/amount_unit.dart b/lib/utilities/amount/amount_unit.dart index 0c0600d7a..fd2366dd4 100644 --- a/lib/utilities/amount/amount_unit.dart +++ b/lib/utilities/amount/amount_unit.dart @@ -50,6 +50,7 @@ enum AmountUnit { case Coin.dogecoin: case Coin.eCash: case Coin.epicCash: + case Coin.tezos: return AmountUnit.values.sublist(0, 4); case Coin.monero: @@ -62,6 +63,7 @@ enum AmountUnit { case Coin.nano: case Coin.banano: return AmountUnit.values; + } } } diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart index 9214e3e0a..3f4384ffc 100644 --- a/lib/widgets/node_card.dart +++ b/lib/widgets/node_card.dart @@ -194,6 +194,7 @@ class _NodeCardState extends ConsumerState { case Coin.nano: case Coin.banano: + case Coin.tezos: //TODO: check network/node } diff --git a/lib/widgets/node_options_sheet.dart b/lib/widgets/node_options_sheet.dart index 16e87581c..faebd95e3 100644 --- a/lib/widgets/node_options_sheet.dart +++ b/lib/widgets/node_options_sheet.dart @@ -177,6 +177,7 @@ class NodeOptionsSheet extends ConsumerWidget { case Coin.nano: case Coin.banano: + case Coin.tezos: //TODO: check network/node } From fbd51fcf6f8b9a9eaa4a030e9d64739a88a60cf6 Mon Sep 17 00:00:00 2001 From: Josh Babb Date: Wed, 19 Jul 2023 14:11:12 -0500 Subject: [PATCH 032/237] update linux section of docs remove emulator references --- docs/building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/building.md b/docs/building.md index b56a87899..e7128df2e 100644 --- a/docs/building.md +++ b/docs/building.md @@ -123,7 +123,7 @@ flutter run android Note on Emulators: Only x86_64 emulators are supported, x86 emulators will not work #### Linux -Plug in your android device or use the emulator available via Android Studio and then run the following commands: +Run the following commands or launch via Android Studio: ``` flutter pub get flutter run linux From c8d0ecf28dc10ee2f63dcc47c84e205acf0daf5b Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Thu, 27 Jul 2023 11:11:11 -0600 Subject: [PATCH 033/237] remove changes to ThemeAssets v1 --- lib/models/isar/stack_theme.dart | 9 --------- lib/themes/coin_image_provider.dart | 4 ---- 2 files changed, 13 deletions(-) diff --git a/lib/models/isar/stack_theme.dart b/lib/models/isar/stack_theme.dart index ea449a497..32878366a 100644 --- a/lib/models/isar/stack_theme.dart +++ b/lib/models/isar/stack_theme.dart @@ -1921,7 +1921,6 @@ class ThemeAssets implements IThemeAssets { late final String wownero; late final String namecoin; late final String particl; - late final String tezos; late final String bitcoinImage; late final String bitcoincashImage; late final String dogecoinImage; @@ -1933,7 +1932,6 @@ class ThemeAssets implements IThemeAssets { late final String wowneroImage; late final String namecoinImage; late final String particlImage; - late final String tezosImage; late final String bitcoinImageSecondary; late final String bitcoincashImageSecondary; late final String dogecoinImageSecondary; @@ -1945,7 +1943,6 @@ class ThemeAssets implements IThemeAssets { late final String wowneroImageSecondary; late final String namecoinImageSecondary; late final String particlImageSecondary; - late final String tezosImageSecondary; @override late final String? loadingGif; @override @@ -1991,8 +1988,6 @@ class ThemeAssets implements IThemeAssets { ..wownero = "$themeId/assets/${json["wownero"] as String}" ..namecoin = "$themeId/assets/${json["namecoin"] as String}" ..particl = "$themeId/assets/${json["particl"] as String}" - ..tezos = - "$themeId/assets/${json["bitcoin"] as String}" ..bitcoinImage = "$themeId/assets/${json["bitcoin_image"] as String}" ..bitcoincashImage = "$themeId/assets/${json["bitcoincash_image"] as String}" @@ -2005,8 +2000,6 @@ class ThemeAssets implements IThemeAssets { ..wowneroImage = "$themeId/assets/${json["wownero_image"] as String}" ..namecoinImage = "$themeId/assets/${json["namecoin_image"] as String}" ..particlImage = "$themeId/assets/${json["particl_image"] as String}" - ..tezosImage = - "$themeId/assets/${json["bitcoin_image"] as String}" ..bitcoinImageSecondary = "$themeId/assets/${json["bitcoin_image_secondary"] as String}" ..bitcoincashImageSecondary = @@ -2029,8 +2022,6 @@ class ThemeAssets implements IThemeAssets { "$themeId/assets/${json["namecoin_image_secondary"] as String}" ..particlImageSecondary = "$themeId/assets/${json["particl_image_secondary"] as String}" - ..tezosImageSecondary = - "$themeId/assets/${json["bitcoin_image_secondary"] as String}" // TODO: change to tezos ..loadingGif = json["loading_gif"] is String ? "$themeId/assets/${json["loading_gif"] as String}" : null diff --git a/lib/themes/coin_image_provider.dart b/lib/themes/coin_image_provider.dart index d72e7b778..6ca839fb9 100644 --- a/lib/themes/coin_image_provider.dart +++ b/lib/themes/coin_image_provider.dart @@ -41,8 +41,6 @@ final coinImageProvider = Provider.family((ref, coin) { return assets.namecoinImage; case Coin.particl: return assets.particlImage; - case Coin.tezos: - return assets.tezosImage; case Coin.bitcoinTestNet: return assets.bitcoinImage; case Coin.bitcoincashTestnet: @@ -91,8 +89,6 @@ final coinImageSecondaryProvider = Provider.family((ref, coin) { return assets.namecoinImageSecondary; case Coin.particl: return assets.particlImageSecondary; - case Coin.tezos: - return assets.tezosImageSecondary; case Coin.bitcoinTestNet: return assets.bitcoinImageSecondary; case Coin.bitcoincashTestnet: From 2ee65b584ea21d59f44d01884afb2cf9fe296068 Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Thu, 27 Jul 2023 23:15:49 +0300 Subject: [PATCH 034/237] fix: fetch from nodes instead of tzkt --- lib/services/coins/tezos/tezos_wallet.dart | 13 +++++++------ lib/utilities/default_nodes.dart | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index e5576741c..38631a071 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -292,8 +292,8 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateBalance() async { - var api = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance"; // TODO: Can we use current node instead of this? - var theBalance = await get(Uri.parse(api)).then((value) => value.body); + var api = "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/context/contracts/${await currentReceivingAddress}/balance"; + var theBalance = (await get(Uri.parse(api)).then((value) => value.body)).substring(1, (await get(Uri.parse(api)).then((value) => value.body)).length - 2); Logging.instance.log("Balance for ${await currentReceivingAddress}: $theBalance", level: LogLevel.Info); var balanceInAmount = Amount(rawValue: BigInt.parse(theBalance.toString()), fractionDigits: 6); _balance = Balance( @@ -355,9 +355,10 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateChainHeight() async { - var api = "https://api.tzkt.io/v1/blocks/count"; // TODO: Can we use current node instead of this? - var returnedHeight = await get(Uri.parse(api)).then((value) => value.body); - final int intHeight = int.parse(returnedHeight.toString()); + var api = "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell"; + var jsonParsedResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + final int intHeight = int.parse(jsonParsedResponse["level"].toString()); + Logging.instance.log("Chain height: $intHeight", level: LogLevel.Info); await updateCachedChainHeight(intHeight); } @@ -375,7 +376,7 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future testNetworkConnection() async{ try { - await get(Uri.parse("https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance")); + await get(Uri.parse("${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell")); return true; } catch (e) { return false; diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index ac2edb482..22f274d62 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -182,8 +182,8 @@ abstract class DefaultNodes { isDown: false ); - static NodeModel get tezos => NodeModel( // TODO: Change this to original one - host: "mainnet.api.tez.ie", + static NodeModel get tezos => NodeModel( // TODO: Change this to stack wallet one + host: "https://mainnet.api.tez.ie", port: 443, name: defaultName, id: _nodeId(Coin.tezos), From 3077465e81e017c524b61b1ea9afcda3c1bb01fc Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Fri, 28 Jul 2023 13:39:07 +0300 Subject: [PATCH 035/237] xtz: update api and add price --- lib/services/coins/tezos/tezos_wallet.dart | 87 +++++++++++----------- lib/services/price.dart | 2 +- 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 38631a071..8faa15427 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -306,52 +306,53 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateTransactions() async { - var api = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/balance_history"; // TODO: Can we use current node instead of this? - var returnedTxs = await get(Uri.parse(api)).then((value) => value.body); - Logging.instance.log( - "Transactions for ${await currentReceivingAddress}: $returnedTxs", - level: LogLevel.Info); + // TODO: Use node RPC instead of tzstats API + var api = "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; + var jsonResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); List> txs = []; - Object? jsonTxs = jsonDecode(returnedTxs); - if (jsonTxs == null) { - await db.addNewTransactionData(txs, walletId); - } else { - for (var tx in jsonTxs as List) { - var theTx = Transaction( - walletId: walletId, - txid: "", - timestamp: DateTime.parse(tx["timestamp"].toString()).toUtc().millisecondsSinceEpoch ~/ 1000, - type: TransactionType.unknown, - subType: TransactionSubType.none, - amount: int.parse(tx["balance"].toString()), - amountString: Amount( - rawValue: BigInt.parse(tx["balance"].toString()), - fractionDigits: 6 - ).toJsonString(), - fee: 0, - height: int.parse(tx["level"].toString()), - isCancelled: false, - isLelantus: false, - slateId: "", - otherData: "", - inputs: [], - outputs: [], - nonce: 0, - numberOfMessages: null, - ); - var theAddress = Address( - walletId: walletId, - value: await currentReceivingAddress, - publicKey: [], // TODO: Add public key - derivationIndex: 0, - derivationPath: null, - type: AddressType.unknown, - subType: AddressSubType.unknown, - ); - txs.add(Tuple2(theTx, theAddress)); + for (var tx in jsonResponse as List) { + var txApi = "https://api.tzstats.com/explorer/op/${tx["hash"]}"; + var txJsonResponse = jsonDecode(await get(Uri.parse(txApi)).then((value) => value.body))[0]; + TransactionType txType; + if (txJsonResponse["sender"] == (await currentReceivingAddress)) { + txType = TransactionType.outgoing; + } else { + txType = TransactionType.incoming; } - await db.addNewTransactionData(txs, walletId); + var theTx = Transaction( + walletId: walletId, + txid: txJsonResponse["hash"].toString(), + timestamp: DateTime.parse(txJsonResponse["time"].toString()).toUtc().millisecondsSinceEpoch ~/ 1000, + type: txType, + subType: TransactionSubType.none, + amount: (float.parse(txJsonResponse["volume"].toString()) * 1000000).toInt(), + amountString: Amount( + rawValue: BigInt.parse((float.parse(txJsonResponse["volume"].toString()) * 1000000).toString()), + fractionDigits: 6 + ).toJsonString(), + fee: (float.parse(txJsonResponse["fee"].toString()) * 1000000).toInt(), + height: int.parse(txJsonResponse["height"].toString()), + isCancelled: false, + isLelantus: false, + slateId: "", + otherData: "", + inputs: [], + outputs: [], + nonce: 0, + numberOfMessages: null, + ); + var theAddress = Address( + walletId: walletId, + value: txJsonResponse["receiver"].toString(), + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + txs.add(Tuple2(theTx, theAddress)); } + await db.addNewTransactionData(txs, walletId); } Future updateChainHeight() async { diff --git a/lib/services/price.dart b/lib/services/price.dart index 24d929062..e9cbacc96 100644 --- a/lib/services/price.dart +++ b/lib/services/price.dart @@ -100,7 +100,7 @@ class PriceAPI { Uri.parse("https://api.coingecko.com/api/v3/coins/markets?vs_currency" "=${baseCurrency.toLowerCase()}" "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," - "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano" + "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,tezos" "&order=market_cap_desc&per_page=50&page=1&sparkline=false"); final coinGeckoResponse = await client.get( From 5c06d9dc596288a8166fca43e2aac25d25cbcd88 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Fri, 28 Jul 2023 10:32:50 -0600 Subject: [PATCH 036/237] format adjustments + remove tezos from themeAssetsv1 --- lib/services/coins/tezos/tezos_wallet.dart | 202 ++++++++++++--------- lib/themes/coin_icon_provider.dart | 2 - lib/utilities/default_nodes.dart | 10 +- 3 files changed, 126 insertions(+), 88 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 8faa15427..4f66df22e 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -1,33 +1,30 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:ffi'; import 'package:http/http.dart'; import 'package:isar/isar.dart'; +import 'package:stackwallet/db/isar/main_db.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'; import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; +import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/services/coins/coin_service.dart'; +import 'package:stackwallet/services/mixins/wallet_cache.dart'; +import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; +import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; -import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/default_nodes.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; - +import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; +import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:tezart/tezart.dart'; import 'package:tuple/tuple.dart'; -import '../../../db/isar/main_db.dart'; -import '../../../models/node_model.dart'; -import '../../../utilities/flutter_secure_storage_interface.dart'; -import '../../../utilities/logger.dart'; -import '../../../utilities/prefs.dart'; -import '../../mixins/wallet_cache.dart'; -import '../../mixins/wallet_db.dart'; -import '../../transaction_notification_tracker.dart'; - const int MINIMUM_CONFIRMATIONS = 1; class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @@ -51,7 +48,10 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { NodeModel? _xtzNode; NodeModel getCurrentNode() { - return _xtzNode ?? NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: Coin.tezos) ?? DefaultNodes.getNodeFor(Coin.tezos); + return _xtzNode ?? + NodeService(secureStorageInterface: _secureStore) + .getPrimaryNodeFor(coin: Coin.tezos) ?? + DefaultNodes.getNodeFor(Coin.tezos); } Future getKeystore() async { @@ -111,12 +111,18 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Balance? _balance; @override - Future> prepareSend({required String address, required Amount amount, Map? args}) async { + Future> prepareSend( + {required String address, + required Amount amount, + Map? args}) async { try { if (amount.decimals != coin.decimals) { throw Exception("Amount decimals do not match coin decimals!"); } - var fee = int.parse((await estimateFeeFor(amount, (args!["feeRate"] as FeeRateType).index)).raw.toString()); + var fee = int.parse((await estimateFeeFor( + amount, (args!["feeRate"] as FeeRateType).index)) + .raw + .toString()); Map txData = { "fee": fee, "address": address, @@ -132,7 +138,10 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future confirmSend({required Map txData}) async { try { final node = getCurrentNode().host + getCurrentNode().port.toString(); - final int amountInMicroTez = ((int.parse((txData["recipientAmt"] as Amount).raw.toString()) * 1000000)).round(); + final int amountInMicroTez = + ((int.parse((txData["recipientAmt"] as Amount).raw.toString()) * + 1000000)) + .round(); final int feeInMicroTez = int.parse(txData["fee"].toString()); final String destinationAddress = txData["address"] as String; final String sourceAddress = await currentReceivingAddress; @@ -155,7 +164,9 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future estimateFeeFor(Amount amount, int feeRate) { return Future.value( - Amount(rawValue: BigInt.parse(100000.toString()), fractionDigits: coin.decimals), + Amount( + rawValue: BigInt.parse(100000.toString()), + fractionDigits: coin.decimals), ); } @@ -169,17 +180,18 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future get fees async { // TODO: Change this to get fees from node and fix numberOfBlocks return FeeObject( - numberOfBlocksFast: 1, - numberOfBlocksAverage: 1, - numberOfBlocksSlow: 1, - fast: 1000000, - medium: 100000, - slow: 10000, + numberOfBlocksFast: 1, + numberOfBlocksAverage: 1, + numberOfBlocksSlow: 1, + fast: 1000000, + medium: 100000, + slow: 10000, ); } @override - Future fullRescan(int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) { + Future fullRescan( + int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) { refresh(); return Future.value(); } @@ -212,13 +224,13 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { ); final address = Address( - walletId: walletId, - value: newKeystore.address, - publicKey: [], // TODO: Add public key - derivationIndex: 0, - derivationPath: null, - type: AddressType.unknown, - subType: AddressSubType.unknown, + walletId: walletId, + value: newKeystore.address, + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, ); await db.putAddress(address); @@ -255,13 +267,20 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future get mnemonicPassphrase => _secureStore.read(key: '${_walletId}_mnemonicPassphrase'); + Future get mnemonicPassphrase => + _secureStore.read(key: '${_walletId}_mnemonicPassphrase'); @override - Future get mnemonicString => _secureStore.read(key: '${_walletId}_mnemonic'); + Future get mnemonicString => + _secureStore.read(key: '${_walletId}_mnemonic'); @override - Future recoverFromMnemonic({required String mnemonic, String? mnemonicPassphrase, required int maxUnusedAddressGap, required int maxNumberOfIndexesToCheck, required int height}) async { + Future recoverFromMnemonic( + {required String mnemonic, + String? mnemonicPassphrase, + required int maxUnusedAddressGap, + required int maxNumberOfIndexesToCheck, + required int height}) async { if ((await mnemonicString) != null || (await this.mnemonicPassphrase) != null) { throw Exception("Attempted to overwrite mnemonic on restore!"); @@ -274,13 +293,13 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { ); final address = Address( - walletId: walletId, - value: Keystore.fromMnemonic(mnemonic).address, - publicKey: [], // TODO: Add public key - derivationIndex: 0, - derivationPath: null, - type: AddressType.unknown, - subType: AddressSubType.unknown, + walletId: walletId, + value: Keystore.fromMnemonic(mnemonic).address, + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, ); await db.putAddress(address); @@ -292,10 +311,16 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateBalance() async { - var api = "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/context/contracts/${await currentReceivingAddress}/balance"; - var theBalance = (await get(Uri.parse(api)).then((value) => value.body)).substring(1, (await get(Uri.parse(api)).then((value) => value.body)).length - 2); - Logging.instance.log("Balance for ${await currentReceivingAddress}: $theBalance", level: LogLevel.Info); - var balanceInAmount = Amount(rawValue: BigInt.parse(theBalance.toString()), fractionDigits: 6); + var api = + "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/context/contracts/${await currentReceivingAddress}/balance"; + var theBalance = (await get(Uri.parse(api)).then((value) => value.body)) + .substring(1, + (await get(Uri.parse(api)).then((value) => value.body)).length - 2); + Logging.instance.log( + "Balance for ${await currentReceivingAddress}: $theBalance", + level: LogLevel.Info); + var balanceInAmount = Amount( + rawValue: BigInt.parse(theBalance.toString()), fractionDigits: 6); _balance = Balance( total: balanceInAmount, spendable: balanceInAmount, @@ -307,12 +332,15 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateTransactions() async { // TODO: Use node RPC instead of tzstats API - var api = "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; - var jsonResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + var api = + "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; + var jsonResponse = + jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); List> txs = []; for (var tx in jsonResponse as List) { var txApi = "https://api.tzstats.com/explorer/op/${tx["hash"]}"; - var txJsonResponse = jsonDecode(await get(Uri.parse(txApi)).then((value) => value.body))[0]; + var txJsonResponse = jsonDecode( + await get(Uri.parse(txApi)).then((value) => value.body))[0]; TransactionType txType; if (txJsonResponse["sender"] == (await currentReceivingAddress)) { txType = TransactionType.outgoing; @@ -320,35 +348,41 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { txType = TransactionType.incoming; } var theTx = Transaction( - walletId: walletId, - txid: txJsonResponse["hash"].toString(), - timestamp: DateTime.parse(txJsonResponse["time"].toString()).toUtc().millisecondsSinceEpoch ~/ 1000, - type: txType, - subType: TransactionSubType.none, - amount: (float.parse(txJsonResponse["volume"].toString()) * 1000000).toInt(), - amountString: Amount( - rawValue: BigInt.parse((float.parse(txJsonResponse["volume"].toString()) * 1000000).toString()), - fractionDigits: 6 - ).toJsonString(), - fee: (float.parse(txJsonResponse["fee"].toString()) * 1000000).toInt(), - height: int.parse(txJsonResponse["height"].toString()), - isCancelled: false, - isLelantus: false, - slateId: "", - otherData: "", - inputs: [], - outputs: [], - nonce: 0, - numberOfMessages: null, + walletId: walletId, + txid: txJsonResponse["hash"].toString(), + timestamp: DateTime.parse(txJsonResponse["time"].toString()) + .toUtc() + .millisecondsSinceEpoch ~/ + 1000, + type: txType, + subType: TransactionSubType.none, + amount: (float.parse(txJsonResponse["volume"].toString()) * 1000000) + .toInt(), + amountString: Amount( + rawValue: BigInt.parse( + (float.parse(txJsonResponse["volume"].toString()) * 1000000) + .toString()), + fractionDigits: 6) + .toJsonString(), + fee: (float.parse(txJsonResponse["fee"].toString()) * 1000000).toInt(), + height: int.parse(txJsonResponse["height"].toString()), + isCancelled: false, + isLelantus: false, + slateId: "", + otherData: "", + inputs: [], + outputs: [], + nonce: 0, + numberOfMessages: null, ); var theAddress = Address( - walletId: walletId, - value: txJsonResponse["receiver"].toString(), - publicKey: [], // TODO: Add public key - derivationIndex: 0, - derivationPath: null, - type: AddressType.unknown, - subType: AddressSubType.unknown, + walletId: walletId, + value: txJsonResponse["receiver"].toString(), + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, ); txs.add(Tuple2(theTx, theAddress)); } @@ -356,8 +390,10 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateChainHeight() async { - var api = "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell"; - var jsonParsedResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + var api = + "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell"; + var jsonParsedResponse = + jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); final int intHeight = int.parse(jsonParsedResponse["level"].toString()); Logging.instance.log("Chain height: $intHeight", level: LogLevel.Info); await updateCachedChainHeight(intHeight); @@ -375,9 +411,10 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { int get storedChainHeight => getCachedChainHeight(); @override - Future testNetworkConnection() async{ + Future testNetworkConnection() async { try { - await get(Uri.parse("${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell")); + await get(Uri.parse( + "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell")); return true; } catch (e) { return false; @@ -385,11 +422,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future> get transactions => db.getTransactions(walletId).findAll(); + Future> get transactions => + db.getTransactions(walletId).findAll(); @override Future updateNode(bool shouldRefresh) async { - _xtzNode = NodeService(secureStorageInterface: _secureStore).getPrimaryNodeFor(coin: coin) ?? DefaultNodes.getNodeFor(coin); + _xtzNode = NodeService(secureStorageInterface: _secureStore) + .getPrimaryNodeFor(coin: coin) ?? + DefaultNodes.getNodeFor(coin); if (shouldRefresh) { await refresh(); diff --git a/lib/themes/coin_icon_provider.dart b/lib/themes/coin_icon_provider.dart index acbfaed3f..9bd3990bb 100644 --- a/lib/themes/coin_icon_provider.dart +++ b/lib/themes/coin_icon_provider.dart @@ -43,8 +43,6 @@ final coinIconProvider = Provider.family((ref, coin) { return assets.namecoin; case Coin.particl: return assets.particl; - case Coin.tezos: - return assets.tezos; case Coin.ethereum: return assets.ethereum; default: diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index 22f274d62..87b7849f4 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -179,10 +179,10 @@ abstract class DefaultNodes { enabled: true, coinName: Coin.particl.name, isFailover: true, - isDown: false - ); + isDown: false); - static NodeModel get tezos => NodeModel( // TODO: Change this to stack wallet one + static NodeModel get tezos => NodeModel( + // TODO: Change this to stack wallet one host: "https://mainnet.api.tez.ie", port: 443, name: defaultName, @@ -191,8 +191,7 @@ abstract class DefaultNodes { enabled: true, coinName: Coin.tezos.name, isFailover: true, - isDown: false - ); + isDown: false); static NodeModel get nano => NodeModel( host: "https://rainstorm.city/api", @@ -318,6 +317,7 @@ abstract class DefaultNodes { case Coin.banano: return banano; + case Coin.tezos: return tezos; From 724f6193d7f95e4f19eea89166af0f414d9a21b8 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Fri, 28 Jul 2023 10:50:05 -0600 Subject: [PATCH 037/237] merge conflicts --- .../manage_nodes_views/add_edit_node_view.dart | 2 +- .../manage_nodes_views/node_details_view.dart | 2 +- lib/services/price.dart | 12 ++++++------ lib/utilities/constants.dart | 3 ++- lib/widgets/node_options_sheet.dart | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index eb100b8cd..781a566ef 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -199,7 +199,7 @@ class _AddEditNodeViewState extends ConsumerState { case Coin.stellar: case Coin.stellarTestnet: throw UnimplementedError(); - //TODO: check network/node + //TODO: check network/node case Coin.tezos: //TODO: check network/node } diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index ee9cf02e5..31a9c6717 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -176,7 +176,7 @@ class _NodeDetailsViewState extends ConsumerState { case Coin.stellar: case Coin.stellarTestnet: throw UnimplementedError(); - //TODO: check network/node + //TODO: check network/node } if (testPassed) { diff --git a/lib/services/price.dart b/lib/services/price.dart index 38f560244..c6f28673f 100644 --- a/lib/services/price.dart +++ b/lib/services/price.dart @@ -96,12 +96,12 @@ class PriceAPI { } Map> result = {}; try { - final uri = - Uri.parse("https://api.coingecko.com/api/v3/coins/markets?vs_currency" - "=${baseCurrency.toLowerCase()}" - "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," - "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar,tezos" - "&order=market_cap_desc&per_page=50&page=1&sparkline=false"); + final uri = Uri.parse( + "https://api.coingecko.com/api/v3/coins/markets?vs_currency" + "=${baseCurrency.toLowerCase()}" + "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," + "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar,tezos" + "&order=market_cap_desc&per_page=50&page=1&sparkline=false"); final coinGeckoResponse = await client.get( uri, diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index b1e2e6b31..1253e08f1 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -42,7 +42,8 @@ abstract class Constants { BigInt.parse("1000000000000000000000000000000"); // 1*10^30 static final BigInt _satsPerCoinBanano = BigInt.parse("100000000000000000000000000000"); // 1*10^29 - static final BigInt _satsPerCoinStellar = BigInt.from(10000000); // https://developers.stellar.org/docs/fundamentals-and-concepts/stellar-data-structures/assets#amount-precision + static final BigInt _satsPerCoinStellar = BigInt.from( + 10000000); // https://developers.stellar.org/docs/fundamentals-and-concepts/stellar-data-structures/assets#amount-precision static final BigInt _satsPerCoin = BigInt.from(100000000); static final BigInt _satsPerCoinTezos = BigInt.from(1000000); static const int _decimalPlaces = 8; diff --git a/lib/widgets/node_options_sheet.dart b/lib/widgets/node_options_sheet.dart index 9f7802536..953ac78a1 100644 --- a/lib/widgets/node_options_sheet.dart +++ b/lib/widgets/node_options_sheet.dart @@ -181,7 +181,7 @@ class NodeOptionsSheet extends ConsumerWidget { case Coin.stellar: case Coin.stellarTestnet: throw UnimplementedError(); - //TODO: check network/node + //TODO: check network/node } if (testPassed) { From 68f3bc8731e215d906ce2ad57dfca5814f86275e Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:15:34 +0300 Subject: [PATCH 038/237] fix dependency conflict --- pubspec.lock | 72 ++++++++++++++++++++++++++++++++++++++++++++++------ pubspec.yaml | 2 ++ 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index cfdf7a710..111b58d75 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.30" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a" + url: "https://pub.dev" + source: hosted + version: "2.0.1" archive: dependency: "direct main" description: @@ -298,10 +306,10 @@ packages: dependency: "direct main" description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.2" cryptography: dependency: transitive description: @@ -451,13 +459,13 @@ packages: source: hosted version: "0.6.0" dio: - dependency: transitive + dependency: "direct overridden" description: name: dio - sha256: "3866d67f93523161b643187af65f5ac08bc991a5bcdaf41a2d587fe4ccb49993" + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" url: "https://pub.dev" source: hosted - version: "5.3.0" + version: "4.0.6" dropdown_button2: dependency: "direct main" description: @@ -942,6 +950,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + json_serializable: + dependency: transitive + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.dev" + source: hosted + version: "6.7.1" keyboard_dismisser: dependency: "direct main" description: @@ -1005,6 +1021,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" + memoize: + dependency: transitive + description: + name: memoize + sha256: "51481d328c86cbdc59711369179bac88551ca0556569249be5317e66fc796cac" + url: "https://pub.dev" + source: hosted + version: "3.0.0" meta: dependency: transitive description: @@ -1230,13 +1254,13 @@ packages: source: hosted version: "5.4.0" pinenacl: - dependency: transitive + dependency: "direct overridden" description: name: pinenacl - sha256: "3a5503637587d635647c93ea9a8fecf48a420cc7deebe6f1fc85c2a5637ab327" + sha256: e5fb0bce1717b7f136f35ee98b5c02b3e6383211f8a77ca882fa7812232a07b9 url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.3.4" platform: dependency: transitive description: @@ -1269,6 +1293,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + pretty_dio_logger: + dependency: transitive + description: + name: pretty_dio_logger + sha256: "00b80053063935cf9a6190da344c5373b9d0e92da4c944c878ff2fbef0ef6dc2" + url: "https://pub.dev" + source: hosted + version: "1.3.1" process: dependency: transitive description: @@ -1317,6 +1349,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + quiver: + dependency: transitive + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" rational: dependency: transitive description: @@ -1325,6 +1365,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + retry: + dependency: transitive + description: + name: retry + sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc" + url: "https://pub.dev" + source: hosted + version: "3.1.2" riverpod: dependency: transitive description: @@ -1547,6 +1595,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" + tezart: + dependency: "direct main" + description: + name: tezart + sha256: "35d526f2e6ca250c64461ebfb4fa9f64b6599fab8c4242c8e89ae27d4ac2e15a" + url: "https://pub.dev" + source: hosted + version: "2.0.5" time: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 506d6d431..4e4a6755e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -202,6 +202,8 @@ dependency_overrides: crypto: 3.0.2 analyzer: ^5.2.0 + pinenacl: ^0.3.3 + dio : ^4.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From f4688bd041974d25219734df285ba2bd679d6ed7 Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:16:04 +0300 Subject: [PATCH 039/237] xtz: filter other operations --- lib/services/coins/tezos/tezos_wallet.dart | 101 +++++++++++---------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 4f66df22e..9fa8e499f 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -332,60 +332,61 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateTransactions() async { // TODO: Use node RPC instead of tzstats API - var api = - "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; - var jsonResponse = - jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + var api = "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; + var jsonResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); List> txs = []; for (var tx in jsonResponse as List) { - var txApi = "https://api.tzstats.com/explorer/op/${tx["hash"]}"; - var txJsonResponse = jsonDecode( - await get(Uri.parse(txApi)).then((value) => value.body))[0]; - TransactionType txType; - if (txJsonResponse["sender"] == (await currentReceivingAddress)) { - txType = TransactionType.outgoing; - } else { - txType = TransactionType.incoming; + if (tx[1] == "transaction") { + var txApi = "https://api.tzstats.com/explorer/op/${tx[2]}"; + var txJsonResponse = jsonDecode(await get(Uri.parse(txApi)).then((value) => value.body)); + // Check if list is larger than 1 (if it is, it's a batch transaction) + if (!((txJsonResponse as List).length > 1)) { + for (var (opJson as Map) in txJsonResponse) { + if (opJson.containsKey("volume")) { // This is to check if transaction is a token transfer + TransactionType txType; + if (opJson["sender"] == (await currentReceivingAddress)) { + txType = TransactionType.outgoing; + } else { + txType = TransactionType.incoming; + } + var theTx = Transaction( + walletId: walletId, + txid: opJson["hash"].toString(), + timestamp: DateTime.parse(opJson["time"].toString()).toUtc().millisecondsSinceEpoch ~/ 1000, + type: txType, + subType: TransactionSubType.none, + amount: (float.parse(opJson["volume"].toString()) * 1000000).toInt(), + amountString: Amount( + rawValue: BigInt.parse((float.parse(opJson["volume"].toString()) * 1000000).toInt().toString()), + fractionDigits: 6 + ).toJsonString(), + fee: (float.parse(opJson["fee"].toString()) * 1000000).toInt(), + height: int.parse(opJson["height"].toString()), + isCancelled: false, + isLelantus: false, + slateId: "", + otherData: "", + inputs: [], + outputs: [], + nonce: 0, + numberOfMessages: null, + ); + var theAddress = Address( + walletId: walletId, + value: opJson["receiver"].toString(), + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + txs.add(Tuple2(theTx, theAddress)); + } + } + } } - var theTx = Transaction( - walletId: walletId, - txid: txJsonResponse["hash"].toString(), - timestamp: DateTime.parse(txJsonResponse["time"].toString()) - .toUtc() - .millisecondsSinceEpoch ~/ - 1000, - type: txType, - subType: TransactionSubType.none, - amount: (float.parse(txJsonResponse["volume"].toString()) * 1000000) - .toInt(), - amountString: Amount( - rawValue: BigInt.parse( - (float.parse(txJsonResponse["volume"].toString()) * 1000000) - .toString()), - fractionDigits: 6) - .toJsonString(), - fee: (float.parse(txJsonResponse["fee"].toString()) * 1000000).toInt(), - height: int.parse(txJsonResponse["height"].toString()), - isCancelled: false, - isLelantus: false, - slateId: "", - otherData: "", - inputs: [], - outputs: [], - nonce: 0, - numberOfMessages: null, - ); - var theAddress = Address( - walletId: walletId, - value: txJsonResponse["receiver"].toString(), - publicKey: [], // TODO: Add public key - derivationIndex: 0, - derivationPath: null, - type: AddressType.unknown, - subType: AddressSubType.unknown, - ); - txs.add(Tuple2(theTx, theAddress)); } + Logging.instance.log("Transactions: $txs", level: LogLevel.Info); await db.addNewTransactionData(txs, walletId); } From a1ef84fbe64f5e815bdfd24e4854a189720f1589 Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Fri, 28 Jul 2023 23:00:14 +0300 Subject: [PATCH 040/237] fix stellarTestNet and dependency problems --- .../add_edit_node_view.dart | 5 +++- .../manage_nodes_views/node_details_view.dart | 2 +- lib/services/coins/coin_service.dart | 9 ++++++++ lib/themes/color_theme.dart | 2 +- lib/themes/stack_colors.dart | 2 +- lib/utilities/address_utils.dart | 2 +- lib/utilities/amount/amount_unit.dart | 2 +- lib/utilities/block_explorers.dart | 2 +- lib/utilities/constants.dart | 10 ++++---- lib/utilities/default_nodes.dart | 6 ++--- lib/utilities/enums/coin_enum.dart | 23 +++++++++++-------- .../enums/derive_path_type_enum.dart | 2 +- lib/widgets/node_card.dart | 2 +- lib/widgets/node_options_sheet.dart | 2 +- pubspec.lock | 10 ++++---- pubspec.yaml | 3 +-- 16 files changed, 49 insertions(+), 35 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 781a566ef..4bd42f70b 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -197,7 +197,7 @@ class _AddEditNodeViewState extends ConsumerState { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: throw UnimplementedError(); //TODO: check network/node case Coin.tezos: @@ -732,11 +732,14 @@ class _NodeFormState extends ConsumerState { case Coin.namecoin: case Coin.bitcoincash: case Coin.particl: + case Coin.stellar: + case Coin.tezos: case Coin.bitcoinTestNet: case Coin.litecoinTestNet: case Coin.bitcoincashTestnet: case Coin.firoTestNet: case Coin.dogecoinTestNet: + case Coin.stellarTestNet: case Coin.epicCash: case Coin.nano: case Coin.banano: diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index 31a9c6717..d22af6e25 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -174,7 +174,7 @@ class _NodeDetailsViewState extends ConsumerState { case Coin.banano: case Coin.tezos: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: throw UnimplementedError(); //TODO: check network/node } diff --git a/lib/services/coins/coin_service.dart b/lib/services/coins/coin_service.dart index 394ff5fc1..9ee397e0d 100644 --- a/lib/services/coins/coin_service.dart +++ b/lib/services/coins/coin_service.dart @@ -229,6 +229,15 @@ abstract class CoinServiceAPI { tracker: tracker, ); + case Coin.stellarTestNet: + return StellarWallet( + walletId: walletId, + walletName: walletName, + coin: coin, + secureStore: secureStorageInterface, + tracker: tracker, + ); + case Coin.tezos: return TezosWallet( walletId: walletId, diff --git a/lib/themes/color_theme.dart b/lib/themes/color_theme.dart index abec28d4e..0e6816dd8 100644 --- a/lib/themes/color_theme.dart +++ b/lib/themes/color_theme.dart @@ -65,7 +65,7 @@ class CoinThemeColorDefault { case Coin.particl: return particl; case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return stellar; case Coin.nano: return nano; diff --git a/lib/themes/stack_colors.dart b/lib/themes/stack_colors.dart index cbec0077a..fde5219cf 100644 --- a/lib/themes/stack_colors.dart +++ b/lib/themes/stack_colors.dart @@ -1708,7 +1708,7 @@ class StackColors extends ThemeExtension { case Coin.particl: return _coin.particl; case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return _coin.stellar; case Coin.nano: return _coin.nano; diff --git a/lib/utilities/address_utils.dart b/lib/utilities/address_utils.dart index 3fa895282..b4974d8c6 100644 --- a/lib/utilities/address_utils.dart +++ b/lib/utilities/address_utils.dart @@ -143,7 +143,7 @@ class AddressUtils { return Address.validateAddress(address, firoTestNetwork); case Coin.dogecoinTestNet: return Address.validateAddress(address, dogecointestnet); - case Coin.stellarTestnet: + case Coin.stellarTestNet: return RegExp(r"^[G][A-Z0-9]{55}$").hasMatch(address); } } diff --git a/lib/utilities/amount/amount_unit.dart b/lib/utilities/amount/amount_unit.dart index 6a646fd11..00055a0fe 100644 --- a/lib/utilities/amount/amount_unit.dart +++ b/lib/utilities/amount/amount_unit.dart @@ -51,7 +51,7 @@ enum AmountUnit { case Coin.eCash: case Coin.epicCash: case Coin.stellar: // TODO: check if this is correct - case Coin.stellarTestnet: + case Coin.stellarTestNet: case Coin.tezos: return AmountUnit.values.sublist(0, 4); diff --git a/lib/utilities/block_explorers.dart b/lib/utilities/block_explorers.dart index bb4ac06fb..ddc055fb1 100644 --- a/lib/utilities/block_explorers.dart +++ b/lib/utilities/block_explorers.dart @@ -60,7 +60,7 @@ Uri getDefaultBlockExplorerUrlFor({ return Uri.parse("https://www.nanolooker.com/block/$txid"); case Coin.banano: return Uri.parse("https://www.bananolooker.com/block/$txid"); - case Coin.stellarTestnet: + case Coin.stellarTestNet: return Uri.parse("https://testnet.stellarchain.io/transactions/$txid"); case Coin.tezos: return Uri.parse("https://tzstats.com/$txid"); diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 1253e08f1..1bd3a5a50 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -102,7 +102,7 @@ abstract class Constants { return _satsPerCoinECash; case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return _satsPerCoinStellar; case Coin.tezos: @@ -146,7 +146,7 @@ abstract class Constants { return _decimalPlacesECash; case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return _decimalPlacesStellar; case Coin.tezos: @@ -174,7 +174,7 @@ abstract class Constants { case Coin.particl: case Coin.nano: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: values.addAll([24, 12]); break; case Coin.banano: @@ -238,7 +238,7 @@ abstract class Constants { return 1; case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return 5; case Coin.tezos: @@ -271,7 +271,7 @@ abstract class Constants { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: case Coin.tezos: return 24; diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index 7a4daf2f2..7fed3d7fd 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -292,10 +292,10 @@ abstract class DefaultNodes { host: "https://horizon-testnet.stellar.org/", port: 50022, name: defaultName, - id: _nodeId(Coin.stellarTestnet), + id: _nodeId(Coin.stellarTestNet), useSSL: true, enabled: true, - coinName: Coin.stellarTestnet.name, + coinName: Coin.stellarTestNet.name, isFailover: true, isDown: false, ); @@ -365,7 +365,7 @@ abstract class DefaultNodes { case Coin.dogecoinTestNet: return dogecoinTestnet; - case Coin.stellarTestnet: + case Coin.stellarTestNet: return stellarTestnet; } } diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index b62e4ea67..2e5062b6d 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -60,9 +60,10 @@ enum Coin { dogecoinTestNet, firoTestNet, litecoinTestNet, + stellarTestNet, } -final int kTestNetCoinCount = 4; // Util.isDesktop ? 5 : 4; +final int kTestNetCoinCount = 5; // Util.isDesktop ? 5 : 4; // remove firotestnet for now extension CoinExt on Coin { @@ -110,6 +111,8 @@ extension CoinExt on Coin { return "tFiro"; case Coin.dogecoinTestNet: return "tDogecoin"; + case Coin.stellarTestNet: + return "tStellar"; } } @@ -157,7 +160,7 @@ extension CoinExt on Coin { return "tFIRO"; case Coin.dogecoinTestNet: return "tDOGE"; - case Coin.stellarTestnet: + case Coin.stellarTestNet: return "tXLM"; } } @@ -207,7 +210,7 @@ extension CoinExt on Coin { return "firo"; case Coin.dogecoinTestNet: return "dogecoin"; - case Coin.stellarTestnet: + case Coin.stellarTestNet: return "stellar"; } } @@ -237,7 +240,7 @@ extension CoinExt on Coin { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return false; } } @@ -267,7 +270,7 @@ extension CoinExt on Coin { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return false; } } @@ -297,7 +300,7 @@ extension CoinExt on Coin { case Coin.litecoinTestNet: case Coin.bitcoincashTestnet: case Coin.firoTestNet: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return true; } } @@ -337,7 +340,7 @@ extension CoinExt on Coin { case Coin.firoTestNet: return Coin.firo; - case Coin.stellarTestnet: + case Coin.stellarTestNet: return Coin.stellar; } } @@ -380,7 +383,7 @@ extension CoinExt on Coin { return particl.MINIMUM_CONFIRMATIONS; case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return xlm.MINIMUM_CONFIRMATIONS; case Coin.tezos: @@ -500,7 +503,7 @@ Coin coinFromPrettyName(String name) { case "Stellar Testnet": case "stellarTestnet": case "tStellar": - return Coin.stellarTestnet; + return Coin.stellarTestNet; default: throw ArgumentError.value( @@ -556,7 +559,7 @@ Coin coinFromTickerCaseInsensitive(String ticker) { case "ban": return Coin.banano; case "txlm": - return Coin.stellarTestnet; + return Coin.stellarTestNet; default: throw ArgumentError.value( ticker, "name", "No Coin enum value with that ticker"); diff --git a/lib/utilities/enums/derive_path_type_enum.dart b/lib/utilities/enums/derive_path_type_enum.dart index 5b94f41f6..f3c456f67 100644 --- a/lib/utilities/enums/derive_path_type_enum.dart +++ b/lib/utilities/enums/derive_path_type_enum.dart @@ -50,7 +50,7 @@ extension DerivePathTypeExt on DerivePathType { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: case Coin.tezos: // TODO: Is this true? throw UnsupportedError( "$coin does not use bitcoin style derivation paths"); diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart index 661af4190..8d4c29ac2 100644 --- a/lib/widgets/node_card.dart +++ b/lib/widgets/node_card.dart @@ -196,7 +196,7 @@ class _NodeCardState extends ConsumerState { case Coin.banano: case Coin.tezos: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: throw UnimplementedError(); //TODO: check network/node } diff --git a/lib/widgets/node_options_sheet.dart b/lib/widgets/node_options_sheet.dart index 953ac78a1..63fd2b13e 100644 --- a/lib/widgets/node_options_sheet.dart +++ b/lib/widgets/node_options_sheet.dart @@ -179,7 +179,7 @@ class NodeOptionsSheet extends ConsumerWidget { case Coin.banano: case Coin.tezos: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: throw UnimplementedError(); //TODO: check network/node } diff --git a/pubspec.lock b/pubspec.lock index 111b58d75..c01aca249 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -459,7 +459,7 @@ packages: source: hosted version: "0.6.0" dio: - dependency: "direct overridden" + dependency: transitive description: name: dio sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" @@ -1297,10 +1297,10 @@ packages: dependency: transitive description: name: pretty_dio_logger - sha256: "00b80053063935cf9a6190da344c5373b9d0e92da4c944c878ff2fbef0ef6dc2" + sha256: "948f7eeb36e7aa0760b51c1a8e3331d4b21e36fabd39efca81f585ed93893544" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.2.0-beta-1" process: dependency: transitive description: @@ -1519,10 +1519,10 @@ packages: dependency: "direct main" description: name: stellar_flutter_sdk - sha256: "7a9b7dc76018bbd0b9c828045cf0e26e07ec44208fb1a1733273de2390205475" + sha256: "4c55b1b6dfbde7f89bba59a422754280715fa3b5726cff5e7eeaed454d2c4b89" url: "https://pub.dev" source: hosted - version: "1.6.0" + version: "1.5.3" stream_channel: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4e4a6755e..e3fa11745 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -138,7 +138,7 @@ dependencies: desktop_drop: ^0.4.1 nanodart: ^2.0.0 basic_utils: ^5.5.4 - stellar_flutter_sdk: ^1.6.0 + stellar_flutter_sdk: ^1.5.3 tezart: ^2.0.5 dev_dependencies: @@ -203,7 +203,6 @@ dependency_overrides: crypto: 3.0.2 analyzer: ^5.2.0 pinenacl: ^0.3.3 - dio : ^4.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From 182a8cc73252fc9799c2d131ea7a7168599f5026 Mon Sep 17 00:00:00 2001 From: detherminal <76167420+detherminal@users.noreply.github.com> Date: Sun, 6 Aug 2023 00:16:19 +0300 Subject: [PATCH 041/237] implement fees and sending? --- lib/services/coins/tezos/tezos_wallet.dart | 66 +++++++++++++++++----- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 9fa8e499f..e62a5afb0 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -144,8 +144,13 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { .round(); final int feeInMicroTez = int.parse(txData["fee"].toString()); final String destinationAddress = txData["address"] as String; - final String sourceAddress = await currentReceivingAddress; - return Future.value(""); // TODO: return tx hash + final secretKey = Keystore.fromMnemonic((await mnemonicString)!).secretKey; + Logging.instance.log(secretKey, level: LogLevel.Info); + final sourceKeyStore = Keystore.fromSecretKey(secretKey); + final client = TezartClient("${getCurrentNode().host}:${getCurrentNode().port}"); + final operation = await client.transferOperation(source: sourceKeyStore, destination: destinationAddress, amount: amountInMicroTez, customFee: feeInMicroTez); + await operation.executeAndMonitor(); // This line gives an error + return Future.value(""); } catch (e) { Logging.instance.log(e.toString(), level: LogLevel.Error); return Future.error(e); @@ -162,12 +167,29 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future estimateFeeFor(Amount amount, int feeRate) { - return Future.value( - Amount( - rawValue: BigInt.parse(100000.toString()), - fractionDigits: coin.decimals), - ); + Future estimateFeeFor(Amount amount, int feeRate) async { + // TODO: Check if this is correct + var api = "https://api.tzstats.com/series/op?start_date=today&collapse=10d"; + var response = jsonDecode((await get(Uri.parse(api))).body)[0]; + double totalFees = response[4] as double; + int totalTxs = response[8] as int; + int feePerTx = (totalFees / totalTxs * 1000000).floor(); + int estimatedFee = 0; + Logging.instance.log("feePerTx:$feePerTx", level: LogLevel.Info); + Logging.instance.log("feeRate:$feeRate", level: LogLevel.Info); + switch (feeRate) { + case 0: + estimatedFee = feePerTx * 2; + case 1: + estimatedFee = feePerTx; + case 2: + case 3: + estimatedFee = (feePerTx / 2).floor(); + default: + estimatedFee = feeRate; + } + Logging.instance.log("estimatedFee:$estimatedFee", level: LogLevel.Info); + return Amount(rawValue: BigInt.from(estimatedFee), fractionDigits: 6); } @override @@ -178,14 +200,21 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future get fees async { - // TODO: Change this to get fees from node and fix numberOfBlocks + // TODO: Check if this is correct + var api = "https://api.tzstats.com/series/op?start_date=today&collapse=10d"; + var response = jsonDecode((await get(Uri.parse(api))).body); + double totalFees = response[0][4] as double; + int totalTxs = response[0][8] as int; + int feePerTx = (totalFees / totalTxs * 1000000).floor(); + Logging.instance.log("feePerTx:$feePerTx", level: LogLevel.Info); + // TODO: fix numberOfBlocks return FeeObject( - numberOfBlocksFast: 1, - numberOfBlocksAverage: 1, - numberOfBlocksSlow: 1, - fast: 1000000, - medium: 100000, - slow: 10000, + numberOfBlocksFast: 3, + numberOfBlocksAverage: 10, + numberOfBlocksSlow: 30, + fast: (feePerTx * 2), + medium: feePerTx, + slow: (feePerTx / 2).floor(), ); } @@ -213,6 +242,13 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future initializeNew() async { + if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) { + throw Exception( + "Attempted to overwrite mnemonic on generate new wallet!"); + } + + await _prefs.init(); + var newKeystore = Keystore.random(); await _secureStore.write( key: '${_walletId}_mnemonic', From f1cb7278c50f98dd172dcf9f2d63ec7a6c0f6aff Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Aug 2023 09:18:08 -0600 Subject: [PATCH 042/237] update network wrapper --- lib/networking/http.dart | 73 ++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/lib/networking/http.dart b/lib/networking/http.dart index ddda3e7e6..909a66d27 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -1,40 +1,79 @@ import 'dart:convert'; +import 'dart:io'; -import 'package:http/http.dart' as http; +import 'package:stackwallet/utilities/logger.dart'; // WIP wrapper layer abstract class HTTP { - static Future get({ + static Future get({ required Uri url, Map? headers, required bool routeOverTor, }) async { - if (routeOverTor) { - // TODO - throw UnimplementedError(); - } else { - return http.get(url, headers: headers); + final httpClient = HttpClient(); + try { + if (routeOverTor) { + // TODO + throw UnimplementedError(); + } else { + final HttpClientRequest request = await httpClient.getUrl( + url, + ); + + request.headers.clear(); + if (headers != null) { + headers.forEach((key, value) => request.headers.add); + } + + return request.close(); + } + } catch (e, s) { + Logging.instance.log( + "HTTP.get() rethrew: $e\n$s", + level: LogLevel.Info, + ); + rethrow; + } finally { + httpClient.close(force: true); } } - static Future post({ + static Future post({ required Uri url, Map? headers, Object? body, Encoding? encoding, required bool routeOverTor, }) async { - if (routeOverTor) { - // TODO - throw UnimplementedError(); - } else { - return http.post( - url, - headers: headers, - body: body, - encoding: encoding, + final httpClient = HttpClient(); + try { + if (routeOverTor) { + // TODO + throw UnimplementedError(); + } else { + final HttpClientRequest request = await httpClient.postUrl( + url, + ); + + request.headers.clear(); + + if (headers != null) { + headers.forEach((key, value) => request.headers.add); + } + + request.write(body); + + return request.close(); + } + } catch (e, s) { + Logging.instance.log( + "HTTP.post() rethrew: $e\n$s", + level: LogLevel.Info, ); + rethrow; + } finally { + httpClient.close(force: true); } } } From 926d080b22b437f014c222cff4458a236c6abbd5 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 7 Aug 2023 11:10:23 -0500 Subject: [PATCH 043/237] add port getter and mark functions as Future async --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 43fd95976..b4bcc93ec 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 43fd95976281e4e205c35f34881749ade22b5234 +Subproject commit b4bcc93ecbd75dababf05c4add9f44a75e341998 From bc6fe692c5f9cc7caf955f17473bdbdafb0d901f Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 7 Aug 2023 11:34:12 -0500 Subject: [PATCH 044/237] julian's getRandomPort and other changes --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index b4bcc93ec..d41e9b19d 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit b4bcc93ecbd75dababf05c4add9f44a75e341998 +Subproject commit d41e9b19d0a6adcc33d7a709f75c39da4a0b3dc5 From 104e75530d160ab26dea321905c808f73312788f Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 7 Aug 2023 11:37:34 -0500 Subject: [PATCH 045/237] sneurlax/tor->cypherstack/flutter_libtor --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index c56eb8eee..1a56e8062 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,4 +9,4 @@ url = https://github.com/cypherstack/flutter_liblelantus.git [submodule "crypto_plugins/tor"] path = crypto_plugins/tor - url = https://github.com/sneurlax/tor.git + url = https://github.com/cypherstack/flutter_libtor.git From 53b8adca16cdfa092dc76df539d56a5eb8100f02 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Aug 2023 10:39:04 -0600 Subject: [PATCH 046/237] basic tor service --- lib/networking/tor_service.dart | 20 ++++++++++++++++++++ lib/utilities/stack_file_system.dart | 13 +++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 lib/networking/tor_service.dart diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart new file mode 100644 index 000000000..b4725414e --- /dev/null +++ b/lib/networking/tor_service.dart @@ -0,0 +1,20 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/utilities/stack_file_system.dart'; +import 'package:tor/tor.dart'; + +final pTorService = Provider((_) => TorService()); + +class TorService { + final _tor = Tor(); + + int get port => _tor.port; + + Future start() async { + final dir = await StackFileSystem.applicationTorDirectory(); + return await _tor.start(torDir: dir); + } + + Future stop() async { + return await _tor.disable(); + } +} diff --git a/lib/utilities/stack_file_system.dart b/lib/utilities/stack_file_system.dart index f36fadf01..4fb3e4617 100644 --- a/lib/utilities/stack_file_system.dart +++ b/lib/utilities/stack_file_system.dart @@ -60,6 +60,19 @@ abstract class StackFileSystem { } } + static Future applicationTorDirectory() async { + final root = await applicationRootDirectory(); + if (Util.isDesktop) { + final dir = Directory("${root.path}/tor"); + if (!dir.existsSync()) { + await dir.create(); + } + return dir; + } else { + return root; + } + } + static Future applicationHiveDirectory() async { final root = await applicationRootDirectory(); if (Util.isDesktop) { From 9965d793bdbd4fe29d72e0ea1645d8130db19c4b Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Aug 2023 10:46:34 -0600 Subject: [PATCH 047/237] WIP route over tor --- lib/main.dart | 11 ++++-- lib/networking/http.dart | 66 +++++++++++++++++++-------------- lib/networking/tor_service.dart | 3 +- pubspec.lock | 8 ++++ pubspec.yaml | 1 + 5 files changed, 56 insertions(+), 33 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 044665e5c..0392accfb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_libmonero/monero/monero.dart'; import 'package:flutter_libmonero/wownero/wownero.dart'; -import 'package:tor/tor.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -39,6 +38,7 @@ import 'package:stackwallet/models/models.dart'; import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/notification_model.dart'; import 'package:stackwallet/models/trade_wallet_lookup.dart'; +import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/pages/home_view/home_view.dart'; import 'package:stackwallet/pages/intro_view.dart'; import 'package:stackwallet/pages/loading_view.dart'; @@ -168,6 +168,12 @@ void main() async { await Hive.openBox(DB.boxNamePrefs); await Prefs.instance.init(); + // TODO create tor pref in Prefs + const useTor = true; // get from prefs + if (useTor) { + await TorService.sharedInstance.start(); + } + await StackFileSystem.initThemesDir(); // Desktop migrate handled elsewhere (currently desktop_login_view.dart) @@ -198,9 +204,6 @@ void main() async { wownero.onStartup(); } - dynamic tor = Tor(); - tor.start(); - // SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, // overlays: [SystemUiOverlay.bottom]); await NotificationApi.init(); diff --git a/lib/networking/http.dart b/lib/networking/http.dart index 909a66d27..e2772b9ba 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -1,6 +1,8 @@ import 'dart:convert'; import 'dart:io'; +import 'package:socks5_proxy/socks_client.dart'; +import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; // WIP wrapper layer @@ -14,20 +16,23 @@ abstract class HTTP { final httpClient = HttpClient(); try { if (routeOverTor) { - // TODO - throw UnimplementedError(); - } else { - final HttpClientRequest request = await httpClient.getUrl( - url, - ); - - request.headers.clear(); - if (headers != null) { - headers.forEach((key, value) => request.headers.add); - } - - return request.close(); + SocksTCPClient.assignToHttpClient(httpClient, [ + ProxySettings( + InternetAddress.loopbackIPv4, + TorService.sharedInstance.port, + ), + ]); } + final HttpClientRequest request = await httpClient.getUrl( + url, + ); + + request.headers.clear(); + if (headers != null) { + headers.forEach((key, value) => request.headers.add); + } + + return request.close(); } catch (e, s) { Logging.instance.log( "HTTP.get() rethrew: $e\n$s", @@ -49,23 +54,28 @@ abstract class HTTP { final httpClient = HttpClient(); try { if (routeOverTor) { - // TODO - throw UnimplementedError(); - } else { - final HttpClientRequest request = await httpClient.postUrl( - url, - ); - - request.headers.clear(); - - if (headers != null) { - headers.forEach((key, value) => request.headers.add); + if (routeOverTor) { + SocksTCPClient.assignToHttpClient(httpClient, [ + ProxySettings( + InternetAddress.loopbackIPv4, + TorService.sharedInstance.port, + ), + ]); } - - request.write(body); - - return request.close(); } + final HttpClientRequest request = await httpClient.postUrl( + url, + ); + + request.headers.clear(); + + if (headers != null) { + headers.forEach((key, value) => request.headers.add); + } + + request.write(body); + + return request.close(); } catch (e, s) { Logging.instance.log( "HTTP.post() rethrew: $e\n$s", diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart index b4725414e..5b1aa4616 100644 --- a/lib/networking/tor_service.dart +++ b/lib/networking/tor_service.dart @@ -2,9 +2,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; import 'package:tor/tor.dart'; -final pTorService = Provider((_) => TorService()); +final pTorService = Provider((_) => TorService.sharedInstance); class TorService { + static final sharedInstance = TorService(); final _tor = Tor(); int get port => _tor.port; diff --git a/pubspec.lock b/pubspec.lock index 914ca108c..675c61c54 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1402,6 +1402,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: "direct main" + description: + name: socks5_proxy + sha256: e0cba6917cd374de6f6cb0ce081e50e6efc24c61644b8e9f20c8bf8b91bb0b75 + url: "https://pub.dev" + source: hosted + version: "1.0.3+dev.3" source_gen: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9ce4aa2b4..6928a17e1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -142,6 +142,7 @@ dependencies: nanodart: ^2.0.0 basic_utils: ^5.5.4 stellar_flutter_sdk: ^1.6.0 + socks5_proxy: ^1.0.3+dev.3 dev_dependencies: flutter_test: From 8b42b36825edd5838ebdb8f9c0f2b72753d2a56c Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 7 Aug 2023 12:19:09 -0500 Subject: [PATCH 048/237] remove redundant check --- lib/networking/http.dart | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/networking/http.dart b/lib/networking/http.dart index e2772b9ba..7203c91e2 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -54,14 +54,12 @@ abstract class HTTP { final httpClient = HttpClient(); try { if (routeOverTor) { - if (routeOverTor) { - SocksTCPClient.assignToHttpClient(httpClient, [ - ProxySettings( - InternetAddress.loopbackIPv4, - TorService.sharedInstance.port, - ), - ]); - } + SocksTCPClient.assignToHttpClient(httpClient, [ + ProxySettings( + InternetAddress.loopbackIPv4, + TorService.sharedInstance.port, + ), + ]); } final HttpClientRequest request = await httpClient.postUrl( url, From 5aea9d6a2a89a11462c5c2d998015db80b3de3ff Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 7 Aug 2023 12:19:31 -0500 Subject: [PATCH 049/237] randomPort changes and sdk upgrades --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index d41e9b19d..b7cd44c2d 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit d41e9b19d0a6adcc33d7a709f75c39da4a0b3dc5 +Subproject commit b7cd44c2daea7836c62445ced922cdcdea4d2017 From 99dc1aef42ffb343b85234a81f43928f27bad422 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Aug 2023 11:06:44 -0600 Subject: [PATCH 050/237] add tor pref --- lib/main.dart | 7 ++++--- lib/utilities/prefs.dart | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 0392accfb..2eb63fdb0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -168,9 +168,10 @@ void main() async { await Hive.openBox(DB.boxNamePrefs); await Prefs.instance.init(); - // TODO create tor pref in Prefs - const useTor = true; // get from prefs - if (useTor) { + // TODO remove this!!!! + Prefs.instance.useTor = true; + + if (Prefs.instance.useTor) { await TorService.sharedInstance.start(); } diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index 7c306bfe5..f5a04a6f9 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -60,6 +60,7 @@ class Prefs extends ChangeNotifier { _systemBrightnessDarkThemeId = await _getSystemBrightnessDarkTheme(); await _setAmountUnits(); await _setMaxDecimals(); + _useTor = await _getUseTor(); _initialized = true; } @@ -869,4 +870,28 @@ class Prefs extends ChangeNotifier { _amountDecimals[coin] = decimals; } } + + // enabled tor + + bool _useTor = false; + + bool get useTor => _useTor; + + set useTor(bool useTor) { + if (_useTor != useTor) { + DB.instance.put( + boxName: DB.boxNamePrefs, + key: "useTor", + value: useTor, + ); + _useTor = useTor; + notifyListeners(); + } + } + + Future _getUseTor() async { + return await DB.instance + .get(boxName: DB.boxNamePrefs, key: "useTor") as bool? ?? + false; + } } From 3e5035bd66018e58a09b2d55a524bf7777523112 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Aug 2023 11:52:36 -0600 Subject: [PATCH 051/237] fix start issues --- .../exchange/change_now/change_now_api.dart | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/lib/services/exchange/change_now/change_now_api.dart b/lib/services/exchange/change_now/change_now_api.dart index a9d628448..1a9067376 100644 --- a/lib/services/exchange/change_now/change_now_api.dart +++ b/lib/services/exchange/change_now/change_now_api.dart @@ -12,7 +12,6 @@ import 'dart:convert'; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; -import 'package:http/http.dart' as http; import 'package:stackwallet/exceptions/exchange/exchange_exception.dart'; import 'package:stackwallet/exceptions/exchange/pair_unavailable_exception.dart'; import 'package:stackwallet/exceptions/exchange/unsupported_currency_exception.dart'; @@ -26,9 +25,11 @@ import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.d import 'package:stackwallet/models/exchange/response_objects/range.dart'; import 'package:stackwallet/models/isar/exchange_cache/currency.dart'; import 'package:stackwallet/models/isar/exchange_cache/pair.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; import 'package:stackwallet/services/exchange/exchange_response.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:tuple/tuple.dart'; class ChangeNowAPI { @@ -41,9 +42,6 @@ class ChangeNowAPI { static final ChangeNowAPI _instance = ChangeNowAPI._(); static ChangeNowAPI get instance => _instance; - /// set this to override using standard http client. Useful for testing - http.Client? client; - Uri _buildUri(String path, Map? params) { return Uri.https(authority, apiVersion + path, params); } @@ -53,21 +51,22 @@ class ChangeNowAPI { } Future _makeGetRequest(Uri uri) async { - final client = this.client ?? http.Client(); try { - final response = await client.get( - uri, + final response = await HTTP.get( + url: uri, headers: {'Content-Type': 'application/json'}, + routeOverTor: Prefs.instance.useTor, ); - + String? data; try { - final parsed = jsonDecode(response.body); + data = await response.transform(utf8.decoder).join(); + final parsed = jsonDecode(data); return parsed; } on FormatException catch (e) { return { "error": "Dart format exception", - "message": response.body, + "message": data, }; } } catch (e, s) { @@ -78,17 +77,18 @@ class ChangeNowAPI { } Future _makeGetRequestV2(Uri uri, String apiKey) async { - final client = this.client ?? http.Client(); try { - final response = await client.get( - uri, + final response = await HTTP.get( + url: uri, headers: { // 'Content-Type': 'application/json', 'x-changenow-api-key': apiKey, }, + routeOverTor: Prefs.instance.useTor, ); - final parsed = jsonDecode(response.body); + final data = await response.transform(utf8.decoder).join(); + final parsed = jsonDecode(data); return parsed; } catch (e, s) { @@ -102,21 +102,23 @@ class ChangeNowAPI { Uri uri, Map body, ) async { - final client = this.client ?? http.Client(); try { - final response = await client.post( - uri, + final response = await HTTP.post( + url: uri, headers: {'Content-Type': 'application/json'}, body: jsonEncode(body), + routeOverTor: Prefs.instance.useTor, ); + String? data; try { - final parsed = jsonDecode(response.body); + data = await response.transform(utf8.decoder).join(); + final parsed = jsonDecode(data); return parsed; } catch (_) { - Logging.instance.log("ChangeNOW api failed to parse: ${response.body}", - level: LogLevel.Error); + Logging.instance + .log("ChangeNOW api failed to parse: $data", level: LogLevel.Error); rethrow; } } catch (e, s) { From a26817ac5dbd8fcdf6d13fc3c6f927ad1e596ae5 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Aug 2023 11:52:53 -0600 Subject: [PATCH 052/237] update ref --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index b7cd44c2d..27699e12f 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit b7cd44c2daea7836c62445ced922cdcdea4d2017 +Subproject commit 27699e12f509e8c06f1085dab08932126d61162b From 11314d95b2649f330aaa3f9f251f2b47c20c7111 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 8 Aug 2023 10:17:51 -0500 Subject: [PATCH 053/237] crypto_plugins/tor->crypto_plugins/flutter_libtor --- .gitmodules | 6 +++--- crypto_plugins/{tor => flutter_libtor} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename crypto_plugins/{tor => flutter_libtor} (100%) diff --git a/.gitmodules b/.gitmodules index 1a56e8062..89e91bd22 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,6 @@ [submodule "crypto_plugins/flutter_liblelantus"] path = crypto_plugins/flutter_liblelantus url = https://github.com/cypherstack/flutter_liblelantus.git -[submodule "crypto_plugins/tor"] - path = crypto_plugins/tor - url = https://github.com/cypherstack/flutter_libtor.git +[submodule "crypto_plugins/flutter_libtor"] + path = crypto_plugins/flutter_libtor + url = https://github.com/cypherstack/flutter_libtor.git \ No newline at end of file diff --git a/crypto_plugins/tor b/crypto_plugins/flutter_libtor similarity index 100% rename from crypto_plugins/tor rename to crypto_plugins/flutter_libtor From 2d130f916e7acad92d938aff5e95a79b6d559907 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 8 Aug 2023 11:01:45 -0500 Subject: [PATCH 054/237] tor->flutter_libtor --- crypto_plugins/flutter_libtor | 2 +- lib/networking/tor_service.dart | 2 +- linux/CMakeLists.txt | 2 +- linux/flutter/generated_plugins.cmake | 2 +- pubspec.lock | 14 +++++++------- pubspec.yaml | 4 ++-- windows/flutter/generated_plugins.cmake | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crypto_plugins/flutter_libtor b/crypto_plugins/flutter_libtor index 27699e12f..f076853b8 160000 --- a/crypto_plugins/flutter_libtor +++ b/crypto_plugins/flutter_libtor @@ -1 +1 @@ -Subproject commit 27699e12f509e8c06f1085dab08932126d61162b +Subproject commit f076853b8ad231d882b1b26d44e22ef9ff2cbcf4 diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart index 5b1aa4616..9c27a35e0 100644 --- a/lib/networking/tor_service.dart +++ b/lib/networking/tor_service.dart @@ -1,6 +1,6 @@ +import 'package:flutter_libtor/flutter_libtor.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; -import 'package:tor/tor.dart'; final pTorService = Provider((_) => TorService.sharedInstance); diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 1fa44c9b7..18faa3a02 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -146,7 +146,7 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/linux/build/libmobileliblelantus.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/tor/scripts/linux/build/native/target/x86_64-unknown-linux-gnu/release/libtor_ffi.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libtor/scripts/linux/build/libtor_ffi.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1.7.4" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 397cac07d..80415b7fc 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -15,7 +15,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - tor + flutter_libtor ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/pubspec.lock b/pubspec.lock index 675c61c54..b50a60636 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -610,6 +610,13 @@ packages: relative: true source: path version: "0.0.1" + flutter_libtor: + dependency: "direct main" + description: + path: "crypto_plugins/flutter_libtor" + relative: true + source: path + version: "0.0.2" flutter_lints: dependency: "direct dev" description: @@ -1595,13 +1602,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.1" - tor: - dependency: "direct main" - description: - path: "crypto_plugins/tor" - relative: true - source: path - version: "0.0.1" tuple: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 6928a17e1..90f986fa7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -57,8 +57,8 @@ dependencies: url: https://github.com/cypherstack/bip47.git ref: 081ca1863c2feba00c35bb5b297902f12f499941 - tor: - path: ./crypto_plugins/tor + flutter_libtor: + path: ./crypto_plugins/flutter_libtor # Utility plugins http: ^0.13.0 diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 934f038bc..05f6f6f03 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -16,7 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - tor + flutter_libtor ) set(PLUGIN_BUNDLED_LIBRARIES) From ec5ae60a61d819322865494ff6bd44da993db108 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 8 Aug 2023 12:48:13 -0500 Subject: [PATCH 055/237] update flutter_libtor to use staging branch personal preference --- crypto_plugins/flutter_libtor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_libtor b/crypto_plugins/flutter_libtor index f076853b8..7f5446969 160000 --- a/crypto_plugins/flutter_libtor +++ b/crypto_plugins/flutter_libtor @@ -1 +1 @@ -Subproject commit f076853b8ad231d882b1b26d44e22ef9ff2cbcf4 +Subproject commit 7f544696969aa0a2d47d1d79ead3107dd2cea27e From 281cd983903111106e6b7b098aec9d65b1665665 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 8 Aug 2023 16:01:41 -0500 Subject: [PATCH 056/237] WIP proxied sockets --- lib/electrumx_rpc/electrumx.dart | 149 +++++++++++++++++++++++++------ lib/electrumx_rpc/rpc.dart | 85 +++++++++++++++--- test/json_rpc_test.dart | 5 +- 3 files changed, 199 insertions(+), 40 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index c9417116d..71bae9aa0 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -15,6 +15,7 @@ import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:decimal/decimal.dart'; import 'package:stackwallet/electrumx_rpc/rpc.dart'; import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; +import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:uuid/uuid.dart'; @@ -71,6 +72,8 @@ class ElectrumX { final Duration connectionTimeoutForSpecialCaseJsonRPCClients; + ({String host, int port})? proxyInfo; + ElectrumX({ required String host, required int port, @@ -80,6 +83,7 @@ class ElectrumX { JsonRPC? client, this.connectionTimeoutForSpecialCaseJsonRPCClients = const Duration(seconds: 60), + ({String host, int port})? proxyInfo, }) { _prefs = prefs; _host = host; @@ -92,14 +96,38 @@ class ElectrumX { required ElectrumXNode node, required Prefs prefs, required List failovers, - }) => - ElectrumX( + ({String host, int port})? proxyInfo, + }) { + if (Prefs.instance.useTor) { + if (proxyInfo == null) { + // TODO await tor / make sure it's running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.batchRequest(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + return ElectrumX( host: node.address, port: node.port, useSSL: node.useSSL, prefs: prefs, failovers: failovers, + proxyInfo: proxyInfo, ); + } else { + return ElectrumX( + host: node.address, + port: node.port, + useSSL: node.useSSL, + prefs: prefs, + failovers: failovers, + proxyInfo: null, + ); + } + } Future _allow() async { if (_prefs.wifiOnly) { @@ -121,20 +149,52 @@ class ElectrumX { throw WifiOnlyException(); } - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - ); + if (Prefs.instance.useTor) { + if (proxyInfo == null) { + // TODO await tor / make sure Tor is running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.batchRequest(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } else { + _rpcClient = JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } } else { - _rpcClient = JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - ); + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } else { + _rpcClient = JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } } try { @@ -221,20 +281,53 @@ class ElectrumX { throw WifiOnlyException(); } - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - ); + if (Prefs.instance.useTor) { + // TODO await tor / make sure Tor is initialized + if (proxyInfo == null) { + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.batchRequest(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } else { + _rpcClient = JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } } else { - _rpcClient = JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - ); + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } else { + _rpcClient = JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } } try { diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 2dc0d3a71..5480acf9e 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -14,7 +14,11 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; +import 'package:socks5_proxy/socks.dart'; +import 'package:socks5_proxy/src/client/socks_client.dart'; +import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; // Json RPC class to handle connecting to electrumx servers class JsonRPC { @@ -23,11 +27,13 @@ class JsonRPC { required this.port, this.useSSL = false, this.connectionTimeout = const Duration(seconds: 60), + required ({String host, int port})? proxyInfo, }); final bool useSSL; final String host; final int port; final Duration connectionTimeout; + ({String host, int port})? proxyInfo; final _requestMutex = Mutex(); final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); @@ -152,19 +158,76 @@ class JsonRPC { ); } - if (useSSL) { - _socket = await SecureSocket.connect( - host, + if (Prefs.instance.useTor) { + if (proxyInfo == null) { + // TODO await tor / make sure it's running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + // TODO connect to proxy socket... + // https://github.com/LacticWhale/socks_dart/blob/master/lib/src/client/socks_client.dart#L50C46-L50C56 + + // TODO implement ssl over tor + // if (useSSL) { + // _socket = await SecureSocket.connect( + // host, + // port, + // timeout: connectionTimeout, + // onBadCertificate: (_) => true, + // ); // TODO do not automatically trust bad certificates + // final _client = SocksSocket.protected(_socket, type); + // } else { + // _socket = await Socket.connect( + // proxyInfo!.host, + // proxyInfo!.port, + // timeout: connectionTimeout, + // ); + // final _client = SocksSocket.protected( + // _socket!, SocksConnectionType.connect + // ); + final InternetAddress _host = + await InternetAddress.lookup(host).then((value) => value.first); + var _socket = await SocksSocket.initialize( + [ + ProxySettings( + InternetAddress.loopbackIPv4, + proxyInfo!.port, + ) + ], + _host, port, - timeout: connectionTimeout, - onBadCertificate: (_) => true, - ); // TODO do not automatically trust bad certificates - } else { - _socket = await Socket.connect( - host, - port, - timeout: connectionTimeout, + SocksConnectionType.connect, ); + if (_socket == null) { + Logging.instance.log( + "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo", + level: LogLevel.Error); + throw Exception("JsonRPC.connect(): failed to connect to tor proxy"); + } else { + Logging.instance.log( + "JsonRPC.connect(): connected to $host over tor proxy at $proxyInfo", + level: LogLevel.Info); + } + } else { + if (useSSL) { + _socket = await SecureSocket.connect( + host, + port, + timeout: connectionTimeout, + onBadCertificate: (_) => true, + ); // TODO do not automatically trust bad certificates + } else { + _socket = await Socket.connect( + host, + port, + timeout: connectionTimeout, + ); + } } _subscription = _socket!.listen( diff --git a/test/json_rpc_test.dart b/test/json_rpc_test.dart index 333c1bde6..b5df1d52f 100644 --- a/test/json_rpc_test.dart +++ b/test/json_rpc_test.dart @@ -11,6 +11,7 @@ void main() { port: DefaultNodes.bitcoin.port, useSSL: true, connectionTimeout: const Duration(seconds: 40), + proxyInfo: null, // TODO test for proxyInfo ); const jsonRequestString = @@ -27,7 +28,8 @@ void main() { final jsonRPC = JsonRPC( host: "some.bad.address.thingdsfsdfsdaf", port: 3000, - connectionTimeout: Duration(seconds: 10), + connectionTimeout: const Duration(seconds: 10), + proxyInfo: null, ); const jsonRequestString = @@ -47,6 +49,7 @@ void main() { port: 3000, useSSL: false, connectionTimeout: const Duration(seconds: 1), + proxyInfo: null, ); const jsonRequestString = From e27d3f921345815e46103ad895ecd651f87d74cc Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 8 Aug 2023 16:27:38 -0500 Subject: [PATCH 057/237] WIP use SocksTCPClient.connect --- lib/electrumx_rpc/rpc.dart | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 5480acf9e..72a2f0b25 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -15,7 +15,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; import 'package:socks5_proxy/socks.dart'; -import 'package:socks5_proxy/src/client/socks_client.dart'; +import 'package:socks5_proxy/src/client/socks_client.dart'; // for SocksSocket import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; @@ -38,6 +38,7 @@ class JsonRPC { final _requestMutex = Mutex(); final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); Socket? _socket; + SocksSocket? _socksSocket; StreamSubscription? _subscription; void _dataHandler(List data) { @@ -81,7 +82,11 @@ class JsonRPC { _requestQueue.nextIncompleteReq.then((req) { if (req != null) { // \r\n required by electrumx server - _socket!.write('${req.jsonRequest}\r\n'); + if (_socksSocket != null) { + _socksSocket!.write('${req.jsonRequest}\r\n'); + } else { + _socket!.write('${req.jsonRequest}\r\n'); + } // TODO different timeout length? req.initiateTimeout( @@ -192,7 +197,7 @@ class JsonRPC { // ); final InternetAddress _host = await InternetAddress.lookup(host).then((value) => value.first); - var _socket = await SocksSocket.initialize( + _socksSocket = await SocksTCPClient.connect( [ ProxySettings( InternetAddress.loopbackIPv4, @@ -201,9 +206,8 @@ class JsonRPC { ], _host, port, - SocksConnectionType.connect, ); - if (_socket == null) { + if (_socksSocket == null) { Logging.instance.log( "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo", level: LogLevel.Error); @@ -213,6 +217,13 @@ class JsonRPC { "JsonRPC.connect(): connected to $host over tor proxy at $proxyInfo", level: LogLevel.Info); } + + _subscription = _socksSocket!.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } else { if (useSSL) { _socket = await SecureSocket.connect( @@ -228,14 +239,14 @@ class JsonRPC { timeout: connectionTimeout, ); } - } - _subscription = _socket!.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, - ); + _subscription = _socket!.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); + } } } From 5552fff3b37d23a53181c364e3862e7f1480a80d Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 8 Aug 2023 16:35:17 -0500 Subject: [PATCH 058/237] disambiguate log messages --- lib/electrumx_rpc/electrumx.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 71bae9aa0..f4eb7daf8 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -106,7 +106,7 @@ class ElectrumX { port: TorService.sharedInstance.port ); Logging.instance.log( - "ElectrumX.batchRequest(): no tor proxy info, read $proxyInfo", + "ElectrumX.from(): no tor proxy info, read $proxyInfo", level: LogLevel.Warning); } return ElectrumX( @@ -157,7 +157,7 @@ class ElectrumX { port: TorService.sharedInstance.port ); Logging.instance.log( - "ElectrumX.batchRequest(): no tor proxy info, read $proxyInfo", + "ElectrumX.request(): no tor proxy info, read $proxyInfo", level: LogLevel.Warning); } if (currentFailoverIndex == -1) { From 7c8796abfe7b97fc04df425d353d85b91d56d092 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 11:39:48 -0500 Subject: [PATCH 059/237] WIP --- lib/electrumx_rpc/electrumx.dart | 4 +-- lib/electrumx_rpc/rpc.dart | 46 +++++++++++++------------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index f4eb7daf8..99967d2df 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -169,7 +169,7 @@ class ElectrumX { proxyInfo: proxyInfo, ); } else { - _rpcClient = JsonRPC( + _rpcClient ??= JsonRPC( host: failovers![currentFailoverIndex].address, port: failovers![currentFailoverIndex].port, useSSL: failovers![currentFailoverIndex].useSSL, @@ -187,7 +187,7 @@ class ElectrumX { proxyInfo: null, ); } else { - _rpcClient = JsonRPC( + _rpcClient ??= JsonRPC( host: failovers![currentFailoverIndex].address, port: failovers![currentFailoverIndex].port, useSSL: failovers![currentFailoverIndex].useSSL, diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 72a2f0b25..1ed748f48 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -103,7 +103,7 @@ class JsonRPC { Duration requestTimeout, ) async { await _requestMutex.protect(() async { - if (_socket == null) { + if (_socket == null && _socksSocket == null) { Logging.instance.log( "JsonRPC request: opening socket $host:$port", level: LogLevel.Info, @@ -157,13 +157,16 @@ class JsonRPC { } Future connect() async { - if (_socket != null) { - throw Exception( - "JsonRPC attempted to connect to an already existing socket!", - ); - } - if (Prefs.instance.useTor) { + if (_socksSocket != null) { + Logging.instance.log( + "JsonRPC.connect(): JsonRPC attempted to connect to an already existing tor socket!", + level: LogLevel.Error); + throw Exception( + "JsonRPC attempted to connect to an already existing tor socket!", + ); + } + if (proxyInfo == null) { // TODO await tor / make sure it's running proxyInfo = ( @@ -174,27 +177,7 @@ class JsonRPC { "ElectrumX.connect(): no tor proxy info, read $proxyInfo", level: LogLevel.Warning); } - // TODO connect to proxy socket... - // https://github.com/LacticWhale/socks_dart/blob/master/lib/src/client/socks_client.dart#L50C46-L50C56 - // TODO implement ssl over tor - // if (useSSL) { - // _socket = await SecureSocket.connect( - // host, - // port, - // timeout: connectionTimeout, - // onBadCertificate: (_) => true, - // ); // TODO do not automatically trust bad certificates - // final _client = SocksSocket.protected(_socket, type); - // } else { - // _socket = await Socket.connect( - // proxyInfo!.host, - // proxyInfo!.port, - // timeout: connectionTimeout, - // ); - // final _client = SocksSocket.protected( - // _socket!, SocksConnectionType.connect - // ); final InternetAddress _host = await InternetAddress.lookup(host).then((value) => value.first); _socksSocket = await SocksTCPClient.connect( @@ -225,6 +208,15 @@ class JsonRPC { cancelOnError: true, ); } else { + if (_socket != null) { + Logging.instance.log( + "JsonRPC.connect(): JsonRPC attempted to connect to an already existing socket!", + level: LogLevel.Error); + throw Exception( + "JsonRPC attempted to connect to an already existing socket!", + ); + } + if (useSSL) { _socket = await SecureSocket.connect( host, From 9e7567a26a7af7c61f781aeb2bcf0499e6e0fd4a Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 12:13:26 -0500 Subject: [PATCH 060/237] add required proxyInfo param to JsonRPC class --- lib/electrumx_rpc/rpc.dart | 83 +++++++++++++++++++++++++++++++++----- test/json_rpc_test.dart | 5 ++- 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 2dc0d3a71..8c44e6dcd 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -14,7 +14,9 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; +import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; // Json RPC class to handle connecting to electrumx servers class JsonRPC { @@ -23,15 +25,17 @@ class JsonRPC { required this.port, this.useSSL = false, this.connectionTimeout = const Duration(seconds: 60), + required ({String host, int port})? proxyInfo, }); final bool useSSL; final String host; final int port; final Duration connectionTimeout; + ({String host, int port})? proxyInfo; final _requestMutex = Mutex(); final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); - Socket? _socket; + Socket? _socket; // TODO make a SocksSocket extension/wrapper or similar StreamSubscription? _subscription; void _dataHandler(List data) { @@ -152,19 +156,76 @@ class JsonRPC { ); } - if (useSSL) { - _socket = await SecureSocket.connect( - host, - port, - timeout: connectionTimeout, - onBadCertificate: (_) => true, - ); // TODO do not automatically trust bad certificates - } else { + if (Prefs.instance.useTor) { + if (proxyInfo == null) { + // TODO await tor / make sure it's running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + // TODO connect to proxy socket... + // https://github.com/LacticWhale/socks_dart/blob/master/lib/src/client/socks_client.dart#L50C46-L50C56 + + // TODO implement ssl over tor + // if (useSSL) { + // _socket = await SecureSocket.connect( + // host, + // port, + // timeout: connectionTimeout, + // onBadCertificate: (_) => true, + // ); // TODO do not automatically trust bad certificates + // final _client = SocksSocket.protected(_socket, type); + // } else { _socket = await Socket.connect( - host, - port, + proxyInfo!.host, + proxyInfo!.port, timeout: connectionTimeout, ); + // final _client = SocksSocket.protected( + // _socket!, SocksConnectionType.connect + // ); + // final InternetAddress _host = + // await InternetAddress.lookup(host).then((value) => value.first); + // var _socket = await SocksSocket.initialize( + // [ + // ProxySettings( + // InternetAddress.loopbackIPv4, + // proxyInfo!.port, + // ) + // ], + // _host, + // port, + // SocksConnectionType.connect, + // ); + if (_socket == null) { + Logging.instance.log( + "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo", + level: LogLevel.Error); + throw Exception("JsonRPC.connect(): failed to connect to tor proxy"); + } else { + Logging.instance.log( + "JsonRPC.connect(): connected to $host over tor proxy at $proxyInfo", + level: LogLevel.Info); + } + } else { + if (useSSL) { + _socket = await SecureSocket.connect( + host, + port, + timeout: connectionTimeout, + onBadCertificate: (_) => true, + ); // TODO do not automatically trust bad certificates + } else { + _socket = await Socket.connect( + host, + port, + timeout: connectionTimeout, + ); + } } _subscription = _socket!.listen( diff --git a/test/json_rpc_test.dart b/test/json_rpc_test.dart index 333c1bde6..b5df1d52f 100644 --- a/test/json_rpc_test.dart +++ b/test/json_rpc_test.dart @@ -11,6 +11,7 @@ void main() { port: DefaultNodes.bitcoin.port, useSSL: true, connectionTimeout: const Duration(seconds: 40), + proxyInfo: null, // TODO test for proxyInfo ); const jsonRequestString = @@ -27,7 +28,8 @@ void main() { final jsonRPC = JsonRPC( host: "some.bad.address.thingdsfsdfsdaf", port: 3000, - connectionTimeout: Duration(seconds: 10), + connectionTimeout: const Duration(seconds: 10), + proxyInfo: null, ); const jsonRequestString = @@ -47,6 +49,7 @@ void main() { port: 3000, useSSL: false, connectionTimeout: const Duration(seconds: 1), + proxyInfo: null, ); const jsonRequestString = From cfce22fa73eca2d625d38ea59e3b8cbfbfd0c765 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 12:14:24 -0500 Subject: [PATCH 061/237] v0l/socks5/master/lib/socks5.dart https://raw.githubusercontent.com/v0l/socks5/master/lib/socks5.dart --- lib/networking/socks5.dart | 365 +++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 lib/networking/socks5.dart diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart new file mode 100644 index 000000000..df4ecee1e --- /dev/null +++ b/lib/networking/socks5.dart @@ -0,0 +1,365 @@ +library socks; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +/// https://tools.ietf.org/html/rfc1928 +/// https://tools.ietf.org/html/rfc1929 +/// + +const SOCKSVersion = 0x05; +const RFC1929Version = 0x01; + +class AuthMethods { + static const NoAuth = const AuthMethods._(0x00); + static const GSSApi = const AuthMethods._(0x01); + static const UsernamePassword = const AuthMethods._(0x02); + static const NoAcceptableMethods = const AuthMethods._(0xFF); + + final int _value; + + const AuthMethods._(this._value); + + String toString() { + return const { + 0x00: 'AuthMethods.NoAuth', + 0x01: 'AuthMethods.GSSApi', + 0x02: 'AuthMethods.UsernamePassword', + 0xFF: 'AuthMethods.NoAcceptableMethods' + }[_value]; + } +} + +class SOCKSState { + static const Starting = const SOCKSState._(0x00); + static const Auth = const SOCKSState._(0x01); + static const RequestReady = const SOCKSState._(0x02); + static const Connected = const SOCKSState._(0x03); + static const AuthStarted = const SOCKSState._(0x04); + + final int _value; + + const SOCKSState._(this._value); + + String toString() { + return const [ + 'SOCKSState.Starting', + 'SOCKSState.Auth', + 'SOCKSState.RequestReady', + 'SOCKSState.Connected', + 'SOCKSState.AuthStarted' + ][_value]; + } +} + +class SOCKSAddressType { + static const IPv4 = const SOCKSAddressType._(0x01); + static const Domain = const SOCKSAddressType._(0x03); + static const IPv6 = const SOCKSAddressType._(0x04); + + final int _value; + + const SOCKSAddressType._(this._value); + + String toString() { + return const [ + null, + 'SOCKSAddressType.IPv4', + null, + 'SOCKSAddressType.Domain', + 'SOCKSAddressType.IPv6', + ][_value]; + } +} + +class SOCKSCommand { + static const Connect = const SOCKSCommand._(0x01); + static const Bind = const SOCKSCommand._(0x02); + static const UDPAssociate = const SOCKSCommand._(0x03); + + final int _value; + + const SOCKSCommand._(this._value); + + String toString() { + return const [ + null, + 'SOCKSCommand.Connect', + 'SOCKSCommand.Bind', + 'SOCKSCommand.UDPAssociate', + ][_value]; + } +} + +class SOCKSReply { + static const Success = const SOCKSReply._(0x00); + static const GeneralFailure = const SOCKSReply._(0x01); + static const ConnectionNotAllowedByRuleset = const SOCKSReply._(0x02); + static const NetworkUnreachable = const SOCKSReply._(0x03); + static const HostUnreachable = const SOCKSReply._(0x04); + static const ConnectionRefused = const SOCKSReply._(0x05); + static const TTLExpired = const SOCKSReply._(0x06); + static const CommandNotSupported = const SOCKSReply._(0x07); + static const AddressTypeNotSupported = const SOCKSReply._(0x08); + + final int _value; + + const SOCKSReply._(this._value); + + String toString() { + return const [ + 'SOCKSReply.Success', + 'SOCKSReply.GeneralFailure', + 'SOCKSReply.ConnectionNotAllowedByRuleset', + 'SOCKSReply.NetworkUnreachable', + 'SOCKSReply.HostUnreachable', + 'SOCKSReply.ConnectionRefused', + 'SOCKSReply.TTLExpired', + 'SOCKSReply.CommandNotSupported', + 'SOCKSReply.AddressTypeNotSupported' + ][_value]; + } +} + +class SOCKSRequest { + final int version = SOCKSVersion; + final SOCKSCommand command; + final SOCKSAddressType addressType; + final Uint8List address; + final int port; + + String getAddressString() { + if (addressType == SOCKSAddressType.Domain) { + return AsciiDecoder().convert(address); + } else if (addressType == SOCKSAddressType.IPv4) { + return address.join("."); + } else if (addressType == SOCKSAddressType.IPv6) { + var ret = List(); + for (var x = 0; x < address.length; x += 2) { + ret.add( + "${address[x].toRadixString(16).padLeft(2, "0")}${address[x + 1].toRadixString(16).padLeft(2, "0")}"); + } + return ret.join(":"); + } + return null; + } + + SOCKSRequest({ + this.command, + this.addressType, + this.address, + this.port, + }); +} + +class SOCKSSocket { + List _auth; + RawSocket _sock; + SOCKSRequest _request; + + StreamSubscription _sockSub; + StreamSubscription get subscription => _sockSub; + + SOCKSState _state; + final StreamController _stateStream = + StreamController(); + SOCKSState get state => _state; + Stream get stateStream => _stateStream?.stream; + + /// For username:password auth + final String username; + final String password; + + /// Waits for state to change to [SOCKSState.Connected] + /// If the connection request returns an error from the + /// socks server it will be thrown as an exception in the stream + /// + /// + Future get _waitForConnect => + stateStream.firstWhere((a) => a == SOCKSState.Connected); + + SOCKSSocket( + RawSocket socket, { + List auth = const [AuthMethods.NoAuth], + this.username, + this.password, + }) { + _sock = socket; + _auth = auth; + _setState(SOCKSState.Starting); + } + + void _setState(SOCKSState ns) { + _state = ns; + _stateStream.add(ns); + } + + /// Issue connect command to proxy + /// + Future connect(String domain) async { + final ds = domain.split(':'); + assert(ds.length == 2, "Domain must contain port, example.com:80"); + + _request = SOCKSRequest( + command: SOCKSCommand.Connect, + addressType: SOCKSAddressType.Domain, + address: AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length), + port: int.tryParse(ds[1]) ?? 80, + ); + await _start(); + await _waitForConnect; + } + + Future connectIp(InternetAddress ip, int port) async { + _request = SOCKSRequest( + command: SOCKSCommand.Connect, + addressType: ip.type == InternetAddressType.IPv4 + ? SOCKSAddressType.IPv4 + : SOCKSAddressType.IPv6, + address: ip.rawAddress, + port: port, + ); + await _start(); + await _waitForConnect; + } + + Future close({bool keepOpen = true}) async { + await _stateStream.close(); + if (!keepOpen) { + await _sock.close(); + } + } + + Future _start() async { + // send auth methods + _setState(SOCKSState.Auth); + //print(">> Version: 5, AuthMethods: $_auth"); + _sock.write([ + 0x05, + _auth.length, + ..._auth.map((v) => v._value), + ]); + + _sockSub = _sock.listen((RawSocketEvent ev) { + switch (ev) { + case RawSocketEvent.read: + { + final have = _sock.available(); + final data = _sock.read(have); + _handleRead(data); + break; + } + case RawSocketEvent.closed: + { + _sockSub.cancel(); + break; + } + } + }); + } + + void _sendUsernamePassword(String uname, String password) { + if (uname.length > 255 || password.length > 255) { + throw "Username or Password is too long"; + } + + final data = [ + RFC1929Version, + uname.length, + ...AsciiEncoder().convert(uname), + password.length, + ...AsciiEncoder().convert(password) + ]; + + //print(">> Sending $username:$password"); + _sock.write(data); + } + + void _handleRead(Uint8List data) async { + if (state == SOCKSState.Auth) { + if (data.length == 2) { + final version = data[0]; + final auth = AuthMethods._(data[1]); + + //print("<< Version: $version, Auth: $auth"); + + if (auth._value == AuthMethods.UsernamePassword._value) { + _setState(SOCKSState.AuthStarted); + _sendUsernamePassword(username, password); + } else if (auth._value == AuthMethods.NoAuth._value) { + _setState(SOCKSState.RequestReady); + _writeRequest(_request); + } else if (auth._value == AuthMethods.NoAcceptableMethods._value) { + throw "No auth methods acceptable"; + } + } else { + throw "Expected 2 bytes"; + } + } else if (_state == SOCKSState.AuthStarted) { + if (_auth.contains(AuthMethods.UsernamePassword)) { + final version = data[0]; + final status = data[1]; + + if (version != RFC1929Version || status != 0x00) { + throw "Invalid username or password"; + } else { + _setState(SOCKSState.RequestReady); + _writeRequest(_request); + } + } + } else if (_state == SOCKSState.RequestReady) { + if (data.length >= 10) { + final version = data[0]; + final reply = SOCKSReply._(data[1]); + //data[2] reserved + final addrType = SOCKSAddressType._(data[3]); + Uint8List addr; + var port = 0; + + if (addrType == SOCKSAddressType.Domain) { + final len = data[4]; + addr = data.sublist(5, 5 + len); + port = data[5 + len] << 8 | data[6 + len]; + } else if (addrType == SOCKSAddressType.IPv4) { + addr = data.sublist(5, 9); + port = data[9] << 8 | data[10]; + } else if (addrType == SOCKSAddressType.IPv6) { + addr = data.sublist(5, 21); + port = data[21] << 8 | data[22]; + } + + //print("<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); + if (reply._value == SOCKSReply.Success._value) { + _setState(SOCKSState.Connected); + } else { + throw reply; + } + } else { + throw "Expected 10 bytes"; + } + } + } + + void _writeRequest(SOCKSRequest req) { + if (_state == SOCKSState.RequestReady) { + final data = [ + req.version, + req.command._value, + 0x00, + req.addressType._value, + if (req.addressType == SOCKSAddressType.Domain) + req.address.lengthInBytes, + ...req.address, + req.port >> 8, + req.port & 0xF0, + ]; + + //print(">> Version: ${req.version}, Command: ${req.command}, AddrType: ${req.addressType}, Addr: ${req.getAddressString()}, Port: ${req.port}"); + _sock.write(data); + } else { + throw "Must be in RequestReady state, current state $_state"; + } + } +} From 7c3c41ae5e3c532f776944c029d241445efaddd8 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 12:14:37 -0500 Subject: [PATCH 062/237] fix v0l/socks5/master/lib/socks5.dart for dart 3 and Android Studio IDE warnings --- lib/networking/socks5.dart | 185 ++++++++++++++++++++----------------- 1 file changed, 100 insertions(+), 85 deletions(-) diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart index df4ecee1e..72591f6d0 100644 --- a/lib/networking/socks5.dart +++ b/lib/networking/socks5.dart @@ -1,4 +1,6 @@ -library socks; +// https://github.com/v0l/socks5 https://pub.dev/packages/socks5 for Dart 3 + +// library socks; import 'dart:async'; import 'dart:convert'; @@ -7,42 +9,44 @@ import 'dart:typed_data'; /// https://tools.ietf.org/html/rfc1928 /// https://tools.ietf.org/html/rfc1929 -/// const SOCKSVersion = 0x05; const RFC1929Version = 0x01; class AuthMethods { - static const NoAuth = const AuthMethods._(0x00); - static const GSSApi = const AuthMethods._(0x01); - static const UsernamePassword = const AuthMethods._(0x02); - static const NoAcceptableMethods = const AuthMethods._(0xFF); + static const NoAuth = AuthMethods._(0x00); + static const GSSApi = AuthMethods._(0x01); + static const UsernamePassword = AuthMethods._(0x02); + static const NoAcceptableMethods = AuthMethods._(0xFF); final int _value; const AuthMethods._(this._value); + @override String toString() { return const { - 0x00: 'AuthMethods.NoAuth', - 0x01: 'AuthMethods.GSSApi', - 0x02: 'AuthMethods.UsernamePassword', - 0xFF: 'AuthMethods.NoAcceptableMethods' - }[_value]; + 0x00: 'AuthMethods.NoAuth', + 0x01: 'AuthMethods.GSSApi', + 0x02: 'AuthMethods.UsernamePassword', + 0xFF: 'AuthMethods.NoAcceptableMethods' + }[_value] ?? + 'Unknown AuthMethod'; } } class SOCKSState { - static const Starting = const SOCKSState._(0x00); - static const Auth = const SOCKSState._(0x01); - static const RequestReady = const SOCKSState._(0x02); - static const Connected = const SOCKSState._(0x03); - static const AuthStarted = const SOCKSState._(0x04); + static const Starting = SOCKSState._(0x00); + static const Auth = SOCKSState._(0x01); + static const RequestReady = SOCKSState._(0x02); + static const Connected = SOCKSState._(0x03); + static const AuthStarted = SOCKSState._(0x04); final int _value; const SOCKSState._(this._value); + @override String toString() { return const [ 'SOCKSState.Starting', @@ -55,59 +59,64 @@ class SOCKSState { } class SOCKSAddressType { - static const IPv4 = const SOCKSAddressType._(0x01); - static const Domain = const SOCKSAddressType._(0x03); - static const IPv6 = const SOCKSAddressType._(0x04); + static const IPv4 = SOCKSAddressType._(0x01); + static const Domain = SOCKSAddressType._(0x03); + static const IPv6 = SOCKSAddressType._(0x04); final int _value; const SOCKSAddressType._(this._value); + @override String toString() { return const [ - null, - 'SOCKSAddressType.IPv4', - null, - 'SOCKSAddressType.Domain', - 'SOCKSAddressType.IPv6', - ][_value]; + null, + 'SOCKSAddressType.IPv4', + null, + 'SOCKSAddressType.Domain', + 'SOCKSAddressType.IPv6', + ][_value] ?? + 'Unknown SOCKSAddressType'; } } class SOCKSCommand { - static const Connect = const SOCKSCommand._(0x01); - static const Bind = const SOCKSCommand._(0x02); - static const UDPAssociate = const SOCKSCommand._(0x03); + static const Connect = SOCKSCommand._(0x01); + static const Bind = SOCKSCommand._(0x02); + static const UDPAssociate = SOCKSCommand._(0x03); final int _value; const SOCKSCommand._(this._value); + @override String toString() { return const [ - null, - 'SOCKSCommand.Connect', - 'SOCKSCommand.Bind', - 'SOCKSCommand.UDPAssociate', - ][_value]; + null, + 'SOCKSCommand.Connect', + 'SOCKSCommand.Bind', + 'SOCKSCommand.UDPAssociate', + ][_value] ?? + 'Unknown SOCKSCommand'; } } class SOCKSReply { - static const Success = const SOCKSReply._(0x00); - static const GeneralFailure = const SOCKSReply._(0x01); - static const ConnectionNotAllowedByRuleset = const SOCKSReply._(0x02); - static const NetworkUnreachable = const SOCKSReply._(0x03); - static const HostUnreachable = const SOCKSReply._(0x04); - static const ConnectionRefused = const SOCKSReply._(0x05); - static const TTLExpired = const SOCKSReply._(0x06); - static const CommandNotSupported = const SOCKSReply._(0x07); - static const AddressTypeNotSupported = const SOCKSReply._(0x08); + static const Success = SOCKSReply._(0x00); + static const GeneralFailure = SOCKSReply._(0x01); + static const ConnectionNotAllowedByRuleset = SOCKSReply._(0x02); + static const NetworkUnreachable = SOCKSReply._(0x03); + static const HostUnreachable = SOCKSReply._(0x04); + static const ConnectionRefused = SOCKSReply._(0x05); + static const TTLExpired = SOCKSReply._(0x06); + static const CommandNotSupported = SOCKSReply._(0x07); + static const AddressTypeNotSupported = SOCKSReply._(0x08); final int _value; const SOCKSReply._(this._value); + @override String toString() { return const [ 'SOCKSReply.Success', @@ -130,13 +139,13 @@ class SOCKSRequest { final Uint8List address; final int port; - String getAddressString() { + String? getAddressString() { if (addressType == SOCKSAddressType.Domain) { - return AsciiDecoder().convert(address); + return const AsciiDecoder().convert(address); } else if (addressType == SOCKSAddressType.IPv4) { return address.join("."); } else if (addressType == SOCKSAddressType.IPv6) { - var ret = List(); + var ret = []; for (var x = 0; x < address.length; x += 2) { ret.add( "${address[x].toRadixString(16).padLeft(2, "0")}${address[x + 1].toRadixString(16).padLeft(2, "0")}"); @@ -147,30 +156,30 @@ class SOCKSRequest { } SOCKSRequest({ - this.command, - this.addressType, - this.address, - this.port, + required this.command, + required this.addressType, + required this.address, + required this.port, }); } class SOCKSSocket { - List _auth; - RawSocket _sock; - SOCKSRequest _request; + late List _auth; + late RawSocket _sock; + late SOCKSRequest _request; - StreamSubscription _sockSub; + late StreamSubscription _sockSub; StreamSubscription get subscription => _sockSub; - SOCKSState _state; + late SOCKSState _state; final StreamController _stateStream = StreamController(); SOCKSState get state => _state; - Stream get stateStream => _stateStream?.stream; + Stream get stateStream => _stateStream.stream; /// For username:password auth - final String username; - final String password; + final String? username; + final String? password; /// Waits for state to change to [SOCKSState.Connected] /// If the connection request returns an error from the @@ -198,21 +207,21 @@ class SOCKSSocket { /// Issue connect command to proxy /// - Future connect(String domain) async { + Future connect(String domain) async { final ds = domain.split(':'); assert(ds.length == 2, "Domain must contain port, example.com:80"); _request = SOCKSRequest( command: SOCKSCommand.Connect, addressType: SOCKSAddressType.Domain, - address: AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length), + address: const AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length), port: int.tryParse(ds[1]) ?? 80, ); await _start(); await _waitForConnect; } - Future connectIp(InternetAddress ip, int port) async { + Future connectIp(InternetAddress ip, int port) async { _request = SOCKSRequest( command: SOCKSCommand.Connect, addressType: ip.type == InternetAddressType.IPv4 @@ -225,14 +234,14 @@ class SOCKSSocket { await _waitForConnect; } - Future close({bool keepOpen = true}) async { + Future close({bool keepOpen = true}) async { await _stateStream.close(); if (!keepOpen) { await _sock.close(); } } - Future _start() async { + Future _start() async { // send auth methods _setState(SOCKSState.Auth); //print(">> Version: 5, AuthMethods: $_auth"); @@ -248,7 +257,7 @@ class SOCKSSocket { { final have = _sock.available(); final data = _sock.read(have); - _handleRead(data); + if (data != null) _handleRead(data); break; } case RawSocketEvent.closed: @@ -256,6 +265,12 @@ class SOCKSSocket { _sockSub.cancel(); break; } + case RawSocketEvent.readClosed: + // TODO: Handle this case. + break; + case RawSocketEvent.write: + // TODO: Handle this case. + break; } }); } @@ -268,9 +283,9 @@ class SOCKSSocket { final data = [ RFC1929Version, uname.length, - ...AsciiEncoder().convert(uname), + ...const AsciiEncoder().convert(uname), password.length, - ...AsciiEncoder().convert(password) + ...const AsciiEncoder().convert(password) ]; //print(">> Sending $username:$password"); @@ -280,14 +295,14 @@ class SOCKSSocket { void _handleRead(Uint8List data) async { if (state == SOCKSState.Auth) { if (data.length == 2) { - final version = data[0]; - final auth = AuthMethods._(data[1]); - + // final version = data[0]; //print("<< Version: $version, Auth: $auth"); + final auth = AuthMethods._(data[1]); if (auth._value == AuthMethods.UsernamePassword._value) { _setState(SOCKSState.AuthStarted); - _sendUsernamePassword(username, password); + _sendUsernamePassword(username ?? '', password ?? ''); + // TODO check that passing an empty string is valid (vs. null previously) } else if (auth._value == AuthMethods.NoAuth._value) { _setState(SOCKSState.RequestReady); _writeRequest(_request); @@ -311,26 +326,26 @@ class SOCKSSocket { } } else if (_state == SOCKSState.RequestReady) { if (data.length >= 10) { - final version = data[0]; final reply = SOCKSReply._(data[1]); //data[2] reserved - final addrType = SOCKSAddressType._(data[3]); - Uint8List addr; - var port = 0; - if (addrType == SOCKSAddressType.Domain) { - final len = data[4]; - addr = data.sublist(5, 5 + len); - port = data[5 + len] << 8 | data[6 + len]; - } else if (addrType == SOCKSAddressType.IPv4) { - addr = data.sublist(5, 9); - port = data[9] << 8 | data[10]; - } else if (addrType == SOCKSAddressType.IPv6) { - addr = data.sublist(5, 21); - port = data[21] << 8 | data[22]; - } + // final version = data[0]; + // final addrType = SOCKSAddressType._(data[3]); + // Uint8List addr; + // var port = 0; + // if (addrType == SOCKSAddressType.Domain) { + // final len = data[4]; + // addr = data.sublist(5, 5 + len); + // port = data[5 + len] << 8 | data[6 + len]; + // } else if (addrType == SOCKSAddressType.IPv4) { + // addr = data.sublist(5, 9); + // port = data[9] << 8 | data[10]; + // } else if (addrType == SOCKSAddressType.IPv6) { + // addr = data.sublist(5, 21); + // port = data[21] << 8 | data[22]; + // } + // print("<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); - //print("<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); if (reply._value == SOCKSReply.Success._value) { _setState(SOCKSState.Connected); } else { From d8f41cccafceb7842b37d99571f90fbc1a92a4a8 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 12:19:11 -0500 Subject: [PATCH 063/237] remove _socksSocket --- lib/electrumx_rpc/rpc.dart | 61 ++++++++------------------------------ 1 file changed, 13 insertions(+), 48 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index a7ea0ccaf..8c44e6dcd 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -79,11 +79,7 @@ class JsonRPC { _requestQueue.nextIncompleteReq.then((req) { if (req != null) { // \r\n required by electrumx server - if (_socksSocket != null) { - _socksSocket!.write('${req.jsonRequest}\r\n'); - } else { - _socket!.write('${req.jsonRequest}\r\n'); - } + _socket!.write('${req.jsonRequest}\r\n'); // TODO different timeout length? req.initiateTimeout( @@ -100,7 +96,7 @@ class JsonRPC { Duration requestTimeout, ) async { await _requestMutex.protect(() async { - if (_socket == null && _socksSocket == null) { + if (_socket == null) { Logging.instance.log( "JsonRPC request: opening socket $host:$port", level: LogLevel.Info, @@ -154,49 +150,11 @@ class JsonRPC { } Future connect() async { - if (Prefs.instance.useTor) { - if (_socksSocket != null) { - Logging.instance.log( - "JsonRPC.connect(): JsonRPC attempted to connect to an already existing tor socket!", - level: LogLevel.Error); - throw Exception( - "JsonRPC attempted to connect to an already existing tor socket!", - ); - } - - if (proxyInfo == null) { - // TODO await tor / make sure it's running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log( - "ElectrumX.connect(): no tor proxy info, read $proxyInfo", - level: LogLevel.Warning); - } - - final InternetAddress _host = - await InternetAddress.lookup(host).then((value) => value.first); - _socksSocket = await SocksTCPClient.connect( - [ - ProxySettings( - InternetAddress.loopbackIPv4, - proxyInfo!.port, - ) - ], - _host, - port, + if (_socket != null) { + throw Exception( + "JsonRPC attempted to connect to an already existing socket!", ); - if (_socksSocket == null) { - Logging.instance.log( - "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo", - level: LogLevel.Error); - throw Exception("JsonRPC.connect(): failed to connect to tor proxy"); - } else { - Logging.instance.log( - "JsonRPC.connect(): connected to $host over tor proxy at $proxyInfo", - level: LogLevel.Info); - } + } if (Prefs.instance.useTor) { if (proxyInfo == null) { @@ -269,6 +227,13 @@ class JsonRPC { ); } } + + _subscription = _socket!.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } } From 29341fc0b03797b76715207d241b465c4d4e5996 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 12:19:17 -0500 Subject: [PATCH 064/237] exception casting --- lib/electrumx_rpc/electrumx.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 99967d2df..7d3dd3d2b 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -213,7 +213,8 @@ class ElectrumX { ); if (response.exception != null) { - throw response.exception!; + throw response.exception! + as Object; // TODO properly check that .exception is an Object } if (response.data is Map && response.data["error"] != null) { @@ -353,7 +354,8 @@ class ElectrumX { (await _rpcClient!.request(request, requestTimeout)); if (jsonRpcResponse.exception != null) { - throw jsonRpcResponse.exception!; + throw jsonRpcResponse.exception! + as Object; // TODO properly check that .exception is an Object } final response = jsonRpcResponse.data as List; From 1eeed74cf684dd405ebf59da4d7742afd40d56a9 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 12:50:12 -0500 Subject: [PATCH 065/237] WIP SOCKSSocket --- lib/electrumx_rpc/rpc.dart | 165 +++++++++++++++++++++---------------- lib/networking/socks5.dart | 5 ++ 2 files changed, 100 insertions(+), 70 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 8c44e6dcd..0e682e8b1 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -14,6 +14,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; +import 'package:stackwallet/networking/socks5.dart'; import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; @@ -35,7 +36,8 @@ class JsonRPC { final _requestMutex = Mutex(); final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); - Socket? _socket; // TODO make a SocksSocket extension/wrapper or similar + Socket? _socket; + SOCKSSocket? _socksSocket; StreamSubscription? _subscription; void _dataHandler(List data) { @@ -79,7 +81,12 @@ class JsonRPC { _requestQueue.nextIncompleteReq.then((req) { if (req != null) { // \r\n required by electrumx server - _socket!.write('${req.jsonRequest}\r\n'); + if (_socket != null) { + _socket!.write('${req.jsonRequest}\r\n'); + } + if (_socksSocket != null) { + _socksSocket!.write('${req.jsonRequest}\r\n'); + } // TODO different timeout length? req.initiateTimeout( @@ -96,12 +103,22 @@ class JsonRPC { Duration requestTimeout, ) async { await _requestMutex.protect(() async { - if (_socket == null) { - Logging.instance.log( - "JsonRPC request: opening socket $host:$port", - level: LogLevel.Info, - ); - await connect(); + if (!Prefs.instance.useTor) { + if (_socket == null) { + Logging.instance.log( + "JsonRPC request: opening socket $host:$port", + level: LogLevel.Info, + ); + await connect(); + } + } else { + if (_socksSocket == null) { + Logging.instance.log( + "JsonRPC request: opening SOCKS socket $host:$port", + level: LogLevel.Info, + ); + await connect(); + } } }); @@ -141,6 +158,9 @@ class JsonRPC { _subscription = null; _socket?.destroy(); _socket = null; + unawaited(_socksSocket?.close(keepOpen: false)); + // TODO check that it's ok to not await this + _socksSocket = null; // clean up remaining queue await _requestQueue.completeRemainingWithError( @@ -150,68 +170,7 @@ class JsonRPC { } Future connect() async { - if (_socket != null) { - throw Exception( - "JsonRPC attempted to connect to an already existing socket!", - ); - } - - if (Prefs.instance.useTor) { - if (proxyInfo == null) { - // TODO await tor / make sure it's running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log( - "ElectrumX.connect(): no tor proxy info, read $proxyInfo", - level: LogLevel.Warning); - } - // TODO connect to proxy socket... - // https://github.com/LacticWhale/socks_dart/blob/master/lib/src/client/socks_client.dart#L50C46-L50C56 - - // TODO implement ssl over tor - // if (useSSL) { - // _socket = await SecureSocket.connect( - // host, - // port, - // timeout: connectionTimeout, - // onBadCertificate: (_) => true, - // ); // TODO do not automatically trust bad certificates - // final _client = SocksSocket.protected(_socket, type); - // } else { - _socket = await Socket.connect( - proxyInfo!.host, - proxyInfo!.port, - timeout: connectionTimeout, - ); - // final _client = SocksSocket.protected( - // _socket!, SocksConnectionType.connect - // ); - // final InternetAddress _host = - // await InternetAddress.lookup(host).then((value) => value.first); - // var _socket = await SocksSocket.initialize( - // [ - // ProxySettings( - // InternetAddress.loopbackIPv4, - // proxyInfo!.port, - // ) - // ], - // _host, - // port, - // SocksConnectionType.connect, - // ); - if (_socket == null) { - Logging.instance.log( - "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo", - level: LogLevel.Error); - throw Exception("JsonRPC.connect(): failed to connect to tor proxy"); - } else { - Logging.instance.log( - "JsonRPC.connect(): connected to $host over tor proxy at $proxyInfo", - level: LogLevel.Info); - } - } else { + if (!Prefs.instance.useTor) { if (useSSL) { _socket = await SecureSocket.connect( host, @@ -226,6 +185,61 @@ class JsonRPC { timeout: connectionTimeout, ); } + } else { + if (proxyInfo == null) { + // TODO await tor / make sure it's running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + // TODO connect to proxy socket... + + // TODO implement ssl over tor + // if (useSSL) { + // _socket = await SecureSocket.connect( + // host, + // port, + // timeout: connectionTimeout, + // onBadCertificate: (_) => true, + // ); // TODO do not automatically trust bad certificates + // final _client = SocksSocket.protected(_socket, type); + // } else { + final sock = await RawSocket.connect( + InternetAddress.loopbackIPv4, proxyInfo!.port); + + _socksSocket = SOCKSSocket(sock); + if (_socksSocket == null) { + Logging.instance.log( + "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); + } else { + Logging.instance.log( + "JsonRPC.connect(): created SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } + + try { + if (!isIpAddress(host)) { + await _socksSocket!.connect("$host:$port"); + } else { + await _socksSocket!.connectIp(InternetAddress(host), port); + } + Logging.instance.log( + "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } catch (e) { + Logging.instance.log( + "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to connect to tor proxy, $e"); + } } _subscription = _socket!.listen( @@ -356,3 +370,14 @@ class JsonRPCResponse { JsonRPCResponse({this.data, this.exception}); } + +bool isIpAddress(String host) { + try { + // if the string can be parsed into an InternetAddress, it's an IP. + InternetAddress(host); + return true; + } catch (e) { + // if parsing fails, it's not an IP. + return false; + } +} diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart index 72591f6d0..e535ec7a2 100644 --- a/lib/networking/socks5.dart +++ b/lib/networking/socks5.dart @@ -377,4 +377,9 @@ class SOCKSSocket { throw "Must be in RequestReady state, current state $_state"; } } + + void write(Object? object) { + _sock.write(utf8.encode(object.toString())); + // TODO make sure the is correct; see _writeRequest above, may need to construct a SOCKSRequest from the data coming in + } } From 6a8bf395a6c7c366429923ddc7376fc55ea333ba Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 12:52:54 -0500 Subject: [PATCH 066/237] print debug info --- lib/networking/socks5.dart | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart index e535ec7a2..5944c1130 100644 --- a/lib/networking/socks5.dart +++ b/lib/networking/socks5.dart @@ -329,22 +329,23 @@ class SOCKSSocket { final reply = SOCKSReply._(data[1]); //data[2] reserved - // final version = data[0]; - // final addrType = SOCKSAddressType._(data[3]); - // Uint8List addr; - // var port = 0; - // if (addrType == SOCKSAddressType.Domain) { - // final len = data[4]; - // addr = data.sublist(5, 5 + len); - // port = data[5 + len] << 8 | data[6 + len]; - // } else if (addrType == SOCKSAddressType.IPv4) { - // addr = data.sublist(5, 9); - // port = data[9] << 8 | data[10]; - // } else if (addrType == SOCKSAddressType.IPv6) { - // addr = data.sublist(5, 21); - // port = data[21] << 8 | data[22]; - // } - // print("<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); + final version = data[0]; + final addrType = SOCKSAddressType._(data[3]); + Uint8List? addr; + var port = 0; + if (addrType == SOCKSAddressType.Domain) { + final len = data[4]; + addr = data.sublist(5, 5 + len); + port = data[5 + len] << 8 | data[6 + len]; + } else if (addrType == SOCKSAddressType.IPv4) { + addr = data.sublist(5, 9); + port = data[9] << 8 | data[10]; + } else if (addrType == SOCKSAddressType.IPv6) { + addr = data.sublist(5, 21); + port = data[21] << 8 | data[22]; + } + print( + "<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); if (reply._value == SOCKSReply.Success._value) { _setState(SOCKSState.Connected); From 658b5269d99534bb5b9130cfc1eef388bf00e6ca Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 14:59:24 -0500 Subject: [PATCH 067/237] reuse an existing _socksSocket --- lib/electrumx_rpc/rpc.dart | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 0e682e8b1..cd204ab2a 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -211,16 +211,26 @@ class JsonRPC { final sock = await RawSocket.connect( InternetAddress.loopbackIPv4, proxyInfo!.port); - _socksSocket = SOCKSSocket(sock); if (_socksSocket == null) { Logging.instance.log( - "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", - level: LogLevel.Error); - throw Exception( - "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); + "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", + level: LogLevel.Info); + _socksSocket = SOCKSSocket(sock); + if (_socksSocket == null) { + Logging.instance.log( + "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); + } else { + Logging.instance.log( + "JsonRPC.connect(): created SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } } else { + // TODO also check if sock == previous sock, eg. if RawSocket is different Logging.instance.log( - "JsonRPC.connect(): created SOCKS socket at $proxyInfo", + "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", level: LogLevel.Info); } From 0d60d23d28ed416755df4d8dc78c56b6a73562ea Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 15:04:57 -0500 Subject: [PATCH 068/237] moar logging --- lib/electrumx_rpc/rpc.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index cd204ab2a..ecbdda49d 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -114,7 +114,7 @@ class JsonRPC { } else { if (_socksSocket == null) { Logging.instance.log( - "JsonRPC request: opening SOCKS socket $host:$port", + "JsonRPC request: opening SOCKS socket to $host:$port", level: LogLevel.Info, ); await connect(); @@ -235,6 +235,9 @@ class JsonRPC { } try { + Logging.instance.log( + "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", + level: LogLevel.Info); if (!isIpAddress(host)) { await _socksSocket!.connect("$host:$port"); } else { From 71b69cc3a468efebd0ab33d2906feaf6be282f1f Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 15:15:51 -0500 Subject: [PATCH 069/237] add logging to socks5.dart --- lib/networking/socks5.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart index 5944c1130..18feb9b18 100644 --- a/lib/networking/socks5.dart +++ b/lib/networking/socks5.dart @@ -7,6 +7,8 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:stackwallet/utilities/logger.dart'; + /// https://tools.ietf.org/html/rfc1928 /// https://tools.ietf.org/html/rfc1929 @@ -267,9 +269,15 @@ class SOCKSSocket { } case RawSocketEvent.readClosed: // TODO: Handle this case. + Logging.instance.log( + "SOCKSSocket._start(): unhandled event RawSocketEvent.readClosed", + level: LogLevel.Warning); break; case RawSocketEvent.write: // TODO: Handle this case. + Logging.instance.log( + "SOCKSSocket._start(): unhandled event RawSocketEvent.write", + level: LogLevel.Warning); break; } }); From 84927734389251ac74e6ea084010326e7f679bd5 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 18:28:19 -0500 Subject: [PATCH 070/237] WIP very messy need to remove SocksSocket as it apparently doesn't work, whereas SocksProxy does --- lib/electrumx_rpc/rpc.dart | 244 ++++++++++++++++++++++++++----------- lib/networking/socks5.dart | 1 + 2 files changed, 172 insertions(+), 73 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index ecbdda49d..94038e8d3 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -38,6 +38,7 @@ class JsonRPC { final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); Socket? _socket; SOCKSSocket? _socksSocket; + SOCKS5Proxy? _socksProxy; StreamSubscription? _subscription; void _dataHandler(List data) { @@ -85,8 +86,17 @@ class JsonRPC { _socket!.write('${req.jsonRequest}\r\n'); } if (_socksSocket != null) { + print('writing to _socksSocket: ${req.jsonRequest}'); + print(req.jsonRequest); + print(req); _socksSocket!.write('${req.jsonRequest}\r\n'); } + if (_socksProxy != null) { + print('writing to _socksProxy: ${req.jsonRequest}'); + print(req.jsonRequest); + print(req); + _socksProxy!.write('${req.jsonRequest}\r\n'); + } // TODO different timeout length? req.initiateTimeout( @@ -109,12 +119,19 @@ class JsonRPC { "JsonRPC request: opening socket $host:$port", level: LogLevel.Info, ); - await connect(); + // await connect(); } } else { - if (_socksSocket == null) { + // if (_socksSocket == null) { + // Logging.instance.log( + // "JsonRPC request: opening SOCKS socket to $host:$port", + // level: LogLevel.Info, + // ); + // await connect(); + // } + if (_socksProxy == null) { Logging.instance.log( - "JsonRPC request: opening SOCKS socket to $host:$port", + "JsonRPC request: opening SOCKS proxy to $host:$port", level: LogLevel.Info, ); await connect(); @@ -185,82 +202,163 @@ class JsonRPC { timeout: connectionTimeout, ); } + + _subscription = _socket!.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } else { - if (proxyInfo == null) { - // TODO await tor / make sure it's running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port + if (_socksProxy == null) { + print(1111111); + _socksProxy = SOCKS5Proxy(); + // TODO check if null + await _socksProxy!.connect(); + print(222222); + // TODO check if null + await _socksProxy!.connectTo('bitcoincash.stackwallet.com', 50002); + + print(333333); + + // TODO check if null + _subscription = _socksProxy!.socket.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, ); - Logging.instance.log( - "ElectrumX.connect(): no tor proxy info, read $proxyInfo", - level: LogLevel.Warning); - } - // TODO connect to proxy socket... - - // TODO implement ssl over tor - // if (useSSL) { - // _socket = await SecureSocket.connect( - // host, - // port, - // timeout: connectionTimeout, - // onBadCertificate: (_) => true, - // ); // TODO do not automatically trust bad certificates - // final _client = SocksSocket.protected(_socket, type); - // } else { - final sock = await RawSocket.connect( - InternetAddress.loopbackIPv4, proxyInfo!.port); - - if (_socksSocket == null) { - Logging.instance.log( - "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", - level: LogLevel.Info); - _socksSocket = SOCKSSocket(sock); - if (_socksSocket == null) { - Logging.instance.log( - "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", - level: LogLevel.Error); - throw Exception( - "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); - } else { - Logging.instance.log( - "JsonRPC.connect(): created SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } } else { - // TODO also check if sock == previous sock, eg. if RawSocket is different - Logging.instance.log( - "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } - - try { - Logging.instance.log( - "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", - level: LogLevel.Info); - if (!isIpAddress(host)) { - await _socksSocket!.connect("$host:$port"); - } else { - await _socksSocket!.connectIp(InternetAddress(host), port); - } - Logging.instance.log( - "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } catch (e) { - Logging.instance.log( - "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", - level: LogLevel.Error); - throw Exception( - "JsonRPC.connect(): failed to connect to tor proxy, $e"); + print('0000000'); } + // if (proxyInfo == null) { + // // TODO await tor / make sure it's running + // proxyInfo = ( + // host: InternetAddress.loopbackIPv4.address, + // port: TorService.sharedInstance.port + // ); + // Logging.instance.log( + // "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + // level: LogLevel.Warning); + // } + // // TODO connect to proxy socket... + // + // // TODO implement ssl over tor + // // if (useSSL) { + // // _socket = await SecureSocket.connect( + // // host, + // // port, + // // timeout: connectionTimeout, + // // onBadCertificate: (_) => true, + // // ); // TODO do not automatically trust bad certificates + // // final _client = SocksSocket.protected(_socket, type); + // // } else { + // final sock = await RawSocket.connect( + // InternetAddress.loopbackIPv4, proxyInfo!.port); + // + // if (_socksSocket == null) { + // Logging.instance.log( + // "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", + // level: LogLevel.Info); + // _socksSocket = SOCKSSocket(sock); + // if (_socksSocket == null) { + // Logging.instance.log( + // "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", + // level: LogLevel.Error); + // throw Exception( + // "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); + // } else { + // Logging.instance.log( + // "JsonRPC.connect(): created SOCKS socket at $proxyInfo", + // level: LogLevel.Info); + // } + // } else { + // // TODO also check if sock == previous sock, eg. if RawSocket is different + // Logging.instance.log( + // "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", + // level: LogLevel.Info); + // } + // + // try { + // Logging.instance.log( + // "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", + // level: LogLevel.Info); + // if (!isIpAddress(host)) { + // await _socksSocket!.connect("$host:$port"); + // } else { + // await _socksSocket!.connectIp(InternetAddress(host), port); + // } + // Logging.instance.log( + // "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", + // level: LogLevel.Info); + // } catch (e) { + // Logging.instance.log( + // "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", + // level: LogLevel.Error); + // throw Exception( + // "JsonRPC.connect(): failed to connect to tor proxy, $e"); + // } } + } +} - _subscription = _socket!.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, - ); +class SOCKS5Proxy { + final String host; + final int port; + + late Socket _socks5Socket; + Socket get socket => _socks5Socket; + + SOCKS5Proxy({String? host, int? port}) + : host = host ?? InternetAddress.loopbackIPv4.address, + port = port ?? TorService.sharedInstance.port; + + Future connect() async { + _socks5Socket = await Socket.connect(host, port); + + // Greeting and method selection + _socks5Socket.add([0x05, 0x01, 0x00]); + + // Wait for server response + var response = await _socks5Socket.first; + if (response[1] != 0x00) { + throw Exception('Failed to connect to SOCKS5 proxy.'); + } + } + + // This is just a basic example for domain-based addresses. + Future connectTo(String domain, int port) async { + // Command, Reserved, Address Type, Address, Port + var request = [ + 0x05, + 0x01, + 0x00, + 0x03, + domain.length, + ...domain.codeUnits, + (port >> 8) & 0xFF, + port & 0xFF + ]; + + _socks5Socket.add(request); + print(444444); + + // Wait for server response + // var response = await _socks5Socket.first; + // if (response[1] != 0x00) { + // throw Exception('Failed to connect to target through SOCKS5 proxy.'); + // } + // print(response); + print(55555); + } + + /// Converts [object] to a String by invoking [Object.toString] and + /// sends the encoding of the result to the socket. + void write(Object? object) { + if (object == null) return; + + List data = utf8.encode(object.toString()); + _socks5Socket.add(data); } } diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart index 18feb9b18..619685381 100644 --- a/lib/networking/socks5.dart +++ b/lib/networking/socks5.dart @@ -275,6 +275,7 @@ class SOCKSSocket { break; case RawSocketEvent.write: // TODO: Handle this case. + Logging.instance.log( "SOCKSSocket._start(): unhandled event RawSocketEvent.write", level: LogLevel.Warning); From c7ea583a442bf59ffe7fb243a77a8b43158bccfa Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 10 Aug 2023 11:40:12 -0500 Subject: [PATCH 071/237] clean up SOCKSSocket, still no joy --- lib/electrumx_rpc/rpc.dart | 266 ++++++++------------- lib/networking/socks5.dart | 395 ------------------------------- lib/networking/socks_socket.dart | 111 +++++++++ 3 files changed, 208 insertions(+), 564 deletions(-) delete mode 100644 lib/networking/socks5.dart create mode 100644 lib/networking/socks_socket.dart diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 94038e8d3..c90d66293 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -14,7 +14,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; -import 'package:stackwallet/networking/socks5.dart'; +import 'package:stackwallet/networking/socks_socket.dart'; import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; @@ -38,7 +38,6 @@ class JsonRPC { final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); Socket? _socket; SOCKSSocket? _socksSocket; - SOCKS5Proxy? _socksProxy; StreamSubscription? _subscription; void _dataHandler(List data) { @@ -81,22 +80,18 @@ class JsonRPC { void _sendNextAvailableRequest() { _requestQueue.nextIncompleteReq.then((req) { if (req != null) { + // TODO check if useTor to determine socket to which to write // \r\n required by electrumx server if (_socket != null) { _socket!.write('${req.jsonRequest}\r\n'); } if (_socksSocket != null) { - print('writing to _socksSocket: ${req.jsonRequest}'); - print(req.jsonRequest); - print(req); + Logging.instance.log( + "writing to _socksSocket: ${req.jsonRequest}", + level: LogLevel.Info, + ); _socksSocket!.write('${req.jsonRequest}\r\n'); } - if (_socksProxy != null) { - print('writing to _socksProxy: ${req.jsonRequest}'); - print(req.jsonRequest); - print(req); - _socksProxy!.write('${req.jsonRequest}\r\n'); - } // TODO different timeout length? req.initiateTimeout( @@ -116,22 +111,15 @@ class JsonRPC { if (!Prefs.instance.useTor) { if (_socket == null) { Logging.instance.log( - "JsonRPC request: opening socket $host:$port", + "JsonRPC request: opening direct socket $host:$port", level: LogLevel.Info, ); - // await connect(); + await connect(); } } else { - // if (_socksSocket == null) { - // Logging.instance.log( - // "JsonRPC request: opening SOCKS socket to $host:$port", - // level: LogLevel.Info, - // ); - // await connect(); - // } - if (_socksProxy == null) { + if (_socksSocket == null) { Logging.instance.log( - "JsonRPC request: opening SOCKS proxy to $host:$port", + "JsonRPC request: opening SOCKS socket to $host:$port", level: LogLevel.Info, ); await connect(); @@ -175,8 +163,8 @@ class JsonRPC { _subscription = null; _socket?.destroy(); _socket = null; - unawaited(_socksSocket?.close(keepOpen: false)); - // TODO check that it's ok to not await this + unawaited(_socksSocket?.close()); + // TODO check that we can safely unawaited this _socksSocket = null; // clean up remaining queue @@ -210,158 +198,98 @@ class JsonRPC { cancelOnError: true, ); } else { - if (_socksProxy == null) { - print(1111111); - _socksProxy = SOCKS5Proxy(); - // TODO check if null - await _socksProxy!.connect(); - print(222222); - // TODO check if null - await _socksProxy!.connectTo('bitcoincash.stackwallet.com', 50002); - - print(333333); - - // TODO check if null - _subscription = _socksProxy!.socket.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, + if (proxyInfo == null) { + // TODO await tor / make sure it's running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port ); - } else { - print('0000000'); + Logging.instance.log( + "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); } - // if (proxyInfo == null) { - // // TODO await tor / make sure it's running - // proxyInfo = ( - // host: InternetAddress.loopbackIPv4.address, - // port: TorService.sharedInstance.port - // ); - // Logging.instance.log( - // "ElectrumX.connect(): no tor proxy info, read $proxyInfo", - // level: LogLevel.Warning); - // } - // // TODO connect to proxy socket... - // - // // TODO implement ssl over tor - // // if (useSSL) { - // // _socket = await SecureSocket.connect( - // // host, - // // port, - // // timeout: connectionTimeout, - // // onBadCertificate: (_) => true, - // // ); // TODO do not automatically trust bad certificates - // // final _client = SocksSocket.protected(_socket, type); - // // } else { - // final sock = await RawSocket.connect( - // InternetAddress.loopbackIPv4, proxyInfo!.port); - // - // if (_socksSocket == null) { - // Logging.instance.log( - // "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", - // level: LogLevel.Info); - // _socksSocket = SOCKSSocket(sock); - // if (_socksSocket == null) { - // Logging.instance.log( - // "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", - // level: LogLevel.Error); - // throw Exception( - // "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); - // } else { - // Logging.instance.log( - // "JsonRPC.connect(): created SOCKS socket at $proxyInfo", - // level: LogLevel.Info); - // } + // TODO connect to proxy socket... + + // TODO implement ssl over tor + // if (useSSL) { + // _socket = await SecureSocket.connect( + // host, + // port, + // timeout: connectionTimeout, + // onBadCertificate: (_) => true, + // ); // TODO do not automatically trust bad certificates + // final _client = SocksSocket.protected(_socket, type); // } else { - // // TODO also check if sock == previous sock, eg. if RawSocket is different - // Logging.instance.log( - // "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", - // level: LogLevel.Info); - // } - // - // try { - // Logging.instance.log( - // "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", - // level: LogLevel.Info); - // if (!isIpAddress(host)) { - // await _socksSocket!.connect("$host:$port"); - // } else { - // await _socksSocket!.connectIp(InternetAddress(host), port); - // } - // Logging.instance.log( - // "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", - // level: LogLevel.Info); - // } catch (e) { - // Logging.instance.log( - // "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", - // level: LogLevel.Error); - // throw Exception( - // "JsonRPC.connect(): failed to connect to tor proxy, $e"); - // } + // set up socks socket + if (_socksSocket == null) { + Logging.instance.log( + "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", + level: LogLevel.Info); + _socksSocket = + SOCKSSocket(host: proxyInfo!.host, port: proxyInfo!.port); + if (_socksSocket == null) { + Logging.instance.log( + "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); + } else { + Logging.instance.log( + "JsonRPC.connect(): created SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } + } else { + // TODO also check if sock == previous sock, eg. if RawSocket is different, and if _socksSocket is valid + Logging.instance.log( + "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } + + // connect to socks socket + try { + Logging.instance.log( + "JsonRPC.connect(): connecting to SOCKS socket at $proxyInfo...", + level: LogLevel.Info); + await _socksSocket!.connect(); + Logging.instance.log( + "JsonRPC.connect(): connected to SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } catch (e) { + Logging.instance.log( + "JsonRPC.connect(): failed to connect to SOCKS socket at $proxyInfo, $e", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to connect to SOCKS socket, $e"); + } + + // connect to node through socks socket + try { + Logging.instance.log( + "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", + level: LogLevel.Info); + await _socksSocket!.connectTo(host, port); + Logging.instance.log( + "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } catch (e) { + Logging.instance.log( + "JsonRPC.connect(): failed to connect to $host over SOCKS socket at $proxyInfo, $e", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to connect to $host over SOCKS socket, $e"); + } + + // TODO check if null + _subscription = _socksSocket!.socket.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } } } -class SOCKS5Proxy { - final String host; - final int port; - - late Socket _socks5Socket; - Socket get socket => _socks5Socket; - - SOCKS5Proxy({String? host, int? port}) - : host = host ?? InternetAddress.loopbackIPv4.address, - port = port ?? TorService.sharedInstance.port; - - Future connect() async { - _socks5Socket = await Socket.connect(host, port); - - // Greeting and method selection - _socks5Socket.add([0x05, 0x01, 0x00]); - - // Wait for server response - var response = await _socks5Socket.first; - if (response[1] != 0x00) { - throw Exception('Failed to connect to SOCKS5 proxy.'); - } - } - - // This is just a basic example for domain-based addresses. - Future connectTo(String domain, int port) async { - // Command, Reserved, Address Type, Address, Port - var request = [ - 0x05, - 0x01, - 0x00, - 0x03, - domain.length, - ...domain.codeUnits, - (port >> 8) & 0xFF, - port & 0xFF - ]; - - _socks5Socket.add(request); - print(444444); - - // Wait for server response - // var response = await _socks5Socket.first; - // if (response[1] != 0x00) { - // throw Exception('Failed to connect to target through SOCKS5 proxy.'); - // } - // print(response); - print(55555); - } - - /// Converts [object] to a String by invoking [Object.toString] and - /// sends the encoding of the result to the socket. - void write(Object? object) { - if (object == null) return; - - List data = utf8.encode(object.toString()); - _socks5Socket.add(data); - } -} - class _JsonRPCRequestQueue { final _lock = Mutex(); final List<_JsonRPCRequest> _rq = []; diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart deleted file mode 100644 index 619685381..000000000 --- a/lib/networking/socks5.dart +++ /dev/null @@ -1,395 +0,0 @@ -// https://github.com/v0l/socks5 https://pub.dev/packages/socks5 for Dart 3 - -// library socks; - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:stackwallet/utilities/logger.dart'; - -/// https://tools.ietf.org/html/rfc1928 -/// https://tools.ietf.org/html/rfc1929 - -const SOCKSVersion = 0x05; -const RFC1929Version = 0x01; - -class AuthMethods { - static const NoAuth = AuthMethods._(0x00); - static const GSSApi = AuthMethods._(0x01); - static const UsernamePassword = AuthMethods._(0x02); - static const NoAcceptableMethods = AuthMethods._(0xFF); - - final int _value; - - const AuthMethods._(this._value); - - @override - String toString() { - return const { - 0x00: 'AuthMethods.NoAuth', - 0x01: 'AuthMethods.GSSApi', - 0x02: 'AuthMethods.UsernamePassword', - 0xFF: 'AuthMethods.NoAcceptableMethods' - }[_value] ?? - 'Unknown AuthMethod'; - } -} - -class SOCKSState { - static const Starting = SOCKSState._(0x00); - static const Auth = SOCKSState._(0x01); - static const RequestReady = SOCKSState._(0x02); - static const Connected = SOCKSState._(0x03); - static const AuthStarted = SOCKSState._(0x04); - - final int _value; - - const SOCKSState._(this._value); - - @override - String toString() { - return const [ - 'SOCKSState.Starting', - 'SOCKSState.Auth', - 'SOCKSState.RequestReady', - 'SOCKSState.Connected', - 'SOCKSState.AuthStarted' - ][_value]; - } -} - -class SOCKSAddressType { - static const IPv4 = SOCKSAddressType._(0x01); - static const Domain = SOCKSAddressType._(0x03); - static const IPv6 = SOCKSAddressType._(0x04); - - final int _value; - - const SOCKSAddressType._(this._value); - - @override - String toString() { - return const [ - null, - 'SOCKSAddressType.IPv4', - null, - 'SOCKSAddressType.Domain', - 'SOCKSAddressType.IPv6', - ][_value] ?? - 'Unknown SOCKSAddressType'; - } -} - -class SOCKSCommand { - static const Connect = SOCKSCommand._(0x01); - static const Bind = SOCKSCommand._(0x02); - static const UDPAssociate = SOCKSCommand._(0x03); - - final int _value; - - const SOCKSCommand._(this._value); - - @override - String toString() { - return const [ - null, - 'SOCKSCommand.Connect', - 'SOCKSCommand.Bind', - 'SOCKSCommand.UDPAssociate', - ][_value] ?? - 'Unknown SOCKSCommand'; - } -} - -class SOCKSReply { - static const Success = SOCKSReply._(0x00); - static const GeneralFailure = SOCKSReply._(0x01); - static const ConnectionNotAllowedByRuleset = SOCKSReply._(0x02); - static const NetworkUnreachable = SOCKSReply._(0x03); - static const HostUnreachable = SOCKSReply._(0x04); - static const ConnectionRefused = SOCKSReply._(0x05); - static const TTLExpired = SOCKSReply._(0x06); - static const CommandNotSupported = SOCKSReply._(0x07); - static const AddressTypeNotSupported = SOCKSReply._(0x08); - - final int _value; - - const SOCKSReply._(this._value); - - @override - String toString() { - return const [ - 'SOCKSReply.Success', - 'SOCKSReply.GeneralFailure', - 'SOCKSReply.ConnectionNotAllowedByRuleset', - 'SOCKSReply.NetworkUnreachable', - 'SOCKSReply.HostUnreachable', - 'SOCKSReply.ConnectionRefused', - 'SOCKSReply.TTLExpired', - 'SOCKSReply.CommandNotSupported', - 'SOCKSReply.AddressTypeNotSupported' - ][_value]; - } -} - -class SOCKSRequest { - final int version = SOCKSVersion; - final SOCKSCommand command; - final SOCKSAddressType addressType; - final Uint8List address; - final int port; - - String? getAddressString() { - if (addressType == SOCKSAddressType.Domain) { - return const AsciiDecoder().convert(address); - } else if (addressType == SOCKSAddressType.IPv4) { - return address.join("."); - } else if (addressType == SOCKSAddressType.IPv6) { - var ret = []; - for (var x = 0; x < address.length; x += 2) { - ret.add( - "${address[x].toRadixString(16).padLeft(2, "0")}${address[x + 1].toRadixString(16).padLeft(2, "0")}"); - } - return ret.join(":"); - } - return null; - } - - SOCKSRequest({ - required this.command, - required this.addressType, - required this.address, - required this.port, - }); -} - -class SOCKSSocket { - late List _auth; - late RawSocket _sock; - late SOCKSRequest _request; - - late StreamSubscription _sockSub; - StreamSubscription get subscription => _sockSub; - - late SOCKSState _state; - final StreamController _stateStream = - StreamController(); - SOCKSState get state => _state; - Stream get stateStream => _stateStream.stream; - - /// For username:password auth - final String? username; - final String? password; - - /// Waits for state to change to [SOCKSState.Connected] - /// If the connection request returns an error from the - /// socks server it will be thrown as an exception in the stream - /// - /// - Future get _waitForConnect => - stateStream.firstWhere((a) => a == SOCKSState.Connected); - - SOCKSSocket( - RawSocket socket, { - List auth = const [AuthMethods.NoAuth], - this.username, - this.password, - }) { - _sock = socket; - _auth = auth; - _setState(SOCKSState.Starting); - } - - void _setState(SOCKSState ns) { - _state = ns; - _stateStream.add(ns); - } - - /// Issue connect command to proxy - /// - Future connect(String domain) async { - final ds = domain.split(':'); - assert(ds.length == 2, "Domain must contain port, example.com:80"); - - _request = SOCKSRequest( - command: SOCKSCommand.Connect, - addressType: SOCKSAddressType.Domain, - address: const AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length), - port: int.tryParse(ds[1]) ?? 80, - ); - await _start(); - await _waitForConnect; - } - - Future connectIp(InternetAddress ip, int port) async { - _request = SOCKSRequest( - command: SOCKSCommand.Connect, - addressType: ip.type == InternetAddressType.IPv4 - ? SOCKSAddressType.IPv4 - : SOCKSAddressType.IPv6, - address: ip.rawAddress, - port: port, - ); - await _start(); - await _waitForConnect; - } - - Future close({bool keepOpen = true}) async { - await _stateStream.close(); - if (!keepOpen) { - await _sock.close(); - } - } - - Future _start() async { - // send auth methods - _setState(SOCKSState.Auth); - //print(">> Version: 5, AuthMethods: $_auth"); - _sock.write([ - 0x05, - _auth.length, - ..._auth.map((v) => v._value), - ]); - - _sockSub = _sock.listen((RawSocketEvent ev) { - switch (ev) { - case RawSocketEvent.read: - { - final have = _sock.available(); - final data = _sock.read(have); - if (data != null) _handleRead(data); - break; - } - case RawSocketEvent.closed: - { - _sockSub.cancel(); - break; - } - case RawSocketEvent.readClosed: - // TODO: Handle this case. - Logging.instance.log( - "SOCKSSocket._start(): unhandled event RawSocketEvent.readClosed", - level: LogLevel.Warning); - break; - case RawSocketEvent.write: - // TODO: Handle this case. - - Logging.instance.log( - "SOCKSSocket._start(): unhandled event RawSocketEvent.write", - level: LogLevel.Warning); - break; - } - }); - } - - void _sendUsernamePassword(String uname, String password) { - if (uname.length > 255 || password.length > 255) { - throw "Username or Password is too long"; - } - - final data = [ - RFC1929Version, - uname.length, - ...const AsciiEncoder().convert(uname), - password.length, - ...const AsciiEncoder().convert(password) - ]; - - //print(">> Sending $username:$password"); - _sock.write(data); - } - - void _handleRead(Uint8List data) async { - if (state == SOCKSState.Auth) { - if (data.length == 2) { - // final version = data[0]; - //print("<< Version: $version, Auth: $auth"); - final auth = AuthMethods._(data[1]); - - if (auth._value == AuthMethods.UsernamePassword._value) { - _setState(SOCKSState.AuthStarted); - _sendUsernamePassword(username ?? '', password ?? ''); - // TODO check that passing an empty string is valid (vs. null previously) - } else if (auth._value == AuthMethods.NoAuth._value) { - _setState(SOCKSState.RequestReady); - _writeRequest(_request); - } else if (auth._value == AuthMethods.NoAcceptableMethods._value) { - throw "No auth methods acceptable"; - } - } else { - throw "Expected 2 bytes"; - } - } else if (_state == SOCKSState.AuthStarted) { - if (_auth.contains(AuthMethods.UsernamePassword)) { - final version = data[0]; - final status = data[1]; - - if (version != RFC1929Version || status != 0x00) { - throw "Invalid username or password"; - } else { - _setState(SOCKSState.RequestReady); - _writeRequest(_request); - } - } - } else if (_state == SOCKSState.RequestReady) { - if (data.length >= 10) { - final reply = SOCKSReply._(data[1]); - //data[2] reserved - - final version = data[0]; - final addrType = SOCKSAddressType._(data[3]); - Uint8List? addr; - var port = 0; - if (addrType == SOCKSAddressType.Domain) { - final len = data[4]; - addr = data.sublist(5, 5 + len); - port = data[5 + len] << 8 | data[6 + len]; - } else if (addrType == SOCKSAddressType.IPv4) { - addr = data.sublist(5, 9); - port = data[9] << 8 | data[10]; - } else if (addrType == SOCKSAddressType.IPv6) { - addr = data.sublist(5, 21); - port = data[21] << 8 | data[22]; - } - print( - "<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); - - if (reply._value == SOCKSReply.Success._value) { - _setState(SOCKSState.Connected); - } else { - throw reply; - } - } else { - throw "Expected 10 bytes"; - } - } - } - - void _writeRequest(SOCKSRequest req) { - if (_state == SOCKSState.RequestReady) { - final data = [ - req.version, - req.command._value, - 0x00, - req.addressType._value, - if (req.addressType == SOCKSAddressType.Domain) - req.address.lengthInBytes, - ...req.address, - req.port >> 8, - req.port & 0xF0, - ]; - - //print(">> Version: ${req.version}, Command: ${req.command}, AddrType: ${req.addressType}, Addr: ${req.getAddressString()}, Port: ${req.port}"); - _sock.write(data); - } else { - throw "Must be in RequestReady state, current state $_state"; - } - } - - void write(Object? object) { - _sock.write(utf8.encode(object.toString())); - // TODO make sure the is correct; see _writeRequest above, may need to construct a SOCKSRequest from the data coming in - } -} diff --git a/lib/networking/socks_socket.dart b/lib/networking/socks_socket.dart new file mode 100644 index 000000000..a6d6371c2 --- /dev/null +++ b/lib/networking/socks_socket.dart @@ -0,0 +1,111 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +/// A SOCKS5 proxy client +class SOCKSSocket { + final String host; + final int port; + + late Socket _socksSocket; + Socket get socket => _socksSocket; + + final StreamController> _responseController = StreamController(); + + // TODO accept String host or InternetAddress host + SOCKSSocket({required this.host, required this.port}) { + _init(); + } + + /// Initializes the SOCKS socket. + Future _init() async { + _socksSocket = await Socket.connect( + host, + port, + ); + + _socksSocket.listen( + (data) { + _responseController.add(data); + }, + onError: (e) { + if (e is Object) { + _responseController.addError(e); + } + _responseController.addError("$e"); + // TODO make sure sending error as string is acceptable + }, + onDone: () { + _responseController.close(); + }, + ); + } + + /// Connects to the SOCKS socket. + Future connect() async { + _socksSocket = await Socket.connect(host, port); + + // Greeting and method selection + _socksSocket.add([0x05, 0x01, 0x00]); + + // Wait for server response + var response = await _socksSocket.first; + if (response[1] != 0x00) { + throw Exception('Failed to connect to SOCKS5 socket.'); + } + } + + /// Connects to the specified [domain] and [port] through the SOCKS socket. + Future connectTo(String domain, int port) async { + // Command, Reserved, Address Type, Address, Port + var request = [ + 0x05, + 0x01, + 0x00, + 0x03, + domain.length, + ...domain.codeUnits, + (port >> 8) & 0xFF, + port & 0xFF + ]; + + _socksSocket.add(request); + + if (await _responseController.stream.isEmpty) { + throw Exception( + 'Stream has no data: Failed to connect to target through SOCKS5 proxy.'); + } + + // // Wait for server response + // var response; + // try { + // response = await _responseController.stream.first + // .timeout(const Duration(seconds: 10), onTimeout: () { + // throw TimeoutException( + // 'Failed to get response from the server within 10 seconds.'); + // }); + // } catch (e) { + // throw Exception('Failed to connect to target through SOCKS5 proxy: $e'); + // } + var response = await _responseController.stream.first; + if (response[1] != 0x00) { + throw Exception('Failed to connect to target through SOCKS5 proxy.'); + } + } + + /// Converts [object] to a String by invoking [Object.toString] and + /// sends the encoding of the result to the socket. + void write(Object? object) { + if (object == null) return; + + List data = utf8.encode(object.toString()); + _socksSocket.add(data); + } + + /// Closes the connection to the Tor proxy. + Future close() async { + await _socksSocket.flush(); // Ensure all data is sent before closing + await _responseController.close(); + return await _socksSocket.close(); + } +} From ed99bdc16960af1cb215d97bbd8a35f1419ed930 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 10 Aug 2023 11:40:12 -0500 Subject: [PATCH 072/237] Revert "clean up SOCKSSocket, still no joy" This reverts commit c7ea583a442bf59ffe7fb243a77a8b43158bccfa. --- lib/electrumx_rpc/rpc.dart | 266 +++++++++++++-------- lib/networking/socks5.dart | 395 +++++++++++++++++++++++++++++++ lib/networking/socks_socket.dart | 111 --------- 3 files changed, 564 insertions(+), 208 deletions(-) create mode 100644 lib/networking/socks5.dart delete mode 100644 lib/networking/socks_socket.dart diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index c90d66293..94038e8d3 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -14,7 +14,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; -import 'package:stackwallet/networking/socks_socket.dart'; +import 'package:stackwallet/networking/socks5.dart'; import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; @@ -38,6 +38,7 @@ class JsonRPC { final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); Socket? _socket; SOCKSSocket? _socksSocket; + SOCKS5Proxy? _socksProxy; StreamSubscription? _subscription; void _dataHandler(List data) { @@ -80,18 +81,22 @@ class JsonRPC { void _sendNextAvailableRequest() { _requestQueue.nextIncompleteReq.then((req) { if (req != null) { - // TODO check if useTor to determine socket to which to write // \r\n required by electrumx server if (_socket != null) { _socket!.write('${req.jsonRequest}\r\n'); } if (_socksSocket != null) { - Logging.instance.log( - "writing to _socksSocket: ${req.jsonRequest}", - level: LogLevel.Info, - ); + print('writing to _socksSocket: ${req.jsonRequest}'); + print(req.jsonRequest); + print(req); _socksSocket!.write('${req.jsonRequest}\r\n'); } + if (_socksProxy != null) { + print('writing to _socksProxy: ${req.jsonRequest}'); + print(req.jsonRequest); + print(req); + _socksProxy!.write('${req.jsonRequest}\r\n'); + } // TODO different timeout length? req.initiateTimeout( @@ -111,15 +116,22 @@ class JsonRPC { if (!Prefs.instance.useTor) { if (_socket == null) { Logging.instance.log( - "JsonRPC request: opening direct socket $host:$port", + "JsonRPC request: opening socket $host:$port", level: LogLevel.Info, ); - await connect(); + // await connect(); } } else { - if (_socksSocket == null) { + // if (_socksSocket == null) { + // Logging.instance.log( + // "JsonRPC request: opening SOCKS socket to $host:$port", + // level: LogLevel.Info, + // ); + // await connect(); + // } + if (_socksProxy == null) { Logging.instance.log( - "JsonRPC request: opening SOCKS socket to $host:$port", + "JsonRPC request: opening SOCKS proxy to $host:$port", level: LogLevel.Info, ); await connect(); @@ -163,8 +175,8 @@ class JsonRPC { _subscription = null; _socket?.destroy(); _socket = null; - unawaited(_socksSocket?.close()); - // TODO check that we can safely unawaited this + unawaited(_socksSocket?.close(keepOpen: false)); + // TODO check that it's ok to not await this _socksSocket = null; // clean up remaining queue @@ -198,98 +210,158 @@ class JsonRPC { cancelOnError: true, ); } else { - if (proxyInfo == null) { - // TODO await tor / make sure it's running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port + if (_socksProxy == null) { + print(1111111); + _socksProxy = SOCKS5Proxy(); + // TODO check if null + await _socksProxy!.connect(); + print(222222); + // TODO check if null + await _socksProxy!.connectTo('bitcoincash.stackwallet.com', 50002); + + print(333333); + + // TODO check if null + _subscription = _socksProxy!.socket.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, ); - Logging.instance.log( - "ElectrumX.connect(): no tor proxy info, read $proxyInfo", - level: LogLevel.Warning); - } - // TODO connect to proxy socket... - - // TODO implement ssl over tor - // if (useSSL) { - // _socket = await SecureSocket.connect( - // host, - // port, - // timeout: connectionTimeout, - // onBadCertificate: (_) => true, - // ); // TODO do not automatically trust bad certificates - // final _client = SocksSocket.protected(_socket, type); - // } else { - // set up socks socket - if (_socksSocket == null) { - Logging.instance.log( - "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", - level: LogLevel.Info); - _socksSocket = - SOCKSSocket(host: proxyInfo!.host, port: proxyInfo!.port); - if (_socksSocket == null) { - Logging.instance.log( - "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", - level: LogLevel.Error); - throw Exception( - "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); - } else { - Logging.instance.log( - "JsonRPC.connect(): created SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } } else { - // TODO also check if sock == previous sock, eg. if RawSocket is different, and if _socksSocket is valid - Logging.instance.log( - "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", - level: LogLevel.Info); + print('0000000'); } - - // connect to socks socket - try { - Logging.instance.log( - "JsonRPC.connect(): connecting to SOCKS socket at $proxyInfo...", - level: LogLevel.Info); - await _socksSocket!.connect(); - Logging.instance.log( - "JsonRPC.connect(): connected to SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } catch (e) { - Logging.instance.log( - "JsonRPC.connect(): failed to connect to SOCKS socket at $proxyInfo, $e", - level: LogLevel.Error); - throw Exception( - "JsonRPC.connect(): failed to connect to SOCKS socket, $e"); - } - - // connect to node through socks socket - try { - Logging.instance.log( - "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", - level: LogLevel.Info); - await _socksSocket!.connectTo(host, port); - Logging.instance.log( - "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } catch (e) { - Logging.instance.log( - "JsonRPC.connect(): failed to connect to $host over SOCKS socket at $proxyInfo, $e", - level: LogLevel.Error); - throw Exception( - "JsonRPC.connect(): failed to connect to $host over SOCKS socket, $e"); - } - - // TODO check if null - _subscription = _socksSocket!.socket.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, - ); + // if (proxyInfo == null) { + // // TODO await tor / make sure it's running + // proxyInfo = ( + // host: InternetAddress.loopbackIPv4.address, + // port: TorService.sharedInstance.port + // ); + // Logging.instance.log( + // "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + // level: LogLevel.Warning); + // } + // // TODO connect to proxy socket... + // + // // TODO implement ssl over tor + // // if (useSSL) { + // // _socket = await SecureSocket.connect( + // // host, + // // port, + // // timeout: connectionTimeout, + // // onBadCertificate: (_) => true, + // // ); // TODO do not automatically trust bad certificates + // // final _client = SocksSocket.protected(_socket, type); + // // } else { + // final sock = await RawSocket.connect( + // InternetAddress.loopbackIPv4, proxyInfo!.port); + // + // if (_socksSocket == null) { + // Logging.instance.log( + // "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", + // level: LogLevel.Info); + // _socksSocket = SOCKSSocket(sock); + // if (_socksSocket == null) { + // Logging.instance.log( + // "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", + // level: LogLevel.Error); + // throw Exception( + // "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); + // } else { + // Logging.instance.log( + // "JsonRPC.connect(): created SOCKS socket at $proxyInfo", + // level: LogLevel.Info); + // } + // } else { + // // TODO also check if sock == previous sock, eg. if RawSocket is different + // Logging.instance.log( + // "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", + // level: LogLevel.Info); + // } + // + // try { + // Logging.instance.log( + // "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", + // level: LogLevel.Info); + // if (!isIpAddress(host)) { + // await _socksSocket!.connect("$host:$port"); + // } else { + // await _socksSocket!.connectIp(InternetAddress(host), port); + // } + // Logging.instance.log( + // "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", + // level: LogLevel.Info); + // } catch (e) { + // Logging.instance.log( + // "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", + // level: LogLevel.Error); + // throw Exception( + // "JsonRPC.connect(): failed to connect to tor proxy, $e"); + // } } } } +class SOCKS5Proxy { + final String host; + final int port; + + late Socket _socks5Socket; + Socket get socket => _socks5Socket; + + SOCKS5Proxy({String? host, int? port}) + : host = host ?? InternetAddress.loopbackIPv4.address, + port = port ?? TorService.sharedInstance.port; + + Future connect() async { + _socks5Socket = await Socket.connect(host, port); + + // Greeting and method selection + _socks5Socket.add([0x05, 0x01, 0x00]); + + // Wait for server response + var response = await _socks5Socket.first; + if (response[1] != 0x00) { + throw Exception('Failed to connect to SOCKS5 proxy.'); + } + } + + // This is just a basic example for domain-based addresses. + Future connectTo(String domain, int port) async { + // Command, Reserved, Address Type, Address, Port + var request = [ + 0x05, + 0x01, + 0x00, + 0x03, + domain.length, + ...domain.codeUnits, + (port >> 8) & 0xFF, + port & 0xFF + ]; + + _socks5Socket.add(request); + print(444444); + + // Wait for server response + // var response = await _socks5Socket.first; + // if (response[1] != 0x00) { + // throw Exception('Failed to connect to target through SOCKS5 proxy.'); + // } + // print(response); + print(55555); + } + + /// Converts [object] to a String by invoking [Object.toString] and + /// sends the encoding of the result to the socket. + void write(Object? object) { + if (object == null) return; + + List data = utf8.encode(object.toString()); + _socks5Socket.add(data); + } +} + class _JsonRPCRequestQueue { final _lock = Mutex(); final List<_JsonRPCRequest> _rq = []; diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart new file mode 100644 index 000000000..619685381 --- /dev/null +++ b/lib/networking/socks5.dart @@ -0,0 +1,395 @@ +// https://github.com/v0l/socks5 https://pub.dev/packages/socks5 for Dart 3 + +// library socks; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:stackwallet/utilities/logger.dart'; + +/// https://tools.ietf.org/html/rfc1928 +/// https://tools.ietf.org/html/rfc1929 + +const SOCKSVersion = 0x05; +const RFC1929Version = 0x01; + +class AuthMethods { + static const NoAuth = AuthMethods._(0x00); + static const GSSApi = AuthMethods._(0x01); + static const UsernamePassword = AuthMethods._(0x02); + static const NoAcceptableMethods = AuthMethods._(0xFF); + + final int _value; + + const AuthMethods._(this._value); + + @override + String toString() { + return const { + 0x00: 'AuthMethods.NoAuth', + 0x01: 'AuthMethods.GSSApi', + 0x02: 'AuthMethods.UsernamePassword', + 0xFF: 'AuthMethods.NoAcceptableMethods' + }[_value] ?? + 'Unknown AuthMethod'; + } +} + +class SOCKSState { + static const Starting = SOCKSState._(0x00); + static const Auth = SOCKSState._(0x01); + static const RequestReady = SOCKSState._(0x02); + static const Connected = SOCKSState._(0x03); + static const AuthStarted = SOCKSState._(0x04); + + final int _value; + + const SOCKSState._(this._value); + + @override + String toString() { + return const [ + 'SOCKSState.Starting', + 'SOCKSState.Auth', + 'SOCKSState.RequestReady', + 'SOCKSState.Connected', + 'SOCKSState.AuthStarted' + ][_value]; + } +} + +class SOCKSAddressType { + static const IPv4 = SOCKSAddressType._(0x01); + static const Domain = SOCKSAddressType._(0x03); + static const IPv6 = SOCKSAddressType._(0x04); + + final int _value; + + const SOCKSAddressType._(this._value); + + @override + String toString() { + return const [ + null, + 'SOCKSAddressType.IPv4', + null, + 'SOCKSAddressType.Domain', + 'SOCKSAddressType.IPv6', + ][_value] ?? + 'Unknown SOCKSAddressType'; + } +} + +class SOCKSCommand { + static const Connect = SOCKSCommand._(0x01); + static const Bind = SOCKSCommand._(0x02); + static const UDPAssociate = SOCKSCommand._(0x03); + + final int _value; + + const SOCKSCommand._(this._value); + + @override + String toString() { + return const [ + null, + 'SOCKSCommand.Connect', + 'SOCKSCommand.Bind', + 'SOCKSCommand.UDPAssociate', + ][_value] ?? + 'Unknown SOCKSCommand'; + } +} + +class SOCKSReply { + static const Success = SOCKSReply._(0x00); + static const GeneralFailure = SOCKSReply._(0x01); + static const ConnectionNotAllowedByRuleset = SOCKSReply._(0x02); + static const NetworkUnreachable = SOCKSReply._(0x03); + static const HostUnreachable = SOCKSReply._(0x04); + static const ConnectionRefused = SOCKSReply._(0x05); + static const TTLExpired = SOCKSReply._(0x06); + static const CommandNotSupported = SOCKSReply._(0x07); + static const AddressTypeNotSupported = SOCKSReply._(0x08); + + final int _value; + + const SOCKSReply._(this._value); + + @override + String toString() { + return const [ + 'SOCKSReply.Success', + 'SOCKSReply.GeneralFailure', + 'SOCKSReply.ConnectionNotAllowedByRuleset', + 'SOCKSReply.NetworkUnreachable', + 'SOCKSReply.HostUnreachable', + 'SOCKSReply.ConnectionRefused', + 'SOCKSReply.TTLExpired', + 'SOCKSReply.CommandNotSupported', + 'SOCKSReply.AddressTypeNotSupported' + ][_value]; + } +} + +class SOCKSRequest { + final int version = SOCKSVersion; + final SOCKSCommand command; + final SOCKSAddressType addressType; + final Uint8List address; + final int port; + + String? getAddressString() { + if (addressType == SOCKSAddressType.Domain) { + return const AsciiDecoder().convert(address); + } else if (addressType == SOCKSAddressType.IPv4) { + return address.join("."); + } else if (addressType == SOCKSAddressType.IPv6) { + var ret = []; + for (var x = 0; x < address.length; x += 2) { + ret.add( + "${address[x].toRadixString(16).padLeft(2, "0")}${address[x + 1].toRadixString(16).padLeft(2, "0")}"); + } + return ret.join(":"); + } + return null; + } + + SOCKSRequest({ + required this.command, + required this.addressType, + required this.address, + required this.port, + }); +} + +class SOCKSSocket { + late List _auth; + late RawSocket _sock; + late SOCKSRequest _request; + + late StreamSubscription _sockSub; + StreamSubscription get subscription => _sockSub; + + late SOCKSState _state; + final StreamController _stateStream = + StreamController(); + SOCKSState get state => _state; + Stream get stateStream => _stateStream.stream; + + /// For username:password auth + final String? username; + final String? password; + + /// Waits for state to change to [SOCKSState.Connected] + /// If the connection request returns an error from the + /// socks server it will be thrown as an exception in the stream + /// + /// + Future get _waitForConnect => + stateStream.firstWhere((a) => a == SOCKSState.Connected); + + SOCKSSocket( + RawSocket socket, { + List auth = const [AuthMethods.NoAuth], + this.username, + this.password, + }) { + _sock = socket; + _auth = auth; + _setState(SOCKSState.Starting); + } + + void _setState(SOCKSState ns) { + _state = ns; + _stateStream.add(ns); + } + + /// Issue connect command to proxy + /// + Future connect(String domain) async { + final ds = domain.split(':'); + assert(ds.length == 2, "Domain must contain port, example.com:80"); + + _request = SOCKSRequest( + command: SOCKSCommand.Connect, + addressType: SOCKSAddressType.Domain, + address: const AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length), + port: int.tryParse(ds[1]) ?? 80, + ); + await _start(); + await _waitForConnect; + } + + Future connectIp(InternetAddress ip, int port) async { + _request = SOCKSRequest( + command: SOCKSCommand.Connect, + addressType: ip.type == InternetAddressType.IPv4 + ? SOCKSAddressType.IPv4 + : SOCKSAddressType.IPv6, + address: ip.rawAddress, + port: port, + ); + await _start(); + await _waitForConnect; + } + + Future close({bool keepOpen = true}) async { + await _stateStream.close(); + if (!keepOpen) { + await _sock.close(); + } + } + + Future _start() async { + // send auth methods + _setState(SOCKSState.Auth); + //print(">> Version: 5, AuthMethods: $_auth"); + _sock.write([ + 0x05, + _auth.length, + ..._auth.map((v) => v._value), + ]); + + _sockSub = _sock.listen((RawSocketEvent ev) { + switch (ev) { + case RawSocketEvent.read: + { + final have = _sock.available(); + final data = _sock.read(have); + if (data != null) _handleRead(data); + break; + } + case RawSocketEvent.closed: + { + _sockSub.cancel(); + break; + } + case RawSocketEvent.readClosed: + // TODO: Handle this case. + Logging.instance.log( + "SOCKSSocket._start(): unhandled event RawSocketEvent.readClosed", + level: LogLevel.Warning); + break; + case RawSocketEvent.write: + // TODO: Handle this case. + + Logging.instance.log( + "SOCKSSocket._start(): unhandled event RawSocketEvent.write", + level: LogLevel.Warning); + break; + } + }); + } + + void _sendUsernamePassword(String uname, String password) { + if (uname.length > 255 || password.length > 255) { + throw "Username or Password is too long"; + } + + final data = [ + RFC1929Version, + uname.length, + ...const AsciiEncoder().convert(uname), + password.length, + ...const AsciiEncoder().convert(password) + ]; + + //print(">> Sending $username:$password"); + _sock.write(data); + } + + void _handleRead(Uint8List data) async { + if (state == SOCKSState.Auth) { + if (data.length == 2) { + // final version = data[0]; + //print("<< Version: $version, Auth: $auth"); + final auth = AuthMethods._(data[1]); + + if (auth._value == AuthMethods.UsernamePassword._value) { + _setState(SOCKSState.AuthStarted); + _sendUsernamePassword(username ?? '', password ?? ''); + // TODO check that passing an empty string is valid (vs. null previously) + } else if (auth._value == AuthMethods.NoAuth._value) { + _setState(SOCKSState.RequestReady); + _writeRequest(_request); + } else if (auth._value == AuthMethods.NoAcceptableMethods._value) { + throw "No auth methods acceptable"; + } + } else { + throw "Expected 2 bytes"; + } + } else if (_state == SOCKSState.AuthStarted) { + if (_auth.contains(AuthMethods.UsernamePassword)) { + final version = data[0]; + final status = data[1]; + + if (version != RFC1929Version || status != 0x00) { + throw "Invalid username or password"; + } else { + _setState(SOCKSState.RequestReady); + _writeRequest(_request); + } + } + } else if (_state == SOCKSState.RequestReady) { + if (data.length >= 10) { + final reply = SOCKSReply._(data[1]); + //data[2] reserved + + final version = data[0]; + final addrType = SOCKSAddressType._(data[3]); + Uint8List? addr; + var port = 0; + if (addrType == SOCKSAddressType.Domain) { + final len = data[4]; + addr = data.sublist(5, 5 + len); + port = data[5 + len] << 8 | data[6 + len]; + } else if (addrType == SOCKSAddressType.IPv4) { + addr = data.sublist(5, 9); + port = data[9] << 8 | data[10]; + } else if (addrType == SOCKSAddressType.IPv6) { + addr = data.sublist(5, 21); + port = data[21] << 8 | data[22]; + } + print( + "<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); + + if (reply._value == SOCKSReply.Success._value) { + _setState(SOCKSState.Connected); + } else { + throw reply; + } + } else { + throw "Expected 10 bytes"; + } + } + } + + void _writeRequest(SOCKSRequest req) { + if (_state == SOCKSState.RequestReady) { + final data = [ + req.version, + req.command._value, + 0x00, + req.addressType._value, + if (req.addressType == SOCKSAddressType.Domain) + req.address.lengthInBytes, + ...req.address, + req.port >> 8, + req.port & 0xF0, + ]; + + //print(">> Version: ${req.version}, Command: ${req.command}, AddrType: ${req.addressType}, Addr: ${req.getAddressString()}, Port: ${req.port}"); + _sock.write(data); + } else { + throw "Must be in RequestReady state, current state $_state"; + } + } + + void write(Object? object) { + _sock.write(utf8.encode(object.toString())); + // TODO make sure the is correct; see _writeRequest above, may need to construct a SOCKSRequest from the data coming in + } +} diff --git a/lib/networking/socks_socket.dart b/lib/networking/socks_socket.dart deleted file mode 100644 index a6d6371c2..000000000 --- a/lib/networking/socks_socket.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -/// A SOCKS5 proxy client -class SOCKSSocket { - final String host; - final int port; - - late Socket _socksSocket; - Socket get socket => _socksSocket; - - final StreamController> _responseController = StreamController(); - - // TODO accept String host or InternetAddress host - SOCKSSocket({required this.host, required this.port}) { - _init(); - } - - /// Initializes the SOCKS socket. - Future _init() async { - _socksSocket = await Socket.connect( - host, - port, - ); - - _socksSocket.listen( - (data) { - _responseController.add(data); - }, - onError: (e) { - if (e is Object) { - _responseController.addError(e); - } - _responseController.addError("$e"); - // TODO make sure sending error as string is acceptable - }, - onDone: () { - _responseController.close(); - }, - ); - } - - /// Connects to the SOCKS socket. - Future connect() async { - _socksSocket = await Socket.connect(host, port); - - // Greeting and method selection - _socksSocket.add([0x05, 0x01, 0x00]); - - // Wait for server response - var response = await _socksSocket.first; - if (response[1] != 0x00) { - throw Exception('Failed to connect to SOCKS5 socket.'); - } - } - - /// Connects to the specified [domain] and [port] through the SOCKS socket. - Future connectTo(String domain, int port) async { - // Command, Reserved, Address Type, Address, Port - var request = [ - 0x05, - 0x01, - 0x00, - 0x03, - domain.length, - ...domain.codeUnits, - (port >> 8) & 0xFF, - port & 0xFF - ]; - - _socksSocket.add(request); - - if (await _responseController.stream.isEmpty) { - throw Exception( - 'Stream has no data: Failed to connect to target through SOCKS5 proxy.'); - } - - // // Wait for server response - // var response; - // try { - // response = await _responseController.stream.first - // .timeout(const Duration(seconds: 10), onTimeout: () { - // throw TimeoutException( - // 'Failed to get response from the server within 10 seconds.'); - // }); - // } catch (e) { - // throw Exception('Failed to connect to target through SOCKS5 proxy: $e'); - // } - var response = await _responseController.stream.first; - if (response[1] != 0x00) { - throw Exception('Failed to connect to target through SOCKS5 proxy.'); - } - } - - /// Converts [object] to a String by invoking [Object.toString] and - /// sends the encoding of the result to the socket. - void write(Object? object) { - if (object == null) return; - - List data = utf8.encode(object.toString()); - _socksSocket.add(data); - } - - /// Closes the connection to the Tor proxy. - Future close() async { - await _socksSocket.flush(); // Ensure all data is sent before closing - await _responseController.close(); - return await _socksSocket.close(); - } -} From 5cccd3e4a3792351782e413ee2264dc0dd924c1e Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 9 Aug 2023 18:28:19 -0500 Subject: [PATCH 073/237] Revert "WIP very messy" This reverts commit 84927734389251ac74e6ea084010326e7f679bd5. --- lib/electrumx_rpc/rpc.dart | 244 +++++++++++-------------------------- lib/networking/socks5.dart | 1 - 2 files changed, 73 insertions(+), 172 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 94038e8d3..ecbdda49d 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -38,7 +38,6 @@ class JsonRPC { final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); Socket? _socket; SOCKSSocket? _socksSocket; - SOCKS5Proxy? _socksProxy; StreamSubscription? _subscription; void _dataHandler(List data) { @@ -86,17 +85,8 @@ class JsonRPC { _socket!.write('${req.jsonRequest}\r\n'); } if (_socksSocket != null) { - print('writing to _socksSocket: ${req.jsonRequest}'); - print(req.jsonRequest); - print(req); _socksSocket!.write('${req.jsonRequest}\r\n'); } - if (_socksProxy != null) { - print('writing to _socksProxy: ${req.jsonRequest}'); - print(req.jsonRequest); - print(req); - _socksProxy!.write('${req.jsonRequest}\r\n'); - } // TODO different timeout length? req.initiateTimeout( @@ -119,19 +109,12 @@ class JsonRPC { "JsonRPC request: opening socket $host:$port", level: LogLevel.Info, ); - // await connect(); + await connect(); } } else { - // if (_socksSocket == null) { - // Logging.instance.log( - // "JsonRPC request: opening SOCKS socket to $host:$port", - // level: LogLevel.Info, - // ); - // await connect(); - // } - if (_socksProxy == null) { + if (_socksSocket == null) { Logging.instance.log( - "JsonRPC request: opening SOCKS proxy to $host:$port", + "JsonRPC request: opening SOCKS socket to $host:$port", level: LogLevel.Info, ); await connect(); @@ -202,163 +185,82 @@ class JsonRPC { timeout: connectionTimeout, ); } - - _subscription = _socket!.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, - ); } else { - if (_socksProxy == null) { - print(1111111); - _socksProxy = SOCKS5Proxy(); - // TODO check if null - await _socksProxy!.connect(); - print(222222); - // TODO check if null - await _socksProxy!.connectTo('bitcoincash.stackwallet.com', 50002); - - print(333333); - - // TODO check if null - _subscription = _socksProxy!.socket.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, + if (proxyInfo == null) { + // TODO await tor / make sure it's running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port ); - } else { - print('0000000'); + Logging.instance.log( + "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); } - // if (proxyInfo == null) { - // // TODO await tor / make sure it's running - // proxyInfo = ( - // host: InternetAddress.loopbackIPv4.address, - // port: TorService.sharedInstance.port - // ); - // Logging.instance.log( - // "ElectrumX.connect(): no tor proxy info, read $proxyInfo", - // level: LogLevel.Warning); - // } - // // TODO connect to proxy socket... - // - // // TODO implement ssl over tor - // // if (useSSL) { - // // _socket = await SecureSocket.connect( - // // host, - // // port, - // // timeout: connectionTimeout, - // // onBadCertificate: (_) => true, - // // ); // TODO do not automatically trust bad certificates - // // final _client = SocksSocket.protected(_socket, type); - // // } else { - // final sock = await RawSocket.connect( - // InternetAddress.loopbackIPv4, proxyInfo!.port); - // - // if (_socksSocket == null) { - // Logging.instance.log( - // "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", - // level: LogLevel.Info); - // _socksSocket = SOCKSSocket(sock); - // if (_socksSocket == null) { - // Logging.instance.log( - // "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", - // level: LogLevel.Error); - // throw Exception( - // "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); - // } else { - // Logging.instance.log( - // "JsonRPC.connect(): created SOCKS socket at $proxyInfo", - // level: LogLevel.Info); - // } + // TODO connect to proxy socket... + + // TODO implement ssl over tor + // if (useSSL) { + // _socket = await SecureSocket.connect( + // host, + // port, + // timeout: connectionTimeout, + // onBadCertificate: (_) => true, + // ); // TODO do not automatically trust bad certificates + // final _client = SocksSocket.protected(_socket, type); // } else { - // // TODO also check if sock == previous sock, eg. if RawSocket is different - // Logging.instance.log( - // "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", - // level: LogLevel.Info); - // } - // - // try { - // Logging.instance.log( - // "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", - // level: LogLevel.Info); - // if (!isIpAddress(host)) { - // await _socksSocket!.connect("$host:$port"); - // } else { - // await _socksSocket!.connectIp(InternetAddress(host), port); - // } - // Logging.instance.log( - // "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", - // level: LogLevel.Info); - // } catch (e) { - // Logging.instance.log( - // "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", - // level: LogLevel.Error); - // throw Exception( - // "JsonRPC.connect(): failed to connect to tor proxy, $e"); - // } + final sock = await RawSocket.connect( + InternetAddress.loopbackIPv4, proxyInfo!.port); + + if (_socksSocket == null) { + Logging.instance.log( + "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", + level: LogLevel.Info); + _socksSocket = SOCKSSocket(sock); + if (_socksSocket == null) { + Logging.instance.log( + "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); + } else { + Logging.instance.log( + "JsonRPC.connect(): created SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } + } else { + // TODO also check if sock == previous sock, eg. if RawSocket is different + Logging.instance.log( + "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } + + try { + Logging.instance.log( + "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", + level: LogLevel.Info); + if (!isIpAddress(host)) { + await _socksSocket!.connect("$host:$port"); + } else { + await _socksSocket!.connectIp(InternetAddress(host), port); + } + Logging.instance.log( + "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } catch (e) { + Logging.instance.log( + "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to connect to tor proxy, $e"); + } } - } -} -class SOCKS5Proxy { - final String host; - final int port; - - late Socket _socks5Socket; - Socket get socket => _socks5Socket; - - SOCKS5Proxy({String? host, int? port}) - : host = host ?? InternetAddress.loopbackIPv4.address, - port = port ?? TorService.sharedInstance.port; - - Future connect() async { - _socks5Socket = await Socket.connect(host, port); - - // Greeting and method selection - _socks5Socket.add([0x05, 0x01, 0x00]); - - // Wait for server response - var response = await _socks5Socket.first; - if (response[1] != 0x00) { - throw Exception('Failed to connect to SOCKS5 proxy.'); - } - } - - // This is just a basic example for domain-based addresses. - Future connectTo(String domain, int port) async { - // Command, Reserved, Address Type, Address, Port - var request = [ - 0x05, - 0x01, - 0x00, - 0x03, - domain.length, - ...domain.codeUnits, - (port >> 8) & 0xFF, - port & 0xFF - ]; - - _socks5Socket.add(request); - print(444444); - - // Wait for server response - // var response = await _socks5Socket.first; - // if (response[1] != 0x00) { - // throw Exception('Failed to connect to target through SOCKS5 proxy.'); - // } - // print(response); - print(55555); - } - - /// Converts [object] to a String by invoking [Object.toString] and - /// sends the encoding of the result to the socket. - void write(Object? object) { - if (object == null) return; - - List data = utf8.encode(object.toString()); - _socks5Socket.add(data); + _subscription = _socket!.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } } diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart index 619685381..18feb9b18 100644 --- a/lib/networking/socks5.dart +++ b/lib/networking/socks5.dart @@ -275,7 +275,6 @@ class SOCKSSocket { break; case RawSocketEvent.write: // TODO: Handle this case. - Logging.instance.log( "SOCKSSocket._start(): unhandled event RawSocketEvent.write", level: LogLevel.Warning); From 1a59a1a577bbf9d078c5d1678bb706394c8f6a0b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 10 Aug 2023 16:32:13 -0500 Subject: [PATCH 074/237] simplify WIP code removing unneeded logging. may as well be printing at this point --- lib/electrumx_rpc/rpc.dart | 57 ++++++++++++++++++-------------------- lib/networking/socks5.dart | 8 ++++-- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index ecbdda49d..497e101bb 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -39,6 +39,7 @@ class JsonRPC { Socket? _socket; SOCKSSocket? _socksSocket; StreamSubscription? _subscription; + StreamSubscription? get subscription => _subscription; void _dataHandler(List data) { _requestQueue.nextIncompleteReq.then((req) { @@ -85,6 +86,7 @@ class JsonRPC { _socket!.write('${req.jsonRequest}\r\n'); } if (_socksSocket != null) { + print(33333333); _socksSocket!.write('${req.jsonRequest}\r\n'); } @@ -185,6 +187,13 @@ class JsonRPC { timeout: connectionTimeout, ); } + + _subscription = _socket!.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } else { if (proxyInfo == null) { // TODO await tor / make sure it's running @@ -210,29 +219,7 @@ class JsonRPC { // } else { final sock = await RawSocket.connect( InternetAddress.loopbackIPv4, proxyInfo!.port); - - if (_socksSocket == null) { - Logging.instance.log( - "JsonRPC.connect(): creating SOCKS socket at $proxyInfo", - level: LogLevel.Info); - _socksSocket = SOCKSSocket(sock); - if (_socksSocket == null) { - Logging.instance.log( - "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo", - level: LogLevel.Error); - throw Exception( - "JsonRPC.connect(): failed to create SOCKS socket at $proxyInfo"); - } else { - Logging.instance.log( - "JsonRPC.connect(): created SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } - } else { - // TODO also check if sock == previous sock, eg. if RawSocket is different - Logging.instance.log( - "JsonRPC.connect(): using pre-existing SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } + _socksSocket = SOCKSSocket(sock); try { Logging.instance.log( @@ -253,14 +240,24 @@ class JsonRPC { throw Exception( "JsonRPC.connect(): failed to connect to tor proxy, $e"); } - } - _subscription = _socket!.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, - ); + // _subscription = _socksSocket!.socket.listen( + // _dataHandler, + // onError: _errorHandler, + // onDone: _doneHandler, + // cancelOnError: true, + // ) as StreamSubscription?; + + _socksSocket!.subscription.onData((RawSocketEvent event) { + /// [RawSocketEvent] messages are here + /// read from here.. + if (event == RawSocketEvent.read) { + final data = sock.read(sock.available()); + print(11111); + print(data); + } + }); + } } } diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart index 18feb9b18..4737ed640 100644 --- a/lib/networking/socks5.dart +++ b/lib/networking/socks5.dart @@ -168,6 +168,7 @@ class SOCKSRequest { class SOCKSSocket { late List _auth; late RawSocket _sock; + RawSocket get socket => _sock; late SOCKSRequest _request; late StreamSubscription _sockSub; @@ -380,15 +381,16 @@ class SOCKSSocket { req.port & 0xF0, ]; - //print(">> Version: ${req.version}, Command: ${req.command}, AddrType: ${req.addressType}, Addr: ${req.getAddressString()}, Port: ${req.port}"); + print( + ">> Version: ${req.version}, Command: ${req.command}, AddrType: ${req.addressType}, Addr: ${req.getAddressString()}, Port: ${req.port}"); _sock.write(data); } else { throw "Must be in RequestReady state, current state $_state"; } } - void write(Object? object) { - _sock.write(utf8.encode(object.toString())); + void write(String data) { + _sock.write(utf8.encode(data)); // TODO make sure the is correct; see _writeRequest above, may need to construct a SOCKSRequest from the data coming in } } From d785a2ef839bde2019faee65f407fc653ac1b5b1 Mon Sep 17 00:00:00 2001 From: likho Date: Mon, 14 Aug 2023 10:14:47 +0200 Subject: [PATCH 075/237] Fix error with Stellar pretty name not found --- lib/utilities/enums/coin_enum.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index 2e5062b6d..8db5d4843 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -502,6 +502,7 @@ Coin coinFromPrettyName(String name) { case "Stellar Testnet": case "stellarTestnet": + case "stellarTestNet": case "tStellar": return Coin.stellarTestNet; From a6d39418584cb884d4ba43a353d57af4d1cb1f2b Mon Sep 17 00:00:00 2001 From: likho Date: Mon, 14 Aug 2023 16:36:27 +0200 Subject: [PATCH 076/237] Fix send and refactoring --- lib/services/coins/tezos/tezos_wallet.dart | 92 ++++++++++++++-------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index e62a5afb0..3ecc94eb8 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; +import 'package:decimal/decimal.dart'; import 'package:http/http.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/db/isar/main_db.dart'; @@ -137,18 +138,26 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future confirmSend({required Map txData}) async { try { - final node = getCurrentNode().host + getCurrentNode().port.toString(); - final int amountInMicroTez = - ((int.parse((txData["recipientAmt"] as Amount).raw.toString()) * - 1000000)) - .round(); + + final amount = txData["recipientAmt"] as Amount; + final amountInMicroTez = + amount.decimal * Decimal.fromInt(1000000); + final microtezToInt = int.parse(amountInMicroTez.toString()); + final int feeInMicroTez = int.parse(txData["fee"].toString()); final String destinationAddress = txData["address"] as String; final secretKey = Keystore.fromMnemonic((await mnemonicString)!).secretKey; Logging.instance.log(secretKey, level: LogLevel.Info); final sourceKeyStore = Keystore.fromSecretKey(secretKey); - final client = TezartClient("${getCurrentNode().host}:${getCurrentNode().port}"); - final operation = await client.transferOperation(source: sourceKeyStore, destination: destinationAddress, amount: amountInMicroTez, customFee: feeInMicroTez); + final client = TezartClient(getCurrentNode().host); + //TODO - Update gas Limit + final operation = await client.transferOperation( + source: sourceKeyStore, + destination: destinationAddress, + amount: microtezToInt, + customFee: feeInMicroTez, + customGasLimit: 400 + ); await operation.executeAndMonitor(); // This line gives an error return Future.value(""); } catch (e) { @@ -189,7 +198,7 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { estimatedFee = feeRate; } Logging.instance.log("estimatedFee:$estimatedFee", level: LogLevel.Info); - return Amount(rawValue: BigInt.from(estimatedFee), fractionDigits: 6); + return Amount(rawValue: BigInt.from(estimatedFee), fractionDigits: coin.decimals); } @override @@ -347,33 +356,43 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateBalance() async { - var api = - "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/context/contracts/${await currentReceivingAddress}/balance"; - var theBalance = (await get(Uri.parse(api)).then((value) => value.body)) - .substring(1, - (await get(Uri.parse(api)).then((value) => value.body)).length - 2); - Logging.instance.log( - "Balance for ${await currentReceivingAddress}: $theBalance", - level: LogLevel.Info); - var balanceInAmount = Amount( - rawValue: BigInt.parse(theBalance.toString()), fractionDigits: 6); - _balance = Balance( - total: balanceInAmount, - spendable: balanceInAmount, - blockedTotal: Amount(rawValue: BigInt.parse("0"), fractionDigits: 6), - pendingSpendable: Amount(rawValue: BigInt.parse("0"), fractionDigits: 6), - ); - await updateCachedBalance(_balance!); + + try { + var api = + "${getCurrentNode().host}/chains/main/blocks/head/context/contracts/${await currentReceivingAddress}/balance"; + var theBalance = (await get(Uri.parse(api)).then((value) => value.body)) + .substring(1, + (await get(Uri.parse(api)).then((value) => value.body)).length - 2); + Logging.instance.log( + "Balance for ${await currentReceivingAddress}: $theBalance", + level: LogLevel.Info); + var balanceInAmount = Amount( + rawValue: BigInt.parse(theBalance.toString()), fractionDigits: coin.decimals); + _balance = Balance( + total: balanceInAmount, + spendable: balanceInAmount, + blockedTotal: Amount(rawValue: BigInt.parse("0"), fractionDigits: coin.decimals), + pendingSpendable: Amount(rawValue: BigInt.parse("0"), fractionDigits: coin.decimals), + ); + await updateCachedBalance(_balance!); + } catch (e, s) { + Logging.instance.log("ERROR GETTING BALANCE ${e.toString()}", level: LogLevel.Error); + } + } Future updateTransactions() async { + // TODO: Use node RPC instead of tzstats API var api = "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; var jsonResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + List> txs = []; + for (var tx in jsonResponse as List) { + if (tx[1] == "transaction") { - var txApi = "https://api.tzstats.com/explorer/op/${tx[2]}"; + var txApi = "https://api.tzstats.com/explorer/op/${tx[0]}"; //Get transactions by Unique Id, this way we will only get txs var txJsonResponse = jsonDecode(await get(Uri.parse(txApi)).then((value) => value.body)); // Check if list is larger than 1 (if it is, it's a batch transaction) if (!((txJsonResponse as List).length > 1)) { @@ -394,7 +413,7 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { amount: (float.parse(opJson["volume"].toString()) * 1000000).toInt(), amountString: Amount( rawValue: BigInt.parse((float.parse(opJson["volume"].toString()) * 1000000).toInt().toString()), - fractionDigits: 6 + fractionDigits: coin.decimals ).toJsonString(), fee: (float.parse(opJson["fee"].toString()) * 1000000).toInt(), height: int.parse(opJson["height"].toString()), @@ -427,13 +446,18 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateChainHeight() async { - var api = - "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell"; - var jsonParsedResponse = - jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); - final int intHeight = int.parse(jsonParsedResponse["level"].toString()); - Logging.instance.log("Chain height: $intHeight", level: LogLevel.Info); - await updateCachedChainHeight(intHeight); + try { + var api = + "${getCurrentNode().host}/chains/main/blocks/head/header/shell"; + var jsonParsedResponse = + jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + final int intHeight = int.parse(jsonParsedResponse["level"].toString()); + Logging.instance.log("Chain height: $intHeight", level: LogLevel.Info); + await updateCachedChainHeight(intHeight); + } catch (e, s) { + Logging.instance.log("GET CHAIN HEIGHT ERROR ${e.toString()}", level: LogLevel.Error); + } + } @override From 27e33f4deaecedca61200871937199d290ff3e97 Mon Sep 17 00:00:00 2001 From: Diego Salazar Date: Mon, 14 Aug 2023 11:49:20 -0600 Subject: [PATCH 077/237] Bump version (build 1.7.18, build 186) --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 9d9e842cf..bca5686c4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: Stack Wallet # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.7.17+185 +version: 1.7.18+186 environment: sdk: ">=3.0.2 <4.0.0" From de4d6952b7d5b792ab576acc15740a398f9a588f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 14 Aug 2023 12:14:53 -0600 Subject: [PATCH 078/237] fix build all script for linux --- scripts/linux/build_all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh index 9a119d0d6..1ba99c0bd 100755 --- a/scripts/linux/build_all.sh +++ b/scripts/linux/build_all.sh @@ -9,7 +9,7 @@ mkdir -p build (cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_monero_all.sh && ./build_sharedfile.sh ) & -(cd ../../crypto_plugins/tor/scripts/linux && ./build_all.sh ) & +(cd ../../crypto_plugins/flutter_libtor/scripts/linux && ./build_all.sh ) & wait echo "Done building" From 9bdadead67936b0e414fb667b96765e9ae09e281 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 14 Aug 2023 15:09:49 -0500 Subject: [PATCH 079/237] update flutter_libtor example to track latest changes feed in torDir instead of torConfig, return TorConfig (mostly for password) --- crypto_plugins/flutter_libtor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_libtor b/crypto_plugins/flutter_libtor index 7f5446969..7b8e6edf1 160000 --- a/crypto_plugins/flutter_libtor +++ b/crypto_plugins/flutter_libtor @@ -1 +1 @@ -Subproject commit 7f544696969aa0a2d47d1d79ead3107dd2cea27e +Subproject commit 7b8e6edf18094f45c4bbe50c6a1a98e1d57f1589 From 05726e45a9f8392acb0fe9d01722b957ed825b6d Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 14 Aug 2023 14:56:18 -0600 Subject: [PATCH 080/237] make proper enums --- lib/networking/socks5.dart | 339 +++++++++++++++++++------------------ 1 file changed, 171 insertions(+), 168 deletions(-) diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart index 4737ed640..ba655f3db 100644 --- a/lib/networking/socks5.dart +++ b/lib/networking/socks5.dart @@ -1,137 +1,132 @@ -// https://github.com/v0l/socks5 https://pub.dev/packages/socks5 for Dart 3 - -// library socks; - import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:stackwallet/utilities/logger.dart'; - /// https://tools.ietf.org/html/rfc1928 /// https://tools.ietf.org/html/rfc1929 +/// const SOCKSVersion = 0x05; const RFC1929Version = 0x01; -class AuthMethods { - static const NoAuth = AuthMethods._(0x00); - static const GSSApi = AuthMethods._(0x01); - static const UsernamePassword = AuthMethods._(0x02); - static const NoAcceptableMethods = AuthMethods._(0xFF); +enum AuthMethods { + NoAuth(0x00), + GSSApi(0x01), + UsernamePassword(0x02), + NoAcceptableMethods(0xFF); - final int _value; + final int rawValue; - const AuthMethods._(this._value); + const AuthMethods(this.rawValue); + + factory AuthMethods.fromValue(int value) { + for (final v in values) { + if (v.rawValue == value) { + return v; + } + } + throw UnsupportedError("Invalid AuthMethods value"); + } @override - String toString() { - return const { - 0x00: 'AuthMethods.NoAuth', - 0x01: 'AuthMethods.GSSApi', - 0x02: 'AuthMethods.UsernamePassword', - 0xFF: 'AuthMethods.NoAcceptableMethods' - }[_value] ?? - 'Unknown AuthMethod'; - } + String toString() => "$runtimeType.$name"; } -class SOCKSState { - static const Starting = SOCKSState._(0x00); - static const Auth = SOCKSState._(0x01); - static const RequestReady = SOCKSState._(0x02); - static const Connected = SOCKSState._(0x03); - static const AuthStarted = SOCKSState._(0x04); +enum SOCKSState { + Starting(0x00), + Auth(0x01), + RequestReady(0x02), + Connected(0x03), + AuthStarted(0x04); - final int _value; + final int rawValue; - const SOCKSState._(this._value); + const SOCKSState(this.rawValue); + + factory SOCKSState.fromValue(int value) { + for (final v in values) { + if (v.rawValue == value) { + return v; + } + } + throw UnsupportedError("Invalid SOCKSState value"); + } @override - String toString() { - return const [ - 'SOCKSState.Starting', - 'SOCKSState.Auth', - 'SOCKSState.RequestReady', - 'SOCKSState.Connected', - 'SOCKSState.AuthStarted' - ][_value]; - } + String toString() => "$runtimeType.$name"; } -class SOCKSAddressType { - static const IPv4 = SOCKSAddressType._(0x01); - static const Domain = SOCKSAddressType._(0x03); - static const IPv6 = SOCKSAddressType._(0x04); +enum SOCKSAddressType { + IPv4(0x01), + Domain(0x03), + IPv6(0x04); - final int _value; + final int rawValue; - const SOCKSAddressType._(this._value); + const SOCKSAddressType(this.rawValue); + + factory SOCKSAddressType.fromValue(int value) { + for (final v in values) { + if (v.rawValue == value) { + return v; + } + } + throw UnsupportedError("Invalid SOCKSAddressType value"); + } @override - String toString() { - return const [ - null, - 'SOCKSAddressType.IPv4', - null, - 'SOCKSAddressType.Domain', - 'SOCKSAddressType.IPv6', - ][_value] ?? - 'Unknown SOCKSAddressType'; - } + String toString() => "$runtimeType.$name"; } -class SOCKSCommand { - static const Connect = SOCKSCommand._(0x01); - static const Bind = SOCKSCommand._(0x02); - static const UDPAssociate = SOCKSCommand._(0x03); +enum SOCKSCommand { + Connect(0x01), + Bind(0x02), + UDPAssociate(0x03); - final int _value; + final int rawValue; - const SOCKSCommand._(this._value); + const SOCKSCommand(this.rawValue); + + factory SOCKSCommand.fromValue(int value) { + for (final v in values) { + if (v.rawValue == value) { + return v; + } + } + throw UnsupportedError("Invalid SOCKSCommand value"); + } @override - String toString() { - return const [ - null, - 'SOCKSCommand.Connect', - 'SOCKSCommand.Bind', - 'SOCKSCommand.UDPAssociate', - ][_value] ?? - 'Unknown SOCKSCommand'; - } + String toString() => "$runtimeType.$name"; } -class SOCKSReply { - static const Success = SOCKSReply._(0x00); - static const GeneralFailure = SOCKSReply._(0x01); - static const ConnectionNotAllowedByRuleset = SOCKSReply._(0x02); - static const NetworkUnreachable = SOCKSReply._(0x03); - static const HostUnreachable = SOCKSReply._(0x04); - static const ConnectionRefused = SOCKSReply._(0x05); - static const TTLExpired = SOCKSReply._(0x06); - static const CommandNotSupported = SOCKSReply._(0x07); - static const AddressTypeNotSupported = SOCKSReply._(0x08); +enum SOCKSReply { + Success(0x00), + GeneralFailure(0x01), + ConnectionNotAllowedByRuleSet(0x02), + NetworkUnreachable(0x03), + HostUnreachable(0x04), + ConnectionRefused(0x05), + TTLExpired(0x06), + CommandNotSupported(0x07), + AddressTypeNotSupported(0x08); - final int _value; + final int rawValue; - const SOCKSReply._(this._value); + const SOCKSReply(this.rawValue); + + factory SOCKSReply.fromValue(int value) { + for (final v in values) { + if (v.rawValue == value) { + return v; + } + } + throw UnsupportedError("Invalid SOCKSReply value"); + } @override - String toString() { - return const [ - 'SOCKSReply.Success', - 'SOCKSReply.GeneralFailure', - 'SOCKSReply.ConnectionNotAllowedByRuleset', - 'SOCKSReply.NetworkUnreachable', - 'SOCKSReply.HostUnreachable', - 'SOCKSReply.ConnectionRefused', - 'SOCKSReply.TTLExpired', - 'SOCKSReply.CommandNotSupported', - 'SOCKSReply.AddressTypeNotSupported' - ][_value]; - } + String toString() => "$runtimeType.$name"; } class SOCKSRequest { @@ -141,20 +136,20 @@ class SOCKSRequest { final Uint8List address; final int port; - String? getAddressString() { - if (addressType == SOCKSAddressType.Domain) { - return const AsciiDecoder().convert(address); - } else if (addressType == SOCKSAddressType.IPv4) { - return address.join("."); - } else if (addressType == SOCKSAddressType.IPv6) { - var ret = []; - for (var x = 0; x < address.length; x += 2) { - ret.add( - "${address[x].toRadixString(16).padLeft(2, "0")}${address[x + 1].toRadixString(16).padLeft(2, "0")}"); - } - return ret.join(":"); + String getAddressString() { + switch (addressType) { + case SOCKSAddressType.Domain: + return const AsciiDecoder().convert(address); + case SOCKSAddressType.IPv4: + return address.join("."); + case SOCKSAddressType.IPv6: + final List ret = []; + for (int x = 0; x < address.length; x += 2) { + ret.add("${address[x].toRadixString(16).padLeft(2, "0")}" + "${address[x + 1].toRadixString(16).padLeft(2, "0")}"); + } + return ret.join(":"); } - return null; } SOCKSRequest({ @@ -168,13 +163,12 @@ class SOCKSRequest { class SOCKSSocket { late List _auth; late RawSocket _sock; - RawSocket get socket => _sock; - late SOCKSRequest _request; + SOCKSRequest? _request; - late StreamSubscription _sockSub; - StreamSubscription get subscription => _sockSub; + StreamSubscription? _sockSub; + StreamSubscription? get subscription => _sockSub; - late SOCKSState _state; + SOCKSState _state = SOCKSState.Starting; final StreamController _stateStream = StreamController(); SOCKSState get state => _state; @@ -217,7 +211,7 @@ class SOCKSSocket { _request = SOCKSRequest( command: SOCKSCommand.Connect, addressType: SOCKSAddressType.Domain, - address: const AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length), + address: AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length), port: int.tryParse(ds[1]) ?? 80, ); await _start(); @@ -251,7 +245,7 @@ class SOCKSSocket { _sock.write([ 0x05, _auth.length, - ..._auth.map((v) => v._value), + ..._auth.map((v) => v.rawValue), ]); _sockSub = _sock.listen((RawSocketEvent ev) { @@ -260,26 +254,32 @@ class SOCKSSocket { { final have = _sock.available(); final data = _sock.read(have); - if (data != null) _handleRead(data); + if (data != null) { + _handleRead(data); + } else { + print("========= sock read DATA is NULL"); + } break; } case RawSocketEvent.closed: { - _sockSub.cancel(); + _sockSub?.cancel(); break; } - case RawSocketEvent.readClosed: - // TODO: Handle this case. - Logging.instance.log( - "SOCKSSocket._start(): unhandled event RawSocketEvent.readClosed", - level: LogLevel.Warning); - break; - case RawSocketEvent.write: - // TODO: Handle this case. - Logging.instance.log( - "SOCKSSocket._start(): unhandled event RawSocketEvent.write", - level: LogLevel.Warning); - break; + default: + print("AAAAAAAAAAAAA: unhandled raw socket event: $ev"); + // case RawSocketEvent.closed: + // // TODO: Handle this case. + // break; + // case RawSocketEvent.read: + // // TODO: Handle this case. + // break; + // case RawSocketEvent.readClosed: + // // TODO: Handle this case. + // break; + // case RawSocketEvent.write: + // // TODO: Handle this case. + // break; } }); } @@ -304,19 +304,23 @@ class SOCKSSocket { void _handleRead(Uint8List data) async { if (state == SOCKSState.Auth) { if (data.length == 2) { - // final version = data[0]; - //print("<< Version: $version, Auth: $auth"); - final auth = AuthMethods._(data[1]); + final version = data[0]; + final auth = AuthMethods.fromValue(data[1]); - if (auth._value == AuthMethods.UsernamePassword._value) { - _setState(SOCKSState.AuthStarted); - _sendUsernamePassword(username ?? '', password ?? ''); - // TODO check that passing an empty string is valid (vs. null previously) - } else if (auth._value == AuthMethods.NoAuth._value) { - _setState(SOCKSState.RequestReady); - _writeRequest(_request); - } else if (auth._value == AuthMethods.NoAcceptableMethods._value) { - throw "No auth methods acceptable"; + print("_handleRead << Version: $version, Auth: $auth"); + + switch (auth) { + case AuthMethods.UsernamePassword: + _setState(SOCKSState.AuthStarted); + _sendUsernamePassword(username ?? '', password ?? ''); + break; + case AuthMethods.NoAuth: + _setState(SOCKSState.RequestReady); + _writeRequest(_request!); + + break; + default: + throw "No auth methods acceptable"; } } else { throw "Expected 2 bytes"; @@ -330,33 +334,37 @@ class SOCKSSocket { throw "Invalid username or password"; } else { _setState(SOCKSState.RequestReady); - _writeRequest(_request); + _writeRequest(_request!); } } } else if (_state == SOCKSState.RequestReady) { if (data.length >= 10) { - final reply = SOCKSReply._(data[1]); - //data[2] reserved - final version = data[0]; - final addrType = SOCKSAddressType._(data[3]); - Uint8List? addr; - var port = 0; - if (addrType == SOCKSAddressType.Domain) { - final len = data[4]; - addr = data.sublist(5, 5 + len); - port = data[5 + len] << 8 | data[6 + len]; - } else if (addrType == SOCKSAddressType.IPv4) { - addr = data.sublist(5, 9); - port = data[9] << 8 | data[10]; - } else if (addrType == SOCKSAddressType.IPv6) { - addr = data.sublist(5, 21); - port = data[21] << 8 | data[22]; + final reply = SOCKSReply.fromValue(data[1]); + //data[2] reserved + final addrType = SOCKSAddressType.fromValue(data[3]); + Uint8List addr; + int port = 0; + + switch (addrType) { + case SOCKSAddressType.Domain: + final len = data[4]; + addr = data.sublist(5, 5 + len); + port = data[5 + len] << 8 | data[6 + len]; + break; + case SOCKSAddressType.IPv4: + addr = data.sublist(5, 9); + port = data[9] << 8 | data[10]; + break; + case SOCKSAddressType.IPv6: + addr = data.sublist(5, 21); + port = data[21] << 8 | data[22]; + break; } + print( "<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); - - if (reply._value == SOCKSReply.Success._value) { + if (reply.rawValue == SOCKSReply.Success.rawValue) { _setState(SOCKSState.Connected); } else { throw reply; @@ -371,9 +379,9 @@ class SOCKSSocket { if (_state == SOCKSState.RequestReady) { final data = [ req.version, - req.command._value, + req.command.rawValue, 0x00, - req.addressType._value, + req.addressType.rawValue, if (req.addressType == SOCKSAddressType.Domain) req.address.lengthInBytes, ...req.address, @@ -382,15 +390,10 @@ class SOCKSSocket { ]; print( - ">> Version: ${req.version}, Command: ${req.command}, AddrType: ${req.addressType}, Addr: ${req.getAddressString()}, Port: ${req.port}"); + "_writeRequest >> Version: ${req.version}, Command: ${req.command}, AddrType: ${req.addressType}, Addr: ${req.getAddressString()}, Port: ${req.port}"); _sock.write(data); } else { throw "Must be in RequestReady state, current state $_state"; } } - - void write(String data) { - _sock.write(utf8.encode(data)); - // TODO make sure the is correct; see _writeRequest above, may need to construct a SOCKSRequest from the data coming in - } } From 373637701c980eb165b671d9746de64eac599fc1 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Mon, 14 Aug 2023 16:53:44 -0600 Subject: [PATCH 081/237] Fix tezos network status --- lib/services/coins/tezos/tezos_wallet.dart | 123 +++++++++++++++------ 1 file changed, 91 insertions(+), 32 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 3ecc94eb8..e60d353dc 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -12,11 +12,14 @@ import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/services/coins/coin_service.dart'; +import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; +import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/default_nodes.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; @@ -90,6 +93,7 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Timer? timer; bool _shouldAutoSync = false; + Timer? _networkAliveTimer; @override bool get shouldAutoSync => _shouldAutoSync; @@ -101,12 +105,55 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { if (!shouldAutoSync) { timer?.cancel(); timer = null; + stopNetworkAlivePinging(); } else { + startNetworkAlivePinging(); refresh(); } } } + void startNetworkAlivePinging() { + // call once on start right away + _periodicPingCheck(); + + // then periodically check + _networkAliveTimer = Timer.periodic( + Constants.networkAliveTimerDuration, + (_) async { + _periodicPingCheck(); + }, + ); + } + + void stopNetworkAlivePinging() { + _networkAliveTimer?.cancel(); + _networkAliveTimer = null; + } + + void _periodicPingCheck() async { + bool hasNetwork = await testNetworkConnection(); + + if (_isConnected != hasNetwork) { + NodeConnectionStatus status = hasNetwork + ? NodeConnectionStatus.connected + : NodeConnectionStatus.disconnected; + + GlobalEventBus.instance.fire( + NodeConnectionStatusChangedEvent( + status, + walletId, + coin, + ), + ); + + _isConnected = hasNetwork; + if (hasNetwork) { + unawaited(refresh()); + } + } + } + @override Balance get balance => _balance ??= getCachedBalance(); Balance? _balance; @@ -138,15 +185,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future confirmSend({required Map txData}) async { try { - final amount = txData["recipientAmt"] as Amount; - final amountInMicroTez = - amount.decimal * Decimal.fromInt(1000000); + final amountInMicroTez = amount.decimal * Decimal.fromInt(1000000); final microtezToInt = int.parse(amountInMicroTez.toString()); final int feeInMicroTez = int.parse(txData["fee"].toString()); final String destinationAddress = txData["address"] as String; - final secretKey = Keystore.fromMnemonic((await mnemonicString)!).secretKey; + final secretKey = + Keystore.fromMnemonic((await mnemonicString)!).secretKey; Logging.instance.log(secretKey, level: LogLevel.Info); final sourceKeyStore = Keystore.fromSecretKey(secretKey); final client = TezartClient(getCurrentNode().host); @@ -156,8 +202,7 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { destination: destinationAddress, amount: microtezToInt, customFee: feeInMicroTez, - customGasLimit: 400 - ); + customGasLimit: 400); await operation.executeAndMonitor(); // This line gives an error return Future.value(""); } catch (e) { @@ -198,7 +243,8 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { estimatedFee = feeRate; } Logging.instance.log("estimatedFee:$estimatedFee", level: LogLevel.Info); - return Amount(rawValue: BigInt.from(estimatedFee), fractionDigits: coin.decimals); + return Amount( + rawValue: BigInt.from(estimatedFee), fractionDigits: coin.decimals); } @override @@ -356,48 +402,55 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateBalance() async { - try { var api = "${getCurrentNode().host}/chains/main/blocks/head/context/contracts/${await currentReceivingAddress}/balance"; var theBalance = (await get(Uri.parse(api)).then((value) => value.body)) - .substring(1, - (await get(Uri.parse(api)).then((value) => value.body)).length - 2); + .substring( + 1, + (await get(Uri.parse(api)).then((value) => value.body)).length - + 2); Logging.instance.log( "Balance for ${await currentReceivingAddress}: $theBalance", level: LogLevel.Info); var balanceInAmount = Amount( - rawValue: BigInt.parse(theBalance.toString()), fractionDigits: coin.decimals); + rawValue: BigInt.parse(theBalance.toString()), + fractionDigits: coin.decimals); _balance = Balance( total: balanceInAmount, spendable: balanceInAmount, - blockedTotal: Amount(rawValue: BigInt.parse("0"), fractionDigits: coin.decimals), - pendingSpendable: Amount(rawValue: BigInt.parse("0"), fractionDigits: coin.decimals), + blockedTotal: + Amount(rawValue: BigInt.parse("0"), fractionDigits: coin.decimals), + pendingSpendable: + Amount(rawValue: BigInt.parse("0"), fractionDigits: coin.decimals), ); await updateCachedBalance(_balance!); } catch (e, s) { - Logging.instance.log("ERROR GETTING BALANCE ${e.toString()}", level: LogLevel.Error); + Logging.instance + .log("ERROR GETTING BALANCE ${e.toString()}", level: LogLevel.Error); } - } Future updateTransactions() async { - // TODO: Use node RPC instead of tzstats API - var api = "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; - var jsonResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + var api = + "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; + var jsonResponse = + jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); List> txs = []; for (var tx in jsonResponse as List) { - if (tx[1] == "transaction") { - var txApi = "https://api.tzstats.com/explorer/op/${tx[0]}"; //Get transactions by Unique Id, this way we will only get txs - var txJsonResponse = jsonDecode(await get(Uri.parse(txApi)).then((value) => value.body)); + var txApi = + "https://api.tzstats.com/explorer/op/${tx[0]}"; //Get transactions by Unique Id, this way we will only get txs + var txJsonResponse = + jsonDecode(await get(Uri.parse(txApi)).then((value) => value.body)); // Check if list is larger than 1 (if it is, it's a batch transaction) if (!((txJsonResponse as List).length > 1)) { for (var (opJson as Map) in txJsonResponse) { - if (opJson.containsKey("volume")) { // This is to check if transaction is a token transfer + if (opJson.containsKey("volume")) { + // This is to check if transaction is a token transfer TransactionType txType; if (opJson["sender"] == (await currentReceivingAddress)) { txType = TransactionType.outgoing; @@ -407,14 +460,21 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { var theTx = Transaction( walletId: walletId, txid: opJson["hash"].toString(), - timestamp: DateTime.parse(opJson["time"].toString()).toUtc().millisecondsSinceEpoch ~/ 1000, + timestamp: DateTime.parse(opJson["time"].toString()) + .toUtc() + .millisecondsSinceEpoch ~/ + 1000, type: txType, subType: TransactionSubType.none, - amount: (float.parse(opJson["volume"].toString()) * 1000000).toInt(), + amount: (float.parse(opJson["volume"].toString()) * 1000000) + .toInt(), amountString: Amount( - rawValue: BigInt.parse((float.parse(opJson["volume"].toString()) * 1000000).toInt().toString()), - fractionDigits: coin.decimals - ).toJsonString(), + rawValue: BigInt.parse( + (float.parse(opJson["volume"].toString()) * 1000000) + .toInt() + .toString()), + fractionDigits: coin.decimals) + .toJsonString(), fee: (float.parse(opJson["fee"].toString()) * 1000000).toInt(), height: int.parse(opJson["height"].toString()), isCancelled: false, @@ -447,17 +507,16 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateChainHeight() async { try { - var api = - "${getCurrentNode().host}/chains/main/blocks/head/header/shell"; + var api = "${getCurrentNode().host}/chains/main/blocks/head/header/shell"; var jsonParsedResponse = - jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); final int intHeight = int.parse(jsonParsedResponse["level"].toString()); Logging.instance.log("Chain height: $intHeight", level: LogLevel.Info); await updateCachedChainHeight(intHeight); } catch (e, s) { - Logging.instance.log("GET CHAIN HEIGHT ERROR ${e.toString()}", level: LogLevel.Error); + Logging.instance + .log("GET CHAIN HEIGHT ERROR ${e.toString()}", level: LogLevel.Error); } - } @override From 520ceabf7993e41ef50023c3fb58c4c7f4450284 Mon Sep 17 00:00:00 2001 From: likho Date: Tue, 15 Aug 2023 15:28:53 +0200 Subject: [PATCH 082/237] Clean up and refactor --- lib/services/coins/tezos/tezos_wallet.dart | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index e60d353dc..f33b619d0 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -185,14 +185,16 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future confirmSend({required Map txData}) async { try { + final amount = txData["recipientAmt"] as Amount; - final amountInMicroTez = amount.decimal * Decimal.fromInt(1000000); + final amountInMicroTez = + amount.decimal * Decimal.fromInt(1000000); final microtezToInt = int.parse(amountInMicroTez.toString()); final int feeInMicroTez = int.parse(txData["fee"].toString()); final String destinationAddress = txData["address"] as String; - final secretKey = - Keystore.fromMnemonic((await mnemonicString)!).secretKey; + final secretKey = Keystore.fromMnemonic((await mnemonicString)!) + .secretKey; Logging.instance.log(secretKey, level: LogLevel.Info); final sourceKeyStore = Keystore.fromSecretKey(secretKey); final client = TezartClient(getCurrentNode().host); @@ -202,7 +204,9 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { destination: destinationAddress, amount: microtezToInt, customFee: feeInMicroTez, - customGasLimit: 400); + customGasLimit: feeInMicroTez + ); + await operation.executeAndMonitor(); // This line gives an error return Future.value(""); } catch (e) { @@ -403,18 +407,12 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateBalance() async { try { - var api = - "${getCurrentNode().host}/chains/main/blocks/head/context/contracts/${await currentReceivingAddress}/balance"; - var theBalance = (await get(Uri.parse(api)).then((value) => value.body)) - .substring( - 1, - (await get(Uri.parse(api)).then((value) => value.body)).length - - 2); - Logging.instance.log( - "Balance for ${await currentReceivingAddress}: $theBalance", - level: LogLevel.Info); - var balanceInAmount = Amount( - rawValue: BigInt.parse(theBalance.toString()), + final client = TezartClient(getCurrentNode().host); + final thisBalance = await client.getBalance( + address: await currentReceivingAddress + ); + Amount balanceInAmount = Amount( + rawValue: BigInt.parse(thisBalance.toString()), fractionDigits: coin.decimals); _balance = Balance( total: balanceInAmount, @@ -507,6 +505,7 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateChainHeight() async { try { + final client = TezartClient(getCurrentNode().host); var api = "${getCurrentNode().host}/chains/main/blocks/head/header/shell"; var jsonParsedResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); From 6047c433afd59d5da917a6f5466872bb16dd6bf0 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Tue, 15 Aug 2023 08:18:39 -0600 Subject: [PATCH 083/237] add tezos coin images --- assets/default_themes/dark.zip | Bin 659201 -> 660115 bytes assets/default_themes/light.zip | Bin 607092 -> 608006 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/default_themes/dark.zip b/assets/default_themes/dark.zip index fe11a5463f8ae50dad10e51a2f664cbdcc55a25c..4ec1a415b80e284ff31ae47e778ea38513befae8 100644 GIT binary patch delta 6136 zcmZ`-2{=^U8=u8;?^v_X7>2TiEZLWeWM8r*C4~4CNtAt=D0{NIMYckg((=)0VI-u` z7s*=LzwC;TCH{9RgZlpSJa^`Ke)Im`^WOJ8=RN2ALbJq@^TilV4be0l2+BvwB$07D zy-j$JlSz0F~g)-jTr8#3ZPvv1L1O5~J}#5pA7i3fP0dy60qG=)cTQEeIcP+k{d2O&8qO)6NQ zgTffYV9O+G!zV7Z`zHmctShAc(CtAQ@E*VXYob-u|mV{uC!-{6Z(#DELxC#ct zIBBUbM0&|dOYnuk(aW1anK;^gxk!KLtQ6f|YDnc$bUI1M5NM^EZX+a(XLKjykVa6E z3H^r8&nEQl`7{Vk7Awf%E4?hkvxpw2ukZu^QtF9A=>$NJzS8SZUDM6cE1-}8kop3> z78Q(Gpik$8K|yw419W2t+L25FQPjkGpdpq(U^{e{6WB(jMsWfwNSGSVy@~n{H$b3( z(>%aNPL!}fFa<2fZL(a$0Zv;6xkLj!3xx;CLSs0ngWSOb>6D=L2*7?Sm`DI>P@Cf` zXoV8FVQLf&hLdWQwH^3!5T+)0ZK8I00o%|pIPSeE6a^nZ9EA*q?EQd^{NC~dj-gNy zFCdygV52_zfdD@eX$zeU+Vp<+f&dy?BqvlJx@n}Ie7T$3dc2k42(}}Jg9r5< z4!XTq9BDVcd|wt663VN(AvM?SDp-^x@258;vW|wV$jW9cpQwBMyzlu}(aDS8Ds!Sj~AFYEC{8Z&^ORgphR?4pUiH zB-#^LdI~1HI$TL?@e0Yv>)EbGN5xYeNl%Q+oyPc1>=y`Dy8SvMC(1qT?~&Pok?!el zn(^LBvF*X+%=#}OWGHY)h7YG({-Mi#EzSXjigS%?_#&|wa+Z>%LU75H`C~G9g--+bZ25Cs4!>sRnA!=1U7eux zj0gAk^wf7Zo}W$F?a0&3{pvQcNyS;nduN&acC+2=?RpZY1KQTA2@vxY?pUsRXEe zP)2hC`R{!rRBgb4go;xFyC$taJpdeHk`w9nFUwebbCfxW0u1Yo#iKKt+=yUd=NtbT zhO#2Tel(qMc&S2%y*+DReyTuP*wuzNskGh(tclfMi*wQhjs#sqO3Pd)cdNhKZR=9Z z)(+LC2CCL3w#6s0hlgr{a-aS4L|yF;UduyhExwogEFVUv4j$knsefs_*!-EM($Dnd zG`PPeht|yg$lw&)RL3Q=6C}GsA~LQimq^N%HLYS3yBDPGha89XXV1^RRYlO^G`~DF zRqXFP{c2bH*o(}N9Q>1N*LxMjyOTC+*t(9@T;`JTmjqKodf+^c{&))N=fwWGwEzeJ z-b0{A7Xf+dI{bPOuz)uWNH2U7crhIKj)K9^D1f?^kgB5qK}HxHNC7sQpGYcD#|ncJ z`S3>aYa1eo6#!=_bf^%Jrh?6dK(sv!T7lq3@5u&1JPiy!Wdf-U2tqFCPM1vg^<%nJ@vz;-@x zqlNJDgVjHL5N9V-BeBatT10YPxf{>zJsD~7HJf^t;L20<{Wk%_gH^^>mrlZ$Kr3QvV~+HmmT{wi3LbQPlYwIe5`c4cVy}gv5IPHA+W8Zdv#}f zI~46-^%<&`1ZQZDohqD`u6#*wgT61#MCc!Dd)Mf3{37w*0>)N0*k7M@@k7y>xx~k;2z_46UJJm?Y4=~ zO}|NM?KhPf`CQ1^wS223XSCxdwIIx+2^W^!?pcD1 zd2jJxl(oB6^e3|95Y{z)LPkM&&=q%6c!?*xbiDMvJ;x387nabMzDDL@rg)isc9D*Z zPMz0?_BO^9on5L1@9F2rRk2giNiupV8e!qFZBz25B_&|->zbuD;0H z)^7L4v#g=(t%+BqtkJ07Q{U_9EhjDBit71tKhK)zym`Uqq*8Q_p+)yB+ek<*Rzj!g zM7+?xTvGZ~!K(@BMg=+{9C}`1J*6T?_RQd0J`$O2TT*$Jp6Ykqj6jl=1Ow$|MwWg4 zjw9X2`4xNAgnB>rRFYsS^bA(wt>gf0-TlsqoU2?pGA36L- zhE{p%JDF)tG*!ErhPYu1N#!J7tM^9HLTZHqam3g9lK#6-PnX3!c8WZA*vhpM;i(!O z@WNOzxsu(fCG(k7x4TQlQvsFiobZRnNs?u8g+*qMlAW%q*qrKbb<*~h^lH0b+;@GL zTiv;{sh_rj<)UtjcK8f))6`7a{aT22S0=&o^|NfZ8x4^a#6k~cYoE?5**#j^@=H+- zPQk&%!d`9i!RPV}4#RG%MRgIiG~E)mPzS4TJJC;!hnQ zJ-e;GhqEFtLq6-PJngMj@aY>ffk=gI`-6$>ei*TMRYb}lKO)kU&Q#@Enri-y=cQI* zZr((e%r}k)M!ag5@79X8_{UU+y%)|FnSVWU(kn~+ee1U2BKy&t5Lz>3+Gkw40&V?k zjP?6y_!-mwb&B1_*4`b?*4^%LkG!aPtuSCkIp!w)4lPIV`Pj#A68y4bn4(pViPoNO z>6c)-p=9%*NL!Ym$1BLtY(gkd zrHc$)+7r;YRJ>qzm!Nd(_=3yXUY6i;pJD#y3!kFpI;6RMFe^`y*Q#CP_sSGh%&L0~ zO0b#_ysA_T{pzXgaD?RQI$v<+Ok8`~iVjdZ!(!b)`tW|@=;QafY1PL9K~~$?QC4p> zi!PQJ$F0{s0A}%-?;5upi>5uJUeefoh0EW|Tbf&Gw^tQ=!ar@@1ssw8+6lzp6zdDP zKiz0C&zBhU8rfAOa%8VonoIdMlDb4;IehBBeeMOyk6HoZy3ov?O4Mzr=BE(>a&I&adT$~7aY(cnE${VH9c z`_l(qEn?dzxjJT-SDX!6rVgWhZ|AL<+h|v#dI+}@zB|dub+=s)VvT&l;JtWSuWFm@ z@B!BFDIeNl-$Q8?$HWY7o)?usX(WV{l9_J_-X`|NlqeV#PcgP@5S8u=EU2v_xr77l`4{M)5jg(=DjOkjL$Wd@!7(tt?1N zeBEH4xJzZ(D4T;UPS?a0AelfjHCVXxAYbf>KsK7j9+cxYYMj`D>v^LK)(Ywz#qr$^%+@7bTHmZ6 zrD;5zofLHMa9}(m@qy#t!w-b}?gY7w98)-wTwSc0$jm6nX*kHw$|0V87n@beyZWNL ze{`uo8aFViIxuQI@OG}&LZL3%yY6jyUGf~U?u}hODG}t(4ZobiXP#J1h}wB{ZFKlt z`nTt@!lNuA!zp#`p`x?TRSNA2PGbv?rt>%K`|jn`xVMhYsY&hKgA5dWyv}yf*mXqsN-7PEfrXIH*Yaj zo=8rrzbb!RW9;*Qw3|W7prI|ZlAaOEKDH3&7@Jc)``jNAuNw5`hjAo7EH%{` ze7e_4TXY3Wb9evev0^`-a>6;xvdGOxp-JToMam-b$_LI~iL?lg82hL)DKMZ4Kold5B%pdF)#$XmL4Dwm#usZZPmH6R~ZQ8AS!|E?qxF=TP^IOWj$_OdOPB8WgF?M5I>4Us4g^iM?vC1nCt z&4U{vNcAen^Gj5L*cU)~stWQ3#PGp~!qW>I2TkY~*0KOnFYFM-0X^lAcQU#N+Vc%Q zLaysIRM(!$P|i0{Yx5s?SYUyGMbLQt#JKJ|U=cL=9h+PP&40(7mO#Vbv9=}9^mj~u z89ewqR=NBqch}0FcDXBm#>f8sPrJzPf5yDD8G|!{M@{%c?yH~?H5eG=gEf?otDAz6 zS%Wbn$YgDkLrNNfAE#)Fit>C7+_yzV`Qck9AXNf$XtQfP$~ho44`cQ_2H}vugRlgX zfW&N6;+IDVh58RmKNMyopX-(r|7Gcj#%xq$-Lm7qKqH#}7^sHkKj=!dzgt=dLw9H~ z8&ifd5V{K%L!U@sQ|2EPOJ!JE>Q5cG$$Katmuq=c9zoN+c z3=V`%(Pa?;^y(t8gPMNI(jmYqAc;}tVk>+b9flVj79sGXu9UB`P_3vm03)=80IxrN z0E0&b#X>FsMr_M}0$jv>}-+Lg2z7u%RIO( zluv~K^gSQ=BZA8y96?eER19JWTin6XO;P?cXM`?bF#M1>2E)F^fbzZufjxomV4bKC zp2DJA#v`#(XjIYmNBSs?rNZhZF_^Ip?ka>W3|PE^8GIa6NlL8D+UeJ2`v;wpldiT4 zDX)VMDv4@>;J#+EXx(3r>v47G4ML7Z2b8slwfQwIvwg zYOC=5u=uk;4-{z@AHz<&;9#~E=oUW+Rq}#=7U;C?zv`(lMH8m%*b+yJzz+&GjUS{+ zkLzLhF~MPUYzLu90w_!^0=yW0Hg_2ls2{dK?Gu95m@r&hIx%__zPzh3V|dX~LLihS z2yRST%3^Y)T;exxCzvfkX?_L~=TADjJ4?Bq^EmTEC|tkZQ+|KD;+q=M{@83(5GsgL N9t7f_MR<=w{157-N-F>W delta 5217 zcmaKwc{o(<8^>oebIvigm~4ZwlzmGywulyyol0pDva87UN|Tf&lC_giX|ZH)v1O+y zd!$Gb*)l|mBK4c`z76wwuiyED>-s$3@BQ4*{ha5_xljB(so)z@crzn3h6h2v6ryAC zVz@9;t;0D|ZTv}KJ(f;gi(}06nH=W z15Rm`@9$`*{NpzRs;jUdGC4j9&|#Qg0>3xX;=NSVWgvbf%_JJKe!iW7Zav?dhAf8X zU6I;E5DhlCp;wd~?&w%c8ceG~GmjI|U$ zC$Nb4(cpO0DyVdsMJEke3ZGQKZe^tOSOL2;4p|BRtj4aSq+5e^zKo25vrKR+F{e#% z9``VT{tJ6yyRSH9)+hWm4lBDTfZACGmwv_VWJJb(!>OW>Ww6#fPM-lo=W*8sX;73K zSb=WbKsS=DESyo&6KI$t5D3fS+%}`GXRDKX$?OPUNzINV4xI9J2Y^0D6pB4)M6-LNjo^OY4|F5DI8cr(O`Ha zz&K9D4UvE-o_@=~z{-sve+_ubNrSVQwA1v@Q7l%>0zB#V8`*#&19oKt5l3n8Fdkgl zh;%$i#L!?JC&;K~2A&I~Gd2RK!El=pKua_Y-sS^WDl*Oo{-EbRB(N%^tRTowpL~Z9 zsLrro6awYx%7?<>O78Q*;4mG&BY`XR6cYujmt%^7Y79F`9F##KqhTWnkm(VG9%svj z6D2?u+=A%x)2g^l0zA`1xn#M>xK;HwArKIPggEW&=;5f~>V3k~+KLT+8KhifxckOtG?{msX>KU{S=IC;OLr9%%;jbalctrd4{r777&&xd;PE3#eMTzz8nsL24Q1V`xUk& ziAmNRE?Ry{scC$_rGdSe67gr5&S?{`tD*ML}U*m7lmlwvp8k*H3r6o zrQYm)c;@ctttXorw{E4@@p~zl)pd!~O1)`$VCl`(CBmLX*#40CEag}e)aTy>z7-p# z3>Wg^l$|uG`J6QeRiFFSDC|}rwzkyoe$F9Km*pxu7NuqMFr$H^PqP#}!sr&u=bz9)54@ zPi>J6!1k(Xw)Sqf4XG=@+>CE8n#`Rvrs&0t7EGxK9O)@6uK`D%rL~pWTsXve;agN> zZt8}oLC1KLH79~eGZovR?J=d{lP21wW!T__TB_zx<-N@cVzbFr`n3=ruL;IxYrZE0AE!6PsC7! zQCzO=?ydva8>C$Y6M~pwaZ|2$lW%x~z<`@~612SdM*TjS_O5MyMhMO6rx-A z-%-&d2$8RPYiXuA;ViJ0l_S*DkclP=xdEF>+9bGjp!<@C-$bB5EjPO&KUVS6L7)1Q zhT1hMC5hT@;-}|tv>*?jj6?6B2)ge{d^M1I-sYjS@Z3o|WwyAd1suN}s;w0>)9%|* zbbnkL`uvl;A1gPkr9`bOpKbK_7HBGLZFfs8%*M`b4Onllbxn*t^^M37Uvh9CABDSs znDAZ$CEzYZ4OLaOBt@_r8pL~}j8gDVG!+u^dS>EOAKNO1k#E}UwwLU1|BScs$tdQS zd%~iiXl5emoGxz|mskXqd4rQrOGn5 z^?N^jLiWg+aSYBL+LdTI?QP8SgTgn@@r`XqBzy9VQQ-9XP?7aXck{2b;3nn+uB{hs zK38Xj&n|MZyjpVYiw108Wi&{-ywAXO{Pxn0e$Xt)Kv~YXWF65iYb^h|g2GW-nKD5I z>d0=HJsgLrQU%9UPrrHc#2{GilZveUoG10gb&&}uEuhKkc5ZGp)Up`sXd^?Bcwg@5 zF`CPx^S;Amn70V=SxL|IqJ&PAx0L?zedR53&-YpqY=b&mc_v>-lT;6)kr{6V0Nvs4 zTOmP5x?sg>d?g!{;Pq9iZQo4&DF>E5lJB8YFDlViL+T{WEx;wG z#=#u558X~JgXfQ^k=vC#wTy)Il5P~Wdd4}`?z>sP%~twh~d@J0!>CAcYY zltM-G-Q`;Ya6^|x5pJzBQ4H7f7#i)(kA8W{{D73?<$)+ zW1|;(Y?GnmpIORPM#n1JsywUVaY?WtZmZtS6Y%^X$GhXsD zr?qD+jAxD=n(^|OIToZ`v@hF3qSo3ODeuVPATf2K`fko|HZQ}2lW6DTTT{%ws5T^+ zT=E$ScCg5oPq&K8k?fU-%N0%MvB(un$6MqO%6`V?a4b+`^T5!)*nD()vw8DUXnAbg zd|3{EZ-AJS^R!ly@`cWE$`{82b(fCpo|SbuyWz5$OXbNdec93+`EBg^#_ET0T-smH z%wLvza8VoB3%{D)TGO~Fc$W9RQFvK8mOpxS#DZ6Q)`_QFxh7eDXj^-bg7nAa@N_KH zop+boY&yhwUY&Sl47~sQR!s5CLrl`+f{kIr(6hHvSCzfZMoX$fn*=HR^LR*ZIBRJa zR_Dva*NhHvmxb*;P)WT>@J5w{42~kH9yd$P{rN=k_ZOy13uB*FRd#sPzlgY3m-Aur zf%>ccoJq|(FU+G+j=Mt#AX)NZgUxa}jUvHS<{biW#SEfPf{$`pq|R<|`99m!R)sV( z!U4DZ#|ni(1cLsyWyWTNMDd{iG?VbVA0VRvgwqy5BK;+J(*n5pPx}YQVxVOhxv=tf z$$--fAfsnlwxgZF`>^dI?WOUb?uJfp=-XbqfQ0?pPy=U<@d8rb*iKkR#c|A(^r_u4!YH$iJcCZcnJypYdy_Tum@_DoxVeVcaeiANN05yNiUxetyeNcLsraz9n0W4G-SR8 zs$-ZT-JOqtm^OsYL|NAAU>4@Z({-%awYp#|#IzZ7-Q0gLH{4q92i#ikUVvFgL>;Jr zn}Jmo5(Ob4dLyU{{=2}5sc<34oHh}~VGVD9nCDr(+u2wlB3uMP9PqnPfS0LuqOP>> z7sYs`ke4U~Vwm>*g`d{J{J9$u!C-GXkLr$NTgcSyX5Mc5Q+=ILD&;}+8JqKYnh=`8N z1mOH^KzPmQIr^v(2*M}uw5P&99qaPBTu#w2@NM8LS|gSTAP|yF(-p8SdxT&m_La{8 zj05e$P7AxhwJagR8U&DyDfaSGdb-Xfv?39RpS1WJm||Zcz;8Kdo59KPAE9^CMo{g% ze=9fyLBdO4&yX_?&;1mP(X$Pd302D#TrlIW5bLdz2QHKPz0 zZM0ovd6W;vi?3Q5{iu?ZqH`F{F8vl^UA45OZDdh6mJ3?X^jKVOn_IXbK~%6P{D}*a w_|rZwuSkpDJ+FSA)4S(C*P~#KN$~&l(y+%mh>x9&AR{#S5Qu^~+D`)Ff0B+{N&o-= diff --git a/assets/default_themes/light.zip b/assets/default_themes/light.zip index 1453d6ba0606fba827105cb4a76af4df5b6b78dc..f9910e94b9ae11dd260a8b7e5707fe37702e1b63 100644 GIT binary patch delta 6186 zcmaJ_2|QF^*uJx1u00`<$eJ*WeT%3p*_UXsg~=9avCf}~EYV^aI-5vP;&avuGTh z`I>G8MKA4Ru_85~aSY|*eNKpoJ}3BZY!Ek6JAlMbqqSzW*p+4r3K2jeV6>@F14bSR zL%-Iehre#Mk<$DHASNl0gUXQJLe7@^4SKmDpOY#2e(0l(b z1PnbOXi$aAgdY^>d*C`tD~J!V(Vra>lBPlJAn^y$l46KksnR@RAVs=6cwKrn*ogvl zhpf+$|Kbfw7*%2G5IXz`5)nvxerX@o7IWlrB*KQ|c3G1O67nz1^{8w86qFi0v~Yt9QK@#^I;1nfUbtY(Vns- zl#jO`1Ast(LIJ?amxr0n>2_)MKwDxMXsla0n4?p;_1mHY`LzI^li1vIeeYYlhy4}jyqUA}5q*OP9qkG5> zWmSd`oW^(^wfF-S^P6v`UGhjM{`76|Q}5Jw&1i4M%UyxB$@SAgwGct@rVodEw#AhX zt@wZ(g}Il%cjWGlQaUoAa=BxkwU9WZXM}xo|IBh<{g44}4`aK?MTI`Ou&PZ_ zJS-o0XVR>)w)O|_KJLfMU$3U^)Jz^zbp&kdc1g{g-uCkbxijObSB#7USMRnL`NUVs zcp-1G5;*}=nXO&A;-_{!xL;v#AZiz+HDIO3oxR=r_)*Do2N<8c$hWvapJdHCb7gdE zTl=tsQKB4q&@H7gpRN8yh;tjWrHH!?a#T4$`JEDq1C#yMH(bRU9E>S<<(Hf|Hd=%^ z5k-on)moM||L!2|g2d?88}5m``O2LL=Dca~f5K3byK4YND;!oJ-)(Qt`XQUlpAd4r zp@mH2eTX&o(QIB?0{@Z!E+V9)lWKd_I%RB}^VqteXJmrPv)GR4xUFHqnxO1g|142A zTjRtmVE^J<*{^aTv})i1jxx3BmlvD9q96L1xJ-dsPts^i?T-vivQ2h}nmU%*T8K!y z#fO$D9e&cbdt7Eg%6`~kMDN@AZ|y1o4Y%fWsfohCn^P|&yT+a;2c_+(dgOM$oOo}- z`uFy_?qBK5cfK_8ndsAD&U4e*#UlZLvai?c*cK@gf4n@M#aiv*M!NZu{NmS7Rc*X# zBElD1mP8y_J3?jJScGLd3?{!u?4^POuMy#eFz6DDq@Jv@!eHdti!dlegQA|wvQsoD zdP5lWHAAh-tISY^fiURNvVr-a1r=)!gE~TJYPl)9DukARV6d_Zy>1g(jTWwf!QBBg z)Y!{T2hi~O!eI3D2C!?IMk5{J4{?%csYL;TDJ>Q7t{R~K^Q>fUOKAFRr*vf-SKSLul@y$3^hNY7clb(7$k&Xl&D~32!@1) zL8Ax^^+iz@8G&&?!r*x12BvrvW)~w28YW<w6D*<3 zNRVrTO?NJ^p91Q0gUV}i=rT7r31a~~;Ck#eJYXh;=)en7*P-k-FBnV##rQx4s`?}! z_yu7Knel_`Il9UZ8X}0J@H=v?UXx`2fF9rn&b#0}@L0EVr#)B7bsSu#*FJxh>xpB> zqcc_5f>P~pW1~%sLc>q|^~=?gZFpU+dUb|bMKw`eh|lL!GZ&}ad8F}Qg&SLIn)v7B zIu^)x#`jd6TCgM9)dU3+o_mvGXC}(-eIedoVB@%6Q~fi=reK2ScYN}ji2r_g<@Zbp zd)|oT7go;gd0zX8hxq!?bp55HeZ+us>VrzmNMFJS3v6>S=l(^7_ooGX;}>Sx<*g9P z=;;%RTFpldLznzUPcLMSAHc>fDP2pttMLM7F|Kr6>Im`#nV5};q5ERb1N5CC)XCRy zT>P*0UBng>+ZeX}?LS;lZ}Pj-U26zl>7%}9BW8EMRYtH{<#-m$@jX-Ztx^v)A?Tei z5)5hk&Kiz2d0V3N+H~(FMV{x8L#A&BHS`1nB;J=>G~hK@nW7!bZNm%Md~$J|4<~4Xi+$tE zjmI=9qP4?rdgq|Kj+Ap1RJ+`@)N!-04Gla~(m&oYW|Z>__b5Spp7H+2D5Hx9jj9=~ zCfzXRDm(ckZ;QzFcFb;RdtY~-fF-cUh);;by1nv`<#LDK_)rb9Qz_n-fKW3RwbPY?YUp(6%nokxSmjJ=<0+3z1E z&!E$aBI%PG#oUQ4IJ)U-e6;D}mHo~r-}9_zuVtwZ^m_V5+!Rwk^~RB3ZQyJCiRp}L z4juZ@j;-pM$KU5UrXt19n;}JivAG$<#(zq_*x4I!*+0f0+=eA-E~F?ky}9C>>O2?u zwT|=4ogAaVC#F6o>(ukOyjtGlq~3q0FoAXnH)()lveBsDL;T=mQI9)m|DbfXOWMTQ z-B}S^k;ta!W1`8OL^?9#^yaNAhqvK1C^X*fA#g_hvY!1m|LGIVi9VutFDnFVJkCCv zJOdtc>C<`X*ZbiDH_ug;Gieu_o*b?(Ek9H=6Q7-fKm1r&@1EbQ`z=s!YH*dbAA2%+ zx5wl0ouT8cL*K3tyPDIc6bIUnK?RW#6GOk!6_k$oyt$UzD+sw)--{mJKfA1CP&BsX zjbUARPOq`|Tdm~w!v2WI3iKy+JwIm!Dl6kZNn~{#N%2xv8MID*W!SiFTZa@!(^XEN zAtCRtf*P}OM{>CxTr&=y97%L3(gT(&wcJv=tb(_>-4Ay-6+#ScQf)q~!5MB}Gn7of zt@LNyUKOF`6E>nWG8JusqWy%ikUPSix;Rb)HnU!CrRE@}DBDXnPcc>7Pk55|-IvF> z*ePeExqJ1U9LY}fjkhjtPzqFRntSZfy`ZHs>n72BMpKcG`<}m8>Ohibn_pWyyBvEF zZ;{;_%6yD(do*q|eb;nK6jP+~QPF3o zS_eaDTUDETI%HB=hK1X;+Uc%`=`Oq&6G+#-eTA{kOOfG_vZNHN%4|OCo4T5zDRN1= zmzZ!!dh+PaPcOJ^=hVlZ4}CoUrG{}q?ex&WfbShXL{y4svqkNRS1Ld9&j}&#?5%v% zQupps44c($ZN3P>aPK>}PTte?zEe_~RaRM#U(#b(yp^0d(XL}))?|~aw~*B!7bccD zjch!o_PBUIeV=3|`2v%(w_bajfN{Yjo`@el*BljAo6iww| zKktZ1(j#6Sk#*{+Mch_$Kgm$@Xe5-DyKc_8(PsCzcFQ@DTi>0S+qk2ysr{^-aK@PL z-H#Z}zlAt>EM7Dxt^T@YOL&5fn4}#^HF;}XLYNvu%rV&*`HaB#L6)<071p~;HO#S{ zoS#3~6C}f08HrDtSS%aVdtQYqD2Q%*Q2x*ik}{hiHqtU(Dt!6S>*1WQNsx~JwZ23F zLDu2xTkj2?5f;_(((6tL;fu&^?z>eLzCFliy!4w-)lbbPAbnVe;B_9GxrE;@i)*ki zSNxhFmtJ42RC#8ijaZ#JL?ApH-y3||ZkbSR^m;fd-FS>U)BK6ZBu{(k(nsJkuC_Dt z)$+&L3}Pzk-2UUOpblI&+NdF<4-FaWQ%vZ;2h^6H8IefC>?4c!9>_+ zlA~rPTWziQqp5dbWN9FbdvHW$aOBwF=YYZN8-sO~gCo6zbxRqi?{)Mwgci4GX}>_^ z>V9B(7N1Y_oe?wqF>pO@mQQ3PzNaf#^xISA9NSx`w&xtZv9m$r=UJzh>UC^RuT(pW z9AB!uGjr5eX_|33q+A#0V5CGGk#W#doNGIwuh4Y%gr58y+lfOZ1<9gqSLj}o^y-zE zbPJExFut^%7k3R3Zn~F+6KUEOqf-4{KW|6&_d_$kXd^!l=saP#)j%$lw6HN7Tm~Gc z7?!XcS>>L(k!;+f!)7P%e!aa-BGi5$&yPz!)tr7=B(owo?tyHsl8Bs=1#yUd;r0?^ zXOLGz#_#-nA{^MB#mex)Pj!1vM!krixAN`J9859Q&W__NPfG7myyU9E_9NCdqPBc8 z{i$ek>m!aDT{*IB%=?}@_}A~0-#=?;v)lIHC{EUE?21Wc()<-qiR%V<)lnCn;Np)8 z?TvRI{p6+HviMl)JSUCvfO2V`6i#&x-;x)fHcQSPcrB&zn~rj`H$-Xv+zJ8!rz0$65tNFM*)S4!xyPPT?**2ILM1Ig!;wTuYjw>2x~}NVgnIY z^CGOFR0&XHtyQr?TxnE5G?Jjk#!dxv1_#pvAP-5#D91^IMDcSUNr7s9*xYuGYQy;waUOV z4uqy;KqIQXl>o^$kb~?7ClnCX6aF0PmIVzqQ&~75UAYZ@C{%t*S7PI@H(~geyY`d> zv&TcbB*C5A|IaSP>T+(8f*#7jspf$wbS_d_Jep(>53c?4gQn#{UOwMk%d={AbF7H~ za3K)^Y<6^xs^p>uO;N$u_3QHRjOL{gBwRcXWG4^OL0Bwe%ik;(1(*TA36ao{J)E_w3b1klMjob5TPfJg8YEd{iGXTI-_+V@{H+lsF{fxwjZj!+EF6@P)(@lg@ z_JWdskA0<#ndL#u>Y(u7V@K5CIA-%P5PcqI=ih^s@F22;33{vn@<97`RQj`ONI(p~!HXOi~o*w%xk31a{8(ZZ{Zd<2Ik1gm&9DTD+l zKDI*ytqq~A?AE8I&|NJ!ONN5bOD#}{YLhakMrk2ze1TG02y0JCaJLZn|1=aJqx~Qk SvofFz6mS8678ZU71OEd^yF+XM delta 5463 zcmZu#c|26#8@_iIGdD(zB^i6fMD{hivX*So`fZUV%38=eQOLfGTze5pNui7=yDWVx zQIRA+v}=*2MEc#CYR2e0f6RP7&wZZfeb0N&J#*d@lPohGBg1988I9ow=%47kG%hJz ztVD}Tj6_RXgdnvEgF(3@rP-}zfg~^~Ek_+EAjKe6K6XHZc~mlH3FDXSbRN|oqr%cL zP|OOS?@rWCj0)#VsM&=XNEl^SN0q>u;L?7DuJ*w4qQN?9DBg?-b>cNp2(-9jBNMXV z%pno#PCGGjN4`pXspo>FU`VOp{4botg3b^SHMzdA{oeB}KxEIv_6NUDs7mTSy zK%Y}6W*l1WDU|<71eC|4nK{yq;?XOt5ir6Lt!BjB;VCCpoW=rjie+$xJ< zR-Tq2i&20Pu(<)l@`M^OG7Si*6pm%)P74gjiU%QJ<}?ESUOTks(^$ho@Fpyp$zi~Z z?wrYCmJT++WpX%HN+0BKhmyct*r^7`ik?@4`?(fOg!7)`Se|3gao#0JAp4VeRc4@s zllWN>0i&Yv+Dx!H8c)R_pkq8}}iKjmadO-*6MIoI(<%H8kp^pd_DF(6DN4pqwo=)_TfLL{} zkbolTpt2OC$y9quLGQsdc;_03RicbFkTpn%cbI3s&8F~2X-JS#vaZF2zS+=!1CDb7 zAm$Ak02p5%cHK>WR!e;TS{`-v0^ifj_3u9((RWfi34R<^#O^Bfl1!Jg^{*$LT$oRN zbXjilz`S#y2biDvF3(wDr>S7q!jG5l``dL(1I)VHDGhavlV6DfS+^A;9w_#^NgBAy zE=r0UicrWu>)QhKd5fiGGbjtWx8uH+iwtY49ImtBe7z=lOkzg}&RAen@33-4=wt+G zy?L;?ja|5?M686tgjuJ~c^6ypPhmcW-CM_{%2LKUCl~CJ3!OVAhxTJnIc9Pgi5)>H z0X1W<;>isHx5GYtXvNDZS;Q53L|n%n8GhfRP6?*$FnRE4ocpa^?NO9O1&>#i`lt5# z5}M8_+fd76RcoSpzwyLuK3D7QTd-y@fwsFNZY(-=@rdyj0W-=T542Y=arTocb}WU9jk$8XT4(=NtpY?cB2N_ z3F8LB0u*npLZZdwh;wb=`J`QN%1< z#DSBN-DQ55pcpDXZEDvRW;gb3;^3QJ0wu=frUrq`SD4ELwa2cfaGjDBDNt3|n?W1x9El2P zaX&`6OA44!+aJBvYNTynOCmX)c$@RuuHEjH`1G!8?<1@C+6JmW(g}*_5I_HA?#=N9 zJ3ld@*}&moms^o{Zpo{^nz}7~*y9{&>#5RaWXbBGx-8m{o}_iEy|v7^1Pl>hA0zKS_c10_I-3Id7$}OwpRUoS=Kq6 z*Zd&?8`6Z`!Sj=n+{do%tnD7)*ly`mP{prtYhA7MTY;3-g5T}u)qF`DDMi)95<=GV zlc|OwVFi_6grpCQ9XF-CW}pG`W1j{93r&!mNM{V?FBmWNbwxQEXoyoA`QQ#I%`+7B6dVJQJgr_rf9Z=`^xN^RCP9NyPrVPYF>D$7#q$32|iCnlE; zsCRk8r^yhJLgBh&i22Bs`N}1Mm-u8bnmG8x=UQX?fvf|#D=CQ`SyMf!$8FkU+VaZz zT8}&&iNZeAy+8Lz_3X-VnLd*~Tvl}FZ1+2<$RY=`@6NUP*pj@=Rd~@5C;Wu-i^;E6 zyY|&)5Sx4MPg!4gO}rQ)J~QTbbTD9FOnpUtz#9E9&w2`|M0CIOLfLJ7#1kE2WWSi# z{x_rEn=IlkJDg8x%{N3_mhHw7*vHoeTAOu z3*PllMN;!1O8b}9RTKMC9P%`#u#~2kr?A4U0q$L1atVD-Giyt~jdNEC$0zB{)84w_ z9rRm)*NIgpqzK)7+msJ(kw0{=yCUPv)vo+|kY($}0v!G^m$Yg5gWL!4KcryJ)1lXWIHh;8@(f`*THk=y*T-re%5JDl}D_YQB}AlftWM_fEs5!Z3%uT?MY)>P*^ z$rTfd4r(WQ>LnZ`^=tme}qJiIw+L{?HoJGo9 zQnKpT+`hO7%4}Bq8Gh~H2cN@zw+_uOyypmeOW|}7yy)i2QJaccl{z#3Quk+l{%m7E zHlg5CtkYr=6sv>XW3^7FF$l288QPXJI4WcjP0O&_I{->RxYEob57K8Ld2#U7t<#jow&)LbxR$)=Bm*~#M*t1{)?V3) zcuXjcFJ6}qWrOK}y_-8zOC)c#*!9dtf0dk=Dp4z4` z6KZ68QE#8xtvy-`XK%FLooVINXuBKGcK1eG-%Q(PjrN3q_PaOQ6J|{N_m2vIF=#0=P5(7Xp! zEvlWezL-}UWL2BrT)V^H{5JQ1D#cvw>+UaR`Y&>;O1)mkeUTL5bj3E z+`C#lcSikA@f^zDe4D@Jne+VnEQkNW`RR{_eNB?zWfjU(sz{!^9Xt6|YgW+_&U#Y3 z2}(HXPp)?Re1Y#4A&OQKA8YqRr{uGb>MkL6R5^z?a zv$#dZP@!LWctd4;c9E*q5FV?zesFaQ46x|Ok5}b2VFqGo{#YUT;o<-`&p^+8) zq;tAgTljo(<>s1*&0wrQ@Zl&#J9A4%aA!8m70H&${V7nPa@uUAV zU$Ctrr2OZo4y$NGB1rQEmnb5~q~EO)ENO;-c1iG}B67m}-GlvN#^%AUN=ujw`RP2k zK?yQs%IP4Z2ZN=RA;YCj*e_?ZIyg}ovi);RWP+dyw2d8ft%E~UAUk#tk$?U#&`otY z6Oj-71tM~LHOTre&o;H?a)h}-9kTh0S)u+POlgh(7*Y0L;I7*+w_?tFFU>>F!E5Z{wwCf;oKCK7;#1Z+6 zQAlT`Jzz30a8EDD%RUIih<5`*+Y^am7>(#dSUB$#irG-Jl5H?vNPDpb0P2PSU@cp+ zLRd6QyaSKs|0~9KdW^&Nzi7(3NWcEO9sRZ9kSsiP5ypX@UyO6QtOlFO7^X9Hr7?d7 zjDbUBF?@f8veiRq74=JK9~v@r(}X`_NbT!m}G!3GG%bAEFR0@c-d(t zxo`rVwy~N?!@_qAAR>D~{!N5`&}nglOd1C6e2!a|7BT_8hR9B1cmhr~grwL!B$q;-FmhvF(lu6QpPu+0KghaUzkm@ z`2u{-7?NSjj-L8EW29mq%J4An6};GAPq&yLPp_5$>i+gD(`sm{}(HDX+ogo58h%VcD7^5ic z3br_oINKo3?6craf?#7QNC;LiU1rS?0%tc3Iw8WFND0;e$lU+_T#s}T{VmKhUA8+g zggv5Ws3wFgjfhEXLQ!#sP-f})MUmSEL;63bnFRcg*|PPgN56Df`lq~t&96ri0*)PW j^>S78JnG}k*t?fpNx&m!kPx>vpbh8>Aw!UdkevPxN&IQ{ From 0a77dad7ec84295eed1b6b31ca3424f88e26c8f3 Mon Sep 17 00:00:00 2001 From: likho Date: Tue, 15 Aug 2023 16:49:28 +0200 Subject: [PATCH 084/237] Refactor Update transactions call --- lib/services/coins/tezos/tezos_wallet.dart | 123 ++++++++++----------- 1 file changed, 57 insertions(+), 66 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index f33b619d0..c628253d8 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -198,7 +198,7 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Logging.instance.log(secretKey, level: LogLevel.Info); final sourceKeyStore = Keystore.fromSecretKey(secretKey); final client = TezartClient(getCurrentNode().host); - //TODO - Update gas Limit + final operation = await client.transferOperation( source: sourceKeyStore, destination: destinationAddress, @@ -431,72 +431,64 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateTransactions() async { // TODO: Use node RPC instead of tzstats API - var api = - "https://api.tzstats.com/tables/op?address=${await currentReceivingAddress}"; - var jsonResponse = - jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); - + String transactionsCall = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/operations"; + var response = jsonDecode(await get(Uri.parse(transactionsCall)).then((value) => value.body)); List> txs = []; - - for (var tx in jsonResponse as List) { - if (tx[1] == "transaction") { - var txApi = - "https://api.tzstats.com/explorer/op/${tx[0]}"; //Get transactions by Unique Id, this way we will only get txs - var txJsonResponse = - jsonDecode(await get(Uri.parse(txApi)).then((value) => value.body)); - // Check if list is larger than 1 (if it is, it's a batch transaction) - if (!((txJsonResponse as List).length > 1)) { - for (var (opJson as Map) in txJsonResponse) { - if (opJson.containsKey("volume")) { - // This is to check if transaction is a token transfer - TransactionType txType; - if (opJson["sender"] == (await currentReceivingAddress)) { - txType = TransactionType.outgoing; - } else { - txType = TransactionType.incoming; - } - var theTx = Transaction( - walletId: walletId, - txid: opJson["hash"].toString(), - timestamp: DateTime.parse(opJson["time"].toString()) - .toUtc() - .millisecondsSinceEpoch ~/ - 1000, - type: txType, - subType: TransactionSubType.none, - amount: (float.parse(opJson["volume"].toString()) * 1000000) - .toInt(), - amountString: Amount( - rawValue: BigInt.parse( - (float.parse(opJson["volume"].toString()) * 1000000) - .toInt() - .toString()), - fractionDigits: coin.decimals) - .toJsonString(), - fee: (float.parse(opJson["fee"].toString()) * 1000000).toInt(), - height: int.parse(opJson["height"].toString()), - isCancelled: false, - isLelantus: false, - slateId: "", - otherData: "", - inputs: [], - outputs: [], - nonce: 0, - numberOfMessages: null, - ); - var theAddress = Address( - walletId: walletId, - value: opJson["receiver"].toString(), - publicKey: [], // TODO: Add public key - derivationIndex: 0, - derivationPath: null, - type: AddressType.unknown, - subType: AddressSubType.unknown, - ); - txs.add(Tuple2(theTx, theAddress)); - } - } + for (var tx in response as List) { + if (tx["type"] == "transaction") { + TransactionType txType; + if (tx["sender"]["address"] == (await currentReceivingAddress)) { + txType = TransactionType.outgoing; + } else { + txType = TransactionType.incoming; } + + final amount = tx["amount"] as int; + final fee = tx["bakerFee"] as int; + final amountInMicroTez = + amount / 1000000; + + final feeInMicroTez = + fee / 1000000; + + var theTx = Transaction( + walletId: walletId, + txid: tx["hash"].toString(), + timestamp: DateTime.parse(tx["timestamp"].toString()) + .toUtc() + .millisecondsSinceEpoch ~/ + 1000, + type: txType, + subType: TransactionSubType.none, + amount: tx["amount"] as int, + amountString: Amount( + rawValue: BigInt.parse( + (tx["amount"] as int) + .toInt() + .toString()), + fractionDigits: coin.decimals) + .toJsonString(), + fee: tx["bakerFee"] as int, + height: int.parse(tx["level"].toString()), + isCancelled: false, + isLelantus: false, + slateId: "", + otherData: "", + inputs: [], + outputs: [], + nonce: 0, + numberOfMessages: null, + ); + var theAddress = Address( + walletId: walletId, + value: tx["target"]["address"].toString(), + publicKey: [], // TODO: Add public key + derivationIndex: 0, + derivationPath: null, + type: AddressType.unknown, + subType: AddressSubType.unknown, + ); + txs.add(Tuple2(theTx, theAddress)); } } Logging.instance.log("Transactions: $txs", level: LogLevel.Info); @@ -505,7 +497,6 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateChainHeight() async { try { - final client = TezartClient(getCurrentNode().host); var api = "${getCurrentNode().host}/chains/main/blocks/head/header/shell"; var jsonParsedResponse = jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); From e3fb83a61fdc8af4a49479fcd54e17881259c670 Mon Sep 17 00:00:00 2001 From: likho Date: Tue, 15 Aug 2023 18:01:51 +0200 Subject: [PATCH 085/237] Send all --- lib/services/coins/tezos/tezos_wallet.dart | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index c628253d8..857f62f12 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -195,14 +195,20 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { final String destinationAddress = txData["address"] as String; final secretKey = Keystore.fromMnemonic((await mnemonicString)!) .secretKey; + Logging.instance.log(secretKey, level: LogLevel.Info); final sourceKeyStore = Keystore.fromSecretKey(secretKey); final client = TezartClient(getCurrentNode().host); + int? sendAmount = microtezToInt; + if (balance.spendable == txData["recipientAmt"] as Amount) { + sendAmount = microtezToInt - feeInMicroTez; + } + final operation = await client.transferOperation( source: sourceKeyStore, destination: destinationAddress, - amount: microtezToInt, + amount: sendAmount, customFee: feeInMicroTez, customGasLimit: feeInMicroTez ); @@ -430,7 +436,6 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateTransactions() async { - // TODO: Use node RPC instead of tzstats API String transactionsCall = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/operations"; var response = jsonDecode(await get(Uri.parse(transactionsCall)).then((value) => value.body)); List> txs = []; @@ -443,14 +448,6 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { txType = TransactionType.incoming; } - final amount = tx["amount"] as int; - final fee = tx["bakerFee"] as int; - final amountInMicroTez = - amount / 1000000; - - final feeInMicroTez = - fee / 1000000; - var theTx = Transaction( walletId: walletId, txid: tx["hash"].toString(), From 9eecaf5951a731faa986e3bb75b14ee6c7dc344b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 15 Aug 2023 16:22:15 -0500 Subject: [PATCH 086/237] update flutter_libtor: use newly-merged main with socket example --- crypto_plugins/flutter_libtor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_libtor b/crypto_plugins/flutter_libtor index 7b8e6edf1..6aca8f78a 160000 --- a/crypto_plugins/flutter_libtor +++ b/crypto_plugins/flutter_libtor @@ -1 +1 @@ -Subproject commit 7b8e6edf18094f45c4bbe50c6a1a98e1d57f1589 +Subproject commit 6aca8f78a10972ce07ee1ededcce02e97cc46834 From 8b73241d292fe245f6744d8fd6bb246a85c617b0 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 15 Aug 2023 16:22:15 -0500 Subject: [PATCH 087/237] update flutter_libtor: use newly-merged main with socket example --- crypto_plugins/flutter_libtor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/flutter_libtor b/crypto_plugins/flutter_libtor index 7f5446969..6aca8f78a 160000 --- a/crypto_plugins/flutter_libtor +++ b/crypto_plugins/flutter_libtor @@ -1 +1 @@ -Subproject commit 7f544696969aa0a2d47d1d79ead3107dd2cea27e +Subproject commit 6aca8f78a10972ce07ee1ededcce02e97cc46834 From f2af2b10bd1e45db2ce264c79669624f0b27c830 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 15 Aug 2023 22:10:36 -0500 Subject: [PATCH 088/237] Revert "Merge branch 'tor' into tor-presocks" This reverts commit 75750e2bd15e24acbe2953bd9c01b352dc6171da. --- lib/electrumx_rpc/cached_electrumx.dart | 4 +- lib/electrumx_rpc/electrumx.dart | 155 ++----- lib/electrumx_rpc/rpc.dart | 160 ++----- lib/networking/socks5.dart | 399 ------------------ .../wallet_settings_view.dart | 59 --- .../wallet_view/sub_widgets/tx_icon.dart | 3 +- .../transaction_details_view.dart | 5 +- scripts/linux/build_all.sh | 2 +- test/json_rpc_test.dart | 5 +- .../services/coins/firo/firo_wallet_test.dart | 4 +- 10 files changed, 73 insertions(+), 723 deletions(-) delete mode 100644 lib/networking/socks5.dart diff --git a/lib/electrumx_rpc/cached_electrumx.dart b/lib/electrumx_rpc/cached_electrumx.dart index cb5237bab..8366e259f 100644 --- a/lib/electrumx_rpc/cached_electrumx.dart +++ b/lib/electrumx_rpc/cached_electrumx.dart @@ -9,7 +9,6 @@ */ import 'dart:convert'; -import 'dart:math'; import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart'; @@ -158,6 +157,7 @@ class CachedElectrumX { Future> getUsedCoinSerials({ required Coin coin, + int startNumber = 0, }) async { try { final box = await DB.instance.getUsedSerialsCacheBox(coin: coin); @@ -168,7 +168,7 @@ class CachedElectrumX { _list == null ? {} : List.from(_list).toSet(); final startNumber = - max(0, cachedSerials.length - 100); // 100 being some arbitrary buffer + cachedSerials.length - 10; // 10 being some arbitrary buffer final serials = await electrumXClient.getUsedCoinSerials( startNumber: startNumber, diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 7d3dd3d2b..c9417116d 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -15,7 +15,6 @@ import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:decimal/decimal.dart'; import 'package:stackwallet/electrumx_rpc/rpc.dart'; import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; -import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:uuid/uuid.dart'; @@ -72,8 +71,6 @@ class ElectrumX { final Duration connectionTimeoutForSpecialCaseJsonRPCClients; - ({String host, int port})? proxyInfo; - ElectrumX({ required String host, required int port, @@ -83,7 +80,6 @@ class ElectrumX { JsonRPC? client, this.connectionTimeoutForSpecialCaseJsonRPCClients = const Duration(seconds: 60), - ({String host, int port})? proxyInfo, }) { _prefs = prefs; _host = host; @@ -96,38 +92,14 @@ class ElectrumX { required ElectrumXNode node, required Prefs prefs, required List failovers, - ({String host, int port})? proxyInfo, - }) { - if (Prefs.instance.useTor) { - if (proxyInfo == null) { - // TODO await tor / make sure it's running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log( - "ElectrumX.from(): no tor proxy info, read $proxyInfo", - level: LogLevel.Warning); - } - return ElectrumX( + }) => + ElectrumX( host: node.address, port: node.port, useSSL: node.useSSL, prefs: prefs, failovers: failovers, - proxyInfo: proxyInfo, ); - } else { - return ElectrumX( - host: node.address, - port: node.port, - useSSL: node.useSSL, - prefs: prefs, - failovers: failovers, - proxyInfo: null, - ); - } - } Future _allow() async { if (_prefs.wifiOnly) { @@ -149,52 +121,20 @@ class ElectrumX { throw WifiOnlyException(); } - if (Prefs.instance.useTor) { - if (proxyInfo == null) { - // TODO await tor / make sure Tor is running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log( - "ElectrumX.request(): no tor proxy info, read $proxyInfo", - level: LogLevel.Warning); - } - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } else { - _rpcClient ??= JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + ); } else { - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } else { - _rpcClient ??= JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } + _rpcClient = JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + ); } try { @@ -213,8 +153,7 @@ class ElectrumX { ); if (response.exception != null) { - throw response.exception! - as Object; // TODO properly check that .exception is an Object + throw response.exception!; } if (response.data is Map && response.data["error"] != null) { @@ -282,53 +221,20 @@ class ElectrumX { throw WifiOnlyException(); } - if (Prefs.instance.useTor) { - // TODO await tor / make sure Tor is initialized - if (proxyInfo == null) { - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log( - "ElectrumX.batchRequest(): no tor proxy info, read $proxyInfo", - level: LogLevel.Warning); - } - - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } else { - _rpcClient = JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + ); } else { - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } else { - _rpcClient = JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } + _rpcClient = JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + ); } try { @@ -354,8 +260,7 @@ class ElectrumX { (await _rpcClient!.request(request, requestTimeout)); if (jsonRpcResponse.exception != null) { - throw jsonRpcResponse.exception! - as Object; // TODO properly check that .exception is an Object + throw jsonRpcResponse.exception!; } final response = jsonRpcResponse.data as List; diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 497e101bb..2dc0d3a71 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -14,10 +14,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; -import 'package:stackwallet/networking/socks5.dart'; -import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; -import 'package:stackwallet/utilities/prefs.dart'; // Json RPC class to handle connecting to electrumx servers class JsonRPC { @@ -26,20 +23,16 @@ class JsonRPC { required this.port, this.useSSL = false, this.connectionTimeout = const Duration(seconds: 60), - required ({String host, int port})? proxyInfo, }); final bool useSSL; final String host; final int port; final Duration connectionTimeout; - ({String host, int port})? proxyInfo; final _requestMutex = Mutex(); final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); Socket? _socket; - SOCKSSocket? _socksSocket; StreamSubscription? _subscription; - StreamSubscription? get subscription => _subscription; void _dataHandler(List data) { _requestQueue.nextIncompleteReq.then((req) { @@ -82,13 +75,7 @@ class JsonRPC { _requestQueue.nextIncompleteReq.then((req) { if (req != null) { // \r\n required by electrumx server - if (_socket != null) { - _socket!.write('${req.jsonRequest}\r\n'); - } - if (_socksSocket != null) { - print(33333333); - _socksSocket!.write('${req.jsonRequest}\r\n'); - } + _socket!.write('${req.jsonRequest}\r\n'); // TODO different timeout length? req.initiateTimeout( @@ -105,22 +92,12 @@ class JsonRPC { Duration requestTimeout, ) async { await _requestMutex.protect(() async { - if (!Prefs.instance.useTor) { - if (_socket == null) { - Logging.instance.log( - "JsonRPC request: opening socket $host:$port", - level: LogLevel.Info, - ); - await connect(); - } - } else { - if (_socksSocket == null) { - Logging.instance.log( - "JsonRPC request: opening SOCKS socket to $host:$port", - level: LogLevel.Info, - ); - await connect(); - } + if (_socket == null) { + Logging.instance.log( + "JsonRPC request: opening socket $host:$port", + level: LogLevel.Info, + ); + await connect(); } }); @@ -160,9 +137,6 @@ class JsonRPC { _subscription = null; _socket?.destroy(); _socket = null; - unawaited(_socksSocket?.close(keepOpen: false)); - // TODO check that it's ok to not await this - _socksSocket = null; // clean up remaining queue await _requestQueue.completeRemainingWithError( @@ -172,92 +146,33 @@ class JsonRPC { } Future connect() async { - if (!Prefs.instance.useTor) { - if (useSSL) { - _socket = await SecureSocket.connect( - host, - port, - timeout: connectionTimeout, - onBadCertificate: (_) => true, - ); // TODO do not automatically trust bad certificates - } else { - _socket = await Socket.connect( - host, - port, - timeout: connectionTimeout, - ); - } - - _subscription = _socket!.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, + if (_socket != null) { + throw Exception( + "JsonRPC attempted to connect to an already existing socket!", ); - } else { - if (proxyInfo == null) { - // TODO await tor / make sure it's running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log( - "ElectrumX.connect(): no tor proxy info, read $proxyInfo", - level: LogLevel.Warning); - } - // TODO connect to proxy socket... - - // TODO implement ssl over tor - // if (useSSL) { - // _socket = await SecureSocket.connect( - // host, - // port, - // timeout: connectionTimeout, - // onBadCertificate: (_) => true, - // ); // TODO do not automatically trust bad certificates - // final _client = SocksSocket.protected(_socket, type); - // } else { - final sock = await RawSocket.connect( - InternetAddress.loopbackIPv4, proxyInfo!.port); - _socksSocket = SOCKSSocket(sock); - - try { - Logging.instance.log( - "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", - level: LogLevel.Info); - if (!isIpAddress(host)) { - await _socksSocket!.connect("$host:$port"); - } else { - await _socksSocket!.connectIp(InternetAddress(host), port); - } - Logging.instance.log( - "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", - level: LogLevel.Info); - } catch (e) { - Logging.instance.log( - "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", - level: LogLevel.Error); - throw Exception( - "JsonRPC.connect(): failed to connect to tor proxy, $e"); - } - - // _subscription = _socksSocket!.socket.listen( - // _dataHandler, - // onError: _errorHandler, - // onDone: _doneHandler, - // cancelOnError: true, - // ) as StreamSubscription?; - - _socksSocket!.subscription.onData((RawSocketEvent event) { - /// [RawSocketEvent] messages are here - /// read from here.. - if (event == RawSocketEvent.read) { - final data = sock.read(sock.available()); - print(11111); - print(data); - } - }); } + + if (useSSL) { + _socket = await SecureSocket.connect( + host, + port, + timeout: connectionTimeout, + onBadCertificate: (_) => true, + ); // TODO do not automatically trust bad certificates + } else { + _socket = await Socket.connect( + host, + port, + timeout: connectionTimeout, + ); + } + + _subscription = _socket!.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } } @@ -380,14 +295,3 @@ class JsonRPCResponse { JsonRPCResponse({this.data, this.exception}); } - -bool isIpAddress(String host) { - try { - // if the string can be parsed into an InternetAddress, it's an IP. - InternetAddress(host); - return true; - } catch (e) { - // if parsing fails, it's not an IP. - return false; - } -} diff --git a/lib/networking/socks5.dart b/lib/networking/socks5.dart deleted file mode 100644 index ba655f3db..000000000 --- a/lib/networking/socks5.dart +++ /dev/null @@ -1,399 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -/// https://tools.ietf.org/html/rfc1928 -/// https://tools.ietf.org/html/rfc1929 -/// - -const SOCKSVersion = 0x05; -const RFC1929Version = 0x01; - -enum AuthMethods { - NoAuth(0x00), - GSSApi(0x01), - UsernamePassword(0x02), - NoAcceptableMethods(0xFF); - - final int rawValue; - - const AuthMethods(this.rawValue); - - factory AuthMethods.fromValue(int value) { - for (final v in values) { - if (v.rawValue == value) { - return v; - } - } - throw UnsupportedError("Invalid AuthMethods value"); - } - - @override - String toString() => "$runtimeType.$name"; -} - -enum SOCKSState { - Starting(0x00), - Auth(0x01), - RequestReady(0x02), - Connected(0x03), - AuthStarted(0x04); - - final int rawValue; - - const SOCKSState(this.rawValue); - - factory SOCKSState.fromValue(int value) { - for (final v in values) { - if (v.rawValue == value) { - return v; - } - } - throw UnsupportedError("Invalid SOCKSState value"); - } - - @override - String toString() => "$runtimeType.$name"; -} - -enum SOCKSAddressType { - IPv4(0x01), - Domain(0x03), - IPv6(0x04); - - final int rawValue; - - const SOCKSAddressType(this.rawValue); - - factory SOCKSAddressType.fromValue(int value) { - for (final v in values) { - if (v.rawValue == value) { - return v; - } - } - throw UnsupportedError("Invalid SOCKSAddressType value"); - } - - @override - String toString() => "$runtimeType.$name"; -} - -enum SOCKSCommand { - Connect(0x01), - Bind(0x02), - UDPAssociate(0x03); - - final int rawValue; - - const SOCKSCommand(this.rawValue); - - factory SOCKSCommand.fromValue(int value) { - for (final v in values) { - if (v.rawValue == value) { - return v; - } - } - throw UnsupportedError("Invalid SOCKSCommand value"); - } - - @override - String toString() => "$runtimeType.$name"; -} - -enum SOCKSReply { - Success(0x00), - GeneralFailure(0x01), - ConnectionNotAllowedByRuleSet(0x02), - NetworkUnreachable(0x03), - HostUnreachable(0x04), - ConnectionRefused(0x05), - TTLExpired(0x06), - CommandNotSupported(0x07), - AddressTypeNotSupported(0x08); - - final int rawValue; - - const SOCKSReply(this.rawValue); - - factory SOCKSReply.fromValue(int value) { - for (final v in values) { - if (v.rawValue == value) { - return v; - } - } - throw UnsupportedError("Invalid SOCKSReply value"); - } - - @override - String toString() => "$runtimeType.$name"; -} - -class SOCKSRequest { - final int version = SOCKSVersion; - final SOCKSCommand command; - final SOCKSAddressType addressType; - final Uint8List address; - final int port; - - String getAddressString() { - switch (addressType) { - case SOCKSAddressType.Domain: - return const AsciiDecoder().convert(address); - case SOCKSAddressType.IPv4: - return address.join("."); - case SOCKSAddressType.IPv6: - final List ret = []; - for (int x = 0; x < address.length; x += 2) { - ret.add("${address[x].toRadixString(16).padLeft(2, "0")}" - "${address[x + 1].toRadixString(16).padLeft(2, "0")}"); - } - return ret.join(":"); - } - } - - SOCKSRequest({ - required this.command, - required this.addressType, - required this.address, - required this.port, - }); -} - -class SOCKSSocket { - late List _auth; - late RawSocket _sock; - SOCKSRequest? _request; - - StreamSubscription? _sockSub; - StreamSubscription? get subscription => _sockSub; - - SOCKSState _state = SOCKSState.Starting; - final StreamController _stateStream = - StreamController(); - SOCKSState get state => _state; - Stream get stateStream => _stateStream.stream; - - /// For username:password auth - final String? username; - final String? password; - - /// Waits for state to change to [SOCKSState.Connected] - /// If the connection request returns an error from the - /// socks server it will be thrown as an exception in the stream - /// - /// - Future get _waitForConnect => - stateStream.firstWhere((a) => a == SOCKSState.Connected); - - SOCKSSocket( - RawSocket socket, { - List auth = const [AuthMethods.NoAuth], - this.username, - this.password, - }) { - _sock = socket; - _auth = auth; - _setState(SOCKSState.Starting); - } - - void _setState(SOCKSState ns) { - _state = ns; - _stateStream.add(ns); - } - - /// Issue connect command to proxy - /// - Future connect(String domain) async { - final ds = domain.split(':'); - assert(ds.length == 2, "Domain must contain port, example.com:80"); - - _request = SOCKSRequest( - command: SOCKSCommand.Connect, - addressType: SOCKSAddressType.Domain, - address: AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length), - port: int.tryParse(ds[1]) ?? 80, - ); - await _start(); - await _waitForConnect; - } - - Future connectIp(InternetAddress ip, int port) async { - _request = SOCKSRequest( - command: SOCKSCommand.Connect, - addressType: ip.type == InternetAddressType.IPv4 - ? SOCKSAddressType.IPv4 - : SOCKSAddressType.IPv6, - address: ip.rawAddress, - port: port, - ); - await _start(); - await _waitForConnect; - } - - Future close({bool keepOpen = true}) async { - await _stateStream.close(); - if (!keepOpen) { - await _sock.close(); - } - } - - Future _start() async { - // send auth methods - _setState(SOCKSState.Auth); - //print(">> Version: 5, AuthMethods: $_auth"); - _sock.write([ - 0x05, - _auth.length, - ..._auth.map((v) => v.rawValue), - ]); - - _sockSub = _sock.listen((RawSocketEvent ev) { - switch (ev) { - case RawSocketEvent.read: - { - final have = _sock.available(); - final data = _sock.read(have); - if (data != null) { - _handleRead(data); - } else { - print("========= sock read DATA is NULL"); - } - break; - } - case RawSocketEvent.closed: - { - _sockSub?.cancel(); - break; - } - default: - print("AAAAAAAAAAAAA: unhandled raw socket event: $ev"); - // case RawSocketEvent.closed: - // // TODO: Handle this case. - // break; - // case RawSocketEvent.read: - // // TODO: Handle this case. - // break; - // case RawSocketEvent.readClosed: - // // TODO: Handle this case. - // break; - // case RawSocketEvent.write: - // // TODO: Handle this case. - // break; - } - }); - } - - void _sendUsernamePassword(String uname, String password) { - if (uname.length > 255 || password.length > 255) { - throw "Username or Password is too long"; - } - - final data = [ - RFC1929Version, - uname.length, - ...const AsciiEncoder().convert(uname), - password.length, - ...const AsciiEncoder().convert(password) - ]; - - //print(">> Sending $username:$password"); - _sock.write(data); - } - - void _handleRead(Uint8List data) async { - if (state == SOCKSState.Auth) { - if (data.length == 2) { - final version = data[0]; - final auth = AuthMethods.fromValue(data[1]); - - print("_handleRead << Version: $version, Auth: $auth"); - - switch (auth) { - case AuthMethods.UsernamePassword: - _setState(SOCKSState.AuthStarted); - _sendUsernamePassword(username ?? '', password ?? ''); - break; - case AuthMethods.NoAuth: - _setState(SOCKSState.RequestReady); - _writeRequest(_request!); - - break; - default: - throw "No auth methods acceptable"; - } - } else { - throw "Expected 2 bytes"; - } - } else if (_state == SOCKSState.AuthStarted) { - if (_auth.contains(AuthMethods.UsernamePassword)) { - final version = data[0]; - final status = data[1]; - - if (version != RFC1929Version || status != 0x00) { - throw "Invalid username or password"; - } else { - _setState(SOCKSState.RequestReady); - _writeRequest(_request!); - } - } - } else if (_state == SOCKSState.RequestReady) { - if (data.length >= 10) { - final version = data[0]; - final reply = SOCKSReply.fromValue(data[1]); - //data[2] reserved - final addrType = SOCKSAddressType.fromValue(data[3]); - Uint8List addr; - int port = 0; - - switch (addrType) { - case SOCKSAddressType.Domain: - final len = data[4]; - addr = data.sublist(5, 5 + len); - port = data[5 + len] << 8 | data[6 + len]; - break; - case SOCKSAddressType.IPv4: - addr = data.sublist(5, 9); - port = data[9] << 8 | data[10]; - break; - case SOCKSAddressType.IPv6: - addr = data.sublist(5, 21); - port = data[21] << 8 | data[22]; - break; - } - - print( - "<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port"); - if (reply.rawValue == SOCKSReply.Success.rawValue) { - _setState(SOCKSState.Connected); - } else { - throw reply; - } - } else { - throw "Expected 10 bytes"; - } - } - } - - void _writeRequest(SOCKSRequest req) { - if (_state == SOCKSState.RequestReady) { - final data = [ - req.version, - req.command.rawValue, - 0x00, - req.addressType.rawValue, - if (req.addressType == SOCKSAddressType.Domain) - req.address.lengthInBytes, - ...req.address, - req.port >> 8, - req.port & 0xF0, - ]; - - print( - "_writeRequest >> Version: ${req.version}, Command: ${req.command}, AddrType: ${req.addressType}, Addr: ${req.getAddressString()}, Port: ${req.port}"); - _sock.write(data); - } else { - throw "Must be in RequestReady state, current state $_state"; - } - } -} diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart index 6b7e57bef..fcacc60d4 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart @@ -13,7 +13,6 @@ import 'dart:async'; import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/models/epicbox_config_model.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/address_book_views/address_book_view.dart'; @@ -37,14 +36,11 @@ import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; -import 'package:stackwallet/utilities/show_loading.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; -import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:tuple/tuple.dart'; /// [eventBus] should only be set during testing @@ -310,61 +306,6 @@ class _WalletSettingsViewState extends ConsumerState { ); }, ), - if (coin == Coin.firo) - const SizedBox( - height: 8, - ), - if (coin == Coin.firo) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.eye, - title: "Clear electrumx cache", - onPressed: () async { - String? result; - await showDialog( - useSafeArea: false, - barrierDismissible: true, - context: context, - builder: (_) => StackOkDialog( - title: - "Are you sure you want to clear " - "${coin.prettyName} electrumx cache?", - onOkPressed: (value) { - result = value; - }, - leftButton: SecondaryButton( - label: "Cancel", - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ), - ); - - if (result == "OK" && mounted) { - await showLoading( - whileFuture: Future.wait( - [ - Future.delayed( - const Duration( - milliseconds: 1500, - ), - ), - DB.instance - .clearSharedTransactionCache( - coin: coin, - ), - ], - ), - context: context, - message: "Clearing cache...", - ); - } - }, - ); - }, - ), if (coin == Coin.nano || coin == Coin.banano) const SizedBox( height: 8, diff --git a/lib/pages/wallet_view/sub_widgets/tx_icon.dart b/lib/pages/wallet_view/sub_widgets/tx_icon.dart index 46972c49b..d86ad6e8d 100644 --- a/lib/pages/wallet_view/sub_widgets/tx_icon.dart +++ b/lib/pages/wallet_view/sub_widgets/tx_icon.dart @@ -35,7 +35,6 @@ class TxIcon extends ConsumerWidget { String _getAssetName( bool isCancelled, bool isReceived, bool isPending, IThemeAssets assets) { - if (!isReceived && transaction.subType == TransactionSubType.mint) { if (isCancelled) { return Assets.svg.anonymizeFailed; @@ -48,7 +47,7 @@ class TxIcon extends ConsumerWidget { if (isReceived) { if (isCancelled) { - return assets.receiveCancelled; + return assets.receive; } if (isPending) { return assets.receivePending; diff --git a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart index 88d0d8b1a..2b1ba62c4 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart @@ -358,6 +358,8 @@ class _TransactionDetailsViewState final currentHeight = ref.watch(walletsChangeNotifierProvider .select((value) => value.getManager(walletId).currentHeight)); + print("THIS TRANSACTION IS $_transaction"); + return ConditionalParent( condition: !isDesktop, builder: (child) => Background( @@ -1582,7 +1584,8 @@ class _TransactionDetailsViewState coin.requiredConfirmations, ) == false && - _transaction.isCancelled == false) + _transaction.isCancelled == false && + _transaction.type == TransactionType.outgoing) ? ConditionalParent( condition: isDesktop, builder: (child) => Padding( diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh index 1ba99c0bd..9a119d0d6 100755 --- a/scripts/linux/build_all.sh +++ b/scripts/linux/build_all.sh @@ -9,7 +9,7 @@ mkdir -p build (cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_monero_all.sh && ./build_sharedfile.sh ) & -(cd ../../crypto_plugins/flutter_libtor/scripts/linux && ./build_all.sh ) & +(cd ../../crypto_plugins/tor/scripts/linux && ./build_all.sh ) & wait echo "Done building" diff --git a/test/json_rpc_test.dart b/test/json_rpc_test.dart index b5df1d52f..333c1bde6 100644 --- a/test/json_rpc_test.dart +++ b/test/json_rpc_test.dart @@ -11,7 +11,6 @@ void main() { port: DefaultNodes.bitcoin.port, useSSL: true, connectionTimeout: const Duration(seconds: 40), - proxyInfo: null, // TODO test for proxyInfo ); const jsonRequestString = @@ -28,8 +27,7 @@ void main() { final jsonRPC = JsonRPC( host: "some.bad.address.thingdsfsdfsdaf", port: 3000, - connectionTimeout: const Duration(seconds: 10), - proxyInfo: null, + connectionTimeout: Duration(seconds: 10), ); const jsonRequestString = @@ -49,7 +47,6 @@ void main() { port: 3000, useSSL: false, connectionTimeout: const Duration(seconds: 1), - proxyInfo: null, ); const jsonRequestString = diff --git a/test/services/coins/firo/firo_wallet_test.dart b/test/services/coins/firo/firo_wallet_test.dart index 2bda494fc..05b4aeeff 100644 --- a/test/services/coins/firo/firo_wallet_test.dart +++ b/test/services/coins/firo/firo_wallet_test.dart @@ -2286,8 +2286,8 @@ void main() { when(cachedClient.getAnonymitySet( groupId: "1", blockhash: "", coin: Coin.firo)) .thenAnswer((_) async => GetAnonymitySetSampleData.data); - when(cachedClient.getUsedCoinSerials(coin: Coin.firo)).thenAnswer( - (_) async => List.from( + when(cachedClient.getUsedCoinSerials(startNumber: 0, coin: Coin.firo)) + .thenAnswer((_) async => List.from( GetUsedSerialsSampleData.serials['serials'] as List)); final firo = FiroWallet( From 256db8547214e82ad17eb49311c798678a418215 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 15 Aug 2023 22:56:41 -0500 Subject: [PATCH 089/237] use socks socket if useTor in ElectrumX and JsonRPC, --- .gitignore | 4 + crypto_plugins/flutter_libtor | 2 +- lib/electrumx_rpc/electrumx.dart | 155 +++++++++++++++++++++++------ lib/electrumx_rpc/rpc.dart | 164 +++++++++++++++++++++++++------ lib/networking/socks_socket.dart | 112 +++++++++++++++++++++ lib/networking/tor_service.dart | 3 +- scripts/linux/build_all.sh | 2 +- test/json_rpc_test.dart | 5 +- 8 files changed, 382 insertions(+), 65 deletions(-) create mode 100644 lib/networking/socks_socket.dart diff --git a/.gitignore b/.gitignore index c38882323..e58a9412f 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,7 @@ libmobileliblelantus.dll libtor_ffi.dll /libisar.so libtor_ffi.so + +tor_logs.txt + +torrc diff --git a/crypto_plugins/flutter_libtor b/crypto_plugins/flutter_libtor index 6aca8f78a..fc91c3f42 160000 --- a/crypto_plugins/flutter_libtor +++ b/crypto_plugins/flutter_libtor @@ -1 +1 @@ -Subproject commit 6aca8f78a10972ce07ee1ededcce02e97cc46834 +Subproject commit fc91c3f421467545f198d95558848e94de2fa6d9 diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index c9417116d..7d3dd3d2b 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -15,6 +15,7 @@ import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:decimal/decimal.dart'; import 'package:stackwallet/electrumx_rpc/rpc.dart'; import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; +import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:uuid/uuid.dart'; @@ -71,6 +72,8 @@ class ElectrumX { final Duration connectionTimeoutForSpecialCaseJsonRPCClients; + ({String host, int port})? proxyInfo; + ElectrumX({ required String host, required int port, @@ -80,6 +83,7 @@ class ElectrumX { JsonRPC? client, this.connectionTimeoutForSpecialCaseJsonRPCClients = const Duration(seconds: 60), + ({String host, int port})? proxyInfo, }) { _prefs = prefs; _host = host; @@ -92,14 +96,38 @@ class ElectrumX { required ElectrumXNode node, required Prefs prefs, required List failovers, - }) => - ElectrumX( + ({String host, int port})? proxyInfo, + }) { + if (Prefs.instance.useTor) { + if (proxyInfo == null) { + // TODO await tor / make sure it's running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.from(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + return ElectrumX( host: node.address, port: node.port, useSSL: node.useSSL, prefs: prefs, failovers: failovers, + proxyInfo: proxyInfo, ); + } else { + return ElectrumX( + host: node.address, + port: node.port, + useSSL: node.useSSL, + prefs: prefs, + failovers: failovers, + proxyInfo: null, + ); + } + } Future _allow() async { if (_prefs.wifiOnly) { @@ -121,20 +149,52 @@ class ElectrumX { throw WifiOnlyException(); } - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - ); + if (Prefs.instance.useTor) { + if (proxyInfo == null) { + // TODO await tor / make sure Tor is running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.request(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } else { + _rpcClient ??= JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } } else { - _rpcClient = JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - ); + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } else { + _rpcClient ??= JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } } try { @@ -153,7 +213,8 @@ class ElectrumX { ); if (response.exception != null) { - throw response.exception!; + throw response.exception! + as Object; // TODO properly check that .exception is an Object } if (response.data is Map && response.data["error"] != null) { @@ -221,20 +282,53 @@ class ElectrumX { throw WifiOnlyException(); } - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - ); + if (Prefs.instance.useTor) { + // TODO await tor / make sure Tor is initialized + if (proxyInfo == null) { + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.batchRequest(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } else { + _rpcClient = JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } } else { - _rpcClient = JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - ); + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } else { + _rpcClient = JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } } try { @@ -260,7 +354,8 @@ class ElectrumX { (await _rpcClient!.request(request, requestTimeout)); if (jsonRpcResponse.exception != null) { - throw jsonRpcResponse.exception!; + throw jsonRpcResponse.exception! + as Object; // TODO properly check that .exception is an Object } final response = jsonRpcResponse.data as List; diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 2dc0d3a71..1b5a42d42 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -14,7 +14,10 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; +import 'package:stackwallet/networking/socks_socket.dart'; +import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; // Json RPC class to handle connecting to electrumx servers class JsonRPC { @@ -23,16 +26,20 @@ class JsonRPC { required this.port, this.useSSL = false, this.connectionTimeout = const Duration(seconds: 60), + required ({String host, int port})? proxyInfo, }); final bool useSSL; final String host; final int port; final Duration connectionTimeout; + ({String host, int port})? proxyInfo; final _requestMutex = Mutex(); final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); Socket? _socket; + SOCKSSocket? _socksSocket; StreamSubscription? _subscription; + StreamSubscription? get subscription => _subscription; void _dataHandler(List data) { _requestQueue.nextIncompleteReq.then((req) { @@ -75,7 +82,12 @@ class JsonRPC { _requestQueue.nextIncompleteReq.then((req) { if (req != null) { // \r\n required by electrumx server - _socket!.write('${req.jsonRequest}\r\n'); + if (_socket != null) { + _socket!.write('${req.jsonRequest}\r\n'); + } + if (_socksSocket != null) { + _socksSocket!.socket.writeln('${req.jsonRequest}\r\n'); + } // TODO different timeout length? req.initiateTimeout( @@ -92,12 +104,22 @@ class JsonRPC { Duration requestTimeout, ) async { await _requestMutex.protect(() async { - if (_socket == null) { - Logging.instance.log( - "JsonRPC request: opening socket $host:$port", - level: LogLevel.Info, - ); - await connect(); + if (!Prefs.instance.useTor) { + if (_socket == null) { + Logging.instance.log( + "JsonRPC request: opening socket $host:$port", + level: LogLevel.Info, + ); + await connect(); + } + } else { + if (_socksSocket == null) { + Logging.instance.log( + "JsonRPC request: opening SOCKS socket to $host:$port", + level: LogLevel.Info, + ); + await connect(); + } } }); @@ -137,6 +159,8 @@ class JsonRPC { _subscription = null; _socket?.destroy(); _socket = null; + await _socksSocket?.close(); + _socksSocket = null; // clean up remaining queue await _requestQueue.completeRemainingWithError( @@ -146,33 +170,100 @@ class JsonRPC { } Future connect() async { - if (_socket != null) { - throw Exception( - "JsonRPC attempted to connect to an already existing socket!", - ); - } + if (!Prefs.instance.useTor) { + if (useSSL) { + _socket = await SecureSocket.connect( + host, + port, + timeout: connectionTimeout, + onBadCertificate: (_) => true, + ); // TODO do not automatically trust bad certificates + } else { + _socket = await Socket.connect( + host, + port, + timeout: connectionTimeout, + ); + } - if (useSSL) { - _socket = await SecureSocket.connect( - host, - port, - timeout: connectionTimeout, - onBadCertificate: (_) => true, - ); // TODO do not automatically trust bad certificates + _subscription = _socket!.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } else { - _socket = await Socket.connect( - host, - port, - timeout: connectionTimeout, - ); - } + if (proxyInfo == null) { + // TODO await tor / make sure it's running + proxyInfo = ( + host: InternetAddress.loopbackIPv4.address, + port: TorService.sharedInstance.port + ); + Logging.instance.log( + "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + level: LogLevel.Warning); + } + // TODO connect to proxy socket... - _subscription = _socket!.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, - ); + // TODO implement ssl over tor + // if (useSSL) { + // _socket = await SecureSocket.connect( + // host, + // port, + // timeout: connectionTimeout, + // onBadCertificate: (_) => true, + // ); // TODO do not automatically trust bad certificates + // final _client = SocksSocket.protected(_socket, type); + // } else { + // instantiate a socks socket at localhost and on the port selected by the tor service + _socksSocket = await SOCKSSocket.create( + proxyHost: InternetAddress.loopbackIPv4.address, + proxyPort: TorService.sharedInstance.port, + ); + + try { + Logging.instance.log( + "JsonRPC.connect(): connecting to SOCKS socket at $proxyInfo...", + level: LogLevel.Info); + + await _socksSocket?.connect(); + + Logging.instance.log( + "JsonRPC.connect(): connected to SOCKS socket at $proxyInfo...", + level: LogLevel.Info); + } catch (e) { + Logging.instance.log( + "JsonRPC.connect(): failed to connect to SOCKS socket at $proxyInfo, $e", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to connect to SOCKS socket at $proxyInfo, $e"); + } + + try { + Logging.instance.log( + "JsonRPC.connect(): connecting to $host:$port over SOCKS socket at $proxyInfo...", + level: LogLevel.Info); + + await _socksSocket?.connectTo(host, port); + + Logging.instance.log( + "JsonRPC.connect(): connected to $host:$port over SOCKS socket at $proxyInfo", + level: LogLevel.Info); + } catch (e) { + Logging.instance.log( + "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", + level: LogLevel.Error); + throw Exception( + "JsonRPC.connect(): failed to connect to tor proxy, $e"); + } + + // _subscription = _socksSocket!.socket.listen( + // _dataHandler, + // onError: _errorHandler, + // onDone: _doneHandler, + // cancelOnError: true, + // ) as StreamSubscription?; + } } } @@ -295,3 +386,14 @@ class JsonRPCResponse { JsonRPCResponse({this.data, this.exception}); } + +bool isIpAddress(String host) { + try { + // if the string can be parsed into an InternetAddress, it's an IP. + InternetAddress(host); + return true; + } catch (e) { + // if parsing fails, it's not an IP. + return false; + } +} diff --git a/lib/networking/socks_socket.dart b/lib/networking/socks_socket.dart new file mode 100644 index 000000000..4d66e0357 --- /dev/null +++ b/lib/networking/socks_socket.dart @@ -0,0 +1,112 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +class SOCKSSocket { + final String proxyHost; + final int proxyPort; + + late final Socket _socksSocket; + Socket get socket => _socksSocket; + + final StreamController> _responseController = + StreamController.broadcast(); + + // Private constructor + SOCKSSocket._(this.proxyHost, this.proxyPort); + + static Future create( + {required String proxyHost, required int proxyPort}) async { + var instance = SOCKSSocket._(proxyHost, proxyPort); + await instance._init(); + return instance; + } + + SOCKSSocket({required this.proxyHost, required this.proxyPort}) { + _init(); + } + + /// Initializes the SOCKS socket. + + Future _init() async { + _socksSocket = await Socket.connect( + proxyHost, + proxyPort, + ); + + _socksSocket.listen( + (data) { + _responseController.add(data); + }, + onError: (dynamic e) { + if (e is Object) { + _responseController.addError(e); + } + _responseController.addError("$e"); + // TODO make sure sending error as string is acceptable + }, + onDone: () { + _responseController.close(); + }, + ); + } + + /// Connects to the SOCKS socket. + Future connect() async { + // Greeting and method selection + _socksSocket.add([0x05, 0x01, 0x00]); + + // Wait for server response + var response = await _responseController.stream.first; + if (response[1] != 0x00) { + throw Exception('Failed to connect to SOCKS5 socket.'); + } + } + + /// Connects to the specified [domain] and [port] through the SOCKS socket. + Future connectTo(String domain, int port) async { + var request = [ + 0x05, + 0x01, + 0x00, + 0x03, + domain.length, + ...domain.codeUnits, + (port >> 8) & 0xFF, + port & 0xFF + ]; + + _socksSocket.add(request); + + var response = await _responseController.stream.first; + if (response[1] != 0x00) { + throw Exception('Failed to connect to target through SOCKS5 proxy.'); + } + } + + /// Converts [object] to a String by invoking [Object.toString] and + /// sends the encoding of the result to the socket. + void write(Object? object) { + if (object == null) return; + + List data = utf8.encode(object.toString()); + _socksSocket.add(data); + } + + /// Sends the server.features command to the proxy server. + Future sendServerFeaturesCommand() async { + const String command = + '{"jsonrpc":"2.0","id":"0","method":"server.features","params":[]}'; + _socksSocket.writeln(command); + + var responseData = await _responseController.stream.first; + print("responseData: ${utf8.decode(responseData)}"); + } + + /// Closes the connection to the Tor proxy. + Future close() async { + await _socksSocket.flush(); // Ensure all data is sent before closing + await _responseController.close(); + return await _socksSocket.close(); + } +} diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart index 9c27a35e0..7085f5401 100644 --- a/lib/networking/tor_service.dart +++ b/lib/networking/tor_service.dart @@ -12,7 +12,8 @@ class TorService { Future start() async { final dir = await StackFileSystem.applicationTorDirectory(); - return await _tor.start(torDir: dir); + await _tor.start(torDir: dir); + return; } Future stop() async { diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh index 9a119d0d6..1ba99c0bd 100755 --- a/scripts/linux/build_all.sh +++ b/scripts/linux/build_all.sh @@ -9,7 +9,7 @@ mkdir -p build (cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_monero_all.sh && ./build_sharedfile.sh ) & -(cd ../../crypto_plugins/tor/scripts/linux && ./build_all.sh ) & +(cd ../../crypto_plugins/flutter_libtor/scripts/linux && ./build_all.sh ) & wait echo "Done building" diff --git a/test/json_rpc_test.dart b/test/json_rpc_test.dart index 333c1bde6..b5df1d52f 100644 --- a/test/json_rpc_test.dart +++ b/test/json_rpc_test.dart @@ -11,6 +11,7 @@ void main() { port: DefaultNodes.bitcoin.port, useSSL: true, connectionTimeout: const Duration(seconds: 40), + proxyInfo: null, // TODO test for proxyInfo ); const jsonRequestString = @@ -27,7 +28,8 @@ void main() { final jsonRPC = JsonRPC( host: "some.bad.address.thingdsfsdfsdaf", port: 3000, - connectionTimeout: Duration(seconds: 10), + connectionTimeout: const Duration(seconds: 10), + proxyInfo: null, ); const jsonRequestString = @@ -47,6 +49,7 @@ void main() { port: 3000, useSSL: false, connectionTimeout: const Duration(seconds: 1), + proxyInfo: null, ); const jsonRequestString = From e8d5c3ad8b865fbe7e21dcd4c58951b98e2e715b Mon Sep 17 00:00:00 2001 From: likho Date: Wed, 16 Aug 2023 14:46:21 +0200 Subject: [PATCH 090/237] Return tx id when sending, implement updateSentTx --- lib/services/coins/tezos/tezos_wallet.dart | 64 +++++++++++++++++----- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 857f62f12..56e08ba8b 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -30,6 +30,7 @@ import 'package:tezart/tezart.dart'; import 'package:tuple/tuple.dart'; const int MINIMUM_CONFIRMATIONS = 1; +const int _gasLimit = 10200; class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { TezosWallet({ @@ -201,8 +202,15 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { final client = TezartClient(getCurrentNode().host); int? sendAmount = microtezToInt; + int gasLimit = _gasLimit; + int thisFee = feeInMicroTez; + if (balance.spendable == txData["recipientAmt"] as Amount) { - sendAmount = microtezToInt - feeInMicroTez; + //Fee guides for emptying a tz account + // https://github.com/TezTech/eztz/blob/master/PROTO_004_FEES.md + thisFee = thisFee + 32; + sendAmount = microtezToInt - thisFee; + gasLimit = _gasLimit + 320; } final operation = await client.transferOperation( @@ -210,11 +218,10 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { destination: destinationAddress, amount: sendAmount, customFee: feeInMicroTez, - customGasLimit: feeInMicroTez + customGasLimit: gasLimit ); - - await operation.executeAndMonitor(); // This line gives an error - return Future.value(""); + await operation.executeAndMonitor(); + return operation.result.id as String; } catch (e) { Logging.instance.log(e.toString(), level: LogLevel.Error); return Future.error(e); @@ -413,12 +420,11 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateBalance() async { try { - final client = TezartClient(getCurrentNode().host); - final thisBalance = await client.getBalance( - address: await currentReceivingAddress - ); + String balanceCall = "https://api.mainnet.tzkt.io/v1/accounts/" + "${await currentReceivingAddress}/balance"; + var response = jsonDecode(await get(Uri.parse(balanceCall)).then((value) => value.body)); Amount balanceInAmount = Amount( - rawValue: BigInt.parse(thisBalance.toString()), + rawValue: BigInt.parse(response.toString()), fractionDigits: coin.decimals); _balance = Balance( total: balanceInAmount, @@ -436,7 +442,8 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future updateTransactions() async { - String transactionsCall = "https://api.mainnet.tzkt.io/v1/accounts/${await currentReceivingAddress}/operations"; + String transactionsCall = "https://api.mainnet.tzkt.io/v1/accounts/" + "${await currentReceivingAddress}/operations"; var response = jsonDecode(await get(Uri.parse(transactionsCall)).then((value) => value.body)); List> txs = []; for (var tx in response as List) { @@ -544,9 +551,38 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future updateSentCachedTxData(Map txData) { - // TODO: implement updateSentCachedTxData - throw UnimplementedError(); + Future updateSentCachedTxData(Map txData) async { + final transaction = Transaction( + walletId: walletId, + txid: txData["txid"] as String, + timestamp: DateTime.now().millisecondsSinceEpoch ~/ 1000, + type: TransactionType.outgoing, + subType: TransactionSubType.none, + // precision may be lost here hence the following amountString + amount: (txData["recipientAmt"] as Amount).raw.toInt(), + amountString: (txData["recipientAmt"] as Amount).toJsonString(), + fee: txData["fee"] as int, + height: null, + isCancelled: false, + isLelantus: false, + otherData: null, + slateId: null, + nonce: null, + inputs: [], + outputs: [], + numberOfMessages: null, + ); + + final address = txData["address"] is String + ? await db.getAddress(walletId, txData["address"] as String) + : null; + + await db.addNewTransactionData( + [ + Tuple2(transaction, address), + ], + walletId, + ); } @override From 444860da53ad13a87137e79c8985eefa120d0343 Mon Sep 17 00:00:00 2001 From: likho Date: Wed, 16 Aug 2023 15:17:58 +0200 Subject: [PATCH 091/237] Return just one value for fees since endpoint returns only one value for fees --- lib/services/coins/tezos/tezos_wallet.dart | 35 +++++++--------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 56e08ba8b..1fb192190 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -239,29 +239,17 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future estimateFeeFor(Amount amount, int feeRate) async { - // TODO: Check if this is correct - var api = "https://api.tzstats.com/series/op?start_date=today&collapse=10d"; + + var api = "https://api.tzstats.com/series/op?start_date=today&collapse=1d"; var response = jsonDecode((await get(Uri.parse(api))).body)[0]; double totalFees = response[4] as double; int totalTxs = response[8] as int; int feePerTx = (totalFees / totalTxs * 1000000).floor(); - int estimatedFee = 0; - Logging.instance.log("feePerTx:$feePerTx", level: LogLevel.Info); - Logging.instance.log("feeRate:$feeRate", level: LogLevel.Info); - switch (feeRate) { - case 0: - estimatedFee = feePerTx * 2; - case 1: - estimatedFee = feePerTx; - case 2: - case 3: - estimatedFee = (feePerTx / 2).floor(); - default: - estimatedFee = feeRate; - } - Logging.instance.log("estimatedFee:$estimatedFee", level: LogLevel.Info); + return Amount( - rawValue: BigInt.from(estimatedFee), fractionDigits: coin.decimals); + rawValue: BigInt.from(feePerTx), + fractionDigits: coin.decimals, + ); } @override @@ -272,21 +260,20 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future get fees async { - // TODO: Check if this is correct var api = "https://api.tzstats.com/series/op?start_date=today&collapse=10d"; var response = jsonDecode((await get(Uri.parse(api))).body); double totalFees = response[0][4] as double; int totalTxs = response[0][8] as int; int feePerTx = (totalFees / totalTxs * 1000000).floor(); Logging.instance.log("feePerTx:$feePerTx", level: LogLevel.Info); - // TODO: fix numberOfBlocks + // TODO: fix numberOfBlocks - Since there is only one fee no need to set blocks return FeeObject( - numberOfBlocksFast: 3, + numberOfBlocksFast: 10, numberOfBlocksAverage: 10, - numberOfBlocksSlow: 30, - fast: (feePerTx * 2), + numberOfBlocksSlow: 10, + fast: feePerTx, medium: feePerTx, - slow: (feePerTx / 2).floor(), + slow: feePerTx, ); } From 2732b2fe7170edee191ee156bfd712ea3ca94281 Mon Sep 17 00:00:00 2001 From: likho Date: Tue, 22 Aug 2023 18:33:24 +0200 Subject: [PATCH 092/237] WIP: XLM fixes and refactor --- .../add_edit_node_view.dart | 9 ++- .../coins/stellar/stellar_wallet.dart | 66 +++++++------------ .../test_stellar_node_connection.dart | 22 +++++++ 3 files changed, 54 insertions(+), 43 deletions(-) create mode 100644 lib/utilities/test_stellar_node_connection.dart diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 56b008093..af6256d23 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -27,6 +27,7 @@ import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/test_epic_box_connection.dart'; import 'package:stackwallet/utilities/test_monero_node_connection.dart'; +import 'package:stackwallet/utilities/test_stellar_node_connection.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; @@ -194,10 +195,14 @@ class _AddEditNodeViewState extends ConsumerState { // await client.getSyncStatus(); } catch (_) {} - case Coin.nano: - case Coin.banano: case Coin.stellar: case Coin.stellarTestnet: + try { + testPassed = await testStellarNodeConnection(formData.host!); + } catch(_) {} + case Coin.nano: + case Coin.banano: + throw UnimplementedError(); //TODO: check network/node } diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index c4c92373f..6fecb6eb3 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -1,5 +1,7 @@ import 'dart:async'; +import 'dart:convert'; +import 'package:decimal/decimal.dart'; import 'package:http/http.dart' as http; import 'package:isar/isar.dart'; import 'package:stackwallet/db/isar/main_db.dart'; @@ -37,6 +39,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { late StellarSDK stellarSdk; late Network stellarNetwork; + StellarWallet({ required String walletId, required String walletName, @@ -53,20 +56,28 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { initCache(walletId, coin); initWalletDB(mockableOverride: mockableOverride); - if (coin.name == "stellarTestnet") { + + if (coin.isTestNet) { stellarSdk = StellarSDK.TESTNET; stellarNetwork = Network.TESTNET; } else { stellarSdk = StellarSDK.PUBLIC; stellarNetwork = Network.PUBLIC; } + + _updateNode(); + } + + void _updateNode() { + _xlmNode = NodeService(secureStorageInterface: _secureStore) + .getPrimaryNodeFor(coin: coin) ?? + DefaultNodes.getNodeFor(coin); + stellarSdk = StellarSDK("${_xlmNode!.host}:${_xlmNode!.port}"); } late final TransactionNotificationTracker txTracker; late SecureStorageInterface _secureStore; - // final StellarSDK stellarSdk = StellarSDK.PUBLIC; - @override bool get isFavorite => _isFavorite ??= getCachedIsFavorite(); bool? _isFavorite; @@ -232,32 +243,14 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { (await _currentReceivingAddress)?.value ?? await getAddressSW(); Future getBaseFee() async { - // final nodeURI = Uri.parse("${getCurrentNode().host}:${getCurrentNode().port}"); - final nodeURI = Uri.parse(getCurrentNode().host); - final httpClient = http.Client(); - FeeStatsResponse fsp = - await FeeStatsRequestBuilder(httpClient, nodeURI).execute(); - return int.parse(fsp.lastLedgerBaseFee); + var fees = await stellarSdk.feeStats.execute(); + return int.parse(fees.lastLedgerBaseFee); } @override Future estimateFeeFor(Amount amount, int feeRate) async { var baseFee = await getBaseFee(); - int fee = 100; - switch (feeRate) { - case 0: - fee = baseFee * 10; - case 1: - case 2: - fee = baseFee * 50; - case 3: - fee = baseFee * 100; - case 4: - fee = baseFee * 200; - default: - fee = baseFee * 50; - } - return Amount(rawValue: BigInt.from(fee), fractionDigits: coin.decimals); + return Amount(rawValue: BigInt.from(baseFee), fractionDigits: coin.decimals); } @override @@ -285,20 +278,13 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future get fees async { - // final nodeURI = Uri.parse("${getCurrentNode().host}:${getCurrentNode().port}"); - final nodeURI = Uri.parse(getCurrentNode().host); - - final httpClient = http.Client(); - FeeStatsResponse fsp = - await FeeStatsRequestBuilder(httpClient, nodeURI).execute(); - return FeeObject( - numberOfBlocksFast: 0, - numberOfBlocksAverage: 0, - numberOfBlocksSlow: 0, - fast: int.parse(fsp.lastLedgerBaseFee) * 100, - medium: int.parse(fsp.lastLedgerBaseFee) * 50, - slow: int.parse(fsp.lastLedgerBaseFee) * 10); + numberOfBlocksFast: 10, + numberOfBlocksAverage: 10, + numberOfBlocksSlow: 10, + fast: 1, + medium: 1, + slow: 1); } @override @@ -399,6 +385,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { {required String address, required Amount amount, Map? args}) async { + try { final feeRate = args?["feeRate"]; var fee = 1000; @@ -750,10 +737,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future updateNode(bool shouldRefresh) async { - _xlmNode = NodeService(secureStorageInterface: _secureStore) - .getPrimaryNodeFor(coin: coin) ?? - DefaultNodes.getNodeFor(coin); - + _updateNode(); if (shouldRefresh) { unawaited(refresh()); } diff --git a/lib/utilities/test_stellar_node_connection.dart b/lib/utilities/test_stellar_node_connection.dart new file mode 100644 index 000000000..12e1e8dc9 --- /dev/null +++ b/lib/utilities/test_stellar_node_connection.dart @@ -0,0 +1,22 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; + +Future testStellarNodeConnection(String host) async { + + final client = http.Client(); + Uri uri = Uri.parse(host); + final response = await client.get( + uri, + headers: {'Content-Type': 'application/json'}, + ).timeout(const Duration(milliseconds: 2000), + onTimeout: () async => http.Response('Error', 408)); + + final json = jsonDecode(response.body); + + if (response.statusCode == 200 && json["horizon_version"] != null) { + return true; + } else { + return false; + } +} \ No newline at end of file From 04bba2bf2a2905f96e3eda51806a308c7d3f0b51 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Aug 2023 15:07:08 -0600 Subject: [PATCH 093/237] new wallet mnemonic options for supported coins --- .../name_your_wallet_view.dart | 92 ++-- .../new_wallet_options_view.dart | 409 ++++++++++++++++++ ...w_wallet_recovery_phrase_warning_view.dart | 32 +- lib/route_generator.dart | 16 + lib/services/coins/banano/banano_wallet.dart | 4 +- .../coins/bitcoin/bitcoin_wallet.dart | 25 +- .../coins/bitcoincash/bitcoincash_wallet.dart | 25 +- lib/services/coins/coin_service.dart | 4 +- .../coins/dogecoin/dogecoin_wallet.dart | 22 +- lib/services/coins/ecash/ecash_wallet.dart | 25 +- .../coins/epiccash/epiccash_wallet.dart | 9 +- .../coins/ethereum/ethereum_wallet.dart | 25 +- lib/services/coins/firo/firo_wallet.dart | 22 +- .../coins/litecoin/litecoin_wallet.dart | 22 +- lib/services/coins/manager.dart | 4 +- lib/services/coins/monero/monero_wallet.dart | 4 +- .../coins/namecoin/namecoin_wallet.dart | 22 +- lib/services/coins/nano/nano_wallet.dart | 4 +- .../coins/particl/particl_wallet.dart | 22 +- .../coins/stellar/stellar_wallet.dart | 26 +- .../coins/wownero/wownero_wallet.dart | 5 +- lib/utilities/enums/coin_enum.dart | 29 ++ 22 files changed, 745 insertions(+), 103 deletions(-) create mode 100644 lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart diff --git a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart index 4e04fcb80..4f88f99b3 100644 --- a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart +++ b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart @@ -14,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart'; +import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart'; import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart'; import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; @@ -336,46 +337,59 @@ class _NameYourWalletViewState extends ConsumerState { ref.read(walletsServiceChangeNotifierProvider); final name = textEditingController.text; - if (await walletsService.checkForDuplicate(name)) { - unawaited(showFloatingFlushBar( - type: FlushBarType.warning, - message: "Wallet name already in use.", - iconAsset: Assets.svg.circleAlert, - context: context, - )); - } else { - // hide keyboard if has focus - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 50)); - } + final hasDuplicateName = + await walletsService.checkForDuplicate(name); - if (mounted) { - switch (widget.addWalletType) { - case AddWalletType.New: - unawaited(Navigator.of(context).pushNamed( - NewWalletRecoveryPhraseWarningView.routeName, - arguments: Tuple2( - name, - coin, - ), - )); - break; - case AddWalletType.Restore: - ref - .read(mnemonicWordCountStateProvider.state) - .state = Constants.possibleLengthsForCoin( - coin) - .first; - unawaited(Navigator.of(context).pushNamed( - RestoreOptionsView.routeName, - arguments: Tuple2( - name, - coin, - ), - )); - break; + if (mounted) { + if (hasDuplicateName) { + unawaited(showFloatingFlushBar( + type: FlushBarType.warning, + message: "Wallet name already in use.", + iconAsset: Assets.svg.circleAlert, + context: context, + )); + } else { + // hide keyboard if has focus + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 50)); + } + + if (mounted) { + ref + .read(mnemonicWordCountStateProvider.state) + .state = + Constants.possibleLengthsForCoin(coin).last; + + switch (widget.addWalletType) { + case AddWalletType.New: + unawaited( + Navigator.of(context).pushNamed( + coin.hasMnemonicPassphraseSupport + ? NewWalletOptionsView.routeName + : NewWalletRecoveryPhraseWarningView + .routeName, + arguments: Tuple2( + name, + coin, + ), + ), + ); + break; + + case AddWalletType.Restore: + unawaited( + Navigator.of(context).pushNamed( + RestoreOptionsView.routeName, + arguments: Tuple2( + name, + coin, + ), + ), + ); + break; + } } } } diff --git a/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart b/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart new file mode 100644 index 000000000..4f2dfb180 --- /dev/null +++ b/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart @@ -0,0 +1,409 @@ +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart'; +import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart'; +import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/mobile_mnemonic_length_selector.dart'; +import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/sub_widgets/mnemonic_word_count_select_sheet.dart'; +import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; +import 'package:stackwallet/providers/ui/verify_recovery_phrase/mnemonic_word_count_state_provider.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/background.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; +import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; +import 'package:stackwallet/widgets/stack_text_field.dart'; +import 'package:tuple/tuple.dart'; + +final pNewWalletOptions = + StateProvider<({String mnemonicPassphrase, int mnemonicWordsCount})?>( + (ref) => null); + +enum NewWalletOptions { + Default, + Advanced; +} + +class NewWalletOptionsView extends ConsumerStatefulWidget { + const NewWalletOptionsView({ + Key? key, + required this.walletName, + required this.coin, + }) : super(key: key); + + static const routeName = "/newWalletOptionsView"; + + final String walletName; + final Coin coin; + + @override + ConsumerState createState() => + _NewWalletOptionsViewState(); +} + +class _NewWalletOptionsViewState extends ConsumerState { + late final FocusNode passwordFocusNode; + late final TextEditingController passwordController; + + bool hidePassword = true; + NewWalletOptions _selectedOptions = NewWalletOptions.Default; + + @override + void initState() { + passwordController = TextEditingController(); + passwordFocusNode = FocusNode(); + + super.initState(); + } + + @override + void dispose() { + passwordController.dispose(); + passwordFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final lengths = Constants.possibleLengthsForCoin(widget.coin).toList(); + return ConditionalParent( + condition: Util.isDesktop, + builder: (child) => DesktopScaffold( + background: Theme.of(context).extension()!.background, + appBar: const DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + ), + body: SizedBox( + width: 480, + child: child, + ), + ), + child: ConditionalParent( + condition: !Util.isDesktop, + builder: (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: const AppBarBackButton(), + title: Text( + "Wallet Options", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ), + ), + ); + }, + ), + ), + ), + ), + child: Column( + children: [ + if (Util.isDesktop) + const Spacer( + flex: 10, + ), + if (!Util.isDesktop) + CoinImage( + coin: widget.coin, + height: 100, + width: 100, + ), + SizedBox( + height: Util.isDesktop ? 0 : 16, + ), + Text( + "Wallet options", + textAlign: TextAlign.center, + style: Util.isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), + ), + SizedBox( + height: Util.isDesktop ? 32 : 16, + ), + DropdownButtonHideUnderline( + child: DropdownButton2( + value: _selectedOptions, + items: [ + ...NewWalletOptions.values.map( + (e) => DropdownMenuItem( + value: e, + child: Text( + e.name, + style: STextStyles.desktopTextMedium(context), + ), + ), + ), + ], + onChanged: (value) { + if (value is NewWalletOptions) { + setState(() { + _selectedOptions = value; + }); + } + }, + isExpanded: true, + iconStyleData: IconStyleData( + icon: SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + height: 6, + color: Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), + ), + dropdownStyleData: DropdownStyleData( + offset: const Offset(0, -10), + elevation: 0, + decoration: BoxDecoration( + color: Theme.of(context) + .extension()! + .textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + menuItemStyleData: const MenuItemStyleData( + padding: EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + ), + ), + ), + const SizedBox( + height: 24, + ), + if (_selectedOptions == NewWalletOptions.Advanced) + Column( + children: [ + if (Util.isDesktop) + DropdownButtonHideUnderline( + child: DropdownButton2( + value: ref + .watch(mnemonicWordCountStateProvider.state) + .state, + items: [ + ...lengths.map( + (e) => DropdownMenuItem( + value: e, + child: Text( + "$e word seed", + style: STextStyles.desktopTextMedium(context), + ), + ), + ), + ], + onChanged: (value) { + if (value is int) { + ref + .read(mnemonicWordCountStateProvider.state) + .state = value; + } + }, + isExpanded: true, + iconStyleData: IconStyleData( + icon: SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + height: 6, + color: Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), + ), + dropdownStyleData: DropdownStyleData( + offset: const Offset(0, -10), + elevation: 0, + decoration: BoxDecoration( + color: Theme.of(context) + .extension()! + .textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + menuItemStyleData: const MenuItemStyleData( + padding: EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + ), + ), + ), + if (!Util.isDesktop) + MobileMnemonicLengthSelector( + chooseMnemonicLength: () { + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: (_) { + return MnemonicWordCountSelectSheet( + lengthOptions: lengths, + ); + }, + ); + }, + ), + const SizedBox( + height: 24, + ), + RoundedWhiteContainer( + child: Center( + child: Text( + "You may protect the wallet seed with an optional passphrase. " + "If you lose this passphrase you will not be able " + "to restore using just your seed words.", + style: Util.isDesktop + ? STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ) + : STextStyles.itemSubtitle(context), + ), + ), + ), + const SizedBox( + height: 8, + ), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key("mnemonicPassphraseFieldKey1"), + focusNode: passwordFocusNode, + controller: passwordController, + style: Util.isDesktop + ? STextStyles.desktopTextMedium(context).copyWith( + height: 2, + ) + : STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Recovery phrase password", + passwordFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: ConditionalParent( + condition: Util.isDesktop, + builder: (child) => SizedBox( + height: 70, + child: child, + ), + child: Row( + children: [ + SizedBox( + width: Util.isDesktop ? 24 : 16, + ), + GestureDetector( + key: const Key( + "mnemonicPassphraseFieldShowPasswordButtonKey"), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: Theme.of(context) + .extension()! + .textDark3, + width: Util.isDesktop ? 24 : 16, + height: Util.isDesktop ? 24 : 16, + ), + ), + const SizedBox( + width: 12, + ), + ], + ), + ), + ), + ), + ), + ), + ], + ), + if (!Util.isDesktop) const Spacer(), + SizedBox( + height: Util.isDesktop ? 32 : 16, + ), + PrimaryButton( + label: "Continue", + onPressed: () { + if (_selectedOptions == NewWalletOptions.Advanced) { + ref.read(pNewWalletOptions.notifier).state = ( + mnemonicWordsCount: + ref.read(mnemonicWordCountStateProvider.state).state, + mnemonicPassphrase: passwordController.text, + ); + } else { + ref.read(pNewWalletOptions.notifier).state = null; + } + + Navigator.of(context).pushNamed( + NewWalletRecoveryPhraseWarningView.routeName, + arguments: Tuple2( + widget.walletName, + widget.coin, + ), + ); + }, + ), + if (!Util.isDesktop) + const SizedBox( + height: 16, + ), + if (Util.isDesktop) + const Spacer( + flex: 15, + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart index e373e817b..f237fd4ae 100644 --- a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart @@ -13,6 +13,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart'; import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart'; import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/recovery_phrase_explanation_dialog.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; @@ -38,7 +39,7 @@ import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:tuple/tuple.dart'; -class NewWalletRecoveryPhraseWarningView extends StatefulWidget { +class NewWalletRecoveryPhraseWarningView extends ConsumerStatefulWidget { const NewWalletRecoveryPhraseWarningView({ Key? key, required this.coin, @@ -51,12 +52,12 @@ class NewWalletRecoveryPhraseWarningView extends StatefulWidget { final String walletName; @override - State createState() => + ConsumerState createState() => _NewWalletRecoveryPhraseWarningViewState(); } class _NewWalletRecoveryPhraseWarningViewState - extends State { + extends ConsumerState { late final Coin coin; late final String walletName; late final bool isDesktop; @@ -72,6 +73,10 @@ class _NewWalletRecoveryPhraseWarningViewState @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); + final options = ref.read(pNewWalletOptions.state).state; + + final seedCount = options?.mnemonicWordsCount ?? + Constants.defaultSeedPhraseLengthFor(coin: coin); return MasterScaffold( isDesktop: isDesktop, @@ -172,7 +177,7 @@ class _NewWalletRecoveryPhraseWarningViewState child: isDesktop ? Text( "On the next screen you will see " - "${Constants.defaultSeedPhraseLengthFor(coin: coin)} " + "$seedCount " "words that make up your recovery phrase.\n\nPlease " "write it down. Keep it safe and never share it with " "anyone. Your recovery phrase is the only way you can" @@ -496,7 +501,24 @@ class _NewWalletRecoveryPhraseWarningViewState final manager = Manager(wallet); - await manager.initializeNew(); + if (coin.hasMnemonicPassphraseSupport && + ref + .read(pNewWalletOptions.state) + .state != + null) { + await manager.initializeNew(( + mnemonicPassphrase: ref + .read(pNewWalletOptions.state) + .state! + .mnemonicPassphrase, + wordCount: ref + .read(pNewWalletOptions.state) + .state! + .mnemonicWordsCount, + )); + } else { + await manager.initializeNew(null); + } // pop progress dialog if (mounted) { diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 2b7aa662d..344eb7876 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -27,6 +27,7 @@ import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_to import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart'; import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart'; import 'package:stackwallet/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart'; +import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart'; import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart'; import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart'; import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart'; @@ -1101,6 +1102,21 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); + case NewWalletOptionsView.routeName: + if (args is Tuple2) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => NewWalletOptionsView( + walletName: args.item1, + coin: args.item2, + ), + settings: RouteSettings( + name: settings.name, + ), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + case RestoreWalletView.routeName: if (args is Tuple5) { return getRoute( diff --git a/lib/services/coins/banano/banano_wallet.dart b/lib/services/coins/banano/banano_wallet.dart index e2032aa09..50b4a3f9e 100644 --- a/lib/services/coins/banano/banano_wallet.dart +++ b/lib/services/coins/banano/banano_wallet.dart @@ -600,7 +600,9 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) { throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart index f40be0e3c..cb8eadeef 100644 --- a/lib/services/coins/bitcoin/bitcoin_wallet.dart +++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart @@ -1290,7 +1290,9 @@ class BitcoinWallet extends CoinServiceAPI bool get isConnected => _isConnected; @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info); @@ -1301,7 +1303,7 @@ class BitcoinWallet extends CoinServiceAPI await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s", level: LogLevel.Fatal); @@ -1499,7 +1501,9 @@ class BitcoinWallet extends CoinServiceAPI } } - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); if (!integrationTestFlag) { @@ -1533,10 +1537,21 @@ class BitcoinWallet extends CoinServiceAPI throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); } + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } await _secureStore.write( key: '${_walletId}_mnemonic', - value: bip39.generateMnemonic(strength: 128)); - await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: ""); + value: bip39.generateMnemonic(strength: strength)); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: data?.mnemonicPassphrase ?? "", + ); // Generate and add addresses to relevant arrays final initialAddresses = await Future.wait([ diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index d0b360b0c..1f4057353 100644 --- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart +++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart @@ -1161,7 +1161,9 @@ class BitcoinCashWallet extends CoinServiceAPI bool get isConnected => _isConnected; @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info); @@ -1171,7 +1173,7 @@ class BitcoinCashWallet extends CoinServiceAPI } await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s", level: LogLevel.Fatal); @@ -1402,7 +1404,9 @@ class BitcoinCashWallet extends CoinServiceAPI } } - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); if (!integrationTestFlag) { @@ -1436,10 +1440,21 @@ class BitcoinCashWallet extends CoinServiceAPI throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); } + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } await _secureStore.write( key: '${_walletId}_mnemonic', - value: bip39.generateMnemonic(strength: 128)); - await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: ""); + value: bip39.generateMnemonic(strength: strength)); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: data?.mnemonicPassphrase ?? "", + ); // Generate and add addresses to relevant arrays final initialAddresses = await Future.wait([ diff --git a/lib/services/coins/coin_service.dart b/lib/services/coins/coin_service.dart index 5aa6e382d..94fa569e4 100644 --- a/lib/services/coins/coin_service.dart +++ b/lib/services/coins/coin_service.dart @@ -348,7 +348,9 @@ abstract class CoinServiceAPI { required int height, }); - Future initializeNew(); + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ); Future initializeExisting(); Future exit(); diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 754834ad1..3d6ae5794 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -1147,7 +1147,9 @@ class DogecoinWallet extends CoinServiceAPI bool get isConnected => _isConnected; @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info); @@ -1157,7 +1159,7 @@ class DogecoinWallet extends CoinServiceAPI } await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s", level: LogLevel.Fatal); @@ -1349,7 +1351,9 @@ class DogecoinWallet extends CoinServiceAPI } } - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); if (!integrationTestFlag) { @@ -1383,12 +1387,20 @@ class DogecoinWallet extends CoinServiceAPI throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); } + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } await _secureStore.write( key: '${_walletId}_mnemonic', - value: bip39.generateMnemonic(strength: 128)); + value: bip39.generateMnemonic(strength: strength)); await _secureStore.write( key: '${_walletId}_mnemonicPassphrase', - value: "", + value: data?.mnemonicPassphrase ?? "", ); // Generate and add addresses diff --git a/lib/services/coins/ecash/ecash_wallet.dart b/lib/services/coins/ecash/ecash_wallet.dart index e891db692..c35f7f4c6 100644 --- a/lib/services/coins/ecash/ecash_wallet.dart +++ b/lib/services/coins/ecash/ecash_wallet.dart @@ -506,7 +506,9 @@ class ECashWallet extends CoinServiceAPI } } - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); if (!integrationTestFlag) { @@ -544,10 +546,21 @@ class ECashWallet extends CoinServiceAPI throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); } + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } await _secureStore.write( key: '${_walletId}_mnemonic', - value: bip39.generateMnemonic(strength: 128)); - await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: ""); + value: bip39.generateMnemonic(strength: strength)); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: data?.mnemonicPassphrase ?? "", + ); const int startingIndex = 0; const int receiveChain = 0; @@ -2778,7 +2791,9 @@ class ECashWallet extends CoinServiceAPI bool get isConnected => _isConnected; @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info); @@ -2789,7 +2804,7 @@ class ECashWallet extends CoinServiceAPI await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s", level: LogLevel.Fatal); diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index b62129248..9d25a5a47 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -766,7 +766,9 @@ class EpicCashWallet extends CoinServiceAPI } @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { await _prefs.init(); await updateNode(false); final mnemonic = await _getMnemonicList(); @@ -1738,7 +1740,6 @@ class EpicCashWallet extends CoinServiceAPI final isIncoming = (tx["tx_type"] == "TxReceived" || tx["tx_type"] == "TxReceivedCancelled"); - final txn = isar_models.Transaction( walletId: walletId, txid: commitId ?? tx["id"].toString(), @@ -1763,7 +1764,9 @@ class EpicCashWallet extends CoinServiceAPI otherData: tx['onChainNote'].toString(), inputs: [], outputs: [], - numberOfMessages: ((tx["numberOfMessages"] == null) ? 0 : tx["numberOfMessages"]) as int, + numberOfMessages: ((tx["numberOfMessages"] == null) + ? 0 + : tx["numberOfMessages"]) as int, ); // txn.address = diff --git a/lib/services/coins/ethereum/ethereum_wallet.dart b/lib/services/coins/ethereum/ethereum_wallet.dart index 62f3020e0..b3800a4e4 100644 --- a/lib/services/coins/ethereum/ethereum_wallet.dart +++ b/lib/services/coins/ethereum/ethereum_wallet.dart @@ -310,7 +310,9 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance.log( "Generating new ${coin.prettyName} wallet.", level: LogLevel.Info, @@ -324,7 +326,7 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB { await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log( "Exception rethrown from initializeNew(): $e\n$s", @@ -338,7 +340,9 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB { ]); } - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { // Logging.instance // .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); // if (!integrationTestFlag) { @@ -366,14 +370,23 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB { "Attempted to overwrite mnemonic on generate new wallet!"); } - final String mnemonic = bip39.generateMnemonic(strength: 128); + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } + final String mnemonic = bip39.generateMnemonic(strength: strength); + final String passphrase = data?.mnemonicPassphrase ?? ""; await _secureStore.write(key: '${_walletId}_mnemonic', value: mnemonic); await _secureStore.write( key: '${_walletId}_mnemonicPassphrase', - value: "", + value: passphrase, ); - await _generateAndSaveAddress(mnemonic, ""); + await _generateAndSaveAddress(mnemonic, passphrase); Logging.instance.log("_generateNewWalletFinished", level: LogLevel.Info); } diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart index a4cea6393..d58cf4402 100644 --- a/lib/services/coins/firo/firo_wallet.dart +++ b/lib/services/coins/firo/firo_wallet.dart @@ -1875,7 +1875,9 @@ class FiroWallet extends CoinServiceAPI } @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info); @@ -1886,7 +1888,7 @@ class FiroWallet extends CoinServiceAPI await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s", level: LogLevel.Fatal); @@ -2124,7 +2126,9 @@ class FiroWallet extends CoinServiceAPI } /// Generates initial wallet values such as mnemonic, chain (receive/change) arrays and indexes. - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); if (!integrationTestFlag) { @@ -2158,12 +2162,20 @@ class FiroWallet extends CoinServiceAPI longMutex = false; throw Exception("Attempted to overwrite mnemonic on initialize new!"); } + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } await _secureStore.write( key: '${_walletId}_mnemonic', - value: bip39.generateMnemonic(strength: 128)); + value: bip39.generateMnemonic(strength: strength)); await _secureStore.write( key: '${_walletId}_mnemonicPassphrase', - value: "", + value: data?.mnemonicPassphrase ?? "", ); // Generate and add addresses to relevant arrays diff --git a/lib/services/coins/litecoin/litecoin_wallet.dart b/lib/services/coins/litecoin/litecoin_wallet.dart index 703ec5cf6..26718bc4e 100644 --- a/lib/services/coins/litecoin/litecoin_wallet.dart +++ b/lib/services/coins/litecoin/litecoin_wallet.dart @@ -1285,7 +1285,9 @@ class LitecoinWallet extends CoinServiceAPI bool get isConnected => _isConnected; @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info); @@ -1296,7 +1298,7 @@ class LitecoinWallet extends CoinServiceAPI await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s", level: LogLevel.Fatal); @@ -1535,7 +1537,9 @@ class LitecoinWallet extends CoinServiceAPI } } - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); if (!integrationTestFlag) { @@ -1570,12 +1574,20 @@ class LitecoinWallet extends CoinServiceAPI throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); } + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } await _secureStore.write( key: '${_walletId}_mnemonic', - value: bip39.generateMnemonic(strength: 128)); + value: bip39.generateMnemonic(strength: strength)); await _secureStore.write( key: '${_walletId}_mnemonicPassphrase', - value: "", + value: data?.mnemonicPassphrase ?? "", ); // Generate and add addresses to relevant arrays diff --git a/lib/services/coins/manager.dart b/lib/services/coins/manager.dart index 1f5ae55f3..05f27d503 100644 --- a/lib/services/coins/manager.dart +++ b/lib/services/coins/manager.dart @@ -180,7 +180,9 @@ class Manager with ChangeNotifier { Future testNetworkConnection() => _currentWallet.testNetworkConnection(); - Future initializeNew() => _currentWallet.initializeNew(); + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + _currentWallet.initializeNew(data); Future initializeExisting() => _currentWallet.initializeExisting(); Future recoverFromMnemonic({ required String mnemonic, diff --git a/lib/services/coins/monero/monero_wallet.dart b/lib/services/coins/monero/monero_wallet.dart index 5911e8592..a5284cc60 100644 --- a/lib/services/coins/monero/monero_wallet.dart +++ b/lib/services/coins/monero/monero_wallet.dart @@ -307,7 +307,9 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { await _prefs.init(); // this should never fail diff --git a/lib/services/coins/namecoin/namecoin_wallet.dart b/lib/services/coins/namecoin/namecoin_wallet.dart index d0f30ecac..8b27fe426 100644 --- a/lib/services/coins/namecoin/namecoin_wallet.dart +++ b/lib/services/coins/namecoin/namecoin_wallet.dart @@ -1268,7 +1268,9 @@ class NamecoinWallet extends CoinServiceAPI bool get isConnected => _isConnected; @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info); @@ -1279,7 +1281,7 @@ class NamecoinWallet extends CoinServiceAPI await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s", level: LogLevel.Fatal); @@ -1517,7 +1519,9 @@ class NamecoinWallet extends CoinServiceAPI } } - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); if (!integrationTestFlag) { @@ -1544,12 +1548,20 @@ class NamecoinWallet extends CoinServiceAPI throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); } + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } await _secureStore.write( key: '${_walletId}_mnemonic', - value: bip39.generateMnemonic(strength: 128)); + value: bip39.generateMnemonic(strength: strength)); await _secureStore.write( key: '${_walletId}_mnemonicPassphrase', - value: "", + value: data?.mnemonicPassphrase ?? "", ); // Generate and add addresses to relevant arrays diff --git a/lib/services/coins/nano/nano_wallet.dart b/lib/services/coins/nano/nano_wallet.dart index 391303675..34de1034d 100644 --- a/lib/services/coins/nano/nano_wallet.dart +++ b/lib/services/coins/nano/nano_wallet.dart @@ -607,7 +607,9 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) { throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); diff --git a/lib/services/coins/particl/particl_wallet.dart b/lib/services/coins/particl/particl_wallet.dart index 324e8d9e5..33064ef85 100644 --- a/lib/services/coins/particl/particl_wallet.dart +++ b/lib/services/coins/particl/particl_wallet.dart @@ -1195,7 +1195,9 @@ class ParticlWallet extends CoinServiceAPI bool get isConnected => _isConnected; @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info); @@ -1206,7 +1208,7 @@ class ParticlWallet extends CoinServiceAPI await _prefs.init(); try { - await _generateNewWallet(); + await _generateNewWallet(data); } catch (e, s) { Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s", level: LogLevel.Fatal); @@ -1432,7 +1434,9 @@ class ParticlWallet extends CoinServiceAPI } } - Future _generateNewWallet() async { + Future _generateNewWallet( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { Logging.instance .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info); if (!integrationTestFlag) { @@ -1459,12 +1463,20 @@ class ParticlWallet extends CoinServiceAPI throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); } + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } await _secureStore.write( key: '${_walletId}_mnemonic', - value: bip39.generateMnemonic(strength: 128)); + value: bip39.generateMnemonic(strength: strength)); await _secureStore.write( key: '${_walletId}_mnemonicPassphrase', - value: "", + value: data?.mnemonicPassphrase ?? "", ); // Generate and add addresses to relevant arrays diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index c4c92373f..2b06d3eef 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:bip39/bip39.dart' as bip39; import 'package:http/http.dart' as http; import 'package:isar/isar.dart'; import 'package:stackwallet/db/isar/main_db.dart'; @@ -326,7 +327,9 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) { throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); @@ -334,11 +337,26 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { await _prefs.init(); - String mnemonic = await Wallet.generate24WordsMnemonic(); + final int strength; + if (data == null || data.wordCount == 12) { + strength = 128; + } else if (data.wordCount == 24) { + strength = 256; + } else { + throw Exception("Invalid word count"); + } + final String mnemonic = bip39.generateMnemonic(strength: strength); + final String passphrase = data?.mnemonicPassphrase ?? ""; await _secureStore.write(key: '${_walletId}_mnemonic', value: mnemonic); - await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: ""); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: passphrase, + ); - Wallet wallet = await Wallet.from(mnemonic); + Wallet wallet = await Wallet.from( + mnemonic, + passphrase: passphrase, + ); KeyPair keyPair = await wallet.getKeyPair(index: 0); String address = keyPair.accountId; String secretSeed = diff --git a/lib/services/coins/wownero/wownero_wallet.dart b/lib/services/coins/wownero/wownero_wallet.dart index 6f0863334..7b3691846 100644 --- a/lib/services/coins/wownero/wownero_wallet.dart +++ b/lib/services/coins/wownero/wownero_wallet.dart @@ -333,7 +333,10 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future initializeNew({int seedWordsLength = 14}) async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, { + int seedWordsLength = 14, + }) async { await _prefs.init(); // this should never fail diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index 677d474e7..6fe2ffa87 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -236,6 +236,35 @@ extension CoinExt on Coin { } } + bool get hasMnemonicPassphraseSupport { + switch (this) { + case Coin.bitcoin: + case Coin.bitcoinTestNet: + case Coin.litecoin: + case Coin.litecoinTestNet: + case Coin.bitcoincash: + case Coin.bitcoincashTestnet: + case Coin.dogecoin: + case Coin.dogecoinTestNet: + case Coin.firo: + case Coin.firoTestNet: + case Coin.namecoin: + case Coin.particl: + case Coin.ethereum: + case Coin.eCash: + case Coin.stellar: + case Coin.stellarTestnet: + return true; + + case Coin.epicCash: + case Coin.monero: + case Coin.wownero: + case Coin.nano: + case Coin.banano: + return false; + } + } + bool get hasBuySupport { switch (this) { case Coin.bitcoin: From 02baf4a1985fc906f78aef8c0f106afbe45b125f Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Aug 2023 15:10:51 -0600 Subject: [PATCH 094/237] ensure new wallet mnemonic options is reset --- .../name_your_wallet_view/name_your_wallet_view.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart index 4f88f99b3..f07941e36 100644 --- a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart +++ b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart @@ -361,6 +361,7 @@ class _NameYourWalletViewState extends ConsumerState { .read(mnemonicWordCountStateProvider.state) .state = Constants.possibleLengthsForCoin(coin).last; + ref.read(pNewWalletOptions.notifier).state = null; switch (widget.addWalletType) { case AddWalletType.New: From abbf557b411be18f9c9cad052d9651ae7fed3415 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Aug 2023 15:40:12 -0600 Subject: [PATCH 095/237] style tweak --- .../new_wallet_options_view.dart | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart b/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart index 4f2dfb180..bf7f088d1 100644 --- a/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart @@ -112,7 +112,7 @@ class _NewWalletOptionsViewState extends ConsumerState { ), child: IntrinsicHeight( child: Padding( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.symmetric(horizontal: 16), child: child, ), ), @@ -129,22 +129,24 @@ class _NewWalletOptionsViewState extends ConsumerState { const Spacer( flex: 10, ), + if (!Util.isDesktop) + const SizedBox( + height: 16, + ), if (!Util.isDesktop) CoinImage( coin: widget.coin, height: 100, width: 100, ), - SizedBox( - height: Util.isDesktop ? 0 : 16, - ), - Text( - "Wallet options", - textAlign: TextAlign.center, - style: Util.isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.pageTitleH1(context), - ), + if (Util.isDesktop) + Text( + "Wallet options", + textAlign: TextAlign.center, + style: Util.isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), + ), SizedBox( height: Util.isDesktop ? 32 : 16, ), From e20ce631e6e232968fdff8e20d0ca43fb413c3da Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Aug 2023 15:40:19 -0600 Subject: [PATCH 096/237] count fix --- .../new_wallet_recovery_phrase_warning_view.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart index f237fd4ae..d843f6ec8 100644 --- a/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart @@ -221,9 +221,7 @@ class _NewWalletRecoveryPhraseWarningViewState ), ), TextSpan( - text: - "${Constants.defaultSeedPhraseLengthFor(coin: coin)}" - " words", + text: "$seedCount words", style: STextStyles.desktopH3(context).copyWith( color: Theme.of(context) .extension()! From 244a1914b370098151c8751b48ba2a1203349181 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Aug 2023 17:06:30 -0600 Subject: [PATCH 097/237] verify mnemonic passphrase dialog --- .../verify_mnemonic_passphrase_dialog.dart | 218 ++++++++++++++++++ .../verify_recovery_phrase_view.dart | 19 ++ lib/widgets/stack_dialog.dart | 9 +- 3 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart diff --git a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart new file mode 100644 index 000000000..3326622ad --- /dev/null +++ b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart @@ -0,0 +1,218 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/notifications/show_flush_bar.dart'; +import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/stack_dialog.dart'; +import 'package:stackwallet/widgets/stack_text_field.dart'; + +class VerifyMnemonicPassphraseDialog extends ConsumerStatefulWidget { + const VerifyMnemonicPassphraseDialog({super.key}); + + @override + ConsumerState createState() => + _VerifyMnemonicPassphraseDialogState(); +} + +class _VerifyMnemonicPassphraseDialogState + extends ConsumerState { + late final FocusNode passwordFocusNode; + late final TextEditingController passwordController; + + bool hidePassword = true; + + bool _verifyLock = false; + + void _verify() { + if (_verifyLock) { + return; + } + _verifyLock = true; + + if (passwordController.text == + ref.read(pNewWalletOptions.state).state!.mnemonicPassphrase) { + Navigator.of(context, rootNavigator: Util.isDesktop).pop("verified"); + } else { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Passphrase does not match", + context: context, + ); + } + + _verifyLock = false; + } + + @override + void initState() { + passwordController = TextEditingController(); + passwordFocusNode = FocusNode(); + + super.initState(); + } + + @override + void dispose() { + passwordController.dispose(); + passwordFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return ConditionalParent( + condition: Util.isDesktop, + builder: (child) => DesktopDialog( + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + ), + child: Text( + "Verify mnemonic passphrase", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: child, + ), + ], + ), + ), + child: ConditionalParent( + condition: !Util.isDesktop, + builder: (child) => StackDialogBase( + keyboardPaddingAmount: MediaQuery.of(context).viewInsets.bottom, + child: child, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (!Util.isDesktop) + Text( + "Verify mnemonic passphrase", + style: STextStyles.pageTitleH2(context), + ), + const SizedBox( + height: 24, + ), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key("mnemonicPassphraseFieldKey1"), + focusNode: passwordFocusNode, + controller: passwordController, + style: Util.isDesktop + ? STextStyles.desktopTextMedium(context).copyWith( + height: 2, + ) + : STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Recovery phrase password", + passwordFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: ConditionalParent( + condition: Util.isDesktop, + builder: (child) => SizedBox( + height: 70, + child: child, + ), + child: Row( + children: [ + SizedBox( + width: Util.isDesktop ? 24 : 16, + ), + GestureDetector( + key: const Key( + "mnemonicPassphraseFieldShowPasswordButtonKey"), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: Theme.of(context) + .extension()! + .textDark3, + width: Util.isDesktop ? 24 : 16, + height: Util.isDesktop ? 24 : 16, + ), + ), + const SizedBox( + width: 12, + ), + ], + ), + ), + ), + ), + ), + ), + SizedBox( + height: Util.isDesktop ? 48 : 24, + ), + ConditionalParent( + condition: !Util.isDesktop, + builder: (child) => Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + onPressed: Navigator.of( + context, + rootNavigator: Util.isDesktop, + ).pop, + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: child, + ), + ], + ), + child: PrimaryButton( + label: "Verify", + onPressed: _verify, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart index fda4419d9..0d0083cc6 100644 --- a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart +++ b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart @@ -16,9 +16,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart'; +import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart'; import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart'; import 'package:stackwallet/pages/add_wallet_views/select_wallet_for_token_view.dart'; import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/sub_widgets/word_table.dart'; +import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart'; import 'package:stackwallet/pages/home_view/home_view.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; @@ -98,8 +100,25 @@ class _VerifyRecoveryPhraseViewState // } // } + Future _verifyMnemonicPassphrase() async { + final result = await showDialog( + context: context, + builder: (_) => const VerifyMnemonicPassphraseDialog(), + ); + + return result == "verified"; + } + Future _continue(bool isMatch) async { if (isMatch) { + if (ref.read(pNewWalletOptions.state).state != null) { + final passphraseVerified = await _verifyMnemonicPassphrase(); + + if (!passphraseVerified) { + return; + } + } + await ref.read(walletsServiceChangeNotifierProvider).setMnemonicVerified( walletId: _manager.walletId, ); diff --git a/lib/widgets/stack_dialog.dart b/lib/widgets/stack_dialog.dart index fead6a00a..be7f22ed9 100644 --- a/lib/widgets/stack_dialog.dart +++ b/lib/widgets/stack_dialog.dart @@ -18,15 +18,22 @@ class StackDialogBase extends StatelessWidget { Key? key, this.child, this.padding = const EdgeInsets.all(24), + this.keyboardPaddingAmount = 0, }) : super(key: key); final EdgeInsets padding; final Widget? child; + final double keyboardPaddingAmount; @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.all(16), + padding: EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: 16 + keyboardPaddingAmount, + ), child: Column( mainAxisAlignment: !Util.isDesktop ? MainAxisAlignment.end : MainAxisAlignment.center, From 4f7f7d57976d304d40fe88721f76192e07ba6ba6 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Aug 2023 17:24:22 -0600 Subject: [PATCH 098/237] update mocks --- .../pages/send_view/send_view_test.mocks.dart | 18 ++++++--- ...d_address_book_view_screen_test.mocks.dart | 6 ++- ..._entry_details_view_screen_test.mocks.dart | 6 ++- ...ess_book_entry_view_screen_test.mocks.dart | 6 ++- .../lockscreen_view_screen_test.mocks.dart | 6 ++- .../main_view_screen_testA_test.mocks.dart | 6 ++- .../main_view_screen_testB_test.mocks.dart | 6 ++- .../main_view_screen_testC_test.mocks.dart | 6 ++- .../backup_key_view_screen_test.mocks.dart | 6 ++- ...up_key_warning_view_screen_test.mocks.dart | 6 ++- .../create_pin_view_screen_test.mocks.dart | 6 ++- ...restore_wallet_view_screen_test.mocks.dart | 6 ++- ...ify_backup_key_view_screen_test.mocks.dart | 6 ++- .../currency_view_screen_test.mocks.dart | 6 ++- ...dd_custom_node_view_screen_test.mocks.dart | 6 ++- .../node_details_view_screen_test.mocks.dart | 6 ++- .../wallet_backup_view_screen_test.mocks.dart | 6 ++- ...rescan_warning_view_screen_test.mocks.dart | 6 ++- ...elete_mnemonic_view_screen_test.mocks.dart | 6 ++- ...allet_settings_view_screen_test.mocks.dart | 16 +++----- .../settings_view_screen_test.mocks.dart | 6 ++- ...search_results_view_screen_test.mocks.dart | 6 ++- .../confirm_send_view_screen_test.mocks.dart | 6 ++- .../receive_view_screen_test.mocks.dart | 6 ++- .../send_view_screen_test.mocks.dart | 6 ++- .../wallet_view_screen_test.mocks.dart | 6 ++- .../bitcoin/bitcoin_wallet_test.mocks.dart | 10 +---- .../bitcoincash/bitcoincash_wallet_test.dart | 3 +- .../bitcoincash_wallet_test.mocks.dart | 10 +---- .../coins/dogecoin/dogecoin_wallet_test.dart | 3 +- .../dogecoin/dogecoin_wallet_test.mocks.dart | 10 +---- .../services/coins/fake_coin_service_api.dart | 4 +- .../coins/firo/firo_wallet_test.mocks.dart | 10 +---- test/services/coins/manager_test.mocks.dart | 27 ++++++++++++- .../namecoin/namecoin_wallet_test.mocks.dart | 10 +---- .../particl/particl_wallet_test.mocks.dart | 10 +---- .../managed_favorite_test.mocks.dart | 18 ++++++--- .../table_view/table_view_row_test.mocks.dart | 18 ++++++--- .../transaction_card_test.mocks.dart | 39 ++++++++++++++++--- test/widget_tests/wallet_card_test.mocks.dart | 6 ++- ...et_info_row_balance_future_test.mocks.dart | 18 ++++++--- .../wallet_info_row_test.mocks.dart | 18 ++++++--- 42 files changed, 245 insertions(+), 147 deletions(-) diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart index c9414583d..52bc87fee 100644 --- a/test/pages/send_view/send_view_test.mocks.dart +++ b/test/pages/send_view/send_view_test.mocks.dart @@ -1283,10 +1283,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), @@ -3062,10 +3064,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i23.Future.value(false), ) as _i23.Future); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), @@ -3415,10 +3419,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: _i23.Future.value(), ) as _i23.Future); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), diff --git a/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart b/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart index 5edc4c538..29318d2c5 100644 --- a/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart +++ b/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart @@ -492,10 +492,12 @@ class MockManager extends _i1.Mock implements _i12.Manager { returnValue: _i9.Future.value(false), ) as _i9.Future); @override - _i9.Future initializeNew() => (super.noSuchMethod( + _i9.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i9.Future.value(), returnValueForMissingStub: _i9.Future.value(), diff --git a/test/screen_tests/address_book_view/subviews/address_book_entry_details_view_screen_test.mocks.dart b/test/screen_tests/address_book_view/subviews/address_book_entry_details_view_screen_test.mocks.dart index a84bb6a51..cd9108d2a 100644 --- a/test/screen_tests/address_book_view/subviews/address_book_entry_details_view_screen_test.mocks.dart +++ b/test/screen_tests/address_book_view/subviews/address_book_entry_details_view_screen_test.mocks.dart @@ -453,10 +453,12 @@ class MockManager extends _i1.Mock implements _i10.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/address_book_view/subviews/edit_address_book_entry_view_screen_test.mocks.dart b/test/screen_tests/address_book_view/subviews/edit_address_book_entry_view_screen_test.mocks.dart index f44df83ca..65ab3b1f2 100644 --- a/test/screen_tests/address_book_view/subviews/edit_address_book_entry_view_screen_test.mocks.dart +++ b/test/screen_tests/address_book_view/subviews/edit_address_book_entry_view_screen_test.mocks.dart @@ -451,10 +451,12 @@ class MockManager extends _i1.Mock implements _i10.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/lockscreen_view_screen_test.mocks.dart b/test/screen_tests/lockscreen_view_screen_test.mocks.dart index 35a1a5f20..dd8f32b04 100644 --- a/test/screen_tests/lockscreen_view_screen_test.mocks.dart +++ b/test/screen_tests/lockscreen_view_screen_test.mocks.dart @@ -771,10 +771,12 @@ class MockManager extends _i1.Mock implements _i13.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/main_view_tests/main_view_screen_testA_test.mocks.dart b/test/screen_tests/main_view_tests/main_view_screen_testA_test.mocks.dart index 8526c77f3..87686d271 100644 --- a/test/screen_tests/main_view_tests/main_view_screen_testA_test.mocks.dart +++ b/test/screen_tests/main_view_tests/main_view_screen_testA_test.mocks.dart @@ -558,10 +558,12 @@ class MockManager extends _i1.Mock implements _i10.Manager { returnValue: _i7.Future.value(false), ) as _i7.Future); @override - _i7.Future initializeNew() => (super.noSuchMethod( + _i7.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i7.Future.value(), returnValueForMissingStub: _i7.Future.value(), diff --git a/test/screen_tests/main_view_tests/main_view_screen_testB_test.mocks.dart b/test/screen_tests/main_view_tests/main_view_screen_testB_test.mocks.dart index ba9350c78..221cbb329 100644 --- a/test/screen_tests/main_view_tests/main_view_screen_testB_test.mocks.dart +++ b/test/screen_tests/main_view_tests/main_view_screen_testB_test.mocks.dart @@ -558,10 +558,12 @@ class MockManager extends _i1.Mock implements _i10.Manager { returnValue: _i7.Future.value(false), ) as _i7.Future); @override - _i7.Future initializeNew() => (super.noSuchMethod( + _i7.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i7.Future.value(), returnValueForMissingStub: _i7.Future.value(), diff --git a/test/screen_tests/main_view_tests/main_view_screen_testC_test.mocks.dart b/test/screen_tests/main_view_tests/main_view_screen_testC_test.mocks.dart index 5f8055c5a..abb608127 100644 --- a/test/screen_tests/main_view_tests/main_view_screen_testC_test.mocks.dart +++ b/test/screen_tests/main_view_tests/main_view_screen_testC_test.mocks.dart @@ -558,10 +558,12 @@ class MockManager extends _i1.Mock implements _i10.Manager { returnValue: _i7.Future.value(false), ) as _i7.Future); @override - _i7.Future initializeNew() => (super.noSuchMethod( + _i7.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i7.Future.value(), returnValueForMissingStub: _i7.Future.value(), diff --git a/test/screen_tests/onboarding/backup_key_view_screen_test.mocks.dart b/test/screen_tests/onboarding/backup_key_view_screen_test.mocks.dart index d621a4ae0..b60b30832 100644 --- a/test/screen_tests/onboarding/backup_key_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/backup_key_view_screen_test.mocks.dart @@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/onboarding/backup_key_warning_view_screen_test.mocks.dart b/test/screen_tests/onboarding/backup_key_warning_view_screen_test.mocks.dart index 6802650ab..90907cd14 100644 --- a/test/screen_tests/onboarding/backup_key_warning_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/backup_key_warning_view_screen_test.mocks.dart @@ -556,10 +556,12 @@ class MockManager extends _i1.Mock implements _i10.Manager { returnValue: _i7.Future.value(false), ) as _i7.Future); @override - _i7.Future initializeNew() => (super.noSuchMethod( + _i7.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i7.Future.value(), returnValueForMissingStub: _i7.Future.value(), diff --git a/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart b/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart index a9b4549a0..460a35f50 100644 --- a/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/create_pin_view_screen_test.mocks.dart @@ -771,10 +771,12 @@ class MockManager extends _i1.Mock implements _i13.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart b/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart index a33b13e7a..b4a8329da 100644 --- a/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/restore_wallet_view_screen_test.mocks.dart @@ -612,10 +612,12 @@ class MockManager extends _i1.Mock implements _i13.Manager { returnValue: _i9.Future.value(false), ) as _i9.Future); @override - _i9.Future initializeNew() => (super.noSuchMethod( + _i9.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i9.Future.value(), returnValueForMissingStub: _i9.Future.value(), diff --git a/test/screen_tests/onboarding/verify_backup_key_view_screen_test.mocks.dart b/test/screen_tests/onboarding/verify_backup_key_view_screen_test.mocks.dart index e372e3781..25241ab80 100644 --- a/test/screen_tests/onboarding/verify_backup_key_view_screen_test.mocks.dart +++ b/test/screen_tests/onboarding/verify_backup_key_view_screen_test.mocks.dart @@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/settings_view/settings_subviews/currency_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/currency_view_screen_test.mocks.dart index ece50ef76..d77078d9c 100644 --- a/test/screen_tests/settings_view/settings_subviews/currency_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/currency_view_screen_test.mocks.dart @@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart index b56c08998..0b8976a88 100644 --- a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view_screen_test.mocks.dart @@ -540,10 +540,12 @@ class MockManager extends _i1.Mock implements _i12.Manager { returnValue: _i9.Future.value(false), ) as _i9.Future); @override - _i9.Future initializeNew() => (super.noSuchMethod( + _i9.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i9.Future.value(), returnValueForMissingStub: _i9.Future.value(), diff --git a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart index 5e62fd6d4..803ef81c6 100644 --- a/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/network_settings_subviews/node_details_view_screen_test.mocks.dart @@ -540,10 +540,12 @@ class MockManager extends _i1.Mock implements _i12.Manager { returnValue: _i9.Future.value(false), ) as _i9.Future); @override - _i9.Future initializeNew() => (super.noSuchMethod( + _i9.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i9.Future.value(), returnValueForMissingStub: _i9.Future.value(), diff --git a/test/screen_tests/settings_view/settings_subviews/wallet_backup_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/wallet_backup_view_screen_test.mocks.dart index 671af0d4b..4e59b2a40 100644 --- a/test/screen_tests/settings_view/settings_subviews/wallet_backup_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/wallet_backup_view_screen_test.mocks.dart @@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/settings_view/settings_subviews/wallet_settings_subviews/rescan_warning_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/wallet_settings_subviews/rescan_warning_view_screen_test.mocks.dart index e3a475bdd..151ecd1ab 100644 --- a/test/screen_tests/settings_view/settings_subviews/wallet_settings_subviews/rescan_warning_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/wallet_settings_subviews/rescan_warning_view_screen_test.mocks.dart @@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/settings_view/settings_subviews/wallet_settings_subviews/wallet_delete_mnemonic_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/wallet_settings_subviews/wallet_delete_mnemonic_view_screen_test.mocks.dart index 439dd35ca..d9e9603d3 100644 --- a/test/screen_tests/settings_view/settings_subviews/wallet_settings_subviews/wallet_delete_mnemonic_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/wallet_settings_subviews/wallet_delete_mnemonic_view_screen_test.mocks.dart @@ -556,10 +556,12 @@ class MockManager extends _i1.Mock implements _i10.Manager { returnValue: _i7.Future.value(false), ) as _i7.Future); @override - _i7.Future initializeNew() => (super.noSuchMethod( + _i7.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i7.Future.value(), returnValueForMissingStub: _i7.Future.value(), diff --git a/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart index cc20dce98..268529741 100644 --- a/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart @@ -154,18 +154,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i7.CachedElectrumX { _i8.Future>.value({}), ) as _i8.Future>); @override - _i8.Future> getUsedCoinSerials({ - required _i9.Coin? coin, - int? startNumber = 0, - }) => + _i8.Future> getUsedCoinSerials({required _i9.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - { - #coin: coin, - #startNumber: startNumber, - }, + {#coin: coin}, ), returnValue: _i8.Future>.value([]), ) as _i8.Future>); @@ -792,10 +786,12 @@ class MockManager extends _i1.Mock implements _i15.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/settings_view/settings_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_view_screen_test.mocks.dart index 4cfabb7bc..97837b511 100644 --- a/test/screen_tests/settings_view/settings_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_view_screen_test.mocks.dart @@ -556,10 +556,12 @@ class MockManager extends _i1.Mock implements _i10.Manager { returnValue: _i7.Future.value(false), ) as _i7.Future); @override - _i7.Future initializeNew() => (super.noSuchMethod( + _i7.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i7.Future.value(), returnValueForMissingStub: _i7.Future.value(), diff --git a/test/screen_tests/transaction_subviews/transaction_search_results_view_screen_test.mocks.dart b/test/screen_tests/transaction_subviews/transaction_search_results_view_screen_test.mocks.dart index b48b433a9..97563c8ad 100644 --- a/test/screen_tests/transaction_subviews/transaction_search_results_view_screen_test.mocks.dart +++ b/test/screen_tests/transaction_subviews/transaction_search_results_view_screen_test.mocks.dart @@ -327,10 +327,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/wallet_view/confirm_send_view_screen_test.mocks.dart b/test/screen_tests/wallet_view/confirm_send_view_screen_test.mocks.dart index df0e2d613..bab69e5d2 100644 --- a/test/screen_tests/wallet_view/confirm_send_view_screen_test.mocks.dart +++ b/test/screen_tests/wallet_view/confirm_send_view_screen_test.mocks.dart @@ -326,10 +326,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/wallet_view/receive_view_screen_test.mocks.dart b/test/screen_tests/wallet_view/receive_view_screen_test.mocks.dart index e00ef1039..75c6d795e 100644 --- a/test/screen_tests/wallet_view/receive_view_screen_test.mocks.dart +++ b/test/screen_tests/wallet_view/receive_view_screen_test.mocks.dart @@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/wallet_view/send_view_screen_test.mocks.dart b/test/screen_tests/wallet_view/send_view_screen_test.mocks.dart index e5e86bf6e..eb261af73 100644 --- a/test/screen_tests/wallet_view/send_view_screen_test.mocks.dart +++ b/test/screen_tests/wallet_view/send_view_screen_test.mocks.dart @@ -367,10 +367,12 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/screen_tests/wallet_view/wallet_view_screen_test.mocks.dart b/test/screen_tests/wallet_view/wallet_view_screen_test.mocks.dart index 674ad6549..d43cb5430 100644 --- a/test/screen_tests/wallet_view/wallet_view_screen_test.mocks.dart +++ b/test/screen_tests/wallet_view/wallet_view_screen_test.mocks.dart @@ -327,10 +327,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i8.Future.value(false), ) as _i8.Future); @override - _i8.Future initializeNew() => (super.noSuchMethod( + _i8.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart index 32719f306..80b582256 100644 --- a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart +++ b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart @@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({ - required _i6.Coin? coin, - int? startNumber = 0, - }) => + _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - { - #coin: coin, - #startNumber: startNumber, - }, + {#coin: coin}, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart b/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart index 661c9a1b7..f3598dfa1 100644 --- a/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart +++ b/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart @@ -626,7 +626,8 @@ void main() async { await Hive.openBox(testWalletId); await Hive.openBox(DB.boxNamePrefs); - await expectLater(() => bch?.initializeNew(), throwsA(isA())) + await expectLater( + () => bch?.initializeNew(null), throwsA(isA())) .then((_) { expect(secureStore.interactions, 2); verifyNever(client?.ping()).called(0); diff --git a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart index 5599f3a29..52ae05ecd 100644 --- a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart +++ b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart @@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({ - required _i6.Coin? coin, - int? startNumber = 0, - }) => + _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - { - #coin: coin, - #startNumber: startNumber, - }, + {#coin: coin}, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.dart index 712000aae..32872dd04 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.dart @@ -483,7 +483,8 @@ void main() { await Hive.openBox(testWalletId); await Hive.openBox(DB.boxNamePrefs); - await expectLater(() => doge?.initializeNew(), throwsA(isA())) + await expectLater( + () => doge?.initializeNew(null), throwsA(isA())) .then((_) { expect(secureStore.interactions, 2); verifyNever(client?.ping()).called(0); diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart index b084875f5..1027d0592 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart @@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({ - required _i6.Coin? coin, - int? startNumber = 0, - }) => + _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - { - #coin: coin, - #startNumber: startNumber, - }, + {#coin: coin}, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/services/coins/fake_coin_service_api.dart b/test/services/coins/fake_coin_service_api.dart index ea70545d1..413c493ab 100644 --- a/test/services/coins/fake_coin_service_api.dart +++ b/test/services/coins/fake_coin_service_api.dart @@ -88,7 +88,9 @@ class FakeCoinServiceAPI extends CoinServiceAPI { } @override - Future initializeNew() { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) { // TODO: implement initializeNew throw UnimplementedError(); } diff --git a/test/services/coins/firo/firo_wallet_test.mocks.dart b/test/services/coins/firo/firo_wallet_test.mocks.dart index 0f7a0b0a3..de0ee0bcb 100644 --- a/test/services/coins/firo/firo_wallet_test.mocks.dart +++ b/test/services/coins/firo/firo_wallet_test.mocks.dart @@ -512,18 +512,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX { _i5.Future>.value({}), ) as _i5.Future>); @override - _i5.Future> getUsedCoinSerials({ - required _i7.Coin? coin, - int? startNumber = 0, - }) => + _i5.Future> getUsedCoinSerials({required _i7.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - { - #coin: coin, - #startNumber: startNumber, - }, + {#coin: coin}, ), returnValue: _i5.Future>.value([]), ) as _i5.Future>); diff --git a/test/services/coins/manager_test.mocks.dart b/test/services/coins/manager_test.mocks.dart index ba4c8eb37..17d9efd5f 100644 --- a/test/services/coins/manager_test.mocks.dart +++ b/test/services/coins/manager_test.mocks.dart @@ -304,6 +304,11 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet { ), ) as _i5.CachedElectrumX); @override + bool get lelantusCoinIsarRescanRequired => (super.noSuchMethod( + Invocation.getter(#lelantusCoinIsarRescanRequired), + returnValue: false, + ) as bool); + @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), returnValue: false, @@ -552,15 +557,35 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet { returnValueForMissingStub: _i11.Future.value(), ) as _i11.Future); @override - _i11.Future initializeNew() => (super.noSuchMethod( + _i11.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, + [data], + ), + returnValue: _i11.Future.value(), + returnValueForMissingStub: _i11.Future.value(), + ) as _i11.Future); + @override + _i11.Future setLelantusCoinIsarRescanRequiredDone() => + (super.noSuchMethod( + Invocation.method( + #setLelantusCoinIsarRescanRequiredDone, [], ), returnValue: _i11.Future.value(), returnValueForMissingStub: _i11.Future.value(), ) as _i11.Future); @override + _i11.Future firoRescanRecovery() => (super.noSuchMethod( + Invocation.method( + #firoRescanRecovery, + [], + ), + returnValue: _i11.Future.value(false), + ) as _i11.Future); + @override _i11.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, diff --git a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart index ea48f7e85..403199041 100644 --- a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart +++ b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart @@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({ - required _i6.Coin? coin, - int? startNumber = 0, - }) => + _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - { - #coin: coin, - #startNumber: startNumber, - }, + {#coin: coin}, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/services/coins/particl/particl_wallet_test.mocks.dart b/test/services/coins/particl/particl_wallet_test.mocks.dart index 862c352d2..a93cde382 100644 --- a/test/services/coins/particl/particl_wallet_test.mocks.dart +++ b/test/services/coins/particl/particl_wallet_test.mocks.dart @@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({ - required _i6.Coin? coin, - int? startNumber = 0, - }) => + _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - { - #coin: coin, - #startNumber: startNumber, - }, + {#coin: coin}, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/widget_tests/managed_favorite_test.mocks.dart b/test/widget_tests/managed_favorite_test.mocks.dart index f81f66ebd..e980b67ee 100644 --- a/test/widget_tests/managed_favorite_test.mocks.dart +++ b/test/widget_tests/managed_favorite_test.mocks.dart @@ -1078,10 +1078,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), @@ -3056,10 +3058,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i23.Future.value(false), ) as _i23.Future); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), @@ -3409,10 +3413,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: _i23.Future.value(), ) as _i23.Future); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), diff --git a/test/widget_tests/table_view/table_view_row_test.mocks.dart b/test/widget_tests/table_view/table_view_row_test.mocks.dart index 2079f64b0..982bd16b1 100644 --- a/test/widget_tests/table_view/table_view_row_test.mocks.dart +++ b/test/widget_tests/table_view/table_view_row_test.mocks.dart @@ -1162,10 +1162,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i22.Future initializeNew() => (super.noSuchMethod( + _i22.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i22.Future.value(), returnValueForMissingStub: _i22.Future.value(), @@ -2302,10 +2304,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i22.Future.value(false), ) as _i22.Future); @override - _i22.Future initializeNew() => (super.noSuchMethod( + _i22.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i22.Future.value(), returnValueForMissingStub: _i22.Future.value(), @@ -2655,10 +2659,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { returnValueForMissingStub: _i22.Future.value(), ) as _i22.Future); @override - _i22.Future initializeNew() => (super.noSuchMethod( + _i22.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i22.Future.value(), returnValueForMissingStub: _i22.Future.value(), diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index 66bd37cf0..90afc98be 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -689,10 +689,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i19.Future.value(false), ) as _i19.Future); @override - _i19.Future initializeNew() => (super.noSuchMethod( + _i19.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i19.Future.value(), returnValueForMissingStub: _i19.Future.value(), @@ -1046,10 +1048,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { returnValueForMissingStub: _i19.Future.value(), ) as _i19.Future); @override - _i19.Future initializeNew() => (super.noSuchMethod( + _i19.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i19.Future.value(), returnValueForMissingStub: _i19.Future.value(), @@ -1313,6 +1317,11 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { ), ) as _i13.CachedElectrumX); @override + bool get lelantusCoinIsarRescanRequired => (super.noSuchMethod( + Invocation.getter(#lelantusCoinIsarRescanRequired), + returnValue: false, + ) as bool); + @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), returnValue: false, @@ -1561,15 +1570,35 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValueForMissingStub: _i19.Future.value(), ) as _i19.Future); @override - _i19.Future initializeNew() => (super.noSuchMethod( + _i19.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, + [data], + ), + returnValue: _i19.Future.value(), + returnValueForMissingStub: _i19.Future.value(), + ) as _i19.Future); + @override + _i19.Future setLelantusCoinIsarRescanRequiredDone() => + (super.noSuchMethod( + Invocation.method( + #setLelantusCoinIsarRescanRequiredDone, [], ), returnValue: _i19.Future.value(), returnValueForMissingStub: _i19.Future.value(), ) as _i19.Future); @override + _i19.Future firoRescanRecovery() => (super.noSuchMethod( + Invocation.method( + #firoRescanRecovery, + [], + ), + returnValue: _i19.Future.value(false), + ) as _i19.Future); + @override _i19.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, diff --git a/test/widget_tests/wallet_card_test.mocks.dart b/test/widget_tests/wallet_card_test.mocks.dart index f2d6e83b1..14744fc3f 100644 --- a/test/widget_tests/wallet_card_test.mocks.dart +++ b/test/widget_tests/wallet_card_test.mocks.dart @@ -817,10 +817,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i21.Future initializeNew() => (super.noSuchMethod( + _i21.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i21.Future.value(), returnValueForMissingStub: _i21.Future.value(), diff --git a/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart b/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart index 36d369769..ef519d4c9 100644 --- a/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/sub_widgets/wallet_info_row_balance_future_test.mocks.dart @@ -1072,10 +1072,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), @@ -2411,10 +2413,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i23.Future.value(false), ) as _i23.Future); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), @@ -2764,10 +2768,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: _i23.Future.value(), ) as _i23.Future); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), diff --git a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart index 357672d7a..16b4aa49e 100644 --- a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart @@ -1174,10 +1174,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), @@ -2514,10 +2516,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: _i23.Future.value(false), ) as _i23.Future); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), @@ -2867,10 +2871,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: _i23.Future.value(), ) as _i23.Future); @override - _i23.Future initializeNew() => (super.noSuchMethod( + _i23.Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data) => + (super.noSuchMethod( Invocation.method( #initializeNew, - [], + [data], ), returnValue: _i23.Future.value(), returnValueForMissingStub: _i23.Future.value(), From 412fb73066c5801f14881fba59c3d65b95df8907 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Aug 2023 18:22:46 -0600 Subject: [PATCH 099/237] bip39 passphrase wording changes to be more specific --- .../new_wallet_options/new_wallet_options_view.dart | 7 +++---- .../restore_options_view/restore_options_view.dart | 6 ++++-- .../verify_mnemonic_passphrase_dialog.dart | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart b/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart index bf7f088d1..3b50f8035 100644 --- a/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart @@ -288,9 +288,8 @@ class _NewWalletOptionsViewState extends ConsumerState { RoundedWhiteContainer( child: Center( child: Text( - "You may protect the wallet seed with an optional passphrase. " - "If you lose this passphrase you will not be able " - "to restore using just your seed words.", + "You may add a BIP39 passphrase. This is optional. " + "You will need BOTH you seed and your passphrase to recover the wallet.", style: Util.isDesktop ? STextStyles.desktopTextExtraSmall(context) .copyWith( @@ -322,7 +321,7 @@ class _NewWalletOptionsViewState extends ConsumerState { enableSuggestions: false, autocorrect: false, decoration: standardInputDecoration( - "Recovery phrase password", + "BIP39 passphrase", passwordFocusNode, context, ).copyWith( diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart index 59d1c0a8f..44ac51aac 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart @@ -535,7 +535,7 @@ class _RestoreOptionsViewState extends ConsumerState { enableSuggestions: false, autocorrect: false, decoration: standardInputDecoration( - "Recovery phrase password", + "BIP39 passphrase", passwordFocusNode, context, ).copyWith( @@ -586,7 +586,9 @@ class _RestoreOptionsViewState extends ConsumerState { RoundedWhiteContainer( child: Center( child: Text( - "If the recovery phrase you are about to restore was created with an optional passphrase you can enter it here.", + "If the recovery phrase you are about to restore " + "was created with an optional BIP39 passphrase " + "you can enter it here.", style: isDesktop ? STextStyles.desktopTextExtraSmall(context) .copyWith( diff --git a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart index 3326622ad..bae25a7e1 100644 --- a/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart +++ b/lib/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart @@ -113,7 +113,7 @@ class _VerifyMnemonicPassphraseDialogState children: [ if (!Util.isDesktop) Text( - "Verify mnemonic passphrase", + "Verify BIP39 passphrase", style: STextStyles.pageTitleH2(context), ), const SizedBox( @@ -136,7 +136,7 @@ class _VerifyMnemonicPassphraseDialogState enableSuggestions: false, autocorrect: false, decoration: standardInputDecoration( - "Recovery phrase password", + "Enter your BIP39 passphrase", passwordFocusNode, context, ).copyWith( From 40ebaaa54751e9e371e30854cb6503bf95ae1dc2 Mon Sep 17 00:00:00 2001 From: Diego Salazar Date: Tue, 22 Aug 2023 20:10:12 -0600 Subject: [PATCH 100/237] Bumped version (v1.7.19, build 187) --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index bca5686c4..cfdb08711 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: Stack Wallet # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.7.18+186 +version: 1.7.19+187 environment: sdk: ">=3.0.2 <4.0.0" From 961b687e274c010e9373ad107b39c81de6dab3de Mon Sep 17 00:00:00 2001 From: likho Date: Wed, 23 Aug 2023 15:13:17 +0200 Subject: [PATCH 101/237] Test node connection when updating and node and show error codes on send fail instead of generic error --- .../coins/stellar/stellar_wallet.dart | 25 ++++++++----------- .../test_stellar_node_connection.dart | 18 ++++++++++--- lib/widgets/node_card.dart | 12 +++++++-- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index 6fecb6eb3..c53e34f59 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -58,10 +58,8 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { if (coin.isTestNet) { - stellarSdk = StellarSDK.TESTNET; stellarNetwork = Network.TESTNET; } else { - stellarSdk = StellarSDK.PUBLIC; stellarNetwork = Network.PUBLIC; } @@ -217,10 +215,12 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { transaction.sign(senderKeyPair, stellarNetwork); try { SubmitTransactionResponse response = - await stellarSdk.submitTransaction(transaction); - + await stellarSdk.submitTransaction(transaction).onError((error, stackTrace) => throw (error.toString())); if (!response.success) { - throw ("Unable to send transaction"); + throw ( + "${response.extras?.resultCodes?.transactionResultCode}" + " ::: ${response.extras?.resultCodes?.operationsResultCodes}" + ); } return response.hash!; } catch (e, s) { @@ -278,13 +278,15 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future get fees async { + + int fee = await getBaseFee(); return FeeObject( numberOfBlocksFast: 10, numberOfBlocksAverage: 10, numberOfBlocksSlow: 10, - fast: 1, - medium: 1, - slow: 1); + fast: fee, + medium: fee, + slow: fee); } @override @@ -482,13 +484,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { if (response is PaymentOperationResponse) { PaymentOperationResponse por = response; - Logging.instance.log( - "ALL TRANSACTIONS IS ${por.transactionSuccessful}", - level: LogLevel.Info); - - Logging.instance.log("THIS TX HASH IS ${por.transactionHash}", - level: LogLevel.Info); - SWTransaction.TransactionType type; if (por.sourceAccount == await getAddressSW()) { type = SWTransaction.TransactionType.outgoing; diff --git a/lib/utilities/test_stellar_node_connection.dart b/lib/utilities/test_stellar_node_connection.dart index 12e1e8dc9..504a81efe 100644 --- a/lib/utilities/test_stellar_node_connection.dart +++ b/lib/utilities/test_stellar_node_connection.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:http/http.dart' as http; +import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; Future testStellarNodeConnection(String host) async { @@ -12,10 +13,21 @@ Future testStellarNodeConnection(String host) async { ).timeout(const Duration(milliseconds: 2000), onTimeout: () async => http.Response('Error', 408)); - final json = jsonDecode(response.body); + if (response.statusCode == 200) { + //Get chain height for sdk + StellarSDK stellarSdk = StellarSDK(host); + final height = await stellarSdk.ledgers + .order(RequestBuilderOrder.DESC) + .limit(1) + .execute() + .then((value) => value.records!.first.sequence) + .onError((error, stackTrace) => throw ("Error getting chain height")); - if (response.statusCode == 200 && json["horizon_version"] != null) { - return true; + if (height > 0) { + return true; + } else { + return false; + } } else { return false; } diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart index 57482119c..59e3663b5 100644 --- a/lib/widgets/node_card.dart +++ b/lib/widgets/node_card.dart @@ -29,6 +29,7 @@ import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/test_epic_box_connection.dart'; import 'package:stackwallet/utilities/test_eth_node_connection.dart'; import 'package:stackwallet/utilities/test_monero_node_connection.dart'; +import 'package:stackwallet/utilities/test_stellar_node_connection.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; @@ -192,10 +193,17 @@ class _NodeCardState extends ConsumerState { } break; - case Coin.nano: - case Coin.banano: case Coin.stellar: case Coin.stellarTestnet: + try { + testPassed = await testStellarNodeConnection(node.host); + } catch(_) { + testPassed = false; + } + break; + + case Coin.nano: + case Coin.banano: throw UnimplementedError(); //TODO: check network/node } From 128272cf20a0d3d1a100bd14dafbac175f095cb0 Mon Sep 17 00:00:00 2001 From: julian-CStack Date: Wed, 23 Aug 2023 07:59:34 -0600 Subject: [PATCH 102/237] fix typo --- .../new_wallet_options/new_wallet_options_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart b/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart index 3b50f8035..f6d3075b2 100644 --- a/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart +++ b/lib/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart @@ -289,7 +289,7 @@ class _NewWalletOptionsViewState extends ConsumerState { child: Center( child: Text( "You may add a BIP39 passphrase. This is optional. " - "You will need BOTH you seed and your passphrase to recover the wallet.", + "You will need BOTH your seed and your passphrase to recover the wallet.", style: Util.isDesktop ? STextStyles.desktopTextExtraSmall(context) .copyWith( From 4729789f9aa9d27c2c6d773ec665a51d819a2940 Mon Sep 17 00:00:00 2001 From: likho Date: Wed, 23 Aug 2023 16:59:00 +0200 Subject: [PATCH 103/237] Add break statements to case, add test connection to node_card and include port when testing node connection --- .../manage_nodes_views/add_edit_node_view.dart | 5 ++++- .../manage_nodes_views/node_details_view.dart | 12 ++++++++++-- lib/utilities/test_stellar_node_connection.dart | 4 ++-- lib/widgets/node_card.dart | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index af6256d23..692e34633 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -194,12 +194,15 @@ class _AddEditNodeViewState extends ConsumerState { try { // await client.getSyncStatus(); } catch (_) {} + break; case Coin.stellar: case Coin.stellarTestnet: try { - testPassed = await testStellarNodeConnection(formData.host!); + testPassed = await testStellarNodeConnection(formData.host!, formData.port!); } catch(_) {} + break; + case Coin.nano: case Coin.banano: diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index 59ff1efad..3354ca396 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -26,6 +26,7 @@ import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/test_epic_box_connection.dart'; import 'package:stackwallet/utilities/test_eth_node_connection.dart'; import 'package:stackwallet/utilities/test_monero_node_connection.dart'; +import 'package:stackwallet/utilities/test_stellar_node_connection.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; @@ -170,10 +171,17 @@ class _NodeDetailsViewState extends ConsumerState { } break; - case Coin.nano: - case Coin.banano: case Coin.stellar: case Coin.stellarTestnet: + try { + testPassed = await testStellarNodeConnection(node!.host, node.port); + } catch(_) { + testPassed = false; + } + break; + case Coin.nano: + case Coin.banano: + throw UnimplementedError(); //TODO: check network/node } diff --git a/lib/utilities/test_stellar_node_connection.dart b/lib/utilities/test_stellar_node_connection.dart index 504a81efe..683d946c9 100644 --- a/lib/utilities/test_stellar_node_connection.dart +++ b/lib/utilities/test_stellar_node_connection.dart @@ -3,10 +3,10 @@ import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; -Future testStellarNodeConnection(String host) async { +Future testStellarNodeConnection(String host, int port) async { final client = http.Client(); - Uri uri = Uri.parse(host); + Uri uri = Uri.parse("$host:$port"); final response = await client.get( uri, headers: {'Content-Type': 'application/json'}, diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart index 59e3663b5..81fe62357 100644 --- a/lib/widgets/node_card.dart +++ b/lib/widgets/node_card.dart @@ -196,7 +196,7 @@ class _NodeCardState extends ConsumerState { case Coin.stellar: case Coin.stellarTestnet: try { - testPassed = await testStellarNodeConnection(node.host); + testPassed = await testStellarNodeConnection(node.host, node.port); } catch(_) { testPassed = false; } From 89aa4e2a327dec3a8b70e747545b076f216af725 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 23 Aug 2023 10:48:28 -0600 Subject: [PATCH 104/237] tezos images --- assets/default_themes/dark.zip | Bin 660115 -> 676128 bytes assets/default_themes/light.zip | Bin 608006 -> 624020 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/default_themes/dark.zip b/assets/default_themes/dark.zip index 4ec1a415b80e284ff31ae47e778ea38513befae8..eb20d7e6e6279c6c6ca50a76aef686d968861b47 100644 GIT binary patch delta 21204 zcmYhj1#sRvw6+_DhMAcgW~PQYY11$?%>0GHVP8J-aex<2r@Q^DN* z`H|7{xg9{_^R%-Qa&whp_xT3i;**Qh`EvPrPV(XP@>apz^Sr^Gb6pI4K2-F)6CCg5 zcv^hw%sug6?ChQ>0VLfot@|G=W`YNCBriHgTTS=1iwq@PYjjc9(`tf6j`JaDN^K<} z?Td6x^^-+SAuC686BNRU&Ziba`)PMlQl7Xk1&xPEt%dD3NjxP&t8+FKN3gnkQ#imx zQ@%>0Q+k!qosX8cP+_J1nKR1yyxh!ZiQa9$MoIc2MbgG^x-#pUc`jm zsMb9JJgm=jgg1~r-*FCanS0*fD(J_^@Wvgb0;Yt#IJ1ohxAr%I&k&E6bm_!-Poa|U zrvVQ*-#&-4laqG2LsINA-!W+BXuLi}ZQ65&k3*a;9p0X)bey_YBL7gl_4{1iAG#el zQ!3HW=M0m4@MNnUhcI`)ecTf)9@$E+ru=~cD(_8C+T_Pk>)j$hQi>8Y=s!Bwg$`@U9a9qR;6`mu zg3Drr{W(UK1Ct@YOVp%EL6x4fisRs>ln|RXXN-6xwX&H-q~aXHsB(H$=J=4}LwQ(? zFJ@(mT5}Y}s=?bcbVfB6SVGUd*4jPMXH0-9x`;@K)i9D_QUKKisG5eoqJjW8NsYI5 zp=q&4653SvBHm4Qx8R;BrOsRe=T+tilhSETDGP7M_b$DH`_z&$o6|P$#+bzFl0H5` zV%9?y-gpn9&U6;ofjz^SL64%m`&jZhr`f)P(EUbrzbKJLf5E$N%QlxONKWG(^($z3$1}y zZ}4hx-@6G3o(;E@ycu#Bsn*}2D_)PccQ|*`^dl6y2Zti1&E&&Z8&slrSBlN-!FkvS z2wf*aHwDM^wmrrej)t9+d=)$Nche8Cik}m2j9gi|CU;^zkLDa>=n;TL)oK;YU?!23 zctz59BySC_cl3%eku2++*6w-uLvr(^k|%T-d)u$;&FVV~OUBi{JrFh3dWosZOJoD} zW*VPi+f$_UW>)dXdb^}-4yR|nLDS1<5_AVO`yU!3EpD$yyVt_AUovny!8`_x@`~_N z4>C9;H3GuvtD#gvA^Jew6dS#AjZzzBT3`ySi5--Oe7_R{P6c77CDL5ME;t}_B;?T*UHI>KFn5-cA z5co=h3NA2uGOI|DAAXu5y=qXFP7J>BzQ~0XY961oH`>npX{ZO_+FFIg+)kR{hNV0Z zTIhA7vA&Q&3n#l+LpulVrjd;|U`k8ko;}yb+#y++F@EqYeepa#7VI(`pxbX|oum#E}dj0%`uHHhCuWfG*T(mj8={M0Tc9=`*5s z1ZK%)rl~s1aKi?ZPWTzMvGkt$f)UyBQs=?-2hmkEr zujPfus*dxIbyVR`-aZ9|0?7tM3w%5`{OHIozuI3($iVzaXpk4S~7 z+#gTUv;$&*f1aV$&+5IAaVM+_r3c;ciZglahm@WrPyB4!kLqZq-!-yEzm$ye6fh)8 z*!|CoMwM8zKmml@Wu6b3(HpTLLH9dCsGS8hHPf$ zP#tFvr+>=vnsAu+lm4)xrn2zj|AV6yKe*H|*HWiutUjI0qPF_!0ZVub~ZqOzUwA*Lt4r&^{1 zS9OqhgpiCP@6u!WpBBH*_^$h;_qHO$)A0(heCC7uanSRqA|#nCShAFj+t!gTQWWk3 zgoShLDE>0V@$j)7qZ=!;=MbPFUbE)?3cKR_XQ;jTnJ>CWY3$Y8x(ea%XJWj?-Doa` z$RJ3W)4=z=OEQXmGhl}5atcm$LZ)U8aNqHHh6+t(g-evCHWp9Z3>n!?<%`WT%HTQV zd+1b;5WHWnzE!)L&!aLQ+)nZT>lY%?k|a-42tn}4wK@iQnFfl zsa|rw!}!M0(B^iiRN|&Mz1}5=4ct>?0xJVH@MhCX1)+KrKX7Nu(-xB4(vw{niC#46 zbH$dI)0oh~X`mTgzKM~KHu97V0l}kjk}G3pNgqPvs2EYa19m}CGg~MF?ZhQW6>vo4 zI=kPq$cf-Uk;s2^%#Nu=WpPQLZ3j5NN*$?jMAt3{x#`liYg?Hz=H6rRv*EMu_1a98 ztR-B5nm-(FwwPJYXJ6A@f`pSSxMveAQf{5*m=4r?hz_@qZ|y>!kBATN0jUp9C4{f< zq0kb>iHWiD5O@PPogo2%WY?m+isJR@0+~t0$f`|#-o5sGxakL@YUtWYqi2>Czot(k zXLuIV9NJEmuR(pSCbP`LwU$A4QPmxoFnQ!oMpjbE7+p6SDL`oa2|U_HsJZB%0n+jbSmFk z7eB>~=;E_>taErt-4vVkfXaEvQ002*_GxzFfXMmpxb>J zb5_FL#kspUH{wp#%u4avR96lQo*%aJc#GdSW7jhUa={xNm zgXOWIDpPWLqkqo~1lAI+PlmHa==6NKjD)CcX8VttM2i(-=!sfl-j_@TkG(%jOV&z+ zi9W7l-X5!w{rYHDY|l#_!E8_1Ek4URv-H?)oT=dH+7^DPGV5-IeGyQ|r;{UOx#k(o zNRa>iBT4NdP6wc+9BvG>GOtFD#>#_RE--8OHnR@*W#k6*(qKO)DMOW=lXf&Bd zEKFqtlDALZj|x|OokHonKmeKXxD?+UT)eD+P-;+E0xd+?MqbcBQELbHneH3g4tzlp zdR|o4bM`Nz4S^F5`-Ua;OoG{n;h^F>8y507%=M2(3DP6k{vk?$U(2RJe`2`-SSZ`Y30Ek8+2TgrEg4 zkDDw2qM5ax6qcm@6DWDEQp_z%)fsti z;G21T;W_pgv99wO)bTKV+~2vK46dMsYZ z4QdU)8s(!mSh&OBJ-IjFI?#i+I+9THe$?1Ge9lB5C2a0~tf>_L-?{vELlcfjl8y>zv9i^WwzEYk@$zgvCiu9je;m*4>CkZ zY}jkZ5!84n;4AvyQ##J{9MV*aHQm)ZJ;Le`f>Q*vVaN6dQJ3OlROLeirsGLON!GAI zg&935M*ZBxr09;5WY+(~Nnpr123wY8`-uF$=`w#mIdA~AV3Zqi^Ea8sN9co*fh#uq*ri_;E5OPFKKszU#%UvlBX0e#yQtUw<{SY7k{5A2{AZM zj=$}b^Dx{bHZ7*Jdj_;V7{qxac4!gxzE6-@S>-jNsBaxA5@wreM--{s@N7c?*nja< zX=V}lq36Ee;$_l#zyjxi> zQm)Az78{}p)4r{*JkanrSrk?@c14f2&NlPJFba8RS!gEvhBcQoNOsyx0$0{vgr}>+ z@VBe$S#3mx_`jQ3-I0X&H%4?YNS%z->QDU1+czTk2}kv18YB}Ze;e0#QCTNU@+P(R z#%~^RPn?`HId-f}h8>N%q$o#s4f;#Vr29Gbqrh-v@4oFlBz&bJo);Ug-za!){pX&v zq#rd5$rY!mwchApt^!2wfaI}{{ zdBN_Zk7CGW#D+a~Pz7Nxy0As?OKbP5M`+0tZ)+F^!J|;YWzE(ckdiys&@;TuDN|p! zy2&B)hKPSqdvNya0b?(_n5I{+PT1g~niNzvf3wd#EHj zj*+U+kwze*Xah+!kceKR7}ETKE9vq>PlORZoHqfgdo~rkK-WU?^!_LY_0O0#*Kc@& zROE>ji8(eTezv|h&BqQl=9O# zg5lFdbC&D^l9KEt8Ry?V7a7{|;KAGPVs`_DN*BS_{0$_#yN6$}1cQe$a-41PxPzBG zBftxk2s{!YkqTrhqD-AIczrLLNC#L4;PsZR`Qb>TC-cN?Lo9xmZTO{|CEPu%l=B%OmLWe%;>4NFZ&~BRZ)I#>Y@-YUMsf%fecs6MyVO{H? zo;q-87Ys*>4J{SYkNkMF8ZhjLZ!B?o;q>^oaY5SK4 zE-H=z3#8wmib?Rhz!`^7E%xMssdgfc@A|M~Ao9oAtZ_%e%lTe8yl};6MP#B~n@KR> z>=}tM>rXIs$`7Ss7(NVSVb|VertR3k6v_)#*YPN?WD7cBQ3!7dKR@eC#jhjMW-Nv$ z^I=gi_FF+%iBP6SYjuiuUeh9&dW2VAH}@0(-jkg;P$QBWwem|4BrG~t7on1zEnM}g zL#yoT7XW*^MbNjUi!=BH+BHLLfkvm6J7OnllTyhj7+sV;Y+L@-UXFsAGKr(ifyan1 z_oXpQT#dp`+7TsrhCkham*p#&OyD>Yh42`N>ceyRm#afwI_o`2l8&%UR;kM;C0;#n z2ylitleNfAP!psuFGs#~sBm#2F@)%F!PO~A#6R&;U}jhx5nFG!X%y7-*X8QvXO~BW z#PW+vDPT;9{_|}Z6VX}T#Uh_GOMJex==`kcs`JGfyA>yWj9LCzxQv243^Qxw1vGoF z@lZ2&rP;cDw^x!5gEbllHX!^(z-b47%Ye-zxC^zEn>~v*ukXPe_AiKGLD|(ko9|S7 z;;ihShWPb2%F=`)eW0(5Z%k2;0f9x~sQ;||no(+1#W~DzsP3`^PV$JLf>s>v>^L7f zg5eLuOK)v-Bqk@D2-P)2lfo|Z@pvmwNkEbRM>W z1_nc(h3Z|3pP~F&By_tJ4=@!uP~V%gFHCP47Sx_DiI$4_4f%LFMBbRX)W(En#H*R# z5=4wak+C3y#}X6xfKE`@_&$YeE)%momtIFoee)QUvj3_GFz-P&I1~mH#1h6UgQ>H} z-^)W(rNUC(T(O9HE1xeVD}lKrpP3e|PBBorh~#rfn?^n@vB|y$s|0GX_Nbi2Ge=HQ z{VrY$szULRAFyO{J-f<|M+m5%Ko2RIM0m>lo1i#t847dvX8;ZS7GfZowo(lb3q)oX zuRx*VEGS_i*fBSjhKT_DN(xK{eSw*BttoJFT6yvn-*6u@(}6+1&euKPufIE6Pa$i9 z#6+TZZ)86y-#H6$>UT3MO69ub?}GYTVlcLUTPrhflyT)_4@aAAo%zn zjN8t5Bp2fM+b1*PM%fTgW!mCL?W9r_hqiSVdp7qW2%scv`@R|EY{C zMM>+iKDhp4ktEe8KA zEEfZIs3Xe!ghd?~F#aP{BZzKni!j6by6TP}x@h<&zQfYrIiFjt}d-5P3RfC8cAA>wT&^T+-;^F$D|RLz>ZpM9XrVY(!ZY4Ajo!O}?P;xhNi#YAiaZR->YUJK6^eqLUb$dkh}f4$^Juoq$&d#i#7+@t-0@JvURogcT}5|>63LYI zPa|fstXXqX#0ulh{5!80FKUY^9jcKA#V5jAEarB@!e9E< zXm%cj7AbpZz9WC>ZiLMv#MB0aV-@{SCbnQBX0?{O^KD;*)rL#hm~@@@qSv*Zz)F)8 zF2B-7#P7&oD*guikc3}ZU?_JS!IwEjun_>m)lyPb2r4@ujoY(^+l0)Xoc(iP>>Fy&K(BR7o*zv(Sn!wA0ts z@)t{+Q?rCD!V>*PUl&HjyKw|TWJ)BpY#fM;kz#LrR4q=kZLzT1{$O1#!Z}~nK>hVH z)JG_+MgJmodoE^7UgejfSZRZn%^(DVPM zp6F9dN1OEvpy|@=H;|5Iy1&9UClyf*5`hYqsc*h}K9$;tx4^s6>o_r>pUz(YvLhPX z6_31LB?q?~@BlhP>m4wbb*n~h;ER+Mi>=)A<7QJm7BDfUvrnv>M3)$0x zu}|4NZ|?myJ(Wa@3I{4amwyTtb=(`Z+{*>No@mzmUe$khIrQOo`qa;9BVk1SBmA8- z&;mYV?$=jFb*{(L@Os-CpuNrLn`*2I%X|$eLv&7dblhbb&TrT;23y$B8aYjy+n`z( zKN?%b<}Z~d2Po-Oa8<)3Eqc3KKA{+y&k;nKDgin2@N4PnmmTcq$t_dB=Tk_IAEkF% zpmUQ*1O%OZmTRL!<`Y>(vH4}}xovMIWeh>uX*0r2`y_sGI{n2u;87iS9Qq*ZMpP0F zzh6n*I^p7CpWJ&evrdr+w+R{(aMY{!*}%a-@4Rp8xaxpqg#Sf=$LfTNPce0p7d!LU zto;`RhrJ#3HP>hvDnjEYL2=4f5=FrZd9erOuyR~-jIBDUF zZ?O9kclz-u)dYVrh`vS7Gx&wsDLn>7d=rk8!H?fPYO9^fm1#koe)p|+{Kbbt$u*N> zYyMqqUoDo70<0NJ_+UA=zF)-Vm{x1_qNMK@u6-8#7dZ%F3^-E6!0_cNVw-2(Ek49g z3KWsXz>~CPR$S#D3VuCZ#fE*$Fx!IcV$jMwVH^2t3BIq^(jt$WI6NZ-ZP(I40xna2 zRc*C#0J)kJ41W1Uxd8L#?a~~EP8jCC0knQkxS}Rf&l_X<7Pi5M_yx>Sa)Ysv%z1yk z@k_B^qgK+mH_#(PEtl$z4=f_0ehEx%%myLJw2QbrG-C~qIAKI!doVZ0nF#lT~KOO6ydjsCo^txRVU!fzl z5*OUY3~ItJJTf@$CCViMg_=@TQ=xdFQBuhWlGQ!8RKWoynTwMQC-~0(>378~YB5|% ziSNix0R9!GOJj+3r@#%3vqK}nF4hdOnK@|qfDa`Ya^{|wK z9I)4A>`7rdSCQN?l?!%Q{LF5IIOkYh4Mb{OtGS@zIU$;xVJyOJe#y-Px{(}X#Gt&m zWZ}`Iy<}mzJ=e@qtq)SEJXWvbAD^Q)w2LRN9h{}$|KW-Xtqmk6aE z6LRxiju6=gc^>Opi-Ag*0*cZG zz{P7J*Yf)bj_6;E31L79fTbH6sby>VnAh5e<{J59<6Xc6!u_F;b+wH69xkIo&PuVWF0nEeqUd9Uaz?8EHW=am#o{p-V>`l796+4I!ly2h2hx|^ z*^HAkk}OLtRkYmrLu)CGUd8TdOZ2y8-&)0WVCWYoy4Su&BmP&u7gGxWQ|%0HS{3AdN%f-cDVlr z<^8c2GmB){E8(5X+%dvQrd*SZ2Id_PH|Fx7yc&Yph`Xf5-$N7FAKwE^^CuKU6>i)( z2EKL+mJb!vtK?NUJcNwJWzbJVI29-9A>no~Nh(w?ia`DF5k<#JG6b(&57?R;WR&`brlsxL3_mJ*;8TKFe7nnphz!4FIgg~i4>e&Z2z2i5VjTZ0 z_=-OY)g||rlF6$h0$U`IqSw9M$}n8?J9h3^vh4M$-7!Bl911g&M84gi4+J>9C~N|g`LQbN*h+f@|6?7pCM!y21#oLrbgQne4?SM* zUl7Z+b3aYr4exNIl_?6^g#nLkVhr|Ga?ozGN#Ix5G6+clFObD1f^IdBXtMY@qE1VT zeS1pYfptb*7)L2V$Ke-^3aDiXwer_Q`J=ywc=m&a2Ab1pNIqbFirKy?bJrA>ApR>N zFkd5lG)LU%SRJ}Uh{IF88#=9eqF-!wG#{1I|4fW^Fct92*~M5SApoEzSP6ISX;rvy zW_;(hZRq9#{8Mopo3Z6@L0IMd4SX;S zL3dIHMLqqgT4eu~cq*;pczwMrnIUG$;XxnAt2w_Vi;sKoM-8ZL0I3@~X3|C~UvMwC zwxYpnkCBm@?+_h5w7*7TQVe-hv+()iH}9~2JNx3|YltDQ0;uKUA%XdfI8+#?&f%$6 z5kwTyE`e@~Da@D1YbCoc_*!pk8R$PeEe%t>>x=xYF{1oT<}$rdZ^#LPWeJkJuAXBs zuZ-laSx+}a-2r_XBrhs&^b8exOdfElk`WQBeM>xRgaPFXaeuk#<@@536r^3b?B6sT z6LX`&ms?!<{K@z8pLG=r3rn`6W&@j!g656^UkVs32paZU0;0F2NH4=EAS|>l644bZ zaz&M}_g^sEV z0?c(6c-T+Zd^HI%6_-_Og2f<9f}{3Lvqrija&3WL&G20kCv6nUpsreFYR=yGs;WW zHa<;snSmUvm}}jb;~nJ_WXTOyR)$|k#+0$^^j<7BL;v)q=HDgx(6m1aHWFX?7i0Zw zxuJKZ(Q$EsFWv#n+B&i<@)R9!?kM>Jtx#Un@R_vPh)Czp!RS{+Jz1&4#X7VslNn!U z(1Pb}TrlExu72iyBbbY1Om4Y^Ib~AOx$sp*Lt8A7u+Ue3Fa&*10=sghmcwcfe9zqxr$Ljo;0ft-5fYxa|#rt%>_YjXLNZ8Yk1|&QoGw`pCa7w zIk__zzn3vFTxbfXAxE?*J%nfFRHJk>!;q&&Aj39m@Sf%ui`6|JtZlihtf{SUo2*j_v!7DwRb4UJSKR$KbzK1?yg)@hJptE5{`dUo{YV=g+psq z2e?LIZI??Ni6V`pc=vO0EM5Y4AnkW=F4Tj_sj&piGFigNNtV%lcJc}RE3xk9o(lS- zlFy-EZ*3`jbJ@xDZ%)aLn)Ay*e}H!%N9O7+#vy+FN7vAYG9t$C@)Xf4j$X}wCf3Z# zA4dfXe%@5$DZ=TKvSI2Ph9;DYTp&Jv^x})Hw(;WbutTV=Ob}F^*9|R4ustoRxm;u3 z4OG*dwGGaR#+>5~QX}efbsKbmSPVSw)EI2hQF9dh8u}Jqo?DF@@afc#e*w@#Ip@7b z%@JJV1d(RH6i`cxE(!g_D)D@j8c@37_nf@MF9{&N4=2-lr=}s7-=eII*J<_F>`j%A zY3C38dU?RFTAB{sNXc5tdn*XMXL~U5|KcE+?$0iJjQ)*$X>LR9Jsy3|tZ6KcR*W1o zor?zsvk5r~S;4%_s77q13l0cTqFvZFmb64#gJ6!n_=ySL%enC$OP#)@<2Y_!ChC@E zzNb|}Tens$8J&nS>TS!s?+}@#kmq6=7%x3A{0%hhavEN3*~Yt!uG{;D;glc7`AN*5 zF3R_%g)js4<;r^nNju$Xg|`veWD=Kmp6-=Df-^n}(-iE=c{?K8iV^sefATdvtkJV9 zA%iSc0fDEyJc3{vk%qafy%^Np*6kTctf33*v@ zOiz?$<3i^(o&_=YcM*Urg@kQ1Yh>m*W)IwoED-_Cc^f1r5STN@k6yr9p845oael$w zxa|fXZkrArxj*)GKM|WVOU?Tbnr2Z5f&@V_e&eBmO=%;c!+J}tqs+57fl-dlCDN2- zS)p8zq!is|ew_HdJ;Xkl?GuwI4Za#4ops$;5)TnCpnfcGDGRJNb#!fEUytha=iAGc z6Y43rzJ<_pzh}O7Fd(ZLK}ZfxRWSPhpfeXr_dAyeJ`EP=O1gvpJyhhUlYu5j70ka* zY{QEkF%^}?#fw($Ds#A6aQWvGKXM-u)GwXm^ViaTEo`h#C*|SDiX!qNiRRN+m8MmE zcabJhk3q1VI3MtufQO-yK*H+3yr`RvviJs}YAMG1?6b8~8}~}QTi`$CG1(?6CHFPw z>FoaGF7I;_-c}a=clT)_I1gTO^&pr*Nzc_vmYhcP0J9SlCx@8^SyL!Ix|F3_@C3-! z$NTBATAU&yCI2+`Kss<$Wyp4bh1>?Y`XqD+aTpGKp%c&<%fk;ACMp97i>UKqwotJm zPb{Pc#+8t@Zy=>)A_W$ln0j>R;v}~iQM9&wy_>jK5|%U+y8aplf82R8r!5oP#|^ye zc}(-0bp>dTeT&ws;YcS_br(PG+TH|wBnbk`@of$3c9q_G6(r2MW=U$kr?r1h3s+ZA z%Ew%`eE_3-xY;pR?;xQy;#3T7v$RPnYraYZRW7t-!n_y?DW3ec2~9S)ejmoT#M$PI z)V(7kt48$5-9^(^yI#o{`;*>V2DOK^{>rGh!6{b5&rUPP_lz@!8eqyxC+K~0_~)vThtA-U)tg=i=X&fg zYhuwTB4FV(C-^(yV;wPz^0-YbonclfjP~mXr3)x+=DtuI_ReCe7AA`5jG0ezoQD@Y z=KVrEM7xx18Lji~0-D)`MZ-aP35~dY_lB1uAB(<|I6V!CzM>sm;a$GgzKSS_v}SjI z3%J>uBT3sfe0)`IIunTG52c0ax|VcfkMqvxzhi~milupE?>aa^Gw|Q^wjO=Gb*rRZ zGWx@CbPwC12Wi@S6&lpu{lm($;cm(y@a^&T;d-Uz!DEwTm4HI1LH&=m@X^xP`XdRa z&{2!t=4a(AJACYcKi1=-Q^M>Mui>X78i1rw#Qwnok)VVV8NySd5u;wtN9bJ?3@J;R zlaUeI!Fl}Qg)vnk?%DI0*&wCz+i}c3&poE(7Om`XKI3x0h+pO$mwMc6ic@lCW^Fi% zLCIS0cogOWtRS5qP_aiu}I4ByOZcZugyB7brRaULPleu;CXRrh?~6 zx0P5f_24**(^DgeCs~ozdEw zbuChF)B0D^zsbj8ijRo6A;@W90M|d$Sg4-jadeGC1*04sK^;0%J1KK_nKlf*xGr*= z^$`{CVbKQk`;J|nIFV$83k5dB}YJk`%kWxP+&sk5# z!;EO{s%Gg@q;ObM>g(D`OvzEtllVXu(ytPu^X7=xJ@iS5E9GWd^4jQn4Tt?EL6nk! zKhZ*X$oy|jU~?0T3<1_tz*j}v@s)~=TMhl|2Vw{cA(U;0e9HXcw)Ys{Y&Hj=P|Eyt9@S|O0^n8nlF8D1F)keH;i+JrYDFXYm8p6 znf5Q)AANAA2?%o1_(@9lCrp5r(8KXadST*D_O0dXw|AsR&<4f?U>ZM~cVrB9-nL{@ zQvg=c-e6geUrk?Ii;Fjenru$`R|6J|xQ9{W!XZ)^o8K!23#>wkon+{g2_f2x8sHdH zkWlBq;bgiRnSvS%-4>1JLLOB3nnE@^ufjR3*QEuj^$IU8E-9^mM7?(6U_4)|xZ_T( zCNA>B&G6t_`BlX~=N(4q@PwN@ zVrGY%!lPg6B!@F@?884uU${JD1dH1%LaF!phliD`7F()`QlY>{XU0gA`R>TkxsEZa zH{OY5U8EM5Oaz*}$_C>e7(PCTpk=|axz z!Li}bMsp3d_*1MM1h`sA?hV6K+et!F<6Bq%B^?G`BE<4F4?IbVpV|iR-o+6xIM)ZA z{N2}Z+^RhYK2qCZTunyvq%&!uWw6zAW>0NtShaVT3ESk9a&#Le65;FhYtlZwVZhOA zJFx*Aw&;6JIgG7_Y&(<|3-|D^FRixtLUuMpplH3F!5Z5r@W?;pUxt&yNYBvPL^`53 zrXy(|&$l;+oLxTFozXy6*XZH_jH|SZ>{aAXB8BEHAa>s+8_eggDDS=GTe$B}e|Xd5 z=Z}}vGhTz*pr>oMyz@(B*wl@t&L6z#wTgg=g9rUya`bzoKrJgTFW%K4h1X3+KKq&V z7lFqk7(p+wjR-WoGS7B~IkV+E!kO#RkA6L9*Pnbn=-!CNDd^Bo;(uwMxznCq=qTB+ zeq)qdXZ$0m-pX1YGKwQr(SruF$^rbu!QHAlQ3^C2n_~aI^}FzrE0g5tqh%!_c;F6u zgT%blI01>Jbx(^uoQRyPzH6NKcNW=1xPAL2Fe+-Sah zIFOnB=boG825Z+{?b&Zuexg&ypqIeCdsF3Wo*mozES;7n>pbPb4G1hdGz>r^mG(pF zB1f`Xgiy(GXZ{Uua)YyA^2e`|0%$xDDhNC)2_=SA=m5GxX6RCnXP+nVgeE1gLJ&nn zcJj5vXCMx1&ch~a&Sn9X46qm<7%dXRn&Y(;zu%JeQL}nNf^^&@=b%uO!FN8g=bPW_zqL+-^=vOZCpL$f)tF0cE+)!V-G)Ey!7&33oxm^ zh`|r4zPoFFkdvIui32arZO|=fHKa4N?B{;GF{E~P$3ce?+KqV+IMtDd1ZG-8&-4_n zFc%4);$1ny0U^3x?5{XQmaa^of_>nbUeoMrnU0I(@@zHpi75~aZv3SxLiUc_asnDu z=w7CizXkse`~Gg8UX~*{Iiq)Eulsc}-A=K4h5nTJ27Oyd1>oAR7|>3~_&!nPUYgi7 z{h8b5iE(*Pvn;^S&TpYkt9(`atIMT5ZAOXbWY7U8y#Q64!hsO_hYe6YJbFzlNnh=f z&c7h_<|_b#ItwG&{!)XzrENVa<3wYgvO`oPzwxt1aqc-38p}jHC8MsBweMkksBEg7 zm&+M5MAV^@2#Ayi-!zlTV84%kN1MTU&~YhuP!NAi)3U zl|S-lr;p+j92NHW#Zula&%b>`;h07&8QLizPjD;99;6{>kN%lb^dR=z>m#C+2{Zt* z9aE)0aQKw^COBMQ>N$F5hJSiyk2`HLaPM8A@QgcM5=a#03FL?9KX@Hlh8*Ju5n-^b zPqOqPDNvMxMPAthyH@u>1-orRhj1b|e3QpD@a=uS_fWHuE^)?h?*9?xK2Ny%8MC-p z7~w&j-ksi6`6xXiy%*}23@AM|U)`GVRANmn`)0jIe%$7;Mk*1$(lJ$9T_?W737@^% z3BSH{0KoHD%V)6m)w|hN&xbbOfC&!g5TxR(-RA`{x?@9ESsRhRwtS2pb9B0IJlj|M zE(&DYnSscJ%NTkTL8NI_7wv%6t)^oJaNO+vEf8<{kfaIJPM9l`zMMvc>gh|v*7>dy z@pMv}o}O@n;L5GRb=(BTux9hYAQQ$3(l_&AV9I*Kxx-k6k5j6hhv^KC^yc1d*EL%Z z@z>@M=&-0{$Ntfr3=(;NBm1zX4-p4d&Y0f~UKKy$Da)!ip@IqmimB&gxA}2fjCX&S zUny~LOFuQyu>C26n1l5UGw?&c`TgPkXloCFikpY_A;j&fKuo;V5X`)tPa>vgo9A#3 zP#BK=qw2bI&%TlSdZ{M~PNIMQWv@|R@Mx|=bN}t{M8?Mn&M?NwIDby`2VoBh@V0ke zv9V-5SmET!Wo5~w?*4Fb#_aQQa6OJO<#{%iWuUdf%q)Vm`ML2Lml)pdy?GJUeUydj z00g-YvtPd~uDPsjftEWqPG9K%x(HkY19O{vR(A3+nkhOYTk?(y9(yMXF+ESCu9s4O zU@Gjqnutb(yFOAbMG$3s-j$G;8no?pLH1UQ{pM%xnOs*R{v*Fhn6Wy zc&{=luEKzQV}6ZC6Vm=P9)3dduLL8CjEZ% zc+5Zd`Fg+3`=0ZDoO|wh+{gLx|NU$NYol}h+qJXR`tImIzjrqCcV z?T8IerFQ+~l-)}r*3ghka@I+`-b-KG)Mz36xl~b{ObWRT5brv4cL|ThAFSVk(8CHmP5hWfJkmsYP~*dM{)A97EmoHw^uR2(plH@obTx^>t%exkA|G{SpI zL(_Pd^iYkgc6c&KRVhY#U!Lh0*B4Vq*oS-&Khq>R6=Io2mtUi~dVkdNoIu!$PtdiZ z%SZ;#W}@vr|68V<9uGfmIlEGt;(o>Jet+lrSWlmXv>u{AM@MO8Nu?or4*xz}KUz*b zOr^2vINfjs}j^w<@CFal3U3e_G16 z6==$bhLYT){7a}j3dn$E8(7W?4_BTSEPdEqA0pZbC!UiO-J``BFDknVce?G;4wSV<& z*qnspqv?l-xu=~~XF5C6kxqQ=Ee9i|yDsjWaAP~^XKN8w_@ubLI%V+vqH$I-sor}3 ze!B1mkt|d|kbSqhKIsx~ zc1}Q<*JN`NS6uKe+mrZR5NXkKHU`?!x1&E5=D1-*TXdi!ekP7*Qk??p4!l!Tw=c>` z8y{pF-hL}^LNsGCOZe8*{FkQ@Wlshf8%7zLiuDYO-Y8`c=|4B&a9Z|x9%Gb=TgZQ* zV|p{nD9xdl);jMd+~r?%YJh$1*;ntHeA%OvD{{&%S>x`*HT+7N_kI zN3iy=BDe9|zC8GRZrz<99W6l-W8w`7uDxSQ+Cu0%Vl&n|Yt zJG`w-ic4@r%j{sSA{nEYfy}ak$w$q7!|EORtIsy~Od5>jCk>qTWp#Zq5x00nto`)O zs9WA07q8l>GG2G{B=j7&LDJ`S@*OXnj$eLrTV1NeO#I&gmB*PiQ6aZYB?3OxoU>Ei zoL2ZO^IY)mz^B=sfx~%Ho~`%IcK8vMEd2AJFjkCLDUEHKDG-zVT1;59c@sr86q7u;M}vpbzt1 z!~ko;;f{ZHu!|4;W23ac@>~eHT($Z^)rp69rW;C(77z1j7?W;9+$&7&0h?kO%tBcr z73#A3Rg$H3&}XE-bg-D!^(F{^x|!GhF{iTRZ<{&(UBtpyTE4>F3r6?3NBxFNf=ot4 zNqJI3y6YoK17}(*Ejwdh44PV zQaM|2g1_dDv`Ks52@eg_pz2;t0xR2@MkW+rZK8X3z{vCZ>PO9&O?Q;9E5n{9Mht(5`_BK)>c(gJ|~Sdh~xu_jUrMpm62tM!(T=D+l0x(E2x@vO7mte@AcbGSmO#Vs$d9se9^=}nOTGB>a^^WK`(=!=1D8Wox4B+E1icx`I@+$_n&pwN zAeQAE+;W3-$goA6bevb=dS=+DyjZ4lh5YplV%VA2VjZtvaURi+99TFOpFo-M?)%A(N z;k^y{(u4-&-YV}et}R8U_`4#!Jn7>c4EZ?LR_8uzQC9BKpVv5cKy-BT;N=pe^JCct zvR5EHkY9$^ZR>||fn){@{(?M)0VFO%JAW)Ee_fqhhIaqFN{zN!`OS}kauyeOx&mqb z_b@K11@J^*1cB}eGg7`xkT@;PtQL2U? zkS7s;$id_rtdSmD*PQwW;WoDQjG|%O$w0kh&{T!w{9Pl62x`5s52Nt=b%qOh7(V1s zDkC-YLeHQ2lb;@z7&9|{cgH0%(%uP(qsIs$-xW|fZ8w1x7$F?BKra%*14N%P(dG`s z;6X%eYWj|wS0TpK3N!~ziUi8ZWdD6*6oD82KYqoL=JV880p}y`a{uRPWz+&i!Y`Ph z7lGkN`ffvmY(KOB8}-fMKd+ZS7{aI_8`m)ig)lV3K>&M^a7W1RpoWWrsd*F)$AhOx zxFhZ>eYXeSkeJ_YSD69k>1Jr)8-x}F`#8}w9jS(_*uNg?gG19;6MzUK-1O?fb#BK< zYfS(bDcsF+oeS`yX)1sKHZj3m#(JF_F#R4MP2nGH)_ElpZ5DPU*`crw5bz- z7YgQ$PU}1u^}ByRg`?7Y&*6UMv>liS zjmv%K!#YOAb)kawJB| z0siC}B_b7p0bVluVhV6+8PZ~{o*jPBU1;#rR1CP{HL$WCh<@3A%j`wDIF4bwJ%~5w z%K?E&tg9sT)996#-)XSySsc?VGlr#UPH)%5^9Se6M0yRp(eV0Pdsi1w03mf>_@Yuo zCRg{Zm-NCveEG)v&ZTClua*@_$$2D%U2Ca8r#$z%Eb;B9-JswR!%icHI>vprx4}%m zIjvU`!M%l6BFdP9{qym4v{8LbpwPZdB?dm1nv6QWjY3b&*f~6idNJ$5{GfM9z{Pa1 zU^K$Y!yX+e4MN=HS9m6Vo_jtdyEvxFds8 zck*c)!}9JPoZe@|_nPYHFOl(5I*IBbq0t>*3E0q6$x7&Swy!FFxj@>;aaQI?a2(Is!W4&B6EnP&%Q?XGlvg%%pm3wz5i~Kq)*0E&YUdU^FSpmcUL&_gVy< zE-P+#f;bcW8v8xMc=Dw0!Sywbqgan};l zrQrrIG#{(Nyi(!$4B83hf&7aO(UZ$(_$K3K!+n_88)uKM+!yK#pAIQ3OpSE3!3t$L zxM7A3tl`MKexB0unW*W{63U`Jrjp+~l)4SQHL5y9*k1;*HdOOO>jz|~#-2Y$eDz4> z2zz-}s$BXvIojL}WMv!SI3`?v&(T1_UO&{qSR5>IlphvuLT7?aPQqnBd{bl*;^xDg z*5-I@(z|ZGxK52052~Q-BEP|USoak)6i99ZT%&fjuvB2uv~^lRe@ z9TT$kOfK))8}TL%Q$rt@t(ZD!HzN839>x7~l9lc4xEH_@{*vBj)m^80kM#I4me4Q0 zwBwggB$Znq)XTgiB1WKAj|(cQVagSJL>P)HI&2YyKC5=YY>4x%=Yp`;C5F@5I%06+ z>pV#@OZ!E$t29cYa(_7ScB%f#UB^}vwVMa_|5)}Ze>?NNxri$)OPGsKR>5oVuEKmO zJS%)rOE~#=3->WK?dGQJ>XF&UwU>v{H7lz%ykDJvzBBaKIDA-^Q0pO7p5{K-I@mM+ ztMqqO)rZN|>Y4GuJd@@_Lk*_yRwrQBvU=om@(+gvpYRLK9}|MZ;_Iq%;%~S1T~kbR zZGgq;46T_N^1$Nc>^en}S4D3OO;MX8e{*u;smo=}Wj1EV6%H$tKtH?%&*l{)sRx}$J z0zA4R&Rjf)ENl<*oVpyS#N&TQ^*~Hz18dTv)w01gD|r>Rg4kXMCaXdY{12-aN$Ss+ z<^(;u92h*s`q}X7cq3KJ_2V>Jz@#x7lSAZzDM$gx*Z#Gre6a5OL_#@2T;BQhvOV z7Mfxf9#5?A3>H~>gUz$cap%rEmBQbs_RHI;NwuEUsag5c(=$!De$zAhxRymnJ#2lv zqmk0MjH9mN_YV&G3WOGK2VME^tPXmm)oI3A+|235!rY^!n0k&?8Hua)#aXL&5)wg9*)G=UIV-0eSvN_*(^pi7tb*$9#hTdRy2wTGQA``9AN>vL@ zk)PZ&#YewR7x;0N3H*av7tVYU9A8GCuOuv|bnN1-aI?U$=>aTZ%;(1=^|Opc-K!O0 z3%CgLX0$nWu6UzbyZ*?75Iw=NtN(tz8pQoOMA*?Q7owA@~5+u6bedSOwTJH5EbTOhC>i#oD%4@3%q1|!r_{GdG!I%&2b z_U;UZ0n2eH9_j{3&;bV-e#N2KD6yC_gmvGMF#>c|M(v@rc?j9SXI!bkg-3L}VDJBM zRuzapM^lqH8njQPW~cNICvorle|fFS?i|)hyngNv=LJ37;k){GI|A{SZt%_i&rHL2 z#UCW`J2ij#5mg$BDZs%23z|*Wl20_dTTAL%A}RlAku%6M9|l#l|M0L{s+;3I6O2;_PyW` zWCvctqbQ~a4L-u7_^B1xH}N!{a$%rB{$mjK=iJ0L$98)slJF?kCcbY8P?QA?0-6xc z=h?((t$O*39ATf;#E62L>^!N8}~K9y0r`5{2{rg3ta}KVE{N^2khUO5e9_oL1o5AfC74` z1C+#-L;|A01w9ly*z}IFMi}rD3HO5}OtH!_pr$@VCh|ZBeUuPo$j1VTz$+z#k++#ZDr8prsj-kut8cA%v5-z+l7O zmvJ|Vbn%b~A1HAONwG{Ypn(yDv3w+q24k&v$1Nw}Tz(Q}2Ql_YTJVbzWxX)qL1W0K z9YeO^rc5oFguC{UF%8&ijG{=N3tTfs?W0yZ0P>rlIClQldj38E*m@#R8m#dZ`TuwxV4_b;NAkr&?;*yJq}fj`hZh?}3DjRiyc6QG$uKS^1w>JMRwh&-{NJ zWkIRm8lAxJiORJ;FE>i?}4FP)A02G5!57B~U}!Cja$>>xMM#`b#ceQ2MTaY5f+;`(NvZNzegt zf3-6jn3Bl9l+gquO#Qco-E|n7LexAl6t(|#`hN+z2n>uo8I={B5CECD+c_~gxtRS> zK?H+A*<3UJ-)-=}0df8b4+ai-1OW#2e-3AvveA^1j)f05^h`4N7Skh_&Fv&eIbD&^ z*vTp2&^vzkzI{xbaLU$x1^v_A**AnY>8THwWtHcoHJ+;#C+5)yv#@__*Fz)AM>f zIqmj*d!9f3cwJS~10J@^nY%vT)4M;m{E59Ex3`0@FO%&)UcsBabFe#}FFwwQ-#wpS z%bB~M*1u$56#*aj<=t=iN4wb`79ZNPk9_CbJI9Iuao2Op-aCt#zaC=t2hMYT!$D$8 zLECjAcd_8gtPS}gjLz;PHZb0pr`+I_Rw;Pvt?4CLP@#9~jC?jHJN;3td()?0oOaU3 zy1)a>|E_itBnp$v;K=@tdz#zepjjx;Aj+;yydMpC-uW(E+^K2KT4*D zy`X9^YmG+#T=UZYUad|zikE>{5%+bAnzmYpvlw|1v?4vhG3 z-LujP4w}NSDCWOspNYsi%LFG$;Il8x9Z=fD*z(P|6}~FnrDTkXDjut-dJXHeYwmIu zS|)$L`rYJYs?p%5^KqYF`+)3xWNCxkc>2(szi8?8@YW1GEiSSy=Z&1}z1rS*^AZ8T zP4Q&c%TB#r_glmdUWKz3on(rvpHuMzOraJ|umEslo`@SAg zMWMG&mOKLH#D{+j9%n8TeLY1*>S2n zaSBL|Y6d-0XMUg1)OBF$!_$1P(m4j)txvUu))7D6un%sSyWd{R=|@R%#~da7Cj~t@ zvy2Be_cnl!VE5)Usf0NX!QyWx{`c5lKZdfB5_i4?C);Jbp;OONdwz)6v}F$+1v_0h zygpHCJ9REc{3d_x^S-=0__^;)p-4@iJw*J@ouzsd%-r?*euuwsXe+Uj{2LmmxQpp0 zmXtp5&r!5ewR4(xo9ULlF5|pVa~nP^{H}{6h1fAZE3-n`R6RC8>XAoDG{Y}6%}azP zAuE?0J+RYblNU>+jlIa3RehS2IpS!E={+7Nb$;cU*)(P!rrWXopuURtybk;nZ+k?WJpu?h=On%Cvsx~Tn0V#_YsmTm^9gKf(CUmiqx!CEXNlLanUJr#_$Ic zE1MYvO3p#_N~aekj(163 zbt7pec~G^#ifQNz3J8FeP=9R`oDzK?rb%%tY2oGg z)~TC+mr`76bJFV75S>s}+{-IK#Co926X#CYk;VekziT)>;9i(}7ehAdG!w7@->O&U zf_0Alz(B|fce3x0B3L~Ts};RC{v(5SaNlkC=hiiU$9QlAbP_-rTG+`Tn1@j8;emt* z-#KDm-1Ic%lJ3R9bec=_Ok?2L6SNZ4`({FnYx6}?&I~D(MDx$!C6D{-8?2jY+95LS zy+fhmM$*BH4GLkLEBQv&z#L5YCmkn(pYo1rt-FlT9QE7BdCGQZZ>H~}8M!ib zOm0QHAIv#M(ZT_X%9Tp!feb<`vGT;R2%c&juc&2XLK)Us&7HHb`=q7`MGvS__E!C? zjjCGtlq}MrP6bTAPGSHm66PLF4mCB2+sS`)_I^ z%`ct}b}t2|`qHr4LEHw6atd&h_tMzJ)%-$fDeR_diS#U(_i|#s^+`o@IjzG>(qj z8f>S3*Vh5Ctu2D0KaU$>ha}zMo9T6;Fh7$*2_?B$LpcZRq>_%+V@OHhoIce=-y&L> zF}`yze)c#z;P5*xPf0}2irLzorf6ZuB|?m;`Enjn5g2NUUrwE_&dY0e4VATO(h92Z zdZ)9RP5-F6Gb8G$7xHW{p5h~1ur1H|SXDay2G53AG8wM*oi%RrO#iR+LRxNpW;bPLUhUgN? z`8Nm*NP4PV;XSN+2xiG;rlB&!aLoptM(`22zWA2%3{Q+`Brh19(ke}9 zELKs)-a(d#*u3}qvfk!Nn~^P8xA~dds+RM&b!5R0o?dzRe2IDl3q0JPcu^6ZzBO&e z^7q_^#Cu)3Q+;T1MP{eT?h*2nIo}_pX!=C~zg$DBA62`^#9)_pSO98bwVAGDdCMRA-tnED~hW5QwHNAlf@iqgW9?>Dw)+`wY}M56^Q zU^L4{BQJ|^#WhIv-9m~4yS5`^4ZYXjxqm5`%hK^#(itRDRFtuZG-^c~W&{R7D7c-z zH;vSkcX~yT$ksowY*|ROBYGS?%?h+Kp2knRKmL^4bv^!> z57m2}UDWgbSP!m#e`{ade6O|>e0jb5czn+8B1aLMqv__Ao&XW_yyeY2e^)O}a6>6R}1kSV<#Ef|9dK@9eNGLZDKqnPl5RM#%7m4^XaDMUezZ4DI%G9|jW zNl2=8wHH#EAqjGlCsd}|s-%at$>yGwgN}v#Ms7cr!m=5nB=NI*x@SMgg!^4br%f1J zAp2S{Mxu>+x!q<(gJ>Eat#U!lCxODX_;I{4k1R0XT z3Y#EBWh|Dk5j?z;!W)xol+Jy?d*7iJE^xP2b)$MYmrH3ru$Aoh$2VBKIZ=+f0M@Ui zQWo_h34>MZskkkwhsu!T#}5O>H{BWNSoQDIcfN?g;h|AiWadQ4p(30(%>NKSQt9djY4KaQ3)OlSI!+n!kH^FM_wmLhwn&N;@3Q!jzK10yCKh1>2lD9=} zt1yAC<~;I@sK@nAk%L+c?@+q2E_#d|*1=MkpPq_}ceaDTU*!(I5w8MBtb zpAE(t9{eY6)mW7RojiAjW!s8#4lI`qMTvsb3+-D*0I(W=bv%?MOsng|Wh6*xGt+n2 zC{iRJO;6Yy{kCW-aOCw-QoLF$MEHIc{rXUa+~Az z=ixK7L*Petu?9-`C2f@-fzd=Nkr1U3NX|ZKFEUKwWfHmL93EuG?NW5TfBw7-Las(; z39t}m8-7LwMXv7OWw@v~dJ&)Pqa)CY_^>=_oUBHB>=ItGilfucTB=($3Q0s=qa~*^Fncau#+d$;lQUm{HZ)t3Y zD(@V&?W8>tn)P0Cyj$O$Svb9)=IruW#aMF(mwjdSPIOB+f@zbx**`X zjJ@$c;R*3$LRB=X{?f+^XS8#^)6;~D1&*LG4hnk&A;89w@;>@QEtj(Lu zV9^`>k^7W*Rx+`nki%j4$(-y*&u9813J!3)%J^3-sb6KVzP{UT7^8L41Rf1FDX|*! zq!v1o#?YBjw3>N!^6-(Nb-FB`NcF1q`VDeX>nvYF;XJ;q!?vRZZMG+(UIW)P20pd_&LG|p4ZAuR(-Q5%C^@ebz6__%NI_kNtKlJ0w z-K00yE)e+!!!S>4^Na$?WA@X9iEY?x#^6=C$>GZT-jdr-bsbVwiZt9*JKRHS;e(R- zwO~f~22d8`qE+OA`KRKDMTl3iKn3aD$wqx~i%Uv=t|UYKX=zA?#_l8Z!0d5K)qt-v z8kMz(GmhY$y_U(H9s&_rT%;F&`0>DO4U5BJoQUlAGMH3~AjB7N^`P-*tk0>p0(91n zTuGA(=VP3!BU=>=6AQmi6$Kd_C&pg)$haA<6B-xN*ggDP?hRtS5ZW~fd)~%Lt*mkz zkkvL16bQ1+w89J3Y`C`|0jxi`D%3OZd{DFBZg4Y@IE0i#BTBV832@=T<*?~=Z{(7K z#<_@gjWU+5T4*m{8lb-Y0b4269-#YKg9|3CbR1Cbq%A2+Iy$|@J?^C5U~aiV=xv9% z(P|ri9kFvX{O+qpe9jqX?qi5w+`jxym&euj-^+uI)CvThh`R+e8xYL2S3|(`W#TJ2 z(*Zg25y_%beWVpuM_=a{Kj)1W5w~uRjNxE8HG7PSD@^qCnDFw9BUpA9M}A|Pt0!88 z`ucYKF$ak%^6rupp`GxJlUEDtdGZyR!$N&zLF(7F<$G$rMvH>-hR&#wmYF8*XhuP= zObd-9pU|e_dWjC33EZr!8u~oHP-9x%$0!1El^ciSztAe7>+4soHR~I zE7lqH{^sl?OU?>oIlKd}qNzPeFXoCP**9Wp?gt`0(OO#K5o>3+s+nBNdyDmYPDHxr z$$``RIHl`qS2j4LUlGu-g3oDjiW{~}QYjT+qEP~PNwDbAo3R9s z`aqI$D40;3_M^$&K?U>&v6sR!RHz{()zDYcgxbTuRPVpiSFk9;yc*h}08D0SRc;3c*e9I1(=3b%hz>!g%5# zyJk|r^K~o~PVNq)QGSnVas7hBPeB@A7N2E9M4BC##2c@%JqPZcTvveEL(2x+)){Ip z6z~_Z_)+Bx1TJJKo1$)2rU9V=& z?yxL&Ab(_lye61p8jTaJHj3&YnqW7qWG7>BQ)0<3g(6n(&MvaVessAv)|q0q(fW(> z3{)B{?@Z2+o>>BvE}8BDm^g{U#aQ4-e<+(U)rJ7CX~AQy!%NMWuxavq*zLatR-;BN!fa6ld`cAR)nCoPPH8V}YR!7Y@AbHfAS4uw(&j z)z3hpt83^PQy^#vJ=@t9_e;>CM>u%CBEEY91Y*8Sd8DZmI*-qJBS}ANKb-E8H6JWV z)I_eRZLr0!(skc7lN^O`VWj)H#9C5vHHcOTXM2NMyU1%OKR7XmQ$cL&cSQCM`tD9r z;4BhTp%Ez5_0WXV%mxcNTxVfaUF~F zOtPRA68YpM?(1uvp+Gk*WyWH7JQo@XZNC|anE+{Ov|6ih>p3Nip-XV-d3{F?;6B=k z0oB4Ok<0o5AR&?2+HmEhETPI5Z5kyXUw@dJP5j>)d0tE6&z z{>XyVLF3}gra-mTW<-5m_ zzNlgaW@3alTro-go--cMq z&YVV>*L7nI`Q=BmAn)j$&UGj}a#r+BebWCEX=y^9*56yoJE|bS0M8>TPiSbI?nD{+WlP9p|;dXxth&hY!wb5BiF1O_LYFy+;!M)@7)qp>Ek8lKwD_J9!m z%e;t+cuMUF$9@yX*OfWoQXC!1H$*mFoZZ|pI6?o@eKAwMxdY9)&5MotG~BqBA;>(x zFHnT&1wj@O($DL#xHrDpiJ%b_leAN#5j}X30V%i<@d+73P$Zt(q=cYFd^Qw;* zgo{OdhP>SE!mmu7s-uF_VpYtq@xsQSh!~K;L$L{*e+MXZY>(VEhl$yqOSe6_u4xof z$!|p%m~$r`7z_pSV+i7uz|`2|?&LmIrod2MU$TgJDV;4QDT28qothS|Ofpco2b}OI8F-J^N{wi7xtVH&f>$hZbJ-y6|gZHl*M++{VfPc*R6R$93 z83KL#yB`(&=2L$XO@%5hCWzE5PM%!ZSwP%EpnY~U6$2j7PYg%`eTJTNticO{n8J0z*9l2iY%scaQzJcR zlz!=L4@;9}o$!ki%R3|dTFDSsdCKB@&4g%K*H6}XD+Yg} zbXjAjWGq9VBi{Y+9hNpcNX^*`I@*wZ%WX~yi^3Wy^jO4nok3AJcXiF>$xad|m|ZvR zN~R%`wu(A$LF+rD_OO5p`&|)Rf}GlIy?^!FB2luJpT?aZr5{1-$Aq~x8abM>3QEQ^ zgYr=5RSs)=jNl8e;oVmvkXz*uX%0HfV0)zbF^d||Z~R-ZS^&-17Ji!bWyK9IWWn%N zY@4O8V=kvk(RJ2CaaqhlgizH-3@LN=sD{;BH96CCP=p`si&foj*!PhQbE@n(`WbEd z80NYlUw2XevUdGXu2xc5olh~#khT0v7FtUqaPAP1)Of!F9S5Z0rdZ;>NluM~d`|v@=E040SOp?%cnEZVN9C+ejng!w z*0oZDmw{-sSKSZEvqUV(wuSbC*NMPvz$~Hc%N2&#R55Gndh&)ehwhXxrp6UX0!t;H zjm_926BV`%u&s+nfkVi}kd(kGAUX))5E-NbEJ?4T9B5bgSOkk2TOe8Mk8wFHovU)% zRc~A_vbm+vrvaewCycP8nrpnNDSTZ%G}9d6y4Ke+Em;KJ?^?pOQsI=F4Vh^HjtRaj zt5xoU-*dE$aGFXPo8$M)HJs+_GjWpm+v|nDR%M4YDU;`K_s9kTgG4^u8izBTPKMk7 z0ah}9!?wEu*5W*w&kC9|q;Q6mUn&ukW%a6)0%j;r24~|yOFOrHRtc|kr9V%d9!KR5 zq`KmaWYvy7Jkw4v#~Se^ZXr#^o!$!5!A@QXrC+&4xRIMoX^;)n$ll@BqS2r25x&-` znVMx%)qH-$13~*R5xtbK+v+{-FTC{wccxGKpPjxoc;i% zaSh&AB_1v|D`m;@Ig^xs;s4OLM6q+rH%r<>@gDj~b-`~OBBa#AA1UjFFtG(0F{?J$ zo^AQSuhd__M5k%L6~3%)2UM6ObNQAuAbdmmT>i)Zy9C_wJVTk|FrM@YybV7Xj;5lD zd|>H5N$jpQ>;^>E#LVw~W1l#4V2x|GG|)&T9{qww&d6jx9Aed|gofU+6U@~nxemF{ z05912&+W*Df^xEPtA%DZTHqy!klxJ^;C2hA>M+a&3fl4TeH!la?1J&q9ye@Vqa>v0Vy+&0^Fy8 zX=2pNzA{RL-@j0g>O5=pJZX*hllKt~f=9>ufXI&Qm%@%CjHI1fmEcPc^I^Hu9n+Rcgl zH@O_s2ZGIz_#e@0mnS+&0Q7vnsK$F0(oko7{i!=O`V6F^nC>pI%t?e*0)-)ir0be) zpH3v#<1BEmb=!{(=%=#QK5vV}bjBgARm#Hd_}_z0Q9JN6r2_oZ9b0t7Ppy(Md<Nkh{jaxdT@uOBdH0eH0|;5E*-Hq%=b)tcG$@90+y@xUlqoC?}(H& zi4+s_wcL%HLxkOxYNf%URxL+WD5PSkD!g;X(oRG3`i! zKL?c7*ksTR_rf^j^rkuaF!Nbc0x^$S+^=qZ)!h|@3-bHQ-WR{~7qs0PG~LSh>5et3 zf34`fxg2=&IeqA5w-Pg={1*B~5?}$BKC4g1sK)hh5>{th4YaiyeN~B3W|^x7rHjnU zjEuP~!TJt4Mq>#XS|g=ueKDxg!HdFDw)sP;!2wD<5m-?-NsZd-l8Y}w;&lX3q=-Wd z-|H`4>f6D59N#ece>?_f`%-wN1~@kghkv5A&vb2Y$ao|zFEYP~IkWA_poqp#J!yi! zZkxa>N~1qt1Kg`(k3#Ncei9Z(!R=KLwT!#C*eCVuPp^?Dz;1v>`5krZyw|bO(K_y0 z+b`Q;7~%Bsaao;E@W>~Rb7Q9en6>GD;;^@)y5brsMS*Ylz%NSPOeD`=CM$BM7*Yyt zkno!|$ok%FzqJ0k=i%DSo;GoTwvc;+fg>bC_~g{?01Om+?=z7?(#1L#v?ht+>CLuv=f%A@ux&Ho z`eY#ZQQ%Mk9o>hkkZq22r|1ALF+f-f9aqAZSz(25FzDrE1qF}QTuWtG+XKEz655ctI-#XR(@mrGM98bPSrI?(bh{*sDN zEq9dZYv?*J!e=l?iFL*XQs=$3hR;R54VsB#UO=}rm28R^9Z7%w- zrJ%}V5xbg{%84Fv;|l=KoV9ktbvTs{MwN3)NXrQ)rCHQhx0lld`UYV%B6^KG;`G>p z2I$3Xh2lxnfZxs(j84gO||-AL|^WqmDp@V>KH% zG%HAbJ%mZH#V4_`Pdl7#j1ZU`nJW4!BQbr25wy@*~_E! zMP^5$VT}?JW2>jUUn&{@>AwZ;;a|0Zm`6x)DeHH&bH9CW%d3hRo48V;%>nKc3(;MW znhT#IGjYxf_v~T&l2Yl0H^Qc0OU|fG5jeIx!Xv7JN~i)KuEW$C!e}K_l))*9Kqz%z zzGIuFtps~zmrb;`=SveWTn1FzNYUq5=VlG!b6z;V<+_rV*bB_``AGU`!R+CxKlMg< ze=xZXM%fP075WioG4ZGh<$$zBH#Xx$^+d}OOJ&WUe6gZt?&kS9nAQ{2P-x?b5FyMv zojDd2HF4=3t}LOaEa}W?U-u2>v|u=0Np$14GnjH*CEOpq@eD$0h0|NOAdjO{LT6%+ z3D!Wv3^GP71nRmFbRG?TC+%*(K)Ju|Ma?1@c8hstGq#PelPFdtqJTNagZ0^5NYDBp zHlj|+vA2+T_J=or)4Xwc5&7$%9Q|}%0%e0m^vb#A4)?*MvFY^V;Z8+~x`;UKOcL@{ z3&N1!y+zP46U?1lCsA-C6TmwaBsp~Qp8F)w$ow~F2N)&4qH1cnHo=XE?0Xj@6y5AF zAt1qRTFxP=?Lm$k3IH8DJLpG0^6BtKAUkFMP%wG6hhqr`koUN?Ss8|je8b8aO_I4< zu{+|!f<Wk3jYG#S@pBmbY!~`wkDQ8;ON)GB;Xj9aCWs z?{}n4+Gs_=EDvstf@am(`L4_3rT=NEX7-2ao8c|CloEMMTE}2LI&DtG6|rA zDg7kD?+LQlfY+(w7D*C2L(pz+wr@+$-M3D!4dp1oZ$J2~UJkh=u3GkzAb0rZ0M~xN z&_H7<710~4S0T$MdG?Cj62x~&2V?j{3b~>c7BP zJ5xTNtX;H4B0K+%+}XOI6(?eYXBo_}$2(`hw1#Hh z7p%XIl8}+Wf=rlMFE|j)@f%+3(ec`+sj_L3HW{RjKZ8K}_A$3DDdG;Z$XaT_CNDtq}2aSsjJrz<>`IeS=G%ma_iZl`803RqR4lwccum{vUr#@~ z_!y$gDFdoGxQJlh!w%)fDYLjLmH6QWG>f2{B69OZvKoo5bKaJl8V34z4@<)ouew4% zYxGE8li3VUlxs5lAQ}8b&&#K1j7uXqYu1x>5jQ}O8qt%|3oTul9)lZPvUph7YR?ka z8opoYT+B~)YU!@%I2mzAHtQEP$N21s(8VTK9$(Vk+(&Ks{QRQrh*|%Jqky@i|L1%L z3;g=sX8))yNs^0D@=q3;=Lu-?Bd%u8^S#~*Qn=nbZO&J$H69k_IA}2nFk=&y8cI*ds zY8*WzfCY54>+JrSc%c#Oy6b5gBmAT%$q_L9>50GPFy%=-e3snqjH#ZI_i+Mi{0ow+ zp)KO%Tjth-_6lcfI$+{ZgAs64LP`3%F6yce$bDS#~#pOscYthVsqgAH> z5t&oA{c%YUD07wzMODUP@(gOeK>vG_}5JL!DAT z7XFdILa%BMheVt}-y^JrHymG}fGI_f@!A&W_qB+p1YVRmBzv#!4ryDvy!1o7huf2B z-NerF6-5ZB{|~{~SEY%VD_dC97Bzrt1jcr$*pV>8NRnqS2ixK~U>m}I=lWbNkcgC3k+$V>fOz--H%%~}^6!aT-^LAve+GHH$ z(|d3Yxi2MT3@b|(x#Z~4_%E<#R`xI=kpJVl3ReMEkAw|F$1o(mO!yq(;k^e>bfuLC zXPf<#>hd^#j5IE8XpBarL?n6hQlo0oM_9^HPzYsph+y#Wc06MG{d7$Rl31%zF+Inew?VrU7wM{X<_t zLoO#_RhF$hOK3Vhujo#Bp`0H?d}$)QpPLENQJycomJzkmoR)bSkW40Uc;;wd_`*5k zA~8(CE}gf+v#c0_-+9M$VWABkrSa*cDe~~#Wo6;`QwY?|rENu^uGTJ(03vl|xu2a9 z0M`YC&9O|sf3M2-xXuzytdCj9;M$huF?&VK=**ho^{%euL2{y>O3`OTj_ks4N%8pRjBz99FqWsjwwj!uan^6Tz=v9=LWb{-eB6#jXU$S_-vy^wghgdu^%lo{ zisM&1lCzWnRvOzoH?gipwEObxWy%P2A$>XytFeQsTzHf7?><)^!rY0E|}(f zCLVMW#NU~C3-@cV&{sPhRhBY{Z;i-?2P=FsGLwr3waQicU?u`bXI}>T~^^=OF zD9@Ak=5|f&3(-!#-=zCQtB9m5UH0SY-SKVi#|E6O4BW4-lLByV+@z`jFoWXm%jHa2 z^{9SkCnin~Gj-C&5PCF8OVyxpkgK=X<3p7gd3ti*NzA@fz>4yqZ9fZ{4N}!{$RNTH zEcko}pgo$47bHYj3K9}ln$lBt4~?uE&?0sgOkeEu#b)*v&C)KM1oSp7gp4JA z+^wW>2JvR)h_p5ysk+B1ltcD*QW{z*^rwrA= zq^EY^+r-e16(e`;fkUfT-FD8km?74L!Vv_(!f96Em;d`3LMFvgt7sa-jAAGa-8+Q~ zD0TX-Kn&*AVzLH0lJJz7S7MBt2R!=iTr60tgmekD)-7q_$4dNAia>07F-&#V4i=%4~#GHbM&AJ;O6))^?G5da)4+~E5GmkumAC9O1qI@Cy zJIkkdMeK-R?qc<5wK84;ufiY*8ItVu^q6+eqjyjA$zm~&?uU$eN#$RTqxQLO(Zx5Y zr3Z8A7yU+j(q}kSV`h__64TSGLy-)MUP6f_dYe~v{&}){;m7?woB&>Gs-T`fw!t#? z*3I>X9>?xWnCEnb&`X|1>7)?g!K(Y#Bz@5)Efl88WG6xY0-;d+HeCeI(?wY5`}H|t zJvm~l_xLJb!2$4mKOTSyJLfPJI8!9!X#rq$~i6l$Z4nt;M9E&D*Ffru>vPts$`XJ8DrEH#17oUhJOV z3d4ex7vTs!@NmkT?fgKXoet@*n|kD3f-?=b-)$c(6Lt)j9|2JJ52_nAJUU06nuC%)u;p%1e;)QU*kcK4P>Tz`OVfUk0eq&r4!FFu9eEmjU@9LiD z6S*MrmO~yz-cajXv`>~B?zdYB=JrtIhT!$ZOXdS2Vg(D18vY?y@2Iorm)VtGy89B% zhTx_PZybND$cc61?7^vVLWpXkmn){d3-$+ZoGE<#>{LGDlD%;gpgH7VEP`H$sDpiT z>FV_j@d31sJ`R}1jpQC0gPpZ5+EnL*mABPf*5Osr*VN$P4x%KPll)PK0VC>WR6lo! z5W?c~jK%~jS7aw1JYj;5@}vSdM&-rTIIuaHE{7)}M?@%e#bWrO{c7rF&43L&znuTw%J+vnT*6bb6 zS7@A8!hoOqVFE%hHM~#(db==5?G+?Jn2 z;1ve`J^W`F5}XH}vS0QawBW(<7qal_?Jwl+eUiu7oUxy|c3?H6p8>4vP9$VH%XmUx1quML4Gwy;hWNJ7oMiewaw1SC9)oMB6}stA)hw5OkHD1OyeHb=4n| zAeUB-JvDKh$yW&E@F5cCJ)h2K7_PQ`6 zjh8c6Ln}Eh*}L5HP+};_DQc^5d(`?=1kJzP0XKhg=T@hlI&5q zz`Pm6?z3ov@kEFG)j8|@DyDSN7XI$DF0t9l8>2eK=n4pcZ7L< zGsRcoTu3ZXGW=dkDI%rH=GJF=J>FCR?7MU2s#ljw8>sXkuF879g_w>|g%$nRa;-t%B!7@#evT%;BRT^0TglUJ04ydQlyepn(OH>IHC^~M>z2Z)+bLLNc*Dub8!WE|cgli?P z$gl$CPg}qYRpS2S{Rkf4sOVV$A`j0>x)T2gz-G<9-(bz&$fuMB7UBY;grixrJs0El znls<4SB{Ah&l-p=0;U<4jzj$}ZAA8`GHf0Sw#=HHd-so%)4ScK0k0kTjd{#sIlENj zkFZIz%UlK}$oES`U49F9Jll&&mdnT){=5-FOgm3dDl<;YM@6`L9z;Yr!@8|s!y>QI zd~{--X%LyobK;9f>$;v7Xxq!(-SczEt7G*s%~t*)KPp!kpN?=ars#B@2ObB$mIrT@ zhznCsWl;9IqOe&LK%+^{vVC~{4A#^Vdh$62Qm>iZe!A(yipncUQf*&EvXb z7x@_9X0lqLkAUGLW!apBim8GJt{H-qkIlVluZu&%ksWv)q;ZJQbn-gyK}y|Qsjj(= zt4D00yz$`n7^YOr!Mls6ZthDy2IXf_xB-9-hZF`5kES-6&_(JvA!*o@N9bg=^YHiFk(s9N(Om= zTS0Uq4m!K{O_!hrvfo@C5+;wM0uXH&%6$PtCsfx#VS18JQPb0WQ`5U&QYQj--{cEU zzobb32}0Zfe4qOEUj~;TM)^R5=qzg!EIo+wozPOIPntS~n3#8EX| zTko%3lq|#x?6K>+|2E}5jl239v$$9o;eI-~J-My)R(wEwE6^+MSA1x?yfNdhz?@w2 z$$X1=zsY8eP$YPvWvZ~cN_c}6I(@MddUh4$NJ9FRzg25xoBPHs5GBAHah!GawMAR{)qUCXnJG;#3>aQE&r9x#v=xBoUFc0 z5Kq~lgbCz!s4J76ta`Z0$#ebY*^VO7RAQ>Gu28+e@{Pe&>^S<6M$`TP6Z$dYSMwoY z(t6#w-B_8IQ?iYl=@gda`p#^}HA?_Ne`64IP*}We|6ooEfwZ@tbx_@lfQ=$+%=Z&c z1uy(D)2b)FobnSSQ}_E$)5Df1&)yK9V#2_tUP^*t+haNr2kR+Dz`I=2+x^|)<}N(t z7jByS;GdWIqGBzEVCHSS;?dn(+y}dW{7}qq71!-M_Vt{X3tb6tV!gA^yA65*hqL7x zd#``S)8CJ=htQA5__Cwk3A%}a*WI)7^+oG}awiWiD@!glxBK%`X7A_yt1gs?8Jjq}K^!%P$hAkb}y{pxvP)n#=PwA8+S@=X87h5t&we|Ce{ z%1$m?BUzhxQ_fM|efM}iy8Cg&^+NJDbh({pBjK=6=X>&nFoI0?n<5f3I6}xStB(WW z9{J_oPoh8;=k6?GZQ`NH7er#u2V(cl4=5#B7+7LFJ-$kT|7|pncSy!b*7k>``MWti z+#iHjpgNLW3DzgkKv>B0)1#pIH5BzF ziX@|>%(5b1*`qEQNs*##C9+qN6(zrW`PLWR-~IFRdVXH-&${Q_&*O0)ui~;t^JO0~ z!5f>a3!Hrhnr+pe>H{(776pz=TnYH0^wfGt_LqoaDb2?BQH%0VdLN`1P`chG<+m`M zvcEEtKi{M)ui9Rj41Ru*gH&&^p};!LS?n6dTYT6vdqQ||M#Qz4*qh>WGdd!z{2s;X z(wp_Q?0I!)!lqmt$6M|RmgBx0Z>h~xEF4`R=aYzIv z)p4sTv?Gx7-lRB<-tk)Zd>~F`RFVu<%m&wVYF2m zX6j+@^)o;1-bHi8RJY58jFn|_Mz|VbtX;iN7^z0KW>nurpiU=qpiJrGIwd-~rg*HO z;G+pA+6PiCj;UWq^x`(CZ=I{Lj4Y-1Er2oCEs%wk`z6&F%_3`WX+{niJS6S4s9`Do zcp=+N%k`9P#FdK`pT2a@8b165YcO+Lqr#L--Y^W;FvL>!wXf3V`5=_73=J++6wL7D z)WtaXf%7L-iYrpp3u`l`7Wg~2bm6|SE^9^!nO%wnMCuNd#cs#QKH4e9l_!r&qpeKN zt-idZeo3*)GWFc_GV~kxOP87?WO3_C35}G*bkN8<_x0`ucr8GFOvp;hjT#zsbQAMH z_(A={iw0}FPkfrWZi`k|2{<-+3l_{4sjTKdImcUae_1zx*myua^38aX^mIzN|5`up zuhV0l1NQO?6!KaonO+{U*yavK?y7khZHAYBTZ#Y4;TwFBmu7*?E-}xZQll^?1(7fY z3?QASt-JE3(bc1_1)(k2TulBZ5H*15GM@Ud!5I|WHkCbAs?`!;-~TjV>h=;D+j2eS z-M8zmMY&-iv5KbpYJIm#Ddkv`FUGQ3{3BK;P1QXxIB-)Bou{6_c`BZ4ivJFRRmRUs z!zOV|fH&7lTqW)8S^9nrba0AV-bbCe2Oc9vUM^<&!B?3F*Sd~p$jD{A&>U0az)ahh zdnK2O6(gb|%10850!e*MVbH=gQ_gDRDWCauhY^iNs#jv^ z72-nqROyjPZ0!tCEv>XiiM1jdpD|ZAb05@pHKEgTj)aUy6_cGfttM(v@v;cPU?2n7 z+nH;3yx%$Nk%vxCs*OpDPr%dO8?YG#-n)8DwMuQx?K7V-*JX%ss}f}GK2?^tWXEM) zjVPPPqL`d-uo0jszgyter#H_44 zc>-JIQ>`YK!?5SAE^I=|X=iLLZTP#VlWyN<`Qn5U$)7l+8kNCB{IuWiXI+8}BQ#fC zqGCCi!G^W@(XiH*|A#d6M{u-w4*gM^CUX$ou>Ab)tZb}hROaP4b^A&!%u$vnHSBaI zpJ%(L$Go1GpnJOKnF`R!y?0j3`fBu%F1(*A;N@2~qjd^v=ioCLjCb=S9Hne|EMtWH zeYG8)o~~dn87+dkSXqs~>ZzN59GkYFpOamd*Vb}>Ban|KRCq+8bgs>Gjk8A}og@KX zP#Szq^oQ&SqjQIQcij!Yb z;4=6AMgsbHh)eWdG0SF7F-$?g{c}CcW6twPJlFCWrM3^AhT@y@ z_QS_OFiLUl|0bQH#MFJOpae-G{|L4J>}F*sc?~uo8^)`Q~{_ zc#_fUT*3IyVG@37&;;#-TKK;1F)20 zQ_sEHcEa5}CvXQmP?tuS^ zPi&iJ)V=&AuEsee7&YydcO~Sck!{P;&Fz<)w=EU1)<~?e8rE71YpsW{F~XiQ#aftS zt{b?%1KIC-Flml!%dE1NgJv(;9Hlx?pMwH}*rG?@@?F;7_c zJEeaZ>0>J)t>?H3jJB6GfgRf z2xixYB~-!-|Chh)!Y_toK{^xDmsAn_apcufR;|Yg*&Bhu(xwjUJ7ERH2RGhk?6;?he^M0VD zVM`34+h}|o%X~=lUf z6FUefDhUu`E=b}SOwg{4f!_gS zP!ixGS^-Dl05`}2Ct$!u%oGZG!2xjsKRIH1Onxd5G;vqN(f{VS?V(2$0X+iECJ2Jw zFAxN$Bd>I@`JobS$o~eV?N(z|KInK|88F(<{7^oyEIZL;|J@kz(PS7Tz>%nQ=rCw6 z50J9{-;A<7Q}jjxY{cgq!8j!DX|QihJImOImy?>oWhC(DCc3A$stQhaehJ#D0Q>}c z7vSYX?Vtn-U;+nK0EWL9E@G!Xyezg~2}J>1#9q^2777s9uk4I!9)&y7^m7y--9Hpu z1aw1Hoc>M^0K2FG2?BZ(UjJqUfJ<}$jDRkyhSOI~clvXHw9EkYeke-~H#`+{utANW z{ZVz?v=NqgnG-Zt$9*gRUf38sbN&pT;Q&K84_4Tj<~oicNwfw))G>es6xAST2|;~`c19cbTzDiFIlfHs;3b`OESh5vcSNJ1c#5FUK~-Oi^XZ1pSv n@wwpW;RtoT*XMIS=W}+>JMFA|e2N?i#dR=l(8Drr z@Is6z`2ie$;lLIy>pv}4Tu!S$Z}mjMSk1pcav)rl%jOUHs|mJjAV7Ws-@!wRAM}7G z40_PNFT^0p7D~M2bU^D*SVa%u0AmU@zDN$Hs1z8IV2Vph>dXmL^x&{8%rr)nCA>}< zutaIB8jTVe~HmJh;}O5Yv74{+NtKngEA{xH&vwlmXd<8k`| zqj5on-7sk}u58+$npH zzqu$RamAb5zl2M}n z6m2`LbwtI1!;NwsO5%F&DghY`!ZoPZiJU%p|5d_TD`%3>p001+u)gA6>hU^UAayc4 zIALzfOKqs2eLl8AP3p03c#R&>3TF~hE)(1NRWKf9^|De6|NP*tL`{h&Nn;0Jj_RAp zL@5u^Y@0Cpx`>{vAGGdqyR5xDM;2;Z$AQAaaV-tGF$7=NhG>4n-cayEl;AbB2F#UD zugy}H_|6}rImh1;3M)X1-kaehRD`F|4ovCaJ->Bkw+I$bNdeNjXpSbd3sOC zyUV+z9kKpqPl*%e);*4dsRN-;3|;q3QfA>-%agb>n-zWA(OjQvG3O61CGYWqg@*_R zr{wC53}7P?t|;pH^&Q)^bL3N++vjVwB1YVk-RtynjtmtZ%jQrDvF1?tA>?CzA?7Ie8vymk8cqhC-#(Zpf4z=y>7u^MM%5x*H7DW$j@&4m%#sXz&H{(M2aQ@H240`SBPGrW1YJGd`tVR=70tAK zHtl*o=1{$yNm<0Ro9*C0Hlb#Fgm5Nhi+}yJByqZ9>`U^CwyPgCM>;uTN|Tgl#(q#W zv<`>$rDPAtfWEb5=g0TVt!SB-Pp$2yW-}gz`5gYXSBjFZYs7&uE!WHYA$3w zfYfS>;XC7;c*T#e)^!F;F}SIY@OII@cGWj<&~xJYrEq-O(TXOmXwBC7diUN%L!CJv z<+h;Rno`KJNX6`t3~XmaXP2;=aQVh^mvvHv*?gFR_6O)q0StsfK3;0GRcAU%j%F7= z4Djt&cS?!)Iq_9l=fJH3QqA~r_sQgxygs#N?7PHS+wI|2E~Q&CVqMS5%szemV|_9n z@lry$wOJG|BU^l%N3ODD*cJbUyyFr7VX5`!(Ua88pR>;JC22btdYo;?pT<>i!$aybXbxJf_;)R0MVAiUs=`>c&1&Dye~ra8Y?H;@Cbc-loX;H1hj-Rj?BO2V zmP0wk=M`$w)hT_T^aBQu8Ta#&-bhhDgyL_t_l<VbyjQc+mM>j)^YVFLJ@`A3XHs^4zdz%Ju-UZ-I$4|t-FG-m zA^&RQMZ5O+bSK4aE@a)zb*brbJ9$WlRY~gCqK9Ja=D6-2-BP7*gX$4|_u3V=Ev|zX z|FBiSu1T-|8Bs$+LF_i|o;9dqJ=?s7FY#8(y}*0(;drYUqsWxOOVToe;}_SJjRwgn z=m(ngrpHPp6toTI)x@ul37f9^5?1qlcPoTCZiEXALFFuC_NbzpTxpu0($%Pq6@ghf@$@c2fXfQ5*7EuI8R~&4WRA^4`419ZRm*Q6@6h*qa-OZcnY)$^doyFo zol)!c6@||jTh#j*4y)tUzpEIKPsOaEmB8-i*TdzT#M9r2ww%+cR=C!x|Q0Zl6jvAKApIsMd~*%E3% zkE;cqqiD@Oo$W+hWj>sNRsK#F)!L()-&zMoCYDFykfReiqZ5Zm-$jjHzdYJdJvuQk z+OT{rpsahaiCEEYxc@1%!1%Smpfb5imXY5gw<3SS;+=R4>5t`z^wP(qv8)C{t*O9^qarJB)?iKl*yM)x+ zss##K@@iVPW5SC!mU(+(0-LV=EH;oALG>?H$KQI}u+{U-)3gQq@ZlVA#1|0pqBK(dcR} zdGLMXnzc*yDj}kr+9TRkg=pP*OnYJ4)j7)bk>@JTxDXbw-QU*%^fxE)s2{NV zPc;H=#sV9_2Y!IYpR$9|A`U(X2H@a&e}MT0z6zf5|G(e{u-~5^_Pad!#W0E!&;Sb< z{9TBbSYQ*V9|&*>qfUf*{d#p19zc8iu7dueIRgPCM*src97rGdzcw6< z3IrrMX1N)*B>AF%$Ug`IoMR;P%Kt(@R1m<9@d=_c>%v!K?&AJM;NZ(3`bde9s|YIQ zUjzZ#1=CXsaH}Jcf`PUF%to4HI(juBHI`k1-U)hw9ex%0c6!}E0SK_1foveG4l;e> zzo)Y)1d!%viCwkbLjYkm5t$+Mh_bj~wuJ_}Mq z0W=#M89=v-NUISJ0c@574$d3Xmw(Lt0|z_90A_9bSM$Dbz?RLFYr_F%srMJH906Ffp{WtTK{m}Ik!(ZaBH7YQ zk-z~qA-+*;>ES50r(=y{+uVQyEZJmhoMbz}ypwEaA|A~)`&%?12^K^H0^qrN#J_tP z4!XtAFKt*HNQeQLh3a2x`ixJA<4$?V|1_N14jtJMv%vx?XEN@(3$SFtBjJ>fA7Oz z|DW{?rdNc)Y-KYHDwb|buLtX6>BIQO0{`CbaFEJiBqbOOyL(LJG~M36kzsEDGmZd! zY=$8)m{3WOdYbK8eP-BBo4~b10L7-aJCSb7N;7(|2d@y>j?ltjEM&m oK7D@I?W~P95Qrg){s4pg57?EME&u=k From 467f57c74e1f3902acf221d1903b24dc7be33c82 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 23 Aug 2023 10:59:13 -0600 Subject: [PATCH 105/237] resolve merge conflicts --- .../manage_nodes_views/add_edit_node_view.dart | 9 +++++---- .../manage_nodes_views/node_details_view.dart | 16 ++++++++-------- lib/utilities/enums/coin_enum.dart | 3 ++- lib/widgets/node_card.dart | 5 +++-- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index c4c10a618..5ae04920d 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -196,10 +196,11 @@ class _AddEditNodeViewState extends ConsumerState { } catch (_) {} break; case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: try { - testPassed = await testStellarNodeConnection(formData.host!, formData.port!); - } catch(_) {} + testPassed = + await testStellarNodeConnection(formData.host!, formData.port!); + } catch (_) {} break; case Coin.nano: @@ -749,7 +750,7 @@ class _NodeFormState extends ConsumerState { case Coin.banano: case Coin.eCash: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: return false; case Coin.ethereum: diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index 0b339469e..d306260d6 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -26,6 +26,7 @@ import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/test_epic_box_connection.dart'; import 'package:stackwallet/utilities/test_eth_node_connection.dart'; import 'package:stackwallet/utilities/test_monero_node_connection.dart'; +import 'package:stackwallet/utilities/test_stellar_node_connection.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; @@ -172,20 +173,19 @@ class _NodeDetailsViewState extends ConsumerState { case Coin.nano: case Coin.banano: - case Coin.tezos: case Coin.stellar: case Coin.stellarTestNet: - try { - testPassed = await testStellarNodeConnection(node!.host, node.port); - } catch(_) { - testPassed = false; - } + try { + testPassed = await testStellarNodeConnection(node!.host, node.port); + } catch (_) { + testPassed = false; + } break; case Coin.nano: case Coin.banano: - + case Coin.tezos: throw UnimplementedError(); - //TODO: check network/node + //TODO: check network/node } if (testPassed) { diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index f4a4ca28f..b8af7f53c 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -262,7 +262,8 @@ extension CoinExt on Coin { case Coin.ethereum: case Coin.eCash: case Coin.stellar: - case Coin.stellarTestnet: + case Coin.stellarTestNet: + case Coin.tezos: return true; case Coin.epicCash: diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart index a75b09c64..b63c21b93 100644 --- a/lib/widgets/node_card.dart +++ b/lib/widgets/node_card.dart @@ -29,6 +29,7 @@ import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/test_epic_box_connection.dart'; import 'package:stackwallet/utilities/test_eth_node_connection.dart'; import 'package:stackwallet/utilities/test_monero_node_connection.dart'; +import 'package:stackwallet/utilities/test_stellar_node_connection.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; @@ -199,7 +200,7 @@ class _NodeCardState extends ConsumerState { case Coin.stellarTestNet: try { testPassed = await testStellarNodeConnection(node.host, node.port); - } catch(_) { + } catch (_) { testPassed = false; } break; @@ -207,7 +208,7 @@ class _NodeCardState extends ConsumerState { case Coin.nano: case Coin.banano: throw UnimplementedError(); - //TODO: check network/node + //TODO: check network/node } if (testPassed) { From 02b67c2a2e0de3743550ea7f5664158ab93d0075 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 23 Aug 2023 11:08:32 -0600 Subject: [PATCH 106/237] add parameter to initializeNew for tezos --- lib/services/coins/tezos/tezos_wallet.dart | 50 +++++++++++----------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 1fb192190..6b0d10cc6 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -186,16 +186,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future confirmSend({required Map txData}) async { try { - final amount = txData["recipientAmt"] as Amount; - final amountInMicroTez = - amount.decimal * Decimal.fromInt(1000000); + final amountInMicroTez = amount.decimal * Decimal.fromInt(1000000); final microtezToInt = int.parse(amountInMicroTez.toString()); final int feeInMicroTez = int.parse(txData["fee"].toString()); final String destinationAddress = txData["address"] as String; - final secretKey = Keystore.fromMnemonic((await mnemonicString)!) - .secretKey; + final secretKey = + Keystore.fromMnemonic((await mnemonicString)!).secretKey; Logging.instance.log(secretKey, level: LogLevel.Info); final sourceKeyStore = Keystore.fromSecretKey(secretKey); @@ -208,9 +206,9 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { if (balance.spendable == txData["recipientAmt"] as Amount) { //Fee guides for emptying a tz account // https://github.com/TezTech/eztz/blob/master/PROTO_004_FEES.md - thisFee = thisFee + 32; - sendAmount = microtezToInt - thisFee; - gasLimit = _gasLimit + 320; + thisFee = thisFee + 32; + sendAmount = microtezToInt - thisFee; + gasLimit = _gasLimit + 320; } final operation = await client.transferOperation( @@ -218,8 +216,7 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { destination: destinationAddress, amount: sendAmount, customFee: feeInMicroTez, - customGasLimit: gasLimit - ); + customGasLimit: gasLimit); await operation.executeAndMonitor(); return operation.result.id as String; } catch (e) { @@ -239,7 +236,6 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future estimateFeeFor(Amount amount, int feeRate) async { - var api = "https://api.tzstats.com/series/op?start_date=today&collapse=1d"; var response = jsonDecode((await get(Uri.parse(api))).body)[0]; double totalFees = response[4] as double; @@ -300,7 +296,9 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future initializeNew() async { + Future initializeNew( + ({String mnemonicPassphrase, int wordCount})? data, + ) async { if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) { throw Exception( "Attempted to overwrite mnemonic on generate new wallet!"); @@ -409,7 +407,8 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { try { String balanceCall = "https://api.mainnet.tzkt.io/v1/accounts/" "${await currentReceivingAddress}/balance"; - var response = jsonDecode(await get(Uri.parse(balanceCall)).then((value) => value.body)); + var response = jsonDecode( + await get(Uri.parse(balanceCall)).then((value) => value.body)); Amount balanceInAmount = Amount( rawValue: BigInt.parse(response.toString()), fractionDigits: coin.decimals); @@ -431,7 +430,8 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateTransactions() async { String transactionsCall = "https://api.mainnet.tzkt.io/v1/accounts/" "${await currentReceivingAddress}/operations"; - var response = jsonDecode(await get(Uri.parse(transactionsCall)).then((value) => value.body)); + var response = jsonDecode( + await get(Uri.parse(transactionsCall)).then((value) => value.body)); List> txs = []; for (var tx in response as List) { if (tx["type"] == "transaction") { @@ -446,18 +446,16 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { walletId: walletId, txid: tx["hash"].toString(), timestamp: DateTime.parse(tx["timestamp"].toString()) - .toUtc() - .millisecondsSinceEpoch ~/ + .toUtc() + .millisecondsSinceEpoch ~/ 1000, type: txType, subType: TransactionSubType.none, amount: tx["amount"] as int, amountString: Amount( - rawValue: BigInt.parse( - (tx["amount"] as int) - .toInt() - .toString()), - fractionDigits: coin.decimals) + rawValue: + BigInt.parse((tx["amount"] as int).toInt().toString()), + fractionDigits: coin.decimals) .toJsonString(), fee: tx["bakerFee"] as int, height: int.parse(tx["level"].toString()), @@ -561,14 +559,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { ); final address = txData["address"] is String - ? await db.getAddress(walletId, txData["address"] as String) - : null; + ? await db.getAddress(walletId, txData["address"] as String) + : null; await db.addNewTransactionData( - [ + [ Tuple2(transaction, address), - ], - walletId, + ], + walletId, ); } From 63ab0b09e897dc993b9c0fdbe1bfb74be4ea2835 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 11:29:10 -0600 Subject: [PATCH 107/237] revert enum name --- .../add_edit_node_view.dart | 4 +-- .../manage_nodes_views/node_details_view.dart | 2 +- lib/services/coins/coin_service.dart | 2 +- lib/themes/color_theme.dart | 2 +- lib/themes/stack_colors.dart | 2 +- lib/utilities/address_utils.dart | 2 +- lib/utilities/amount/amount_unit.dart | 2 +- lib/utilities/block_explorers.dart | 2 +- lib/utilities/constants.dart | 10 ++++---- lib/utilities/default_nodes.dart | 25 +++++++++---------- lib/utilities/enums/coin_enum.dart | 24 +++++++++--------- .../enums/derive_path_type_enum.dart | 2 +- lib/widgets/node_card.dart | 2 +- lib/widgets/node_options_sheet.dart | 2 +- 14 files changed, 41 insertions(+), 42 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 5ae04920d..8a09a3d03 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -196,7 +196,7 @@ class _AddEditNodeViewState extends ConsumerState { } catch (_) {} break; case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: try { testPassed = await testStellarNodeConnection(formData.host!, formData.port!); @@ -750,7 +750,7 @@ class _NodeFormState extends ConsumerState { case Coin.banano: case Coin.eCash: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return false; case Coin.ethereum: diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index d306260d6..de3a4b5e5 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -174,7 +174,7 @@ class _NodeDetailsViewState extends ConsumerState { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: try { testPassed = await testStellarNodeConnection(node!.host, node.port); } catch (_) { diff --git a/lib/services/coins/coin_service.dart b/lib/services/coins/coin_service.dart index 72478b353..360372095 100644 --- a/lib/services/coins/coin_service.dart +++ b/lib/services/coins/coin_service.dart @@ -229,7 +229,7 @@ abstract class CoinServiceAPI { tracker: tracker, ); - case Coin.stellarTestNet: + case Coin.stellarTestnet: return StellarWallet( walletId: walletId, walletName: walletName, diff --git a/lib/themes/color_theme.dart b/lib/themes/color_theme.dart index 0e6816dd8..abec28d4e 100644 --- a/lib/themes/color_theme.dart +++ b/lib/themes/color_theme.dart @@ -65,7 +65,7 @@ class CoinThemeColorDefault { case Coin.particl: return particl; case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return stellar; case Coin.nano: return nano; diff --git a/lib/themes/stack_colors.dart b/lib/themes/stack_colors.dart index fde5219cf..cbec0077a 100644 --- a/lib/themes/stack_colors.dart +++ b/lib/themes/stack_colors.dart @@ -1708,7 +1708,7 @@ class StackColors extends ThemeExtension { case Coin.particl: return _coin.particl; case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return _coin.stellar; case Coin.nano: return _coin.nano; diff --git a/lib/utilities/address_utils.dart b/lib/utilities/address_utils.dart index b4974d8c6..3fa895282 100644 --- a/lib/utilities/address_utils.dart +++ b/lib/utilities/address_utils.dart @@ -143,7 +143,7 @@ class AddressUtils { return Address.validateAddress(address, firoTestNetwork); case Coin.dogecoinTestNet: return Address.validateAddress(address, dogecointestnet); - case Coin.stellarTestNet: + case Coin.stellarTestnet: return RegExp(r"^[G][A-Z0-9]{55}$").hasMatch(address); } } diff --git a/lib/utilities/amount/amount_unit.dart b/lib/utilities/amount/amount_unit.dart index 00055a0fe..6a646fd11 100644 --- a/lib/utilities/amount/amount_unit.dart +++ b/lib/utilities/amount/amount_unit.dart @@ -51,7 +51,7 @@ enum AmountUnit { case Coin.eCash: case Coin.epicCash: case Coin.stellar: // TODO: check if this is correct - case Coin.stellarTestNet: + case Coin.stellarTestnet: case Coin.tezos: return AmountUnit.values.sublist(0, 4); diff --git a/lib/utilities/block_explorers.dart b/lib/utilities/block_explorers.dart index ddc055fb1..bb4ac06fb 100644 --- a/lib/utilities/block_explorers.dart +++ b/lib/utilities/block_explorers.dart @@ -60,7 +60,7 @@ Uri getDefaultBlockExplorerUrlFor({ return Uri.parse("https://www.nanolooker.com/block/$txid"); case Coin.banano: return Uri.parse("https://www.bananolooker.com/block/$txid"); - case Coin.stellarTestNet: + case Coin.stellarTestnet: return Uri.parse("https://testnet.stellarchain.io/transactions/$txid"); case Coin.tezos: return Uri.parse("https://tzstats.com/$txid"); diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 1bd3a5a50..1253e08f1 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -102,7 +102,7 @@ abstract class Constants { return _satsPerCoinECash; case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return _satsPerCoinStellar; case Coin.tezos: @@ -146,7 +146,7 @@ abstract class Constants { return _decimalPlacesECash; case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return _decimalPlacesStellar; case Coin.tezos: @@ -174,7 +174,7 @@ abstract class Constants { case Coin.particl: case Coin.nano: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: values.addAll([24, 12]); break; case Coin.banano: @@ -238,7 +238,7 @@ abstract class Constants { return 1; case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return 5; case Coin.tezos: @@ -271,7 +271,7 @@ abstract class Constants { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: case Coin.tezos: return 24; diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index 7fed3d7fd..210959f65 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -191,8 +191,7 @@ abstract class DefaultNodes { enabled: true, coinName: Coin.stellar.name, isFailover: true, - isDown: false - ); + isDown: false); static NodeModel get tezos => NodeModel( // TODO: Change this to stack wallet one @@ -289,16 +288,16 @@ abstract class DefaultNodes { ); static NodeModel get stellarTestnet => NodeModel( - host: "https://horizon-testnet.stellar.org/", - port: 50022, - name: defaultName, - id: _nodeId(Coin.stellarTestNet), - useSSL: true, - enabled: true, - coinName: Coin.stellarTestNet.name, - isFailover: true, - isDown: false, - ); + host: "https://horizon-testnet.stellar.org/", + port: 50022, + name: defaultName, + id: _nodeId(Coin.stellarTestnet), + useSSL: true, + enabled: true, + coinName: Coin.stellarTestnet.name, + isFailover: true, + isDown: false, + ); static NodeModel getNodeFor(Coin coin) { switch (coin) { @@ -365,7 +364,7 @@ abstract class DefaultNodes { case Coin.dogecoinTestNet: return dogecoinTestnet; - case Coin.stellarTestNet: + case Coin.stellarTestnet: return stellarTestnet; } } diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index b8af7f53c..f5a42e8da 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -60,7 +60,7 @@ enum Coin { dogecoinTestNet, firoTestNet, litecoinTestNet, - stellarTestNet, + stellarTestnet, } final int kTestNetCoinCount = 5; // Util.isDesktop ? 5 : 4; @@ -111,7 +111,7 @@ extension CoinExt on Coin { return "tFiro"; case Coin.dogecoinTestNet: return "tDogecoin"; - case Coin.stellarTestNet: + case Coin.stellarTestnet: return "tStellar"; } } @@ -160,7 +160,7 @@ extension CoinExt on Coin { return "tFIRO"; case Coin.dogecoinTestNet: return "tDOGE"; - case Coin.stellarTestNet: + case Coin.stellarTestnet: return "tXLM"; } } @@ -210,7 +210,7 @@ extension CoinExt on Coin { return "firo"; case Coin.dogecoinTestNet: return "dogecoin"; - case Coin.stellarTestNet: + case Coin.stellarTestnet: return "stellar"; } } @@ -240,7 +240,7 @@ extension CoinExt on Coin { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return false; } } @@ -262,7 +262,7 @@ extension CoinExt on Coin { case Coin.ethereum: case Coin.eCash: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: case Coin.tezos: return true; @@ -300,7 +300,7 @@ extension CoinExt on Coin { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return false; } } @@ -330,7 +330,7 @@ extension CoinExt on Coin { case Coin.litecoinTestNet: case Coin.bitcoincashTestnet: case Coin.firoTestNet: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return true; } } @@ -370,7 +370,7 @@ extension CoinExt on Coin { case Coin.firoTestNet: return Coin.firo; - case Coin.stellarTestNet: + case Coin.stellarTestnet: return Coin.stellar; } } @@ -413,7 +413,7 @@ extension CoinExt on Coin { return particl.MINIMUM_CONFIRMATIONS; case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: return xlm.MINIMUM_CONFIRMATIONS; case Coin.tezos: @@ -534,7 +534,7 @@ Coin coinFromPrettyName(String name) { case "stellarTestnet": case "stellarTestNet": case "tStellar": - return Coin.stellarTestNet; + return Coin.stellarTestnet; default: throw ArgumentError.value( @@ -590,7 +590,7 @@ Coin coinFromTickerCaseInsensitive(String ticker) { case "ban": return Coin.banano; case "txlm": - return Coin.stellarTestNet; + return Coin.stellarTestnet; default: throw ArgumentError.value( ticker, "name", "No Coin enum value with that ticker"); diff --git a/lib/utilities/enums/derive_path_type_enum.dart b/lib/utilities/enums/derive_path_type_enum.dart index f3c456f67..5b94f41f6 100644 --- a/lib/utilities/enums/derive_path_type_enum.dart +++ b/lib/utilities/enums/derive_path_type_enum.dart @@ -50,7 +50,7 @@ extension DerivePathTypeExt on DerivePathType { case Coin.nano: case Coin.banano: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: case Coin.tezos: // TODO: Is this true? throw UnsupportedError( "$coin does not use bitcoin style derivation paths"); diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart index b63c21b93..0f65fcfd5 100644 --- a/lib/widgets/node_card.dart +++ b/lib/widgets/node_card.dart @@ -197,7 +197,7 @@ class _NodeCardState extends ConsumerState { case Coin.banano: case Coin.tezos: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: try { testPassed = await testStellarNodeConnection(node.host, node.port); } catch (_) { diff --git a/lib/widgets/node_options_sheet.dart b/lib/widgets/node_options_sheet.dart index 63fd2b13e..953ac78a1 100644 --- a/lib/widgets/node_options_sheet.dart +++ b/lib/widgets/node_options_sheet.dart @@ -179,7 +179,7 @@ class NodeOptionsSheet extends ConsumerWidget { case Coin.banano: case Coin.tezos: case Coin.stellar: - case Coin.stellarTestNet: + case Coin.stellarTestnet: throw UnimplementedError(); //TODO: check network/node } From 4de632bdb47d8ee11310bc57ae957c202caeb4cd Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 11:35:04 -0600 Subject: [PATCH 108/237] fix switch statement logic --- .../manage_nodes_views/add_edit_node_view.dart | 3 +-- .../manage_nodes_views/node_details_view.dart | 8 +++----- lib/widgets/node_card.dart | 7 ++----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 8a09a3d03..2bb833fd1 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -205,9 +205,8 @@ class _AddEditNodeViewState extends ConsumerState { case Coin.nano: case Coin.banano: - throw UnimplementedError(); - //TODO: check network/node case Coin.tezos: + throw UnimplementedError(); //TODO: check network/node } diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index de3a4b5e5..c05cbbca5 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -173,6 +173,9 @@ class _NodeDetailsViewState extends ConsumerState { case Coin.nano: case Coin.banano: + case Coin.tezos: + throw UnimplementedError(); + //TODO: check network/node case Coin.stellar: case Coin.stellarTestnet: try { @@ -181,11 +184,6 @@ class _NodeDetailsViewState extends ConsumerState { testPassed = false; } break; - case Coin.nano: - case Coin.banano: - case Coin.tezos: - throw UnimplementedError(); - //TODO: check network/node } if (testPassed) { diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart index 0f65fcfd5..44b8a696a 100644 --- a/lib/widgets/node_card.dart +++ b/lib/widgets/node_card.dart @@ -196,6 +196,8 @@ class _NodeCardState extends ConsumerState { case Coin.nano: case Coin.banano: case Coin.tezos: + //TODO: check network/node + throw UnimplementedError(); case Coin.stellar: case Coin.stellarTestnet: try { @@ -204,11 +206,6 @@ class _NodeCardState extends ConsumerState { testPassed = false; } break; - - case Coin.nano: - case Coin.banano: - throw UnimplementedError(); - //TODO: check network/node } if (testPassed) { From 2e64d356294486af92b8b335085eded4f14aa0ed Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 11:49:21 -0600 Subject: [PATCH 109/237] tezos does not used the bip39 lib directly. Do not show new wallet options. Needs more investigation --- lib/utilities/enums/coin_enum.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index f5a42e8da..77af4b4d1 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -263,7 +263,6 @@ extension CoinExt on Coin { case Coin.eCash: case Coin.stellar: case Coin.stellarTestnet: - case Coin.tezos: return true; case Coin.epicCash: @@ -271,6 +270,7 @@ extension CoinExt on Coin { case Coin.wownero: case Coin.nano: case Coin.banano: + case Coin.tezos: return false; } } From 19a6e0b8263d9c89e5af278891b8d44062ee8abe Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 11:58:16 -0600 Subject: [PATCH 110/237] fix tezos refresh function --- lib/services/coins/tezos/tezos_wallet.dart | 68 ++++++++++++++++++++-- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 6b0d10cc6..bf0a8cf5d 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -13,6 +13,8 @@ import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/services/coins/coin_service.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart'; +import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; @@ -499,11 +501,67 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future refresh() { - updateChainHeight(); - updateBalance(); - updateTransactions(); - return Future.value(); + Future refresh() async { + if (refreshMutex) { + Logging.instance.log( + "$walletId $walletName refreshMutex denied", + level: LogLevel.Info, + ); + return; + } else { + refreshMutex = true; + } + + try { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.syncing, + walletId, + coin, + ), + ); + + await updateChainHeight(); + await updateBalance(); + await updateTransactions(); + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.synced, + walletId, + coin, + ), + ); + + if (shouldAutoSync) { + timer ??= Timer.periodic(const Duration(seconds: 30), (timer) async { + Logging.instance.log( + "Periodic refresh check for $walletId $walletName in object instance: $hashCode", + level: LogLevel.Info); + + await refresh(); + GlobalEventBus.instance.fire( + UpdatedInBackgroundEvent( + "New data found in $walletId $walletName in background!", + walletId, + ), + ); + }); + } + } catch (e, s) { + Logging.instance.log( + "Failed to refresh stellar wallet $walletId: '$walletName': $e\n$s", + level: LogLevel.Warning, + ); + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.unableToSync, + walletId, + coin, + ), + ); + } + + refreshMutex = false; } @override From 31cac4b9502eb02b5ccc190d93dacd2e764d4cf5 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 14:12:11 -0600 Subject: [PATCH 111/237] code formatting --- .../coins/stellar/stellar_wallet.dart | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index a9f9d97df..c5ee3114b 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -1,6 +1,6 @@ import 'dart:async'; + import 'package:bip39/bip39.dart' as bip39; -import 'package:http/http.dart' as http; import 'package:isar/isar.dart'; import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/models/balance.dart' as SWBalance; @@ -37,7 +37,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { late StellarSDK stellarSdk; late Network stellarNetwork; - StellarWallet({ required String walletId, required String walletName, @@ -54,7 +53,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { initCache(walletId, coin); initWalletDB(mockableOverride: mockableOverride); - if (coin.isTestNet) { stellarNetwork = Network.TESTNET; } else { @@ -66,7 +64,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { void _updateNode() { _xlmNode = NodeService(secureStorageInterface: _secureStore) - .getPrimaryNodeFor(coin: coin) ?? + .getPrimaryNodeFor(coin: coin) ?? DefaultNodes.getNodeFor(coin); stellarSdk = StellarSDK("${_xlmNode!.host}:${_xlmNode!.port}"); } @@ -212,13 +210,12 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { } transaction.sign(senderKeyPair, stellarNetwork); try { - SubmitTransactionResponse response = - await stellarSdk.submitTransaction(transaction).onError((error, stackTrace) => throw (error.toString())); + SubmitTransactionResponse response = await stellarSdk + .submitTransaction(transaction) + .onError((error, stackTrace) => throw (error.toString())); if (!response.success) { - throw ( - "${response.extras?.resultCodes?.transactionResultCode}" - " ::: ${response.extras?.resultCodes?.operationsResultCodes}" - ); + throw ("${response.extras?.resultCodes?.transactionResultCode}" + " ::: ${response.extras?.resultCodes?.operationsResultCodes}"); } return response.hash!; } catch (e, s) { @@ -248,7 +245,8 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future estimateFeeFor(Amount amount, int feeRate) async { var baseFee = await getBaseFee(); - return Amount(rawValue: BigInt.from(baseFee), fractionDigits: coin.decimals); + return Amount( + rawValue: BigInt.from(baseFee), fractionDigits: coin.decimals); } @override @@ -276,7 +274,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future get fees async { - int fee = await getBaseFee(); return FeeObject( numberOfBlocksFast: 10, @@ -402,7 +399,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { {required String address, required Amount amount, Map? args}) async { - try { final feeRate = args?["feeRate"]; var fee = 1000; @@ -433,12 +429,13 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - Future recoverFromMnemonic( - {required String mnemonic, - String? mnemonicPassphrase, - required int maxUnusedAddressGap, - required int maxNumberOfIndexesToCheck, - required int height}) async { + Future recoverFromMnemonic({ + required String mnemonic, + String? mnemonicPassphrase, + required int maxUnusedAddressGap, + required int maxNumberOfIndexesToCheck, + required int height, + }) async { if ((await mnemonicString) != null || (await this.mnemonicPassphrase) != null) { throw Exception("Attempted to overwrite mnemonic on restore!"); From 4b5686d8a4c009146ec853ab3481c47d7bde41c9 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 14:31:34 -0600 Subject: [PATCH 112/237] handle stellar rescan properly --- .../coins/stellar/stellar_wallet.dart | 173 ++++++++++++++---- 1 file changed, 133 insertions(+), 40 deletions(-) diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index c5ee3114b..fc77bfe72 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -28,6 +28,7 @@ import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; +import 'package:stackwallet/utilities/test_stellar_node_connection.dart'; import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; import 'package:tuple/tuple.dart'; @@ -286,16 +287,65 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future fullRescan( - int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) async { - await _prefs.init(); - await updateTransactions(); - await updateChainHeight(); - await updateBalance(); + int maxUnusedAddressGap, + int maxNumberOfIndexesToCheck, + ) async { + try { + Logging.instance.log("Starting full rescan!", level: LogLevel.Info); + longMutex = true; + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.syncing, + walletId, + coin, + ), + ); + + final _mnemonic = await mnemonicString; + final _mnemonicPassphrase = await mnemonicPassphrase; + + await db.deleteWalletBlockchainData(walletId); + + await _recoverWalletFromBIP32SeedPhrase( + mnemonic: _mnemonic!, + mnemonicPassphrase: _mnemonicPassphrase!, + isRescan: true, + ); + + await refresh(); + Logging.instance.log("Full rescan complete!", level: LogLevel.Info); + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.synced, + walletId, + coin, + ), + ); + } catch (e, s) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.unableToSync, + walletId, + coin, + ), + ); + + // restore from backup + // await _rescanRestore(); + + Logging.instance.log( + "Exception rethrown from fullRescan(): $e\n$s", + level: LogLevel.Error, + ); + rethrow; + } finally { + longMutex = false; + } } @override Future generateNewAddress() { - // TODO: implement generateNewAddress + // not used for stellar(?) throw UnimplementedError(); } @@ -428,6 +478,44 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { } } + Future _recoverWalletFromBIP32SeedPhrase({ + required String mnemonic, + required String mnemonicPassphrase, + bool isRescan = false, + }) async { + final Wallet wallet = await Wallet.from( + mnemonic, + passphrase: mnemonicPassphrase, + ); + final KeyPair keyPair = await wallet.getKeyPair(index: 0); + final String address = keyPair.accountId; + String secretSeed = + keyPair.secretSeed; //This will be required for sending a tx + + await _secureStore.write( + key: '${_walletId}_secretSeed', + value: secretSeed, + ); + + final swAddress = SWAddress.Address( + walletId: walletId, + value: address, + publicKey: keyPair.publicKey, + derivationIndex: 0, + derivationPath: null, + type: SWAddress.AddressType.unknown, + subType: SWAddress.AddressSubType.unknown, + ); + + if (isRescan) { + await db.updateOrPutAddresses([swAddress]); + } else { + await db.putAddress(swAddress); + } + } + + bool longMutex = false; + @override Future recoverFromMnemonic({ required String mnemonic, @@ -436,37 +524,41 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { required int maxNumberOfIndexesToCheck, required int height, }) async { - if ((await mnemonicString) != null || - (await this.mnemonicPassphrase) != null) { - throw Exception("Attempted to overwrite mnemonic on restore!"); + longMutex = true; + try { + if ((await mnemonicString) != null || + (await this.mnemonicPassphrase) != null) { + throw Exception("Attempted to overwrite mnemonic on restore!"); + } + + await _secureStore.write( + key: '${_walletId}_mnemonic', + value: mnemonic.trim(), + ); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: mnemonicPassphrase ?? "", + ); + + await _recoverWalletFromBIP32SeedPhrase( + mnemonic: mnemonic, + mnemonicPassphrase: mnemonicPassphrase ?? "", + isRescan: false, + ); + + await Future.wait([ + updateCachedId(walletId), + updateCachedIsFavorite(false), + ]); + } catch (e, s) { + Logging.instance.log( + "Exception rethrown from recoverFromMnemonic(): $e\n$s", + level: LogLevel.Error); + + rethrow; + } finally { + longMutex = false; } - - var wallet = await Wallet.from(mnemonic); - var keyPair = await wallet.getKeyPair(index: 0); - var address = keyPair.accountId; - var secretSeed = keyPair.secretSeed; - - await _secureStore.write( - key: '${_walletId}_mnemonic', value: mnemonic.trim()); - await _secureStore.write( - key: '${_walletId}_mnemonicPassphrase', - value: mnemonicPassphrase ?? "", - ); - await _secureStore.write(key: '${_walletId}_secretSeed', value: secretSeed); - - final swAddress = SWAddress.Address( - walletId: walletId, - value: address, - publicKey: keyPair.publicKey, - derivationIndex: 0, - derivationPath: null, - type: SWAddress.AddressType.unknown, // TODO: set type - subType: SWAddress.AddressSubType.unknown); - - await db.putAddress(swAddress); - - await Future.wait( - [updateCachedId(walletId), updateCachedIsFavorite(false)]); } Future updateChainHeight() async { @@ -622,6 +714,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { Logging.instance.log( "Exception rethrown from updateTransactions(): $e\n$s", level: LogLevel.Error); + rethrow; } } @@ -659,6 +752,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { "ERROR GETTING BALANCE $e\n$s", level: LogLevel.Info, ); + rethrow; } } @@ -733,9 +827,8 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { int get storedChainHeight => getCachedChainHeight(); @override - Future testNetworkConnection() { - // TODO: implement testNetworkConnection - throw UnimplementedError(); + Future testNetworkConnection() async { + return await testStellarNodeConnection(_xlmNode!.host, _xlmNode!.port); } @override @@ -786,7 +879,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { } @override - // TODO: implement utxos + // not used Future> get utxos => throw UnimplementedError(); @override From 3cd31d1bf26fa26dccbb161966d6f3c16a7eb125 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 14:56:40 -0600 Subject: [PATCH 113/237] clean up --- lib/services/coins/stellar/stellar_wallet.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index fc77bfe72..b12954628 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -330,9 +330,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { ), ); - // restore from backup - // await _rescanRestore(); - Logging.instance.log( "Exception rethrown from fullRescan(): $e\n$s", level: LogLevel.Error, From 6e4a23007b5fe804e87e5afe7deac27308192e8e Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 14:58:22 -0600 Subject: [PATCH 114/237] fix some rescan functionality --- lib/services/coins/tezos/tezos_wallet.dart | 180 ++++++++++++++++----- 1 file changed, 141 insertions(+), 39 deletions(-) diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index bf0a8cf5d..6e128478e 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -275,13 +275,6 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { ); } - @override - Future fullRescan( - int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) { - refresh(); - return Future.value(); - } - @override Future generateNewAddress() { // TODO: implement generateNewAddress @@ -321,11 +314,11 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { final address = Address( walletId: walletId, value: newKeystore.address, - publicKey: [], // TODO: Add public key + publicKey: [], derivationIndex: 0, derivationPath: null, type: AddressType.unknown, - subType: AddressSubType.unknown, + subType: AddressSubType.receiving, ); await db.putAddress(address); @@ -369,40 +362,131 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future get mnemonicString => _secureStore.read(key: '${_walletId}_mnemonic'); - @override - Future recoverFromMnemonic( - {required String mnemonic, - String? mnemonicPassphrase, - required int maxUnusedAddressGap, - required int maxNumberOfIndexesToCheck, - required int height}) async { - if ((await mnemonicString) != null || - (await this.mnemonicPassphrase) != null) { - throw Exception("Attempted to overwrite mnemonic on restore!"); - } - await _secureStore.write( - key: '${_walletId}_mnemonic', value: mnemonic.trim()); - await _secureStore.write( - key: '${_walletId}_mnemonicPassphrase', - value: mnemonicPassphrase ?? "", + Future _recoverWalletFromSeedPhrase({ + required String mnemonic, + required String mnemonicPassphrase, + bool isRescan = false, + }) async { + final keystore = Keystore.fromMnemonic( + mnemonic, + password: mnemonicPassphrase, ); final address = Address( walletId: walletId, - value: Keystore.fromMnemonic(mnemonic).address, - publicKey: [], // TODO: Add public key + value: keystore.address, + publicKey: [], derivationIndex: 0, derivationPath: null, type: AddressType.unknown, - subType: AddressSubType.unknown, + subType: AddressSubType.receiving, ); - await db.putAddress(address); + if (isRescan) { + await db.updateOrPutAddresses([address]); + } else { + await db.putAddress(address); + } + } - await Future.wait([ - updateCachedId(walletId), - updateCachedIsFavorite(false), - ]); + bool longMutex = false; + @override + Future fullRescan( + int maxUnusedAddressGap, + int maxNumberOfIndexesToCheck, + ) async { + try { + Logging.instance.log("Starting full rescan!", level: LogLevel.Info); + longMutex = true; + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.syncing, + walletId, + coin, + ), + ); + + final _mnemonic = await mnemonicString; + final _mnemonicPassphrase = await mnemonicPassphrase; + + await db.deleteWalletBlockchainData(walletId); + + await _recoverWalletFromSeedPhrase( + mnemonic: _mnemonic!, + mnemonicPassphrase: _mnemonicPassphrase!, + isRescan: true, + ); + + await refresh(); + Logging.instance.log("Full rescan complete!", level: LogLevel.Info); + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.synced, + walletId, + coin, + ), + ); + } catch (e, s) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.unableToSync, + walletId, + coin, + ), + ); + + Logging.instance.log( + "Exception rethrown from fullRescan(): $e\n$s", + level: LogLevel.Error, + ); + rethrow; + } finally { + longMutex = false; + } + } + + @override + Future recoverFromMnemonic({ + required String mnemonic, + String? mnemonicPassphrase, + required int maxUnusedAddressGap, + required int maxNumberOfIndexesToCheck, + required int height, + }) async { + longMutex = true; + try { + if ((await mnemonicString) != null || + (await this.mnemonicPassphrase) != null) { + throw Exception("Attempted to overwrite mnemonic on restore!"); + } + await _secureStore.write( + key: '${_walletId}_mnemonic', value: mnemonic.trim()); + await _secureStore.write( + key: '${_walletId}_mnemonicPassphrase', + value: mnemonicPassphrase ?? "", + ); + + await _recoverWalletFromSeedPhrase( + mnemonic: mnemonic, + mnemonicPassphrase: mnemonicPassphrase ?? "", + isRescan: false, + ); + + await Future.wait([ + updateCachedId(walletId), + updateCachedIsFavorite(false), + ]); + + await refresh(); + } catch (e, s) { + Logging.instance.log( + "Exception rethrown from recoverFromMnemonic(): $e\n$s", + level: LogLevel.Error); + + rethrow; + } finally { + longMutex = false; + } } Future updateBalance() async { @@ -438,10 +522,17 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { for (var tx in response as List) { if (tx["type"] == "transaction") { TransactionType txType; - if (tx["sender"]["address"] == (await currentReceivingAddress)) { + final String myAddress = await currentReceivingAddress; + final String senderAddress = tx["sender"]["address"] as String; + final String targetAddress = tx["target"]["address"] as String; + if (senderAddress == myAddress && targetAddress == myAddress) { + txType = TransactionType.sentToSelf; + } else if (senderAddress == myAddress) { txType = TransactionType.outgoing; - } else { + } else if (targetAddress == myAddress) { txType = TransactionType.incoming; + } else { + txType = TransactionType.unknown; } var theTx = Transaction( @@ -470,14 +561,25 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { nonce: 0, numberOfMessages: null, ); - var theAddress = Address( + final AddressSubType subType; + switch (txType) { + case TransactionType.incoming: + case TransactionType.sentToSelf: + subType = AddressSubType.receiving; + break; + case TransactionType.outgoing: + case TransactionType.unknown: + subType = AddressSubType.unknown; + break; + } + final theAddress = Address( walletId: walletId, - value: tx["target"]["address"].toString(), - publicKey: [], // TODO: Add public key + value: targetAddress, + publicKey: [], derivationIndex: 0, derivationPath: null, type: AddressType.unknown, - subType: AddressSubType.unknown, + subType: subType, ); txs.add(Tuple2(theTx, theAddress)); } From 5b4e4c49037d9240134c5931ae3a9af67f9db544 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Aug 2023 15:05:16 -0600 Subject: [PATCH 115/237] fix price tests to include tezos --- test/price_test.dart | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/price_test.dart b/test/price_test.dart index 6741d5445..e5383bef8 100644 --- a/test/price_test.dart +++ b/test/price_test.dart @@ -28,7 +28,8 @@ void main() { Uri.parse( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids" "=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin,bitcoin-cash" - ",namecoin,wownero,ethereum,particl,nano,banano,stellar&order=market_cap_desc&per_page=50" + ",namecoin,wownero,ethereum,particl,nano,banano,stellar,tezos" + "&order=market_cap_desc&per_page=50" "&page=1&sparkline=false"), headers: { 'Content-Type': 'application/json' @@ -114,6 +115,7 @@ void main() { 'Coin.nano: [0, 0.0], ' 'Coin.particl: [0, 0.0], ' 'Coin.stellar: [0, 0.0], ' + 'Coin.tezos: [0, 0.0], ' 'Coin.wownero: [0, 0.0], ' 'Coin.bitcoinTestNet: [0, 0.0], ' 'Coin.bitcoincashTestnet: [0, 0.0], ' @@ -128,6 +130,7 @@ void main() { "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc" "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" + ",tezos" "&order=market_cap_desc&per_page=50&page=1&sparkline=false", ), headers: {'Content-Type': 'application/json'})).called(1); @@ -143,6 +146,7 @@ void main() { "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&" "ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" + ",tezos" "&order=market_cap_desc&per_page=50&page=1&sparkline=false"), headers: { 'Content-Type': 'application/json' @@ -228,7 +232,10 @@ void main() { 'Coin.firo: [0.0001096, -0.89304], ' 'Coin.litecoin: [0, 0.0], ' 'Coin.namecoin: [0, 0.0], ' - 'Coin.nano: [0, 0.0], Coin.particl: [0, 0.0], Coin.stellar: [0, 0.0], ' + 'Coin.nano: [0, 0.0], ' + 'Coin.particl: [0, 0.0], ' + 'Coin.stellar: [0, 0.0], ' + 'Coin.tezos: [0, 0.0], ' 'Coin.wownero: [0, 0.0], ' 'Coin.bitcoinTestNet: [0, 0.0], ' 'Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], ' @@ -244,6 +251,7 @@ void main() { "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids" "=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" + ",tezos" "&order=market_cap_desc&per_page=50&page=1&sparkline=false"), headers: {'Content-Type': 'application/json'})).called(1); @@ -258,6 +266,7 @@ void main() { "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc" "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" + ",tezos" "&order=market_cap_desc&per_page=50&page=1&sparkline=false"), headers: { 'Content-Type': 'application/json' @@ -343,6 +352,7 @@ void main() { 'Coin.nano: [0, 0.0], ' 'Coin.particl: [0, 0.0], ' 'Coin.stellar: [0, 0.0], ' + 'Coin.tezos: [0, 0.0], ' 'Coin.wownero: [0, 0.0], ' 'Coin.bitcoinTestNet: [0, 0.0], ' 'Coin.bitcoincashTestnet: [0, 0.0], ' @@ -362,6 +372,7 @@ void main() { "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc" "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" + ",tezos" "&order=market_cap_desc&per_page=50&page=1&sparkline=false"), headers: { 'Content-Type': 'application/json' @@ -390,6 +401,7 @@ void main() { 'Coin.nano: [0, 0.0], ' 'Coin.particl: [0, 0.0], ' 'Coin.stellar: [0, 0.0], ' + 'Coin.tezos: [0, 0.0], ' 'Coin.wownero: [0, 0.0], ' 'Coin.bitcoinTestNet: [0, 0.0], ' 'Coin.bitcoincashTestnet: [0, 0.0], ' From 0c481f2e492eab0e687732bf8967c10a84743d93 Mon Sep 17 00:00:00 2001 From: likho Date: Thu, 24 Aug 2023 11:30:04 +0200 Subject: [PATCH 116/237] Remove new address button for xtz and xlm --- lib/pages/receive_view/receive_view.dart | 10 ++++++++-- .../wallet_view/sub_widgets/desktop_receive.dart | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/pages/receive_view/receive_view.dart b/lib/pages/receive_view/receive_view.dart index d77e0e244..480813fc9 100644 --- a/lib/pages/receive_view/receive_view.dart +++ b/lib/pages/receive_view/receive_view.dart @@ -307,14 +307,20 @@ class _ReceiveViewState extends ConsumerState { if (coin != Coin.epicCash && coin != Coin.ethereum && coin != Coin.banano && - coin != Coin.nano) + coin != Coin.nano && + coin != Coin.stellar && + coin != Coin.stellarTestnet && + coin != Coin.tezos) const SizedBox( height: 12, ), if (coin != Coin.epicCash && coin != Coin.ethereum && coin != Coin.banano && - coin != Coin.nano) + coin != Coin.nano && + coin != Coin.stellar && + coin != Coin.stellarTestnet && + coin != Coin.tezos) TextButton( onPressed: generateNewAddress, style: Theme.of(context) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart index 292517699..22da0f217 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart @@ -219,14 +219,20 @@ class _DesktopReceiveState extends ConsumerState { if (coin != Coin.epicCash && coin != Coin.ethereum && coin != Coin.banano && - coin != Coin.nano) + coin != Coin.nano && + coin != Coin.stellar && + coin != Coin.stellarTestnet && + coin != Coin.tezos) const SizedBox( height: 20, ), if (coin != Coin.epicCash && coin != Coin.ethereum && coin != Coin.banano && - coin != Coin.nano) + coin != Coin.nano && + coin != Coin.stellar && + coin != Coin.stellarTestnet && + coin != Coin.tezos) SecondaryButton( buttonHeight: ButtonHeight.l, onPressed: generateNewAddress, From aec99eada16a16738a947da99c30866908547c6d Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 30 Aug 2023 13:30:41 -0500 Subject: [PATCH 117/237] flutter_libtor->flutter_libarti --- .gitmodules | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 89e91bd22..b7c0ce0f4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,6 @@ [submodule "crypto_plugins/flutter_liblelantus"] path = crypto_plugins/flutter_liblelantus url = https://github.com/cypherstack/flutter_liblelantus.git -[submodule "crypto_plugins/flutter_libtor"] - path = crypto_plugins/flutter_libtor - url = https://github.com/cypherstack/flutter_libtor.git \ No newline at end of file +[submodule "crypto_plugins/flutter_libarti"] + path = crypto_plugins/flutter_libarti + url = https://github.com/cypherstack/flutter_libarti.git From f9be7716e0e8b57df173555158092389b2883d45 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 30 Aug 2023 13:32:01 -0500 Subject: [PATCH 118/237] Removed submodule crypto_plugins/flutter_libtor --- .gitmodules | 2 +- crypto_plugins/flutter_libtor | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 160000 crypto_plugins/flutter_libtor diff --git a/.gitmodules b/.gitmodules index b7c0ce0f4..9eef219ef 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,4 +9,4 @@ url = https://github.com/cypherstack/flutter_liblelantus.git [submodule "crypto_plugins/flutter_libarti"] path = crypto_plugins/flutter_libarti - url = https://github.com/cypherstack/flutter_libarti.git + url = https://github.com/cypherstack/flutter_libarti.git \ No newline at end of file diff --git a/crypto_plugins/flutter_libtor b/crypto_plugins/flutter_libtor deleted file mode 160000 index fc91c3f42..000000000 --- a/crypto_plugins/flutter_libtor +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fc91c3f421467545f198d95558848e94de2fa6d9 From 662602bd2bbdcbe405cc0a56d83149c3cfe978dc Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 1 Sep 2023 17:46:42 -0500 Subject: [PATCH 119/237] use flutter_libarti main now even newer and better --- crypto_plugins/flutter_libarti | 1 + lib/networking/tor_service.dart | 2 +- linux/CMakeLists.txt | 2 +- linux/flutter/generated_plugins.cmake | 2 +- pubspec.lock | 42 ++++++++++++------------- pubspec.yaml | 4 +-- scripts/linux/build_all.sh | 2 +- windows/flutter/generated_plugins.cmake | 2 +- 8 files changed, 29 insertions(+), 28 deletions(-) create mode 160000 crypto_plugins/flutter_libarti diff --git a/crypto_plugins/flutter_libarti b/crypto_plugins/flutter_libarti new file mode 160000 index 000000000..4c9ad3036 --- /dev/null +++ b/crypto_plugins/flutter_libarti @@ -0,0 +1 @@ +Subproject commit 4c9ad30368ce48faad9e40c4d972df3f44877d4f diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart index 7085f5401..0412440d2 100644 --- a/lib/networking/tor_service.dart +++ b/lib/networking/tor_service.dart @@ -1,4 +1,4 @@ -import 'package:flutter_libtor/flutter_libtor.dart'; +import 'package:flutter_libarti/flutter_libarti.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 18faa3a02..026ef6c85 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -146,7 +146,7 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/linux/build/libmobileliblelantus.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libtor/scripts/linux/build/libtor_ffi.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libarti/scripts/linux/build/libtor_ffi.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1.7.4" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 80415b7fc..6143e5daf 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -15,7 +15,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - flutter_libtor + flutter_libarti ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/pubspec.lock b/pubspec.lock index b50a60636..7d2594778 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -534,10 +534,10 @@ packages: dependency: "direct main" description: name: ffi - sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.0" file: dependency: transitive description: @@ -596,6 +596,13 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.1" + flutter_libarti: + dependency: "direct main" + description: + path: "crypto_plugins/flutter_libarti" + relative: true + source: path + version: "0.0.2" flutter_libepiccash: dependency: "direct main" description: @@ -610,13 +617,6 @@ packages: relative: true source: path version: "0.0.1" - flutter_libtor: - dependency: "direct main" - description: - path: "crypto_plugins/flutter_libtor" - relative: true - source: path - version: "0.0.2" flutter_lints: dependency: "direct dev" description: @@ -1144,50 +1144,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" url: "https://pub.dev" source: hosted - version: "2.0.27" + version: "2.2.0" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.11" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" permission_handler: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 79b140414..0298b014e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -57,8 +57,8 @@ dependencies: url: https://github.com/cypherstack/bip47.git ref: 081ca1863c2feba00c35bb5b297902f12f499941 - flutter_libtor: - path: ./crypto_plugins/flutter_libtor + flutter_libarti: + path: ./crypto_plugins/flutter_libarti # Utility plugins http: ^0.13.0 diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh index 1ba99c0bd..bd6efaa65 100755 --- a/scripts/linux/build_all.sh +++ b/scripts/linux/build_all.sh @@ -9,7 +9,7 @@ mkdir -p build (cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_monero_all.sh && ./build_sharedfile.sh ) & -(cd ../../crypto_plugins/flutter_libtor/scripts/linux && ./build_all.sh ) & +(cd ../../crypto_plugins/flutter_libarti/scripts/linux && ./build_all.sh ) & wait echo "Done building" diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 05f6f6f03..a73555e77 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -16,7 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - flutter_libtor + flutter_libarti ) set(PLUGIN_BUNDLED_LIBRARIES) From f6a0950c24fe9e55dbd4f6b202f644202eadde7b Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Fri, 1 Sep 2023 16:50:17 -0600 Subject: [PATCH 120/237] WIP: tor settings view for mobile --- assets/svg/tor-synced.svg | 4 + assets/svg/tor-syncing.svg | 4 + assets/svg/tor.svg | 4 + .../global_settings_view.dart | 13 ++ .../tor_settings/tor_settings_view.dart | 200 ++++++++++++++++++ lib/route_generator.dart | 7 + lib/utilities/assets.dart | 3 + lib/utilities/prefs.dart | 22 ++ pubspec.yaml | 3 + 9 files changed, 260 insertions(+) create mode 100644 assets/svg/tor-synced.svg create mode 100644 assets/svg/tor-syncing.svg create mode 100644 assets/svg/tor.svg create mode 100644 lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart diff --git a/assets/svg/tor-synced.svg b/assets/svg/tor-synced.svg new file mode 100644 index 000000000..20cff1f37 --- /dev/null +++ b/assets/svg/tor-synced.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svg/tor-syncing.svg b/assets/svg/tor-syncing.svg new file mode 100644 index 000000000..b51803c70 --- /dev/null +++ b/assets/svg/tor-syncing.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svg/tor.svg b/assets/svg/tor.svg new file mode 100644 index 000000000..a893c0907 --- /dev/null +++ b/assets/svg/tor.svg @@ -0,0 +1,4 @@ + + + + diff --git a/lib/pages/settings_views/global_settings_view/global_settings_view.dart b/lib/pages/settings_views/global_settings_view/global_settings_view.dart index 7cadc1a77..29984b928 100644 --- a/lib/pages/settings_views/global_settings_view/global_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/global_settings_view.dart @@ -25,6 +25,7 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back import 'package:stackwallet/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/support_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages/settings_views/sub_widgets/settings_list_button.dart'; import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/themes/stack_colors.dart'; @@ -159,6 +160,18 @@ class GlobalSettingsView extends StatelessWidget { const SizedBox( height: 8, ), + SettingsListButton( + iconAssetName: Assets.svg.tor, + iconSize: 18, + title: "Tor Settings", + onPressed: () { + Navigator.of(context) + .pushNamed(TorSettingsView.routeName); + }, + ), + const SizedBox( + height: 8, + ), SettingsListButton( iconAssetName: Assets.svg.node, iconSize: 16, diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart new file mode 100644 index 000000000..d97cb34e2 --- /dev/null +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -0,0 +1,200 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/background.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; +import 'package:stackwallet/widgets/stack_dialog.dart'; + +class TorSettingsView extends ConsumerStatefulWidget { + const TorSettingsView({Key? key}) : super(key: key); + + static const String routeName = "/torSettings"; + + @override + ConsumerState createState() => _TorSettingsViewState(); +} + +class _TorSettingsViewState extends ConsumerState { + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final isDesktop = Util.isDesktop; + + return Background( + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + automaticallyImplyLeading: false, + backgroundColor: + Theme.of(context).extension()!.backgroundAppBar, + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Tor Settings", + style: STextStyles.navBarTitle(context), + ), + actions: [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + icon: SvgPicture.asset( + Assets.svg.circleQuestion, + ), + onPressed: () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return const StackDialog( + title: "What is Tor?", + message: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + "Sed sit amet nulla accumsan, ornare felis pellentesque, auctor nulla.", + rightButton: SecondaryButton( + label: "Close", + ), + ); + }, + ); + }, + ), + ), + ], + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(10.0), + child: SvgPicture.asset( + Assets.svg.tor, + height: 200, + width: 200, + ), + ), + ], + ), + SizedBox( + height: 30, + ), + RoundedWhiteContainer( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Row( + children: [ + Text( + "Tor status", + style: STextStyles.titleBold12(context), + ), + const Spacer(), + Text( + "Tor network status", + style: STextStyles.itemSubtitle(context), + ), + ], + ), + ), + ), + SizedBox( + height: 8, + ), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + "Tor killswitch", + style: STextStyles.titleBold12(context), + ), + const SizedBox(width: 8), + SvgPicture.asset( + Assets.svg.circleInfo, + height: 16, + width: 16, + color: Theme.of(context) + .extension()! + .infoItemLabel, + ), + ], + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider + .select((value) => value.torKillswitch), + ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .torKillswitch = newValue; + }, + ), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 344eb7876..4f18b32d4 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -110,6 +110,7 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/support_vi import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_view.dart'; @@ -654,6 +655,12 @@ class RouteGenerator { builder: (_) => const LanguageSettingsView(), settings: RouteSettings(name: settings.name)); + case TorSettingsView.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const TorSettingsView(), + settings: RouteSettings(name: settings.name)); + case AboutView.routeName: return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index d1d7a55d8..2e0bd0949 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -92,6 +92,9 @@ class _SVG { final coinControl = const _COIN_CONTROL(); + String get torConnected => "assets/svg/tor-synced.svg"; + String get torConnecting => "assets/svg/tor-syncing.svg"; + String get tor => "assets/svg/tor.svg"; String get monkey => "assets/svg/monkey.svg"; String get circleSliders => "assets/svg/configuration.svg"; String get circlePlus => "assets/svg/plus-circle.svg"; diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index 7c306bfe5..3168d75f2 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -42,6 +42,7 @@ class Prefs extends ChangeNotifier { _lastUnlocked = await _getLastUnlocked(); _lastUnlockedTimeout = await _getLastUnlockedTimeout(); _showTestNetCoins = await _getShowTestNetCoins(); + _torKillswitch = await _getTorKillswitch(); _isAutoBackupEnabled = await _getIsAutoBackupEnabled(); _autoBackupLocation = await _getAutoBackupLocation(); _backupFrequencyType = await _getBackupFrequencyType(); @@ -393,6 +394,27 @@ class Prefs extends ChangeNotifier { 0; } + // tor + + bool _torKillswitch = false; + + bool get torKillswitch => _torKillswitch; + + set torKillswitch(bool torKillswitch) { + if (_torKillswitch != showTestNetCoins) { + DB.instance.put( + boxName: DB.boxNamePrefs, key: "torKillswitch", value: torKillswitch); + _torKillswitch = torKillswitch; + notifyListeners(); + } + } + + Future _getTorKillswitch() async { + return await DB.instance.get( + boxName: DB.boxNamePrefs, key: "torKillswitch") as bool? ?? + false; + } + // show testnet coins bool _showTestNetCoins = false; diff --git a/pubspec.yaml b/pubspec.yaml index dbb5ecfe5..7d69fdab6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -342,6 +342,9 @@ flutter: - assets/svg/send.svg - assets/svg/ordinal.svg - assets/svg/monkey.svg + - assets/svg/tor.svg + - assets/svg/tor-syncing.svg + - assets/svg/tor-synced.svg # coin control icons - assets/svg/coin_control/ From 0ce108aa349aa73bf9cdfe552c3f9fe76d753dd4 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 4 Sep 2023 20:13:05 -0500 Subject: [PATCH 121/237] use cypherstack/tor, a Foundation-Devices/tor fork use main --- .gitmodules | 6 +++--- crypto_plugins/flutter_libarti | 1 - crypto_plugins/tor | 1 + lib/networking/tor_service.dart | 2 +- linux/flutter/generated_plugins.cmake | 2 +- pubspec.yaml | 4 ++-- scripts/linux/build_all.sh | 2 +- windows/flutter/generated_plugins.cmake | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) delete mode 160000 crypto_plugins/flutter_libarti create mode 160000 crypto_plugins/tor diff --git a/.gitmodules b/.gitmodules index 9eef219ef..eb71f2df5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,6 @@ [submodule "crypto_plugins/flutter_liblelantus"] path = crypto_plugins/flutter_liblelantus url = https://github.com/cypherstack/flutter_liblelantus.git -[submodule "crypto_plugins/flutter_libarti"] - path = crypto_plugins/flutter_libarti - url = https://github.com/cypherstack/flutter_libarti.git \ No newline at end of file +[submodule "crypto_plugins/tor"] + path = crypto_plugins/tor + url = https://github.com/cypherstack/tor.git \ No newline at end of file diff --git a/crypto_plugins/flutter_libarti b/crypto_plugins/flutter_libarti deleted file mode 160000 index 4c9ad3036..000000000 --- a/crypto_plugins/flutter_libarti +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4c9ad30368ce48faad9e40c4d972df3f44877d4f diff --git a/crypto_plugins/tor b/crypto_plugins/tor new file mode 160000 index 000000000..76c2c70a4 --- /dev/null +++ b/crypto_plugins/tor @@ -0,0 +1 @@ +Subproject commit 76c2c70a4c3601cab5fad4faaa1705374df0dd59 diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart index 0412440d2..3eb6e4961 100644 --- a/lib/networking/tor_service.dart +++ b/lib/networking/tor_service.dart @@ -1,4 +1,4 @@ -import 'package:flutter_libarti/flutter_libarti.dart'; +import 'package:tor/tor.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 6143e5daf..397cac07d 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -15,7 +15,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - flutter_libarti + tor ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/pubspec.yaml b/pubspec.yaml index 0298b014e..eabf29e50 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -57,8 +57,8 @@ dependencies: url: https://github.com/cypherstack/bip47.git ref: 081ca1863c2feba00c35bb5b297902f12f499941 - flutter_libarti: - path: ./crypto_plugins/flutter_libarti + tor: + path: ./crypto_plugins/tor # Utility plugins http: ^0.13.0 diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh index bd6efaa65..9a119d0d6 100755 --- a/scripts/linux/build_all.sh +++ b/scripts/linux/build_all.sh @@ -9,7 +9,7 @@ mkdir -p build (cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_monero_all.sh && ./build_sharedfile.sh ) & -(cd ../../crypto_plugins/flutter_libarti/scripts/linux && ./build_all.sh ) & +(cd ../../crypto_plugins/tor/scripts/linux && ./build_all.sh ) & wait echo "Done building" diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index a73555e77..934f038bc 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -16,7 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - flutter_libarti + tor ) set(PLUGIN_BUNDLED_LIBRARIES) From ca95612d69a5b90752e2cd1fe49a799cc9dde296 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 5 Sep 2023 10:19:58 -0600 Subject: [PATCH 122/237] fix firo lelantus sends to non wallet addresses not showing as confirmed in wallet ui --- lib/services/coins/firo/firo_wallet.dart | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart index d58cf4402..d765f8d0f 100644 --- a/lib/services/coins/firo/firo_wallet.dart +++ b/lib/services/coins/firo/firo_wallet.dart @@ -3352,6 +3352,30 @@ class FiroWallet extends CoinServiceAPI List> allTransactions = []; + // some lelantus transactions aren't fetched via wallet addresses so they + // will never show as confirmed in the gui. + final unconfirmedTransactions = + await db.getTransactions(walletId).filter().heightIsNull().findAll(); + for (final tx in unconfirmedTransactions) { + final txn = await cachedElectrumXClient.getTransaction( + txHash: tx.txid, + verbose: true, + coin: coin, + ); + final height = txn["height"] as int?; + + if (height != null) { + // tx was mined + // add to allTxHashes + final info = { + "tx_hash": tx.txid, + "height": height, + "address": tx.address.value?.value, + }; + allTxHashes.add(info); + } + } + // final currentHeight = await chainHeight; for (final txHash in allTxHashes) { From 9237e99f0c0e85049b0947d5595ae060344c0247 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 5 Sep 2023 11:53:44 -0600 Subject: [PATCH 123/237] clean up hidden settings --- .../global_settings_view/hidden_settings.dart | 142 +++++++++--------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/hidden_settings.dart b/lib/pages/settings_views/global_settings_view/hidden_settings.dart index 4e42e3733..52a523f22 100644 --- a/lib/pages/settings_views/global_settings_view/hidden_settings.dart +++ b/lib/pages/settings_views/global_settings_view/hidden_settings.dart @@ -167,77 +167,77 @@ class HiddenSettings extends StatelessWidget { // ), // ); // }), - const SizedBox( - height: 12, - ), - Consumer(builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - ref - .read(priceAnd24hChangeNotifierProvider) - .tokenContractAddressesToCheck - .add( - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); - ref - .read(priceAnd24hChangeNotifierProvider) - .tokenContractAddressesToCheck - .add( - "0xdAC17F958D2ee523a2206206994597C13D831ec7"); - await ref - .read(priceAnd24hChangeNotifierProvider) - .updatePrice(); - - final x = ref - .read(priceAnd24hChangeNotifierProvider) - .getTokenPrice( - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); - - print( - "PRICE 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48: $x"); - }, - child: RoundedWhiteContainer( - child: Text( - "Click me", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark), - ), - ), - ); - }), - const SizedBox( - height: 12, - ), - Consumer(builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - // final erc20 = Erc20ContractInfo( - // contractAddress: 'some con', - // name: "loonamsn", - // symbol: "DD", - // decimals: 19, - // ); - // - // final json = erc20.toJson(); - // - // print(json); - // - // final ee = EthContractInfo.fromJson(json); - // - // print(ee); - }, - child: RoundedWhiteContainer( - child: Text( - "Click me", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark), - ), - ), - ); - }), + // const SizedBox( + // height: 12, + // ), + // Consumer(builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // ref + // .read(priceAnd24hChangeNotifierProvider) + // .tokenContractAddressesToCheck + // .add( + // "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); + // ref + // .read(priceAnd24hChangeNotifierProvider) + // .tokenContractAddressesToCheck + // .add( + // "0xdAC17F958D2ee523a2206206994597C13D831ec7"); + // await ref + // .read(priceAnd24hChangeNotifierProvider) + // .updatePrice(); + // + // final x = ref + // .read(priceAnd24hChangeNotifierProvider) + // .getTokenPrice( + // "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); + // + // print( + // "PRICE 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48: $x"); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Click me", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark), + // ), + // ), + // ); + // }), + // const SizedBox( + // height: 12, + // ), + // Consumer(builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // // final erc20 = Erc20ContractInfo( + // // contractAddress: 'some con', + // // name: "loonamsn", + // // symbol: "DD", + // // decimals: 19, + // // ); + // // + // // final json = erc20.toJson(); + // // + // // print(json); + // // + // // final ee = EthContractInfo.fromJson(json); + // // + // // print(ee); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Click me", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark), + // ), + // ), + // ); + // }), const SizedBox( height: 12, ), From 7072c919ae40dd76392cd0bcae82fdceea48909f Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Tue, 5 Sep 2023 13:11:08 -0600 Subject: [PATCH 124/237] WIP: add tor to home page --- lib/pages/home_view/home_view.dart | 69 +++++++++++++++++++ .../tor_sync_status_changed_event.dart | 22 ++++++ 2 files changed, 91 insertions(+) create mode 100644 lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index c3cad7a97..be1597adb 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -17,9 +17,11 @@ import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages/buy_view/buy_view.dart'; import 'package:stackwallet/pages/exchange_view/exchange_view.dart'; import 'package:stackwallet/pages/home_view/sub_widgets/home_view_button_bar.dart'; +import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart'; import 'package:stackwallet/pages/notification_views/notifications_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/global_settings_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/hidden_settings.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages/wallets_view/wallets_view.dart'; import 'package:stackwallet/providers/global/notifications_provider.dart'; import 'package:stackwallet/providers/ui/home_view_index_provider.dart'; @@ -55,6 +57,8 @@ class _HomeViewState extends ConsumerState { bool _exitEnabled = false; + late TorSyncStatus _currentSyncStatus; + // final _buyDataLoadingService = BuyDataLoadingService(); Future _onWillPop() async { @@ -113,6 +117,32 @@ class _HomeViewState extends ConsumerState { ); } + Widget _buildTorIcon(TorSyncStatus status) { + switch (status) { + case TorSyncStatus.unableToSync: + return SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context).extension()!.accentColorRed, + width: 20, + height: 20, + ); + case TorSyncStatus.synced: + return SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context).extension()!.accentColorGreen, + width: 20, + height: 20, + ); + case TorSyncStatus.syncing: + return SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context).extension()!.accentColorYellow, + width: 20, + height: 20, + ); + } + } + @override void initState() { _pageController = PageController(); @@ -125,6 +155,20 @@ class _HomeViewState extends ConsumerState { ref.read(notificationsProvider).startCheckingWatchedNotifications(); + /// todo change to watch tor network + // if (ref.read(managerProvider).isRefreshing) { + // _currentSyncStatus = WalletSyncStatus.syncing; + // _currentNodeStatus = NodeConnectionStatus.connected; + // } else { + // _currentSyncStatus = WalletSyncStatus.synced; + // if (ref.read(managerProvider).isConnected) { + // _currentNodeStatus = NodeConnectionStatus.connected; + // } else { + // _currentNodeStatus = NodeConnectionStatus.disconnected; + // _currentSyncStatus = WalletSyncStatus.unableToSync; + // } + // } + super.initState(); } @@ -200,6 +244,31 @@ class _HomeViewState extends ConsumerState { ], ), actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + semanticsLabel: + "Tor Settings Button. Takes To Tor Settings Page.", + key: const Key("walletsViewTorButton"), + size: 36, + shadows: const [], + color: Theme.of(context) + .extension()! + .backgroundAppBar, + icon: _buildTorIcon(TorSyncStatus.syncing), + onPressed: () { + Navigator.of(context) + .pushNamed(TorSettingsView.routeName); + }, + ), + ), + ), Padding( padding: const EdgeInsets.only( top: 10, diff --git a/lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart b/lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart new file mode 100644 index 000000000..87910b806 --- /dev/null +++ b/lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart @@ -0,0 +1,22 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ +import 'package:stackwallet/utilities/logger.dart'; + +enum TorSyncStatus { unableToSync, synced, syncing } + +class TorSyncStatusChangedEvent { + TorSyncStatus newStatus; + + TorSyncStatusChangedEvent(this.newStatus) { + Logging.instance.log( + "TorSyncStatusChangedEvent fired with arg newStatus = $newStatus", + level: LogLevel.Info); + } +} From fcf98d8096586c69fb3cf28bc10b944096bdd6ba Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Tue, 5 Sep 2023 13:39:57 -0600 Subject: [PATCH 125/237] WIP: add tor settings to desktop --- .../settings/desktop_settings_view.dart | 6 ++++++ lib/pages_desktop_specific/settings/settings_menu.dart | 1 + 2 files changed, 7 insertions(+) diff --git a/lib/pages_desktop_specific/settings/desktop_settings_view.dart b/lib/pages_desktop_specific/settings/desktop_settings_view.dart index 2a8c180f9..e1920aa0b 100644 --- a/lib/pages_desktop_specific/settings/desktop_settings_view.dart +++ b/lib/pages_desktop_specific/settings/desktop_settings_view.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/appearance_settings/appearance_settings.dart'; @@ -56,6 +57,11 @@ class _DesktopSettingsViewState extends ConsumerState { key: Key("settingsLanguageDesktopKey"), onGenerateRoute: RouteGenerator.generateRoute, initialRoute: LanguageOptionSettings.routeName, + ), + const Navigator( + key: Key("settingsTorDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: TorSettingsView.routeName, ), //language const Navigator( key: Key("settingsNodesDesktopKey"), diff --git a/lib/pages_desktop_specific/settings/settings_menu.dart b/lib/pages_desktop_specific/settings/settings_menu.dart index 4f3175a72..ba2c21781 100644 --- a/lib/pages_desktop_specific/settings/settings_menu.dart +++ b/lib/pages_desktop_specific/settings/settings_menu.dart @@ -32,6 +32,7 @@ class _SettingsMenuState extends ConsumerState { "Security", "Currency", "Language", + "Tor settings", "Nodes", "Syncing preferences", "Appearance", From 1dea6cdb7da09e797a42696b539e6d9e51f2053d Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Tue, 5 Sep 2023 16:26:52 -0600 Subject: [PATCH 126/237] rough ui for desktop tor settings + svgs for tor settings --- assets/svg/connected-button.svg | 4 + assets/svg/connecting-button.svg | 4 + assets/svg/disconnected-button.svg | 4 + assets/svg/tor-circle.svg | 5 + .../tor_settings/tor_settings_view.dart | 2 +- .../settings/desktop_settings_view.dart | 6 +- .../tor_settings/tor_settings.dart | 181 ++++++++++++++++++ lib/route_generator.dart | 7 + lib/utilities/assets.dart | 6 +- pubspec.yaml | 6 +- 10 files changed, 217 insertions(+), 8 deletions(-) create mode 100644 assets/svg/connected-button.svg create mode 100644 assets/svg/connecting-button.svg create mode 100644 assets/svg/disconnected-button.svg create mode 100644 assets/svg/tor-circle.svg create mode 100644 lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart diff --git a/assets/svg/connected-button.svg b/assets/svg/connected-button.svg new file mode 100644 index 000000000..96a9970c0 --- /dev/null +++ b/assets/svg/connected-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svg/connecting-button.svg b/assets/svg/connecting-button.svg new file mode 100644 index 000000000..1bc6e953b --- /dev/null +++ b/assets/svg/connecting-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svg/disconnected-button.svg b/assets/svg/disconnected-button.svg new file mode 100644 index 000000000..03a8067d7 --- /dev/null +++ b/assets/svg/disconnected-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svg/tor-circle.svg b/assets/svg/tor-circle.svg new file mode 100644 index 000000000..8268a00f6 --- /dev/null +++ b/assets/svg/tor-circle.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index d97cb34e2..406f7ebf4 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -61,7 +61,7 @@ class _TorSettingsViewState extends ConsumerState { }, ), title: Text( - "Tor Settings", + "Tor settings", style: STextStyles.navBarTitle(context), ), actions: [ diff --git a/lib/pages_desktop_specific/settings/desktop_settings_view.dart b/lib/pages_desktop_specific/settings/desktop_settings_view.dart index e1920aa0b..6a785fc8a 100644 --- a/lib/pages_desktop_specific/settings/desktop_settings_view.dart +++ b/lib/pages_desktop_specific/settings/desktop_settings_view.dart @@ -10,7 +10,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/appearance_settings/appearance_settings.dart'; @@ -20,6 +19,7 @@ import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/langua import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/nodes_settings.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/security_settings.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/syncing_preferences_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart'; import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/text_styles.dart'; @@ -61,8 +61,8 @@ class _DesktopSettingsViewState extends ConsumerState { const Navigator( key: Key("settingsTorDesktopKey"), onGenerateRoute: RouteGenerator.generateRoute, - initialRoute: TorSettingsView.routeName, - ), //language + initialRoute: TorSettings.routeName, + ), //tor const Navigator( key: Key("settingsNodesDesktopKey"), onGenerateRoute: RouteGenerator.generateRoute, diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart new file mode 100644 index 000000000..6a8a8e8c8 --- /dev/null +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -0,0 +1,181 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +import '../../../../providers/global/prefs_provider.dart'; +import '../../../../themes/stack_colors.dart'; +import '../../../../widgets/custom_buttons/draggable_switch_button.dart'; + +class TorSettings extends ConsumerStatefulWidget { + const TorSettings({Key? key}) : super(key: key); + + static const String routeName = "/torDesktopSettings"; + + @override + ConsumerState createState() => _TorSettingsState(); +} + +class _TorSettingsState extends ConsumerState { + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final isDesktop = Util.isDesktop; + + return Column( + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + Assets.svg.circleTor, + width: 48, + height: 48, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + Assets.svg.disconnectedButton, + width: 48, + height: 48, + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Tor settings", + style: STextStyles.desktopTextSmall(context), + ), + RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: + "\nConnect to the Tor Network with one click.", + style: STextStyles.desktopTextExtraExtraSmall( + context), + ), + TextSpan( + text: "\tWhat is Tor?", + style: STextStyles.richLink(context).copyWith( + fontSize: 14, + ), + recognizer: TapGestureRecognizer()..onTap = () {}, + ), + ], + ), + ), + ], + ), + ), + const SizedBox( + height: 20, + ), + SecondaryButton( + label: "Disconnect from Tor", + width: 200, + buttonHeight: ButtonHeight.m, + onPressed: () {}, + ), + const SizedBox( + height: 40, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Tor killswitch", + style: STextStyles.desktopTextExtraExtraSmall( + context) + .copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + TextSpan( + text: "\nWhat is Tor killswitch?", + style: STextStyles.richLink(context).copyWith( + fontSize: 14, + ), + recognizer: TapGestureRecognizer() + ..onTap = () {}, + ), + ], + ), + ), + ], + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider + .select((value) => value.torKillswitch), + ), + onValueChanged: (newValue) { + ref.read(prefsChangeNotifierProvider).torKillswitch = + newValue; + }, + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 4f18b32d4..38604bc33 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -167,6 +167,7 @@ import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/langua import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/nodes_settings.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/security_settings.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/syncing_preferences_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart'; import 'package:stackwallet/services/coins/manager.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; @@ -661,6 +662,12 @@ class RouteGenerator { builder: (_) => const TorSettingsView(), settings: RouteSettings(name: settings.name)); + case TorSettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const TorSettings(), + settings: RouteSettings(name: settings.name)); + case AboutView.routeName: return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index 2e0bd0949..9880e12c5 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -92,8 +92,10 @@ class _SVG { final coinControl = const _COIN_CONTROL(); - String get torConnected => "assets/svg/tor-synced.svg"; - String get torConnecting => "assets/svg/tor-syncing.svg"; + String get connectedButton => "assets/svg/connected-button.svg"; + String get connectingButton => "assets/svg/connecting-button.svg"; + String get disconnectedButton => "assets/svg/disconnected-button.svg"; + String get circleTor => "assets/svg/tor-circle.svg"; String get tor => "assets/svg/tor.svg"; String get monkey => "assets/svg/monkey.svg"; String get circleSliders => "assets/svg/configuration.svg"; diff --git a/pubspec.yaml b/pubspec.yaml index 7d69fdab6..0a52e183c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -343,8 +343,10 @@ flutter: - assets/svg/ordinal.svg - assets/svg/monkey.svg - assets/svg/tor.svg - - assets/svg/tor-syncing.svg - - assets/svg/tor-synced.svg + - assets/svg/tor-circle.svg + - assets/svg/connected-button.svg + - assets/svg/connecting-button.svg + - assets/svg/disconnected-button.svg # coin control icons - assets/svg/coin_control/ From 2fc116707b261cbbe0c2b5bb86aca58290c575eb Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Tue, 5 Sep 2023 16:34:53 -0600 Subject: [PATCH 127/237] adjust padding --- .../tor_settings/tor_settings.dart | 109 ++++++++++-------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index 6a8a8e8c8..3a1e4dd81 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -46,6 +46,7 @@ class _TorSettingsState extends ConsumerState { Widget build(BuildContext context) { final isDesktop = Util.isDesktop; + /// todo: redo the padding return Column( children: [ Padding( @@ -110,63 +111,73 @@ class _TorSettingsState extends ConsumerState { ), ), const SizedBox( - height: 20, + height: 10, ), - SecondaryButton( - label: "Disconnect from Tor", - width: 200, - buttonHeight: ButtonHeight.m, - onPressed: () {}, + Padding( + padding: const EdgeInsets.all(10.0), + child: SecondaryButton( + label: "Disconnect from Tor", + width: 200, + buttonHeight: ButtonHeight.m, + onPressed: () {}, + ), ), const SizedBox( - height: 40, + height: 30, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - RichText( - textAlign: TextAlign.start, - text: TextSpan( - children: [ - TextSpan( - text: "Tor killswitch", - style: STextStyles.desktopTextExtraExtraSmall( - context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark), - ), - TextSpan( - text: "\nWhat is Tor killswitch?", - style: STextStyles.richLink(context).copyWith( - fontSize: 14, + Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Tor killswitch", + style: STextStyles.desktopTextExtraExtraSmall( + context) + .copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), ), - recognizer: TapGestureRecognizer() - ..onTap = () {}, - ), - ], + TextSpan( + text: "\nWhat is Tor killswitch?", + style: STextStyles.richLink(context).copyWith( + fontSize: 14, + ), + recognizer: TapGestureRecognizer() + ..onTap = () {}, + ), + ], + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider + .select((value) => value.torKillswitch), + ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .torKillswitch = newValue; + }, ), ), - ], - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.torKillswitch), - ), - onValueChanged: (newValue) { - ref.read(prefsChangeNotifierProvider).torKillswitch = - newValue; - }, ), - ), - ], + ], + ), ), const SizedBox( height: 10, From 1a20029c18710267d213991314b3f28a58c3639b Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Tue, 5 Sep 2023 16:55:54 -0600 Subject: [PATCH 128/237] add dialogs to tor settings --- .../tor_settings/tor_settings.dart | 126 +++++++++++++++++- 1 file changed, 124 insertions(+), 2 deletions(-) diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index 3a1e4dd81..d4c0b3a53 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -15,6 +15,8 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; @@ -102,7 +104,66 @@ class _TorSettingsState extends ConsumerState { style: STextStyles.richLink(context).copyWith( fontSize: 14, ), - recognizer: TapGestureRecognizer()..onTap = () {}, + recognizer: TapGestureRecognizer() + ..onTap = () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + DesktopDialogCloseButton( + onPressedOverride: () => + Navigator.of(context) + .pop(true), + ), + ], + ), + Padding( + padding: + const EdgeInsets.all(20), + child: Column( + mainAxisSize: + MainAxisSize.max, + children: [ + Text( + "What is Tor?", + style: + STextStyles.desktopH2( + context), + ), + const SizedBox( + height: 20, + ), + Text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + "Sed sit amet nulla accumsan, ornare felis pellentesque, auctor nulla.", + style: STextStyles + .desktopTextMedium( + context) + .copyWith( + color: Theme.of(context) + .extension< + StackColors>()! + .textDark3, + ), + ), + ], + ), + ), + ], + ), + ); + }); + }, ), ], ), @@ -151,7 +212,68 @@ class _TorSettingsState extends ConsumerState { fontSize: 14, ), recognizer: TapGestureRecognizer() - ..onTap = () {}, + ..onTap = () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + DesktopDialogCloseButton( + onPressedOverride: () => + Navigator.of( + context) + .pop(true), + ), + ], + ), + Padding( + padding: + const EdgeInsets.all( + 20), + child: Column( + mainAxisSize: + MainAxisSize.max, + children: [ + Text( + "What is Tor killswitch?", + style: STextStyles + .desktopH2( + context), + ), + const SizedBox( + height: 20, + ), + Text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + "Sed sit amet nulla accumsan, ornare felis pellentesque, auctor nulla.", + style: STextStyles + .desktopTextMedium( + context) + .copyWith( + color: Theme.of( + context) + .extension< + StackColors>()! + .textDark3, + ), + ), + ], + ), + ), + ], + ), + ); + }); + }, ), ], ), From d560a3094195619ee3d66a71804bb51b2ccc0de5 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Tue, 5 Sep 2023 16:56:56 -0600 Subject: [PATCH 129/237] add dialogs to tor settings --- .../tor_settings/tor_settings_view.dart | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 406f7ebf4..43efc48d5 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -159,13 +159,33 @@ class _TorSettingsViewState extends ConsumerState { style: STextStyles.titleBold12(context), ), const SizedBox(width: 8), - SvgPicture.asset( - Assets.svg.circleInfo, - height: 16, - width: 16, - color: Theme.of(context) - .extension()! - .infoItemLabel, + GestureDetector( + onTap: () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return const StackDialog( + title: "What is Tor killswitch?", + message: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + "Sed sit amet nulla accumsan, ornare felis pellentesque, auctor nulla.", + rightButton: SecondaryButton( + label: "Close", + ), + ); + }, + ); + }, + child: SvgPicture.asset( + Assets.svg.circleInfo, + height: 16, + width: 16, + color: Theme.of(context) + .extension()! + .infoItemLabel, + ), ), ], ), From 41e3c2371dcd08e186bc666764e0405f9da3386d Mon Sep 17 00:00:00 2001 From: likho Date: Wed, 6 Sep 2023 15:18:23 +0200 Subject: [PATCH 130/237] Fix HTTP send error --- lib/services/coins/epiccash/epiccash_wallet.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index 9d25a5a47..578638b5f 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -176,7 +176,7 @@ Future executeNative(Map arguments) async { final selectionStrategyIsAll = arguments['selectionStrategyIsAll'] as int?; final minimumConfirmations = arguments['minimumConfirmations'] as int?; - final message = arguments['onChainNote'] as String?; + final message = arguments['message'] as String?; final amount = arguments['amount'] as int?; final address = arguments['address'] as String?; @@ -1727,7 +1727,6 @@ class EpicCashWallet extends CoinServiceAPI String? commitId = slatesToCommits[slateId]?['commitId'] as String?; tx['numberOfMessages'] = tx['messages']?['messages']?.length; tx['onChainNote'] = tx['messages']?['messages']?[0]?['message']; - print("ON CHAIN MESSAGE IS ${tx['onChainNote']}"); int? height; From 150ccdf57d3e67f5e4e8f07ffafb5c063763c429 Mon Sep 17 00:00:00 2001 From: likho Date: Wed, 6 Sep 2023 18:26:31 +0200 Subject: [PATCH 131/237] Return more descriptive error for http send --- lib/services/coins/epiccash/epiccash_wallet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index 578638b5f..ba5a7b3f7 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -492,7 +492,7 @@ class EpicCashWallet extends CoinServiceAPI Logging.instance .log("this is a string $message", level: LogLevel.Error); stop(receivePort); - throw Exception("txHttpSend isolate failed"); + throw Exception(message); } stop(receivePort); Logging.instance From c3aaf0574b275eff804c2bbd17a2627036ea7354 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 6 Sep 2023 13:43:09 -0600 Subject: [PATCH 132/237] added information to tor dialogs --- .../tor_settings/tor_settings_view.dart | 10 ++++++---- .../settings_menu/tor_settings/tor_settings.dart | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 43efc48d5..29a53ba7e 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -80,8 +80,9 @@ class _TorSettingsViewState extends ConsumerState { return const StackDialog( title: "What is Tor?", message: - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " - "Sed sit amet nulla accumsan, ornare felis pellentesque, auctor nulla.", + "Short for \"The Onion Router\", is an open-source software that enables internet communication" + " to remain anonymous by routing internet traffic through a series of layered nodes," + " to obscure the origin and destination of data.", rightButton: SecondaryButton( label: "Close", ), @@ -169,8 +170,9 @@ class _TorSettingsViewState extends ConsumerState { return const StackDialog( title: "What is Tor killswitch?", message: - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " - "Sed sit amet nulla accumsan, ornare felis pellentesque, auctor nulla.", + "A security feature that protects your information from accidental exposure by" + " disconnecting your device from the Tor network if your virtual private network (VPN)" + " connection is disrupted or compromised.", rightButton: SecondaryButton( label: "Close", ), diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index d4c0b3a53..e8d4b3f6a 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -144,8 +144,9 @@ class _TorSettingsState extends ConsumerState { height: 20, ), Text( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " - "Sed sit amet nulla accumsan, ornare felis pellentesque, auctor nulla.", + "Short for \"The Onion Router\", is an open-source software that enables internet communication" + " to remain anonymous by routing internet traffic through a series of layered nodes," + " to obscure the origin and destination of data.", style: STextStyles .desktopTextMedium( context) @@ -253,8 +254,9 @@ class _TorSettingsState extends ConsumerState { height: 20, ), Text( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " - "Sed sit amet nulla accumsan, ornare felis pellentesque, auctor nulla.", + "A security feature that protects your information from accidental exposure by" + " disconnecting your device from the Tor network if your virtual private network (VPN)" + " connection is disrupted or compromised.", style: STextStyles .desktopTextMedium( context) From 6377b73deb2b866afe30c2ed459888f6ac3aaba0 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 6 Sep 2023 13:43:55 -0600 Subject: [PATCH 133/237] add tor network status to desktop home --- lib/pages/home_view/home_view.dart | 4 +- lib/pages_desktop_specific/desktop_menu.dart | 82 +++++++++++++++++++- 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index be1597adb..ebd53abdb 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -122,7 +122,7 @@ class _HomeViewState extends ConsumerState { case TorSyncStatus.unableToSync: return SvgPicture.asset( Assets.svg.tor, - color: Theme.of(context).extension()!.accentColorRed, + color: Theme.of(context).extension()!.infoItemLabel, width: 20, height: 20, ); @@ -261,7 +261,7 @@ class _HomeViewState extends ConsumerState { color: Theme.of(context) .extension()! .backgroundAppBar, - icon: _buildTorIcon(TorSyncStatus.syncing), + icon: _buildTorIcon(TorSyncStatus.unableToSync), onPressed: () { Navigator.of(context) .pushNamed(TorSettingsView.routeName); diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index 1a0a1f09f..f89fd3aef 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -14,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart'; import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart'; import 'package:stackwallet/themes/stack_colors.dart'; @@ -57,6 +58,70 @@ class _DesktopMenuState extends ConsumerState { // final _buyDataLoadingService = BuyDataLoadingService(); + Widget _buildTorIcon(TorSyncStatus status) { + switch (status) { + case TorSyncStatus.unableToSync: + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context).extension()!.infoItemLabel, + width: 20, + height: 20, + ), + Text( + "\tDisconnected", + style: STextStyles.smallMed12(context).copyWith( + color: Theme.of(context) + .extension()! + .infoItemLabel), + ) + ], + ); + case TorSyncStatus.synced: + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: + Theme.of(context).extension()!.accentColorGreen, + width: 20, + height: 20, + ), + Text( + "\tConnected", + style: STextStyles.smallMed12(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorGreen), + ) + ], + ); + case TorSyncStatus.syncing: + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: + Theme.of(context).extension()!.accentColorYellow, + width: 20, + height: 20, + ), + Text( + "\tConnecting", + style: STextStyles.smallMed12(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorYellow), + ) + ], + ); + } + } + void updateSelectedMenuItem(DesktopMenuItemId idKey) { widget.onSelectionWillChange?.call(idKey); @@ -140,7 +205,22 @@ class _DesktopMenuState extends ConsumerState { ), ), const SizedBox( - height: 60, + height: 5, + ), + MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + // ref.watch(selectedSettingsMenuItemStateProvider.state).state = + // 4; + // ref.watch(selectedSettingsMenuItemStateProvider.state).state = + // 5; + // Navigator.of(context).pushNamed(DesktopHomeView.routeName); + }, + child: _buildTorIcon(TorSyncStatus.unableToSync)), + ), + const SizedBox( + height: 40, ), Expanded( child: AnimatedContainer( From 7289de016060011d699eb094a3b6e89d6a3f125a Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 6 Sep 2023 14:26:04 -0600 Subject: [PATCH 134/237] minor ui fixes --- lib/pages/home_view/home_view.dart | 2 +- .../tor_settings/tor_settings_view.dart | 33 ++++++++++++++++--- lib/pages_desktop_specific/desktop_menu.dart | 4 +-- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index ebd53abdb..759c7760d 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -122,7 +122,7 @@ class _HomeViewState extends ConsumerState { case TorSyncStatus.unableToSync: return SvgPicture.asset( Assets.svg.tor, - color: Theme.of(context).extension()!.infoItemLabel, + color: Theme.of(context).extension()!.textSubtitle3, width: 20, height: 20, ); diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 29a53ba7e..366aff80a 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -11,6 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; @@ -34,6 +35,32 @@ class TorSettingsView extends ConsumerStatefulWidget { } class _TorSettingsViewState extends ConsumerState { + Widget _buildTorIcon(TorSyncStatus status) { + switch (status) { + case TorSyncStatus.unableToSync: + return SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context).extension()!.textSubtitle3, + width: 200, + height: 200, + ); + case TorSyncStatus.synced: + return SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context).extension()!.accentColorGreen, + width: 200, + height: 200, + ); + case TorSyncStatus.syncing: + return SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context).extension()!.accentColorYellow, + width: 200, + height: 200, + ); + } + } + @override void initState() { super.initState(); @@ -104,11 +131,7 @@ class _TorSettingsViewState extends ConsumerState { children: [ Padding( padding: const EdgeInsets.all(10.0), - child: SvgPicture.asset( - Assets.svg.tor, - height: 200, - width: 200, - ), + child: _buildTorIcon(TorSyncStatus.unableToSync), ), ], ), diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index f89fd3aef..6e0b38c65 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -66,7 +66,7 @@ class _DesktopMenuState extends ConsumerState { children: [ SvgPicture.asset( Assets.svg.tor, - color: Theme.of(context).extension()!.infoItemLabel, + color: Theme.of(context).extension()!.textSubtitle3, width: 20, height: 20, ), @@ -75,7 +75,7 @@ class _DesktopMenuState extends ConsumerState { style: STextStyles.smallMed12(context).copyWith( color: Theme.of(context) .extension()! - .infoItemLabel), + .textSubtitle3), ) ], ); From ce34c9709b968c6ae5c87d9a8a484a7520ef45db Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 6 Sep 2023 15:42:01 -0500 Subject: [PATCH 135/237] use cypherstack/tor#staging with ssl socks5 proxy socket example --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 76c2c70a4..5c14a4397 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 76c2c70a4c3601cab5fad4faaa1705374df0dd59 +Subproject commit 5c14a4397c6c1344d09bbe650f2c14a640c768d8 From e6e5c43f69b6e641da517e95b9402f86d52dbb62 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 6 Sep 2023 16:56:18 -0500 Subject: [PATCH 136/237] use updated tor correctly --- lib/networking/tor_service.dart | 4 ++-- linux/CMakeLists.txt | 2 +- linux/flutter/generated_plugins.cmake | 1 - pubspec.lock | 14 +++++++------- windows/flutter/generated_plugins.cmake | 1 - 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart index 3eb6e4961..35df3509c 100644 --- a/lib/networking/tor_service.dart +++ b/lib/networking/tor_service.dart @@ -1,6 +1,6 @@ -import 'package:tor/tor.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; +import 'package:tor/tor.dart'; final pTorService = Provider((_) => TorService.sharedInstance); @@ -12,7 +12,7 @@ class TorService { Future start() async { final dir = await StackFileSystem.applicationTorDirectory(); - await _tor.start(torDir: dir); + await _tor.start(); return; } diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 026ef6c85..273f97bc2 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -146,7 +146,7 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/linux/build/libmobileliblelantus.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libarti/scripts/linux/build/libtor_ffi.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/tor/native/tor-ffi/target/x86_64-unknown-linux-gnu/release/libtor_ffi.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1.7.4" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 397cac07d..38eed0699 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -15,7 +15,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - tor ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/pubspec.lock b/pubspec.lock index 7d2594778..f64b6a5c4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -596,13 +596,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.1" - flutter_libarti: - dependency: "direct main" - description: - path: "crypto_plugins/flutter_libarti" - relative: true - source: path - version: "0.0.2" flutter_libepiccash: dependency: "direct main" description: @@ -1602,6 +1595,13 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.1" + tor: + dependency: "direct main" + description: + path: "crypto_plugins/tor" + relative: true + source: path + version: "0.0.1" tuple: dependency: "direct main" description: diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 934f038bc..324c950be 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -16,7 +16,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - tor ) set(PLUGIN_BUNDLED_LIBRARIES) From 7a01682bff7f0e399b90c793db55e75989d26783 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 6 Sep 2023 17:27:59 -0500 Subject: [PATCH 137/237] WIP update SOCKSSocket class --- lib/electrumx_rpc/rpc.dart | 29 ++-- lib/networking/socks_socket.dart | 246 ++++++++++++++++++++++++++++--- 2 files changed, 234 insertions(+), 41 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 1b5a42d42..749dc624f 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -86,7 +86,8 @@ class JsonRPC { _socket!.write('${req.jsonRequest}\r\n'); } if (_socksSocket != null) { - _socksSocket!.socket.writeln('${req.jsonRequest}\r\n'); + _socksSocket!.write('${req.jsonRequest}\r\n\n'); + // _socksSocket!.socket.writeln('${req.jsonRequest}\r\n'); } // TODO different timeout length? @@ -203,27 +204,17 @@ class JsonRPC { "ElectrumX.connect(): no tor proxy info, read $proxyInfo", level: LogLevel.Warning); } - // TODO connect to proxy socket... - // TODO implement ssl over tor - // if (useSSL) { - // _socket = await SecureSocket.connect( - // host, - // port, - // timeout: connectionTimeout, - // onBadCertificate: (_) => true, - // ); // TODO do not automatically trust bad certificates - // final _client = SocksSocket.protected(_socket, type); - // } else { // instantiate a socks socket at localhost and on the port selected by the tor service _socksSocket = await SOCKSSocket.create( proxyHost: InternetAddress.loopbackIPv4.address, proxyPort: TorService.sharedInstance.port, + sslEnabled: useSSL, ); try { Logging.instance.log( - "JsonRPC.connect(): connecting to SOCKS socket at $proxyInfo...", + "JsonRPC.connect(): connecting to SOCKS socket at $proxyInfo (SSL $useSSL)...", level: LogLevel.Info); await _socksSocket?.connect(); @@ -257,12 +248,12 @@ class JsonRPC { "JsonRPC.connect(): failed to connect to tor proxy, $e"); } - // _subscription = _socksSocket!.socket.listen( - // _dataHandler, - // onError: _errorHandler, - // onDone: _doneHandler, - // cancelOnError: true, - // ) as StreamSubscription?; + _subscription = _socksSocket!.socket.listen( + _dataHandler, + onError: _errorHandler, + onDone: _doneHandler, + cancelOnError: true, + ); } } } diff --git a/lib/networking/socks_socket.dart b/lib/networking/socks_socket.dart index 4d66e0357..b469026b6 100644 --- a/lib/networking/socks_socket.dart +++ b/lib/networking/socks_socket.dart @@ -2,110 +2,312 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +/// A SOCKS5 socket. +/// +/// This class is a wrapper around a Socket that connects to a SOCKS5 proxy +/// server and sends all data through the proxy. +/// +/// This class is used to connect to the Tor proxy server. +/// +/// Attributes: +/// - [proxyHost]: The host of the SOCKS5 proxy server. +/// - [proxyPort]: The port of the SOCKS5 proxy server. +/// - [_socksSocket]: The underlying [Socket] that connects to the SOCKS5 proxy +/// server. +/// - [_responseController]: A [StreamController] that listens to the +/// [_socksSocket] and broadcasts the response. +/// +/// Methods: +/// - connect: Connects to the SOCKS5 proxy server. +/// - connectTo: Connects to the specified [domain] and [port] through the +/// SOCKS5 proxy server. +/// - write: Converts [object] to a String by invoking [Object.toString] and +/// sends the encoding of the result to the socket. +/// - sendServerFeaturesCommand: Sends the server.features command to the +/// proxy server. +/// - close: Closes the connection to the Tor proxy. +/// +/// Usage: +/// ```dart +/// // Instantiate a socks socket at localhost and on the port selected by the +/// // tor service. +/// var socksSocket = await SOCKSSocket.create( +/// proxyHost: InternetAddress.loopbackIPv4.address, +/// proxyPort: tor.port, +/// // sslEnabled: true, // For SSL connections. +/// ); +/// +/// // Connect to the socks instantiated above. +/// await socksSocket.connect(); +/// +/// // Connect to bitcoincash.stackwallet.com on port 50001 via socks socket. +/// await socksSocket.connectTo( +/// 'bitcoincash.stackwallet.com', 50001); +/// +/// // Send a server features command to the connected socket, see method for +/// // more specific usage example.. +/// await socksSocket.sendServerFeaturesCommand(); +/// await socksSocket.close(); +/// ``` +/// +/// See also: +/// - SOCKS5 protocol(https://www.ietf.org/rfc/rfc1928.txt) class SOCKSSocket { + /// The host of the SOCKS5 proxy server. final String proxyHost; + + /// The port of the SOCKS5 proxy server. final int proxyPort; + /// The underlying Socket that connects to the SOCKS5 proxy server. late final Socket _socksSocket; - Socket get socket => _socksSocket; + /// Getter for the underlying Socket that connects to the SOCKS5 proxy server. + Socket get socket => sslEnabled ? _secureSocksSocket : _socksSocket; + + /// A wrapper around the _socksSocket that enables SSL connections. + late final Socket _secureSocksSocket; + + /// A StreamController that listens to the _socksSocket and broadcasts. final StreamController> _responseController = StreamController.broadcast(); - // Private constructor - SOCKSSocket._(this.proxyHost, this.proxyPort); + /// Getter for the StreamController that listens to the _socksSocket and + /// broadcasts. + StreamController> get responseController => + sslEnabled ? _secureResponseController : _responseController; + /// A StreamController that listens to the _secureSocksSocket and broadcasts. + final StreamController> _secureResponseController = + StreamController.broadcast(); + + /// Is SSL enabled? + final bool sslEnabled; + + /// Private constructor. + SOCKSSocket._(this.proxyHost, this.proxyPort, this.sslEnabled); + + /// Creates a SOCKS5 socket to the specified [proxyHost] and [proxyPort]. + /// + /// This method is a factory constructor that returns a Future that resolves + /// to a SOCKSSocket instance. + /// + /// Parameters: + /// - [proxyHost]: The host of the SOCKS5 proxy server. + /// - [proxyPort]: The port of the SOCKS5 proxy server. + /// + /// Returns: + /// A Future that resolves to a SOCKSSocket instance. static Future create( - {required String proxyHost, required int proxyPort}) async { - var instance = SOCKSSocket._(proxyHost, proxyPort); + {required String proxyHost, + required int proxyPort, + bool sslEnabled = false}) async { + // Create a SOCKS socket instance. + var instance = SOCKSSocket._(proxyHost, proxyPort, sslEnabled); + + // Initialize the SOCKS socket. await instance._init(); + + // Return the SOCKS socket instance. return instance; } - SOCKSSocket({required this.proxyHost, required this.proxyPort}) { + /// Constructor. + SOCKSSocket( + {required this.proxyHost, + required this.proxyPort, + required this.sslEnabled}) { _init(); } /// Initializes the SOCKS socket. - + /// + /// This method is a private method that is called by the constructor. + /// + /// Returns: + /// A Future that resolves to void. Future _init() async { + // Connect to the SOCKS proxy server. _socksSocket = await Socket.connect( proxyHost, proxyPort, ); + // Listen to the socket. _socksSocket.listen( (data) { + // Add the data to the response controller. _responseController.add(data); }, - onError: (dynamic e) { + onError: (e) { + // Handle errors. if (e is Object) { _responseController.addError(e); } + + // If the error is not an object, send the error as a string. _responseController.addError("$e"); - // TODO make sure sending error as string is acceptable + // TODO make sure sending error as string is acceptable. }, onDone: () { + // Close the response controller when the socket is closed. _responseController.close(); }, ); } /// Connects to the SOCKS socket. + /// + /// Returns: + /// A Future that resolves to void. Future connect() async { - // Greeting and method selection + // Greeting and method selection. _socksSocket.add([0x05, 0x01, 0x00]); - // Wait for server response + // Wait for server response. var response = await _responseController.stream.first; + + // Check if the connection was successful. if (response[1] != 0x00) { - throw Exception('Failed to connect to SOCKS5 socket.'); + throw Exception( + 'socks_socket.connect(): Failed to connect to SOCKS5 proxy.'); } } /// Connects to the specified [domain] and [port] through the SOCKS socket. + /// + /// Parameters: + /// - [domain]: The domain to connect to. + /// - [port]: The port to connect to. + /// + /// Returns: + /// A Future that resolves to void. Future connectTo(String domain, int port) async { + // Connect command. var request = [ - 0x05, - 0x01, - 0x00, - 0x03, + 0x05, // SOCKS version. + 0x01, // Connect command. + 0x00, // Reserved. + 0x03, // Domain name. domain.length, ...domain.codeUnits, (port >> 8) & 0xFF, port & 0xFF ]; + // Send the connect command to the SOCKS proxy server. _socksSocket.add(request); + // Wait for server response. var response = await _responseController.stream.first; + + // Check if the connection was successful. if (response[1] != 0x00) { - throw Exception('Failed to connect to target through SOCKS5 proxy.'); + throw Exception( + 'socks_socket.connectTo(): Failed to connect to target through SOCKS5 proxy.'); } + + // Upgrade to SSL if needed + if (sslEnabled) { + // Upgrade to SSL. + _secureSocksSocket = await SecureSocket.secure( + _socksSocket, + host: domain, + // onBadCertificate: (_) => true, // Uncomment this to bypass certificate validation (NOT recommended for production). + ); + + // Listen to the secure socket. + _secureSocksSocket.listen( + (data) { + // Add the data to the response controller. + _secureResponseController.add(data); + }, + onError: (e) { + // Handle errors. + if (e is Object) { + _secureResponseController.addError(e); + } + + // If the error is not an object, send the error as a string. + _secureResponseController.addError("$e"); + // TODO make sure sending error as string is acceptable. + }, + onDone: () { + // Close the response controller when the socket is closed. + _secureResponseController.close(); + }, + ); + } + + return; } /// Converts [object] to a String by invoking [Object.toString] and /// sends the encoding of the result to the socket. + /// + /// Parameters: + /// - [object]: The object to write to the socket. + /// + /// Returns: + /// A Future that resolves to void. void write(Object? object) { + // Don't write null. if (object == null) return; + // Write the data to the socket. List data = utf8.encode(object.toString()); - _socksSocket.add(data); + if (sslEnabled) { + _secureSocksSocket.add(data); + } else { + _socksSocket.add(data); + } } /// Sends the server.features command to the proxy server. + /// + /// This method is used to send the server.features command to the proxy + /// server. This command is used to request the features of the proxy server. + /// It serves as a demonstration of how to send commands to the proxy server. + /// + /// Returns: + /// A Future that resolves to void. Future sendServerFeaturesCommand() async { + // The server.features command. const String command = '{"jsonrpc":"2.0","id":"0","method":"server.features","params":[]}'; - _socksSocket.writeln(command); - var responseData = await _responseController.stream.first; - print("responseData: ${utf8.decode(responseData)}"); + if (!sslEnabled) { + // Send the command to the proxy server. + _socksSocket.writeln(command); + + // Wait for the response from the proxy server. + var responseData = await _responseController.stream.first; + print("responseData: ${utf8.decode(responseData)}"); + } else { + // Send the command to the proxy server. + _secureSocksSocket.writeln(command); + + // Wait for the response from the proxy server. + var responseData = await _secureResponseController.stream.first; + print("secure responseData: ${utf8.decode(responseData)}"); + } + + return; } /// Closes the connection to the Tor proxy. + /// + /// Returns: + /// A Future that resolves to void. Future close() async { - await _socksSocket.flush(); // Ensure all data is sent before closing + // Ensure all data is sent before closing. + // + // TODO test this. + if (sslEnabled) { + await _socksSocket.flush(); + await _secureResponseController.close(); + } + await _socksSocket.flush(); await _responseController.close(); return await _socksSocket.close(); } From b5fcea18f6abf2d783669b908fc0b14eb81b8b6a Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 6 Sep 2023 16:39:45 -0600 Subject: [PATCH 138/237] tor status text --- .../tor_settings/tor_settings_view.dart | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 366aff80a..5fd8128b5 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -61,6 +61,32 @@ class _TorSettingsViewState extends ConsumerState { } } + Widget _buildTorStatus(TorSyncStatus status) { + switch (status) { + case TorSyncStatus.unableToSync: + return Text( + "Disconnected", + style: STextStyles.itemSubtitle(context).copyWith( + color: Theme.of(context).extension()!.textSubtitle3), + ); + case TorSyncStatus.synced: + return Text( + "Connected", + style: STextStyles.itemSubtitle(context).copyWith( + color: + Theme.of(context).extension()!.accentColorGreen), + ); + case TorSyncStatus.syncing: + return Text( + "Connecting", + style: STextStyles.itemSubtitle(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorYellow), + ); + } + } + @override void initState() { super.initState(); @@ -131,7 +157,7 @@ class _TorSettingsViewState extends ConsumerState { children: [ Padding( padding: const EdgeInsets.all(10.0), - child: _buildTorIcon(TorSyncStatus.unableToSync), + child: _buildTorIcon(TorSyncStatus.syncing), ), ], ), @@ -148,10 +174,7 @@ class _TorSettingsViewState extends ConsumerState { style: STextStyles.titleBold12(context), ), const Spacer(), - Text( - "Tor network status", - style: STextStyles.itemSubtitle(context), - ), + _buildTorStatus(TorSyncStatus.syncing), ], ), ), From f7ddaa1f73d9f0c80ba5235a0206623ae219b5db Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 6 Sep 2023 17:48:50 -0500 Subject: [PATCH 139/237] use tor for nodes --- lib/electrumx_rpc/rpc.dart | 8 ++++---- lib/networking/socks_socket.dart | 29 ++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 749dc624f..51f62a8a1 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -38,8 +38,8 @@ class JsonRPC { final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); Socket? _socket; SOCKSSocket? _socksSocket; - StreamSubscription? _subscription; - StreamSubscription? get subscription => _subscription; + StreamSubscription>? _subscription; + StreamSubscription>? get subscription => _subscription; void _dataHandler(List data) { _requestQueue.nextIncompleteReq.then((req) { @@ -86,7 +86,7 @@ class JsonRPC { _socket!.write('${req.jsonRequest}\r\n'); } if (_socksSocket != null) { - _socksSocket!.write('${req.jsonRequest}\r\n\n'); + _socksSocket!.write('${req.jsonRequest}\r\n'); // _socksSocket!.socket.writeln('${req.jsonRequest}\r\n'); } @@ -248,7 +248,7 @@ class JsonRPC { "JsonRPC.connect(): failed to connect to tor proxy, $e"); } - _subscription = _socksSocket!.socket.listen( + _subscription = _socksSocket!.listen( _dataHandler, onError: _errorHandler, onDone: _doneHandler, diff --git a/lib/networking/socks_socket.dart b/lib/networking/socks_socket.dart index b469026b6..0337ff85b 100644 --- a/lib/networking/socks_socket.dart +++ b/lib/networking/socks_socket.dart @@ -73,10 +73,12 @@ class SOCKSSocket { StreamController.broadcast(); /// Getter for the StreamController that listens to the _socksSocket and - /// broadcasts. + /// broadcasts, or the _secureSocksSocket and broadcasts if SSL is enabled. StreamController> get responseController => sslEnabled ? _secureResponseController : _responseController; + StreamSubscription? _subscription; + /// A StreamController that listens to the _secureSocksSocket and broadcasts. final StreamController> _secureResponseController = StreamController.broadcast(); @@ -134,7 +136,7 @@ class SOCKSSocket { ); // Listen to the socket. - _socksSocket.listen( + _subscription = _socksSocket.listen( (data) { // Add the data to the response controller. _responseController.add(data); @@ -217,7 +219,7 @@ class SOCKSSocket { ); // Listen to the secure socket. - _secureSocksSocket.listen( + _subscription = _secureSocksSocket.listen( (data) { // Add the data to the response controller. _secureResponseController.add(data); @@ -311,4 +313,25 @@ class SOCKSSocket { await _responseController.close(); return await _socksSocket.close(); } + + StreamSubscription> listen( + void Function(List data)? onData, { + Function? onError, + void Function()? onDone, + bool? cancelOnError, + }) { + return sslEnabled + ? _secureResponseController.stream.listen( + onData, + onError: onError, + onDone: onDone, + cancelOnError: cancelOnError, + ) + : _responseController.stream.listen( + onData, + onError: onError, + onDone: onDone, + cancelOnError: cancelOnError, + ); + } } From 11b7456855b00dc898c2a2126bd320a23c337cf0 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Wed, 6 Sep 2023 16:49:47 -0600 Subject: [PATCH 140/237] fixed tor status text --- .../tor_settings/tor_settings_view.dart | 68 ++++++++++++++----- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 5fd8128b5..8304eb851 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -35,28 +35,62 @@ class TorSettingsView extends ConsumerStatefulWidget { } class _TorSettingsViewState extends ConsumerState { + TorSyncStatus _networkStatus = TorSyncStatus.unableToSync; + Widget _buildTorIcon(TorSyncStatus status) { switch (status) { case TorSyncStatus.unableToSync: - return SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context).extension()!.textSubtitle3, - width: 200, - height: 200, + return Stack( + alignment: AlignmentDirectional.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context).extension()!.textSubtitle3, + width: 200, + height: 200, + ), + Text( + "CONNECT", + style: STextStyles.smallMed14(context).copyWith( + color: Theme.of(context).extension()!.popupBG), + ) + ], ); case TorSyncStatus.synced: - return SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context).extension()!.accentColorGreen, - width: 200, - height: 200, + return Stack( + alignment: AlignmentDirectional.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: + Theme.of(context).extension()!.accentColorGreen, + width: 200, + height: 200, + ), + Text( + "CONNECTED", + style: STextStyles.smallMed14(context).copyWith( + color: Theme.of(context).extension()!.popupBG), + ) + ], ); case TorSyncStatus.syncing: - return SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context).extension()!.accentColorYellow, - width: 200, - height: 200, + return Stack( + alignment: AlignmentDirectional.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: + Theme.of(context).extension()!.accentColorYellow, + width: 200, + height: 200, + ), + Text( + "CONNECTING", + style: STextStyles.smallMed14(context).copyWith( + color: Theme.of(context).extension()!.popupBG), + ) + ], ); } } @@ -157,7 +191,7 @@ class _TorSettingsViewState extends ConsumerState { children: [ Padding( padding: const EdgeInsets.all(10.0), - child: _buildTorIcon(TorSyncStatus.syncing), + child: _buildTorIcon(_networkStatus), ), ], ), @@ -174,7 +208,7 @@ class _TorSettingsViewState extends ConsumerState { style: STextStyles.titleBold12(context), ), const Spacer(), - _buildTorStatus(TorSyncStatus.syncing), + _buildTorStatus(_networkStatus), ], ), ), From d84f2d7b7a3c324e0c8e89af707d98d35d422241 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 6 Sep 2023 18:09:41 -0500 Subject: [PATCH 141/237] prettify tor messages and use tor main --- crypto_plugins/tor | 2 +- lib/electrumx_rpc/electrumx.dart | 8 +++----- lib/electrumx_rpc/rpc.dart | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 5c14a4397..22abf0036 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 5c14a4397c6c1344d09bbe650f2c14a640c768d8 +Subproject commit 22abf0036d8eda68efda5a31dc32c6f8932de4ec diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 7d3dd3d2b..674029fea 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -105,8 +105,7 @@ class ElectrumX { host: InternetAddress.loopbackIPv4.address, port: TorService.sharedInstance.port ); - Logging.instance.log( - "ElectrumX.from(): no tor proxy info, read $proxyInfo", + Logging.instance.log("ElectrumX.from(): tor detected at $proxyInfo", level: LogLevel.Warning); } return ElectrumX( @@ -156,8 +155,7 @@ class ElectrumX { host: InternetAddress.loopbackIPv4.address, port: TorService.sharedInstance.port ); - Logging.instance.log( - "ElectrumX.request(): no tor proxy info, read $proxyInfo", + Logging.instance.log("ElectrumX.request(): tor detected at $proxyInfo", level: LogLevel.Warning); } if (currentFailoverIndex == -1) { @@ -290,7 +288,7 @@ class ElectrumX { port: TorService.sharedInstance.port ); Logging.instance.log( - "ElectrumX.batchRequest(): no tor proxy info, read $proxyInfo", + "ElectrumX.batchRequest(): tor detected at $proxyInfo", level: LogLevel.Warning); } diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 51f62a8a1..106b5a21b 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -200,8 +200,7 @@ class JsonRPC { host: InternetAddress.loopbackIPv4.address, port: TorService.sharedInstance.port ); - Logging.instance.log( - "ElectrumX.connect(): no tor proxy info, read $proxyInfo", + Logging.instance.log("ElectrumX.connect(): tor detected at $proxyInfo", level: LogLevel.Warning); } From 3bb0a647bf9fbddeef67dbd81181cede7903686e Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 6 Sep 2023 18:17:28 -0500 Subject: [PATCH 142/237] documentation in SOCKSSocket. TODO remove unused getters and update the example in cypherstack/tor... or expose that file and use it here --- lib/networking/socks_socket.dart | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/networking/socks_socket.dart b/lib/networking/socks_socket.dart index 0337ff85b..03dc60945 100644 --- a/lib/networking/socks_socket.dart +++ b/lib/networking/socks_socket.dart @@ -72,16 +72,22 @@ class SOCKSSocket { final StreamController> _responseController = StreamController.broadcast(); + /// A StreamController that listens to the _secureSocksSocket and broadcasts. + final StreamController> _secureResponseController = + StreamController.broadcast(); + /// Getter for the StreamController that listens to the _socksSocket and /// broadcasts, or the _secureSocksSocket and broadcasts if SSL is enabled. StreamController> get responseController => sslEnabled ? _secureResponseController : _responseController; - StreamSubscription? _subscription; + /// A StreamSubscription that listens to the _socksSocket or the + /// _secureSocksSocket if SSL is enabled. + StreamSubscription>? _subscription; - /// A StreamController that listens to the _secureSocksSocket and broadcasts. - final StreamController> _secureResponseController = - StreamController.broadcast(); + /// Getter for the StreamSubscription that listens to the _socksSocket or the + /// _secureSocksSocket if SSL is enabled. + StreamSubscription>? get subscription => _subscription; /// Is SSL enabled? final bool sslEnabled; From 7dabba3d0eda756b266c7df53bf111401183b8db Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 7 Sep 2023 09:09:49 -0600 Subject: [PATCH 143/237] comment out unused class to avoid confusion --- lib/electrumx_rpc/subscribable_electrumx.dart | 648 +++++++++--------- 1 file changed, 324 insertions(+), 324 deletions(-) diff --git a/lib/electrumx_rpc/subscribable_electrumx.dart b/lib/electrumx_rpc/subscribable_electrumx.dart index 4720e345b..b7da56a52 100644 --- a/lib/electrumx_rpc/subscribable_electrumx.dart +++ b/lib/electrumx_rpc/subscribable_electrumx.dart @@ -1,324 +1,324 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter/foundation.dart'; -import 'package:stackwallet/utilities/logger.dart'; - -class ElectrumXSubscription with ChangeNotifier { - dynamic _response; - dynamic get response => _response; - set response(dynamic newData) { - _response = newData; - notifyListeners(); - } -} - -class SocketTask { - SocketTask({this.completer, this.subscription}); - - final Completer? completer; - final ElectrumXSubscription? subscription; - - bool get isSubscription => subscription != null; -} - -class SubscribableElectrumXClient { - int _currentRequestID = 0; - bool _isConnected = false; - List _responseData = []; - final Map _tasks = {}; - Timer? _aliveTimer; - Socket? _socket; - late final bool _useSSL; - late final Duration _connectionTimeout; - late final Duration _keepAlive; - - bool get isConnected => _isConnected; - bool get useSSL => _useSSL; - - void Function(bool)? onConnectionStatusChanged; - - SubscribableElectrumXClient({ - bool useSSL = true, - this.onConnectionStatusChanged, - Duration connectionTimeout = const Duration(seconds: 5), - Duration keepAlive = const Duration(seconds: 10), - }) { - _useSSL = useSSL; - _connectionTimeout = connectionTimeout; - _keepAlive = keepAlive; - } - - Future connect({required String host, required int port}) async { - try { - await _socket?.close(); - } catch (_) {} - - if (_useSSL) { - _socket = await SecureSocket.connect( - host, - port, - timeout: _connectionTimeout, - onBadCertificate: (_) => true, - ); - } else { - _socket = await Socket.connect( - host, - port, - timeout: _connectionTimeout, - ); - } - _updateConnectionStatus(true); - - _socket!.listen( - _dataHandler, - onError: _errorHandler, - onDone: _doneHandler, - cancelOnError: true, - ); - - _aliveTimer?.cancel(); - _aliveTimer = Timer.periodic( - _keepAlive, - (_) async => _updateConnectionStatus(await ping()), - ); - } - - Future disconnect() async { - _aliveTimer?.cancel(); - await _socket?.close(); - onConnectionStatusChanged = null; - } - - String _buildJsonRequestString({ - required String method, - required String id, - required List params, - }) { - final paramString = jsonEncode(params); - return '{"jsonrpc": "2.0", "id": "$id","method": "$method","params": $paramString}\r\n'; - } - - void _updateConnectionStatus(bool connectionStatus) { - if (_isConnected != connectionStatus && onConnectionStatusChanged != null) { - onConnectionStatusChanged!(connectionStatus); - } - _isConnected = connectionStatus; - } - - void _dataHandler(List data) { - _responseData.addAll(data); - - // 0x0A is newline - // https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-basics.html - if (data.last == 0x0A) { - try { - final response = jsonDecode(String.fromCharCodes(_responseData)) - as Map; - _responseHandler(response); - } catch (e, s) { - Logging.instance - .log("JsonRPC jsonDecode: $e\n$s", level: LogLevel.Error); - rethrow; - } finally { - _responseData = []; - } - } - } - - void _responseHandler(Map response) { - // subscriptions will have a method in the response - if (response['method'] is String) { - _subscriptionHandler(response: response); - return; - } - - final id = response['id'] as String; - final result = response['result']; - - _complete(id, result); - } - - void _subscriptionHandler({ - required Map response, - }) { - final method = response['method']; - switch (method) { - case "blockchain.scripthash.subscribe": - final params = response["params"] as List; - final scripthash = params.first as String; - final taskId = "blockchain.scripthash.subscribe:$scripthash"; - - _tasks[taskId]?.subscription?.response = params.last; - break; - case "blockchain.headers.subscribe": - final params = response["params"]; - const taskId = "blockchain.headers.subscribe"; - - _tasks[taskId]?.subscription?.response = params.first; - break; - default: - break; - } - } - - void _errorHandler(Object error, StackTrace trace) { - _updateConnectionStatus(false); - Logging.instance.log( - "SubscribableElectrumXClient called _errorHandler with: $error\n$trace", - level: LogLevel.Info); - } - - void _doneHandler() { - _updateConnectionStatus(false); - Logging.instance.log("SubscribableElectrumXClient called _doneHandler", - level: LogLevel.Info); - } - - void _complete(String id, dynamic data) { - if (_tasks[id] == null) { - return; - } - - if (!(_tasks[id]?.completer?.isCompleted ?? false)) { - _tasks[id]?.completer?.complete(data); - } - - if (!(_tasks[id]?.isSubscription ?? false)) { - _tasks.remove(id); - } else { - _tasks[id]?.subscription?.response = data; - } - } - - void _addTask({ - required String id, - required Completer completer, - }) { - _tasks[id] = SocketTask(completer: completer, subscription: null); - } - - void _addSubscriptionTask({ - required String id, - required ElectrumXSubscription subscription, - }) { - _tasks[id] = SocketTask(completer: null, subscription: subscription); - } - - Future _call({ - required String method, - List params = const [], - }) async { - final completer = Completer(); - _currentRequestID++; - final id = _currentRequestID.toString(); - _addTask(id: id, completer: completer); - - _socket?.write( - _buildJsonRequestString( - method: method, - id: id, - params: params, - ), - ); - - return completer.future; - } - - Future _callWithTimeout({ - required String method, - List params = const [], - Duration timeout = const Duration(seconds: 2), - }) async { - final completer = Completer(); - _currentRequestID++; - final id = _currentRequestID.toString(); - _addTask(id: id, completer: completer); - - _socket?.write( - _buildJsonRequestString( - method: method, - id: id, - params: params, - ), - ); - - Timer(timeout, () { - if (!completer.isCompleted) { - completer.completeError( - Exception("Request \"id: $id, method: $method\" timed out!"), - ); - } - }); - - return completer.future; - } - - ElectrumXSubscription _subscribe({ - required String taskId, - required String method, - List params = const [], - }) { - // try { - final subscription = ElectrumXSubscription(); - _addSubscriptionTask(id: taskId, subscription: subscription); - _currentRequestID++; - _socket?.write( - _buildJsonRequestString( - method: method, - id: taskId, - params: params, - ), - ); - - return subscription; - // } catch (e, s) { - // Logging.instance.log("SubscribableElectrumXClient _subscribe: $e\n$s", level: LogLevel.Error); - // return null; - // } - } - - /// Ping the server to ensure it is responding - /// - /// Returns true if ping succeeded - Future ping() async { - try { - final response = (await _callWithTimeout(method: "server.ping")) as Map; - return response.keys.contains("result") && response["result"] == null; - } catch (_) { - return false; - } - } - - /// Subscribe to a scripthash to receive notifications on status changes - ElectrumXSubscription subscribeToScripthash({required String scripthash}) { - return _subscribe( - taskId: 'blockchain.scripthash.subscribe:$scripthash', - method: 'blockchain.scripthash.subscribe', - params: [scripthash], - ); - } - - /// Subscribe to block headers to receive notifications on new blocks found - /// - /// Returns the existing subscription if found - ElectrumXSubscription subscribeToBlockHeaders() { - return _tasks["blockchain.headers.subscribe"]?.subscription ?? - _subscribe( - taskId: "blockchain.headers.subscribe", - method: "blockchain.headers.subscribe", - params: [], - ); - } -} +// /* +// * This file is part of Stack Wallet. +// * +// * Copyright (c) 2023 Cypher Stack +// * All Rights Reserved. +// * The code is distributed under GPLv3 license, see LICENSE file for details. +// * Generated by Cypher Stack on 2023-05-26 +// * +// */ +// +// import 'dart:async'; +// import 'dart:convert'; +// import 'dart:io'; +// +// import 'package:flutter/foundation.dart'; +// import 'package:stackwallet/utilities/logger.dart'; +// +// class ElectrumXSubscription with ChangeNotifier { +// dynamic _response; +// dynamic get response => _response; +// set response(dynamic newData) { +// _response = newData; +// notifyListeners(); +// } +// } +// +// class SocketTask { +// SocketTask({this.completer, this.subscription}); +// +// final Completer? completer; +// final ElectrumXSubscription? subscription; +// +// bool get isSubscription => subscription != null; +// } +// +// class SubscribableElectrumXClient { +// int _currentRequestID = 0; +// bool _isConnected = false; +// List _responseData = []; +// final Map _tasks = {}; +// Timer? _aliveTimer; +// Socket? _socket; +// late final bool _useSSL; +// late final Duration _connectionTimeout; +// late final Duration _keepAlive; +// +// bool get isConnected => _isConnected; +// bool get useSSL => _useSSL; +// +// void Function(bool)? onConnectionStatusChanged; +// +// SubscribableElectrumXClient({ +// bool useSSL = true, +// this.onConnectionStatusChanged, +// Duration connectionTimeout = const Duration(seconds: 5), +// Duration keepAlive = const Duration(seconds: 10), +// }) { +// _useSSL = useSSL; +// _connectionTimeout = connectionTimeout; +// _keepAlive = keepAlive; +// } +// +// Future connect({required String host, required int port}) async { +// try { +// await _socket?.close(); +// } catch (_) {} +// +// if (_useSSL) { +// _socket = await SecureSocket.connect( +// host, +// port, +// timeout: _connectionTimeout, +// onBadCertificate: (_) => true, +// ); +// } else { +// _socket = await Socket.connect( +// host, +// port, +// timeout: _connectionTimeout, +// ); +// } +// _updateConnectionStatus(true); +// +// _socket!.listen( +// _dataHandler, +// onError: _errorHandler, +// onDone: _doneHandler, +// cancelOnError: true, +// ); +// +// _aliveTimer?.cancel(); +// _aliveTimer = Timer.periodic( +// _keepAlive, +// (_) async => _updateConnectionStatus(await ping()), +// ); +// } +// +// Future disconnect() async { +// _aliveTimer?.cancel(); +// await _socket?.close(); +// onConnectionStatusChanged = null; +// } +// +// String _buildJsonRequestString({ +// required String method, +// required String id, +// required List params, +// }) { +// final paramString = jsonEncode(params); +// return '{"jsonrpc": "2.0", "id": "$id","method": "$method","params": $paramString}\r\n'; +// } +// +// void _updateConnectionStatus(bool connectionStatus) { +// if (_isConnected != connectionStatus && onConnectionStatusChanged != null) { +// onConnectionStatusChanged!(connectionStatus); +// } +// _isConnected = connectionStatus; +// } +// +// void _dataHandler(List data) { +// _responseData.addAll(data); +// +// // 0x0A is newline +// // https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-basics.html +// if (data.last == 0x0A) { +// try { +// final response = jsonDecode(String.fromCharCodes(_responseData)) +// as Map; +// _responseHandler(response); +// } catch (e, s) { +// Logging.instance +// .log("JsonRPC jsonDecode: $e\n$s", level: LogLevel.Error); +// rethrow; +// } finally { +// _responseData = []; +// } +// } +// } +// +// void _responseHandler(Map response) { +// // subscriptions will have a method in the response +// if (response['method'] is String) { +// _subscriptionHandler(response: response); +// return; +// } +// +// final id = response['id'] as String; +// final result = response['result']; +// +// _complete(id, result); +// } +// +// void _subscriptionHandler({ +// required Map response, +// }) { +// final method = response['method']; +// switch (method) { +// case "blockchain.scripthash.subscribe": +// final params = response["params"] as List; +// final scripthash = params.first as String; +// final taskId = "blockchain.scripthash.subscribe:$scripthash"; +// +// _tasks[taskId]?.subscription?.response = params.last; +// break; +// case "blockchain.headers.subscribe": +// final params = response["params"]; +// const taskId = "blockchain.headers.subscribe"; +// +// _tasks[taskId]?.subscription?.response = params.first; +// break; +// default: +// break; +// } +// } +// +// void _errorHandler(Object error, StackTrace trace) { +// _updateConnectionStatus(false); +// Logging.instance.log( +// "SubscribableElectrumXClient called _errorHandler with: $error\n$trace", +// level: LogLevel.Info); +// } +// +// void _doneHandler() { +// _updateConnectionStatus(false); +// Logging.instance.log("SubscribableElectrumXClient called _doneHandler", +// level: LogLevel.Info); +// } +// +// void _complete(String id, dynamic data) { +// if (_tasks[id] == null) { +// return; +// } +// +// if (!(_tasks[id]?.completer?.isCompleted ?? false)) { +// _tasks[id]?.completer?.complete(data); +// } +// +// if (!(_tasks[id]?.isSubscription ?? false)) { +// _tasks.remove(id); +// } else { +// _tasks[id]?.subscription?.response = data; +// } +// } +// +// void _addTask({ +// required String id, +// required Completer completer, +// }) { +// _tasks[id] = SocketTask(completer: completer, subscription: null); +// } +// +// void _addSubscriptionTask({ +// required String id, +// required ElectrumXSubscription subscription, +// }) { +// _tasks[id] = SocketTask(completer: null, subscription: subscription); +// } +// +// Future _call({ +// required String method, +// List params = const [], +// }) async { +// final completer = Completer(); +// _currentRequestID++; +// final id = _currentRequestID.toString(); +// _addTask(id: id, completer: completer); +// +// _socket?.write( +// _buildJsonRequestString( +// method: method, +// id: id, +// params: params, +// ), +// ); +// +// return completer.future; +// } +// +// Future _callWithTimeout({ +// required String method, +// List params = const [], +// Duration timeout = const Duration(seconds: 2), +// }) async { +// final completer = Completer(); +// _currentRequestID++; +// final id = _currentRequestID.toString(); +// _addTask(id: id, completer: completer); +// +// _socket?.write( +// _buildJsonRequestString( +// method: method, +// id: id, +// params: params, +// ), +// ); +// +// Timer(timeout, () { +// if (!completer.isCompleted) { +// completer.completeError( +// Exception("Request \"id: $id, method: $method\" timed out!"), +// ); +// } +// }); +// +// return completer.future; +// } +// +// ElectrumXSubscription _subscribe({ +// required String taskId, +// required String method, +// List params = const [], +// }) { +// // try { +// final subscription = ElectrumXSubscription(); +// _addSubscriptionTask(id: taskId, subscription: subscription); +// _currentRequestID++; +// _socket?.write( +// _buildJsonRequestString( +// method: method, +// id: taskId, +// params: params, +// ), +// ); +// +// return subscription; +// // } catch (e, s) { +// // Logging.instance.log("SubscribableElectrumXClient _subscribe: $e\n$s", level: LogLevel.Error); +// // return null; +// // } +// } +// +// /// Ping the server to ensure it is responding +// /// +// /// Returns true if ping succeeded +// Future ping() async { +// try { +// final response = (await _callWithTimeout(method: "server.ping")) as Map; +// return response.keys.contains("result") && response["result"] == null; +// } catch (_) { +// return false; +// } +// } +// +// /// Subscribe to a scripthash to receive notifications on status changes +// ElectrumXSubscription subscribeToScripthash({required String scripthash}) { +// return _subscribe( +// taskId: 'blockchain.scripthash.subscribe:$scripthash', +// method: 'blockchain.scripthash.subscribe', +// params: [scripthash], +// ); +// } +// +// /// Subscribe to block headers to receive notifications on new blocks found +// /// +// /// Returns the existing subscription if found +// ElectrumXSubscription subscribeToBlockHeaders() { +// return _tasks["blockchain.headers.subscribe"]?.subscription ?? +// _subscribe( +// taskId: "blockchain.headers.subscribe", +// method: "blockchain.headers.subscribe", +// params: [], +// ); +// } +// } From 6e625e2c7483a14d831e802c1357443c2752e450 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 7 Sep 2023 09:20:45 -0600 Subject: [PATCH 144/237] add tor status change event and fire on pref changed --- .../global/tor_status_changed_event.dart | 28 +++++++++++++++++++ lib/utilities/prefs.dart | 14 ++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 lib/services/event_bus/events/global/tor_status_changed_event.dart diff --git a/lib/services/event_bus/events/global/tor_status_changed_event.dart b/lib/services/event_bus/events/global/tor_status_changed_event.dart new file mode 100644 index 000000000..cf9cac5ee --- /dev/null +++ b/lib/services/event_bus/events/global/tor_status_changed_event.dart @@ -0,0 +1,28 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import 'package:stackwallet/utilities/logger.dart'; + +enum TorStatus { enabled, disabled } + +class TorStatusChangedEvent { + String? message; + TorStatus status; + + TorStatusChangedEvent({ + required this.status, + this.message, + }) { + Logging.instance.log( + "TorStatusChangedEvent changed to \"$status\" with message: $message", + level: LogLevel.Warning, + ); + } +} diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index f5a04a6f9..d9a2192be 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -10,6 +10,8 @@ import 'package:flutter/cupertino.dart'; import 'package:stackwallet/db/hive/db.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/utilities/amount/amount_unit.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; @@ -886,12 +888,20 @@ class Prefs extends ChangeNotifier { ); _useTor = useTor; notifyListeners(); + GlobalEventBus.instance.fire( + TorStatusChangedEvent( + status: useTor ? TorStatus.enabled : TorStatus.disabled, + message: "useTor updated in prefs", + ), + ); } } Future _getUseTor() async { - return await DB.instance - .get(boxName: DB.boxNamePrefs, key: "useTor") as bool? ?? + return await DB.instance.get( + boxName: DB.boxNamePrefs, + key: "useTor", + ) as bool? ?? false; } } From 236c5bf2a8a5c80d4f20d9239f3ca88e88b68143 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Thu, 7 Sep 2023 11:22:59 -0600 Subject: [PATCH 145/237] tor settings when clicking connection on menu --- lib/pages_desktop_specific/desktop_menu.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index 6e0b38c65..b21a1d724 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -16,6 +16,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart'; +import 'package:stackwallet/pages_desktop_specific/settings/settings_menu.dart'; import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; @@ -211,11 +212,11 @@ class _DesktopMenuState extends ConsumerState { cursor: SystemMouseCursors.click, child: GestureDetector( onTap: () { - // ref.watch(selectedSettingsMenuItemStateProvider.state).state = - // 4; - // ref.watch(selectedSettingsMenuItemStateProvider.state).state = - // 5; - // Navigator.of(context).pushNamed(DesktopHomeView.routeName); + ref.read(currentDesktopMenuItemProvider.state).state = + DesktopMenuItemId.settings; + ref + .watch(selectedSettingsMenuItemStateProvider.state) + .state = 4; }, child: _buildTorIcon(TorSyncStatus.unableToSync)), ), From d4e0f3b04540fb51c24c2d5fefcbd2abe7f06730 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 7 Sep 2023 12:07:05 -0600 Subject: [PATCH 146/237] listen to tor status changes in electrumx --- lib/electrumx_rpc/electrumx.dart | 227 ++++++++++++++----------------- lib/electrumx_rpc/rpc.dart | 18 ++- lib/networking/http.dart | 8 +- lib/networking/tor_service.dart | 62 ++++++++- 4 files changed, 169 insertions(+), 146 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 674029fea..6e54c69ce 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -8,14 +8,18 @@ * */ +import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:decimal/decimal.dart'; +import 'package:event_bus/event_bus.dart'; import 'package:stackwallet/electrumx_rpc/rpc.dart'; import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; import 'package:stackwallet/networking/tor_service.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:uuid/uuid.dart'; @@ -66,13 +70,14 @@ class ElectrumX { JsonRPC? _rpcClient; late Prefs _prefs; + late TorService _torService; List? failovers; int currentFailoverIndex = -1; final Duration connectionTimeoutForSpecialCaseJsonRPCClients; - ({String host, int port})? proxyInfo; + StreamSubscription? _torStatusListener; ElectrumX({ required String host, @@ -83,49 +88,60 @@ class ElectrumX { JsonRPC? client, this.connectionTimeoutForSpecialCaseJsonRPCClients = const Duration(seconds: 60), - ({String host, int port})? proxyInfo, + TorService? torService, + EventBus? globalEventBusForTesting, }) { _prefs = prefs; + _torService = torService ?? TorService.sharedInstance; _host = host; _port = port; _useSSL = useSSL; _rpcClient = client; + + final bus = globalEventBusForTesting ?? GlobalEventBus.instance; + _torStatusListener = bus.on().listen( + (event) async { + // not sure if we need to do anything specific here + // switch (event.status) { + // case TorStatus.enabled: + // case TorStatus.disabled: + // } + + // might be ok to just reset/kill the current _jsonRpcClient + + // since disconnecting is async and we want to ensure instant change over + // we will keep temp reference to current rpc client to call disconnect + // on before awaiting the disconnection future + + final temp = _rpcClient; + + // setting to null should force the creation of a new json rpc client + // on the next request sent through this electrumx instance + _rpcClient = null; + + await temp?.disconnect( + reason: "Tor status changed to \"${event.status}\"", + ); + }, + ); } factory ElectrumX.from({ required ElectrumXNode node, required Prefs prefs, required List failovers, - ({String host, int port})? proxyInfo, + TorService? torService, + EventBus? globalEventBusForTesting, }) { - if (Prefs.instance.useTor) { - if (proxyInfo == null) { - // TODO await tor / make sure it's running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log("ElectrumX.from(): tor detected at $proxyInfo", - level: LogLevel.Warning); - } - return ElectrumX( - host: node.address, - port: node.port, - useSSL: node.useSSL, - prefs: prefs, - failovers: failovers, - proxyInfo: proxyInfo, - ); - } else { - return ElectrumX( - host: node.address, - port: node.port, - useSSL: node.useSSL, - prefs: prefs, - failovers: failovers, - proxyInfo: null, - ); - } + return ElectrumX( + host: node.address, + port: node.port, + useSSL: node.useSSL, + prefs: prefs, + torService: torService, + failovers: failovers, + globalEventBusForTesting: globalEventBusForTesting, + ); } Future _allow() async { @@ -136,6 +152,59 @@ class ElectrumX { return true; } + void _checkRpcClient() { + if (_prefs.useTor) { + if (!_torService.enabled) { + throw Exception("Tor is not enabled"); + } + + final proxyInfo = _torService.proxyInfo; + + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } else { + _rpcClient ??= JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } + + if (_rpcClient!.proxyInfo != proxyInfo) { + _rpcClient!.proxyInfo = proxyInfo; + _rpcClient!.disconnect( + reason: "Tor proxyInfo does not match current info", + ); + } + } else { + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } else { + _rpcClient ??= JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); + } + } + } + /// Send raw rpc command Future request({ required String command, @@ -148,52 +217,7 @@ class ElectrumX { throw WifiOnlyException(); } - if (Prefs.instance.useTor) { - if (proxyInfo == null) { - // TODO await tor / make sure Tor is running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log("ElectrumX.request(): tor detected at $proxyInfo", - level: LogLevel.Warning); - } - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } else { - _rpcClient ??= JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } - } else { - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } else { - _rpcClient ??= JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } - } + _checkRpcClient(); try { final requestId = requestID ?? const Uuid().v1(); @@ -280,54 +304,7 @@ class ElectrumX { throw WifiOnlyException(); } - if (Prefs.instance.useTor) { - // TODO await tor / make sure Tor is initialized - if (proxyInfo == null) { - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port - ); - Logging.instance.log( - "ElectrumX.batchRequest(): tor detected at $proxyInfo", - level: LogLevel.Warning); - } - - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } else { - _rpcClient = JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } - } else { - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } else { - _rpcClient = JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } - } + _checkRpcClient(); try { final List requestStrings = []; diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 106b5a21b..a6335bf9e 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -26,13 +26,13 @@ class JsonRPC { required this.port, this.useSSL = false, this.connectionTimeout = const Duration(seconds: 60), - required ({String host, int port})? proxyInfo, + required ({InternetAddress host, int port})? proxyInfo, }); final bool useSSL; final String host; final int port; final Duration connectionTimeout; - ({String host, int port})? proxyInfo; + ({InternetAddress host, int port})? proxyInfo; final _requestMutex = Mutex(); final _JsonRPCRequestQueue _requestQueue = _JsonRPCRequestQueue(); @@ -195,19 +195,17 @@ class JsonRPC { ); } else { if (proxyInfo == null) { - // TODO await tor / make sure it's running - proxyInfo = ( - host: InternetAddress.loopbackIPv4.address, - port: TorService.sharedInstance.port + proxyInfo = TorService.sharedInstance.proxyInfo; + Logging.instance.log( + "ElectrumX.connect(): tor detected at $proxyInfo", + level: LogLevel.Warning, ); - Logging.instance.log("ElectrumX.connect(): tor detected at $proxyInfo", - level: LogLevel.Warning); } // instantiate a socks socket at localhost and on the port selected by the tor service _socksSocket = await SOCKSSocket.create( - proxyHost: InternetAddress.loopbackIPv4.address, - proxyPort: TorService.sharedInstance.port, + proxyHost: proxyInfo!.host.address, + proxyPort: proxyInfo!.port, sslEnabled: useSSL, ); diff --git a/lib/networking/http.dart b/lib/networking/http.dart index 7203c91e2..5ab41a5d8 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -18,8 +18,8 @@ abstract class HTTP { if (routeOverTor) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( - InternetAddress.loopbackIPv4, - TorService.sharedInstance.port, + TorService.sharedInstance.proxyInfo.host, + TorService.sharedInstance.proxyInfo.port, ), ]); } @@ -56,8 +56,8 @@ abstract class HTTP { if (routeOverTor) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( - InternetAddress.loopbackIPv4, - TorService.sharedInstance.port, + TorService.sharedInstance.proxyInfo.host, + TorService.sharedInstance.proxyInfo.port, ), ]); } diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart index 35df3509c..02d520db6 100644 --- a/lib/networking/tor_service.dart +++ b/lib/networking/tor_service.dart @@ -1,22 +1,70 @@ +import 'dart:io'; + import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:stackwallet/utilities/stack_file_system.dart'; +import 'package:stackwallet/utilities/logger.dart'; import 'package:tor/tor.dart'; final pTorService = Provider((_) => TorService.sharedInstance); class TorService { - static final sharedInstance = TorService(); final _tor = Tor(); + bool _enabled = false; - int get port => _tor.port; + TorService._(); + + static final sharedInstance = TorService._(); + + ({ + InternetAddress host, + int port, + }) get proxyInfo => ( + host: InternetAddress.loopbackIPv4, + port: _tor.port, + ); + + bool get enabled => _enabled; Future start() async { - final dir = await StackFileSystem.applicationTorDirectory(); - await _tor.start(); - return; + if (_enabled) { + // already started so just return + // could throw an exception here or something so the caller + // is explicitly made aware of this + return; + } + + try { + await _tor.start(); + // no exception or error so we can (probably?) assume tor + // has started successfully + _enabled = true; + } catch (e, s) { + Logging.instance.log( + "TorService.start failed: $e\n$s", + level: LogLevel.Warning, + ); + rethrow; + } } Future stop() async { - return await _tor.disable(); + if (!_enabled) { + // already stopped so just return + // could throw an exception here or something so the caller + // is explicitly made aware of this + return; + } + + try { + await _tor.disable(); + // no exception or error so we can (probably?) assume tor + // has started successfully + _enabled = false; + } catch (e, s) { + Logging.instance.log( + "TorService.stop failed: $e\n$s", + level: LogLevel.Warning, + ); + rethrow; + } } } From 9c648affe88efc998109065214d7c64d8f66c81a Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 7 Sep 2023 12:16:15 -0600 Subject: [PATCH 147/237] `.exception` will always be of type `Object` here as we check for null --- lib/electrumx_rpc/electrumx.dart | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 6e54c69ce..7eaf0ba5a 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -235,8 +235,7 @@ class ElectrumX { ); if (response.exception != null) { - throw response.exception! - as Object; // TODO properly check that .exception is an Object + throw response.exception!; } if (response.data is Map && response.data["error"] != null) { @@ -329,8 +328,7 @@ class ElectrumX { (await _rpcClient!.request(request, requestTimeout)); if (jsonRpcResponse.exception != null) { - throw jsonRpcResponse.exception! - as Object; // TODO properly check that .exception is an Object + throw jsonRpcResponse.exception!; } final response = jsonRpcResponse.data as List; From 67beaf21cd43b60033f43b77dc4ac669067d6dce Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 7 Sep 2023 12:27:19 -0600 Subject: [PATCH 148/237] add finalizer to cancel stream subscription when all references to an instance of ElectrumX becomes inaccessible --- lib/electrumx_rpc/electrumx.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 7eaf0ba5a..81dc67148 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -77,6 +77,11 @@ class ElectrumX { final Duration connectionTimeoutForSpecialCaseJsonRPCClients; + // add finalizer to cancel stream subscription when all references to an + // instance of ElectrumX becomes inaccessible + static final Finalizer _finalizer = Finalizer( + (p0) => p0._torStatusListener?.cancel(), + ); StreamSubscription? _torStatusListener; ElectrumX({ From 98f3046e04c8a94f1c79e80fa9556803edbeff79 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 7 Sep 2023 14:05:25 -0600 Subject: [PATCH 149/237] stellar sync error fix --- .../coins/stellar/stellar_wallet.dart | 56 +++++++++++++++---- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index b12954628..064c1310b 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -572,14 +572,29 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { try { List> transactionList = []; - - Page payments = await stellarSdk.payments - .forAccount(await getAddressSW()) - .order(RequestBuilderOrder.DESC) - .execute() - .onError( - (error, stackTrace) => throw ("Could not fetch transactions")); - + Page payments; + try { + payments = await stellarSdk.payments + .forAccount(await getAddressSW()) + .order(RequestBuilderOrder.DESC) + .execute() + .onError((error, stackTrace) => throw error!); + } catch (e) { + if (e is ErrorResponse && + e.body.contains("The resource at the url requested was not found. " + "This usually occurs for one of two reasons: " + "The url requested is not valid, or no data in our database " + "could be found with the parameters provided.")) { + // probably just doesn't have any history yet or whatever stellar needs + return; + } else { + Logging.instance.log( + "Stellar $walletName $walletId failed to fetch transactions", + level: LogLevel.Warning, + ); + rethrow; + } + } for (OperationResponse response in payments.records!) { // PaymentOperationResponse por; if (response is PaymentOperationResponse) { @@ -717,8 +732,29 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateBalance() async { try { - AccountResponse accountResponse = - await stellarSdk.accounts.account(await getAddressSW()); + AccountResponse accountResponse; + + try { + accountResponse = await stellarSdk.accounts + .account(await getAddressSW()) + .onError((error, stackTrace) => throw error!); + } catch (e) { + if (e is ErrorResponse && + e.body.contains("The resource at the url requested was not found. " + "This usually occurs for one of two reasons: " + "The url requested is not valid, or no data in our database " + "could be found with the parameters provided.")) { + // probably just doesn't have any history yet or whatever stellar needs + return; + } else { + Logging.instance.log( + "Stellar $walletName $walletId failed to fetch transactions", + level: LogLevel.Warning, + ); + rethrow; + } + } + for (Balance balance in accountResponse.balances) { switch (balance.assetType) { case Asset.TYPE_NATIVE: From 3e36723da305bebe9b3d0a3e1b335e9724664456 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 7 Sep 2023 15:37:23 -0500 Subject: [PATCH 150/237] TorStatusChangedEvent->TorPreferenceChangedEvent --- lib/electrumx_rpc/electrumx.dart | 4 ++-- lib/networking/tor_service.dart | 2 ++ .../event_bus/events/global/tor_status_changed_event.dart | 4 ++-- lib/utilities/prefs.dart | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 81dc67148..847a92aa1 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -82,7 +82,7 @@ class ElectrumX { static final Finalizer _finalizer = Finalizer( (p0) => p0._torStatusListener?.cancel(), ); - StreamSubscription? _torStatusListener; + StreamSubscription? _torStatusListener; ElectrumX({ required String host, @@ -104,7 +104,7 @@ class ElectrumX { _rpcClient = client; final bus = globalEventBusForTesting ?? GlobalEventBus.instance; - _torStatusListener = bus.on().listen( + _torStatusListener = bus.on().listen( (event) async { // not sure if we need to do anything specific here // switch (event.status) { diff --git a/lib/networking/tor_service.dart b/lib/networking/tor_service.dart index 02d520db6..2a13a8006 100644 --- a/lib/networking/tor_service.dart +++ b/lib/networking/tor_service.dart @@ -29,6 +29,7 @@ class TorService { // already started so just return // could throw an exception here or something so the caller // is explicitly made aware of this + // TODO restart tor after that's been added to the tor-ffi crate return; } @@ -51,6 +52,7 @@ class TorService { // already stopped so just return // could throw an exception here or something so the caller // is explicitly made aware of this + // TODO make sure to kill return; } diff --git a/lib/services/event_bus/events/global/tor_status_changed_event.dart b/lib/services/event_bus/events/global/tor_status_changed_event.dart index cf9cac5ee..6f974bf75 100644 --- a/lib/services/event_bus/events/global/tor_status_changed_event.dart +++ b/lib/services/event_bus/events/global/tor_status_changed_event.dart @@ -12,11 +12,11 @@ import 'package:stackwallet/utilities/logger.dart'; enum TorStatus { enabled, disabled } -class TorStatusChangedEvent { +class TorPreferenceChangedEvent { String? message; TorStatus status; - TorStatusChangedEvent({ + TorPreferenceChangedEvent({ required this.status, this.message, }) { diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index 8adb19ce3..027c6037d 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -911,7 +911,7 @@ class Prefs extends ChangeNotifier { _useTor = useTor; notifyListeners(); GlobalEventBus.instance.fire( - TorStatusChangedEvent( + TorPreferenceChangedEvent( status: useTor ? TorStatus.enabled : TorStatus.disabled, message: "useTor updated in prefs", ), From a8ed46d8041058392163dc09936090fbda0f1102 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 7 Sep 2023 15:44:53 -0500 Subject: [PATCH 151/237] TorSyncStatusEvent->TorConnectionStatusEvent and rename file --- lib/pages/home_view/home_view.dart | 14 ++++++------- ... tor_connection_status_changed_event.dart} | 8 ++++---- .../tor_settings/tor_settings_view.dart | 20 +++++++++---------- lib/pages_desktop_specific/desktop_menu.dart | 12 +++++------ 4 files changed, 27 insertions(+), 27 deletions(-) rename lib/pages/home_view/sub_widgets/{tor_sync_status_changed_event.dart => tor_connection_status_changed_event.dart} (68%) diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index 759c7760d..71427ab4c 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -17,7 +17,7 @@ import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages/buy_view/buy_view.dart'; import 'package:stackwallet/pages/exchange_view/exchange_view.dart'; import 'package:stackwallet/pages/home_view/sub_widgets/home_view_button_bar.dart'; -import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart'; +import 'package:stackwallet/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart'; import 'package:stackwallet/pages/notification_views/notifications_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/global_settings_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/hidden_settings.dart'; @@ -57,7 +57,7 @@ class _HomeViewState extends ConsumerState { bool _exitEnabled = false; - late TorSyncStatus _currentSyncStatus; + late TorConnectionStatus _currentSyncStatus; // final _buyDataLoadingService = BuyDataLoadingService(); @@ -117,23 +117,23 @@ class _HomeViewState extends ConsumerState { ); } - Widget _buildTorIcon(TorSyncStatus status) { + Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { - case TorSyncStatus.unableToSync: + case TorConnectionStatus.unableToConnect: return SvgPicture.asset( Assets.svg.tor, color: Theme.of(context).extension()!.textSubtitle3, width: 20, height: 20, ); - case TorSyncStatus.synced: + case TorConnectionStatus.connected: return SvgPicture.asset( Assets.svg.tor, color: Theme.of(context).extension()!.accentColorGreen, width: 20, height: 20, ); - case TorSyncStatus.syncing: + case TorConnectionStatus.connecting: return SvgPicture.asset( Assets.svg.tor, color: Theme.of(context).extension()!.accentColorYellow, @@ -261,7 +261,7 @@ class _HomeViewState extends ConsumerState { color: Theme.of(context) .extension()! .backgroundAppBar, - icon: _buildTorIcon(TorSyncStatus.unableToSync), + icon: _buildTorIcon(TorConnectionStatus.unableToConnect), onPressed: () { Navigator.of(context) .pushNamed(TorSettingsView.routeName); diff --git a/lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart b/lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart similarity index 68% rename from lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart rename to lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart index 87910b806..00682d32e 100644 --- a/lib/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart +++ b/lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart @@ -9,12 +9,12 @@ */ import 'package:stackwallet/utilities/logger.dart'; -enum TorSyncStatus { unableToSync, synced, syncing } +enum TorConnectionStatus { unableToConnect, connected, connecting } -class TorSyncStatusChangedEvent { - TorSyncStatus newStatus; +class TorConnectionStatusChangedEvent { + TorConnectionStatus newStatus; - TorSyncStatusChangedEvent(this.newStatus) { + TorConnectionStatusChangedEvent(this.newStatus) { Logging.instance.log( "TorSyncStatusChangedEvent fired with arg newStatus = $newStatus", level: LogLevel.Info); diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 8304eb851..731f31f1a 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart'; +import 'package:stackwallet/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; @@ -35,11 +35,11 @@ class TorSettingsView extends ConsumerStatefulWidget { } class _TorSettingsViewState extends ConsumerState { - TorSyncStatus _networkStatus = TorSyncStatus.unableToSync; + TorConnectionStatus _networkStatus = TorConnectionStatus.unableToConnect; - Widget _buildTorIcon(TorSyncStatus status) { + Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { - case TorSyncStatus.unableToSync: + case TorConnectionStatus.unableToConnect: return Stack( alignment: AlignmentDirectional.center, children: [ @@ -56,7 +56,7 @@ class _TorSettingsViewState extends ConsumerState { ) ], ); - case TorSyncStatus.synced: + case TorConnectionStatus.connected: return Stack( alignment: AlignmentDirectional.center, children: [ @@ -74,7 +74,7 @@ class _TorSettingsViewState extends ConsumerState { ) ], ); - case TorSyncStatus.syncing: + case TorConnectionStatus.connecting: return Stack( alignment: AlignmentDirectional.center, children: [ @@ -95,22 +95,22 @@ class _TorSettingsViewState extends ConsumerState { } } - Widget _buildTorStatus(TorSyncStatus status) { + Widget _buildTorStatus(TorConnectionStatus status) { switch (status) { - case TorSyncStatus.unableToSync: + case TorConnectionStatus.unableToConnect: return Text( "Disconnected", style: STextStyles.itemSubtitle(context).copyWith( color: Theme.of(context).extension()!.textSubtitle3), ); - case TorSyncStatus.synced: + case TorConnectionStatus.connected: return Text( "Connected", style: STextStyles.itemSubtitle(context).copyWith( color: Theme.of(context).extension()!.accentColorGreen), ); - case TorSyncStatus.syncing: + case TorConnectionStatus.connecting: return Text( "Connecting", style: STextStyles.itemSubtitle(context).copyWith( diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index b21a1d724..62aa30ec8 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -14,7 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stackwallet/pages/home_view/sub_widgets/tor_sync_status_changed_event.dart'; +import 'package:stackwallet/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu.dart'; import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart'; @@ -59,9 +59,9 @@ class _DesktopMenuState extends ConsumerState { // final _buyDataLoadingService = BuyDataLoadingService(); - Widget _buildTorIcon(TorSyncStatus status) { + Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { - case TorSyncStatus.unableToSync: + case TorConnectionStatus.unableToConnect: return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -80,7 +80,7 @@ class _DesktopMenuState extends ConsumerState { ) ], ); - case TorSyncStatus.synced: + case TorConnectionStatus.connected: return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -100,7 +100,7 @@ class _DesktopMenuState extends ConsumerState { ) ], ); - case TorSyncStatus.syncing: + case TorConnectionStatus.connecting: return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -218,7 +218,7 @@ class _DesktopMenuState extends ConsumerState { .watch(selectedSettingsMenuItemStateProvider.state) .state = 4; }, - child: _buildTorIcon(TorSyncStatus.unableToSync)), + child: _buildTorIcon(TorConnectionStatus.unableToConnect)), ), const SizedBox( height: 40, From 850d0bbfd8fb3ba26101761d742cb7bcfac41323 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Thu, 7 Sep 2023 15:04:57 -0600 Subject: [PATCH 152/237] minor text color fix --- .../settings/settings_menu/tor_settings/tor_settings.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index e8d4b3f6a..58f1fc8ee 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -205,7 +205,7 @@ class _TorSettingsState extends ConsumerState { .copyWith( color: Theme.of(context) .extension()! - .accentColorDark), + .textDark), ), TextSpan( text: "\nWhat is Tor killswitch?", From 2c77ac1b5d9d31d7e0c0b617c14c3b477bb03a67 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 7 Sep 2023 16:27:00 -0500 Subject: [PATCH 153/237] fire TorConnectionStatusChangedEvents from tor service and move tor_service file and unableToConnect->disconnected --- lib/electrumx_rpc/electrumx.dart | 2 +- lib/electrumx_rpc/rpc.dart | 2 +- lib/main.dart | 2 +- lib/networking/http.dart | 2 +- lib/pages/home_view/home_view.dart | 4 +-- .../tor_connection_status_changed_event.dart | 7 ++--- .../tor_settings/tor_settings_view.dart | 6 ++--- lib/pages_desktop_specific/desktop_menu.dart | 4 +-- lib/{networking => services}/tor_service.dart | 27 +++++++++++++++++++ 9 files changed, 42 insertions(+), 14 deletions(-) rename lib/{networking => services}/tor_service.dart (62%) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 847a92aa1..e09446e43 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -17,9 +17,9 @@ import 'package:decimal/decimal.dart'; import 'package:event_bus/event_bus.dart'; import 'package:stackwallet/electrumx_rpc/rpc.dart'; import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; -import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/services/event_bus/events/global/tor_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/global_event_bus.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:uuid/uuid.dart'; diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index a6335bf9e..5d0f503b8 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -15,7 +15,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; import 'package:stackwallet/networking/socks_socket.dart'; -import 'package:stackwallet/networking/tor_service.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; diff --git a/lib/main.dart b/lib/main.dart index 2eb63fdb0..d919e0ae7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,7 +38,6 @@ import 'package:stackwallet/models/models.dart'; import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/notification_model.dart'; import 'package:stackwallet/models/trade_wallet_lookup.dart'; -import 'package:stackwallet/networking/tor_service.dart'; import 'package:stackwallet/pages/home_view/home_view.dart'; import 'package:stackwallet/pages/intro_view.dart'; import 'package:stackwallet/pages/loading_view.dart'; @@ -60,6 +59,7 @@ import 'package:stackwallet/services/locale_service.dart'; import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/services/notifications_api.dart'; import 'package:stackwallet/services/notifications_service.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/services/trade_service.dart'; import 'package:stackwallet/themes/theme_providers.dart'; import 'package:stackwallet/themes/theme_service.dart'; diff --git a/lib/networking/http.dart b/lib/networking/http.dart index 5ab41a5d8..62c8d225e 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:socks5_proxy/socks_client.dart'; -import 'package:stackwallet/networking/tor_service.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; // WIP wrapper layer diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index 71427ab4c..b611421a9 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -119,7 +119,7 @@ class _HomeViewState extends ConsumerState { Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { - case TorConnectionStatus.unableToConnect: + case TorConnectionStatus.disconnected: return SvgPicture.asset( Assets.svg.tor, color: Theme.of(context).extension()!.textSubtitle3, @@ -261,7 +261,7 @@ class _HomeViewState extends ConsumerState { color: Theme.of(context) .extension()! .backgroundAppBar, - icon: _buildTorIcon(TorConnectionStatus.unableToConnect), + icon: _buildTorIcon(TorConnectionStatus.disconnected), onPressed: () { Navigator.of(context) .pushNamed(TorSettingsView.routeName); diff --git a/lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart b/lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart index 00682d32e..0a395b6a5 100644 --- a/lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart +++ b/lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart @@ -9,14 +9,15 @@ */ import 'package:stackwallet/utilities/logger.dart'; -enum TorConnectionStatus { unableToConnect, connected, connecting } +enum TorConnectionStatus { disconnected, connecting, connected } class TorConnectionStatusChangedEvent { TorConnectionStatus newStatus; + String message = ""; - TorConnectionStatusChangedEvent(this.newStatus) { + TorConnectionStatusChangedEvent(this.newStatus, this.message) { Logging.instance.log( - "TorSyncStatusChangedEvent fired with arg newStatus = $newStatus", + "TorSyncStatusChangedEvent fired with arg newStatus = $newStatus ($message)", level: LogLevel.Info); } } diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 731f31f1a..241cd1cd6 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -35,11 +35,11 @@ class TorSettingsView extends ConsumerStatefulWidget { } class _TorSettingsViewState extends ConsumerState { - TorConnectionStatus _networkStatus = TorConnectionStatus.unableToConnect; + TorConnectionStatus _networkStatus = TorConnectionStatus.disconnected; Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { - case TorConnectionStatus.unableToConnect: + case TorConnectionStatus.disconnected: return Stack( alignment: AlignmentDirectional.center, children: [ @@ -97,7 +97,7 @@ class _TorSettingsViewState extends ConsumerState { Widget _buildTorStatus(TorConnectionStatus status) { switch (status) { - case TorConnectionStatus.unableToConnect: + case TorConnectionStatus.disconnected: return Text( "Disconnected", style: STextStyles.itemSubtitle(context).copyWith( diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index 62aa30ec8..bf5239bda 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -61,7 +61,7 @@ class _DesktopMenuState extends ConsumerState { Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { - case TorConnectionStatus.unableToConnect: + case TorConnectionStatus.disconnected: return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -218,7 +218,7 @@ class _DesktopMenuState extends ConsumerState { .watch(selectedSettingsMenuItemStateProvider.state) .state = 4; }, - child: _buildTorIcon(TorConnectionStatus.unableToConnect)), + child: _buildTorIcon(TorConnectionStatus.disconnected)), ), const SizedBox( height: 40, diff --git a/lib/networking/tor_service.dart b/lib/services/tor_service.dart similarity index 62% rename from lib/networking/tor_service.dart rename to lib/services/tor_service.dart index 2a13a8006..074e62e6e 100644 --- a/lib/networking/tor_service.dart +++ b/lib/services/tor_service.dart @@ -1,6 +1,8 @@ import 'dart:io'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:tor/tor.dart'; @@ -34,15 +36,34 @@ class TorService { } try { + GlobalEventBus.instance.fire( + TorConnectionStatusChangedEvent( + TorConnectionStatus.connecting, + "Tor connection status changed: connecting", + ), + ); await _tor.start(); // no exception or error so we can (probably?) assume tor // has started successfully _enabled = true; + GlobalEventBus.instance.fire( + TorConnectionStatusChangedEvent( + TorConnectionStatus.connected, + "Tor connection status changed: connect ($_enabled)", + ), + ); } catch (e, s) { Logging.instance.log( "TorService.start failed: $e\n$s", level: LogLevel.Warning, ); + // _enabled should already be false + GlobalEventBus.instance.fire( + TorConnectionStatusChangedEvent( + TorConnectionStatus.disconnected, + "Tor connection status changed: $_enabled (failed)", + ), + ); rethrow; } } @@ -61,6 +82,12 @@ class TorService { // no exception or error so we can (probably?) assume tor // has started successfully _enabled = false; + GlobalEventBus.instance.fire( + TorConnectionStatusChangedEvent( + TorConnectionStatus.disconnected, + "Tor connection status changed: $_enabled (disabled)", + ), + ); } catch (e, s) { Logging.instance.log( "TorService.stop failed: $e\n$s", From de632023e00f24b3d28a2dbb3b54ba88e2d5cb40 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 7 Sep 2023 17:13:04 -0500 Subject: [PATCH 154/237] don't enable tor by default --- lib/main.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d919e0ae7..8df829495 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -168,9 +168,7 @@ void main() async { await Hive.openBox(DB.boxNamePrefs); await Prefs.instance.init(); - // TODO remove this!!!! - Prefs.instance.useTor = true; - + // Prefs.instance.useTor = true; // For testing purposes only. if (Prefs.instance.useTor) { await TorService.sharedInstance.start(); } From a0491b9d22a076314925387c283b9f2cbb519f4a Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 7 Sep 2023 17:13:27 -0500 Subject: [PATCH 155/237] move tor_connection_status_changed_event.dart to event_bus global folder --- lib/pages/home_view/home_view.dart | 2 +- .../global_settings_view/tor_settings/tor_settings_view.dart | 2 +- lib/pages_desktop_specific/desktop_menu.dart | 2 +- .../events/global}/tor_connection_status_changed_event.dart | 0 lib/services/tor_service.dart | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename lib/{pages/home_view/sub_widgets => services/event_bus/events/global}/tor_connection_status_changed_event.dart (100%) diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index b611421a9..7fcc9f4ca 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -17,7 +17,6 @@ import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages/buy_view/buy_view.dart'; import 'package:stackwallet/pages/exchange_view/exchange_view.dart'; import 'package:stackwallet/pages/home_view/sub_widgets/home_view_button_bar.dart'; -import 'package:stackwallet/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart'; import 'package:stackwallet/pages/notification_views/notifications_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/global_settings_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/hidden_settings.dart'; @@ -26,6 +25,7 @@ import 'package:stackwallet/pages/wallets_view/wallets_view.dart'; import 'package:stackwallet/providers/global/notifications_provider.dart'; import 'package:stackwallet/providers/ui/home_view_index_provider.dart'; import 'package:stackwallet/providers/ui/unread_notifications_provider.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_providers.dart'; import 'package:stackwallet/utilities/assets.dart'; diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 241cd1cd6..76b51889d 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -11,8 +11,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stackwallet/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index bf5239bda..9394be09c 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -14,7 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stackwallet/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu.dart'; import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart'; diff --git a/lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart b/lib/services/event_bus/events/global/tor_connection_status_changed_event.dart similarity index 100% rename from lib/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart rename to lib/services/event_bus/events/global/tor_connection_status_changed_event.dart diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index 074e62e6e..a297bcdc7 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:stackwallet/pages/home_view/sub_widgets/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:tor/tor.dart'; From 6b76696edf4c543a8353b84b5a181f7945252a1a Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 7 Sep 2023 17:14:50 -0500 Subject: [PATCH 156/237] package imports --- .../settings/settings_menu/tor_settings/tor_settings.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index 58f1fc8ee..d3cd2683b 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -12,18 +12,17 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -import '../../../../providers/global/prefs_provider.dart'; -import '../../../../themes/stack_colors.dart'; -import '../../../../widgets/custom_buttons/draggable_switch_button.dart'; - class TorSettings extends ConsumerStatefulWidget { const TorSettings({Key? key}) : super(key: key); From bc25d5b3af81c5bde40468ece3c42920b8ecf69f Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 7 Sep 2023 16:41:44 -0600 Subject: [PATCH 157/237] WIP stellar memo field on send screens as well as in trade details and exchange flow --- .../exchange_step_views/step_4_view.dart | 75 ++++++++++ lib/pages/exchange_view/send_from_view.dart | 7 + .../exchange_view/trade_details_view.dart | 75 ++++++++++ lib/pages/send_view/send_view.dart | 139 +++++++++++++++--- .../subwidgets/desktop_step_4.dart | 17 +++ .../wallet_view/sub_widgets/desktop_send.dart | 88 +++++++++++ .../coins/stellar/stellar_wallet.dart | 93 ++++++------ 7 files changed, 431 insertions(+), 63 deletions(-) diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart index 25967801a..d491899f8 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart @@ -252,10 +252,17 @@ class _Step4ViewState extends ConsumerState { }, ); } else { + final memo = + manager.coin == Coin.stellar || manager.coin == Coin.stellarTestnet + ? model.trade!.payInExtraId.isNotEmpty + ? model.trade!.payInExtraId + : null + : null; txDataFuture = manager.prepareSend( address: address, amount: amount, args: { + "memo": memo, "feeRate": FeeRateType.average, // ref.read(feeRateTypeStateProvider) }, @@ -568,6 +575,74 @@ class _Step4ViewState extends ConsumerState { const SizedBox( height: 6, ), + if (model.trade!.payInExtraId.isNotEmpty) + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Memo", + style: + STextStyles.itemSubtitle(context), + ), + GestureDetector( + onTap: () async { + final data = ClipboardData( + text: + model.trade!.payInExtraId); + await clipboard.setData(data); + if (mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + context: context, + ), + ); + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + color: Theme.of(context) + .extension()! + .infoItemIcons, + width: 10, + ), + const SizedBox( + width: 4, + ), + Text( + "Copy", + style: + STextStyles.link2(context), + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 4, + ), + Text( + model.trade!.payInExtraId, + style: + STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + if (model.trade!.payInExtraId.isNotEmpty) + const SizedBox( + height: 6, + ), RoundedWhiteContainer( child: Row( children: [ diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index 4935a1b20..68b595900 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -268,10 +268,17 @@ class _SendFromCardState extends ConsumerState { // if not firo then do normal send if (shouldSendPublicFiroFunds == null) { + final memo = + manager.coin == Coin.stellar || manager.coin == Coin.stellarTestnet + ? trade.payInExtraId.isNotEmpty + ? trade.payInExtraId + : null + : null; txDataFuture = manager.prepareSend( address: address, amount: amount, args: { + "memo": memo, "feeRate": FeeRateType.average, // ref.read(feeRateTypeStateProvider) }, diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index ff9b7ae24..24208a19c 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -850,6 +850,81 @@ class _TradeDetailsViewState extends ConsumerState { : const SizedBox( height: 12, ), + if (trade.payInExtraId.isNotEmpty && !sentFromStack && !hasTx) + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Memo", + style: STextStyles.itemSubtitle(context), + ), + isDesktop + ? IconCopyButton( + data: trade.payInExtraId, + ) + : GestureDetector( + onTap: () async { + final address = trade.payInExtraId; + await Clipboard.setData( + ClipboardData( + text: address, + ), + ); + if (mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + context: context, + ), + ); + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + width: 12, + height: 12, + color: Theme.of(context) + .extension()! + .infoItemIcons, + ), + const SizedBox( + width: 4, + ), + Text( + "Copy", + style: STextStyles.link2(context), + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 4, + ), + SelectableText( + trade.payInExtraId, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + if (trade.payInExtraId.isNotEmpty && !sentFromStack && !hasTx) + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), RoundedWhiteContainer( padding: isDesktop ? const EdgeInsets.all(16) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index c3e66e758..01131b536 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -103,6 +103,7 @@ class _SendViewState extends ConsumerState { late TextEditingController noteController; late TextEditingController onChainNoteController; late TextEditingController feeController; + late TextEditingController memoController; late final SendViewAutoFillData? _data; @@ -111,6 +112,9 @@ class _SendViewState extends ConsumerState { final _onChainNoteFocusNode = FocusNode(); final _cryptoFocus = FocusNode(); final _baseFocus = FocusNode(); + final _memoFocus = FocusNode(); + + late final bool isStellar; Amount? _amountToSend; Amount? _cachedAmountToSend; @@ -522,10 +526,15 @@ class _SendViewState extends ConsumerState { }, ); } else { + final memo = + manager.coin == Coin.stellar || manager.coin == Coin.stellarTestnet + ? memoController.text + : null; txDataFuture = manager.prepareSend( address: _address!, amount: amount, args: { + "memo": memo, "feeRate": ref.read(feeRateTypeStateProvider), "satsPerVByte": isCustomFee ? customFeeRate : null, "UTXOs": (manager.hasCoinControlSupport && @@ -622,6 +631,7 @@ class _SendViewState extends ConsumerState { walletId = widget.walletId; clipboard = widget.clipboard; scanner = widget.barcodeScanner; + isStellar = coin == Coin.stellar || coin == Coin.stellarTestnet; sendToController = TextEditingController(); cryptoAmountController = TextEditingController(); @@ -629,6 +639,7 @@ class _SendViewState extends ConsumerState { noteController = TextEditingController(); onChainNoteController = TextEditingController(); feeController = TextEditingController(); + memoController = TextEditingController(); onCryptoAmountChanged = _cryptoAmountChanged; cryptoAmountController.addListener(onCryptoAmountChanged); @@ -704,12 +715,14 @@ class _SendViewState extends ConsumerState { noteController.dispose(); onChainNoteController.dispose(); feeController.dispose(); + memoController.dispose(); _noteFocusNode.dispose(); _onChainNoteFocusNode.dispose(); _addressFocusNode.dispose(); _cryptoFocus.dispose(); _baseFocus.dispose(); + _memoFocus.dispose(); super.dispose(); } @@ -1298,6 +1311,88 @@ class _SendViewState extends ConsumerState { ), ), ), + const SizedBox( + height: 10, + ), + if (isStellar) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key("sendViewMemoFieldKey"), + controller: memoController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + focusNode: _memoFocus, + style: STextStyles.field(context), + onChanged: (_) { + setState(() {}); + }, + decoration: standardInputDecoration( + "Enter memo (optional)", + _memoFocus, + context, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: memoController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + memoController.text.isNotEmpty + ? TextFieldIconButton( + semanticsLabel: + "Clear Button. Clears The Memo Field Input.", + key: const Key( + "sendViewClearMemoFieldButtonKey"), + onTap: () { + memoController.text = ""; + setState(() {}); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + semanticsLabel: + "Paste Button. Pastes From Clipboard To Memo Field Input.", + key: const Key( + "sendViewPasteMemoFieldButtonKey"), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard + .kTextPlain); + if (data?.text != null && + data! + .text!.isNotEmpty) { + String content = + data.text!.trim(); + + memoController.text = + content.trim(); + + setState(() {}); + } + }, + child: const ClipboardIcon(), + ), + ], + ), + ), + ), + ), + ), + ), Builder( builder: (_) { final error = _updateInvalidAddressText( @@ -1817,7 +1912,8 @@ class _SendViewState extends ConsumerState { ), child: TextField( autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, maxLength: 256, controller: onChainNoteController, focusNode: _onChainNoteFocusNode, @@ -1828,25 +1924,27 @@ class _SendViewState extends ConsumerState { _onChainNoteFocusNode, context, ).copyWith( - suffixIcon: onChainNoteController.text.isNotEmpty + suffixIcon: onChainNoteController + .text.isNotEmpty ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - onChainNoteController.text = ""; - }); - }, + padding: + const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + onChainNoteController + .text = ""; + }); + }, + ), + ], + ), ), - ], - ), - ), - ) + ) : null, ), ), @@ -1856,8 +1954,9 @@ class _SendViewState extends ConsumerState { height: 12, ), Text( - (coin == Coin.epicCash) ? "Local Note (optional)" - : "Note (optional)", + (coin == Coin.epicCash) + ? "Local Note (optional)" + : "Note (optional)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart index 8b30b2e2a..437e45210 100644 --- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart +++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart @@ -155,6 +155,23 @@ class _DesktopStep4State extends ConsumerState { height: 1, color: Theme.of(context).extension()!.background, ), + if (ref.watch(desktopExchangeModelProvider + .select((value) => value!.trade?.payInExtraId)) != + null) + DesktopStepItem( + vertical: true, + label: "Memo", + value: ref.watch(desktopExchangeModelProvider + .select((value) => value!.trade?.payInExtraId)) ?? + "Error", + ), + if (ref.watch(desktopExchangeModelProvider + .select((value) => value!.trade?.payInExtraId)) != + null) + Container( + height: 1, + color: Theme.of(context).extension()!.background, + ), DesktopStepItem( label: "Amount", value: diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 3d65eb6e2..f9f24cb76 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -97,12 +97,16 @@ class _DesktopSendState extends ConsumerState { late TextEditingController cryptoAmountController; late TextEditingController baseAmountController; // late TextEditingController feeController; + late TextEditingController memoController; late final SendViewAutoFillData? _data; final _addressFocusNode = FocusNode(); final _cryptoFocus = FocusNode(); final _baseFocus = FocusNode(); + final _memoFocus = FocusNode(); + + late final bool isStellar; String? _note; String? _onChainNote; @@ -326,10 +330,12 @@ class _DesktopSendState extends ConsumerState { }, ); } else { + final memo = isStellar ? memoController.text : null; txDataFuture = manager.prepareSend( address: _address!, amount: amount, args: { + "memo": memo, "feeRate": ref.read(feeRateTypeStateProvider), "satsPerVByte": isCustomFee ? customFeeRate : null, "UTXOs": (manager.hasCoinControlSupport && @@ -663,6 +669,23 @@ class _DesktopSendState extends ConsumerState { } } + Future pasteMemo() async { + if (memoController.text.isNotEmpty) { + setState(() { + memoController.text = ""; + }); + } else { + final ClipboardData? data = await clipboard.getData(Clipboard.kTextPlain); + if (data?.text != null && data!.text!.isNotEmpty) { + String content = data.text!.trim(); + + setState(() { + memoController.text = content; + }); + } + } + } + void fiatTextFieldOnChanged(String baseAmountString) { final baseAmount = Amount.tryParseFiatString( baseAmountString, @@ -762,10 +785,12 @@ class _DesktopSendState extends ConsumerState { coin = ref.read(walletsChangeNotifierProvider).getManager(walletId).coin; clipboard = widget.clipboard; scanner = widget.barcodeScanner; + isStellar = coin == Coin.stellar || coin == Coin.stellarTestnet; sendToController = TextEditingController(); cryptoAmountController = TextEditingController(); baseAmountController = TextEditingController(); + memoController = TextEditingController(); // feeController = TextEditingController(); onCryptoAmountChanged = _cryptoAmountChanged; @@ -814,11 +839,13 @@ class _DesktopSendState extends ConsumerState { sendToController.dispose(); cryptoAmountController.dispose(); baseAmountController.dispose(); + memoController.dispose(); // feeController.dispose(); _addressFocusNode.dispose(); _cryptoFocus.dispose(); _baseFocus.dispose(); + _memoFocus.dispose(); super.dispose(); } @@ -1367,6 +1394,67 @@ class _DesktopSendState extends ConsumerState { } }, ), + if (isStellar) + const SizedBox( + height: 10, + ), + if (isStellar) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + minLines: 1, + maxLines: 5, + key: const Key("sendViewMemoFieldKey"), + controller: memoController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + focusNode: _memoFocus, + onChanged: (_) { + setState(() {}); + }, + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ), + decoration: standardInputDecoration( + "Enter memo (optional)", + _memoFocus, + context, + desktopMed: true, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ), + suffixIcon: Padding( + padding: memoController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + TextFieldIconButton( + key: const Key("sendViewPasteMemoButtonKey"), + onTap: pasteMemo, + child: memoController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + ], + ), + ), + ), + ), + ), + ), if (!isPaynymSend) const SizedBox( height: 20, diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index 064c1310b..8efe7fbdd 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -181,6 +181,41 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { return exists; } + @override + Future> prepareSend( + {required String address, + required Amount amount, + Map? args}) async { + try { + final feeRate = args?["feeRate"]; + var fee = 1000; + if (feeRate is FeeRateType) { + final theFees = await fees; + switch (feeRate) { + case FeeRateType.fast: + fee = theFees.fast; + case FeeRateType.slow: + fee = theFees.slow; + case FeeRateType.average: + default: + fee = theFees.medium; + } + } + Map txData = { + "fee": fee, + "address": address, + "recipientAmt": amount, + "memo": args?["memo"] as String?, + }; + + Logging.instance.log("prepare send: $txData", level: LogLevel.Info); + return txData; + } catch (e, s) { + Logging.instance.log("Error getting fees $e - $s", level: LogLevel.Error); + rethrow; + } + } + @override Future confirmSend({required Map txData}) async { final secretSeed = await _secureStore.read(key: '${_walletId}_secretSeed'); @@ -188,27 +223,33 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { AccountResponse sender = await stellarSdk.accounts.account(senderKeyPair.accountId); final amountToSend = txData['recipientAmt'] as Amount; + final memo = txData["memo"] as String?; //First check if account exists, can be skipped, but if the account does not exist, // the transaction fee will be charged when the transaction fails. bool validAccount = await _accountExists(txData['address'] as String); - Transaction transaction; + TransactionBuilder transactionBuilder; if (!validAccount) { //Fund the account, user must ensure account is correct CreateAccountOperationBuilder createAccBuilder = CreateAccountOperationBuilder( txData['address'] as String, amountToSend.decimal.toString()); - transaction = TransactionBuilder(sender) - .addOperation(createAccBuilder.build()) - .build(); + transactionBuilder = + TransactionBuilder(sender).addOperation(createAccBuilder.build()); } else { - transaction = TransactionBuilder(sender) - .addOperation(PaymentOperationBuilder(txData['address'] as String, - Asset.NATIVE, amountToSend.decimal.toString()) - .build()) - .build(); + transactionBuilder = TransactionBuilder(sender).addOperation( + PaymentOperationBuilder(txData['address'] as String, Asset.NATIVE, + amountToSend.decimal.toString()) + .build()); } + + if (memo != null) { + transactionBuilder.addMemo(MemoText(memo)); + } + + final transaction = transactionBuilder.build(); + transaction.sign(senderKeyPair, stellarNetwork); try { SubmitTransactionResponse response = await stellarSdk @@ -441,40 +482,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB { Future get mnemonicString => _secureStore.read(key: '${_walletId}_mnemonic'); - @override - Future> prepareSend( - {required String address, - required Amount amount, - Map? args}) async { - try { - final feeRate = args?["feeRate"]; - var fee = 1000; - if (feeRate is FeeRateType) { - final theFees = await fees; - switch (feeRate) { - case FeeRateType.fast: - fee = theFees.fast; - case FeeRateType.slow: - fee = theFees.slow; - case FeeRateType.average: - default: - fee = theFees.medium; - } - } - Map txData = { - "fee": fee, - "address": address, - "recipientAmt": amount, - }; - - Logging.instance.log("prepare send: $txData", level: LogLevel.Info); - return txData; - } catch (e, s) { - Logging.instance.log("Error getting fees $e - $s", level: LogLevel.Error); - rethrow; - } - } - Future _recoverWalletFromBIP32SeedPhrase({ required String mnemonic, required String mnemonicPassphrase, From 5cf202efc078dd193979859ef4e693aebf0061a7 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 7 Sep 2023 17:56:48 -0500 Subject: [PATCH 158/237] add a status getter to the tor service and document it --- lib/services/tor_service.dart | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index a297bcdc7..f6d412b0a 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -10,12 +10,29 @@ final pTorService = Provider((_) => TorService.sharedInstance); class TorService { final _tor = Tor(); + + /// Flag to indicate that a Tor circuit is thought to have been established. bool _enabled = false; + /// Getter for the enabled flag. + bool get enabled => _enabled; + + /// The current status of the Tor connection. + TorConnectionStatus _status = TorConnectionStatus.disconnected; + + /// Getter for the status. + /// + /// Used mostly to indicate "Connected" status in the UI. + TorConnectionStatus get status => _status; + TorService._(); + /// Singleton instance of the TorService. + /// + /// Use this to access the TorService and its properties. static final sharedInstance = TorService._(); + /// Getter for the proxyInfo. ({ InternetAddress host, int port, @@ -24,9 +41,17 @@ class TorService { port: _tor.port, ); - bool get enabled => _enabled; - + /// Start the Tor service. + /// + /// This will start the Tor service and establish a Tor circuit. + /// + /// Throws an exception if the Tor service fails to start. + /// + /// Returns a Future that completes when the Tor service has started. Future start() async { + // Set the status to connecting. + _status = TorConnectionStatus.connecting; + if (_enabled) { // already started so just return // could throw an exception here or something so the caller @@ -35,6 +60,7 @@ class TorService { return; } + // Start the Tor service. try { GlobalEventBus.instance.fire( TorConnectionStatusChangedEvent( @@ -69,6 +95,9 @@ class TorService { } Future stop() async { + // Set the status to disconnected. + _status = TorConnectionStatus.disconnected; + if (!_enabled) { // already stopped so just return // could throw an exception here or something so the caller @@ -77,6 +106,7 @@ class TorService { return; } + // Stop the Tor service. try { await _tor.disable(); // no exception or error so we can (probably?) assume tor From 79c1dee7adfa5f417066c47a7fd838ae55666fd3 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 7 Sep 2023 18:28:55 -0500 Subject: [PATCH 159/237] hook up existing ui elements to the tor service and add a status getter to the tor service --- lib/pages_desktop_specific/desktop_menu.dart | 97 ++++++++++++++----- .../tor_settings/tor_settings.dart | 92 ++++++++++++++++-- lib/services/tor_service.dart | 10 ++ 3 files changed, 170 insertions(+), 29 deletions(-) diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index 9394be09c..eb6646898 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -8,21 +8,26 @@ * */ +import 'dart:async'; import 'dart:io'; +import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu.dart'; import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/desktop/living_stack_icon.dart'; +import '../services/event_bus/global_event_bus.dart'; + enum DesktopMenuItemId { myStack, exchange, @@ -59,6 +64,17 @@ class _DesktopMenuState extends ConsumerState { // final _buyDataLoadingService = BuyDataLoadingService(); + /// The global event bus. + late final EventBus eventBus; + + /// The subscription to the TorConnectionStatusChangedEvent. + late StreamSubscription + _torConnectionStatusSubscription; + + /// The current status of the Tor connection. + TorConnectionStatus _torConnectionStatus = TorConnectionStatus.disconnected; + + /// Builds the tor icon based on the current status. Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { case TorConnectionStatus.disconnected: @@ -80,26 +96,6 @@ class _DesktopMenuState extends ConsumerState { ) ], ); - case TorConnectionStatus.connected: - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: - Theme.of(context).extension()!.accentColorGreen, - width: 20, - height: 20, - ), - Text( - "\tConnected", - style: STextStyles.smallMed12(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorGreen), - ) - ], - ); case TorConnectionStatus.connecting: return Row( mainAxisAlignment: MainAxisAlignment.center, @@ -120,6 +116,26 @@ class _DesktopMenuState extends ConsumerState { ) ], ); + case TorConnectionStatus.connected: + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: + Theme.of(context).extension()!.accentColorGreen, + width: 20, + height: 20, + ), + Text( + "\tConnected", + style: STextStyles.smallMed12(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorGreen), + ) + ], + ); } } @@ -157,6 +173,39 @@ class _DesktopMenuState extends ConsumerState { DMIController(), ]; + // Initialize the global event bus. + eventBus = GlobalEventBus.instance; + + // Subscribe to the TorConnectionStatusChangedEvent. + _torConnectionStatusSubscription = + eventBus.on().listen( + (event) async { + // Rebuild the widget. + setState(() { + _torConnectionStatus = event.newStatus; + }); + + // TODO implement spinner or animations and control from here + // switch (event.newStatus) { + // case TorConnectionStatus.disconnected: + // // if (_spinController.hasLoadedAnimation) { + // // _spinController.stop?.call(); + // // } + // break; + // case TorConnectionStatus.connecting: + // // if (_spinController.hasLoadedAnimation) { + // // _spinController.repeat?.call(); + // // } + // break; + // case TorConnectionStatus.connected: + // // if (_spinController.hasLoadedAnimation) { + // // _spinController.stop?.call(); + // // } + // break; + // } + }, + ); + super.initState(); } @@ -165,6 +214,10 @@ class _DesktopMenuState extends ConsumerState { for (var e in controllers) { e.dispose(); } + + // Clean up the subscription to the TorConnectionStatusChangedEvent. + _torConnectionStatusSubscription.cancel(); + super.dispose(); } @@ -218,7 +271,7 @@ class _DesktopMenuState extends ConsumerState { .watch(selectedSettingsMenuItemStateProvider.state) .state = 4; }, - child: _buildTorIcon(TorConnectionStatus.disconnected)), + child: _buildTorIcon(TorService.sharedInstance.status)), ), const SizedBox( height: 40, diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index d3cd2683b..53616117e 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -8,11 +8,17 @@ * */ +import 'dart:async'; + +import 'package:event_bus/event_bus.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; @@ -23,6 +29,8 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; +import '../../../../utilities/prefs.dart'; + class TorSettings extends ConsumerStatefulWidget { const TorSettings({Key? key}) : super(key: key); @@ -33,13 +41,83 @@ class TorSettings extends ConsumerStatefulWidget { } class _TorSettingsState extends ConsumerState { + // The Prefs instance. + final Prefs _prefs = Prefs.instance; + + /// The global event bus. + EventBus eventBus = GlobalEventBus.instance; + + /// Subscription to the TorConnectionStatusChangedEvent. + late StreamSubscription + _torConnectionStatusSubscription; + + /// The current status of the Tor connection. + TorConnectionStatus _torConnectionStatus = TorConnectionStatus.disconnected; + + Widget _buildConnectButton(TorConnectionStatus status) { + switch (status) { + case TorConnectionStatus.disconnected: + return SecondaryButton( + label: "Connect to Tor", + width: 200, + buttonHeight: ButtonHeight.m, + onPressed: () { + // Toggle the useTor preference. + _prefs.useTor = true; + + // Start the Tor service. + TorService.sharedInstance.start(); + }, + ); + case TorConnectionStatus.connecting: + return AbsorbPointer( + child: SecondaryButton( + label: "Connecting to Tor", + width: 200, + buttonHeight: ButtonHeight.m, + onPressed: () {}, + ), + ); + case TorConnectionStatus.connected: + return SecondaryButton( + label: "Disconnect from Tor", + width: 200, + buttonHeight: ButtonHeight.m, + onPressed: () { + // Toggle the useTor preference. + _prefs.useTor = false; + + // Stop the Tor service. + TorService.sharedInstance.stop(); + }, + ); + } + } + @override void initState() { + // Initialize the global event bus. + eventBus = GlobalEventBus.instance; + + // Subscribe to the TorConnectionStatusChangedEvent. + _torConnectionStatusSubscription = + eventBus.on().listen( + (event) async { + // Rebuild the widget. + setState(() { + _torConnectionStatus = event.newStatus; + }); + }, + ); + super.initState(); } @override void dispose() { + // Clean up the TorConnectionStatusChangedEvent subscription. + _torConnectionStatusSubscription.cancel(); + super.dispose(); } @@ -72,7 +150,12 @@ class _TorSettingsState extends ConsumerState { Padding( padding: const EdgeInsets.all(8.0), child: SvgPicture.asset( - Assets.svg.disconnectedButton, + _torConnectionStatus == TorConnectionStatus.connected + ? Assets.svg.connectedButton + : _torConnectionStatus == + TorConnectionStatus.connecting + ? Assets.svg.connectingButton + : Assets.svg.disconnectedButton, width: 48, height: 48, ), @@ -176,12 +259,7 @@ class _TorSettingsState extends ConsumerState { ), Padding( padding: const EdgeInsets.all(10.0), - child: SecondaryButton( - label: "Disconnect from Tor", - width: 200, - buttonHeight: ButtonHeight.m, - onPressed: () {}, - ), + child: _buildConnectButton(TorService.sharedInstance.status), ), const SizedBox( height: 30, diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index f6d412b0a..9b8f27032 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -72,6 +72,11 @@ class TorService { // no exception or error so we can (probably?) assume tor // has started successfully _enabled = true; + + // Set the status to connected. + _status = TorConnectionStatus.connected; + + // Fire a TorConnectionStatusChangedEvent on the event bus. GlobalEventBus.instance.fire( TorConnectionStatusChangedEvent( TorConnectionStatus.connected, @@ -84,6 +89,11 @@ class TorService { level: LogLevel.Warning, ); // _enabled should already be false + + // Set the status to disconnected. + _status = TorConnectionStatus.disconnected; + + // Fire a TorConnectionStatusChangedEvent on the event bus. GlobalEventBus.instance.fire( TorConnectionStatusChangedEvent( TorConnectionStatus.disconnected, From 81bbdb1b6291414a158c77231fcd699781a06510 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 07:53:06 -0600 Subject: [PATCH 160/237] add a couple notes --- lib/main.dart | 6 +++++- lib/services/tor_service.dart | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 8df829495..53c0df498 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -168,7 +168,11 @@ void main() async { await Hive.openBox(DB.boxNamePrefs); await Prefs.instance.init(); - // Prefs.instance.useTor = true; // For testing purposes only. + // TODO: + // This should be moved to happen during the loading animation instead of + // showing a blank screen for 4-10 seconds. + // Some refactoring will need to be done here to make sure we don't make any + // network calls before starting up tor if (Prefs.instance.useTor) { await TorService.sharedInstance.start(); } diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index 9b8f27032..799aa4878 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -57,6 +57,7 @@ class TorService { // could throw an exception here or something so the caller // is explicitly made aware of this // TODO restart tor after that's been added to the tor-ffi crate + // (probably better to have a restart function separately) return; } From 3e9a22547061b20cf84a65f7c0733c0699deaaaa Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 09:18:55 -0600 Subject: [PATCH 161/237] HTTP basic updates --- lib/networking/http.dart | 26 +++++++++++++++---- .../exchange/change_now/change_now_api.dart | 14 +++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/lib/networking/http.dart b/lib/networking/http.dart index 62c8d225e..dc2ee2e8b 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -7,8 +7,16 @@ import 'package:stackwallet/utilities/logger.dart'; // WIP wrapper layer -abstract class HTTP { - static Future get({ +// TODO expand this class +class Response { + final int code; + final String body; + + Response(this.body, this.code); +} + +class HTTP { + Future get({ required Uri url, Map? headers, required bool routeOverTor, @@ -32,7 +40,11 @@ abstract class HTTP { headers.forEach((key, value) => request.headers.add); } - return request.close(); + final response = await request.close(); + return Response( + await response.transform(utf8.decoder).join(), + response.statusCode, + ); } catch (e, s) { Logging.instance.log( "HTTP.get() rethrew: $e\n$s", @@ -44,7 +56,7 @@ abstract class HTTP { } } - static Future post({ + Future post({ required Uri url, Map? headers, Object? body, @@ -73,7 +85,11 @@ abstract class HTTP { request.write(body); - return request.close(); + final response = await request.close(); + return Response( + await response.transform(utf8.decoder).join(), + response.statusCode, + ); } catch (e, s) { Logging.instance.log( "HTTP.post() rethrew: $e\n$s", diff --git a/lib/services/exchange/change_now/change_now_api.dart b/lib/services/exchange/change_now/change_now_api.dart index 1a9067376..d7cd5bcb9 100644 --- a/lib/services/exchange/change_now/change_now_api.dart +++ b/lib/services/exchange/change_now/change_now_api.dart @@ -38,6 +38,8 @@ class ChangeNowAPI { static const String apiVersion = "/v1"; static const String apiVersionV2 = "/v2"; + HTTP client = HTTP(); + ChangeNowAPI._(); static final ChangeNowAPI _instance = ChangeNowAPI._(); static ChangeNowAPI get instance => _instance; @@ -52,14 +54,14 @@ class ChangeNowAPI { Future _makeGetRequest(Uri uri) async { try { - final response = await HTTP.get( + final response = await client.get( url: uri, headers: {'Content-Type': 'application/json'}, routeOverTor: Prefs.instance.useTor, ); String? data; try { - data = await response.transform(utf8.decoder).join(); + data = response.body; final parsed = jsonDecode(data); return parsed; @@ -78,7 +80,7 @@ class ChangeNowAPI { Future _makeGetRequestV2(Uri uri, String apiKey) async { try { - final response = await HTTP.get( + final response = await client.get( url: uri, headers: { // 'Content-Type': 'application/json', @@ -87,7 +89,7 @@ class ChangeNowAPI { routeOverTor: Prefs.instance.useTor, ); - final data = await response.transform(utf8.decoder).join(); + final data = response.body; final parsed = jsonDecode(data); return parsed; @@ -103,7 +105,7 @@ class ChangeNowAPI { Map body, ) async { try { - final response = await HTTP.post( + final response = await client.post( url: uri, headers: {'Content-Type': 'application/json'}, body: jsonEncode(body), @@ -112,7 +114,7 @@ class ChangeNowAPI { String? data; try { - data = await response.transform(utf8.decoder).join(); + data = response.body; final parsed = jsonDecode(data); return parsed; From f6b9548e1d729c43a217dff368c99159f8e2d07a Mon Sep 17 00:00:00 2001 From: Diego Salazar Date: Fri, 8 Sep 2023 09:25:58 -0600 Subject: [PATCH 162/237] Bumped version (1.7.20, build 188) --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index dbb5ecfe5..fece8ca4b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: Stack Wallet # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.7.19+187 +version: 1.7.20+188 environment: sdk: ">=3.0.2 <4.0.0" From cf27dd92527e008d3a5e5ab6d6875208150ab25b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 10:30:49 -0500 Subject: [PATCH 163/237] remove tor service status getter --- lib/pages_desktop_specific/desktop_menu.dart | 9 +++++++-- .../tor_settings/tor_settings.dart | 11 ++++++++-- lib/services/tor_service.dart | 20 ------------------- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index eb6646898..8db055823 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -72,7 +72,7 @@ class _DesktopMenuState extends ConsumerState { _torConnectionStatusSubscription; /// The current status of the Tor connection. - TorConnectionStatus _torConnectionStatus = TorConnectionStatus.disconnected; + late TorConnectionStatus _torConnectionStatus; /// Builds the tor icon based on the current status. Widget _buildTorIcon(TorConnectionStatus status) { @@ -176,6 +176,11 @@ class _DesktopMenuState extends ConsumerState { // Initialize the global event bus. eventBus = GlobalEventBus.instance; + // Initialize the TorConnectionStatus. + _torConnectionStatus = TorService.sharedInstance.enabled + ? TorConnectionStatus.connected + : TorConnectionStatus.disconnected; + // Subscribe to the TorConnectionStatusChangedEvent. _torConnectionStatusSubscription = eventBus.on().listen( @@ -271,7 +276,7 @@ class _DesktopMenuState extends ConsumerState { .watch(selectedSettingsMenuItemStateProvider.state) .state = 4; }, - child: _buildTorIcon(TorService.sharedInstance.status)), + child: _buildTorIcon(_torConnectionStatus)), ), const SizedBox( height: 40, diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index 53616117e..cefdadff8 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -52,8 +52,10 @@ class _TorSettingsState extends ConsumerState { _torConnectionStatusSubscription; /// The current status of the Tor connection. - TorConnectionStatus _torConnectionStatus = TorConnectionStatus.disconnected; + late TorConnectionStatus _torConnectionStatus = + TorConnectionStatus.disconnected; + /// Build the connect/disconnect button. Widget _buildConnectButton(TorConnectionStatus status) { switch (status) { case TorConnectionStatus.disconnected: @@ -99,6 +101,11 @@ class _TorSettingsState extends ConsumerState { // Initialize the global event bus. eventBus = GlobalEventBus.instance; + // Set the initial Tor connection status. + _torConnectionStatus = TorService.sharedInstance.enabled + ? TorConnectionStatus.connected + : TorConnectionStatus.disconnected; + // Subscribe to the TorConnectionStatusChangedEvent. _torConnectionStatusSubscription = eventBus.on().listen( @@ -259,7 +266,7 @@ class _TorSettingsState extends ConsumerState { ), Padding( padding: const EdgeInsets.all(10.0), - child: _buildConnectButton(TorService.sharedInstance.status), + child: _buildConnectButton(_torConnectionStatus), ), const SizedBox( height: 30, diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index 799aa4878..dc95f89c8 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -17,14 +17,6 @@ class TorService { /// Getter for the enabled flag. bool get enabled => _enabled; - /// The current status of the Tor connection. - TorConnectionStatus _status = TorConnectionStatus.disconnected; - - /// Getter for the status. - /// - /// Used mostly to indicate "Connected" status in the UI. - TorConnectionStatus get status => _status; - TorService._(); /// Singleton instance of the TorService. @@ -49,9 +41,6 @@ class TorService { /// /// Returns a Future that completes when the Tor service has started. Future start() async { - // Set the status to connecting. - _status = TorConnectionStatus.connecting; - if (_enabled) { // already started so just return // could throw an exception here or something so the caller @@ -74,9 +63,6 @@ class TorService { // has started successfully _enabled = true; - // Set the status to connected. - _status = TorConnectionStatus.connected; - // Fire a TorConnectionStatusChangedEvent on the event bus. GlobalEventBus.instance.fire( TorConnectionStatusChangedEvent( @@ -91,9 +77,6 @@ class TorService { ); // _enabled should already be false - // Set the status to disconnected. - _status = TorConnectionStatus.disconnected; - // Fire a TorConnectionStatusChangedEvent on the event bus. GlobalEventBus.instance.fire( TorConnectionStatusChangedEvent( @@ -106,9 +89,6 @@ class TorService { } Future stop() async { - // Set the status to disconnected. - _status = TorConnectionStatus.disconnected; - if (!_enabled) { // already stopped so just return // could throw an exception here or something so the caller From d317bc5e8b5dcee1d519364f0dfc9d023f5287f3 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 10:50:50 -0500 Subject: [PATCH 164/237] implement tor killswitch comment update --- lib/electrumx_rpc/electrumx.dart | 102 ++++++++++++++++++------------- 1 file changed, 59 insertions(+), 43 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index e09446e43..fe4bb1796 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -158,55 +158,71 @@ class ElectrumX { } void _checkRpcClient() { + // If we're supposed to use Tor... if (_prefs.useTor) { + // But Tor isn't enabled... if (!_torService.enabled) { - throw Exception("Tor is not enabled"); - } - - final proxyInfo = _torService.proxyInfo; - - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); + // And the killswitch isn't set... + if (!_prefs.torKillswitch) { + // Then we'll just proceed and connect to ElectrumX through clearnet at the bottom of this function. + Logging.instance.log( + "Tor preference set but Tor is not enabled, killswitch not set, connecting to ElectrumX through clearnet", + level: LogLevel.Warning, + ); + } else { + // ... But if the killswitch is set, then we throw an exception. + throw Exception( + "Tor preference and killswitch set but Tor is not enabled, not connecting to ElectrumX"); + } } else { - _rpcClient ??= JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: proxyInfo, - ); - } + // Get the proxy info from the TorService. + final proxyInfo = _torService.proxyInfo; - if (_rpcClient!.proxyInfo != proxyInfo) { - _rpcClient!.proxyInfo = proxyInfo; - _rpcClient!.disconnect( - reason: "Tor proxyInfo does not match current info", - ); + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } else { + _rpcClient ??= JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: proxyInfo, + ); + } + + if (_rpcClient!.proxyInfo != proxyInfo) { + _rpcClient!.proxyInfo = proxyInfo; + _rpcClient!.disconnect( + reason: "Tor proxyInfo does not match current info", + ); + } + + return; } + } + + if (currentFailoverIndex == -1) { + _rpcClient ??= JsonRPC( + host: host, + port: port, + useSSL: useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); } else { - if (currentFailoverIndex == -1) { - _rpcClient ??= JsonRPC( - host: host, - port: port, - useSSL: useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } else { - _rpcClient ??= JsonRPC( - host: failovers![currentFailoverIndex].address, - port: failovers![currentFailoverIndex].port, - useSSL: failovers![currentFailoverIndex].useSSL, - connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, - proxyInfo: null, - ); - } + _rpcClient ??= JsonRPC( + host: failovers![currentFailoverIndex].address, + port: failovers![currentFailoverIndex].port, + useSSL: failovers![currentFailoverIndex].useSSL, + connectionTimeout: connectionTimeoutForSpecialCaseJsonRPCClients, + proxyInfo: null, + ); } } From a97be12f5781687d853ad8f4ccc3427f8f05c62f Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 10:04:56 -0600 Subject: [PATCH 165/237] update tests --- lib/widgets/node_options_sheet.dart | 2 + test/cached_electrumx_test.mocks.dart | 26 ++ test/electrumx_test.dart | 188 ++++++++- test/electrumx_test.mocks.dart | 209 +++++++--- .../pages/send_view/send_view_test.mocks.dart | 26 ++ .../exchange/exchange_view_test.mocks.dart | 384 ++++++++++-------- ...allet_settings_view_screen_test.mocks.dart | 10 +- test/services/change_now/change_now_test.dart | 174 ++++---- .../change_now/change_now_test.mocks.dart | 214 ++-------- .../bitcoin/bitcoin_wallet_test.mocks.dart | 10 +- .../bitcoincash_wallet_test.mocks.dart | 10 +- .../dogecoin/dogecoin_wallet_test.mocks.dart | 11 +- .../coins/firo/firo_wallet_test.mocks.dart | 10 +- .../namecoin/namecoin_wallet_test.mocks.dart | 10 +- .../particl/particl_wallet_test.mocks.dart | 10 +- .../managed_favorite_test.mocks.dart | 26 ++ .../widget_tests/node_options_sheet_test.dart | 7 +- .../node_options_sheet_test.mocks.dart | 318 +++++++++------ .../transaction_card_test.mocks.dart | 26 ++ 19 files changed, 1051 insertions(+), 620 deletions(-) diff --git a/lib/widgets/node_options_sheet.dart b/lib/widgets/node_options_sheet.dart index 953ac78a1..5dfa68d27 100644 --- a/lib/widgets/node_options_sheet.dart +++ b/lib/widgets/node_options_sheet.dart @@ -19,6 +19,7 @@ import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart'; import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; @@ -157,6 +158,7 @@ class NodeOptionsSheet extends ConsumerWidget { useSSL: node.useSSL, failovers: [], prefs: ref.read(prefsChangeNotifierProvider), + torService: ref.read(pTorService), ); try { diff --git a/test/cached_electrumx_test.mocks.dart b/test/cached_electrumx_test.mocks.dart index cdda4902b..8a40e9349 100644 --- a/test/cached_electrumx_test.mocks.dart +++ b/test/cached_electrumx_test.mocks.dart @@ -582,6 +582,19 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs { returnValueForMissingStub: null, ); @override + bool get torKillswitch => (super.noSuchMethod( + Invocation.getter(#torKillswitch), + returnValue: false, + ) as bool); + @override + set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + Invocation.setter( + #torKillswitch, + torKillswitch, + ), + returnValueForMissingStub: null, + ); + @override bool get showTestNetCoins => (super.noSuchMethod( Invocation.getter(#showTestNetCoins), returnValue: false, @@ -754,6 +767,19 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs { returnValueForMissingStub: null, ); @override + bool get useTor => (super.noSuchMethod( + Invocation.getter(#useTor), + returnValue: false, + ) as bool); + @override + set useTor(bool? useTor) => super.noSuchMethod( + Invocation.setter( + #useTor, + useTor, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index 93fc77ba5..effbb54a4 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -3,6 +3,7 @@ import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/electrumx_rpc/rpc.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'electrumx_test.mocks.dart'; @@ -10,7 +11,7 @@ import 'sample_data/get_anonymity_set_sample_data.dart'; import 'sample_data/get_used_serials_sample_data.dart'; import 'sample_data/transaction_data_samples.dart'; -@GenerateMocks([JsonRPC, Prefs]) +@GenerateMocks([JsonRPC, Prefs, TorService]) void main() { group("factory constructors and getters", () { test("electrumxnode .from factory", () { @@ -38,9 +39,16 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); - final client = - ElectrumX.from(node: node, failovers: [], prefs: mockPrefs); + final client = ElectrumX.from( + node: node, + failovers: [], + prefs: mockPrefs, + torService: torService, + ); expect(client.useSSL, node.useSSL); expect(client.host, node.address); @@ -73,18 +81,23 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( - host: "some server", - port: 0, - useSSL: true, - client: mockClient, - failovers: [], - prefs: mockPrefs); + host: "some server", + port: 0, + useSSL: true, + client: mockClient, + failovers: [], + prefs: mockPrefs, + torService: torService, + ); expect(() => client.getTransaction(requestID: "some requestId", txHash: ''), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -109,6 +122,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -116,13 +131,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await (client.getBlockHeadTip(requestID: "some requestId")); expect(result["height"], 520481); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -139,6 +157,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -146,10 +166,12 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect(() => client.getBlockHeadTip(requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -175,6 +197,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -182,12 +206,15 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.ping(requestID: "some requestId"); expect(result, true); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -204,6 +231,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -211,10 +240,12 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect(() => client.ping(requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -251,6 +282,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -258,6 +291,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = @@ -275,7 +309,9 @@ void main() { "server_version": "ElectrumX 1.0.17", "hash_function": "sha256", }); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -292,6 +328,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -299,10 +337,12 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect(() => client.getServerFeatures(requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -328,6 +368,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -335,13 +377,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.broadcastTransaction( rawTx: "some raw transaction string", requestID: "some requestId"); expect(result, "the txid of the rawtx"); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -358,6 +403,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -365,6 +412,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( @@ -372,6 +420,7 @@ void main() { rawTx: "some raw transaction string", requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -400,6 +449,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -407,13 +458,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getBalance( scripthash: "dummy hash", requestID: "some requestId"); expect(result, {"confirmed": 103873966, "unconfirmed": 23684400}); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -430,6 +484,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -437,12 +493,14 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( () => client.getBalance( scripthash: "dummy hash", requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -479,6 +537,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -486,6 +546,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getHistory( @@ -503,7 +564,9 @@ void main() { "f3e1bf48975b8d6060a9de8884296abb80be618dc00ae3cb2f6cee3085e09403" } ]); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -520,6 +583,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -527,12 +592,14 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( () => client.getHistory( scripthash: "dummy hash", requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -573,6 +640,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -580,6 +649,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getUTXOs( @@ -601,7 +671,9 @@ void main() { "height": 441696 } ]); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -618,6 +690,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -625,12 +699,14 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( () => client.getUTXOs( scripthash: "dummy hash", requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -656,6 +732,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -663,6 +741,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getTransaction( @@ -671,7 +750,9 @@ void main() { requestID: "some requestId"); expect(result, SampleGetTransactionData.txData0); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -688,6 +769,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -695,6 +778,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( @@ -702,6 +786,7 @@ void main() { txHash: SampleGetTransactionData.txHash0, requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -727,6 +812,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -734,13 +821,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getAnonymitySet( groupId: "1", blockhash: "", requestID: "some requestId"); expect(result, GetAnonymitySetSampleData.data); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -757,6 +847,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -764,12 +856,14 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( () => client.getAnonymitySet(groupId: "1", requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -795,6 +889,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -802,13 +898,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getMintData( mints: "some mints", requestID: "some requestId"); expect(result, "mint meta data"); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -825,6 +924,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -832,12 +933,14 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( () => client.getMintData( mints: "some mints", requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -863,6 +966,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -870,13 +975,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getUsedCoinSerials( requestID: "some requestId", startNumber: 0); expect(result, GetUsedSerialsSampleData.serials); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -893,6 +1001,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -900,12 +1010,14 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( () => client.getUsedCoinSerials( requestID: "some requestId", startNumber: 0), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -931,6 +1043,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -938,12 +1052,15 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getLatestCoinId(requestID: "some requestId"); expect(result, 1); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -960,6 +1077,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -967,6 +1086,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( @@ -974,6 +1094,7 @@ void main() { requestID: "some requestId", ), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -999,6 +1120,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1006,13 +1129,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getAnonymitySet( groupId: "1", blockhash: "", requestID: "some requestId"); expect(result, GetAnonymitySetSampleData.data); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1029,6 +1155,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1036,6 +1164,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( @@ -1044,6 +1173,7 @@ void main() { requestID: "some requestId", ), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1069,6 +1199,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1076,13 +1208,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getMintData( mints: "some mints", requestID: "some requestId"); expect(result, "mint meta data"); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1099,6 +1234,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1106,6 +1243,7 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( @@ -1114,6 +1252,7 @@ void main() { requestID: "some requestId", ), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1139,6 +1278,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1146,13 +1287,16 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getUsedCoinSerials( requestID: "some requestId", startNumber: 0); expect(result, GetUsedSerialsSampleData.serials); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1169,6 +1313,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1176,12 +1322,14 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect( () => client.getUsedCoinSerials( requestID: "some requestId", startNumber: 0), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1207,6 +1355,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1214,12 +1364,15 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getLatestCoinId(requestID: "some requestId"); expect(result, 1); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1236,6 +1389,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1243,10 +1398,12 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect(() => client.getLatestCoinId(requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1274,6 +1431,8 @@ void main() { ); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1281,12 +1440,15 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); final result = await client.getFeeRate(requestID: "some requestId"); expect(result, {"rate": 1000}); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1303,6 +1465,8 @@ void main() { ).thenThrow(Exception()); final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1310,10 +1474,12 @@ void main() { useSSL: true, client: mockClient, prefs: mockPrefs, + torService: torService, failovers: []); expect(() => client.getFeeRate(requestID: "some requestId"), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); @@ -1321,6 +1487,8 @@ void main() { test("rpcClient is null throws with bad server info", () { final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => false); + final torService = MockTorService(); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final client = ElectrumX( client: null, @@ -1328,10 +1496,12 @@ void main() { host: "_ :sa %", useSSL: false, prefs: mockPrefs, + torService: torService, failovers: [], ); expect(() => client.getFeeRate(), throwsA(isA())); + verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); diff --git a/test/electrumx_test.mocks.dart b/test/electrumx_test.mocks.dart index 578b1fe56..57d9b7f9c 100644 --- a/test/electrumx_test.mocks.dart +++ b/test/electrumx_test.mocks.dart @@ -3,16 +3,20 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i3; -import 'dart:ui' as _i9; +import 'dart:async' as _i4; +import 'dart:io' as _i3; +import 'dart:ui' as _i10; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/electrumx_rpc/rpc.dart' as _i2; -import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i7; -import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i6; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i8; -import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i5; -import 'package:stackwallet/utilities/prefs.dart' as _i4; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart' + as _i12; +import 'package:stackwallet/services/tor_service.dart' as _i11; +import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i8; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i7; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i9; +import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i6; +import 'package:stackwallet/utilities/prefs.dart' as _i5; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -46,6 +50,17 @@ class _FakeJsonRPCResponse_1 extends _i1.SmartFake ); } +class _FakeInternetAddress_2 extends _i1.SmartFake + implements _i3.InternetAddress { + _FakeInternetAddress_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + /// A class which mocks [JsonRPC]. /// /// See the documentation for Mockito's code generation for more information. @@ -78,7 +93,16 @@ class MockJsonRPC extends _i1.Mock implements _i2.JsonRPC { ), ) as Duration); @override - _i3.Future<_i2.JsonRPCResponse> request( + set proxyInfo(({_i3.InternetAddress host, int port})? _proxyInfo) => + super.noSuchMethod( + Invocation.setter( + #proxyInfo, + _proxyInfo, + ), + returnValueForMissingStub: null, + ); + @override + _i4.Future<_i2.JsonRPCResponse> request( String? jsonRpcRequest, Duration? requestTimeout, ) => @@ -91,7 +115,7 @@ class MockJsonRPC extends _i1.Mock implements _i2.JsonRPC { ], ), returnValue: - _i3.Future<_i2.JsonRPCResponse>.value(_FakeJsonRPCResponse_1( + _i4.Future<_i2.JsonRPCResponse>.value(_FakeJsonRPCResponse_1( this, Invocation.method( #request, @@ -101,32 +125,32 @@ class MockJsonRPC extends _i1.Mock implements _i2.JsonRPC { ], ), )), - ) as _i3.Future<_i2.JsonRPCResponse>); + ) as _i4.Future<_i2.JsonRPCResponse>); @override - _i3.Future disconnect({required String? reason}) => (super.noSuchMethod( + _i4.Future disconnect({required String? reason}) => (super.noSuchMethod( Invocation.method( #disconnect, [], {#reason: reason}, ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i3.Future connect() => (super.noSuchMethod( + _i4.Future connect() => (super.noSuchMethod( Invocation.method( #connect, [], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); } /// A class which mocks [Prefs]. /// /// See the documentation for Mockito's code generation for more information. -class MockPrefs extends _i1.Mock implements _i4.Prefs { +class MockPrefs extends _i1.Mock implements _i5.Prefs { MockPrefs() { _i1.throwOnMissingStub(this); } @@ -182,12 +206,12 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); @override - _i5.SyncingType get syncType => (super.noSuchMethod( + _i6.SyncingType get syncType => (super.noSuchMethod( Invocation.getter(#syncType), - returnValue: _i5.SyncingType.currentWalletOnly, - ) as _i5.SyncingType); + returnValue: _i6.SyncingType.currentWalletOnly, + ) as _i6.SyncingType); @override - set syncType(_i5.SyncingType? syncType) => super.noSuchMethod( + set syncType(_i6.SyncingType? syncType) => super.noSuchMethod( Invocation.setter( #syncType, syncType, @@ -299,6 +323,19 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); @override + bool get torKillswitch => (super.noSuchMethod( + Invocation.getter(#torKillswitch), + returnValue: false, + ) as bool); + @override + set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + Invocation.setter( + #torKillswitch, + torKillswitch, + ), + returnValueForMissingStub: null, + ); + @override bool get showTestNetCoins => (super.noSuchMethod( Invocation.getter(#showTestNetCoins), returnValue: false, @@ -333,12 +370,12 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); @override - _i6.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( + _i7.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( Invocation.getter(#backupFrequencyType), - returnValue: _i6.BackupFrequencyType.everyTenMinutes, - ) as _i6.BackupFrequencyType); + returnValue: _i7.BackupFrequencyType.everyTenMinutes, + ) as _i7.BackupFrequencyType); @override - set backupFrequencyType(_i6.BackupFrequencyType? backupFrequencyType) => + set backupFrequencyType(_i7.BackupFrequencyType? backupFrequencyType) => super.noSuchMethod( Invocation.setter( #backupFrequencyType, @@ -471,66 +508,79 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); @override + bool get useTor => (super.noSuchMethod( + Invocation.getter(#useTor), + returnValue: false, + ) as bool); + @override + set useTor(bool? useTor) => super.noSuchMethod( + Invocation.setter( + #useTor, + useTor, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i3.Future init() => (super.noSuchMethod( + _i4.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i3.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( + _i4.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( Invocation.method( #incrementCurrentNotificationIndex, [], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i3.Future isExternalCallsSet() => (super.noSuchMethod( + _i4.Future isExternalCallsSet() => (super.noSuchMethod( Invocation.method( #isExternalCallsSet, [], ), - returnValue: _i3.Future.value(false), - ) as _i3.Future); + returnValue: _i4.Future.value(false), + ) as _i4.Future); @override - _i3.Future saveUserID(String? userId) => (super.noSuchMethod( + _i4.Future saveUserID(String? userId) => (super.noSuchMethod( Invocation.method( #saveUserID, [userId], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i3.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( + _i4.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( Invocation.method( #saveSignupEpoch, [signupEpoch], ), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) as _i3.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i7.AmountUnit amountUnit(_i8.Coin? coin) => (super.noSuchMethod( + _i8.AmountUnit amountUnit(_i9.Coin? coin) => (super.noSuchMethod( Invocation.method( #amountUnit, [coin], ), - returnValue: _i7.AmountUnit.normal, - ) as _i7.AmountUnit); + returnValue: _i8.AmountUnit.normal, + ) as _i8.AmountUnit); @override void updateAmountUnit({ - required _i8.Coin? coin, - required _i7.AmountUnit? amountUnit, + required _i9.Coin? coin, + required _i8.AmountUnit? amountUnit, }) => super.noSuchMethod( Invocation.method( @@ -544,7 +594,7 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); @override - int maxDecimals(_i8.Coin? coin) => (super.noSuchMethod( + int maxDecimals(_i9.Coin? coin) => (super.noSuchMethod( Invocation.method( #maxDecimals, [coin], @@ -553,7 +603,7 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { ) as int); @override void updateMaxDecimals({ - required _i8.Coin? coin, + required _i9.Coin? coin, required int? maxDecimals, }) => super.noSuchMethod( @@ -568,7 +618,7 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); @override - void addListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i10.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -576,7 +626,7 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); @override - void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i10.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -600,3 +650,52 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); } + +/// A class which mocks [TorService]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTorService extends _i1.Mock implements _i11.TorService { + MockTorService() { + _i1.throwOnMissingStub(this); + } + + @override + bool get enabled => (super.noSuchMethod( + Invocation.getter(#enabled), + returnValue: false, + ) as bool); + @override + _i12.TorConnectionStatus get status => (super.noSuchMethod( + Invocation.getter(#status), + returnValue: _i12.TorConnectionStatus.disconnected, + ) as _i12.TorConnectionStatus); + @override + ({_i3.InternetAddress host, int port}) get proxyInfo => (super.noSuchMethod( + Invocation.getter(#proxyInfo), + returnValue: ( + host: _FakeInternetAddress_2( + this, + Invocation.getter(#proxyInfo), + ), + port: 0 + ), + ) as ({_i3.InternetAddress host, int port})); + @override + _i4.Future start() => (super.noSuchMethod( + Invocation.method( + #start, + [], + ), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); + @override + _i4.Future stop() => (super.noSuchMethod( + Invocation.method( + #stop, + [], + ), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); +} diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart index 52bc87fee..3ebe98c2e 100644 --- a/test/pages/send_view/send_view_test.mocks.dart +++ b/test/pages/send_view/send_view_test.mocks.dart @@ -2504,6 +2504,19 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override + bool get torKillswitch => (super.noSuchMethod( + Invocation.getter(#torKillswitch), + returnValue: false, + ) as bool); + @override + set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + Invocation.setter( + #torKillswitch, + torKillswitch, + ), + returnValueForMissingStub: null, + ); + @override bool get showTestNetCoins => (super.noSuchMethod( Invocation.getter(#showTestNetCoins), returnValue: false, @@ -2676,6 +2689,19 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override + bool get useTor => (super.noSuchMethod( + Invocation.getter(#useTor), + returnValue: false, + ) as bool); + @override + set useTor(bool? useTor) => super.noSuchMethod( + Invocation.setter( + #useTor, + useTor, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart index 7b55ab9e0..1441aa4ad 100644 --- a/test/screen_tests/exchange/exchange_view_test.mocks.dart +++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart @@ -3,11 +3,10 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i6; -import 'dart:ui' as _i9; +import 'dart:async' as _i7; +import 'dart:ui' as _i10; import 'package:decimal/decimal.dart' as _i16; -import 'package:http/http.dart' as _i14; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/models/exchange/change_now/cn_exchange_estimate.dart' as _i19; @@ -22,19 +21,20 @@ import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.d import 'package:stackwallet/models/exchange/response_objects/range.dart' as _i17; import 'package:stackwallet/models/exchange/response_objects/trade.dart' - as _i11; + as _i12; import 'package:stackwallet/models/isar/exchange_cache/currency.dart' as _i15; import 'package:stackwallet/models/isar/exchange_cache/pair.dart' as _i23; +import 'package:stackwallet/networking/http.dart' as _i2; import 'package:stackwallet/services/exchange/change_now/change_now_api.dart' - as _i13; -import 'package:stackwallet/services/exchange/exchange_response.dart' as _i2; -import 'package:stackwallet/services/trade_notes_service.dart' as _i12; -import 'package:stackwallet/services/trade_service.dart' as _i10; -import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i7; -import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i5; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i8; -import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i4; -import 'package:stackwallet/utilities/prefs.dart' as _i3; + as _i14; +import 'package:stackwallet/services/exchange/exchange_response.dart' as _i3; +import 'package:stackwallet/services/trade_notes_service.dart' as _i13; +import 'package:stackwallet/services/trade_service.dart' as _i11; +import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i8; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i6; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i9; +import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i5; +import 'package:stackwallet/utilities/prefs.dart' as _i4; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -47,9 +47,19 @@ import 'package:stackwallet/utilities/prefs.dart' as _i3; // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class -class _FakeExchangeResponse_0 extends _i1.SmartFake - implements _i2.ExchangeResponse { - _FakeExchangeResponse_0( +class _FakeHTTP_0 extends _i1.SmartFake implements _i2.HTTP { + _FakeHTTP_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeExchangeResponse_1 extends _i1.SmartFake + implements _i3.ExchangeResponse { + _FakeExchangeResponse_1( Object parent, Invocation parentInvocation, ) : super( @@ -61,7 +71,7 @@ class _FakeExchangeResponse_0 extends _i1.SmartFake /// A class which mocks [Prefs]. /// /// See the documentation for Mockito's code generation for more information. -class MockPrefs extends _i1.Mock implements _i3.Prefs { +class MockPrefs extends _i1.Mock implements _i4.Prefs { MockPrefs() { _i1.throwOnMissingStub(this); } @@ -117,12 +127,12 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { returnValueForMissingStub: null, ); @override - _i4.SyncingType get syncType => (super.noSuchMethod( + _i5.SyncingType get syncType => (super.noSuchMethod( Invocation.getter(#syncType), - returnValue: _i4.SyncingType.currentWalletOnly, - ) as _i4.SyncingType); + returnValue: _i5.SyncingType.currentWalletOnly, + ) as _i5.SyncingType); @override - set syncType(_i4.SyncingType? syncType) => super.noSuchMethod( + set syncType(_i5.SyncingType? syncType) => super.noSuchMethod( Invocation.setter( #syncType, syncType, @@ -234,6 +244,19 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { returnValueForMissingStub: null, ); @override + bool get torKillswitch => (super.noSuchMethod( + Invocation.getter(#torKillswitch), + returnValue: false, + ) as bool); + @override + set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + Invocation.setter( + #torKillswitch, + torKillswitch, + ), + returnValueForMissingStub: null, + ); + @override bool get showTestNetCoins => (super.noSuchMethod( Invocation.getter(#showTestNetCoins), returnValue: false, @@ -268,12 +291,12 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { returnValueForMissingStub: null, ); @override - _i5.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( + _i6.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( Invocation.getter(#backupFrequencyType), - returnValue: _i5.BackupFrequencyType.everyTenMinutes, - ) as _i5.BackupFrequencyType); + returnValue: _i6.BackupFrequencyType.everyTenMinutes, + ) as _i6.BackupFrequencyType); @override - set backupFrequencyType(_i5.BackupFrequencyType? backupFrequencyType) => + set backupFrequencyType(_i6.BackupFrequencyType? backupFrequencyType) => super.noSuchMethod( Invocation.setter( #backupFrequencyType, @@ -406,66 +429,79 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { returnValueForMissingStub: null, ); @override + bool get useTor => (super.noSuchMethod( + Invocation.getter(#useTor), + returnValue: false, + ) as bool); + @override + set useTor(bool? useTor) => super.noSuchMethod( + Invocation.setter( + #useTor, + useTor, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i6.Future init() => (super.noSuchMethod( + _i7.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( + _i7.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( Invocation.method( #incrementCurrentNotificationIndex, [], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future isExternalCallsSet() => (super.noSuchMethod( + _i7.Future isExternalCallsSet() => (super.noSuchMethod( Invocation.method( #isExternalCallsSet, [], ), - returnValue: _i6.Future.value(false), - ) as _i6.Future); + returnValue: _i7.Future.value(false), + ) as _i7.Future); @override - _i6.Future saveUserID(String? userId) => (super.noSuchMethod( + _i7.Future saveUserID(String? userId) => (super.noSuchMethod( Invocation.method( #saveUserID, [userId], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( + _i7.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( Invocation.method( #saveSignupEpoch, [signupEpoch], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i7.AmountUnit amountUnit(_i8.Coin? coin) => (super.noSuchMethod( + _i8.AmountUnit amountUnit(_i9.Coin? coin) => (super.noSuchMethod( Invocation.method( #amountUnit, [coin], ), - returnValue: _i7.AmountUnit.normal, - ) as _i7.AmountUnit); + returnValue: _i8.AmountUnit.normal, + ) as _i8.AmountUnit); @override void updateAmountUnit({ - required _i8.Coin? coin, - required _i7.AmountUnit? amountUnit, + required _i9.Coin? coin, + required _i8.AmountUnit? amountUnit, }) => super.noSuchMethod( Invocation.method( @@ -479,7 +515,7 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { returnValueForMissingStub: null, ); @override - int maxDecimals(_i8.Coin? coin) => (super.noSuchMethod( + int maxDecimals(_i9.Coin? coin) => (super.noSuchMethod( Invocation.method( #maxDecimals, [coin], @@ -488,7 +524,7 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { ) as int); @override void updateMaxDecimals({ - required _i8.Coin? coin, + required _i9.Coin? coin, required int? maxDecimals, }) => super.noSuchMethod( @@ -503,7 +539,7 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { returnValueForMissingStub: null, ); @override - void addListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i10.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -511,7 +547,7 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { returnValueForMissingStub: null, ); @override - void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i10.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -539,29 +575,29 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs { /// A class which mocks [TradesService]. /// /// See the documentation for Mockito's code generation for more information. -class MockTradesService extends _i1.Mock implements _i10.TradesService { +class MockTradesService extends _i1.Mock implements _i11.TradesService { MockTradesService() { _i1.throwOnMissingStub(this); } @override - List<_i11.Trade> get trades => (super.noSuchMethod( + List<_i12.Trade> get trades => (super.noSuchMethod( Invocation.getter(#trades), - returnValue: <_i11.Trade>[], - ) as List<_i11.Trade>); + returnValue: <_i12.Trade>[], + ) as List<_i12.Trade>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i11.Trade? get(String? tradeId) => (super.noSuchMethod(Invocation.method( + _i12.Trade? get(String? tradeId) => (super.noSuchMethod(Invocation.method( #get, [tradeId], - )) as _i11.Trade?); + )) as _i12.Trade?); @override - _i6.Future add({ - required _i11.Trade? trade, + _i7.Future add({ + required _i12.Trade? trade, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -573,12 +609,12 @@ class MockTradesService extends _i1.Mock implements _i10.TradesService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future edit({ - required _i11.Trade? trade, + _i7.Future edit({ + required _i12.Trade? trade, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -590,12 +626,12 @@ class MockTradesService extends _i1.Mock implements _i10.TradesService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future delete({ - required _i11.Trade? trade, + _i7.Future delete({ + required _i12.Trade? trade, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -607,11 +643,11 @@ class MockTradesService extends _i1.Mock implements _i10.TradesService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future deleteByUuid({ + _i7.Future deleteByUuid({ required String? uuid, required bool? shouldNotifyListeners, }) => @@ -624,11 +660,11 @@ class MockTradesService extends _i1.Mock implements _i10.TradesService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - void addListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i10.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -636,7 +672,7 @@ class MockTradesService extends _i1.Mock implements _i10.TradesService { returnValueForMissingStub: null, ); @override - void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i10.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -664,7 +700,7 @@ class MockTradesService extends _i1.Mock implements _i10.TradesService { /// A class which mocks [TradeNotesService]. /// /// See the documentation for Mockito's code generation for more information. -class MockTradeNotesService extends _i1.Mock implements _i12.TradeNotesService { +class MockTradeNotesService extends _i1.Mock implements _i13.TradeNotesService { MockTradeNotesService() { _i1.throwOnMissingStub(this); } @@ -689,7 +725,7 @@ class MockTradeNotesService extends _i1.Mock implements _i12.TradeNotesService { returnValue: '', ) as String); @override - _i6.Future set({ + _i7.Future set({ required String? tradeId, required String? note, }) => @@ -702,21 +738,21 @@ class MockTradeNotesService extends _i1.Mock implements _i12.TradeNotesService { #note: note, }, ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future delete({required String? tradeId}) => (super.noSuchMethod( + _i7.Future delete({required String? tradeId}) => (super.noSuchMethod( Invocation.method( #delete, [], {#tradeId: tradeId}, ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - void addListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i10.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -724,7 +760,7 @@ class MockTradeNotesService extends _i1.Mock implements _i12.TradeNotesService { returnValueForMissingStub: null, ); @override - void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i10.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -752,13 +788,21 @@ class MockTradeNotesService extends _i1.Mock implements _i12.TradeNotesService { /// A class which mocks [ChangeNowAPI]. /// /// See the documentation for Mockito's code generation for more information. -class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { +class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { MockChangeNowAPI() { _i1.throwOnMissingStub(this); } @override - set client(_i14.Client? _client) => super.noSuchMethod( + _i2.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_0( + this, + Invocation.getter(#client), + ), + ) as _i2.HTTP); + @override + set client(_i2.HTTP? _client) => super.noSuchMethod( Invocation.setter( #client, _client, @@ -766,7 +810,7 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { returnValueForMissingStub: null, ); @override - _i6.Future<_i2.ExchangeResponse>> getAvailableCurrencies({ + _i7.Future<_i3.ExchangeResponse>> getAvailableCurrencies({ bool? fixedRate, bool? active, }) => @@ -780,8 +824,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), returnValue: - _i6.Future<_i2.ExchangeResponse>>.value( - _FakeExchangeResponse_0>( + _i7.Future<_i3.ExchangeResponse>>.value( + _FakeExchangeResponse_1>( this, Invocation.method( #getAvailableCurrencies, @@ -792,26 +836,26 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse>>); + ) as _i7.Future<_i3.ExchangeResponse>>); @override - _i6.Future<_i2.ExchangeResponse>> getCurrenciesV2() => + _i7.Future<_i3.ExchangeResponse>> getCurrenciesV2() => (super.noSuchMethod( Invocation.method( #getCurrenciesV2, [], ), returnValue: - _i6.Future<_i2.ExchangeResponse>>.value( - _FakeExchangeResponse_0>( + _i7.Future<_i3.ExchangeResponse>>.value( + _FakeExchangeResponse_1>( this, Invocation.method( #getCurrenciesV2, [], ), )), - ) as _i6.Future<_i2.ExchangeResponse>>); + ) as _i7.Future<_i3.ExchangeResponse>>); @override - _i6.Future<_i2.ExchangeResponse>> getPairedCurrencies({ + _i7.Future<_i3.ExchangeResponse>> getPairedCurrencies({ required String? ticker, bool? fixedRate, }) => @@ -825,8 +869,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), returnValue: - _i6.Future<_i2.ExchangeResponse>>.value( - _FakeExchangeResponse_0>( + _i7.Future<_i3.ExchangeResponse>>.value( + _FakeExchangeResponse_1>( this, Invocation.method( #getPairedCurrencies, @@ -837,9 +881,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse>>); + ) as _i7.Future<_i3.ExchangeResponse>>); @override - _i6.Future<_i2.ExchangeResponse<_i16.Decimal>> getMinimalExchangeAmount({ + _i7.Future<_i3.ExchangeResponse<_i16.Decimal>> getMinimalExchangeAmount({ required String? fromTicker, required String? toTicker, String? apiKey, @@ -854,8 +898,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i6.Future<_i2.ExchangeResponse<_i16.Decimal>>.value( - _FakeExchangeResponse_0<_i16.Decimal>( + returnValue: _i7.Future<_i3.ExchangeResponse<_i16.Decimal>>.value( + _FakeExchangeResponse_1<_i16.Decimal>( this, Invocation.method( #getMinimalExchangeAmount, @@ -867,9 +911,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse<_i16.Decimal>>); + ) as _i7.Future<_i3.ExchangeResponse<_i16.Decimal>>); @override - _i6.Future<_i2.ExchangeResponse<_i17.Range>> getRange({ + _i7.Future<_i3.ExchangeResponse<_i17.Range>> getRange({ required String? fromTicker, required String? toTicker, required bool? isFixedRate, @@ -886,8 +930,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i6.Future<_i2.ExchangeResponse<_i17.Range>>.value( - _FakeExchangeResponse_0<_i17.Range>( + returnValue: _i7.Future<_i3.ExchangeResponse<_i17.Range>>.value( + _FakeExchangeResponse_1<_i17.Range>( this, Invocation.method( #getRange, @@ -900,9 +944,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse<_i17.Range>>); + ) as _i7.Future<_i3.ExchangeResponse<_i17.Range>>); @override - _i6.Future<_i2.ExchangeResponse<_i18.Estimate>> getEstimatedExchangeAmount({ + _i7.Future<_i3.ExchangeResponse<_i18.Estimate>> getEstimatedExchangeAmount({ required String? fromTicker, required String? toTicker, required _i16.Decimal? fromAmount, @@ -919,8 +963,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i6.Future<_i2.ExchangeResponse<_i18.Estimate>>.value( - _FakeExchangeResponse_0<_i18.Estimate>( + returnValue: _i7.Future<_i3.ExchangeResponse<_i18.Estimate>>.value( + _FakeExchangeResponse_1<_i18.Estimate>( this, Invocation.method( #getEstimatedExchangeAmount, @@ -933,9 +977,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse<_i18.Estimate>>); + ) as _i7.Future<_i3.ExchangeResponse<_i18.Estimate>>); @override - _i6.Future<_i2.ExchangeResponse<_i18.Estimate>> + _i7.Future<_i3.ExchangeResponse<_i18.Estimate>> getEstimatedExchangeAmountFixedRate({ required String? fromTicker, required String? toTicker, @@ -957,8 +1001,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i6.Future<_i2.ExchangeResponse<_i18.Estimate>>.value( - _FakeExchangeResponse_0<_i18.Estimate>( + returnValue: _i7.Future<_i3.ExchangeResponse<_i18.Estimate>>.value( + _FakeExchangeResponse_1<_i18.Estimate>( this, Invocation.method( #getEstimatedExchangeAmountFixedRate, @@ -973,9 +1017,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse<_i18.Estimate>>); + ) as _i7.Future<_i3.ExchangeResponse<_i18.Estimate>>); @override - _i6.Future<_i2.ExchangeResponse<_i19.CNExchangeEstimate>> + _i7.Future<_i3.ExchangeResponse<_i19.CNExchangeEstimate>> getEstimatedExchangeAmountV2({ required String? fromTicker, required String? toTicker, @@ -1002,8 +1046,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), returnValue: - _i6.Future<_i2.ExchangeResponse<_i19.CNExchangeEstimate>>.value( - _FakeExchangeResponse_0<_i19.CNExchangeEstimate>( + _i7.Future<_i3.ExchangeResponse<_i19.CNExchangeEstimate>>.value( + _FakeExchangeResponse_1<_i19.CNExchangeEstimate>( this, Invocation.method( #getEstimatedExchangeAmountV2, @@ -1020,18 +1064,18 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse<_i19.CNExchangeEstimate>>); + ) as _i7.Future<_i3.ExchangeResponse<_i19.CNExchangeEstimate>>); @override - _i6.Future<_i2.ExchangeResponse>> + _i7.Future<_i3.ExchangeResponse>> getAvailableFixedRateMarkets({String? apiKey}) => (super.noSuchMethod( Invocation.method( #getAvailableFixedRateMarkets, [], {#apiKey: apiKey}, ), - returnValue: _i6 - .Future<_i2.ExchangeResponse>>.value( - _FakeExchangeResponse_0>( + returnValue: _i7.Future< + _i3.ExchangeResponse>>.value( + _FakeExchangeResponse_1>( this, Invocation.method( #getAvailableFixedRateMarkets, @@ -1039,9 +1083,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { {#apiKey: apiKey}, ), )), - ) as _i6.Future<_i2.ExchangeResponse>>); + ) as _i7.Future<_i3.ExchangeResponse>>); @override - _i6.Future<_i2.ExchangeResponse<_i21.ExchangeTransaction>> + _i7.Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>> createStandardExchangeTransaction({ required String? fromTicker, required String? toTicker, @@ -1071,9 +1115,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i6 - .Future<_i2.ExchangeResponse<_i21.ExchangeTransaction>>.value( - _FakeExchangeResponse_0<_i21.ExchangeTransaction>( + returnValue: _i7.Future< + _i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( + _FakeExchangeResponse_1<_i21.ExchangeTransaction>( this, Invocation.method( #createStandardExchangeTransaction, @@ -1092,9 +1136,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse<_i21.ExchangeTransaction>>); + ) as _i7.Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>>); @override - _i6.Future<_i2.ExchangeResponse<_i21.ExchangeTransaction>> + _i7.Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>> createFixedRateExchangeTransaction({ required String? fromTicker, required String? toTicker, @@ -1128,9 +1172,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i6 - .Future<_i2.ExchangeResponse<_i21.ExchangeTransaction>>.value( - _FakeExchangeResponse_0<_i21.ExchangeTransaction>( + returnValue: _i7.Future< + _i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( + _FakeExchangeResponse_1<_i21.ExchangeTransaction>( this, Invocation.method( #createFixedRateExchangeTransaction, @@ -1151,39 +1195,39 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { }, ), )), - ) as _i6.Future<_i2.ExchangeResponse<_i21.ExchangeTransaction>>); + ) as _i7.Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>>); @override - _i6.Future< - _i2 - .ExchangeResponse<_i22.ExchangeTransactionStatus>> getTransactionStatus({ + _i7.Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>> + getTransactionStatus({ required String? id, String? apiKey, }) => - (super.noSuchMethod( - Invocation.method( - #getTransactionStatus, - [], - { - #id: id, - #apiKey: apiKey, - }, - ), - returnValue: _i6 - .Future<_i2.ExchangeResponse<_i22.ExchangeTransactionStatus>>.value( - _FakeExchangeResponse_0<_i22.ExchangeTransactionStatus>( - this, - Invocation.method( - #getTransactionStatus, - [], - { - #id: id, - #apiKey: apiKey, - }, - ), - )), - ) as _i6.Future<_i2.ExchangeResponse<_i22.ExchangeTransactionStatus>>); + (super.noSuchMethod( + Invocation.method( + #getTransactionStatus, + [], + { + #id: id, + #apiKey: apiKey, + }, + ), + returnValue: _i7.Future< + _i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>.value( + _FakeExchangeResponse_1<_i22.ExchangeTransactionStatus>( + this, + Invocation.method( + #getTransactionStatus, + [], + { + #id: id, + #apiKey: apiKey, + }, + ), + )), + ) as _i7 + .Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>); @override - _i6.Future<_i2.ExchangeResponse>> + _i7.Future<_i3.ExchangeResponse>> getAvailableFloatingRatePairs({bool? includePartners = false}) => (super.noSuchMethod( Invocation.method( @@ -1192,8 +1236,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { {#includePartners: includePartners}, ), returnValue: - _i6.Future<_i2.ExchangeResponse>>.value( - _FakeExchangeResponse_0>( + _i7.Future<_i3.ExchangeResponse>>.value( + _FakeExchangeResponse_1>( this, Invocation.method( #getAvailableFloatingRatePairs, @@ -1201,5 +1245,5 @@ class MockChangeNowAPI extends _i1.Mock implements _i13.ChangeNowAPI { {#includePartners: includePartners}, ), )), - ) as _i6.Future<_i2.ExchangeResponse>>); + ) as _i7.Future<_i3.ExchangeResponse>>); } diff --git a/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart b/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart index 268529741..e0fae8b21 100644 --- a/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart +++ b/test/screen_tests/settings_view/settings_subviews/wallet_settings_view_screen_test.mocks.dart @@ -154,12 +154,18 @@ class MockCachedElectrumX extends _i1.Mock implements _i7.CachedElectrumX { _i8.Future>.value({}), ) as _i8.Future>); @override - _i8.Future> getUsedCoinSerials({required _i9.Coin? coin}) => + _i8.Future> getUsedCoinSerials({ + required _i9.Coin? coin, + int? startNumber = 0, + }) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - {#coin: coin}, + { + #coin: coin, + #startNumber: startNumber, + }, ), returnValue: _i8.Future>.value([]), ) as _i8.Future>); diff --git a/test/services/change_now/change_now_test.dart b/test/services/change_now/change_now_test.dart index f79cbcd4d..0b909cf12 100644 --- a/test/services/change_now/change_now_test.dart +++ b/test/services/change_now/change_now_test.dart @@ -2,7 +2,6 @@ import 'dart:convert'; import 'package:decimal/decimal.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:http/http.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:stackwallet/exceptions/exchange/exchange_exception.dart'; @@ -10,21 +9,23 @@ import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart'; import 'package:stackwallet/models/exchange/response_objects/estimate.dart'; import 'package:stackwallet/models/isar/exchange_cache/pair.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_api.dart'; import 'change_now_sample_data.dart'; import 'change_now_test.mocks.dart'; -@GenerateMocks([Client]) +@GenerateMocks([HTTP]) void main() { group("getAvailableCurrencies", () { test("getAvailableCurrencies succeeds without options", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse("https://api.ChangeNow.io/v1/currencies"), + url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response(jsonEncode(availableCurrenciesJSON), 200)); @@ -36,12 +37,13 @@ void main() { }); test("getAvailableCurrencies succeeds with active option", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse("https://api.ChangeNow.io/v1/currencies?active=true"), + url: Uri.parse("https://api.ChangeNow.io/v1/currencies?active=true"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response(jsonEncode(availableCurrenciesJSONActive), 200)); @@ -54,12 +56,13 @@ void main() { }); test("getAvailableCurrencies succeeds with fixedRate option", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse("https://api.ChangeNow.io/v1/currencies?fixedRate=true"), + url: Uri.parse("https://api.ChangeNow.io/v1/currencies?fixedRate=true"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response(jsonEncode(availableCurrenciesJSONFixedRate), 200)); @@ -73,13 +76,14 @@ void main() { test("getAvailableCurrencies succeeds with fixedRate and active options", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/currencies?fixedRate=true&active=true"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response(jsonEncode(availableCurrenciesJSONActiveFixedRate), 200)); @@ -94,12 +98,13 @@ void main() { test( "getAvailableCurrencies fails with ChangeNowExceptionType.serializeResponseError", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse("https://api.ChangeNow.io/v1/currencies"), + url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('{"some unexpected": "but valid json data"}', 200)); @@ -111,12 +116,13 @@ void main() { }); test("getAvailableCurrencies fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse("https://api.ChangeNow.io/v1/currencies"), + url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response("", 400)); final result = await ChangeNowAPI.instance.getAvailableCurrencies(); @@ -129,12 +135,13 @@ void main() { group("getPairedCurrencies", () { test("getPairedCurrencies succeeds without fixedRate option", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), + url: Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response(jsonEncode(getPairedCurrenciesJSON), 200)); @@ -147,13 +154,14 @@ void main() { }); test("getPairedCurrencies succeeds with fixedRate option", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/currencies-to/XMR?fixedRate=true"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response(jsonEncode(getPairedCurrenciesJSONFixedRate), 200)); @@ -168,12 +176,13 @@ void main() { test( "getPairedCurrencies fails with ChangeNowExceptionType.serializeResponseError A", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), + url: Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('[{"some unexpected": "but valid json data"}]', 200)); @@ -186,12 +195,13 @@ void main() { }); test("getPairedCurrencies fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse("https://api.ChangeNow.io/v1/currencies"), + url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response("", 400)); final result = await ChangeNowAPI.instance @@ -204,13 +214,14 @@ void main() { group("getMinimalExchangeAmount", () { test("getMinimalExchangeAmount succeeds", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer( (realInvocation) async => Response('{"minAmount": 42}', 200)); @@ -228,13 +239,14 @@ void main() { test( "getMinimalExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); final result = await ChangeNowAPI.instance.getMinimalExchangeAmount( @@ -249,13 +261,14 @@ void main() { }); test("getMinimalExchangeAmount fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('', 400)); final result = await ChangeNowAPI.instance.getMinimalExchangeAmount( @@ -272,13 +285,14 @@ void main() { group("getEstimatedExchangeAmount", () { test("getEstimatedExchangeAmount succeeds", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response( '{"estimatedAmount": 58.4142873, "transactionSpeedForecast": "10-60", "warningMessage": null}', 200)); @@ -298,13 +312,14 @@ void main() { test( "getEstimatedExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); final result = await ChangeNowAPI.instance.getEstimatedExchangeAmount( @@ -320,13 +335,14 @@ void main() { }); test("getEstimatedExchangeAmount fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('', 400)); final result = await ChangeNowAPI.instance.getEstimatedExchangeAmount( @@ -343,13 +359,14 @@ void main() { // group("getEstimatedFixedRateExchangeAmount", () { // test("getEstimatedFixedRateExchangeAmount succeeds", () async { - // final client = MockClient(); + // final client = MockHTTP(); // ChangeNow.instance.client = client; // - // when(client.get( + // when(client.get(url: // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, + // routeOverTor: false, // )).thenAnswer((realInvocation) async => // Response(jsonEncode(estFixedRateExchangeAmountJSON), 200)); // @@ -370,13 +387,14 @@ void main() { // test( // "getEstimatedFixedRateExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", // () async { - // final client = MockClient(); + // final client = MockHTTP(); // ChangeNow.instance.client = client; // - // when(client.get( + // when(client.get(url: // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, + // routeOverTor: false, // )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); // // final result = @@ -394,13 +412,14 @@ void main() { // // test("getEstimatedFixedRateExchangeAmount fails for any other reason", // () async { - // final client = MockClient(); + // final client = MockHTTP(); // ChangeNow.instance.client = client; // - // when(client.get( + // when(client.get(url: // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, + // routeOverTor: false, // )).thenAnswer((realInvocation) async => Response('', 400)); // // final result = @@ -418,13 +437,14 @@ void main() { group("getAvailableFixedRateMarkets", () { test("getAvailableFixedRateMarkets succeeds", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response(jsonEncode(fixedRateMarketsJSON), 200)); @@ -440,13 +460,14 @@ void main() { test( "getAvailableFixedRateMarkets fails with ChangeNowExceptionType.serializeResponseError", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); final result = await ChangeNowAPI.instance.getAvailableFixedRateMarkets( @@ -459,13 +480,14 @@ void main() { }); test("getAvailableFixedRateMarkets fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('', 400)); final result = await ChangeNowAPI.instance.getAvailableFixedRateMarkets( @@ -480,12 +502,13 @@ void main() { group("createStandardExchangeTransaction", () { test("createStandardExchangeTransaction succeeds", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.post( - Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), + url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, @@ -511,12 +534,13 @@ void main() { test( "createStandardExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.post( - Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), + url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, @@ -540,12 +564,13 @@ void main() { test("createStandardExchangeTransaction fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.post( - Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), + url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, @@ -569,13 +594,14 @@ void main() { group("createFixedRateExchangeTransaction", () { test("createFixedRateExchangeTransaction succeeds", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.post( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, body: '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":"","amount":"0.3"}', encoding: null, @@ -603,13 +629,14 @@ void main() { test( "createFixedRateExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.post( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, body: '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","amount":"0.3","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":""}', encoding: null, @@ -634,13 +661,14 @@ void main() { test("createFixedRateExchangeTransaction fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.post( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, body: '{"from": "btc","to": "eth","address": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", "amount": "1.12345","extraId": "", "userId": "","contactEmail": "","refundAddress": "", "refundExtraId": "", "rateId": "" }', encoding: null, @@ -666,13 +694,14 @@ void main() { group("getTransactionStatus", () { test("getTransactionStatus succeeds", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response( '{"status": "waiting", "payinAddress": "32Ge2ci26rj1sRGw2NjiQa9L7Xvxtgzhrj", "payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", "fromCurrency": "btc", "toCurrency": "eth", "id": "50727663e5d9a4", "updatedAt": "2019-08-22T14:47:49.943Z", "expectedSendAmount": 1, "expectedReceiveAmount": 52.31667, "createdAt": "2019-08-22T14:47:49.943Z", "isPartner": false}', 200)); @@ -690,13 +719,14 @@ void main() { test( "getTransactionStatus fails with ChangeNowExceptionType.serializeResponseError", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); final result = await ChangeNowAPI.instance.getTransactionStatus( @@ -710,13 +740,14 @@ void main() { }); test("getTransactionStatus fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('', 400)); final result = await ChangeNowAPI.instance.getTransactionStatus( @@ -732,13 +763,14 @@ void main() { group("getAvailableFloatingRatePairs", () { test("getAvailableFloatingRatePairs succeeds", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('["btc_xmr","btc_firo","btc_doge","eth_ltc"]', 200)); @@ -753,13 +785,14 @@ void main() { test( "getAvailableFloatingRatePairs fails with ChangeNowExceptionType.serializeResponseError", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); final result = @@ -771,13 +804,14 @@ void main() { }); test("getAvailableFloatingRatePairs fails for any other reason", () async { - final client = MockClient(); + final client = MockHTTP(); ChangeNowAPI.instance.client = client; when(client.get( - Uri.parse( + url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, + routeOverTor: false, )).thenAnswer((realInvocation) async => Response('', 400)); final result = diff --git a/test/services/change_now/change_now_test.mocks.dart b/test/services/change_now/change_now_test.mocks.dart index 21ccddff8..71e4c0ad4 100644 --- a/test/services/change_now/change_now_test.mocks.dart +++ b/test/services/change_now/change_now_test.mocks.dart @@ -5,10 +5,9 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; import 'dart:convert' as _i4; -import 'dart:typed_data' as _i5; -import 'package:http/http.dart' as _i2; import 'package:mockito/mockito.dart' as _i1; +import 'package:stackwallet/networking/http.dart' as _i2; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -31,233 +30,76 @@ class _FakeResponse_0 extends _i1.SmartFake implements _i2.Response { ); } -class _FakeStreamedResponse_1 extends _i1.SmartFake - implements _i2.StreamedResponse { - _FakeStreamedResponse_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -/// A class which mocks [Client]. +/// A class which mocks [HTTP]. /// /// See the documentation for Mockito's code generation for more information. -class MockClient extends _i1.Mock implements _i2.Client { - MockClient() { +class MockHTTP extends _i1.Mock implements _i2.HTTP { + MockHTTP() { _i1.throwOnMissingStub(this); } @override - _i3.Future<_i2.Response> head( - Uri? url, { - Map? headers, - }) => - (super.noSuchMethod( - Invocation.method( - #head, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #head, - [url], - {#headers: headers}, - ), - )), - ) as _i3.Future<_i2.Response>); - @override - _i3.Future<_i2.Response> get( - Uri? url, { + _i3.Future<_i2.Response> get({ + required Uri? url, Map? headers, + required bool? routeOverTor, }) => (super.noSuchMethod( Invocation.method( #get, - [url], - {#headers: headers}, + [], + { + #url: url, + #headers: headers, + #routeOverTor: routeOverTor, + }, ), returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( this, Invocation.method( #get, - [url], - {#headers: headers}, + [], + { + #url: url, + #headers: headers, + #routeOverTor: routeOverTor, + }, ), )), ) as _i3.Future<_i2.Response>); @override - _i3.Future<_i2.Response> post( - Uri? url, { + _i3.Future<_i2.Response> post({ + required Uri? url, Map? headers, Object? body, _i4.Encoding? encoding, + required bool? routeOverTor, }) => (super.noSuchMethod( Invocation.method( #post, - [url], + [], { + #url: url, #headers: headers, #body: body, #encoding: encoding, + #routeOverTor: routeOverTor, }, ), returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( this, Invocation.method( #post, - [url], + [], { + #url: url, #headers: headers, #body: body, #encoding: encoding, + #routeOverTor: routeOverTor, }, ), )), ) as _i3.Future<_i2.Response>); - @override - _i3.Future<_i2.Response> put( - Uri? url, { - Map? headers, - Object? body, - _i4.Encoding? encoding, - }) => - (super.noSuchMethod( - Invocation.method( - #put, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #put, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); - @override - _i3.Future<_i2.Response> patch( - Uri? url, { - Map? headers, - Object? body, - _i4.Encoding? encoding, - }) => - (super.noSuchMethod( - Invocation.method( - #patch, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #patch, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); - @override - _i3.Future<_i2.Response> delete( - Uri? url, { - Map? headers, - Object? body, - _i4.Encoding? encoding, - }) => - (super.noSuchMethod( - Invocation.method( - #delete, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #delete, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); - @override - _i3.Future read( - Uri? url, { - Map? headers, - }) => - (super.noSuchMethod( - Invocation.method( - #read, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future.value(''), - ) as _i3.Future); - @override - _i3.Future<_i5.Uint8List> readBytes( - Uri? url, { - Map? headers, - }) => - (super.noSuchMethod( - Invocation.method( - #readBytes, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future<_i5.Uint8List>.value(_i5.Uint8List(0)), - ) as _i3.Future<_i5.Uint8List>); - @override - _i3.Future<_i2.StreamedResponse> send(_i2.BaseRequest? request) => - (super.noSuchMethod( - Invocation.method( - #send, - [request], - ), - returnValue: - _i3.Future<_i2.StreamedResponse>.value(_FakeStreamedResponse_1( - this, - Invocation.method( - #send, - [request], - ), - )), - ) as _i3.Future<_i2.StreamedResponse>); - @override - void close() => super.noSuchMethod( - Invocation.method( - #close, - [], - ), - returnValueForMissingStub: null, - ); } diff --git a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart index 80b582256..32719f306 100644 --- a/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart +++ b/test/services/coins/bitcoin/bitcoin_wallet_test.mocks.dart @@ -485,12 +485,18 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => + _i4.Future> getUsedCoinSerials({ + required _i6.Coin? coin, + int? startNumber = 0, + }) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - {#coin: coin}, + { + #coin: coin, + #startNumber: startNumber, + }, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart index 52ae05ecd..5599f3a29 100644 --- a/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart +++ b/test/services/coins/bitcoincash/bitcoincash_wallet_test.mocks.dart @@ -485,12 +485,18 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => + _i4.Future> getUsedCoinSerials({ + required _i6.Coin? coin, + int? startNumber = 0, + }) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - {#coin: coin}, + { + #coin: coin, + #startNumber: startNumber, + }, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart index 1027d0592..c19e63a44 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart @@ -485,12 +485,18 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => + _i4.Future> getUsedCoinSerials({ + required _i6.Coin? coin, + int? startNumber = 0, + }) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - {#coin: coin}, + { + #coin: coin, + #startNumber: startNumber, + }, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); @@ -531,6 +537,7 @@ class MockTransactionNotificationTracker extends _i1.Mock Invocation.getter(#confirmeds), returnValue: [], ) as List); + @override bool wasNotifiedPending(String? txid) => (super.noSuchMethod( Invocation.method( diff --git a/test/services/coins/firo/firo_wallet_test.mocks.dart b/test/services/coins/firo/firo_wallet_test.mocks.dart index de0ee0bcb..0f7a0b0a3 100644 --- a/test/services/coins/firo/firo_wallet_test.mocks.dart +++ b/test/services/coins/firo/firo_wallet_test.mocks.dart @@ -512,12 +512,18 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX { _i5.Future>.value({}), ) as _i5.Future>); @override - _i5.Future> getUsedCoinSerials({required _i7.Coin? coin}) => + _i5.Future> getUsedCoinSerials({ + required _i7.Coin? coin, + int? startNumber = 0, + }) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - {#coin: coin}, + { + #coin: coin, + #startNumber: startNumber, + }, ), returnValue: _i5.Future>.value([]), ) as _i5.Future>); diff --git a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart index 403199041..ea48f7e85 100644 --- a/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart +++ b/test/services/coins/namecoin/namecoin_wallet_test.mocks.dart @@ -485,12 +485,18 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => + _i4.Future> getUsedCoinSerials({ + required _i6.Coin? coin, + int? startNumber = 0, + }) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - {#coin: coin}, + { + #coin: coin, + #startNumber: startNumber, + }, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/services/coins/particl/particl_wallet_test.mocks.dart b/test/services/coins/particl/particl_wallet_test.mocks.dart index a93cde382..862c352d2 100644 --- a/test/services/coins/particl/particl_wallet_test.mocks.dart +++ b/test/services/coins/particl/particl_wallet_test.mocks.dart @@ -485,12 +485,18 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX { _i4.Future>.value({}), ) as _i4.Future>); @override - _i4.Future> getUsedCoinSerials({required _i6.Coin? coin}) => + _i4.Future> getUsedCoinSerials({ + required _i6.Coin? coin, + int? startNumber = 0, + }) => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], - {#coin: coin}, + { + #coin: coin, + #startNumber: startNumber, + }, ), returnValue: _i4.Future>.value([]), ) as _i4.Future>); diff --git a/test/widget_tests/managed_favorite_test.mocks.dart b/test/widget_tests/managed_favorite_test.mocks.dart index e980b67ee..856a2c6f5 100644 --- a/test/widget_tests/managed_favorite_test.mocks.dart +++ b/test/widget_tests/managed_favorite_test.mocks.dart @@ -2236,6 +2236,19 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override + bool get torKillswitch => (super.noSuchMethod( + Invocation.getter(#torKillswitch), + returnValue: false, + ) as bool); + @override + set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + Invocation.setter( + #torKillswitch, + torKillswitch, + ), + returnValueForMissingStub: null, + ); + @override bool get showTestNetCoins => (super.noSuchMethod( Invocation.getter(#showTestNetCoins), returnValue: false, @@ -2408,6 +2421,19 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override + bool get useTor => (super.noSuchMethod( + Invocation.getter(#useTor), + returnValue: false, + ) as bool); + @override + set useTor(bool? useTor) => super.noSuchMethod( + Invocation.setter( + #useTor, + useTor, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, diff --git a/test/widget_tests/node_options_sheet_test.dart b/test/widget_tests/node_options_sheet_test.dart index b80e4682d..ce2b52560 100644 --- a/test/widget_tests/node_options_sheet_test.dart +++ b/test/widget_tests/node_options_sheet_test.dart @@ -9,6 +9,7 @@ import 'package:stackwallet/models/isar/stack_theme.dart'; import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/services/node_service.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/services/wallets.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; @@ -19,7 +20,7 @@ import 'package:tuple/tuple.dart'; import '../sample_data/theme_json.dart'; import 'node_options_sheet_test.mocks.dart'; -@GenerateMocks([Wallets, Prefs, NodeService]) +@GenerateMocks([Wallets, Prefs, NodeService, TorService]) void main() { testWidgets("Load Node Options widget", (tester) async { final mockWallets = MockWallets(); @@ -163,6 +164,7 @@ void main() { final mockWallets = MockWallets(); final mockPrefs = MockPrefs(); final mockNodeService = MockNodeService(); + final mockTorService = MockTorService(); when(mockNodeService.getNodeById(id: "node id")).thenAnswer( (realInvocation) => NodeModel( @@ -193,7 +195,8 @@ void main() { overrides: [ walletsChangeNotifierProvider.overrideWithValue(mockWallets), prefsChangeNotifierProvider.overrideWithValue(mockPrefs), - nodeServiceChangeNotifierProvider.overrideWithValue(mockNodeService) + nodeServiceChangeNotifierProvider.overrideWithValue(mockNodeService), + pTorService.overrideWithValue(mockTorService), ], child: MaterialApp( theme: ThemeData( diff --git a/test/widget_tests/node_options_sheet_test.mocks.dart b/test/widget_tests/node_options_sheet_test.mocks.dart index 86fdf5727..e99d4184f 100644 --- a/test/widget_tests/node_options_sheet_test.mocks.dart +++ b/test/widget_tests/node_options_sheet_test.mocks.dart @@ -3,25 +3,29 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i11; -import 'dart:ui' as _i13; +import 'dart:async' as _i12; +import 'dart:io' as _i8; +import 'dart:ui' as _i14; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/models/node_model.dart' as _i17; +import 'package:stackwallet/models/node_model.dart' as _i18; import 'package:stackwallet/services/coins/manager.dart' as _i6; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart' + as _i20; import 'package:stackwallet/services/node_service.dart' as _i3; -import 'package:stackwallet/services/wallets.dart' as _i8; +import 'package:stackwallet/services/tor_service.dart' as _i19; +import 'package:stackwallet/services/wallets.dart' as _i9; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i16; -import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i15; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i9; -import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i14; +import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i17; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i16; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i10; +import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i15; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' as _i7; -import 'package:stackwallet/utilities/prefs.dart' as _i12; -import 'package:tuple/tuple.dart' as _i10; +import 'package:stackwallet/utilities/prefs.dart' as _i13; +import 'package:tuple/tuple.dart' as _i11; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -87,10 +91,21 @@ class _FakeSecureStorageInterface_4 extends _i1.SmartFake ); } +class _FakeInternetAddress_5 extends _i1.SmartFake + implements _i8.InternetAddress { + _FakeInternetAddress_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + /// A class which mocks [Wallets]. /// /// See the documentation for Mockito's code generation for more information. -class MockWallets extends _i1.Mock implements _i8.Wallets { +class MockWallets extends _i1.Mock implements _i9.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -157,7 +172,7 @@ class MockWallets extends _i1.Mock implements _i8.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i9.Coin? coin}) => + List getWalletIdsFor({required _i10.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -167,20 +182,20 @@ class MockWallets extends _i1.Mock implements _i8.Wallets { returnValue: [], ) as List); @override - List<_i10.Tuple2<_i9.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> + List<_i11.Tuple2<_i10.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i10.Tuple2<_i9.Coin, + returnValue: <_i11.Tuple2<_i10.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>[], ) as List< - _i10.Tuple2<_i9.Coin, + _i11.Tuple2<_i10.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i9.Coin? coin) => + _i10.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -244,17 +259,17 @@ class MockWallets extends _i1.Mock implements _i8.Wallets { returnValueForMissingStub: null, ); @override - _i11.Future load(_i12.Prefs? prefs) => (super.noSuchMethod( + _i12.Future load(_i13.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future loadAfterStackRestore( - _i12.Prefs? prefs, + _i12.Future loadAfterStackRestore( + _i13.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -265,11 +280,11 @@ class MockWallets extends _i1.Mock implements _i8.Wallets { managers, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - void addListener(_i13.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i14.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -277,7 +292,7 @@ class MockWallets extends _i1.Mock implements _i8.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i13.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i14.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -297,7 +312,7 @@ class MockWallets extends _i1.Mock implements _i8.Wallets { /// A class which mocks [Prefs]. /// /// See the documentation for Mockito's code generation for more information. -class MockPrefs extends _i1.Mock implements _i12.Prefs { +class MockPrefs extends _i1.Mock implements _i13.Prefs { MockPrefs() { _i1.throwOnMissingStub(this); } @@ -353,12 +368,12 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); @override - _i14.SyncingType get syncType => (super.noSuchMethod( + _i15.SyncingType get syncType => (super.noSuchMethod( Invocation.getter(#syncType), - returnValue: _i14.SyncingType.currentWalletOnly, - ) as _i14.SyncingType); + returnValue: _i15.SyncingType.currentWalletOnly, + ) as _i15.SyncingType); @override - set syncType(_i14.SyncingType? syncType) => super.noSuchMethod( + set syncType(_i15.SyncingType? syncType) => super.noSuchMethod( Invocation.setter( #syncType, syncType, @@ -470,6 +485,19 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); @override + bool get torKillswitch => (super.noSuchMethod( + Invocation.getter(#torKillswitch), + returnValue: false, + ) as bool); + @override + set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + Invocation.setter( + #torKillswitch, + torKillswitch, + ), + returnValueForMissingStub: null, + ); + @override bool get showTestNetCoins => (super.noSuchMethod( Invocation.getter(#showTestNetCoins), returnValue: false, @@ -504,12 +532,12 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); @override - _i15.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( + _i16.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( Invocation.getter(#backupFrequencyType), - returnValue: _i15.BackupFrequencyType.everyTenMinutes, - ) as _i15.BackupFrequencyType); + returnValue: _i16.BackupFrequencyType.everyTenMinutes, + ) as _i16.BackupFrequencyType); @override - set backupFrequencyType(_i15.BackupFrequencyType? backupFrequencyType) => + set backupFrequencyType(_i16.BackupFrequencyType? backupFrequencyType) => super.noSuchMethod( Invocation.setter( #backupFrequencyType, @@ -642,66 +670,79 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); @override + bool get useTor => (super.noSuchMethod( + Invocation.getter(#useTor), + returnValue: false, + ) as bool); + @override + set useTor(bool? useTor) => super.noSuchMethod( + Invocation.setter( + #useTor, + useTor, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i11.Future init() => (super.noSuchMethod( + _i12.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( + _i12.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( Invocation.method( #incrementCurrentNotificationIndex, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future isExternalCallsSet() => (super.noSuchMethod( + _i12.Future isExternalCallsSet() => (super.noSuchMethod( Invocation.method( #isExternalCallsSet, [], ), - returnValue: _i11.Future.value(false), - ) as _i11.Future); + returnValue: _i12.Future.value(false), + ) as _i12.Future); @override - _i11.Future saveUserID(String? userId) => (super.noSuchMethod( + _i12.Future saveUserID(String? userId) => (super.noSuchMethod( Invocation.method( #saveUserID, [userId], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( + _i12.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( Invocation.method( #saveSignupEpoch, [signupEpoch], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i16.AmountUnit amountUnit(_i9.Coin? coin) => (super.noSuchMethod( + _i17.AmountUnit amountUnit(_i10.Coin? coin) => (super.noSuchMethod( Invocation.method( #amountUnit, [coin], ), - returnValue: _i16.AmountUnit.normal, - ) as _i16.AmountUnit); + returnValue: _i17.AmountUnit.normal, + ) as _i17.AmountUnit); @override void updateAmountUnit({ - required _i9.Coin? coin, - required _i16.AmountUnit? amountUnit, + required _i10.Coin? coin, + required _i17.AmountUnit? amountUnit, }) => super.noSuchMethod( Invocation.method( @@ -715,7 +756,7 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); @override - int maxDecimals(_i9.Coin? coin) => (super.noSuchMethod( + int maxDecimals(_i10.Coin? coin) => (super.noSuchMethod( Invocation.method( #maxDecimals, [coin], @@ -724,7 +765,7 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { ) as int); @override void updateMaxDecimals({ - required _i9.Coin? coin, + required _i10.Coin? coin, required int? maxDecimals, }) => super.noSuchMethod( @@ -739,7 +780,7 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); @override - void addListener(_i13.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i14.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -747,7 +788,7 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs { returnValueForMissingStub: null, ); @override - void removeListener(_i13.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i14.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -789,33 +830,33 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ), ) as _i7.SecureStorageInterface); @override - List<_i17.NodeModel> get primaryNodes => (super.noSuchMethod( + List<_i18.NodeModel> get primaryNodes => (super.noSuchMethod( Invocation.getter(#primaryNodes), - returnValue: <_i17.NodeModel>[], - ) as List<_i17.NodeModel>); + returnValue: <_i18.NodeModel>[], + ) as List<_i18.NodeModel>); @override - List<_i17.NodeModel> get nodes => (super.noSuchMethod( + List<_i18.NodeModel> get nodes => (super.noSuchMethod( Invocation.getter(#nodes), - returnValue: <_i17.NodeModel>[], - ) as List<_i17.NodeModel>); + returnValue: <_i18.NodeModel>[], + ) as List<_i18.NodeModel>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i11.Future updateDefaults() => (super.noSuchMethod( + _i12.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future setPrimaryNodeFor({ - required _i9.Coin? coin, - required _i17.NodeModel? node, + _i12.Future setPrimaryNodeFor({ + required _i10.Coin? coin, + required _i18.NodeModel? node, bool? shouldNotifyListeners = false, }) => (super.noSuchMethod( @@ -828,44 +869,44 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i17.NodeModel? getPrimaryNodeFor({required _i9.Coin? coin}) => + _i18.NodeModel? getPrimaryNodeFor({required _i10.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getPrimaryNodeFor, [], {#coin: coin}, - )) as _i17.NodeModel?); + )) as _i18.NodeModel?); @override - List<_i17.NodeModel> getNodesFor(_i9.Coin? coin) => (super.noSuchMethod( + List<_i18.NodeModel> getNodesFor(_i10.Coin? coin) => (super.noSuchMethod( Invocation.method( #getNodesFor, [coin], ), - returnValue: <_i17.NodeModel>[], - ) as List<_i17.NodeModel>); + returnValue: <_i18.NodeModel>[], + ) as List<_i18.NodeModel>); @override - _i17.NodeModel? getNodeById({required String? id}) => + _i18.NodeModel? getNodeById({required String? id}) => (super.noSuchMethod(Invocation.method( #getNodeById, [], {#id: id}, - )) as _i17.NodeModel?); + )) as _i18.NodeModel?); @override - List<_i17.NodeModel> failoverNodesFor({required _i9.Coin? coin}) => + List<_i18.NodeModel> failoverNodesFor({required _i10.Coin? coin}) => (super.noSuchMethod( Invocation.method( #failoverNodesFor, [], {#coin: coin}, ), - returnValue: <_i17.NodeModel>[], - ) as List<_i17.NodeModel>); + returnValue: <_i18.NodeModel>[], + ) as List<_i18.NodeModel>); @override - _i11.Future add( - _i17.NodeModel? node, + _i12.Future add( + _i18.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => @@ -878,11 +919,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future delete( + _i12.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -894,11 +935,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future setEnabledState( + _i12.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -912,12 +953,12 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future edit( - _i17.NodeModel? editedNode, + _i12.Future edit( + _i18.NodeModel? editedNode, String? password, bool? shouldNotifyListeners, ) => @@ -930,20 +971,20 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - _i11.Future updateCommunityNodes() => (super.noSuchMethod( + _i12.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i11.Future.value(), - returnValueForMissingStub: _i11.Future.value(), - ) as _i11.Future); + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); @override - void addListener(_i13.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i14.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -951,7 +992,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); @override - void removeListener(_i13.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i14.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -975,3 +1016,52 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); } + +/// A class which mocks [TorService]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTorService extends _i1.Mock implements _i19.TorService { + MockTorService() { + _i1.throwOnMissingStub(this); + } + + @override + bool get enabled => (super.noSuchMethod( + Invocation.getter(#enabled), + returnValue: false, + ) as bool); + @override + _i20.TorConnectionStatus get status => (super.noSuchMethod( + Invocation.getter(#status), + returnValue: _i20.TorConnectionStatus.disconnected, + ) as _i20.TorConnectionStatus); + @override + ({_i8.InternetAddress host, int port}) get proxyInfo => (super.noSuchMethod( + Invocation.getter(#proxyInfo), + returnValue: ( + host: _FakeInternetAddress_5( + this, + Invocation.getter(#proxyInfo), + ), + port: 0 + ), + ) as ({_i8.InternetAddress host, int port})); + @override + _i12.Future start() => (super.noSuchMethod( + Invocation.method( + #start, + [], + ), + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); + @override + _i12.Future stop() => (super.noSuchMethod( + Invocation.method( + #stop, + [], + ), + returnValue: _i12.Future.value(), + returnValueForMissingStub: _i12.Future.value(), + ) as _i12.Future); +} diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index 90afc98be..2db160a4c 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -2329,6 +2329,19 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValueForMissingStub: null, ); @override + bool get torKillswitch => (super.noSuchMethod( + Invocation.getter(#torKillswitch), + returnValue: false, + ) as bool); + @override + set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + Invocation.setter( + #torKillswitch, + torKillswitch, + ), + returnValueForMissingStub: null, + ); + @override bool get showTestNetCoins => (super.noSuchMethod( Invocation.getter(#showTestNetCoins), returnValue: false, @@ -2501,6 +2514,19 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValueForMissingStub: null, ); @override + bool get useTor => (super.noSuchMethod( + Invocation.getter(#useTor), + returnValue: false, + ) as bool); + @override + set useTor(bool? useTor) => super.noSuchMethod( + Invocation.setter( + #useTor, + useTor, + ), + returnValueForMissingStub: null, + ); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, From a97c8ad25841e5dd1f5450bb968bf722e01a5871 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 10:14:55 -0600 Subject: [PATCH 166/237] update mock --- test/electrumx_test.mocks.dart | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/electrumx_test.mocks.dart b/test/electrumx_test.mocks.dart index 57d9b7f9c..3069a2f5f 100644 --- a/test/electrumx_test.mocks.dart +++ b/test/electrumx_test.mocks.dart @@ -9,8 +9,6 @@ import 'dart:ui' as _i10; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/electrumx_rpc/rpc.dart' as _i2; -import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart' - as _i12; import 'package:stackwallet/services/tor_service.dart' as _i11; import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i8; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i7; @@ -665,11 +663,6 @@ class MockTorService extends _i1.Mock implements _i11.TorService { returnValue: false, ) as bool); @override - _i12.TorConnectionStatus get status => (super.noSuchMethod( - Invocation.getter(#status), - returnValue: _i12.TorConnectionStatus.disconnected, - ) as _i12.TorConnectionStatus); - @override ({_i3.InternetAddress host, int port}) get proxyInfo => (super.noSuchMethod( Invocation.getter(#proxyInfo), returnValue: ( From 5fcd03413fb201f1e1dd7b8e62ef4ebd745b2ec8 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 10:15:43 -0600 Subject: [PATCH 167/237] update mock p2 --- test/widget_tests/node_options_sheet_test.mocks.dart | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/widget_tests/node_options_sheet_test.mocks.dart b/test/widget_tests/node_options_sheet_test.mocks.dart index e99d4184f..047792e59 100644 --- a/test/widget_tests/node_options_sheet_test.mocks.dart +++ b/test/widget_tests/node_options_sheet_test.mocks.dart @@ -12,8 +12,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/models/node_model.dart' as _i18; import 'package:stackwallet/services/coins/manager.dart' as _i6; -import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart' - as _i20; import 'package:stackwallet/services/node_service.dart' as _i3; import 'package:stackwallet/services/tor_service.dart' as _i19; import 'package:stackwallet/services/wallets.dart' as _i9; @@ -1031,11 +1029,6 @@ class MockTorService extends _i1.Mock implements _i19.TorService { returnValue: false, ) as bool); @override - _i20.TorConnectionStatus get status => (super.noSuchMethod( - Invocation.getter(#status), - returnValue: _i20.TorConnectionStatus.disconnected, - ) as _i20.TorConnectionStatus); - @override ({_i8.InternetAddress host, int port}) get proxyInfo => (super.noSuchMethod( Invocation.getter(#proxyInfo), returnValue: ( From 696b8bc8c3cca13464ecfdfbd9d30f3cb61ec51a Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 10:37:50 -0600 Subject: [PATCH 168/237] tor connecting mutex --- lib/electrumx_rpc/electrumx.dart | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index fe4bb1796..9a2f19d75 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -15,8 +15,10 @@ import 'dart:io'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:decimal/decimal.dart'; import 'package:event_bus/event_bus.dart'; +import 'package:mutex/mutex.dart'; import 'package:stackwallet/electrumx_rpc/rpc.dart'; import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/tor_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/tor_service.dart'; @@ -80,9 +82,15 @@ class ElectrumX { // add finalizer to cancel stream subscription when all references to an // instance of ElectrumX becomes inaccessible static final Finalizer _finalizer = Finalizer( - (p0) => p0._torStatusListener?.cancel(), + (p0) { + p0._torPreferenceListener?.cancel(); + p0._torStatusListener?.cancel(); + }, ); - StreamSubscription? _torStatusListener; + StreamSubscription? _torPreferenceListener; + StreamSubscription? _torStatusListener; + + final Mutex _torConnectingLock = Mutex(); ElectrumX({ required String host, @@ -104,7 +112,21 @@ class ElectrumX { _rpcClient = client; final bus = globalEventBusForTesting ?? GlobalEventBus.instance; - _torStatusListener = bus.on().listen( + _torStatusListener = bus.on().listen( + (event) async { + switch (event.newStatus) { + case TorConnectionStatus.connecting: + await _torConnectingLock.acquire(); + break; + + case TorConnectionStatus.connected: + case TorConnectionStatus.disconnected: + _torConnectingLock.release(); + break; + } + }, + ); + _torPreferenceListener = bus.on().listen( (event) async { // not sure if we need to do anything specific here // switch (event.status) { @@ -238,7 +260,7 @@ class ElectrumX { throw WifiOnlyException(); } - _checkRpcClient(); + await _torConnectingLock.protect(() async => _checkRpcClient()); try { final requestId = requestID ?? const Uuid().v1(); @@ -324,7 +346,7 @@ class ElectrumX { throw WifiOnlyException(); } - _checkRpcClient(); + await _torConnectingLock.protect(() async => _checkRpcClient()); try { final List requestStrings = []; From 8f0da21d2b37dda4c0c2e533e1869e66b153cd79 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 11:45:07 -0500 Subject: [PATCH 169/237] WIP killswitch tests --- test/electrumx_test.dart | 118 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index effbb54a4..9e2972f72 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -40,7 +40,6 @@ void main() { final mockPrefs = MockPrefs(); when(mockPrefs.useTor).thenAnswer((realInvocation) => false); - when(mockPrefs.useTor).thenAnswer((realInvocation) => false); final torService = MockTorService(); final client = ElectrumX.from( @@ -1505,4 +1504,121 @@ void main() { verify(mockPrefs.wifiOnly).called(1); verifyNoMoreInteractions(mockPrefs); }); + + group("Tor killswitch tests", () { + test("killswitch enabled", () async { + final mockClient = MockJsonRPC(); + const command = "blockchain.transaction.get"; + const jsonArgs = '["",true]'; + when( + mockClient.request( + '{"jsonrpc": "2.0", "id": "some requestId",' + '"method": "$command","params": $jsonArgs}', + const Duration(seconds: 60), + ), + ).thenAnswer( + (_) async => JsonRPCResponse(data: { + "jsonrpc": "2.0", + "error": { + "code": 1, + "message": "None should be a transaction hash", + }, + "id": "some requestId", + }), + ); + + final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => true); + when(mockPrefs.torKillswitch).thenAnswer((realInvocation) => true); + when(mockPrefs.wifiOnly).thenAnswer((_) => false); + final torService = MockTorService(); + when(torService.enabled).thenAnswer((_) => false); + + final client = ElectrumX( + host: "some server", + port: 0, + useSSL: true, + client: mockClient, + failovers: [], + prefs: mockPrefs, + torService: torService, + ); + + try { + var result = + client.getTransaction(requestID: "some requestId", txHash: ''); + } catch (e) { + expect(e, isA()); + expect( + e.toString(), + equals( + "Tor preference and killswitch set but Tor is not enabled, not connecting to ElectrumX")); + } + + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); + verifyNoMoreInteractions(mockPrefs); + }); + + test("killswitch disabled", () async { + final mockClient = MockJsonRPC(); + const command = "blockchain.transaction.get"; + const jsonArgs = '["",true]'; + when( + mockClient.request( + '{"jsonrpc": "2.0", "id": "some requestId",' + '"method": "$command","params": $jsonArgs}', + const Duration(seconds: 60), + ), + ).thenAnswer( + (_) async => JsonRPCResponse(data: { + "jsonrpc": "2.0", + "error": { + "code": 1, + "message": "None should be a transaction hash", + }, + "id": "some requestId", + }), + ); + + final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((realInvocation) => true); + when(mockPrefs.torKillswitch).thenAnswer((realInvocation) => true); + when(mockPrefs.wifiOnly).thenAnswer((_) => false); + final torService = MockTorService(); + when(torService.enabled).thenAnswer((_) => false); + + final client = ElectrumX( + host: "some server", + port: 0, + useSSL: true, + client: mockClient, + failovers: [], + prefs: mockPrefs, + torService: torService, + ); + + bool didThrow = false; + try { + final result = await client.getTransaction( + txHash: SampleGetTransactionData.txHash0, + verbose: true, + requestID: "some requestId"); + + expect(result, SampleGetTransactionData.txData0); + } catch (e) { + didThrow = true; + // expect(e, isNotA()); + expect( + e.toString(), + isNot(equals( + "Tor preference and killswitch set but Tor is not enabled, not connecting to ElectrumX"))); + } + expect(didThrow, isFalse); + + // verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); + verifyNoMoreInteractions(mockPrefs); + }); + }); } From 25bc126cf9037eaf820298eda720de9ccf2fd773 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 10:54:31 -0600 Subject: [PATCH 170/237] untested extra bool mutex flag --- lib/electrumx_rpc/electrumx.dart | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 9a2f19d75..a93e1656e 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -91,6 +91,7 @@ class ElectrumX { StreamSubscription? _torStatusListener; final Mutex _torConnectingLock = Mutex(); + bool _requireMutex = false; ElectrumX({ required String host, @@ -117,11 +118,13 @@ class ElectrumX { switch (event.newStatus) { case TorConnectionStatus.connecting: await _torConnectingLock.acquire(); + _requireMutex = true; break; case TorConnectionStatus.connected: case TorConnectionStatus.disconnected: _torConnectingLock.release(); + _requireMutex = false; break; } }, @@ -260,7 +263,11 @@ class ElectrumX { throw WifiOnlyException(); } - await _torConnectingLock.protect(() async => _checkRpcClient()); + if (_requireMutex) { + await _torConnectingLock.protect(() async => _checkRpcClient()); + } else { + _checkRpcClient(); + } try { final requestId = requestID ?? const Uuid().v1(); @@ -346,7 +353,11 @@ class ElectrumX { throw WifiOnlyException(); } - await _torConnectingLock.protect(() async => _checkRpcClient()); + if (_requireMutex) { + await _torConnectingLock.protect(() async => _checkRpcClient()); + } else { + _checkRpcClient(); + } try { final List requestStrings = []; From 6cf88d22b596586ed3f100e7bac3e9bb9234d5df Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 12:04:25 -0500 Subject: [PATCH 171/237] fix killswitch enabled test, WIP killswitch disabled test --- test/electrumx_test.dart | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index 9e2972f72..a15e3e70f 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -1528,8 +1528,8 @@ void main() { ); final mockPrefs = MockPrefs(); - when(mockPrefs.useTor).thenAnswer((realInvocation) => true); - when(mockPrefs.torKillswitch).thenAnswer((realInvocation) => true); + when(mockPrefs.useTor).thenAnswer((_) => true); + when(mockPrefs.torKillswitch).thenAnswer((_) => true); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final torService = MockTorService(); when(torService.enabled).thenAnswer((_) => false); @@ -1545,25 +1545,26 @@ void main() { ); try { - var result = - client.getTransaction(requestID: "some requestId", txHash: ''); + var result = await client.getTransaction( + requestID: "some requestId", txHash: ''); } catch (e) { expect(e, isA()); expect( e.toString(), equals( - "Tor preference and killswitch set but Tor is not enabled, not connecting to ElectrumX")); + "Exception: Tor preference and killswitch set but Tor is not enabled, not connecting to ElectrumX")); } verify(mockPrefs.wifiOnly).called(1); verify(mockPrefs.useTor).called(1); + verify(mockPrefs.torKillswitch).called(1); verifyNoMoreInteractions(mockPrefs); }); test("killswitch disabled", () async { final mockClient = MockJsonRPC(); const command = "blockchain.transaction.get"; - const jsonArgs = '["",true]'; + const jsonArgs = '["${SampleGetTransactionData.txHash0}",true]'; when( mockClient.request( '{"jsonrpc": "2.0", "id": "some requestId",' @@ -1573,17 +1574,14 @@ void main() { ).thenAnswer( (_) async => JsonRPCResponse(data: { "jsonrpc": "2.0", - "error": { - "code": 1, - "message": "None should be a transaction hash", - }, - "id": "some requestId", + "result": SampleGetTransactionData.txData0, + "id": "some requestId" }), ); final mockPrefs = MockPrefs(); - when(mockPrefs.useTor).thenAnswer((realInvocation) => true); - when(mockPrefs.torKillswitch).thenAnswer((realInvocation) => true); + when(mockPrefs.useTor).thenAnswer((_) => true); + when(mockPrefs.torKillswitch).thenAnswer((_) => true); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final torService = MockTorService(); when(torService.enabled).thenAnswer((_) => false); @@ -1609,15 +1607,16 @@ void main() { } catch (e) { didThrow = true; // expect(e, isNotA()); - expect( - e.toString(), - isNot(equals( - "Tor preference and killswitch set but Tor is not enabled, not connecting to ElectrumX"))); + // expect( + // e.toString(), + // isNot(equals( + // "Exception: Tor preference and killswitch set but Tor is not enabled, not connecting to ElectrumX"))); } expect(didThrow, isFalse); - // verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.wifiOnly).called(1); verify(mockPrefs.useTor).called(1); + verify(mockPrefs.torKillswitch).called(1); verifyNoMoreInteractions(mockPrefs); }); }); From 03a849d61fdd6febd468fb969074b25b97462238 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 12:32:04 -0600 Subject: [PATCH 172/237] use a tor service instance variable to allow using a mocked TorService in testing --- lib/networking/http.dart | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/networking/http.dart b/lib/networking/http.dart index dc2ee2e8b..393b16bcd 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:socks5_proxy/socks_client.dart'; import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; @@ -16,6 +17,10 @@ class Response { } class HTTP { + /// Visible for testing so we can override with a mock TorService + @visibleForTesting + TorService torService = TorService.sharedInstance; + Future get({ required Uri url, Map? headers, @@ -26,8 +31,8 @@ class HTTP { if (routeOverTor) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( - TorService.sharedInstance.proxyInfo.host, - TorService.sharedInstance.proxyInfo.port, + torService.proxyInfo.host, + torService.proxyInfo.port, ), ]); } @@ -68,8 +73,8 @@ class HTTP { if (routeOverTor) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( - TorService.sharedInstance.proxyInfo.host, - TorService.sharedInstance.proxyInfo.port, + torService.proxyInfo.host, + torService.proxyInfo.port, ), ]); } From 8135079046a25a85523719f28ca4f68bf89823d7 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 12:43:52 -0600 Subject: [PATCH 173/237] access tor service via provider in ui code --- lib/pages_desktop_specific/desktop_menu.dart | 2 +- .../settings/settings_menu/tor_settings/tor_settings.dart | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index 8db055823..b7e7f28a0 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -177,7 +177,7 @@ class _DesktopMenuState extends ConsumerState { eventBus = GlobalEventBus.instance; // Initialize the TorConnectionStatus. - _torConnectionStatus = TorService.sharedInstance.enabled + _torConnectionStatus = ref.read(pTorService).enabled ? TorConnectionStatus.connected : TorConnectionStatus.disconnected; diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index cefdadff8..fc70a0fdc 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -68,7 +68,7 @@ class _TorSettingsState extends ConsumerState { _prefs.useTor = true; // Start the Tor service. - TorService.sharedInstance.start(); + ref.read(pTorService).start(); }, ); case TorConnectionStatus.connecting: @@ -90,7 +90,7 @@ class _TorSettingsState extends ConsumerState { _prefs.useTor = false; // Stop the Tor service. - TorService.sharedInstance.stop(); + ref.read(pTorService).stop(); }, ); } @@ -102,7 +102,7 @@ class _TorSettingsState extends ConsumerState { eventBus = GlobalEventBus.instance; // Set the initial Tor connection status. - _torConnectionStatus = TorService.sharedInstance.enabled + _torConnectionStatus = ref.read(pTorService).enabled ? TorConnectionStatus.connected : TorConnectionStatus.disconnected; From d4cdbd3455aad76cff976efc5df911319ab572f9 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 12:44:34 -0600 Subject: [PATCH 174/237] add and use JsonRpcException exception type --- lib/electrumx_rpc/rpc.dart | 21 ++++++++----------- .../json_rpc/json_rpc_exception.dart | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 lib/exceptions/json_rpc/json_rpc_exception.dart diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 5d0f503b8..21d64c5e3 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -14,8 +14,8 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; +import 'package:stackwallet/exceptions/json_rpc/json_rpc_exception.dart'; import 'package:stackwallet/networking/socks_socket.dart'; -import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; @@ -136,9 +136,9 @@ class JsonRPC { reason: "return req.completer.future.onError: $error\n$stackTrace", ); return JsonRPCResponse( - exception: error is Exception + exception: error is JsonRpcException ? error - : Exception( + : JsonRpcException( "req.completer.future.onError: $error\n$stackTrace", ), ); @@ -195,11 +195,8 @@ class JsonRPC { ); } else { if (proxyInfo == null) { - proxyInfo = TorService.sharedInstance.proxyInfo; - Logging.instance.log( - "ElectrumX.connect(): tor detected at $proxyInfo", - level: LogLevel.Warning, - ); + throw JsonRpcException( + "JsonRPC.connect failed with useTor=${Prefs.instance.useTor} and proxyInfo is null"); } // instantiate a socks socket at localhost and on the port selected by the tor service @@ -223,7 +220,7 @@ class JsonRPC { Logging.instance.log( "JsonRPC.connect(): failed to connect to SOCKS socket at $proxyInfo, $e", level: LogLevel.Error); - throw Exception( + throw JsonRpcException( "JsonRPC.connect(): failed to connect to SOCKS socket at $proxyInfo, $e"); } @@ -241,7 +238,7 @@ class JsonRPC { Logging.instance.log( "JsonRPC.connect(): failed to connect to $host over tor proxy at $proxyInfo, $e", level: LogLevel.Error); - throw Exception( + throw JsonRpcException( "JsonRPC.connect(): failed to connect to tor proxy, $e"); } @@ -356,7 +353,7 @@ class _JsonRPCRequest { Future.delayed(requestTimeout).then((_) { if (!isComplete) { try { - throw Exception("_JsonRPCRequest timed out: $jsonRequest"); + throw JsonRpcException("_JsonRPCRequest timed out: $jsonRequest"); } catch (e, s) { completer.completeError(e, s); onTimedOut?.call(); @@ -370,7 +367,7 @@ class _JsonRPCRequest { class JsonRPCResponse { final dynamic data; - final Exception? exception; + final JsonRpcException? exception; JsonRPCResponse({this.data, this.exception}); } diff --git a/lib/exceptions/json_rpc/json_rpc_exception.dart b/lib/exceptions/json_rpc/json_rpc_exception.dart new file mode 100644 index 000000000..e0a51ce84 --- /dev/null +++ b/lib/exceptions/json_rpc/json_rpc_exception.dart @@ -0,0 +1,21 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import 'package:stackwallet/exceptions/sw_exception.dart'; + +class JsonRpcException implements SWException { + JsonRpcException(this.message); + + @override + final String message; + + @override + toString() => message; +} From 2cf5e01d58a329cc0869f843bad9f226788ee790 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 12:56:49 -0600 Subject: [PATCH 175/237] json rpc clean up --- lib/electrumx_rpc/rpc.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 21d64c5e3..3d2d499a6 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -39,7 +39,6 @@ class JsonRPC { Socket? _socket; SOCKSSocket? _socksSocket; StreamSubscription>? _subscription; - StreamSubscription>? get subscription => _subscription; void _dataHandler(List data) { _requestQueue.nextIncompleteReq.then((req) { @@ -87,7 +86,6 @@ class JsonRPC { } if (_socksSocket != null) { _socksSocket!.write('${req.jsonRequest}\r\n'); - // _socksSocket!.socket.writeln('${req.jsonRequest}\r\n'); } // TODO different timeout length? From cdee2181337b36116d17163518de655877d02b16 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 12:59:54 -0600 Subject: [PATCH 176/237] mutex release bugfix --- lib/electrumx_rpc/electrumx.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index a93e1656e..7ee8063cd 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -123,7 +123,9 @@ class ElectrumX { case TorConnectionStatus.connected: case TorConnectionStatus.disconnected: - _torConnectingLock.release(); + if (_torConnectingLock.isLocked) { + _torConnectingLock.release(); + } _requireMutex = false; break; } From dea3be904edf40c12301c80aa3b83676f9e151aa Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 14:14:36 -0500 Subject: [PATCH 177/237] update killswitch disabled test --- test/electrumx_test.dart | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index a15e3e70f..5f192c43b 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -1581,7 +1581,7 @@ void main() { final mockPrefs = MockPrefs(); when(mockPrefs.useTor).thenAnswer((_) => true); - when(mockPrefs.torKillswitch).thenAnswer((_) => true); + when(mockPrefs.torKillswitch).thenAnswer((_) => false); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final torService = MockTorService(); when(torService.enabled).thenAnswer((_) => false); @@ -1596,23 +1596,12 @@ void main() { torService: torService, ); - bool didThrow = false; - try { - final result = await client.getTransaction( - txHash: SampleGetTransactionData.txHash0, - verbose: true, - requestID: "some requestId"); + final result = await client.getTransaction( + txHash: SampleGetTransactionData.txHash0, + verbose: true, + requestID: "some requestId"); - expect(result, SampleGetTransactionData.txData0); - } catch (e) { - didThrow = true; - // expect(e, isNotA()); - // expect( - // e.toString(), - // isNot(equals( - // "Exception: Tor preference and killswitch set but Tor is not enabled, not connecting to ElectrumX"))); - } - expect(didThrow, isFalse); + expect(result, SampleGetTransactionData.txData0); verify(mockPrefs.wifiOnly).called(1); verify(mockPrefs.useTor).called(1); From 596f917a0fdf6bbc746f61e74faabbec7037094e Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 13:29:42 -0600 Subject: [PATCH 178/237] extract desktop tor status button into its own widget and animate it when collapsing/expanding the desktop menu --- lib/pages_desktop_specific/desktop_menu.dart | 155 ++------------ .../desktop/desktop_tor_status_button.dart | 192 ++++++++++++++++++ 2 files changed, 213 insertions(+), 134 deletions(-) create mode 100644 lib/widgets/desktop/desktop_tor_status_button.dart diff --git a/lib/pages_desktop_specific/desktop_menu.dart b/lib/pages_desktop_specific/desktop_menu.dart index b7e7f28a0..64faa0d16 100644 --- a/lib/pages_desktop_specific/desktop_menu.dart +++ b/lib/pages_desktop_specific/desktop_menu.dart @@ -8,10 +8,8 @@ * */ -import 'dart:async'; import 'dart:io'; -import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -19,15 +17,12 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu.dart'; import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart'; -import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; -import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/widgets/desktop/desktop_tor_status_button.dart'; import 'package:stackwallet/widgets/desktop/living_stack_icon.dart'; -import '../services/event_bus/global_event_bus.dart'; - enum DesktopMenuItemId { myStack, exchange, @@ -59,86 +54,10 @@ class _DesktopMenuState extends ConsumerState { final Duration duration = const Duration(milliseconds: 250); late final List controllers; + late final DMIController torButtonController; double _width = expandedWidth; - // final _buyDataLoadingService = BuyDataLoadingService(); - - /// The global event bus. - late final EventBus eventBus; - - /// The subscription to the TorConnectionStatusChangedEvent. - late StreamSubscription - _torConnectionStatusSubscription; - - /// The current status of the Tor connection. - late TorConnectionStatus _torConnectionStatus; - - /// Builds the tor icon based on the current status. - Widget _buildTorIcon(TorConnectionStatus status) { - switch (status) { - case TorConnectionStatus.disconnected: - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context).extension()!.textSubtitle3, - width: 20, - height: 20, - ), - Text( - "\tDisconnected", - style: STextStyles.smallMed12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle3), - ) - ], - ); - case TorConnectionStatus.connecting: - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: - Theme.of(context).extension()!.accentColorYellow, - width: 20, - height: 20, - ), - Text( - "\tConnecting", - style: STextStyles.smallMed12(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorYellow), - ) - ], - ); - case TorConnectionStatus.connected: - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: - Theme.of(context).extension()!.accentColorGreen, - width: 20, - height: 20, - ), - Text( - "\tConnected", - style: STextStyles.smallMed12(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorGreen), - ) - ], - ); - } - } - void updateSelectedMenuItem(DesktopMenuItemId idKey) { widget.onSelectionWillChange?.call(idKey); @@ -154,6 +73,8 @@ class _DesktopMenuState extends ConsumerState { e.toggle?.call(); } + torButtonController.toggle?.call(); + setState(() { _width = expanded ? minimizedWidth : expandedWidth; }); @@ -173,43 +94,7 @@ class _DesktopMenuState extends ConsumerState { DMIController(), ]; - // Initialize the global event bus. - eventBus = GlobalEventBus.instance; - - // Initialize the TorConnectionStatus. - _torConnectionStatus = ref.read(pTorService).enabled - ? TorConnectionStatus.connected - : TorConnectionStatus.disconnected; - - // Subscribe to the TorConnectionStatusChangedEvent. - _torConnectionStatusSubscription = - eventBus.on().listen( - (event) async { - // Rebuild the widget. - setState(() { - _torConnectionStatus = event.newStatus; - }); - - // TODO implement spinner or animations and control from here - // switch (event.newStatus) { - // case TorConnectionStatus.disconnected: - // // if (_spinController.hasLoadedAnimation) { - // // _spinController.stop?.call(); - // // } - // break; - // case TorConnectionStatus.connecting: - // // if (_spinController.hasLoadedAnimation) { - // // _spinController.repeat?.call(); - // // } - // break; - // case TorConnectionStatus.connected: - // // if (_spinController.hasLoadedAnimation) { - // // _spinController.stop?.call(); - // // } - // break; - // } - }, - ); + torButtonController = DMIController(); super.initState(); } @@ -219,9 +104,7 @@ class _DesktopMenuState extends ConsumerState { for (var e in controllers) { e.dispose(); } - - // Clean up the subscription to the TorConnectionStatusChangedEvent. - _torConnectionStatusSubscription.cancel(); + torButtonController.dispose(); super.dispose(); } @@ -266,17 +149,21 @@ class _DesktopMenuState extends ConsumerState { const SizedBox( height: 5, ), - MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () { - ref.read(currentDesktopMenuItemProvider.state).state = - DesktopMenuItemId.settings; - ref - .watch(selectedSettingsMenuItemStateProvider.state) - .state = 4; - }, - child: _buildTorIcon(_torConnectionStatus)), + AnimatedContainer( + duration: duration, + width: _width == expandedWidth + ? _width - 32 // 16 padding on either side + : _width - 16, // 8 padding on either side + child: DesktopTorStatusButton( + transitionDuration: duration, + controller: torButtonController, + onPressed: () { + ref.read(currentDesktopMenuItemProvider.state).state = + DesktopMenuItemId.settings; + ref.watch(selectedSettingsMenuItemStateProvider.state).state = + 4; + }, + ), ), const SizedBox( height: 40, diff --git a/lib/widgets/desktop/desktop_tor_status_button.dart b/lib/widgets/desktop/desktop_tor_status_button.dart new file mode 100644 index 000000000..bf8ecf04e --- /dev/null +++ b/lib/widgets/desktop/desktop_tor_status_button.dart @@ -0,0 +1,192 @@ +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 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; +import 'package:stackwallet/services/tor_service.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; + +class DesktopTorStatusButton extends ConsumerStatefulWidget { + const DesktopTorStatusButton({ + super.key, + this.onPressed, + required this.transitionDuration, + this.controller, + this.labelLength = 125, + }); + + final VoidCallback? onPressed; + final Duration transitionDuration; + final DMIController? controller; + final double labelLength; + + @override + ConsumerState createState() => + _DesktopTorStatusButtonState(); +} + +class _DesktopTorStatusButtonState extends ConsumerState + with SingleTickerProviderStateMixin { + late final AnimationController animationController; + late final DMIController? controller; + late final double labelLength; + + /// The global event bus. + late final EventBus eventBus; + + /// The subscription to the TorConnectionStatusChangedEvent. + late final StreamSubscription + _torConnectionStatusSubscription; + + /// The current status of the Tor connection. + late TorConnectionStatus _torConnectionStatus; + + Color _color(TorConnectionStatus status) { + switch (status) { + case TorConnectionStatus.disconnected: + return Theme.of(context).extension()!.textSubtitle3; + case TorConnectionStatus.connecting: + return Theme.of(context).extension()!.accentColorYellow; + case TorConnectionStatus.connected: + return Theme.of(context).extension()!.accentColorGreen; + } + } + + bool _iconOnly = false; + + void toggle() { + setState(() { + _iconOnly = !_iconOnly; + }); + if (_iconOnly) { + animationController.reverse(); + } else { + animationController.forward(); + } + } + + @override + void initState() { + labelLength = widget.labelLength; + controller = widget.controller; + + // Initialize the global event bus. + eventBus = GlobalEventBus.instance; + + // Initialize the TorConnectionStatus. + _torConnectionStatus = ref.read(pTorService).enabled + ? TorConnectionStatus.connected + : TorConnectionStatus.disconnected; + + // Subscribe to the TorConnectionStatusChangedEvent. + _torConnectionStatusSubscription = + eventBus.on().listen( + (event) async { + // Rebuild the widget. + setState(() { + _torConnectionStatus = event.newStatus; + }); + + // TODO implement spinner or animations and control from here + // switch (event.newStatus) { + // case TorConnectionStatus.disconnected: + // // if (_spinController.hasLoadedAnimation) { + // // _spinController.stop?.call(); + // // } + // break; + // case TorConnectionStatus.connecting: + // // if (_spinController.hasLoadedAnimation) { + // // _spinController.repeat?.call(); + // // } + // break; + // case TorConnectionStatus.connected: + // // if (_spinController.hasLoadedAnimation) { + // // _spinController.stop?.call(); + // // } + // break; + // } + }, + ); + + controller?.toggle = toggle; + animationController = AnimationController( + vsync: this, + duration: widget.transitionDuration, + )..forward(); + + super.initState(); + } + + @override + void dispose() { + // Clean up the subscription to the TorConnectionStatusChangedEvent. + _torConnectionStatusSubscription.cancel(); + + + controller?.dispose(); + animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return TextButton( + style: Theme.of(context) + .extension()! + .getDesktopMenuButtonStyle(context), + onPressed: widget.onPressed, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 16, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AnimatedContainer( + duration: widget.transitionDuration, + width: _iconOnly ? 0 : 16, + ), + SvgPicture.asset( + Assets.svg.tor, + color: _color(_torConnectionStatus), + width: 20, + height: 20, + ), + AnimatedOpacity( + duration: widget.transitionDuration, + opacity: _iconOnly ? 0 : 1.0, + child: SizeTransition( + sizeFactor: animationController, + axis: Axis.horizontal, + axisAlignment: -1, + child: SizedBox( + width: labelLength, + child: Row( + children: [ + const SizedBox( + width: 12, + ), + Text( + _torConnectionStatus.name.capitalize(), + style: STextStyles.smallMed12(context).copyWith( + color: _color(_torConnectionStatus), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ); + } +} From 4aba0b50fb90c9b7a9025e43b808a6bba42e366b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 14:50:43 -0500 Subject: [PATCH 179/237] add to killswitch disabled test --- test/electrumx_test.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index 5f192c43b..547923d8c 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -1561,6 +1561,7 @@ void main() { verifyNoMoreInteractions(mockPrefs); }); + // useTor is true but Tor is not enabled, but because the killswitch is off, TorService calls should be made. test("killswitch disabled", () async { final mockClient = MockJsonRPC(); const command = "blockchain.transaction.get"; @@ -1583,8 +1584,8 @@ void main() { when(mockPrefs.useTor).thenAnswer((_) => true); when(mockPrefs.torKillswitch).thenAnswer((_) => false); when(mockPrefs.wifiOnly).thenAnswer((_) => false); - final torService = MockTorService(); - when(torService.enabled).thenAnswer((_) => false); + final mockTorService = MockTorService(); + when(mockTorService.enabled).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1593,7 +1594,7 @@ void main() { client: mockClient, failovers: [], prefs: mockPrefs, - torService: torService, + torService: mockTorService, ); final result = await client.getTransaction( @@ -1607,6 +1608,8 @@ void main() { verify(mockPrefs.useTor).called(1); verify(mockPrefs.torKillswitch).called(1); verifyNoMoreInteractions(mockPrefs); + verify(mockTorService.enabled).called(1); + verifyNoMoreInteractions(mockTorService); }); }); } From 941a24a6cc5ebcf3b37bec5cc6242a57d7e3163f Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 14:51:00 -0500 Subject: [PATCH 180/237] add to killswitch enabled test --- test/electrumx_test.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index 547923d8c..4cdf1dd49 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -1506,6 +1506,7 @@ void main() { }); group("Tor killswitch tests", () { + // useTor is true, but TorService is not enabled and the killswitch is on, so no TorService calls should be made. test("killswitch enabled", () async { final mockClient = MockJsonRPC(); const command = "blockchain.transaction.get"; @@ -1531,8 +1532,8 @@ void main() { when(mockPrefs.useTor).thenAnswer((_) => true); when(mockPrefs.torKillswitch).thenAnswer((_) => true); when(mockPrefs.wifiOnly).thenAnswer((_) => false); - final torService = MockTorService(); - when(torService.enabled).thenAnswer((_) => false); + final mockTorService = MockTorService(); + when(mockTorService.enabled).thenAnswer((_) => false); final client = ElectrumX( host: "some server", @@ -1541,7 +1542,7 @@ void main() { client: mockClient, failovers: [], prefs: mockPrefs, - torService: torService, + torService: mockTorService, ); try { @@ -1559,6 +1560,8 @@ void main() { verify(mockPrefs.useTor).called(1); verify(mockPrefs.torKillswitch).called(1); verifyNoMoreInteractions(mockPrefs); + verify(mockTorService.enabled).called(1); + verifyNoMoreInteractions(mockTorService); }); // useTor is true but Tor is not enabled, but because the killswitch is off, TorService calls should be made. From cea666347f8cc1f11691333ccaaed8a64a2d7238 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 14:51:54 -0500 Subject: [PATCH 181/237] add tests for Tor not in use and useTor but Tor unavailable but killswitch off --- test/electrumx_test.dart | 95 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index 4cdf1dd49..8253cf1df 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -1505,7 +1505,100 @@ void main() { verifyNoMoreInteractions(mockPrefs); }); - group("Tor killswitch tests", () { + group("Tor tests", () { + // useTor is false, so no TorService calls should be made. + test("Tor not in use", () async { + final mockClient = MockJsonRPC(); + const command = "blockchain.transaction.get"; + const jsonArgs = '["${SampleGetTransactionData.txHash0}",true]'; + when(mockClient.request( + '{"jsonrpc": "2.0", "id": "some requestId","method": "$command","params": $jsonArgs}', + const Duration(seconds: 60), + )).thenAnswer((_) async => JsonRPCResponse(data: { + "jsonrpc": "2.0", + "result": SampleGetTransactionData.txData0, + "id": "some requestId", + })); + + final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((_) => false); + when(mockPrefs.torKillswitch) + .thenAnswer((_) => false); // Or true, shouldn't matter. + when(mockPrefs.wifiOnly).thenAnswer((_) => false); + final mockTorService = MockTorService(); + when(mockTorService.enabled).thenAnswer((_) => false); + + final client = ElectrumX( + host: "some server", + port: 0, + useSSL: true, + client: mockClient, + failovers: [], + prefs: mockPrefs, + torService: mockTorService, + ); + + final result = await client.getTransaction( + txHash: SampleGetTransactionData.txHash0, + verbose: true, + requestID: "some requestId"); + + expect(result, SampleGetTransactionData.txData0); + + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); + verifyNever(mockPrefs.torKillswitch); + verifyNoMoreInteractions(mockPrefs); + verifyNever(mockTorService.enabled); + verifyNoMoreInteractions(mockTorService); + }); + + // useTor is true, but TorService is not enabled and the killswitch is off, so a clearnet call should be made. + test("useTor but Tor unavailable but killswitch off", () async { + final mockClient = MockJsonRPC(); + const command = "blockchain.transaction.get"; + const jsonArgs = '["${SampleGetTransactionData.txHash0}",true]'; + when(mockClient.request( + '{"jsonrpc": "2.0", "id": "some requestId","method": "$command","params": $jsonArgs}', + const Duration(seconds: 60), + )).thenAnswer((_) async => JsonRPCResponse(data: { + "jsonrpc": "2.0", + "result": SampleGetTransactionData.txData0, + "id": "some requestId", + })); + + final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((_) => true); + when(mockPrefs.torKillswitch).thenAnswer((_) => false); + when(mockPrefs.wifiOnly).thenAnswer((_) => false); + + final mockTorService = MockTorService(); + when(mockTorService.enabled).thenAnswer((_) => false); + + final client = ElectrumX( + host: "some server", + port: 0, + useSSL: true, + client: mockClient, + prefs: mockPrefs, + torService: mockTorService, + failovers: []); + + final result = await client.getTransaction( + txHash: SampleGetTransactionData.txHash0, + verbose: true, + requestID: "some requestId"); + + expect(result, SampleGetTransactionData.txData0); + + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); + verify(mockPrefs.torKillswitch).called(1); + verifyNoMoreInteractions(mockPrefs); + verify(mockTorService.enabled).called(1); + verifyNoMoreInteractions(mockTorService); + }); + // useTor is true, but TorService is not enabled and the killswitch is on, so no TorService calls should be made. test("killswitch enabled", () async { final mockClient = MockJsonRPC(); From 6d0bb277117a1e3d3aeb986abf19e101c2c7917b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 15:22:51 -0500 Subject: [PATCH 182/237] add a Tor in use and available test --- test/electrumx_test.dart | 63 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index 8253cf1df..c71b7549a 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; @@ -1554,7 +1556,7 @@ void main() { }); // useTor is true, but TorService is not enabled and the killswitch is off, so a clearnet call should be made. - test("useTor but Tor unavailable but killswitch off", () async { + test("Tor in use but Tor unavailable and killswitch off", () async { final mockClient = MockJsonRPC(); const command = "blockchain.transaction.get"; const jsonArgs = '["${SampleGetTransactionData.txHash0}",true]'; @@ -1574,6 +1576,10 @@ void main() { final mockTorService = MockTorService(); when(mockTorService.enabled).thenAnswer((_) => false); + when(mockTorService.proxyInfo).thenAnswer((_) => ( + host: InternetAddress('1.2.3.4'), + port: -1 + )); // Port is set to -1 until Tor is enabled. final client = ElectrumX( host: "some server", @@ -1596,6 +1602,59 @@ void main() { verify(mockPrefs.torKillswitch).called(1); verifyNoMoreInteractions(mockPrefs); verify(mockTorService.enabled).called(1); + verifyNever(mockTorService.proxyInfo); + verifyNoMoreInteractions(mockTorService); + }); + + // useTor is true and TorService is enabled, so a TorService call should be made. + test("Tor in use and available", () async { + final mockClient = MockJsonRPC(); + const command = "blockchain.transaction.get"; + const jsonArgs = '["${SampleGetTransactionData.txHash0}",true]'; + when(mockClient.request( + '{"jsonrpc": "2.0", "id": "some requestId","method": "$command","params": $jsonArgs}', + const Duration(seconds: 60), + )).thenAnswer((_) async => JsonRPCResponse(data: { + "jsonrpc": "2.0", + "result": SampleGetTransactionData.txData0, + "id": "some requestId", + })); + when(mockClient.proxyInfo) + .thenAnswer((_) => (host: InternetAddress('1.2.3.4'), port: 42)); + + final mockPrefs = MockPrefs(); + when(mockPrefs.useTor).thenAnswer((_) => true); + when(mockPrefs.torKillswitch).thenAnswer((_) => false); // Or true. + when(mockPrefs.wifiOnly).thenAnswer((_) => false); + + final mockTorService = MockTorService(); + when(mockTorService.enabled).thenAnswer((_) => true); + when(mockTorService.proxyInfo) + .thenAnswer((_) => (host: InternetAddress('1.2.3.4'), port: 42)); + + final client = ElectrumX( + host: "some server", + port: 0, + useSSL: true, + client: mockClient, + prefs: mockPrefs, + torService: mockTorService, + failovers: []); + + final result = await client.getTransaction( + txHash: SampleGetTransactionData.txHash0, + verbose: true, + requestID: "some requestId"); + + expect(result, SampleGetTransactionData.txData0); + + verify(mockClient.proxyInfo).called(1); + verify(mockPrefs.wifiOnly).called(1); + verify(mockPrefs.useTor).called(1); + verifyNever(mockPrefs.torKillswitch); + verifyNoMoreInteractions(mockPrefs); + verify(mockTorService.enabled).called(1); + verify(mockTorService.proxyInfo).called(1); verifyNoMoreInteractions(mockTorService); }); @@ -1657,7 +1716,7 @@ void main() { verifyNoMoreInteractions(mockTorService); }); - // useTor is true but Tor is not enabled, but because the killswitch is off, TorService calls should be made. + // useTor is true but Tor is not enabled, but because the killswitch is off, a clearnet call should be made. test("killswitch disabled", () async { final mockClient = MockJsonRPC(); const command = "blockchain.transaction.get"; From 9d6cdfd2c1cd3532f9fadad909fe1a167a97de8d Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 14:41:39 -0600 Subject: [PATCH 183/237] Modify HTTP to take in proxy info rather than rely on the tor service singleton --- lib/networking/http.dart | 53 ++- .../exchange/change_now/change_now_api.dart | 18 +- .../exchange/exchange_view_test.mocks.dart | 72 ++-- test/services/change_now/change_now_test.dart | 315 +++++++++--------- .../change_now/change_now_test.mocks.dart | 17 +- .../dogecoin/dogecoin_wallet_test.mocks.dart | 1 - 6 files changed, 250 insertions(+), 226 deletions(-) diff --git a/lib/networking/http.dart b/lib/networking/http.dart index 393b16bcd..6d4c775ae 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -1,9 +1,9 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:socks5_proxy/socks_client.dart'; -import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; // WIP wrapper layer @@ -11,28 +11,29 @@ import 'package:stackwallet/utilities/logger.dart'; // TODO expand this class class Response { final int code; - final String body; + final List bodyBytes; - Response(this.body, this.code); + String get body => utf8.decode(bodyBytes, allowMalformed: true); + + Response(this.bodyBytes, this.code); } class HTTP { - /// Visible for testing so we can override with a mock TorService - @visibleForTesting - TorService torService = TorService.sharedInstance; - Future get({ required Uri url, Map? headers, - required bool routeOverTor, + required ({ + InternetAddress host, + int port, + })? proxyInfo, }) async { final httpClient = HttpClient(); try { - if (routeOverTor) { + if (proxyInfo != null) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( - torService.proxyInfo.host, - torService.proxyInfo.port, + proxyInfo.host, + proxyInfo.port, ), ]); } @@ -46,8 +47,9 @@ class HTTP { } final response = await request.close(); + return Response( - await response.transform(utf8.decoder).join(), + await _bodyBytes(response), response.statusCode, ); } catch (e, s) { @@ -66,15 +68,18 @@ class HTTP { Map? headers, Object? body, Encoding? encoding, - required bool routeOverTor, + required ({ + InternetAddress host, + int port, + })? proxyInfo, }) async { final httpClient = HttpClient(); try { - if (routeOverTor) { + if (proxyInfo != null) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( - torService.proxyInfo.host, - torService.proxyInfo.port, + proxyInfo.host, + proxyInfo.port, ), ]); } @@ -92,7 +97,7 @@ class HTTP { final response = await request.close(); return Response( - await response.transform(utf8.decoder).join(), + await _bodyBytes(response), response.statusCode, ); } catch (e, s) { @@ -105,4 +110,18 @@ class HTTP { httpClient.close(force: true); } } + + Future _bodyBytes(HttpClientResponse response) { + final completer = Completer(); + final List bytes = []; + response.listen( + (data) { + bytes.addAll(data); + }, + onDone: () => completer.complete( + Uint8List.fromList(bytes), + ), + ); + return completer.future; + } } diff --git a/lib/services/exchange/change_now/change_now_api.dart b/lib/services/exchange/change_now/change_now_api.dart index d7cd5bcb9..d8b260495 100644 --- a/lib/services/exchange/change_now/change_now_api.dart +++ b/lib/services/exchange/change_now/change_now_api.dart @@ -28,6 +28,7 @@ import 'package:stackwallet/models/isar/exchange_cache/pair.dart'; import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; import 'package:stackwallet/services/exchange/exchange_response.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:tuple/tuple.dart'; @@ -38,10 +39,12 @@ class ChangeNowAPI { static const String apiVersion = "/v1"; static const String apiVersionV2 = "/v2"; - HTTP client = HTTP(); + final HTTP client; - ChangeNowAPI._(); - static final ChangeNowAPI _instance = ChangeNowAPI._(); + @visibleForTesting + ChangeNowAPI({HTTP? http}) : client = http ?? HTTP(); + + static final ChangeNowAPI _instance = ChangeNowAPI(); static ChangeNowAPI get instance => _instance; Uri _buildUri(String path, Map? params) { @@ -57,7 +60,8 @@ class ChangeNowAPI { final response = await client.get( url: uri, headers: {'Content-Type': 'application/json'}, - routeOverTor: Prefs.instance.useTor, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); String? data; try { @@ -86,7 +90,8 @@ class ChangeNowAPI { // 'Content-Type': 'application/json', 'x-changenow-api-key': apiKey, }, - routeOverTor: Prefs.instance.useTor, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final data = response.body; @@ -109,7 +114,8 @@ class ChangeNowAPI { url: uri, headers: {'Content-Type': 'application/json'}, body: jsonEncode(body), - routeOverTor: Prefs.instance.useTor, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); String? data; diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart index 1441aa4ad..5263fad93 100644 --- a/test/screen_tests/exchange/exchange_view_test.mocks.dart +++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart @@ -802,14 +802,6 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { ), ) as _i2.HTTP); @override - set client(_i2.HTTP? _client) => super.noSuchMethod( - Invocation.setter( - #client, - _client, - ), - returnValueForMissingStub: null, - ); - @override _i7.Future<_i3.ExchangeResponse>> getAvailableCurrencies({ bool? fixedRate, bool? active, @@ -1073,8 +1065,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { [], {#apiKey: apiKey}, ), - returnValue: _i7.Future< - _i3.ExchangeResponse>>.value( + returnValue: _i7 + .Future<_i3.ExchangeResponse>>.value( _FakeExchangeResponse_1>( this, Invocation.method( @@ -1115,8 +1107,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i7.Future< - _i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( + returnValue: _i7 + .Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( _FakeExchangeResponse_1<_i21.ExchangeTransaction>( this, Invocation.method( @@ -1172,8 +1164,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i7.Future< - _i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( + returnValue: _i7 + .Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( _FakeExchangeResponse_1<_i21.ExchangeTransaction>( this, Invocation.method( @@ -1197,35 +1189,35 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { )), ) as _i7.Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>>); @override - _i7.Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>> - getTransactionStatus({ + _i7.Future< + _i3 + .ExchangeResponse<_i22.ExchangeTransactionStatus>> getTransactionStatus({ required String? id, String? apiKey, }) => - (super.noSuchMethod( - Invocation.method( - #getTransactionStatus, - [], - { - #id: id, - #apiKey: apiKey, - }, - ), - returnValue: _i7.Future< - _i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>.value( - _FakeExchangeResponse_1<_i22.ExchangeTransactionStatus>( - this, - Invocation.method( - #getTransactionStatus, - [], - { - #id: id, - #apiKey: apiKey, - }, - ), - )), - ) as _i7 - .Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>); + (super.noSuchMethod( + Invocation.method( + #getTransactionStatus, + [], + { + #id: id, + #apiKey: apiKey, + }, + ), + returnValue: _i7 + .Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>.value( + _FakeExchangeResponse_1<_i22.ExchangeTransactionStatus>( + this, + Invocation.method( + #getTransactionStatus, + [], + { + #id: id, + #apiKey: apiKey, + }, + ), + )), + ) as _i7.Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>); @override _i7.Future<_i3.ExchangeResponse>> getAvailableFloatingRatePairs({bool? includePartners = false}) => diff --git a/test/services/change_now/change_now_test.dart b/test/services/change_now/change_now_test.dart index 0b909cf12..f49c52064 100644 --- a/test/services/change_now/change_now_test.dart +++ b/test/services/change_now/change_now_test.dart @@ -20,16 +20,17 @@ void main() { group("getAvailableCurrencies", () { test("getAvailableCurrencies succeeds without options", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => - Response(jsonEncode(availableCurrenciesJSON), 200)); + Response(utf8.encode(jsonEncode(availableCurrenciesJSON)), 200)); - final result = await ChangeNowAPI.instance.getAvailableCurrencies(); + final result = await instance.getAvailableCurrencies(); expect(result.exception, null); expect(result.value == null, false); @@ -38,17 +39,16 @@ void main() { test("getAvailableCurrencies succeeds with active option", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies?active=true"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(availableCurrenciesJSONActive), 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONActive)), 200)); - final result = - await ChangeNowAPI.instance.getAvailableCurrencies(active: true); + final result = await instance.getAvailableCurrencies(active: true); expect(result.exception, null); expect(result.value == null, false); @@ -57,17 +57,16 @@ void main() { test("getAvailableCurrencies succeeds with fixedRate option", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies?fixedRate=true"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(availableCurrenciesJSONFixedRate), 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONFixedRate)), 200)); - final result = - await ChangeNowAPI.instance.getAvailableCurrencies(fixedRate: true); + final result = await instance.getAvailableCurrencies(fixedRate: true); expect(result.exception, null); expect(result.value == null, false); @@ -77,18 +76,19 @@ void main() { test("getAvailableCurrencies succeeds with fixedRate and active options", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/currencies?fixedRate=true&active=true"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(availableCurrenciesJSONActiveFixedRate), 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONActiveFixedRate)), + 200)); - final result = await ChangeNowAPI.instance - .getAvailableCurrencies(active: true, fixedRate: true); + final result = + await instance.getAvailableCurrencies(active: true, fixedRate: true); expect(result.exception, null); expect(result.value == null, false); @@ -99,16 +99,16 @@ void main() { "getAvailableCurrencies fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response('{"some unexpected": "but valid json data"}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode('{"some unexpected": "but valid json data"}'), 200)); - final result = await ChangeNowAPI.instance.getAvailableCurrencies(); + final result = await instance.getAvailableCurrencies(); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); @@ -117,15 +117,15 @@ void main() { test("getAvailableCurrencies fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response("", 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(""), 400)); - final result = await ChangeNowAPI.instance.getAvailableCurrencies(); + final result = await instance.getAvailableCurrencies(); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); @@ -136,17 +136,16 @@ void main() { group("getPairedCurrencies", () { test("getPairedCurrencies succeeds without fixedRate option", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => - Response(jsonEncode(getPairedCurrenciesJSON), 200)); + Response(utf8.encode(jsonEncode(getPairedCurrenciesJSON)), 200)); - final result = - await ChangeNowAPI.instance.getPairedCurrencies(ticker: "XMR"); + final result = await instance.getPairedCurrencies(ticker: "XMR"); expect(result.exception, null); expect(result.value == null, false); @@ -155,18 +154,18 @@ void main() { test("getPairedCurrencies succeeds with fixedRate option", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/currencies-to/XMR?fixedRate=true"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(getPairedCurrenciesJSONFixedRate), 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(getPairedCurrenciesJSONFixedRate)), 200)); - final result = await ChangeNowAPI.instance - .getPairedCurrencies(ticker: "XMR", fixedRate: true); + final result = + await instance.getPairedCurrencies(ticker: "XMR", fixedRate: true); expect(result.exception, null); expect(result.value == null, false); @@ -177,17 +176,16 @@ void main() { "getPairedCurrencies fails with ChangeNowExceptionType.serializeResponseError A", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response('[{"some unexpected": "but valid json data"}]', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode('[{"some unexpected": "but valid json data"}]'), 200)); - final result = - await ChangeNowAPI.instance.getPairedCurrencies(ticker: "XMR"); + final result = await instance.getPairedCurrencies(ticker: "XMR"); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); @@ -196,16 +194,16 @@ void main() { test("getPairedCurrencies fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response("", 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(""), 400)); - final result = await ChangeNowAPI.instance - .getPairedCurrencies(ticker: "XMR", fixedRate: true); + final result = + await instance.getPairedCurrencies(ticker: "XMR", fixedRate: true); expect(result.exception!.type, ExchangeExceptionType.generic); expect(result.value == null, true); @@ -215,17 +213,17 @@ void main() { group("getMinimalExchangeAmount", () { test("getMinimalExchangeAmount succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer( - (realInvocation) async => Response('{"minAmount": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"minAmount": 42}'), 200)); - final result = await ChangeNowAPI.instance.getMinimalExchangeAmount( + final result = await instance.getMinimalExchangeAmount( fromTicker: "xmr", toTicker: "btc", apiKey: "testAPIKEY", @@ -240,16 +238,17 @@ void main() { "getMinimalExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = await ChangeNowAPI.instance.getMinimalExchangeAmount( + final result = await instance.getMinimalExchangeAmount( fromTicker: "xmr", toTicker: "btc", apiKey: "testAPIKEY", @@ -262,16 +261,16 @@ void main() { test("getMinimalExchangeAmount fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = await ChangeNowAPI.instance.getMinimalExchangeAmount( + final result = await instance.getMinimalExchangeAmount( fromTicker: "xmr", toTicker: "btc", apiKey: "testAPIKEY", @@ -286,18 +285,19 @@ void main() { group("getEstimatedExchangeAmount", () { test("getEstimatedExchangeAmount succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => Response( - '{"estimatedAmount": 58.4142873, "transactionSpeedForecast": "10-60", "warningMessage": null}', + utf8.encode( + '{"estimatedAmount": 58.4142873, "transactionSpeedForecast": "10-60", "warningMessage": null}'), 200)); - final result = await ChangeNowAPI.instance.getEstimatedExchangeAmount( + final result = await instance.getEstimatedExchangeAmount( fromTicker: "xmr", toTicker: "btc", fromAmount: Decimal.fromInt(42), @@ -313,16 +313,17 @@ void main() { "getEstimatedExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = await ChangeNowAPI.instance.getEstimatedExchangeAmount( + final result = await instance.getEstimatedExchangeAmount( fromTicker: "xmr", toTicker: "btc", fromAmount: Decimal.fromInt(42), @@ -336,16 +337,16 @@ void main() { test("getEstimatedExchangeAmount fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = await ChangeNowAPI.instance.getEstimatedExchangeAmount( + final result = await instance.getEstimatedExchangeAmount( fromTicker: "xmr", toTicker: "btc", fromAmount: Decimal.fromInt(42), @@ -366,9 +367,9 @@ void main() { // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, - // routeOverTor: false, + // proxyInfo: null, // )).thenAnswer((realInvocation) async => - // Response(jsonEncode(estFixedRateExchangeAmountJSON), 200)); + // Response(utf8.encode(jsonEncode(estFixedRateExchangeAmountJSON )), 200)); // // final result = // await ChangeNow.instance.getEstimatedFixedRateExchangeAmount( @@ -394,7 +395,7 @@ void main() { // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, - // routeOverTor: false, + // proxyInfo: null, // )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); // // final result = @@ -419,7 +420,7 @@ void main() { // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, - // routeOverTor: false, + // proxyInfo: null, // )).thenAnswer((realInvocation) async => Response('', 400)); // // final result = @@ -438,17 +439,17 @@ void main() { group("getAvailableFixedRateMarkets", () { test("getAvailableFixedRateMarkets succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => - Response(jsonEncode(fixedRateMarketsJSON), 200)); + Response(utf8.encode(jsonEncode(fixedRateMarketsJSON)), 200)); - final result = await ChangeNowAPI.instance.getAvailableFixedRateMarkets( + final result = await instance.getAvailableFixedRateMarkets( apiKey: "testAPIKEY", ); @@ -461,16 +462,17 @@ void main() { "getAvailableFixedRateMarkets fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = await ChangeNowAPI.instance.getAvailableFixedRateMarkets( + final result = await instance.getAvailableFixedRateMarkets( apiKey: "testAPIKEY", ); @@ -481,16 +483,16 @@ void main() { test("getAvailableFixedRateMarkets fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = await ChangeNowAPI.instance.getAvailableFixedRateMarkets( + final result = await instance.getAvailableFixedRateMarkets( apiKey: "testAPIKEY", ); @@ -503,20 +505,19 @@ void main() { group("createStandardExchangeTransaction", () { test("createStandardExchangeTransaction succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(createStandardTransactionResponse), 200)); + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(createStandardTransactionResponse)), 200)); - final result = - await ChangeNowAPI.instance.createStandardExchangeTransaction( + final result = await instance.createStandardExchangeTransaction( fromTicker: "xmr", toTicker: "btc", receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", @@ -535,19 +536,19 @@ void main() { "createStandardExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = - await ChangeNowAPI.instance.createStandardExchangeTransaction( + final result = await instance.createStandardExchangeTransaction( fromTicker: "xmr", toTicker: "btc", receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", @@ -565,19 +566,18 @@ void main() { test("createStandardExchangeTransaction fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, - )).thenAnswer((realInvocation) async => Response('', 400)); + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = - await ChangeNowAPI.instance.createStandardExchangeTransaction( + final result = await instance.createStandardExchangeTransaction( fromTicker: "xmr", toTicker: "btc", receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", @@ -595,22 +595,26 @@ void main() { group("createFixedRateExchangeTransaction", () { test("createFixedRateExchangeTransaction succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":"","amount":"0.3"}', encoding: null, )).thenAnswer((realInvocation) async => Response( - '{"payinAddress": "33eFX2jfeWbXMSmRe9ewUUTrmSVSxZi5cj", "payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886","payoutExtraId": "", "fromCurrency": "btc", "toCurrency": "eth", "refundAddress": "","refundExtraId": "","validUntil": "2019-09-09T14:01:04.921Z","id": "a5c73e2603f40d","amount": 62.9737711}', + utf8.encode( + '{"payinAddress": "33eFX2jfeWbXMSmRe9ewUUTrmSVSxZi5cj", "payoutAddress":' + ' "0x57f31ad4b64095347F87eDB1675566DAfF5EC886","payoutExtraId": "",' + ' "fromCurrency": "btc", "toCurrency": "eth", "refundAddress": "",' + '"refundExtraId": "","validUntil": "2019-09-09T14:01:04.921Z","id":' + ' "a5c73e2603f40d","amount": 62.9737711}'), 200)); - final result = - await ChangeNowAPI.instance.createFixedRateExchangeTransaction( + final result = await instance.createFixedRateExchangeTransaction( fromTicker: "btc", toTicker: "eth", receivingAddress: "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", @@ -630,21 +634,20 @@ void main() { "createFixedRateExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","amount":"0.3","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":""}', encoding: null, - )).thenAnswer((realInvocation) async => - Response('{"id": "a5c73e2603f40d","amount": 62.9737711}', 200)); + )).thenAnswer((realInvocation) async => Response( + utf8.encode('{"id": "a5c73e2603f40d","amount": 62.9737711}'), 200)); - final result = - await ChangeNowAPI.instance.createFixedRateExchangeTransaction( + final result = await instance.createFixedRateExchangeTransaction( fromTicker: "btc", toTicker: "eth", receivingAddress: "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", @@ -662,20 +665,19 @@ void main() { test("createFixedRateExchangeTransaction fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from": "btc","to": "eth","address": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", "amount": "1.12345","extraId": "", "userId": "","contactEmail": "","refundAddress": "", "refundExtraId": "", "rateId": "" }', encoding: null, - )).thenAnswer((realInvocation) async => Response('', 400)); + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = - await ChangeNowAPI.instance.createFixedRateExchangeTransaction( + final result = await instance.createFixedRateExchangeTransaction( fromTicker: "xmr", toTicker: "btc", receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", @@ -695,18 +697,24 @@ void main() { group("getTransactionStatus", () { test("getTransactionStatus succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => Response( - '{"status": "waiting", "payinAddress": "32Ge2ci26rj1sRGw2NjiQa9L7Xvxtgzhrj", "payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", "fromCurrency": "btc", "toCurrency": "eth", "id": "50727663e5d9a4", "updatedAt": "2019-08-22T14:47:49.943Z", "expectedSendAmount": 1, "expectedReceiveAmount": 52.31667, "createdAt": "2019-08-22T14:47:49.943Z", "isPartner": false}', + utf8.encode( + '{"status": "waiting", "payinAddress": "32Ge2ci26rj1sRGw2NjiQa9L7Xvxtgzhrj", ' + '"payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", ' + '"fromCurrency": "btc", "toCurrency": "eth", "id": "50727663e5d9a4", ' + '"updatedAt": "2019-08-22T14:47:49.943Z", "expectedSendAmount": 1, ' + '"expectedReceiveAmount": 52.31667, "createdAt": "2019-08-22T14:47:49.943Z",' + ' "isPartner": false}'), 200)); - final result = await ChangeNowAPI.instance.getTransactionStatus( + final result = await instance.getTransactionStatus( id: "47F87eDB1675566DAfF5EC886", apiKey: "testAPIKEY", ); @@ -720,16 +728,17 @@ void main() { "getTransactionStatus fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = await ChangeNowAPI.instance.getTransactionStatus( + final result = await instance.getTransactionStatus( id: "47F87eDB1675566DAfF5EC886", apiKey: "testAPIKEY", ); @@ -741,16 +750,16 @@ void main() { test("getTransactionStatus fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = await ChangeNowAPI.instance.getTransactionStatus( + final result = await instance.getTransactionStatus( id: "47F87eDB1675566DAfF5EC886", apiKey: "testAPIKEY", ); @@ -764,18 +773,17 @@ void main() { group("getAvailableFloatingRatePairs", () { test("getAvailableFloatingRatePairs succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response('["btc_xmr","btc_firo","btc_doge","eth_ltc"]', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode('["btc_xmr","btc_firo","btc_doge","eth_ltc"]'), 200)); - final result = - await ChangeNowAPI.instance.getAvailableFloatingRatePairs(); + final result = await instance.getAvailableFloatingRatePairs(); expect(result.exception, null); expect(result.value == null, false); @@ -786,17 +794,17 @@ void main() { "getAvailableFloatingRatePairs fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = - await ChangeNowAPI.instance.getAvailableFloatingRatePairs(); + final result = await instance.getAvailableFloatingRatePairs(); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); @@ -805,17 +813,16 @@ void main() { test("getAvailableFloatingRatePairs fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = - await ChangeNowAPI.instance.getAvailableFloatingRatePairs(); + final result = await instance.getAvailableFloatingRatePairs(); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); diff --git a/test/services/change_now/change_now_test.mocks.dart b/test/services/change_now/change_now_test.mocks.dart index 71e4c0ad4..f0b375d72 100644 --- a/test/services/change_now/change_now_test.mocks.dart +++ b/test/services/change_now/change_now_test.mocks.dart @@ -4,7 +4,8 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; -import 'dart:convert' as _i4; +import 'dart:convert' as _i5; +import 'dart:io' as _i4; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/networking/http.dart' as _i2; @@ -42,7 +43,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { _i3.Future<_i2.Response> get({ required Uri? url, Map? headers, - required bool? routeOverTor, + required ({_i4.InternetAddress host, int port})? proxyInfo, }) => (super.noSuchMethod( Invocation.method( @@ -51,7 +52,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { { #url: url, #headers: headers, - #routeOverTor: routeOverTor, + #proxyInfo: proxyInfo, }, ), returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( @@ -62,7 +63,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { { #url: url, #headers: headers, - #routeOverTor: routeOverTor, + #proxyInfo: proxyInfo, }, ), )), @@ -72,8 +73,8 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { required Uri? url, Map? headers, Object? body, - _i4.Encoding? encoding, - required bool? routeOverTor, + _i5.Encoding? encoding, + required ({_i4.InternetAddress host, int port})? proxyInfo, }) => (super.noSuchMethod( Invocation.method( @@ -84,7 +85,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { #headers: headers, #body: body, #encoding: encoding, - #routeOverTor: routeOverTor, + #proxyInfo: proxyInfo, }, ), returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( @@ -97,7 +98,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { #headers: headers, #body: body, #encoding: encoding, - #routeOverTor: routeOverTor, + #proxyInfo: proxyInfo, }, ), )), diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart index c19e63a44..b084875f5 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart @@ -537,7 +537,6 @@ class MockTransactionNotificationTracker extends _i1.Mock Invocation.getter(#confirmeds), returnValue: [], ) as List); - @override bool wasNotifiedPending(String? txid) => (super.noSuchMethod( Invocation.method( From afcd6d14dcd9dd662b1902370b9f9a41c98cb31a Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 15:50:25 -0500 Subject: [PATCH 184/237] add just one row of the needed tor status network status dialog row --- .../wallet_network_settings_view.dart | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index b447a53ee..249f6b51b 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -27,8 +27,10 @@ import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart'; import 'package:stackwallet/services/event_bus/events/global/blocks_remaining_event.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/refresh_percent_changed_event.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/global_event_bus.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; @@ -92,6 +94,13 @@ class _WalletNetworkSettingsViewState late int _blocksRemaining; bool _advancedIsExpanded = false; + /// The current status of the Tor connection. + late TorConnectionStatus _torConnectionStatus; + + /// The subscription to the TorConnectionStatusChangedEvent. + late final StreamSubscription + _torConnectionStatusSubscription; + Future _attemptRescan() async { if (!Platform.isLinux) await Wakelock.enable(); @@ -268,6 +277,25 @@ class _WalletNetworkSettingsViewState // } // }, // ); + + // Initialize the TorConnectionStatus. + _torConnectionStatus = ref.read(pTorService).enabled + ? TorConnectionStatus.connected + : TorConnectionStatus.disconnected; + + // Subscribe to the TorConnectionStatusChangedEvent. + _torConnectionStatusSubscription = + eventBus.on().listen( + (event) async { + // Rebuild the widget. + setState(() { + _torConnectionStatus = event.newStatus; + }); + + // TODO implement spinner or animations and control from here + }, + ); + super.initState(); } @@ -749,6 +777,53 @@ class _WalletNetworkSettingsViewState SizedBox( height: isDesktop ? 32 : 20, ), + if (TorService.sharedInstance.enabled) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tor status", + textAlign: TextAlign.left, + style: isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), + ), + GestureDetector( + onTap: () { + TorService.sharedInstance.stop(); + }, + child: Text( + "Disconnect", + style: STextStyles.link2(context), + ), + ), + ], + ), + if (!TorService.sharedInstance.enabled) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tor status", + textAlign: TextAlign.left, + style: isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), + ), + GestureDetector( + onTap: () { + TorService.sharedInstance.start(); + }, + child: Text( + "Connect", + style: STextStyles.link2(context), + ), + ), + ], + ), + SizedBox( + height: isDesktop ? 12 : 9, + ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ From 16718fd88dfecd29ee8474ebaf9a09783280311a Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 14:51:59 -0600 Subject: [PATCH 185/237] add riverpod provider for HTTP --- lib/providers/global/http_provider.dart | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 lib/providers/global/http_provider.dart diff --git a/lib/providers/global/http_provider.dart b/lib/providers/global/http_provider.dart new file mode 100644 index 000000000..84f8793c0 --- /dev/null +++ b/lib/providers/global/http_provider.dart @@ -0,0 +1,4 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/networking/http.dart'; + +final pHTTP = Provider((ref) => HTTP()); From 6d24242489ececfff9d7d1becb406cf89ce158e7 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 15:59:29 -0500 Subject: [PATCH 186/237] cancel sub on dispose and refactor row --- .../wallet_network_settings_view.dart | 41 +++++++------------ 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index 249f6b51b..c080200d0 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -305,6 +305,7 @@ class _WalletNetworkSettingsViewState _syncStatusSubscription.cancel(); _refreshSubscription.cancel(); _blocksRemainingSubscription?.cancel(); + _torConnectionStatusSubscription.cancel(); super.dispose(); } @@ -777,17 +778,17 @@ class _WalletNetworkSettingsViewState SizedBox( height: isDesktop ? 32 : 20, ), - if (TorService.sharedInstance.enabled) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Tor status", - textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tor status", + textAlign: TextAlign.left, + style: isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), + ), + if (TorService.sharedInstance.enabled) GestureDetector( onTap: () { TorService.sharedInstance.stop(); @@ -797,19 +798,7 @@ class _WalletNetworkSettingsViewState style: STextStyles.link2(context), ), ), - ], - ), - if (!TorService.sharedInstance.enabled) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Tor status", - textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), - ), + if (!TorService.sharedInstance.enabled) GestureDetector( onTap: () { TorService.sharedInstance.start(); @@ -819,8 +808,8 @@ class _WalletNetworkSettingsViewState style: STextStyles.link2(context), ), ), - ], - ), + ], + ), SizedBox( height: isDesktop ? 12 : 9, ), From 5de7b76131190c17d9bd2da233c2a6d0c116b3a5 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 15:06:50 -0600 Subject: [PATCH 187/237] http headers bugfix --- lib/networking/http.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/networking/http.dart b/lib/networking/http.dart index 6d4c775ae..e6b3b22c5 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -41,7 +41,6 @@ class HTTP { url, ); - request.headers.clear(); if (headers != null) { headers.forEach((key, value) => request.headers.add); } @@ -87,8 +86,6 @@ class HTTP { url, ); - request.headers.clear(); - if (headers != null) { headers.forEach((key, value) => request.headers.add); } From f240163a91b77a5c60352949cd9e3a903a181c4d Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Fri, 8 Sep 2023 15:09:59 -0600 Subject: [PATCH 188/237] WIP: tor http connection --- lib/services/buy/simplex/simplex_api.dart | 50 +++++--- lib/services/coins/banano/banano_wallet.dart | 116 +++++++++++------- lib/services/coins/nano/nano_wallet.dart | 114 +++++++++++------ .../exchange/trocador/trocador_api.dart | 13 +- lib/services/litescribe_api.dart | 13 +- lib/services/nano_api.dart | 20 ++- lib/utilities/paynym_is_api.dart | 16 ++- 7 files changed, 229 insertions(+), 113 deletions(-) diff --git a/lib/services/buy/simplex/simplex_api.dart b/lib/services/buy/simplex/simplex_api.dart index 8158c6b8c..1b2d26e26 100644 --- a/lib/services/buy/simplex/simplex_api.dart +++ b/lib/services/buy/simplex/simplex_api.dart @@ -12,12 +12,13 @@ import 'dart:async'; import 'dart:convert'; import 'package:decimal/decimal.dart'; -import 'package:http/http.dart' as http; import 'package:stackwallet/models/buy/response_objects/crypto.dart'; import 'package:stackwallet/models/buy/response_objects/fiat.dart'; import 'package:stackwallet/models/buy/response_objects/order.dart'; import 'package:stackwallet/models/buy/response_objects/quote.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/buy/buy_response.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/fiat_enum.dart'; import 'package:stackwallet/utilities/logger.dart'; @@ -35,8 +36,7 @@ class SimplexAPI { static final SimplexAPI _instance = SimplexAPI._(); static SimplexAPI get instance => _instance; - /// set this to override using standard http client. Useful for testing - http.Client? client; + HTTP client = HTTP(); Uri _buildUri(String path, Map? params) { if (scheme == "http") { @@ -55,10 +55,15 @@ class SimplexAPI { }; Uri url = _buildUri('api.php', data); - var res = await http.post(url, headers: headers); - if (res.statusCode != 200) { + var res = await client.post( + url: url, + headers: headers, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); + if (res.code != 200) { throw Exception( - 'getAvailableCurrencies exception: statusCode= ${res.statusCode}'); + 'getAvailableCurrencies exception: statusCode= ${res.code}'); } final jsonArray = jsonDecode(res.body); // TODO handle if invalid json @@ -116,10 +121,15 @@ class SimplexAPI { }; Uri url = _buildUri('api.php', data); - var res = await http.post(url, headers: headers); - if (res.statusCode != 200) { + var res = await client.post( + url: url, + headers: headers, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); + if (res.code != 200) { throw Exception( - 'getAvailableCurrencies exception: statusCode= ${res.statusCode}'); + 'getAvailableCurrencies exception: statusCode= ${res.code}'); } final jsonArray = jsonDecode(res.body); // TODO validate json @@ -192,9 +202,14 @@ class SimplexAPI { } Uri url = _buildUri('api.php', data); - var res = await http.get(url, headers: headers); - if (res.statusCode != 200) { - throw Exception('getQuote exception: statusCode= ${res.statusCode}'); + var res = await client.get( + url: url, + headers: headers, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); + if (res.code != 200) { + throw Exception('getQuote exception: statusCode= ${res.code}'); } final jsonArray = jsonDecode(res.body); if (jsonArray.containsKey('error') as bool) { @@ -294,9 +309,14 @@ class SimplexAPI { } Uri url = _buildUri('api.php', data); - var res = await http.get(url, headers: headers); - if (res.statusCode != 200) { - throw Exception('newOrder exception: statusCode= ${res.statusCode}'); + var res = await client.get( + url: url, + headers: headers, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); + if (res.code != 200) { + throw Exception('newOrder exception: statusCode= ${res.code}'); } final jsonArray = jsonDecode(res.body); // TODO check if valid json if (jsonArray.containsKey('error') as bool) { diff --git a/lib/services/coins/banano/banano_wallet.dart b/lib/services/coins/banano/banano_wallet.dart index 50b4a3f9e..9f314f3a3 100644 --- a/lib/services/coins/banano/banano_wallet.dart +++ b/lib/services/coins/banano/banano_wallet.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; -import 'package:http/http.dart' as http; import 'package:isar/isar.dart'; import 'package:nanodart/nanodart.dart'; import 'package:stackwallet/db/hive/db.dart'; @@ -10,6 +9,7 @@ import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/coins/coin_service.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart'; @@ -19,6 +19,7 @@ import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/nano_api.dart'; import 'package:stackwallet/services/node_service.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/constants.dart'; @@ -145,10 +146,12 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { Balance get balance => _balance ??= getCachedBalance(); Balance? _balance; + HTTP client = HTTP(); + Future requestWork(String hash) async { - return http + return client .post( - Uri.parse("https://rpc.nano.to"), // this should be a + url: Uri.parse("https://rpc.nano.to"), // this should be a headers: {'Content-type': 'application/json'}, body: json.encode( { @@ -156,17 +159,19 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { "hash": hash, }, ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ) - .then((http.Response response) { - if (response.statusCode == 200) { + .then((client) { + if (client.code == 200) { final Map decoded = - json.decode(response.body) as Map; + json.decode(client.body) as Map; if (decoded.containsKey("error")) { throw Exception("Received error ${decoded["error"]}"); } return decoded["work"] as String?; } else { - throw Exception("Received error ${response.statusCode}"); + throw Exception("Received error ${client.code}"); } }); } @@ -185,10 +190,12 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { final headers = { "Content-Type": "application/json", }; - final balanceResponse = await http.post( - Uri.parse(getCurrentNode().host), + final balanceResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: balanceBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final balanceData = jsonDecode(balanceResponse.body); @@ -203,10 +210,12 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { "representative": "true", "account": publicAddress, }); - final infoResponse = await http.post( - Uri.parse(getCurrentNode().host), + final infoResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: infoBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final String frontier = @@ -256,10 +265,12 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { "subtype": "send", "block": sendBlock, }); - final processResponse = await http.post( - Uri.parse(getCurrentNode().host), + final processResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: processBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final Map decoded = @@ -328,8 +339,13 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { final headers = { "Content-Type": "application/json", }; - final response = await http.post(Uri.parse(getCurrentNode().host), - headers: headers, body: body); + final response = await client.post( + url: Uri.parse(getCurrentNode().host), + headers: headers, + body: body, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); final data = jsonDecode(response.body); _balance = Balance( total: Amount( @@ -367,10 +383,12 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { "representative": "true", "account": publicAddress, }); - final infoResponse = await http.post( - Uri.parse(getCurrentNode().host), + final infoResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: infoBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final infoData = jsonDecode(infoResponse.body); @@ -385,10 +403,12 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { "account": publicAddress, }); - final balanceResponse = await http.post( - Uri.parse(getCurrentNode().host), + final balanceResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: balanceBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final balanceData = jsonDecode(balanceResponse.body); @@ -458,10 +478,12 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { "subtype": "receive", "block": receiveBlock, }); - final processResponse = await http.post( - Uri.parse(getCurrentNode().host), + final processResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: processBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final Map decoded = @@ -472,14 +494,18 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future confirmAllReceivable() async { - final receivableResponse = await http.post(Uri.parse(getCurrentNode().host), - headers: {"Content-Type": "application/json"}, - body: jsonEncode({ - "action": "receivable", - "source": "true", - "account": await currentReceivingAddress, - "count": "-1", - })); + final receivableResponse = await client.post( + url: Uri.parse(getCurrentNode().host), + headers: {"Content-Type": "application/json"}, + body: jsonEncode({ + "action": "receivable", + "source": "true", + "account": await currentReceivingAddress, + "count": "-1", + }), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); final receivableData = await jsonDecode(receivableResponse.body); if (receivableData["blocks"] == "") { @@ -501,13 +527,17 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { await confirmAllReceivable(); final receivingAddress = (await _currentReceivingAddress)!; final String publicAddress = receivingAddress.value; - final response = await http.post(Uri.parse(getCurrentNode().host), - headers: {"Content-Type": "application/json"}, - body: jsonEncode({ - "action": "account_history", - "account": publicAddress, - "count": "-1", - })); + final response = await client.post( + url: Uri.parse(getCurrentNode().host), + headers: {"Content-Type": "application/json"}, + body: jsonEncode({ + "action": "account_history", + "account": publicAddress, + "count": "-1", + }), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); final data = await jsonDecode(response.body); final transactions = data["history"] is List ? data["history"] as List : []; @@ -819,17 +849,19 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { Future testNetworkConnection() async { final uri = Uri.parse(getCurrentNode().host); - final response = await http.post( - uri, + final response = await client.post( + url: uri, headers: {"Content-Type": "application/json"}, body: jsonEncode( { "action": "version", }, ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - return response.statusCode == 200; + return response.code == 200; } Timer? _networkAliveTimer; @@ -915,10 +947,12 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB { final headers = { "Content-Type": "application/json", }; - final infoResponse = await http.post( - Uri.parse(getCurrentNode().host), + final infoResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: infoBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final infoData = jsonDecode(infoResponse.body); diff --git a/lib/services/coins/nano/nano_wallet.dart b/lib/services/coins/nano/nano_wallet.dart index 34de1034d..56404ed1a 100644 --- a/lib/services/coins/nano/nano_wallet.dart +++ b/lib/services/coins/nano/nano_wallet.dart @@ -11,7 +11,6 @@ import 'dart:async'; import 'dart:convert'; -import 'package:http/http.dart' as http; import 'package:isar/isar.dart'; import 'package:nanodart/nanodart.dart'; import 'package:stackwallet/db/isar/main_db.dart'; @@ -19,6 +18,7 @@ import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/coins/coin_service.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart'; @@ -28,6 +28,7 @@ import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/nano_api.dart'; import 'package:stackwallet/services/node_service.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/constants.dart'; @@ -154,10 +155,12 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { Balance get balance => _balance ??= getCachedBalance(); Balance? _balance; + HTTP client = HTTP(); + Future requestWork(String hash) async { - return http + return client .post( - Uri.parse("https://rpc.nano.to"), // this should be a + url: Uri.parse("https://rpc.nano.to"), // this should be a headers: {'Content-type': 'application/json'}, body: json.encode( { @@ -165,9 +168,11 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { "hash": hash, }, ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ) - .then((http.Response response) { - if (response.statusCode == 200) { + .then((Response response) { + if (response.code == 200) { final Map decoded = json.decode(response.body) as Map; if (decoded.containsKey("error")) { @@ -175,7 +180,7 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { } return decoded["work"] as String?; } else { - throw Exception("Received error ${response.statusCode}"); + throw Exception("Received error ${response.body}"); } }); } @@ -194,10 +199,12 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { final headers = { "Content-Type": "application/json", }; - final balanceResponse = await http.post( - Uri.parse(getCurrentNode().host), + final balanceResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: balanceBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final balanceData = jsonDecode(balanceResponse.body); @@ -212,10 +219,12 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { "representative": "true", "account": publicAddress, }); - final infoResponse = await http.post( - Uri.parse(getCurrentNode().host), + final infoResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: infoBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final String frontier = @@ -265,10 +274,12 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { "subtype": "send", "block": sendBlock, }); - final processResponse = await http.post( - Uri.parse(getCurrentNode().host), + final processResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: processBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final Map decoded = @@ -333,8 +344,13 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { final headers = { "Content-Type": "application/json", }; - final response = await http.post(Uri.parse(getCurrentNode().host), - headers: headers, body: body); + final response = await client.post( + url: Uri.parse(getCurrentNode().host), + headers: headers, + body: body, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); final data = jsonDecode(response.body); _balance = Balance( total: Amount( @@ -372,10 +388,12 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { "representative": "true", "account": publicAddress, }); - final infoResponse = await http.post( - Uri.parse(getCurrentNode().host), + final infoResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: infoBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final infoData = jsonDecode(infoResponse.body); @@ -390,10 +408,12 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { "account": publicAddress, }); - final balanceResponse = await http.post( - Uri.parse(getCurrentNode().host), + final balanceResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: balanceBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final balanceData = jsonDecode(balanceResponse.body); @@ -463,10 +483,12 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { "subtype": "receive", "block": receiveBlock, }); - final processResponse = await http.post( - Uri.parse(getCurrentNode().host), + final processResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: processBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final Map decoded = @@ -477,14 +499,18 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { } Future confirmAllReceivable() async { - final receivableResponse = await http.post(Uri.parse(getCurrentNode().host), - headers: {"Content-Type": "application/json"}, - body: jsonEncode({ - "action": "receivable", - "source": "true", - "account": await currentReceivingAddress, - "count": "-1", - })); + final receivableResponse = await client.post( + url: Uri.parse(getCurrentNode().host), + headers: {"Content-Type": "application/json"}, + body: jsonEncode({ + "action": "receivable", + "source": "true", + "account": await currentReceivingAddress, + "count": "-1", + }), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); final receivableData = await jsonDecode(receivableResponse.body); if (receivableData["blocks"] == "") { @@ -506,13 +532,17 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { await confirmAllReceivable(); final receivingAddress = (await _currentReceivingAddress)!; final String publicAddress = receivingAddress.value; - final response = await http.post(Uri.parse(getCurrentNode().host), - headers: {"Content-Type": "application/json"}, - body: jsonEncode({ - "action": "account_history", - "account": publicAddress, - "count": "-1", - })); + final response = await client.post( + url: Uri.parse(getCurrentNode().host), + headers: {"Content-Type": "application/json"}, + body: jsonEncode({ + "action": "account_history", + "account": publicAddress, + "count": "-1", + }), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); final data = await jsonDecode(response.body); final transactions = data["history"] is List ? data["history"] as List : []; @@ -830,17 +860,19 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { Future testNetworkConnection() async { final uri = Uri.parse(getCurrentNode().host); - final response = await http.post( - uri, + final response = await client.post( + url: uri, headers: {"Content-Type": "application/json"}, body: jsonEncode( { "action": "version", }, ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - return response.statusCode == 200; + return response.code == 200; } Timer? _networkAliveTimer; @@ -926,10 +958,12 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB { final headers = { "Content-Type": "application/json", }; - final infoResponse = await http.post( - Uri.parse(getCurrentNode().host), + final infoResponse = await client.post( + url: Uri.parse(getCurrentNode().host), headers: headers, body: infoBody, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final infoData = jsonDecode(infoResponse.body); diff --git a/lib/services/exchange/trocador/trocador_api.dart b/lib/services/exchange/trocador/trocador_api.dart index 4c9b2cbac..8dadfb499 100644 --- a/lib/services/exchange/trocador/trocador_api.dart +++ b/lib/services/exchange/trocador/trocador_api.dart @@ -12,14 +12,16 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter_native_splash/cli_commands.dart'; -import 'package:http/http.dart' as http; import 'package:stackwallet/exceptions/exchange/exchange_exception.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/exchange/exchange_response.dart'; import 'package:stackwallet/services/exchange/trocador/response_objects/trocador_coin.dart'; import 'package:stackwallet/services/exchange/trocador/response_objects/trocador_rate.dart'; import 'package:stackwallet/services/exchange/trocador/response_objects/trocador_trade.dart'; import 'package:stackwallet/services/exchange/trocador/response_objects/trocador_trade_new.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; const kTrocadorApiKey = "8rFqf7QLxX1mUBiNPEMaLUpV2biz6n"; const kTrocadorRefCode = "9eHm9BkQfS"; @@ -31,6 +33,7 @@ abstract class TrocadorAPI { static const String markup = "1"; static const String minKYCRating = "C"; + static HTTP client = HTTP(); static Uri _buildUri({ required String method, @@ -46,12 +49,14 @@ abstract class TrocadorAPI { int code = -1; try { debugPrint("URI: $uri"); - final response = await http.get( - uri, + final response = await client.get( + url: uri, headers: {'Content-Type': 'application/json'}, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - code = response.statusCode; + code = response.code; debugPrint("CODE: $code"); debugPrint("BODY: ${response.body}"); diff --git a/lib/services/litescribe_api.dart b/lib/services/litescribe_api.dart index 1acc047b8..ea4013457 100644 --- a/lib/services/litescribe_api.dart +++ b/lib/services/litescribe_api.dart @@ -1,8 +1,10 @@ import 'dart:convert'; -import 'package:http/http.dart' as http; import 'package:stackwallet/dto/ordinals/inscription_data.dart'; import 'package:stackwallet/dto/ordinals/litescribe_response.dart'; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; +import 'package:stackwallet/utilities/prefs.dart'; class LitescribeAPI { static final LitescribeAPI _instance = LitescribeAPI._internal(); @@ -13,12 +15,17 @@ class LitescribeAPI { } LitescribeAPI._internal(); + HTTP client = HTTP(); late String baseUrl; Future _getResponse(String endpoint) async { - final response = await http.get(Uri.parse('$baseUrl$endpoint')); - if (response.statusCode == 200) { + final response = await client.get( + url: Uri.parse('$baseUrl$endpoint'), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); + if (response.code == 200) { return LitescribeResponse(data: _validateJson(response.body)); } else { throw Exception( diff --git a/lib/services/nano_api.dart b/lib/services/nano_api.dart index 3173bfbe6..c0d194a31 100644 --- a/lib/services/nano_api.dart +++ b/lib/services/nano_api.dart @@ -1,7 +1,9 @@ import 'dart:convert'; -import 'package:http/http.dart' as http; import 'package:nanodart/nanodart.dart'; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; +import 'package:stackwallet/utilities/prefs.dart'; class NanoAPI { static Future< @@ -16,9 +18,11 @@ class NanoAPI { NAccountInfo? accountInfo; Exception? exception; + HTTP client = HTTP(); + try { - final response = await http.post( - server, + final response = await client.post( + url: server, headers: { "Content-Type": "application/json", }, @@ -27,6 +31,8 @@ class NanoAPI { "representative": "true", "account": account, }), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final map = jsonDecode(response.body); @@ -105,8 +111,10 @@ class NanoAPI { required Uri server, required Map block, }) async { - final response = await http.post( - server, + HTTP client = HTTP(); + + final response = await client.post( + url: server, headers: { "Content-Type": "application/json", }, @@ -116,6 +124,8 @@ class NanoAPI { "subtype": "change", "block": block, }), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); return jsonDecode(response.body); diff --git a/lib/utilities/paynym_is_api.dart b/lib/utilities/paynym_is_api.dart index f69e751cd..67cafa1c1 100644 --- a/lib/utilities/paynym_is_api.dart +++ b/lib/utilities/paynym_is_api.dart @@ -11,13 +11,15 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; -import 'package:http/http.dart' as http; import 'package:stackwallet/models/paynym/created_paynym.dart'; import 'package:stackwallet/models/paynym/paynym_account.dart'; import 'package:stackwallet/models/paynym/paynym_claim.dart'; import 'package:stackwallet/models/paynym/paynym_follow.dart'; import 'package:stackwallet/models/paynym/paynym_response.dart'; import 'package:stackwallet/models/paynym/paynym_unfollow.dart'; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:tuple/tuple.dart'; // todo: better error message parsing (from response itself?) @@ -26,6 +28,8 @@ class PaynymIsApi { static const String baseURL = "https://paynym.is/api"; static const String version = "/v1"; + HTTP client = HTTP(); + Future, int>> _post( String endpoint, Map body, [ @@ -38,21 +42,23 @@ class PaynymIsApi { final headers = { 'Content-Type': 'application/json; charset=UTF-8', }..addAll(additionalHeaders); - final response = await http.post( - uri, + final response = await client.post( + url: uri, headers: headers, body: jsonEncode(body), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); debugPrint("Paynym request uri: $uri"); debugPrint("Paynym request body: $body"); debugPrint("Paynym request headers: $headers"); - debugPrint("Paynym response code: ${response.statusCode}"); + debugPrint("Paynym response code: ${response.code}"); debugPrint("Paynym response body: ${response.body}"); return Tuple2( jsonDecode(response.body) as Map, - response.statusCode, + response.code, ); } From e34df895de3ace6a519f76dd4ac9c44cfd8ee510 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 16:23:10 -0500 Subject: [PATCH 189/237] add rest of tor status row to wallet network settings view --- .../wallet_network_settings_view.dart | 93 +++++++++++++++++-- 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index c080200d0..c028630d8 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -550,14 +550,6 @@ class _WalletNetworkSettingsViewState "Synchronized", style: STextStyles.w600_12(context), ), - Text( - "100%", - style: STextStyles.syncPercent(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorGreen, - ), - ), ], ), ), @@ -813,6 +805,91 @@ class _WalletNetworkSettingsViewState SizedBox( height: isDesktop ? 12 : 9, ), + RoundedWhiteContainer( + borderColor: isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), + child: Row( + children: [ + if (TorService.sharedInstance.enabled) + Container( + width: _iconSize, + height: _iconSize, + decoration: BoxDecoration( + color: Theme.of(context) + .extension()! + .accentColorGreen + .withOpacity(0.2), + borderRadius: BorderRadius.circular(_iconSize), + ), + child: Center( + child: SvgPicture.asset( + Assets.svg.tor, + height: isDesktop ? 19 : 14, + width: isDesktop ? 19 : 14, + color: Theme.of(context) + .extension()! + .accentColorGreen, + ), + ), + ), + if (!TorService.sharedInstance.enabled) + Container( + width: _iconSize, + height: _iconSize, + decoration: BoxDecoration( + color: Theme.of(context) + .extension()! + .textDark + .withOpacity(0.08), + borderRadius: BorderRadius.circular(_iconSize), + ), + child: Center( + child: SvgPicture.asset( + Assets.svg.tor, + height: isDesktop ? 19 : 14, + width: isDesktop ? 19 : 14, + color: Theme.of(context) + .extension()! + .textDark, + ), + ), + ), + SizedBox( + width: _boxPadding, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Tor status", + style: STextStyles.desktopTextExtraExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark, + ), + ), + if (TorService.sharedInstance.enabled) + Text( + "Connected", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + if (!TorService.sharedInstance.enabled) + Text( + "Disconnected", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ], + ), + ], + ), + ), + SizedBox( + height: isDesktop ? 32 : 20, + ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ From 832bfc08f74076f2f6eb5e5c9d48157e7be4ba43 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 16:26:43 -0500 Subject: [PATCH 190/237] show connecting state --- .../wallet_network_settings_view.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index c028630d8..840a9c385 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -872,12 +872,18 @@ class _WalletNetworkSettingsViewState .textDark, ), ), - if (TorService.sharedInstance.enabled) + if (_torConnectionStatus == TorConnectionStatus.connected) Text( "Connected", style: STextStyles.desktopTextExtraExtraSmall(context), ), - if (!TorService.sharedInstance.enabled) + if (_torConnectionStatus == TorConnectionStatus.connecting) + Text( + "Connecting...", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + if (_torConnectionStatus == + TorConnectionStatus.disconnected) Text( "Disconnected", style: STextStyles.desktopTextExtraExtraSmall(context), From 95790faf526ff9cc9243b0b68641d7d1527b6e57 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 8 Sep 2023 16:43:24 -0500 Subject: [PATCH 191/237] toggle useTor pref on text button click in wallet network settings view and formatting --- .../wallet_network_settings_view.dart | 8 ++++++++ .../settings/settings_menu/tor_settings/tor_settings.dart | 3 +-- lib/widgets/desktop/desktop_tor_status_button.dart | 1 - 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index 840a9c385..dd8bc253e 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -35,6 +35,7 @@ import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/animated_text.dart'; @@ -101,6 +102,9 @@ class _WalletNetworkSettingsViewState late final StreamSubscription _torConnectionStatusSubscription; + /// The Prefs instance. + final Prefs _prefs = Prefs.instance; + Future _attemptRescan() async { if (!Platform.isLinux) await Wakelock.enable(); @@ -784,6 +788,8 @@ class _WalletNetworkSettingsViewState GestureDetector( onTap: () { TorService.sharedInstance.stop(); + // And toggle preference. + _prefs.useTor = false; }, child: Text( "Disconnect", @@ -794,6 +800,8 @@ class _WalletNetworkSettingsViewState GestureDetector( onTap: () { TorService.sharedInstance.start(); + // And toggle preference. + _prefs.useTor = true; }, child: Text( "Connect", diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index fc70a0fdc..76a1fa3bc 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -21,6 +21,7 @@ import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart'; @@ -29,8 +30,6 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -import '../../../../utilities/prefs.dart'; - class TorSettings extends ConsumerStatefulWidget { const TorSettings({Key? key}) : super(key: key); diff --git a/lib/widgets/desktop/desktop_tor_status_button.dart b/lib/widgets/desktop/desktop_tor_status_button.dart index bf8ecf04e..42677aa0f 100644 --- a/lib/widgets/desktop/desktop_tor_status_button.dart +++ b/lib/widgets/desktop/desktop_tor_status_button.dart @@ -129,7 +129,6 @@ class _DesktopTorStatusButtonState extends ConsumerState // Clean up the subscription to the TorConnectionStatusChangedEvent. _torConnectionStatusSubscription.cancel(); - controller?.dispose(); animationController.dispose(); super.dispose(); From b278f691cc64d52bf9d71fdb4f651aca8e5a7daa Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 15:41:37 -0600 Subject: [PATCH 192/237] add init function to TorService so the compiled rust lib isn't loaded on instance creation but rather on init being called --- lib/main.dart | 1 + .../tor_settings/tor_settings.dart | 3 +++ lib/services/tor_service.dart | 22 +++++++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 53c0df498..c39bc766d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -174,6 +174,7 @@ void main() async { // Some refactoring will need to be done here to make sure we don't make any // network calls before starting up tor if (Prefs.instance.useTor) { + TorService.sharedInstance.init(); await TorService.sharedInstance.start(); } diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index 76a1fa3bc..95c798930 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -66,6 +66,9 @@ class _TorSettingsState extends ConsumerState { // Toggle the useTor preference. _prefs.useTor = true; + // Start the Tor service. + ref.read(pTorService).init(); + // Start the Tor service. ref.read(pTorService).start(); }, diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index dc95f89c8..3998dba5e 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -9,7 +9,7 @@ import 'package:tor/tor.dart'; final pTorService = Provider((_) => TorService.sharedInstance); class TorService { - final _tor = Tor(); + Tor? _tor; /// Flag to indicate that a Tor circuit is thought to have been established. bool _enabled = false; @@ -30,9 +30,15 @@ class TorService { int port, }) get proxyInfo => ( host: InternetAddress.loopbackIPv4, - port: _tor.port, + port: _tor!.port, ); + /// Initialize the tor ffi lib instance if it hasn't already been set. Nothing + /// changes if _tor is already been set. + void init({Tor? mockableOverride}) { + _tor ??= mockableOverride ?? Tor(); + } + /// Start the Tor service. /// /// This will start the Tor service and establish a Tor circuit. @@ -41,6 +47,10 @@ class TorService { /// /// Returns a Future that completes when the Tor service has started. Future start() async { + if (_tor == null) { + throw Exception("TorService.init has not been called!"); + } + if (_enabled) { // already started so just return // could throw an exception here or something so the caller @@ -58,7 +68,7 @@ class TorService { "Tor connection status changed: connecting", ), ); - await _tor.start(); + await _tor!.start(); // no exception or error so we can (probably?) assume tor // has started successfully _enabled = true; @@ -89,6 +99,10 @@ class TorService { } Future stop() async { + if (_tor == null) { + throw Exception("TorService.init has not been called!"); + } + if (!_enabled) { // already stopped so just return // could throw an exception here or something so the caller @@ -99,7 +113,7 @@ class TorService { // Stop the Tor service. try { - await _tor.disable(); + await _tor!.disable(); // no exception or error so we can (probably?) assume tor // has started successfully _enabled = false; From aa56d39721c001368681c338f6a9f4cfbb440dbe Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 16:01:47 -0600 Subject: [PATCH 193/237] await tor start/stop before modifying pref --- .../tor_settings/tor_settings_view.dart | 10 +- .../tor_settings/tor_settings.dart | 255 +++++++++--------- 2 files changed, 138 insertions(+), 127 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 76b51889d..1c5127a34 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -13,6 +13,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; @@ -35,7 +36,7 @@ class TorSettingsView extends ConsumerStatefulWidget { } class _TorSettingsViewState extends ConsumerState { - TorConnectionStatus _networkStatus = TorConnectionStatus.disconnected; + late TorConnectionStatus _networkStatus; Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { @@ -123,6 +124,9 @@ class _TorSettingsViewState extends ConsumerState { @override void initState() { + _networkStatus = ref.read(pTorService).enabled + ? TorConnectionStatus.connected + : TorConnectionStatus.disconnected; super.initState(); } @@ -195,7 +199,7 @@ class _TorSettingsViewState extends ConsumerState { ), ], ), - SizedBox( + const SizedBox( height: 30, ), RoundedWhiteContainer( @@ -213,7 +217,7 @@ class _TorSettingsViewState extends ConsumerState { ), ), ), - SizedBox( + const SizedBox( height: 8, ), RoundedWhiteContainer( diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index 95c798930..b95863768 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -21,7 +21,7 @@ import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; -import 'package:stackwallet/utilities/prefs.dart'; +import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart'; @@ -40,9 +40,6 @@ class TorSettings extends ConsumerStatefulWidget { } class _TorSettingsState extends ConsumerState { - // The Prefs instance. - final Prefs _prefs = Prefs.instance; - /// The global event bus. EventBus eventBus = GlobalEventBus.instance; @@ -51,8 +48,7 @@ class _TorSettingsState extends ConsumerState { _torConnectionStatusSubscription; /// The current status of the Tor connection. - late TorConnectionStatus _torConnectionStatus = - TorConnectionStatus.disconnected; + late TorConnectionStatus _torConnectionStatus; /// Build the connect/disconnect button. Widget _buildConnectButton(TorConnectionStatus status) { @@ -62,15 +58,22 @@ class _TorSettingsState extends ConsumerState { label: "Connect to Tor", width: 200, buttonHeight: ButtonHeight.m, - onPressed: () { - // Toggle the useTor preference. - _prefs.useTor = true; - + onPressed: () async { // Start the Tor service. ref.read(pTorService).init(); // Start the Tor service. - ref.read(pTorService).start(); + try { + await ref.read(pTorService).start(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = true; + } catch (e, s) { + Logging.instance.log( + "Error starting tor: $e\n$s", + level: LogLevel.Error, + ); + } }, ); case TorConnectionStatus.connecting: @@ -87,12 +90,19 @@ class _TorSettingsState extends ConsumerState { label: "Disconnect from Tor", width: 200, buttonHeight: ButtonHeight.m, - onPressed: () { - // Toggle the useTor preference. - _prefs.useTor = false; - + onPressed: () async { // Stop the Tor service. - ref.read(pTorService).stop(); + try { + await ref.read(pTorService).stop(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = false; + } catch (e, s) { + Logging.instance.log( + "Error stopping tor: $e\n$s", + level: LogLevel.Error, + ); + } }, ); } @@ -198,63 +208,62 @@ class _TorSettingsState extends ConsumerState { recognizer: TapGestureRecognizer() ..onTap = () { showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.end, + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + DesktopDialogCloseButton( + onPressedOverride: () => + Navigator.of(context) + .pop(true), + ), + ], + ), + Padding( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisSize: MainAxisSize.max, children: [ - DesktopDialogCloseButton( - onPressedOverride: () => - Navigator.of(context) - .pop(true), + Text( + "What is Tor?", + style: + STextStyles.desktopH2( + context), + ), + const SizedBox( + height: 20, + ), + Text( + "Short for \"The Onion Router\", is an open-source software that enables internet communication" + " to remain anonymous by routing internet traffic through a series of layered nodes," + " to obscure the origin and destination of data.", + style: STextStyles + .desktopTextMedium( + context) + .copyWith( + color: Theme.of(context) + .extension< + StackColors>()! + .textDark3, + ), ), ], ), - Padding( - padding: - const EdgeInsets.all(20), - child: Column( - mainAxisSize: - MainAxisSize.max, - children: [ - Text( - "What is Tor?", - style: - STextStyles.desktopH2( - context), - ), - const SizedBox( - height: 20, - ), - Text( - "Short for \"The Onion Router\", is an open-source software that enables internet communication" - " to remain anonymous by routing internet traffic through a series of layered nodes," - " to obscure the origin and destination of data.", - style: STextStyles - .desktopTextMedium( - context) - .copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textDark3, - ), - ), - ], - ), - ), - ], - ), - ); - }); + ), + ], + ), + ); + }, + ); }, ), ], @@ -301,66 +310,64 @@ class _TorSettingsState extends ConsumerState { recognizer: TapGestureRecognizer() ..onTap = () { showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.end, + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + DesktopDialogCloseButton( + onPressedOverride: () => + Navigator.of(context) + .pop(true), + ), + ], + ), + Padding( + padding: + const EdgeInsets.all(20), + child: Column( + mainAxisSize: + MainAxisSize.max, children: [ - DesktopDialogCloseButton( - onPressedOverride: () => - Navigator.of( + Text( + "What is Tor killswitch?", + style: STextStyles + .desktopH2(context), + ), + const SizedBox( + height: 20, + ), + Text( + "A security feature that protects your information from accidental exposure by" + " disconnecting your device from the Tor network if your virtual private network (VPN)" + " connection is disrupted or compromised.", + style: STextStyles + .desktopTextMedium( context) - .pop(true), + .copyWith( + color: Theme.of( + context) + .extension< + StackColors>()! + .textDark3, + ), ), ], ), - Padding( - padding: - const EdgeInsets.all( - 20), - child: Column( - mainAxisSize: - MainAxisSize.max, - children: [ - Text( - "What is Tor killswitch?", - style: STextStyles - .desktopH2( - context), - ), - const SizedBox( - height: 20, - ), - Text( - "A security feature that protects your information from accidental exposure by" - " disconnecting your device from the Tor network if your virtual private network (VPN)" - " connection is disrupted or compromised.", - style: STextStyles - .desktopTextMedium( - context) - .copyWith( - color: Theme.of( - context) - .extension< - StackColors>()! - .textDark3, - ), - ), - ], - ), - ), - ], - ), - ); - }); + ), + ], + ), + ); + }, + ); }, ), ], From c7cb9c30d9f377f40a561375fca4da3b6025e838 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 16:11:21 -0600 Subject: [PATCH 194/237] await tor start/stop before modifying pref and use providers --- .../wallet_network_settings_view.dart | 54 +++++++++++++------ .../tor_settings/tor_settings.dart | 2 +- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index dd8bc253e..32289b6f3 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -35,7 +35,7 @@ import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; -import 'package:stackwallet/utilities/prefs.dart'; +import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/animated_text.dart'; @@ -102,9 +102,6 @@ class _WalletNetworkSettingsViewState late final StreamSubscription _torConnectionStatusSubscription; - /// The Prefs instance. - final Prefs _prefs = Prefs.instance; - Future _attemptRescan() async { if (!Platform.isLinux) await Wakelock.enable(); @@ -784,24 +781,47 @@ class _WalletNetworkSettingsViewState ? STextStyles.desktopTextExtraExtraSmall(context) : STextStyles.smallMed12(context), ), - if (TorService.sharedInstance.enabled) + if (ref.watch( + prefsChangeNotifierProvider.select((value) => value.useTor))) GestureDetector( - onTap: () { - TorService.sharedInstance.stop(); - // And toggle preference. - _prefs.useTor = false; + onTap: () async { + // Stop the Tor service. + try { + await ref.read(pTorService).stop(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = false; + } catch (e, s) { + Logging.instance.log( + "Error stopping tor: $e\n$s", + level: LogLevel.Error, + ); + } }, child: Text( "Disconnect", style: STextStyles.link2(context), ), ), - if (!TorService.sharedInstance.enabled) + if (!ref.watch( + prefsChangeNotifierProvider.select((value) => value.useTor))) GestureDetector( - onTap: () { - TorService.sharedInstance.start(); - // And toggle preference. - _prefs.useTor = true; + onTap: () async { + // Init the Tor service if it hasn't already been. + ref.read(pTorService).init(); + + // Start the Tor service. + try { + await ref.read(pTorService).start(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = true; + } catch (e, s) { + Logging.instance.log( + "Error starting tor: $e\n$s", + level: LogLevel.Error, + ); + } }, child: Text( "Connect", @@ -821,7 +841,8 @@ class _WalletNetworkSettingsViewState isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), child: Row( children: [ - if (TorService.sharedInstance.enabled) + if (ref.watch(prefsChangeNotifierProvider + .select((value) => value.useTor))) Container( width: _iconSize, height: _iconSize, @@ -843,7 +864,8 @@ class _WalletNetworkSettingsViewState ), ), ), - if (!TorService.sharedInstance.enabled) + if (!ref.watch(prefsChangeNotifierProvider + .select((value) => value.useTor))) Container( width: _iconSize, height: _iconSize, diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index b95863768..1b18a1ee8 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -59,7 +59,7 @@ class _TorSettingsState extends ConsumerState { width: 200, buttonHeight: ButtonHeight.m, onPressed: () async { - // Start the Tor service. + // Init the Tor service if it hasn't already been. ref.read(pTorService).init(); // Start the Tor service. From dea35fd80167068b6041d7a2cd7c310ef9dd4251 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Fri, 8 Sep 2023 16:53:09 -0600 Subject: [PATCH 195/237] WIP: tor http connection --- lib/pages/ordinals/ordinal_details_view.dart | 17 ++- .../desktop_ordinal_details_view.dart | 17 ++- lib/services/coins/tezos/tezos_wallet.dart | 57 +++++++-- lib/services/ethereum/ethereum_api.dart | 109 +++++++++++------- lib/services/monkey_service.dart | 17 ++- lib/themes/theme_service.dart | 21 +++- 6 files changed, 168 insertions(+), 70 deletions(-) diff --git a/lib/pages/ordinals/ordinal_details_view.dart b/lib/pages/ordinals/ordinal_details_view.dart index 041401767..17a518bf9 100644 --- a/lib/pages/ordinals/ordinal_details_view.dart +++ b/lib/pages/ordinals/ordinal_details_view.dart @@ -5,20 +5,22 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:http/http.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; import 'package:stackwallet/models/isar/ordinal.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/providers/db/main_db_provider.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/amount/amount_formatter.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/show_loading.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/background.dart'; @@ -230,11 +232,16 @@ class _OrdinalImageGroup extends StatelessWidget { static const _spacing = 12.0; Future _savePngToFile() async { - final response = await get(Uri.parse(ordinal.content)); + HTTP client = HTTP(); - if (response.statusCode != 200) { - throw Exception( - "statusCode=${response.statusCode} body=${response.bodyBytes}"); + final response = await client.get( + url: Uri.parse(ordinal.content), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); + + if (response.code != 200) { + throw Exception("statusCode=${response.code} body=${response.bodyBytes}"); } final bytes = response.bodyBytes; diff --git a/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart b/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart index b0225f286..f1c6093aa 100644 --- a/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart +++ b/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart @@ -3,21 +3,23 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:http/http.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; import 'package:stackwallet/models/isar/ordinal.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart'; import 'package:stackwallet/providers/db/main_db_provider.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/amount/amount_formatter.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/show_loading.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; @@ -50,11 +52,16 @@ class _DesktopOrdinalDetailsViewState late final UTXO? utxo; Future _savePngToFile() async { - final response = await get(Uri.parse(widget.ordinal.content)); + HTTP client = HTTP(); - if (response.statusCode != 200) { - throw Exception( - "statusCode=${response.statusCode} body=${response.bodyBytes}"); + final response = await client.get( + url: Uri.parse(widget.ordinal.content), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); + + if (response.code != 200) { + throw Exception("statusCode=${response.code} body=${response.bodyBytes}"); } final bytes = response.bodyBytes; diff --git a/lib/services/coins/tezos/tezos_wallet.dart b/lib/services/coins/tezos/tezos_wallet.dart index 6e128478e..130671264 100644 --- a/lib/services/coins/tezos/tezos_wallet.dart +++ b/lib/services/coins/tezos/tezos_wallet.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:decimal/decimal.dart'; -import 'package:http/http.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/models/balance.dart'; @@ -11,6 +10,7 @@ import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart' import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/coins/coin_service.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart'; @@ -19,6 +19,7 @@ import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/constants.dart'; @@ -101,6 +102,8 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override bool get shouldAutoSync => _shouldAutoSync; + HTTP client = HTTP(); + @override set shouldAutoSync(bool shouldAutoSync) { if (_shouldAutoSync != shouldAutoSync) { @@ -239,7 +242,12 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future estimateFeeFor(Amount amount, int feeRate) async { var api = "https://api.tzstats.com/series/op?start_date=today&collapse=1d"; - var response = jsonDecode((await get(Uri.parse(api))).body)[0]; + var response = jsonDecode((await client.get( + url: Uri.parse(api), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + )) + .body)[0]; double totalFees = response[4] as double; int totalTxs = response[8] as int; int feePerTx = (totalFees / totalTxs * 1000000).floor(); @@ -259,7 +267,12 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future get fees async { var api = "https://api.tzstats.com/series/op?start_date=today&collapse=10d"; - var response = jsonDecode((await get(Uri.parse(api))).body); + var response = jsonDecode((await client.get( + url: Uri.parse(api), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + )) + .body); double totalFees = response[0][4] as double; int totalTxs = response[0][8] as int; int feePerTx = (totalFees / totalTxs * 1000000).floor(); @@ -493,8 +506,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { try { String balanceCall = "https://api.mainnet.tzkt.io/v1/accounts/" "${await currentReceivingAddress}/balance"; - var response = jsonDecode( - await get(Uri.parse(balanceCall)).then((value) => value.body)); + var response = jsonDecode(await client + .get( + url: Uri.parse(balanceCall), + proxyInfo: Prefs.instance.useTor + ? TorService.sharedInstance.proxyInfo + : null, + ) + .then((value) => value.body)); Amount balanceInAmount = Amount( rawValue: BigInt.parse(response.toString()), fractionDigits: coin.decimals); @@ -516,8 +535,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateTransactions() async { String transactionsCall = "https://api.mainnet.tzkt.io/v1/accounts/" "${await currentReceivingAddress}/operations"; - var response = jsonDecode( - await get(Uri.parse(transactionsCall)).then((value) => value.body)); + var response = jsonDecode(await client + .get( + url: Uri.parse(transactionsCall), + proxyInfo: Prefs.instance.useTor + ? TorService.sharedInstance.proxyInfo + : null, + ) + .then((value) => value.body)); List> txs = []; for (var tx in response as List) { if (tx["type"] == "transaction") { @@ -591,8 +616,14 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { Future updateChainHeight() async { try { var api = "${getCurrentNode().host}/chains/main/blocks/head/header/shell"; - var jsonParsedResponse = - jsonDecode(await get(Uri.parse(api)).then((value) => value.body)); + var jsonParsedResponse = jsonDecode(await client + .get( + url: Uri.parse(api), + proxyInfo: Prefs.instance.useTor + ? TorService.sharedInstance.proxyInfo + : null, + ) + .then((value) => value.body)); final int intHeight = int.parse(jsonParsedResponse["level"].toString()); Logging.instance.log("Chain height: $intHeight", level: LogLevel.Info); await updateCachedChainHeight(intHeight); @@ -672,8 +703,12 @@ class TezosWallet extends CoinServiceAPI with WalletCache, WalletDB { @override Future testNetworkConnection() async { try { - await get(Uri.parse( - "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell")); + await client.get( + url: Uri.parse( + "${getCurrentNode().host}:${getCurrentNode().port}/chains/main/blocks/head/header/shell"), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); return true; } catch (e) { return false; diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index 5e95e3aa1..19fa6b081 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -17,11 +17,14 @@ import 'package:stackwallet/dto/ethereum/eth_tx_dto.dart'; import 'package:stackwallet/dto/ethereum/pending_eth_tx_dto.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart'; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/default_nodes.dart'; import 'package:stackwallet/utilities/eth_commons.dart'; import 'package:stackwallet/utilities/extensions/extensions.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:tuple/tuple.dart'; class EthApiException implements Exception { @@ -46,19 +49,23 @@ class EthereumResponse { abstract class EthereumAPI { static String get stackBaseServer => DefaultNodes.ethereum.host; + static HTTP client = HTTP(); + static Future>> getEthTransactions({ required String address, int firstBlock = 0, bool includeTokens = false, }) async { try { - final response = await get( - Uri.parse( + final response = await client.get( + url: Uri.parse( "$stackBaseServer/export?addrs=$address&firstBlock=$firstBlock", ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - if (response.statusCode == 200) { + if (response.code == 200) { if (response.body.isNotEmpty) { final json = jsonDecode(response.body) as Map; final list = json["data"] as List?; @@ -86,7 +93,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getEthTransactions($address) failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -173,13 +180,15 @@ abstract class EthereumAPI { List txns, ) async { try { - final response = await get( - Uri.parse( + final response = await client.get( + url: Uri.parse( "$stackBaseServer/transactions?transactions=${txns.map((e) => e.hash).join(" ")}&raw=true", ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - if (response.statusCode == 200) { + if (response.code == 200) { if (response.body.isNotEmpty) { final json = jsonDecode(response.body) as Map; final list = List>.from(json["data"] as List); @@ -208,7 +217,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getEthTransactionNonces($txns) failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -231,13 +240,15 @@ abstract class EthereumAPI { static Future>> getEthTokenTransactionsByTxids(List txids) async { try { - final response = await get( - Uri.parse( + final response = await client.get( + url: Uri.parse( "$stackBaseServer/transactions?transactions=${txids.join(" ")}", ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - if (response.statusCode == 200) { + if (response.code == 200) { if (response.body.isNotEmpty) { final json = jsonDecode(response.body) as Map; final list = json["data"] as List?; @@ -257,13 +268,13 @@ abstract class EthereumAPI { } else { throw EthApiException( "getEthTokenTransactionsByTxids($txids) response is empty but status code is " - "${response.statusCode}", + "${response.code}", ); } } else { throw EthApiException( "getEthTokenTransactionsByTxids($txids) failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -288,13 +299,15 @@ abstract class EthereumAPI { required String tokenContractAddress, }) async { try { - final response = await get( - Uri.parse( + final response = await client.get( + url: Uri.parse( "$stackBaseServer/export?addrs=$address&emitter=$tokenContractAddress&logs=true", ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - if (response.statusCode == 200) { + if (response.code == 200) { if (response.body.isNotEmpty) { final json = jsonDecode(response.body) as Map; final list = json["data"] as List?; @@ -321,7 +334,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getTokenTransactions($address, $tokenContractAddress) failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -422,9 +435,13 @@ abstract class EthereumAPI { final uri = Uri.parse( "$stackBaseServer/tokens?addrs=$contractAddress $address", ); - final response = await get(uri); + final response = await client.get( + url: uri, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); - if (response.statusCode == 200) { + if (response.code == 200) { final json = jsonDecode(response.body); if (json["data"] is List) { final map = json["data"].first as Map; @@ -442,7 +459,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getWalletTokenBalance($address) failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -469,9 +486,13 @@ abstract class EthereumAPI { final uri = Uri.parse( "$stackBaseServer/state?addrs=$address&parts=all", ); - final response = await get(uri); + final response = await client.get( + url: uri, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); - if (response.statusCode == 200) { + if (response.code == 200) { final json = jsonDecode(response.body); if (json["data"] is List) { final map = json["data"].first as Map; @@ -488,7 +509,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getAddressNonce($address) failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -510,13 +531,15 @@ abstract class EthereumAPI { static Future> getGasOracle() async { try { - final response = await get( - Uri.parse( + final response = await client.get( + url: Uri.parse( "$stackBaseServer/gas-prices", ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - if (response.statusCode == 200) { + if (response.code == 200) { final json = jsonDecode(response.body) as Map; if (json["success"] == true) { try { @@ -541,7 +564,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getGasOracle() failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -579,13 +602,15 @@ abstract class EthereumAPI { static Future> getTokenContractInfoByAddress( String contractAddress) async { try { - final response = await get( - Uri.parse( + final response = await client.get( + url: Uri.parse( "$stackBaseServer/tokens?addrs=$contractAddress&parts=all", ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - if (response.statusCode == 200) { + if (response.code == 200) { final json = jsonDecode(response.body) as Map; if (json["data"] is List) { final map = Map.from(json["data"].first as Map); @@ -621,7 +646,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getTokenByContractAddress($contractAddress) failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -646,13 +671,15 @@ abstract class EthereumAPI { required String contractAddress, }) async { try { - final response = await get( - Uri.parse( + final response = await client.get( + url: Uri.parse( "$stackBaseServer/abis?addrs=$contractAddress&verbose=true", ), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - if (response.statusCode == 200) { + if (response.code == 200) { final json = jsonDecode(response.body)["data"] as List; return EthereumResponse( @@ -662,7 +689,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getTokenAbi($name, $contractAddress) failed with status code: " - "${response.statusCode}", + "${response.code}", ); } } on EthApiException catch (e) { @@ -687,9 +714,13 @@ abstract class EthereumAPI { String contractAddress, ) async { try { - final response = await get(Uri.parse( - "$stackBaseServer/state?addrs=$contractAddress&parts=proxy")); - if (response.statusCode == 200) { + final response = await client.get( + url: Uri.parse( + "$stackBaseServer/state?addrs=$contractAddress&parts=proxy"), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); + if (response.code == 200) { final json = jsonDecode(response.body); final list = json["data"] as List; final map = Map.from(list.first as Map); @@ -701,7 +732,7 @@ abstract class EthereumAPI { } else { throw EthApiException( "getProxyTokenImplementationAddress($contractAddress) failed with" - " status code: ${response.statusCode}", + " status code: ${response.code}", ); } } on EthApiException catch (e) { diff --git a/lib/services/monkey_service.dart b/lib/services/monkey_service.dart index 46dfbb0ef..eb3687fcd 100644 --- a/lib/services/monkey_service.dart +++ b/lib/services/monkey_service.dart @@ -1,13 +1,16 @@ import 'dart:typed_data'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:http/http.dart' as http; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; final pMonKeyService = Provider((ref) => MonKeyService()); class MonKeyService { static const baseURL = "https://monkey.banano.cc/api/v1/monkey/"; + HTTP client = HTTP(); Future fetchMonKey({ required String address, @@ -20,13 +23,17 @@ class MonKeyService { url += '?format=png&size=512&background=false'; } - final response = await http.get(Uri.parse(url)); + final response = await client.get( + url: Uri.parse(url), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); - if (response.statusCode == 200) { - return response.bodyBytes; + if (response.code == 200) { + return Uint8List.fromList(response.bodyBytes); } else { throw Exception( - "statusCode=${response.statusCode} body=${response.body}", + "statusCode=${response.code} body=${response.body}", ); } } catch (e, s) { diff --git a/lib/themes/theme_service.dart b/lib/themes/theme_service.dart index baeac44f2..62165d646 100644 --- a/lib/themes/theme_service.dart +++ b/lib/themes/theme_service.dart @@ -15,11 +15,13 @@ import 'package:archive/archive_io.dart'; import 'package:crypto/crypto.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:http/http.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/models/isar/stack_theme.dart'; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; final pThemeService = Provider((ref) { @@ -39,6 +41,8 @@ class ThemeService { void init(MainDB db) => _db ??= db; + HTTP client = HTTP(); + Future install({required Uint8List themeArchiveData}) async { final themesDir = StackFileSystem.themesDir!; @@ -207,7 +211,11 @@ class ThemeService { Future> fetchThemes() async { try { - final response = await get(Uri.parse("$baseServerUrl/themes")); + final response = await client.get( + url: Uri.parse("$baseServerUrl/themes"), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); final jsonList = jsonDecode(response.body) as List; @@ -230,10 +238,13 @@ class ThemeService { required StackThemeMetaData themeMetaData, }) async { try { - final response = - await get(Uri.parse("$baseServerUrl/theme/${themeMetaData.id}")); + final response = await client.get( + url: Uri.parse("$baseServerUrl/theme/${themeMetaData.id}"), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ); - final bytes = response.bodyBytes; + final bytes = Uint8List.fromList(response.bodyBytes); // verify hash final digest = sha256.convert(bytes); From 6efcdf97eaaaec96e53c35b13414b06b4cd710fe Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 10 Sep 2023 08:25:28 -0600 Subject: [PATCH 196/237] clean up cancel transaction in epiccash wallet --- .../coins/epiccash/epiccash_wallet.dart | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index ba5a7b3f7..08758b03f 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -421,34 +421,28 @@ class EpicCashWallet extends CoinServiceAPI late SecureStorageInterface _secureStore; + /// returns an empty String on success, error message on failure Future cancelPendingTransactionAndPost(String txSlateId) async { - String? result; try { - result = await cancelPendingTransaction(txSlateId); + final String wallet = (await _secureStore.read( + key: '${_walletId}_wallet', + ))!; + + final result = await m.protect(() async { + return await compute( + _cancelTransactionWrapper, + Tuple2( + wallet, + txSlateId, + ), + ); + }); Logging.instance.log("result?: $result", level: LogLevel.Info); + return result; } catch (e, s) { Logging.instance.log("$e, $s", level: LogLevel.Error); + return e.toString(); } - return result!; - } - -// - /// returns an empty String on success, error message on failure - Future cancelPendingTransaction(String txSlateId) async { - final String wallet = - (await _secureStore.read(key: '${_walletId}_wallet'))!; - - String? result; - await m.protect(() async { - result = await compute( - _cancelTransactionWrapper, - Tuple2( - wallet, - txSlateId, - ), - ); - }); - return result!; } @override From 381672d368d44f9010d809b4a9ad7fb049c6140b Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 10 Sep 2023 10:44:33 -0600 Subject: [PATCH 197/237] apply scans error propagation fix --- .../coins/epiccash/epiccash_wallet.dart | 181 ++++++++++-------- 1 file changed, 100 insertions(+), 81 deletions(-) diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index 08758b03f..44865e195 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -437,7 +437,10 @@ class EpicCashWallet extends CoinServiceAPI ), ); }); - Logging.instance.log("result?: $result", level: LogLevel.Info); + Logging.instance.log( + "cancel $txSlateId result: $result", + level: LogLevel.Info, + ); return result; } catch (e, s) { Logging.instance.log("$e, $s", level: LogLevel.Error); @@ -661,25 +664,8 @@ class EpicCashWallet extends CoinServiceAPI await epicUpdateLastScannedBlock(await getRestoreHeight()); - if (!await startScans()) { - refreshMutex = false; - GlobalEventBus.instance.fire( - NodeConnectionStatusChangedEvent( - NodeConnectionStatus.disconnected, - walletId, - coin, - ), - ); - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.unableToSync, - walletId, - coin, - ), - ); - return; - } - await refresh(); + await _startScans(); + GlobalEventBus.instance.fire( WalletSyncStatusChangedEvent( WalletSyncStatus.synced, @@ -688,12 +674,23 @@ class EpicCashWallet extends CoinServiceAPI ), ); } catch (e, s) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.unableToSync, + walletId, + coin, + ), + ); + + Logging.instance.log( + "Exception rethrown from fullRescan(): $e\n$s", + level: LogLevel.Error, + printFullLength: true, + ); + rethrow; + } finally { refreshMutex = false; - Logging.instance - .log("$e, $s", level: LogLevel.Error, printFullLength: true); } - refreshMutex = false; - return; } @override @@ -1159,58 +1156,97 @@ class EpicCashWallet extends CoinServiceAPI // TODO: refresh anything that needs to be refreshed/updated due to epicbox info changed } - Future startScans() async { + Future _startScans() async { try { + //First stop the current listener if (ListenerManager.pointer != null) { + Logging.instance + .log("LISTENER HANDLER IS NOT NULL ....", level: LogLevel.Info); + Logging.instance + .log("STOPPING ANY WALLET LISTENER ....", level: LogLevel.Info); epicboxListenerStop(ListenerManager.pointer!); } - final wallet = await _secureStore.read(key: '${_walletId}_wallet'); - var restoreHeight = epicGetRestoreHeight(); - var chainHeight = await this.chainHeight; - if (epicGetLastScannedBlock() == null) { - await epicUpdateLastScannedBlock(await getRestoreHeight()); - } - int lastScannedBlock = epicGetLastScannedBlock()!; - const MAX_PER_LOOP = 10000; - await getSyncPercent; - for (; lastScannedBlock < chainHeight;) { - chainHeight = await this.chainHeight; - lastScannedBlock = epicGetLastScannedBlock()!; - Logging.instance.log( - "chainHeight: $chainHeight, restoreHeight: $restoreHeight, lastScannedBlock: $lastScannedBlock", - level: LogLevel.Info); - int? nextScannedBlock; - await m.protect(() async { - ReceivePort receivePort = await getIsolate({ - "function": "scanOutPuts", - "wallet": wallet!, - "startHeight": lastScannedBlock, - "numberOfBlocks": MAX_PER_LOOP, - }, name: walletName); + // max number of blocks to scan per loop iteration + const scanChunkSize = 10000; - var message = await receivePort.first; - if (message is String) { - Logging.instance - .log("this is a string $message", level: LogLevel.Error); - stop(receivePort); - throw Exception("scanOutPuts isolate failed"); + // force firing of scan progress event + await getSyncPercent; + + // fetch current chain height and last scanned block (should be the + // restore height if full rescan or a wallet restore) + int chainHeight = await this.chainHeight; + int lastScannedBlock = + epicGetLastScannedBlock() ?? await getRestoreHeight(); + + // loop while scanning in chain in chunks (of blocks?) + while (lastScannedBlock < chainHeight) { + Logging.instance.log( + "chainHeight: $chainHeight, lastScannedBlock: $lastScannedBlock", + level: LogLevel.Info, + ); + + final int nextScannedBlock = await m.protect(() async { + ReceivePort? receivePort; + try { + receivePort = await getIsolate({ + "function": "scanOutPuts", + "wallet": wallet!, + "startHeight": lastScannedBlock, + "numberOfBlocks": scanChunkSize, + }, name: walletName); + + // get response + final message = await receivePort.first; + + // check for error message + if (message is String) { + throw Exception("scanOutPuts isolate failed: $message"); + } + + // attempt to grab next scanned block number + final nextScanned = int.tryParse(message['outputs'] as String); + if (nextScanned == null) { + throw Exception( + "scanOutPuts failed to parse next scanned block number from: $message", + ); + } + + return nextScanned; + } catch (_) { + rethrow; + } finally { + if (receivePort != null) { + // kill isolate + stop(receivePort); + } } - nextScannedBlock = int.parse(message['outputs'] as String); - stop(receivePort); - Logging.instance - .log('Closing scanOutPuts!\n $message', level: LogLevel.Info); }); - await epicUpdateLastScannedBlock(nextScannedBlock!); + + // update local cache + await epicUpdateLastScannedBlock(nextScannedBlock); + + // force firing of scan progress event await getSyncPercent; + + // update while loop condition variables + chainHeight = await this.chainHeight; + lastScannedBlock = nextScannedBlock; } - Logging.instance.log("successfully at the tip", level: LogLevel.Info); + + Logging.instance.log( + "_startScans successfully at the tip", + level: LogLevel.Info, + ); + //Once scanner completes restart listener await listenToEpicbox(); - return true; } catch (e, s) { - Logging.instance.log("$e, $s", level: LogLevel.Warning); - return false; + Logging.instance.log( + "_startScans failed: $e\n$s", + level: LogLevel.Error, + ); + rethrow; } } @@ -1490,24 +1526,7 @@ class EpicCashWallet extends CoinServiceAPI final int curAdd = await setCurrentIndex(); await _getReceivingAddressForIndex(curAdd); - if (!await startScans()) { - refreshMutex = false; - GlobalEventBus.instance.fire( - NodeConnectionStatusChangedEvent( - NodeConnectionStatus.disconnected, - walletId, - coin, - ), - ); - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.unableToSync, - walletId, - coin, - ), - ); - return; - } + await _startScans(); unawaited(startSync()); From 4160196135abb3bfdc37de06244fd49b7968b4db Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 10 Sep 2023 10:55:06 -0600 Subject: [PATCH 198/237] clean up epic wallet file --- .../coins/epiccash/epiccash_wallet.dart | 83 +------------------ 1 file changed, 1 insertion(+), 82 deletions(-) diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index 44865e195..2dacb1639 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -1700,26 +1700,13 @@ class EpicCashWallet extends CoinServiceAPI final List> txnsData = []; - // int latestTxnBlockHeight = - // DB.instance.get(boxName: walletId, key: "storedTxnDataHeight") - // as int? ?? - // 0; final slatesToCommits = await getSlatesToCommits(); for (var tx in jsonTransactions) { Logging.instance.log("tx: $tx", level: LogLevel.Info); // // TODO: does "confirmed" mean finalized? If so please remove this todo final isConfirmed = tx["confirmed"] as bool; - // // TODO: since we are now caching tx history in hive are we losing anything by skipping here? - // // TODO: we can skip this filtering if it causes issues as the cache is later merged with updated data anyways - // // this would just make processing and updating cache more efficient - // if (txHeight > 0 && - // txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS && - // isConfirmed) { - // continue; - // } - // Logging.instance.log("Transactions listed below"); - // Logging.instance.log(jsonTransactions); + int amt = 0; if (tx["tx_type"] == "TxReceived" || tx["tx_type"] == "TxReceivedCancelled") { @@ -1820,24 +1807,7 @@ class EpicCashWallet extends CoinServiceAPI } } - // - // midSortedTx["inputSize"] = tx["num_inputs"]; - // midSortedTx["outputSize"] = tx["num_outputs"]; - // midSortedTx["aliens"] = []; - // midSortedTx["inputs"] = []; - // midSortedTx["outputs"] = []; - - // key id not used afaik? - // midSortedTx["key_id"] = tx["parent_key_id"]; - - // if (txHeight >= latestTxnBlockHeight) { - // latestTxnBlockHeight = txHeight; - // } - txnsData.add(Tuple2(txn, transactionAddress)); - // cachedMap?.remove(tx["id"].toString()); - // cachedMap?.remove(commitId); - // Logging.instance.log("cmap: $cachedMap", level: LogLevel.Info); } await db.addNewTransactionData(txnsData, walletId); @@ -1852,57 +1822,6 @@ class EpicCashWallet extends CoinServiceAPI ), ); } - - // midSortedArray - // .sort((a, b) => (b["timestamp"] as int) - (a["timestamp"] as int)); - // - // final Map result = {"dateTimeChunks": []}; - // final dateArray = []; - // - // for (int i = 0; i < midSortedArray.length; i++) { - // final txObject = midSortedArray[i]; - // final date = extractDateFromTimestamp(txObject["timestamp"] as int); - // - // final txTimeArray = [txObject["timestamp"], date]; - // - // if (dateArray.contains(txTimeArray[1])) { - // result["dateTimeChunks"].forEach((dynamic chunk) { - // if (extractDateFromTimestamp(chunk["timestamp"] as int) == - // txTimeArray[1]) { - // if (chunk["transactions"] == null) { - // chunk["transactions"] = >[]; - // } - // chunk["transactions"].add(txObject); - // } - // }); - // } else { - // dateArray.add(txTimeArray[1]); - // - // final chunk = { - // "timestamp": txTimeArray[0], - // "transactions": [txObject], - // };sendAll - // - // // result["dateTimeChunks"]. - // result["dateTimeChunks"].add(chunk); - // } - // } - // final transactionsMap = - // TransactionData.fromJson(result).getAllTransactions(); - // if (cachedMap != null) { - // transactionsMap.addAll(cachedMap); - // } - // - // final txModel = TransactionData.fromMap(transactionsMap); - // - // await DB.instance.put( - // boxName: walletId, - // key: 'storedTxnDataHeight', - // value: latestTxnBlockHeight); - // await DB.instance.put( - // boxName: walletId, key: 'latest_tx_model', value: txModel); - // - // return txModel; } @override From 8d054215421a9c20ca1fcdd7979564b01a95a6e2 Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 10 Sep 2023 08:25:28 -0600 Subject: [PATCH 199/237] clean up cancel transaction in epiccash wallet --- .../coins/epiccash/epiccash_wallet.dart | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index ba5a7b3f7..08758b03f 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -421,34 +421,28 @@ class EpicCashWallet extends CoinServiceAPI late SecureStorageInterface _secureStore; + /// returns an empty String on success, error message on failure Future cancelPendingTransactionAndPost(String txSlateId) async { - String? result; try { - result = await cancelPendingTransaction(txSlateId); + final String wallet = (await _secureStore.read( + key: '${_walletId}_wallet', + ))!; + + final result = await m.protect(() async { + return await compute( + _cancelTransactionWrapper, + Tuple2( + wallet, + txSlateId, + ), + ); + }); Logging.instance.log("result?: $result", level: LogLevel.Info); + return result; } catch (e, s) { Logging.instance.log("$e, $s", level: LogLevel.Error); + return e.toString(); } - return result!; - } - -// - /// returns an empty String on success, error message on failure - Future cancelPendingTransaction(String txSlateId) async { - final String wallet = - (await _secureStore.read(key: '${_walletId}_wallet'))!; - - String? result; - await m.protect(() async { - result = await compute( - _cancelTransactionWrapper, - Tuple2( - wallet, - txSlateId, - ), - ); - }); - return result!; } @override From a5a8bb8ab5bdbff98e64e22cc123715f8411f592 Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 10 Sep 2023 10:44:33 -0600 Subject: [PATCH 200/237] apply scans error propagation fix --- .../coins/epiccash/epiccash_wallet.dart | 181 ++++++++++-------- 1 file changed, 100 insertions(+), 81 deletions(-) diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index 08758b03f..44865e195 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -437,7 +437,10 @@ class EpicCashWallet extends CoinServiceAPI ), ); }); - Logging.instance.log("result?: $result", level: LogLevel.Info); + Logging.instance.log( + "cancel $txSlateId result: $result", + level: LogLevel.Info, + ); return result; } catch (e, s) { Logging.instance.log("$e, $s", level: LogLevel.Error); @@ -661,25 +664,8 @@ class EpicCashWallet extends CoinServiceAPI await epicUpdateLastScannedBlock(await getRestoreHeight()); - if (!await startScans()) { - refreshMutex = false; - GlobalEventBus.instance.fire( - NodeConnectionStatusChangedEvent( - NodeConnectionStatus.disconnected, - walletId, - coin, - ), - ); - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.unableToSync, - walletId, - coin, - ), - ); - return; - } - await refresh(); + await _startScans(); + GlobalEventBus.instance.fire( WalletSyncStatusChangedEvent( WalletSyncStatus.synced, @@ -688,12 +674,23 @@ class EpicCashWallet extends CoinServiceAPI ), ); } catch (e, s) { + GlobalEventBus.instance.fire( + WalletSyncStatusChangedEvent( + WalletSyncStatus.unableToSync, + walletId, + coin, + ), + ); + + Logging.instance.log( + "Exception rethrown from fullRescan(): $e\n$s", + level: LogLevel.Error, + printFullLength: true, + ); + rethrow; + } finally { refreshMutex = false; - Logging.instance - .log("$e, $s", level: LogLevel.Error, printFullLength: true); } - refreshMutex = false; - return; } @override @@ -1159,58 +1156,97 @@ class EpicCashWallet extends CoinServiceAPI // TODO: refresh anything that needs to be refreshed/updated due to epicbox info changed } - Future startScans() async { + Future _startScans() async { try { + //First stop the current listener if (ListenerManager.pointer != null) { + Logging.instance + .log("LISTENER HANDLER IS NOT NULL ....", level: LogLevel.Info); + Logging.instance + .log("STOPPING ANY WALLET LISTENER ....", level: LogLevel.Info); epicboxListenerStop(ListenerManager.pointer!); } - final wallet = await _secureStore.read(key: '${_walletId}_wallet'); - var restoreHeight = epicGetRestoreHeight(); - var chainHeight = await this.chainHeight; - if (epicGetLastScannedBlock() == null) { - await epicUpdateLastScannedBlock(await getRestoreHeight()); - } - int lastScannedBlock = epicGetLastScannedBlock()!; - const MAX_PER_LOOP = 10000; - await getSyncPercent; - for (; lastScannedBlock < chainHeight;) { - chainHeight = await this.chainHeight; - lastScannedBlock = epicGetLastScannedBlock()!; - Logging.instance.log( - "chainHeight: $chainHeight, restoreHeight: $restoreHeight, lastScannedBlock: $lastScannedBlock", - level: LogLevel.Info); - int? nextScannedBlock; - await m.protect(() async { - ReceivePort receivePort = await getIsolate({ - "function": "scanOutPuts", - "wallet": wallet!, - "startHeight": lastScannedBlock, - "numberOfBlocks": MAX_PER_LOOP, - }, name: walletName); + // max number of blocks to scan per loop iteration + const scanChunkSize = 10000; - var message = await receivePort.first; - if (message is String) { - Logging.instance - .log("this is a string $message", level: LogLevel.Error); - stop(receivePort); - throw Exception("scanOutPuts isolate failed"); + // force firing of scan progress event + await getSyncPercent; + + // fetch current chain height and last scanned block (should be the + // restore height if full rescan or a wallet restore) + int chainHeight = await this.chainHeight; + int lastScannedBlock = + epicGetLastScannedBlock() ?? await getRestoreHeight(); + + // loop while scanning in chain in chunks (of blocks?) + while (lastScannedBlock < chainHeight) { + Logging.instance.log( + "chainHeight: $chainHeight, lastScannedBlock: $lastScannedBlock", + level: LogLevel.Info, + ); + + final int nextScannedBlock = await m.protect(() async { + ReceivePort? receivePort; + try { + receivePort = await getIsolate({ + "function": "scanOutPuts", + "wallet": wallet!, + "startHeight": lastScannedBlock, + "numberOfBlocks": scanChunkSize, + }, name: walletName); + + // get response + final message = await receivePort.first; + + // check for error message + if (message is String) { + throw Exception("scanOutPuts isolate failed: $message"); + } + + // attempt to grab next scanned block number + final nextScanned = int.tryParse(message['outputs'] as String); + if (nextScanned == null) { + throw Exception( + "scanOutPuts failed to parse next scanned block number from: $message", + ); + } + + return nextScanned; + } catch (_) { + rethrow; + } finally { + if (receivePort != null) { + // kill isolate + stop(receivePort); + } } - nextScannedBlock = int.parse(message['outputs'] as String); - stop(receivePort); - Logging.instance - .log('Closing scanOutPuts!\n $message', level: LogLevel.Info); }); - await epicUpdateLastScannedBlock(nextScannedBlock!); + + // update local cache + await epicUpdateLastScannedBlock(nextScannedBlock); + + // force firing of scan progress event await getSyncPercent; + + // update while loop condition variables + chainHeight = await this.chainHeight; + lastScannedBlock = nextScannedBlock; } - Logging.instance.log("successfully at the tip", level: LogLevel.Info); + + Logging.instance.log( + "_startScans successfully at the tip", + level: LogLevel.Info, + ); + //Once scanner completes restart listener await listenToEpicbox(); - return true; } catch (e, s) { - Logging.instance.log("$e, $s", level: LogLevel.Warning); - return false; + Logging.instance.log( + "_startScans failed: $e\n$s", + level: LogLevel.Error, + ); + rethrow; } } @@ -1490,24 +1526,7 @@ class EpicCashWallet extends CoinServiceAPI final int curAdd = await setCurrentIndex(); await _getReceivingAddressForIndex(curAdd); - if (!await startScans()) { - refreshMutex = false; - GlobalEventBus.instance.fire( - NodeConnectionStatusChangedEvent( - NodeConnectionStatus.disconnected, - walletId, - coin, - ), - ); - GlobalEventBus.instance.fire( - WalletSyncStatusChangedEvent( - WalletSyncStatus.unableToSync, - walletId, - coin, - ), - ); - return; - } + await _startScans(); unawaited(startSync()); From f3f63289ef79eaa102c5d62c3c50cf64ee3f3829 Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 10 Sep 2023 10:55:06 -0600 Subject: [PATCH 201/237] clean up epic wallet file --- .../coins/epiccash/epiccash_wallet.dart | 83 +------------------ 1 file changed, 1 insertion(+), 82 deletions(-) diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index 44865e195..2dacb1639 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -1700,26 +1700,13 @@ class EpicCashWallet extends CoinServiceAPI final List> txnsData = []; - // int latestTxnBlockHeight = - // DB.instance.get(boxName: walletId, key: "storedTxnDataHeight") - // as int? ?? - // 0; final slatesToCommits = await getSlatesToCommits(); for (var tx in jsonTransactions) { Logging.instance.log("tx: $tx", level: LogLevel.Info); // // TODO: does "confirmed" mean finalized? If so please remove this todo final isConfirmed = tx["confirmed"] as bool; - // // TODO: since we are now caching tx history in hive are we losing anything by skipping here? - // // TODO: we can skip this filtering if it causes issues as the cache is later merged with updated data anyways - // // this would just make processing and updating cache more efficient - // if (txHeight > 0 && - // txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS && - // isConfirmed) { - // continue; - // } - // Logging.instance.log("Transactions listed below"); - // Logging.instance.log(jsonTransactions); + int amt = 0; if (tx["tx_type"] == "TxReceived" || tx["tx_type"] == "TxReceivedCancelled") { @@ -1820,24 +1807,7 @@ class EpicCashWallet extends CoinServiceAPI } } - // - // midSortedTx["inputSize"] = tx["num_inputs"]; - // midSortedTx["outputSize"] = tx["num_outputs"]; - // midSortedTx["aliens"] = []; - // midSortedTx["inputs"] = []; - // midSortedTx["outputs"] = []; - - // key id not used afaik? - // midSortedTx["key_id"] = tx["parent_key_id"]; - - // if (txHeight >= latestTxnBlockHeight) { - // latestTxnBlockHeight = txHeight; - // } - txnsData.add(Tuple2(txn, transactionAddress)); - // cachedMap?.remove(tx["id"].toString()); - // cachedMap?.remove(commitId); - // Logging.instance.log("cmap: $cachedMap", level: LogLevel.Info); } await db.addNewTransactionData(txnsData, walletId); @@ -1852,57 +1822,6 @@ class EpicCashWallet extends CoinServiceAPI ), ); } - - // midSortedArray - // .sort((a, b) => (b["timestamp"] as int) - (a["timestamp"] as int)); - // - // final Map result = {"dateTimeChunks": []}; - // final dateArray = []; - // - // for (int i = 0; i < midSortedArray.length; i++) { - // final txObject = midSortedArray[i]; - // final date = extractDateFromTimestamp(txObject["timestamp"] as int); - // - // final txTimeArray = [txObject["timestamp"], date]; - // - // if (dateArray.contains(txTimeArray[1])) { - // result["dateTimeChunks"].forEach((dynamic chunk) { - // if (extractDateFromTimestamp(chunk["timestamp"] as int) == - // txTimeArray[1]) { - // if (chunk["transactions"] == null) { - // chunk["transactions"] = >[]; - // } - // chunk["transactions"].add(txObject); - // } - // }); - // } else { - // dateArray.add(txTimeArray[1]); - // - // final chunk = { - // "timestamp": txTimeArray[0], - // "transactions": [txObject], - // };sendAll - // - // // result["dateTimeChunks"]. - // result["dateTimeChunks"].add(chunk); - // } - // } - // final transactionsMap = - // TransactionData.fromJson(result).getAllTransactions(); - // if (cachedMap != null) { - // transactionsMap.addAll(cachedMap); - // } - // - // final txModel = TransactionData.fromMap(transactionsMap); - // - // await DB.instance.put( - // boxName: walletId, - // key: 'storedTxnDataHeight', - // value: latestTxnBlockHeight); - // await DB.instance.put( - // boxName: walletId, key: 'latest_tx_model', value: txModel); - // - // return txModel; } @override From 8b4f25e0f3a424b3f65602934b8bc286b25d34b8 Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 10 Sep 2023 14:57:07 -0600 Subject: [PATCH 202/237] hide epic rescan for now --- .../wallet_network_settings_view.dart | 181 ++++++++++-------- 1 file changed, 101 insertions(+), 80 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index b447a53ee..8f9fc9eec 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -340,92 +340,98 @@ class _WalletNetworkSettingsViewState style: STextStyles.navBarTitle(context), ), actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key( - "walletNetworkSettingsAddNewNodeViewButton"), - size: 36, - shadows: const [], - color: Theme.of(context) - .extension()! - .background, - icon: SvgPicture.asset( - Assets.svg.verticalEllipsis, + if (ref + .read(walletsChangeNotifierProvider) + .getManager(widget.walletId) + .coin != + Coin.epicCash) + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key( + "walletNetworkSettingsAddNewNodeViewButton"), + size: 36, + shadows: const [], color: Theme.of(context) .extension()! - .accentColorDark, - width: 20, - height: 20, - ), - onPressed: () { - showDialog( - barrierColor: Colors.transparent, - barrierDismissible: true, - context: context, - builder: (_) { - return Stack( - children: [ - Positioned( - top: 9, - right: 10, - child: Container( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius), - // boxShadow: [CFColors.standardBoxShadow], - boxShadow: const [], - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - GestureDetector( - onTap: () { - Navigator.of(context).pop(); - showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return ConfirmFullRescanDialog( - onConfirm: _attemptRescan, - ); - }, - ); - }, - child: RoundedWhiteContainer( - child: Material( - color: Colors.transparent, - child: Text( - "Rescan blockchain", - style: - STextStyles.baseXS(context), + .background, + icon: SvgPicture.asset( + Assets.svg.verticalEllipsis, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + showDialog( + barrierColor: Colors.transparent, + barrierDismissible: true, + context: context, + builder: (_) { + return Stack( + children: [ + Positioned( + top: 9, + right: 10, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context) + .extension()! + .popupBG, + borderRadius: BorderRadius.circular( + Constants + .size.circularBorderRadius), + // boxShadow: [CFColors.standardBoxShadow], + boxShadow: const [], + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: () { + Navigator.of(context).pop(); + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return ConfirmFullRescanDialog( + onConfirm: _attemptRescan, + ); + }, + ); + }, + child: RoundedWhiteContainer( + child: Material( + color: Colors.transparent, + child: Text( + "Rescan blockchain", + style: STextStyles.baseXS( + context), + ), ), ), ), - ), - ], + ], + ), ), ), - ), - ], - ); - }, - ); - }, + ], + ); + }, + ); + }, + ), ), ), - ), ], ), body: Padding( @@ -786,11 +792,21 @@ class _WalletNetworkSettingsViewState .select((value) => value.getManager(widget.walletId).coin)), popBackToRoute: WalletNetworkSettingsView.routeName, ), - if (isDesktop) + if (isDesktop && + ref + .read(walletsChangeNotifierProvider) + .getManager(widget.walletId) + .coin != + Coin.epicCash) const SizedBox( height: 32, ), - if (isDesktop) + if (isDesktop && + ref + .read(walletsChangeNotifierProvider) + .getManager(widget.walletId) + .coin != + Coin.epicCash) Padding( padding: const EdgeInsets.only( bottom: 12, @@ -806,7 +822,12 @@ class _WalletNetworkSettingsViewState ], ), ), - if (isDesktop) + if (isDesktop && + ref + .read(walletsChangeNotifierProvider) + .getManager(widget.walletId) + .coin != + Coin.epicCash) RoundedWhiteContainer( borderColor: isDesktop ? Theme.of(context).extension()!.background From 6f06bb834f5d63295f3056618b055636e96a4ff0 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 11 Sep 2023 12:48:32 -0600 Subject: [PATCH 203/237] only show epic cancel button if no confirmations --- .../transaction_views/transaction_details_view.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart index 88d0d8b1a..54b528245 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart @@ -1577,11 +1577,7 @@ class _TransactionDetailsViewState ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, floatingActionButton: (coin == Coin.epicCash && - _transaction.isConfirmed( - currentHeight, - coin.requiredConfirmations, - ) == - false && + _transaction.getConfirmations(currentHeight) < 1 && _transaction.isCancelled == false) ? ConditionalParent( condition: isDesktop, From 5053e7d97a6a767600d354adc2efcdd01190c17f Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Mon, 11 Sep 2023 14:20:40 -0600 Subject: [PATCH 204/237] WIP: tor http connection --- .../global_settings_view/about_view.dart | 17 +++++++++---- .../majestic_bank/majestic_bank_api.dart | 15 +++++++----- .../exchange/simpleswap/simpleswap_api.dart | 21 +++++++++------- lib/services/price.dart | 22 ++++++++++++----- lib/utilities/test_epic_box_connection.dart | 24 ++++++++++++------- 5 files changed, 65 insertions(+), 34 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/about_view.dart b/lib/pages/settings_views/global_settings_view/about_view.dart index 5daa1e81a..0d3e8d811 100644 --- a/lib/pages/settings_views/global_settings_view/about_view.dart +++ b/lib/pages/settings_views/global_settings_view/about_view.dart @@ -15,11 +15,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_libepiccash/git_versions.dart' as EPIC_VERSIONS; import 'package:flutter_libmonero/git_versions.dart' as MONERO_VERSIONS; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:http/http.dart'; import 'package:lelantus/git_versions.dart' as FIRO_VERSIONS; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; @@ -39,14 +41,17 @@ Future doesCommitExist( String commit, ) async { Logging.instance.log("doesCommitExist", level: LogLevel.Info); - final Client client = Client(); + // final Client client = Client(); + HTTP client = HTTP(); try { final uri = Uri.parse( "$kGithubAPI$kGithubHead/$organization/$project/commits/$commit"); final commitQuery = await client.get( - uri, + url: uri, headers: {'Content-Type': 'application/json'}, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final response = jsonDecode(commitQuery.body.toString()); @@ -76,14 +81,16 @@ Future isHeadCommit( String commit, ) async { Logging.instance.log("doesCommitExist", level: LogLevel.Info); - final Client client = Client(); + HTTP client = HTTP(); try { final uri = Uri.parse( "$kGithubAPI$kGithubHead/$organization/$project/commits/$branch"); final commitQuery = await client.get( - uri, + url: uri, headers: {'Content-Type': 'application/json'}, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final response = jsonDecode(commitQuery.body.toString()); diff --git a/lib/services/exchange/majestic_bank/majestic_bank_api.dart b/lib/services/exchange/majestic_bank/majestic_bank_api.dart index 613899f9c..d32209ae5 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_api.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_api.dart @@ -11,7 +11,6 @@ import 'dart:convert'; import 'package:decimal/decimal.dart'; -import 'package:http/http.dart' as http; import 'package:stackwallet/exceptions/exchange/exchange_exception.dart'; import 'package:stackwallet/exceptions/exchange/majestic_bank/mb_exception.dart'; import 'package:stackwallet/exceptions/exchange/pair_unavailable_exception.dart'; @@ -20,8 +19,11 @@ import 'package:stackwallet/models/exchange/majestic_bank/mb_order.dart'; import 'package:stackwallet/models/exchange/majestic_bank/mb_order_calculation.dart'; import 'package:stackwallet/models/exchange/majestic_bank/mb_order_status.dart'; import 'package:stackwallet/models/exchange/majestic_bank/mb_rate.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/exchange/exchange_response.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; class MajesticBankAPI { static const String scheme = "https"; @@ -35,22 +37,23 @@ class MajesticBankAPI { static MajesticBankAPI get instance => _instance; - /// set this to override using standard http client. Useful for testing - http.Client? client; + HTTP client = HTTP(); Uri _buildUri({required String endpoint, Map? params}) { return Uri.https(authority, "/api/$version/$endpoint", params); } Future _makeGetRequest(Uri uri) async { - final client = this.client ?? http.Client(); + // final client = this.client ?? http.Client(); int code = -1; try { final response = await client.get( - uri, + url: uri, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - code = response.statusCode; + code = response.code; final parsed = jsonDecode(response.body); diff --git a/lib/services/exchange/simpleswap/simpleswap_api.dart b/lib/services/exchange/simpleswap/simpleswap_api.dart index adca1f567..d52f8aa21 100644 --- a/lib/services/exchange/simpleswap/simpleswap_api.dart +++ b/lib/services/exchange/simpleswap/simpleswap_api.dart @@ -12,7 +12,6 @@ import 'dart:convert'; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; -import 'package:http/http.dart' as http; import 'package:stackwallet/exceptions/exchange/exchange_exception.dart'; import 'package:stackwallet/external_api_keys.dart'; import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.dart'; @@ -20,9 +19,12 @@ import 'package:stackwallet/models/exchange/response_objects/range.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart'; import 'package:stackwallet/models/exchange/simpleswap/sp_currency.dart'; import 'package:stackwallet/models/isar/exchange_cache/pair.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/exchange/exchange_response.dart'; import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:tuple/tuple.dart'; import 'package:uuid/uuid.dart'; @@ -34,22 +36,22 @@ class SimpleSwapAPI { static final SimpleSwapAPI _instance = SimpleSwapAPI._(); static SimpleSwapAPI get instance => _instance; - /// set this to override using standard http client. Useful for testing - http.Client? client; + HTTP client = HTTP(); Uri _buildUri(String path, Map? params) { return Uri.https(authority, path, params); } Future _makeGetRequest(Uri uri) async { - final client = this.client ?? http.Client(); int code = -1; try { final response = await client.get( - uri, + url: uri, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - code = response.statusCode; + code = response.code; final parsed = jsonDecode(response.body); @@ -67,15 +69,16 @@ class SimpleSwapAPI { Uri uri, Map body, ) async { - final client = this.client ?? http.Client(); try { final response = await client.post( - uri, + url: uri, headers: {'Content-Type': 'application/json'}, body: jsonEncode(body), + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); - if (response.statusCode == 200) { + if (response.code == 200) { final parsed = jsonDecode(response.body); return parsed; } diff --git a/lib/services/price.dart b/lib/services/price.dart index c6f28673f..91e9b1db8 100644 --- a/lib/services/price.dart +++ b/lib/services/price.dart @@ -13,8 +13,9 @@ import 'dart:convert'; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; -import 'package:http/http.dart'; import 'package:stackwallet/db/hive/db.dart'; +import 'package:stackwallet/networking/http.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; @@ -32,7 +33,8 @@ class PriceAPI { static const Duration refreshIntervalDuration = Duration(seconds: refreshInterval); - final Client client; + // final Client client; + HTTP client = HTTP(); PriceAPI(this.client); @@ -104,8 +106,10 @@ class PriceAPI { "&order=market_cap_desc&per_page=50&page=1&sparkline=false"); final coinGeckoResponse = await client.get( - uri, + url: uri, headers: {'Content-Type': 'application/json'}, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final coinGeckoData = jsonDecode(coinGeckoResponse.body) as List; @@ -136,6 +140,8 @@ class PriceAPI { static Future?> availableBaseCurrencies() async { final externalCalls = Prefs.instance.externalCalls; + HTTP client = HTTP(); + if ((!Logger.isTestEnv && !externalCalls) || !(await Prefs.instance.isExternalCallsSet())) { Logging.instance.log("User does not want to use external calls", @@ -146,9 +152,11 @@ class PriceAPI { "https://api.coingecko.com/api/v3/simple/supported_vs_currencies"; try { final uri = Uri.parse(uriString); - final response = await Client().get( - uri, + final response = await client.get( + url: uri, headers: {'Content-Type': 'application/json'}, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final json = jsonDecode(response.body) as List; @@ -186,8 +194,10 @@ class PriceAPI { "=$contractAddressesString&include_24hr_change=true"); final coinGeckoResponse = await client.get( - uri, + url: uri, headers: {'Content-Type': 'application/json'}, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final coinGeckoData = jsonDecode(coinGeckoResponse.body) as Map; diff --git a/lib/utilities/test_epic_box_connection.dart b/lib/utilities/test_epic_box_connection.dart index c65f85ac7..87e3948e8 100644 --- a/lib/utilities/test_epic_box_connection.dart +++ b/lib/utilities/test_epic_box_connection.dart @@ -10,22 +10,30 @@ import 'dart:convert'; -import 'package:http/http.dart' as http; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; Future _testEpicBoxNodeConnection(Uri uri) async { + HTTP client = HTTP(); try { - final client = http.Client(); - final response = await client.get( - uri, - headers: {'Content-Type': 'application/json'}, - ).timeout(const Duration(milliseconds: 2000), - onTimeout: () async => http.Response('Error', 408)); + // final client = http.Client(); + final response = await client + .get( + url: uri, + headers: {'Content-Type': 'application/json'}, + proxyInfo: Prefs.instance.useTor + ? TorService.sharedInstance.proxyInfo + : null, + ) + .timeout(const Duration(milliseconds: 2000), + onTimeout: () async => Response(utf8.encode('Error'), 408)); final json = jsonDecode(response.body); - if (response.statusCode == 200 && json["node_version"] != null) { + if (response.code == 200 && json["node_version"] != null) { return true; } else { return false; From 5b863dcb9df8ee69e0da3ec0037aacc5a8ea8006 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Mon, 11 Sep 2023 14:29:10 -0600 Subject: [PATCH 205/237] tor http connection --- lib/utilities/test_epic_box_connection.dart | 1 - .../test_stellar_node_connection.dart | 28 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/utilities/test_epic_box_connection.dart b/lib/utilities/test_epic_box_connection.dart index 87e3948e8..ed2fd4828 100644 --- a/lib/utilities/test_epic_box_connection.dart +++ b/lib/utilities/test_epic_box_connection.dart @@ -19,7 +19,6 @@ import 'package:stackwallet/utilities/prefs.dart'; Future _testEpicBoxNodeConnection(Uri uri) async { HTTP client = HTTP(); try { - // final client = http.Client(); final response = await client .get( url: uri, diff --git a/lib/utilities/test_stellar_node_connection.dart b/lib/utilities/test_stellar_node_connection.dart index 683d946c9..32f756025 100644 --- a/lib/utilities/test_stellar_node_connection.dart +++ b/lib/utilities/test_stellar_node_connection.dart @@ -1,19 +1,25 @@ import 'dart:convert'; -import 'package:http/http.dart' as http; +import 'package:stackwallet/networking/http.dart' as http; +import 'package:stackwallet/services/tor_service.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; Future testStellarNodeConnection(String host, int port) async { - - final client = http.Client(); + http.HTTP client = http.HTTP(); Uri uri = Uri.parse("$host:$port"); - final response = await client.get( - uri, - headers: {'Content-Type': 'application/json'}, - ).timeout(const Duration(milliseconds: 2000), - onTimeout: () async => http.Response('Error', 408)); - if (response.statusCode == 200) { + final response = await client + .get( + url: uri, + headers: {'Content-Type': 'application/json'}, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + ) + .timeout(const Duration(milliseconds: 2000), + onTimeout: () async => http.Response(utf8.encode('Error'), 408)); + + if (response.code == 200) { //Get chain height for sdk StellarSDK stellarSdk = StellarSDK(host); final height = await stellarSdk.ledgers @@ -24,11 +30,11 @@ Future testStellarNodeConnection(String host, int port) async { .onError((error, stackTrace) => throw ("Error getting chain height")); if (height > 0) { - return true; + return true; } else { return false; } } else { return false; } -} \ No newline at end of file +} From bcb92ae63831c281dee70124484b35db7e831b80 Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Mon, 11 Sep 2023 14:38:40 -0600 Subject: [PATCH 206/237] price api use tor HTTP --- lib/services/price_service.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/services/price_service.dart b/lib/services/price_service.dart index 46c0ff85a..8a0b2741a 100644 --- a/lib/services/price_service.dart +++ b/lib/services/price_service.dart @@ -13,6 +13,7 @@ import 'dart:async'; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/price.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:tuple/tuple.dart'; @@ -29,7 +30,7 @@ class PriceService extends ChangeNotifier { final Map> _cachedTokenPrices = {}; - final _priceAPI = PriceAPI(Client()); + final _priceAPI = PriceAPI(HTTP()); Tuple2 getPrice(Coin coin) => _cachedPrices[coin]!; From dcfb6e9dacb46018eedf6a743e03074961f97cc7 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 11 Sep 2023 16:31:48 -0500 Subject: [PATCH 207/237] WIP exchange tor support --- .../exchange_currency_selection_view.dart | 14 ++++++++++++-- .../exchange/change_now/change_now_exchange.dart | 11 +++++++++++ lib/services/exchange/exchange.dart | 3 +++ .../exchange/exchange_data_loading_service.dart | 12 ++++++++++++ .../majestic_bank/majestic_bank_exchange.dart | 4 ++++ .../exchange/trocador/trocador_exchange.dart | 4 ++++ 6 files changed, 46 insertions(+), 2 deletions(-) diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 87fc590e9..9d92ba1e9 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -125,7 +125,7 @@ class _ExchangeCurrencySelectionViewState await showDialog( context: context, builder: (context) => StackDialog( - title: "ChangeNOW Error", + title: "Exchange Error", message: "Failed to load currency data: ${cn.exception}", leftButton: SecondaryButton( label: "Ok", @@ -151,6 +151,10 @@ class _ExchangeCurrencySelectionViewState } Future> _getCurrencies() async { + // This is where exchanges are added to the list of available currencies. + // + // TODO: make an exchange's addition to the list of available currencies + // be dynamic and dependant upon the exchange's supportsTor implementation. final currencies = await ExchangeDataLoadingService.instance.isar.currencies .where() .filter() @@ -161,10 +165,16 @@ class _ExchangeCurrencySelectionViewState .rateTypeEqualTo(SupportedRateType.both) .or() .rateTypeEqualTo(SupportedRateType.fixed) + .and() + .not() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) : q .rateTypeEqualTo(SupportedRateType.both) .or() - .rateTypeEqualTo(SupportedRateType.estimated)) + .rateTypeEqualTo(SupportedRateType.estimated) + .and() + .not() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName)) .sortByIsStackCoin() .thenByName() .findAll(); diff --git a/lib/services/exchange/change_now/change_now_exchange.dart b/lib/services/exchange/change_now/change_now_exchange.dart index 953d17077..63c99cc40 100644 --- a/lib/services/exchange/change_now/change_now_exchange.dart +++ b/lib/services/exchange/change_now/change_now_exchange.dart @@ -274,4 +274,15 @@ class ChangeNowExchange extends Exchange { // TODO: implement getTrades throw UnimplementedError(); } + + // ChangeNow does not support Tor. + // + // This code isn't required because the Exchange abstract class has a + // default implementation that returns false. This serves as an example and + // reminder in case ChangeNow files are copied to create a new exchange (or + // if ChangeNow ever supports Tor). + /* + @override + bool get supportsTor => true; + */ } diff --git a/lib/services/exchange/exchange.dart b/lib/services/exchange/exchange.dart index 5b750ec6c..0a750b86e 100644 --- a/lib/services/exchange/exchange.dart +++ b/lib/services/exchange/exchange.dart @@ -90,4 +90,7 @@ abstract class Exchange { Estimate? estimate, required bool reversed, }); + + // Flag to indicate that the exchange supports Tor. + bool get supportsTor => false; } diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index ee0ed50a0..eb0896639 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -144,6 +144,7 @@ class ExchangeDataLoadingService { ); final start = DateTime.now(); try { + /* await Future.wait([ _loadChangeNowCurrencies(), // _loadChangeNowFixedRatePairs(), @@ -157,6 +158,17 @@ class ExchangeDataLoadingService { // quicker to load available currencies on the fly for a specific base currency // await _loadChangeNowFixedRatePairs(); // await _loadChangeNowEstimatedRatePairs(); + */ + // Use the supportsTor flag to filter out unsupported exchanges. + if (ChangeNowExchange.instance.supportsTor) { + await _loadChangeNowCurrencies(); + } + if (MajesticBankExchange.instance.supportsTor) { + await loadMajesticBankCurrencies(); + } + if (TrocadorExchange.instance.supportsTor) { + await loadTrocadorCurrencies(); + } Logging.instance.log( "ExchangeDataLoadingService.loadAll finished in ${DateTime.now().difference(start).inSeconds} seconds", diff --git a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart index 60e97d723..3ba914fb9 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart @@ -324,4 +324,8 @@ class MajesticBankExchange extends Exchange { return ExchangeResponse(exception: response.exception); } } + + // Majestic Bank supports tor. + @override + bool get supportsTor => true; } diff --git a/lib/services/exchange/trocador/trocador_exchange.dart b/lib/services/exchange/trocador/trocador_exchange.dart index e4f14ff17..d5a819b46 100644 --- a/lib/services/exchange/trocador/trocador_exchange.dart +++ b/lib/services/exchange/trocador/trocador_exchange.dart @@ -401,4 +401,8 @@ class TrocadorExchange extends Exchange { return ExchangeResponse(exception: response.exception); } } + + // Trocador supports Tor. + @override + bool get supportsTor => true; } From 2b3b7db206fec37407b5ea3c92be495593a998a4 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 11 Sep 2023 16:27:44 -0600 Subject: [PATCH 208/237] screen height in debug mode (desktop) --- lib/main.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 94c70c8b1..b948a9510 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,7 +16,6 @@ import 'package:cw_core/node.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_libmonero/monero/monero.dart'; @@ -97,7 +96,7 @@ void main() async { setWindowMaxSize(Size.infinite); final screenHeight = screen?.frame.height; - if (screenHeight != null && !kDebugMode) { + if (screenHeight != null) { // starting to height be 3/4 screen height or 900, whichever is smaller final height = min(screenHeight * 0.75, 900); setWindowFrame( From 0e64696c2013c6245dbc27d58d20babbc2f3e70f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 11 Sep 2023 17:03:56 -0600 Subject: [PATCH 209/237] possible "fix" for android 13 not being able to load swb files --- pubspec.lock | 23 ++++++++++++----------- pubspec.yaml | 10 ++++++++-- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index c01aca249..f24f7916a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -557,11 +557,12 @@ packages: file_picker: dependency: "direct main" description: - name: file_picker - sha256: b1729fc96627dd44012d0a901558177418818d6bd428df59dcfeb594e5f66432 - url: "https://pub.dev" - source: hosted - version: "5.3.2" + path: "." + ref: f0930d9fa79d347b2a0e25a7de4f5a4a88a9a907 + resolved-ref: f0930d9fa79d347b2a0e25a7de4f5a4a88a9a907 + url: "https://github.com/muttsu-623/flutter_file_picker.git" + source: git + version: "5.3.3" fixnum: dependency: transitive description: @@ -1209,18 +1210,18 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81" + sha256: ad65ba9af42a3d067203641de3fd9f547ded1410bad3b84400c2b4899faede70 url: "https://pub.dev" source: hosted - version: "10.4.3" + version: "11.0.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "2ffaf52a21f64ac9b35fe7369bb9533edbd4f698e5604db8645b1064ff4cf221" + sha256: "6901d50f4d4b9a27e1749dbd4adbf06aa00d90a21a2db563405d5ce27ee120ac" url: "https://pub.dev" source: hosted - version: "10.3.3" + version: "11.0.0" permission_handler_apple: dependency: transitive description: @@ -1233,10 +1234,10 @@ packages: dependency: transitive description: name: permission_handler_platform_interface - sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" + sha256: f2343e9fa9c22ae4fd92d4732755bfe452214e7189afcc097380950cf567b4b2 url: "https://pub.dev" source: hosted - version: "3.11.3" + version: "3.11.5" permission_handler_windows: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index fece8ca4b..e692f0cfc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,7 +60,7 @@ dependencies: # Utility plugins http: ^0.13.0 local_auth: ^1.1.10 - permission_handler: ^10.0.0 + permission_handler: ^11.0.0 flutter_local_notifications: ^9.4.0 rxdart: ^0.27.3 zxcvbn: ^1.0.0 @@ -123,7 +123,7 @@ dependencies: pointycastle: ^3.6.0 package_info_plus: ^4.0.2 lottie: ^2.3.2 - file_picker: ^5.3.1 + file_picker: ^5.5.0 connectivity_plus: ^4.0.1 isar: 3.0.5 isar_flutter_libs: 3.0.5 # contains the binaries @@ -200,6 +200,12 @@ dependency_overrides: url: https://github.com/cypherstack/stack-bip39.git ref: 0cd6d54e2860bea68fc50c801cb9db2a760192fb + + file_picker: + git: + url: https://github.com/muttsu-623/flutter_file_picker.git + ref: f0930d9fa79d347b2a0e25a7de4f5a4a88a9a907 + crypto: 3.0.2 analyzer: ^5.2.0 pinenacl: ^0.3.3 From 45e6354fb647e90cefbb73342cc09e7e2b7d8356 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 11 Sep 2023 18:07:59 -0500 Subject: [PATCH 210/237] replace get supportsTor with an exchangesWithTorSupport List more convenient to use elsewhere --- .../exchange_currency_selection_view.dart | 22 +++++++++++++------ lib/pages/exchange_view/exchange_form.dart | 19 +++++++++++++--- lib/services/exchange/exchange.dart | 22 +++++++++++++++++-- .../exchange_data_loading_service.dart | 21 +++++++++++------- 4 files changed, 64 insertions(+), 20 deletions(-) diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 9d92ba1e9..1be2885b7 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -24,6 +24,7 @@ import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; @@ -39,6 +40,8 @@ import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import '../../../services/exchange/exchange.dart'; + class ExchangeCurrencySelectionView extends StatefulWidget { const ExchangeCurrencySelectionView({ Key? key, @@ -165,20 +168,25 @@ class _ExchangeCurrencySelectionViewState .rateTypeEqualTo(SupportedRateType.both) .or() .rateTypeEqualTo(SupportedRateType.fixed) - .and() - .not() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) : q .rateTypeEqualTo(SupportedRateType.both) .or() - .rateTypeEqualTo(SupportedRateType.estimated) - .and() - .not() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName)) + .rateTypeEqualTo(SupportedRateType.estimated)) .sortByIsStackCoin() .thenByName() .findAll(); + // If using Tor, filter exchanges which do not support Tor. + if (Prefs.instance.useTor) { + if (Exchange.exchangesWithTorSupport.isNotEmpty) { + currencies + .removeWhere((element) => !Exchange.exchangesWithTorSupport.any( + (e) => e.name == element.exchangeName, + )); + // Could have also filtered using the List Exchange.exchangeNamesWithTorSupport. But I didn't. This is fancier. + } + } + return _getDistinctCurrenciesFrom(currencies); } diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index a15e13843..a81f758a6 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -31,15 +31,19 @@ import 'package:stackwallet/pages/exchange_view/sub_widgets/rate_type_toggle.dar import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; +import 'package:stackwallet/services/exchange/exchange.dart'; import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart'; +import 'package:stackwallet/services/exchange/exchange_response.dart'; import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart'; import 'package:stackwallet/services/exchange/trocador/trocador_exchange.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/amount/amount_unit.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; @@ -55,8 +59,6 @@ import 'package:stackwallet/widgets/textfields/exchange_textfield.dart'; import 'package:tuple/tuple.dart'; import 'package:uuid/uuid.dart'; -import '../../services/exchange/exchange_response.dart'; - class ExchangeForm extends ConsumerStatefulWidget { const ExchangeForm({ Key? key, @@ -78,7 +80,7 @@ class _ExchangeFormState extends ConsumerState { late final Coin? coin; late final bool walletInitiated; - final exchanges = [ + var exchanges = [ MajesticBankExchange.instance, ChangeNowExchange.instance, TrocadorExchange.instance, @@ -773,6 +775,14 @@ class _ExchangeFormState extends ConsumerState { }); } + // Instantiate the Tor service. + torService = TorService.sharedInstance; + + // Filter exchanges based on Tor support. + if (Prefs.instance.useTor) { + exchanges = Exchange.exchangesWithTorSupport; + } + super.initState(); } @@ -1007,4 +1017,7 @@ class _ExchangeFormState extends ConsumerState { ], ); } + + // TorService instance. + late TorService torService; } diff --git a/lib/services/exchange/exchange.dart b/lib/services/exchange/exchange.dart index 0a750b86e..9530639ee 100644 --- a/lib/services/exchange/exchange.dart +++ b/lib/services/exchange/exchange.dart @@ -91,6 +91,24 @@ abstract class Exchange { required bool reversed, }); - // Flag to indicate that the exchange supports Tor. - bool get supportsTor => false; + /// List of exchanges which support Tor. + /// + /// Add to this list when adding a new exchange which supports Tor. + static List get exchangesWithTorSupport => [ + MajesticBankExchange.instance, + TrocadorExchange.instance, + ]; + + /// List of exchange names which support Tor. + /// + /// Convenience method for when you just want to check for a String + /// .exchangeName instead of Exchange instances. Shouldn't need to be updated + /// as long as the above List is updated. + static List get exchangeNamesWithTorSupport => + exchangesWithTorSupport.map((exchange) => exchange.name).toList(); + // Instead of using this, you can do like: + // currencies + // .removeWhere((element) => !Exchange.exchangesWithTorSupport.any( + // (e) => e.name == element.exchangeName, + // )); } diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index eb0896639..eecb80462 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -20,6 +20,7 @@ import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchan import 'package:stackwallet/services/exchange/trocador/trocador_exchange.dart'; import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; import 'package:tuple/tuple.dart'; @@ -145,6 +146,7 @@ class ExchangeDataLoadingService { final start = DateTime.now(); try { /* + // Old exchange data loading code. await Future.wait([ _loadChangeNowCurrencies(), // _loadChangeNowFixedRatePairs(), @@ -159,16 +161,19 @@ class ExchangeDataLoadingService { // await _loadChangeNowFixedRatePairs(); // await _loadChangeNowEstimatedRatePairs(); */ - // Use the supportsTor flag to filter out unsupported exchanges. - if (ChangeNowExchange.instance.supportsTor) { + + // If using Tor, don't load data for exchanges which don't support Tor. + // + // Add to this list when adding an exchange which doesn't supports Tor. + if (!Prefs.instance.useTor) { await _loadChangeNowCurrencies(); } - if (MajesticBankExchange.instance.supportsTor) { - await loadMajesticBankCurrencies(); - } - if (TrocadorExchange.instance.supportsTor) { - await loadTrocadorCurrencies(); - } + + // Exchanges which support Tor just get treated normally. + await Future.wait([ + loadMajesticBankCurrencies(), + loadTrocadorCurrencies(), + ]); Logging.instance.log( "ExchangeDataLoadingService.loadAll finished in ${DateTime.now().difference(start).inSeconds} seconds", From 474ec39a5fca4f7074070b420d9ff2ddef34f2dd Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 11 Sep 2023 18:08:27 -0500 Subject: [PATCH 211/237] filter non tor exchanges from the exchange provider options list --- .../sub_widgets/exchange_provider_options.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart index 13330e2f9..6f0108f66 100644 --- a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart +++ b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart @@ -14,9 +14,11 @@ import 'package:stackwallet/models/exchange/aggregate_currency.dart'; import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_provider_option.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; +import 'package:stackwallet/services/exchange/exchange.dart'; import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart'; import 'package:stackwallet/services/exchange/trocador/trocador_exchange.dart'; import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; @@ -44,6 +46,13 @@ class _ExchangeProviderOptionsState required AggregateCurrency? sendCurrency, required AggregateCurrency? receiveCurrency, }) { + // If using Tor, only allow exchanges that support it. + if (Prefs.instance.useTor) { + if (!Exchange.exchangeNamesWithTorSupport.contains(exchangeName)) { + return false; + } + } + final send = sendCurrency?.forExchange(exchangeName); if (send == null) return false; From dae4a38287eb410af962249e4c1f942355e38258 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 11 Sep 2023 17:12:35 -0600 Subject: [PATCH 212/237] add placeholder icon to ethereum tokens select --- .../sub_widgets/add_token_list_element.dart | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart index be5aaa37d..e6d9149a7 100644 --- a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart +++ b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart @@ -8,7 +8,10 @@ * */ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/models/isar/exchange_cache/currency.dart'; @@ -16,6 +19,7 @@ import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/themes/theme_providers.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; @@ -30,16 +34,17 @@ class AddTokenListElementData { bool selected = false; } -class AddTokenListElement extends StatefulWidget { +class AddTokenListElement extends ConsumerStatefulWidget { const AddTokenListElement({Key? key, required this.data}) : super(key: key); final AddTokenListElementData data; @override - State createState() => _AddTokenListElementState(); + ConsumerState createState() => + _AddTokenListElementState(); } -class _AddTokenListElementState extends State { +class _AddTokenListElementState extends ConsumerState { final bool isDesktop = Util.isDesktop; @override @@ -74,6 +79,17 @@ class _AddTokenListElementState extends State { currency.image, width: iconSize, height: iconSize, + placeholderBuilder: (_) => SvgPicture.file( + File( + ref.watch( + themeAssetsProvider.select( + (value) => value.stackIcon, + ), + ), + ), + width: iconSize, + height: iconSize, + ), ) : SvgPicture.asset( widget.data.token.symbol == "BNB" From d342dd5cb9011e1c412e1aca62282a193fc0d119 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 11 Sep 2023 18:12:56 -0500 Subject: [PATCH 213/237] fix currency filter --- .../exchange_currency_selection_view.dart | 14 ++++---------- lib/services/exchange/exchange.dart | 8 ++++---- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 1be2885b7..ada195455 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -154,10 +154,6 @@ class _ExchangeCurrencySelectionViewState } Future> _getCurrencies() async { - // This is where exchanges are added to the list of available currencies. - // - // TODO: make an exchange's addition to the list of available currencies - // be dynamic and dependant upon the exchange's supportsTor implementation. final currencies = await ExchangeDataLoadingService.instance.isar.currencies .where() .filter() @@ -178,12 +174,10 @@ class _ExchangeCurrencySelectionViewState // If using Tor, filter exchanges which do not support Tor. if (Prefs.instance.useTor) { - if (Exchange.exchangesWithTorSupport.isNotEmpty) { - currencies - .removeWhere((element) => !Exchange.exchangesWithTorSupport.any( - (e) => e.name == element.exchangeName, - )); - // Could have also filtered using the List Exchange.exchangeNamesWithTorSupport. But I didn't. This is fancier. + if (Exchange.exchangeNamesWithTorSupport.isNotEmpty) { + currencies.removeWhere((element) => !Exchange + .exchangeNamesWithTorSupport + .contains(element.exchangeName)); } } diff --git a/lib/services/exchange/exchange.dart b/lib/services/exchange/exchange.dart index 9530639ee..a8553854c 100644 --- a/lib/services/exchange/exchange.dart +++ b/lib/services/exchange/exchange.dart @@ -107,8 +107,8 @@ abstract class Exchange { static List get exchangeNamesWithTorSupport => exchangesWithTorSupport.map((exchange) => exchange.name).toList(); // Instead of using this, you can do like: - // currencies - // .removeWhere((element) => !Exchange.exchangesWithTorSupport.any( - // (e) => e.name == element.exchangeName, - // )); + // currencies.removeWhere((element) => + // !Exchange.exchangesWithTorSupport.any((e) => e.name == element.exchangeName) + // ); + // But this helper may be more readable. } From 090262017a59a078158cb5eac165555e71472549 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 11 Sep 2023 18:23:53 -0500 Subject: [PATCH 214/237] do not use Majestic Bank-supplied onion service address for MB API intentionally left unused imports TODO enable tor services in cypherstack/tor then revert this snippet, see https://github.com/cypherstack/tor/issues/10#issuecomment-1714731696 --- .../exchange/majestic_bank/majestic_bank_api.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/services/exchange/majestic_bank/majestic_bank_api.dart b/lib/services/exchange/majestic_bank/majestic_bank_api.dart index d32209ae5..4a23597a5 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_api.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_api.dart @@ -47,10 +47,17 @@ class MajesticBankAPI { // final client = this.client ?? http.Client(); int code = -1; try { + // Use Tor if enabled. + // + // This section is commented out because Arti does not yet support + // onion services by default. Once it does, we can uncomment the + // proxyInfo ternary below. + // + // TODO: enable onion services in Arti and uncomment the snippet below. final response = await client.get( url: uri, proxyInfo: - Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, + /*Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo :*/ null, ); code = response.code; From 20e5f74ab2caa56cec3fb0ba3b09ef36beb22e05 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 11 Sep 2023 18:23:53 -0500 Subject: [PATCH 215/237] Revert "do not use Majestic Bank-supplied onion service address for MB API" This reverts commit 090262017a59a078158cb5eac165555e71472549. --- .../exchange/majestic_bank/majestic_bank_api.dart | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/services/exchange/majestic_bank/majestic_bank_api.dart b/lib/services/exchange/majestic_bank/majestic_bank_api.dart index 4a23597a5..d32209ae5 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_api.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_api.dart @@ -47,17 +47,10 @@ class MajesticBankAPI { // final client = this.client ?? http.Client(); int code = -1; try { - // Use Tor if enabled. - // - // This section is commented out because Arti does not yet support - // onion services by default. Once it does, we can uncomment the - // proxyInfo ternary below. - // - // TODO: enable onion services in Arti and uncomment the snippet below. final response = await client.get( url: uri, proxyInfo: - /*Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo :*/ null, + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); code = response.code; From ba42b762962a6fc4fe8849b9d55c86f24eaaa2b6 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Mon, 11 Sep 2023 18:41:37 -0500 Subject: [PATCH 216/237] WIP showing that added Content-Lengths get stripped/ignored --- lib/utilities/paynym_is_api.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/utilities/paynym_is_api.dart b/lib/utilities/paynym_is_api.dart index 67cafa1c1..629a88f7e 100644 --- a/lib/utilities/paynym_is_api.dart +++ b/lib/utilities/paynym_is_api.dart @@ -39,8 +39,13 @@ class PaynymIsApi { version + (endpoint.startsWith("/") ? endpoint : "/$endpoint"); final uri = Uri.parse(url); + + // Calculate the body length. + int contentLength = utf8.encode(jsonEncode(body)).length; + final headers = { 'Content-Type': 'application/json; charset=UTF-8', + 'Content-Length': contentLength.toString(), // Set the Content-Length header. }..addAll(additionalHeaders); final response = await client.post( url: uri, From 16718b94e600899e53b0d4f8cd6680e21df3eb55 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 11 Sep 2023 17:54:01 -0600 Subject: [PATCH 217/237] revert auto focus next field on valid mnemonic word --- .../restore_wallet_view.dart | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 87219d277..1a62af746 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -98,7 +98,7 @@ class _RestoreWalletViewState extends ConsumerState { final List _controllers = []; final List _inputStatuses = []; - final List _focusNodes = []; + // final List _focusNodes = []; late final BarcodeScannerInterface scanner; @@ -152,7 +152,7 @@ class _RestoreWalletViewState extends ConsumerState { for (int i = 0; i < _seedWordCount; i++) { _controllers.add(TextEditingController()); _inputStatuses.add(FormInputStatus.empty); - _focusNodes.add(FocusNode()); + // _focusNodes.add(FocusNode()); } super.initState(); @@ -821,8 +821,8 @@ class _RestoreWalletViewState extends ConsumerState { i * 4 + j - 1 == 1 ? textSelectionControls : null, - focusNode: - _focusNodes[i * 4 + j - 1], + // focusNode: + // _focusNodes[i * 4 + j - 1], onChanged: (value) { final FormInputStatus formInputStatus; @@ -841,18 +841,18 @@ class _RestoreWalletViewState extends ConsumerState { FormInputStatus.invalid; } - if (formInputStatus == - FormInputStatus.valid) { - if (i * 4 + j < - _focusNodes.length) { - _focusNodes[i * 4 + j] - .requestFocus(); - } else if (i * 4 + j == - _focusNodes.length) { - _focusNodes[i * 4 + j - 1] - .unfocus(); - } - } + // if (formInputStatus == + // FormInputStatus.valid) { + // if (i * 4 + j < + // _focusNodes.length) { + // _focusNodes[i * 4 + j] + // .requestFocus(); + // } else if (i * 4 + j == + // _focusNodes.length) { + // _focusNodes[i * 4 + j - 1] + // .unfocus(); + // } + // } setState(() { _inputStatuses[i * 4 + j - @@ -929,7 +929,7 @@ class _RestoreWalletViewState extends ConsumerState { selectionControls: i == 1 ? textSelectionControls : null, - focusNode: _focusNodes[i], + // focusNode: _focusNodes[i], onChanged: (value) { final FormInputStatus formInputStatus; @@ -948,27 +948,27 @@ class _RestoreWalletViewState extends ConsumerState { FormInputStatus.invalid; } - if (formInputStatus == - FormInputStatus - .valid && - (i - 1) < - _focusNodes.length) { - Focus.of(context) - .requestFocus( - _focusNodes[i]); - } + // if (formInputStatus == + // FormInputStatus + // .valid && + // (i - 1) < + // _focusNodes.length) { + // Focus.of(context) + // .requestFocus( + // _focusNodes[i]); + // } - if (formInputStatus == - FormInputStatus.valid) { - if (i + 1 < - _focusNodes.length) { - _focusNodes[i + 1] - .requestFocus(); - } else if (i + 1 == - _focusNodes.length) { - _focusNodes[i].unfocus(); - } - } + // if (formInputStatus == + // FormInputStatus.valid) { + // if (i + 1 < + // _focusNodes.length) { + // _focusNodes[i + 1] + // .requestFocus(); + // } else if (i + 1 == + // _focusNodes.length) { + // _focusNodes[i].unfocus(); + // } + // } }, controller: _controllers[i], style: @@ -1068,7 +1068,7 @@ class _RestoreWalletViewState extends ConsumerState { AutovalidateMode.onUserInteraction, selectionControls: i == 1 ? textSelectionControls : null, - focusNode: _focusNodes[i - 1], + // focusNode: _focusNodes[i - 1], onChanged: (value) { final FormInputStatus formInputStatus; @@ -1084,14 +1084,14 @@ class _RestoreWalletViewState extends ConsumerState { FormInputStatus.invalid; } - if (formInputStatus == - FormInputStatus.valid) { - if (i < _focusNodes.length) { - _focusNodes[i].requestFocus(); - } else if (i == _focusNodes.length) { - _focusNodes[i - 1].unfocus(); - } - } + // if (formInputStatus == + // FormInputStatus.valid) { + // if (i < _focusNodes.length) { + // _focusNodes[i].requestFocus(); + // } else if (i == _focusNodes.length) { + // _focusNodes[i - 1].unfocus(); + // } + // } setState(() { _inputStatuses[i - 1] = formInputStatus; From 26ce10c8fffd465d274cf8366ff7d5991a2580ff Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 12 Sep 2023 09:42:50 -0600 Subject: [PATCH 218/237] update flutter_svg --- pubspec.lock | 36 ++++++++++++++++++++++++++---------- pubspec.yaml | 2 +- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index f24f7916a..2b04a97a2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -743,10 +743,10 @@ packages: dependency: "direct main" description: name: flutter_svg - sha256: "6ff9fa12892ae074092de2fa6a9938fb21dbabfdaa2ff57dc697ff912fc8d4b2" + sha256: "8c5d68a82add3ca76d792f058b186a0599414f279f00ece4830b9b231b570338" url: "https://pub.dev" source: hosted - version: "1.1.6" + version: "2.0.7" flutter_test: dependency: "direct dev" description: flutter @@ -1142,14 +1142,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" - path_drawing: - dependency: transitive - description: - name: path_drawing - sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 - url: "https://pub.dev" - source: hosted - version: "1.0.1" path_parsing: dependency: transitive description: @@ -1748,6 +1740,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.7" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "670f6e07aca990b4a2bcdc08a784193c4ccdd1932620244c3a86bb72a0eac67f" + url: "https://pub.dev" + source: hosted + version: "1.1.7" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "7451721781d967db9933b63f5733b1c4533022c0ba373a01bdd79d1a5457f69f" + url: "https://pub.dev" + source: hosted + version: "1.1.7" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "80a13c613c8bde758b1464a1755a7b3a8f2b6cec61fbf0f5a53c94c30f03ba2e" + url: "https://pub.dev" + source: hosted + version: "1.1.7" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e692f0cfc..f05cfe781 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -101,7 +101,7 @@ dependencies: flutter_native_splash: ^2.2.4 google_fonts: ^4.0.4 url_launcher: ^6.0.5 - flutter_svg: ^1.0.1 + flutter_svg: ^2.0.7 flutter_feather_icons: ^2.0.0+1 decimal: ^2.1.0 event_bus: ^2.0.0 From 4d537d88a3d40d655cfaee35f47a7e165d704736 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 12 Sep 2023 10:41:49 -0600 Subject: [PATCH 219/237] fix tests --- .../notifications/notification_card_test.dart | 7 ++ test/pages/send_view/send_view_test.dart | 13 ++- test/widget_tests/managed_favorite_test.dart | 17 ++- .../table_view/table_view_row_test.dart | 7 ++ test/widget_tests/trade_card_test.dart | 20 ++++ test/widget_tests/trade_card_test.mocks.dart | 100 ++++++++++++++++++ test/widget_tests/transaction_card_test.dart | 71 ++++++++++++- .../transaction_card_test.mocks.dart | 100 ++++++++++++++++++ test/widget_tests/wallet_card_test.dart | 7 ++ .../wallet_info_row/wallet_info_row_test.dart | 7 ++ 10 files changed, 344 insertions(+), 5 deletions(-) diff --git a/test/notifications/notification_card_test.dart b/test/notifications/notification_card_test.dart index 55a9dcae5..d471064b6 100644 --- a/test/notifications/notification_card_test.dart +++ b/test/notifications/notification_card_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; @@ -7,6 +9,7 @@ import 'package:mockito/mockito.dart'; import 'package:stackwallet/models/isar/stack_theme.dart'; import 'package:stackwallet/models/notification_model.dart'; import 'package:stackwallet/notifications/notification_card.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_service.dart'; import 'package:stackwallet/utilities/assets.dart'; @@ -47,6 +50,10 @@ void main() { ProviderScope( overrides: [ pThemeService.overrideWithValue(mockThemeService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), ], child: MaterialApp( theme: ThemeData( diff --git a/test/pages/send_view/send_view_test.dart b/test/pages/send_view/send_view_test.dart index 975554c8d..389ea1469 100644 --- a/test/pages/send_view/send_view_test.dart +++ b/test/pages/send_view/send_view_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -14,6 +16,7 @@ import 'package:stackwallet/services/locale_service.dart'; import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/services/wallets.dart'; import 'package:stackwallet/services/wallets_service.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_service.dart'; import 'package:stackwallet/utilities/amount/amount_unit.dart'; @@ -80,6 +83,10 @@ void main() { .overrideWithValue(mockLocaleService), prefsChangeNotifierProvider.overrideWithValue(mockPrefs), pThemeService.overrideWithValue(mockThemeService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), // previewTxButtonStateProvider ], child: MaterialApp( @@ -157,7 +164,11 @@ void main() { localeServiceChangeNotifierProvider .overrideWithValue(mockLocaleService), prefsChangeNotifierProvider.overrideWithValue(mockPrefs), - pThemeService.overrideWithValue(mockThemeService) + pThemeService.overrideWithValue(mockThemeService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), // previewTxButtonStateProvider ], child: MaterialApp( diff --git a/test/widget_tests/managed_favorite_test.dart b/test/widget_tests/managed_favorite_test.dart index 3d8bb66fa..623e70e30 100644 --- a/test/widget_tests/managed_favorite_test.dart +++ b/test/widget_tests/managed_favorite_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -14,6 +16,7 @@ import 'package:stackwallet/services/locale_service.dart'; import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/services/wallets.dart'; import 'package:stackwallet/services/wallets_service.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; @@ -89,6 +92,10 @@ void main() { walletsChangeNotifierProvider.overrideWithValue(wallets), pThemeService.overrideWithValue(mockThemeService), prefsChangeNotifierProvider.overrideWithValue(mockPrefs), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), ], child: MaterialApp( theme: ThemeData( @@ -176,6 +183,10 @@ void main() { walletsServiceChangeNotifierProvider .overrideWithValue(mockWalletsService), prefsChangeNotifierProvider.overrideWithValue(mockPrefs), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), ], child: MaterialApp( theme: ThemeData( @@ -261,7 +272,11 @@ void main() { pThemeService.overrideWithValue(mockThemeService), prefsChangeNotifierProvider.overrideWithValue(mockPrefs), walletsServiceChangeNotifierProvider - .overrideWithValue(mockWalletsService) + .overrideWithValue(mockWalletsService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), ], child: MaterialApp( theme: ThemeData( diff --git a/test/widget_tests/table_view/table_view_row_test.dart b/test/widget_tests/table_view/table_view_row_test.dart index 4a84f0e64..9e9f4360e 100644 --- a/test/widget_tests/table_view/table_view_row_test.dart +++ b/test/widget_tests/table_view/table_view_row_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -12,6 +14,7 @@ import 'package:stackwallet/services/coins/coin_service.dart'; import 'package:stackwallet/services/coins/manager.dart'; import 'package:stackwallet/services/wallets.dart'; import 'package:stackwallet/services/wallets_service.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; @@ -72,6 +75,10 @@ void main() { overrides: [ walletsChangeNotifierProvider.overrideWithValue(mockWallet), pThemeService.overrideWithValue(mockThemeService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), ], child: MaterialApp( theme: ThemeData( diff --git a/test/widget_tests/trade_card_test.dart b/test/widget_tests/trade_card_test.dart index d42c00b85..d30c91560 100644 --- a/test/widget_tests/trade_card_test.dart +++ b/test/widget_tests/trade_card_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -5,7 +7,9 @@ import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart'; import 'package:stackwallet/models/isar/stack_theme.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/themes/theme_providers.dart'; import 'package:stackwallet/themes/theme_service.dart'; import 'package:stackwallet/widgets/trade_card.dart'; @@ -14,10 +18,17 @@ import 'trade_card_test.mocks.dart'; @GenerateMocks([ ThemeService, + IThemeAssets, ]) void main() { testWidgets("Test Trade card builds", (widgetTester) async { final mockThemeService = MockThemeService(); + final mockIThemeAssets = MockIThemeAssets(); + + when(mockIThemeAssets.txExchangeFailed).thenAnswer( + (_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg", + ); when(mockThemeService.getTheme(themeId: "light")).thenAnswer( (_) => StackTheme.fromJson( json: lightThemeJsonMap, @@ -51,6 +62,15 @@ void main() { ProviderScope( overrides: [ pThemeService.overrideWithValue(mockThemeService), + themeAssetsProvider.overrideWithProvider( + StateProvider( + (ref) => mockIThemeAssets, + ), + ), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), ], child: MaterialApp( theme: ThemeData( diff --git a/test/widget_tests/trade_card_test.mocks.dart b/test/widget_tests/trade_card_test.mocks.dart index 1bb236eb4..88b3eb240 100644 --- a/test/widget_tests/trade_card_test.mocks.dart +++ b/test/widget_tests/trade_card_test.mocks.dart @@ -129,3 +129,103 @@ class MockThemeService extends _i1.Mock implements _i3.ThemeService { {#themeId: themeId}, )) as _i4.StackTheme?); } + +/// A class which mocks [IThemeAssets]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIThemeAssets extends _i1.Mock implements _i4.IThemeAssets { + MockIThemeAssets() { + _i1.throwOnMissingStub(this); + } + + @override + String get bellNew => (super.noSuchMethod( + Invocation.getter(#bellNew), + returnValue: '', + ) as String); + @override + String get buy => (super.noSuchMethod( + Invocation.getter(#buy), + returnValue: '', + ) as String); + @override + String get exchange => (super.noSuchMethod( + Invocation.getter(#exchange), + returnValue: '', + ) as String); + @override + String get personaIncognito => (super.noSuchMethod( + Invocation.getter(#personaIncognito), + returnValue: '', + ) as String); + @override + String get personaEasy => (super.noSuchMethod( + Invocation.getter(#personaEasy), + returnValue: '', + ) as String); + @override + String get stack => (super.noSuchMethod( + Invocation.getter(#stack), + returnValue: '', + ) as String); + @override + String get stackIcon => (super.noSuchMethod( + Invocation.getter(#stackIcon), + returnValue: '', + ) as String); + @override + String get receive => (super.noSuchMethod( + Invocation.getter(#receive), + returnValue: '', + ) as String); + @override + String get receivePending => (super.noSuchMethod( + Invocation.getter(#receivePending), + returnValue: '', + ) as String); + @override + String get receiveCancelled => (super.noSuchMethod( + Invocation.getter(#receiveCancelled), + returnValue: '', + ) as String); + @override + String get send => (super.noSuchMethod( + Invocation.getter(#send), + returnValue: '', + ) as String); + @override + String get sendPending => (super.noSuchMethod( + Invocation.getter(#sendPending), + returnValue: '', + ) as String); + @override + String get sendCancelled => (super.noSuchMethod( + Invocation.getter(#sendCancelled), + returnValue: '', + ) as String); + @override + String get themeSelector => (super.noSuchMethod( + Invocation.getter(#themeSelector), + returnValue: '', + ) as String); + @override + String get themePreview => (super.noSuchMethod( + Invocation.getter(#themePreview), + returnValue: '', + ) as String); + @override + String get txExchange => (super.noSuchMethod( + Invocation.getter(#txExchange), + returnValue: '', + ) as String); + @override + String get txExchangePending => (super.noSuchMethod( + Invocation.getter(#txExchangePending), + returnValue: '', + ) as String); + @override + String get txExchangeFailed => (super.noSuchMethod( + Invocation.getter(#txExchangeFailed), + returnValue: '', + ) as String); +} diff --git a/test/widget_tests/transaction_card_test.dart b/test/widget_tests/transaction_card_test.dart index c4b89fb4a..755b367c1 100644 --- a/test/widget_tests/transaction_card_test.dart +++ b/test/widget_tests/transaction_card_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_feather_icons/flutter_feather_icons.dart'; @@ -22,7 +24,9 @@ import 'package:stackwallet/services/locale_service.dart'; import 'package:stackwallet/services/notes_service.dart'; import 'package:stackwallet/services/price_service.dart'; import 'package:stackwallet/services/wallets.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/themes/theme_providers.dart'; import 'package:stackwallet/themes/theme_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/amount/amount_unit.dart'; @@ -46,6 +50,7 @@ import 'transaction_card_test.mocks.dart'; NotesService, ThemeService, MainDB, + IThemeAssets, ], customMocks: []) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -57,6 +62,12 @@ void main() { final mockPriceService = MockPriceService(); final mockThemeService = MockThemeService(); final mockDB = MockMainDB(); + final mockIThemeAssets = MockIThemeAssets(); + + when(mockIThemeAssets.send).thenAnswer( + (_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg", + ); final tx = Transaction( txid: "some txid", @@ -130,6 +141,15 @@ void main() { prefsChangeNotifierProvider.overrideWithValue(mockPrefs), priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService), mainDBProvider.overrideWithValue(mockDB), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), + themeAssetsProvider.overrideWithProvider( + StateProvider( + (ref) => mockIThemeAssets, + ), + ), ], child: MaterialApp( theme: ThemeData( @@ -186,6 +206,12 @@ void main() { final mockPriceService = MockPriceService(); final mockThemeService = MockThemeService(); final mockDB = MockMainDB(); + final mockIThemeAssets = MockIThemeAssets(); + + when(mockIThemeAssets.txExchangeFailed).thenAnswer( + (_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg", + ); final tx = Transaction( txid: "some txid", @@ -257,7 +283,16 @@ void main() { prefsChangeNotifierProvider.overrideWithValue(mockPrefs), pThemeService.overrideWithValue(mockThemeService), mainDBProvider.overrideWithValue(mockDB), - priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService) + priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), + themeAssetsProvider.overrideWithProvider( + StateProvider( + (ref) => mockIThemeAssets, + ), + ), ], child: MaterialApp( theme: ThemeData( @@ -312,6 +347,12 @@ void main() { final mockPriceService = MockPriceService(); final mockThemeService = MockThemeService(); final mockDB = MockMainDB(); + final mockIThemeAssets = MockIThemeAssets(); + + when(mockIThemeAssets.receive).thenAnswer( + (_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg", + ); final tx = Transaction( txid: "some txid", @@ -384,7 +425,16 @@ void main() { prefsChangeNotifierProvider.overrideWithValue(mockPrefs), pThemeService.overrideWithValue(mockThemeService), mainDBProvider.overrideWithValue(mockDB), - priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService) + priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), + themeAssetsProvider.overrideWithProvider( + StateProvider( + (ref) => mockIThemeAssets, + ), + ), ], child: MaterialApp( theme: ThemeData( @@ -432,6 +482,12 @@ void main() { final mockThemeService = MockThemeService(); final mockDB = MockMainDB(); final navigator = mockingjay.MockNavigator(); + final mockIThemeAssets = MockIThemeAssets(); + + when(mockIThemeAssets.send).thenAnswer( + (_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg", + ); final tx = Transaction( txid: "some txid", @@ -509,7 +565,16 @@ void main() { prefsChangeNotifierProvider.overrideWithValue(mockPrefs), pThemeService.overrideWithValue(mockThemeService), mainDBProvider.overrideWithValue(mockDB), - priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService) + priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), + themeAssetsProvider.overrideWithProvider( + StateProvider( + (ref) => mockIThemeAssets, + ), + ), ], child: MaterialApp( theme: ThemeData( diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index 90afc98be..50c290da8 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -3538,3 +3538,103 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { returnValue: _i19.Future.value(), ) as _i19.Future); } + +/// A class which mocks [IThemeAssets]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIThemeAssets extends _i1.Mock implements _i33.IThemeAssets { + MockIThemeAssets() { + _i1.throwOnMissingStub(this); + } + + @override + String get bellNew => (super.noSuchMethod( + Invocation.getter(#bellNew), + returnValue: '', + ) as String); + @override + String get buy => (super.noSuchMethod( + Invocation.getter(#buy), + returnValue: '', + ) as String); + @override + String get exchange => (super.noSuchMethod( + Invocation.getter(#exchange), + returnValue: '', + ) as String); + @override + String get personaIncognito => (super.noSuchMethod( + Invocation.getter(#personaIncognito), + returnValue: '', + ) as String); + @override + String get personaEasy => (super.noSuchMethod( + Invocation.getter(#personaEasy), + returnValue: '', + ) as String); + @override + String get stack => (super.noSuchMethod( + Invocation.getter(#stack), + returnValue: '', + ) as String); + @override + String get stackIcon => (super.noSuchMethod( + Invocation.getter(#stackIcon), + returnValue: '', + ) as String); + @override + String get receive => (super.noSuchMethod( + Invocation.getter(#receive), + returnValue: '', + ) as String); + @override + String get receivePending => (super.noSuchMethod( + Invocation.getter(#receivePending), + returnValue: '', + ) as String); + @override + String get receiveCancelled => (super.noSuchMethod( + Invocation.getter(#receiveCancelled), + returnValue: '', + ) as String); + @override + String get send => (super.noSuchMethod( + Invocation.getter(#send), + returnValue: '', + ) as String); + @override + String get sendPending => (super.noSuchMethod( + Invocation.getter(#sendPending), + returnValue: '', + ) as String); + @override + String get sendCancelled => (super.noSuchMethod( + Invocation.getter(#sendCancelled), + returnValue: '', + ) as String); + @override + String get themeSelector => (super.noSuchMethod( + Invocation.getter(#themeSelector), + returnValue: '', + ) as String); + @override + String get themePreview => (super.noSuchMethod( + Invocation.getter(#themePreview), + returnValue: '', + ) as String); + @override + String get txExchange => (super.noSuchMethod( + Invocation.getter(#txExchange), + returnValue: '', + ) as String); + @override + String get txExchangePending => (super.noSuchMethod( + Invocation.getter(#txExchangePending), + returnValue: '', + ) as String); + @override + String get txExchangeFailed => (super.noSuchMethod( + Invocation.getter(#txExchangeFailed), + returnValue: '', + ) as String); +} diff --git a/test/widget_tests/wallet_card_test.dart b/test/widget_tests/wallet_card_test.dart index c2e77d012..b93bdbf20 100644 --- a/test/widget_tests/wallet_card_test.dart +++ b/test/widget_tests/wallet_card_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -12,6 +14,7 @@ import 'package:stackwallet/services/coins/coin_service.dart'; import 'package:stackwallet/services/coins/manager.dart'; import 'package:stackwallet/services/locale_service.dart'; import 'package:stackwallet/services/wallets.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; @@ -73,6 +76,10 @@ void main() { overrides: [ walletsChangeNotifierProvider.overrideWithValue(wallets), pThemeService.overrideWithValue(mockThemeService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), ], child: MaterialApp( theme: ThemeData( diff --git a/test/widget_tests/wallet_info_row/wallet_info_row_test.dart b/test/widget_tests/wallet_info_row/wallet_info_row_test.dart index c3fb2eef5..db4966a50 100644 --- a/test/widget_tests/wallet_info_row/wallet_info_row_test.dart +++ b/test/widget_tests/wallet_info_row/wallet_info_row_test.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -12,6 +14,7 @@ import 'package:stackwallet/services/coins/manager.dart'; import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/services/wallets.dart'; import 'package:stackwallet/services/wallets_service.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_service.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; @@ -65,6 +68,10 @@ void main() { overrides: [ walletsChangeNotifierProvider.overrideWithValue(wallets), pThemeService.overrideWithValue(mockThemeService), + coinIconProvider.overrideWithProvider( + (argument) => Provider((_) => + "${Directory.current.path}/test/sample_data/light/assets/dummy.svg"), + ), ], child: MaterialApp( theme: ThemeData( From 50466ff509f77f9694b6dfab51c0b65c9f76ca4b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 12 Sep 2023 13:49:25 -0500 Subject: [PATCH 220/237] use updated cargokit, rename tor->tor_ffi_plugin --- crypto_plugins/tor | 2 +- lib/services/tor_service.dart | 4 ++-- linux/CMakeLists.txt | 3 --- linux/flutter/generated_plugins.cmake | 1 + pubspec.lock | 2 +- pubspec.yaml | 2 +- windows/flutter/generated_plugins.cmake | 1 + 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 22abf0036..db8b4873d 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 22abf0036d8eda68efda5a31dc32c6f8932de4ec +Subproject commit db8b4873df443205c6f909039c0ea0ef90590093 diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index 3998dba5e..82d507653 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -4,7 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/utilities/logger.dart'; -import 'package:tor/tor.dart'; +import 'package:tor_ffi_plugin/tor_ffi_plugin.dart'; final pTorService = Provider((_) => TorService.sharedInstance); @@ -36,7 +36,7 @@ class TorService { /// Initialize the tor ffi lib instance if it hasn't already been set. Nothing /// changes if _tor is already been set. void init({Tor? mockableOverride}) { - _tor ??= mockableOverride ?? Tor(); + _tor ??= mockableOverride ?? Tor.instance; } /// Start the Tor service. diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 273f97bc2..53391e7ad 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -146,9 +146,6 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/linux/build/libmobileliblelantus.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/tor/native/tor-ffi/target/x86_64-unknown-linux-gnu/release/libtor_ffi.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1.7.4" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 38eed0699..f48fdcd94 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -15,6 +15,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + tor_ffi_plugin ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/pubspec.lock b/pubspec.lock index 0415b5efe..167c41441 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1644,7 +1644,7 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.1" - tor: + tor_ffi_plugin: dependency: "direct main" description: path: "crypto_plugins/tor" diff --git a/pubspec.yaml b/pubspec.yaml index 8e92c253e..f53d44348 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -57,7 +57,7 @@ dependencies: url: https://github.com/cypherstack/bip47.git ref: 081ca1863c2feba00c35bb5b297902f12f499941 - tor: + tor_ffi_plugin: path: ./crypto_plugins/tor # Utility plugins diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 324c950be..701de9701 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -16,6 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + tor_ffi_plugin ) set(PLUGIN_BUNDLED_LIBRARIES) From f53bd53af4ddbe5d8cc0ac04ae101022469316ed Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 12 Sep 2023 15:01:02 -0500 Subject: [PATCH 221/237] tap the onion to connect/disconnect --- .../tor_settings/tor_settings_view.dart | 107 +++++++++++++----- 1 file changed, 76 insertions(+), 31 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 1c5127a34..09536f506 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -17,6 +17,7 @@ import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; @@ -41,40 +42,84 @@ class _TorSettingsViewState extends ConsumerState { Widget _buildTorIcon(TorConnectionStatus status) { switch (status) { case TorConnectionStatus.disconnected: - return Stack( - alignment: AlignmentDirectional.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context).extension()!.textSubtitle3, - width: 200, - height: 200, + return GestureDetector( + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: + Theme.of(context).extension()!.textSubtitle3, + width: 200, + height: 200, + ), + Text( + "CONNECT", + style: STextStyles.smallMed14(context).copyWith( + color: + Theme.of(context).extension()!.popupBG), + ) + ], ), - Text( - "CONNECT", - style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context).extension()!.popupBG), - ) - ], - ); + onTap: () async { + // Init the Tor service if it hasn't already been. + ref.read(pTorService).init(); + + // Start the Tor service. + try { + await ref.read(pTorService).start(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = true; + } catch (e, s) { + Logging.instance.log( + "Error starting tor: $e\n$s", + level: LogLevel.Error, + ); + } + + setState(() { + _networkStatus = TorConnectionStatus.connecting; + }); + }); case TorConnectionStatus.connected: - return Stack( - alignment: AlignmentDirectional.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: - Theme.of(context).extension()!.accentColorGreen, - width: 200, - height: 200, + return GestureDetector( + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context) + .extension()! + .accentColorGreen, + width: 200, + height: 200, + ), + Text( + "CONNECTED", + style: STextStyles.smallMed14(context).copyWith( + color: + Theme.of(context).extension()!.popupBG), + ) + ], ), - Text( - "CONNECTED", - style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context).extension()!.popupBG), - ) - ], - ); + onTap: () async { + // Init the Tor service if it hasn't already been. + ref.read(pTorService).init(); + + // Start the Tor service. + try { + await ref.read(pTorService).start(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = true; + } catch (e, s) { + Logging.instance.log( + "Error starting tor: $e\n$s", + level: LogLevel.Error, + ); + } + }); case TorConnectionStatus.connecting: return Stack( alignment: AlignmentDirectional.center, From 4773f1ab9ff2cda9c1d730f45b8e878bbbd0dcfe Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 12 Sep 2023 15:15:08 -0500 Subject: [PATCH 222/237] refactor connect and disconnect and apply it to onion and row --- .../tor_settings/tor_settings_view.dart | 154 ++++++++++++------ 1 file changed, 107 insertions(+), 47 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 09536f506..06944b579 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -62,25 +62,7 @@ class _TorSettingsViewState extends ConsumerState { ], ), onTap: () async { - // Init the Tor service if it hasn't already been. - ref.read(pTorService).init(); - - // Start the Tor service. - try { - await ref.read(pTorService).start(); - - // Toggle the useTor preference on success. - ref.read(prefsChangeNotifierProvider).useTor = true; - } catch (e, s) { - Logging.instance.log( - "Error starting tor: $e\n$s", - level: LogLevel.Error, - ); - } - - setState(() { - _networkStatus = TorConnectionStatus.connecting; - }); + await connect(); }); case TorConnectionStatus.connected: return GestureDetector( @@ -104,21 +86,8 @@ class _TorSettingsViewState extends ConsumerState { ], ), onTap: () async { - // Init the Tor service if it hasn't already been. - ref.read(pTorService).init(); - - // Start the Tor service. - try { - await ref.read(pTorService).start(); - - // Toggle the useTor preference on success. - ref.read(prefsChangeNotifierProvider).useTor = true; - } catch (e, s) { - Logging.instance.log( - "Error starting tor: $e\n$s", - level: LogLevel.Error, - ); - } + // TODO we could make this sync. + await disconnect(); // TODO we could do away with the Future here. }); case TorConnectionStatus.connecting: return Stack( @@ -247,21 +216,67 @@ class _TorSettingsViewState extends ConsumerState { const SizedBox( height: 30, ), - RoundedWhiteContainer( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Row( - children: [ - Text( - "Tor status", - style: STextStyles.titleBold12(context), + GestureDetector( + child: RoundedWhiteContainer( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Row( + children: [ + Text( + "Tor status", + style: STextStyles.titleBold12(context), + ), + const Spacer(), + _buildTorStatus(_networkStatus), + ], ), - const Spacer(), - _buildTorStatus(_networkStatus), - ], + ), ), - ), - ), + onTap: () async { + // Connect or disconnect when the user taps the status. + switch (_networkStatus) { + case TorConnectionStatus.disconnected: + // Update the UI. + setState(() { + _networkStatus = TorConnectionStatus.connecting; + }); + + try { + await connect(); + } catch (e, s) { + Logging.instance.log( + "Error starting tor: $e\n$s", + level: LogLevel.Error, + ); + rethrow; + } + + // Update the UI. + setState(() { + _networkStatus = TorConnectionStatus.connected; + }); + break; + case TorConnectionStatus.connected: + try { + await disconnect(); + } catch (e, s) { + Logging.instance.log( + "Error stopping tor: $e\n$s", + level: LogLevel.Error, + ); + rethrow; + } + + // Update the UI. + setState(() { + _networkStatus = TorConnectionStatus.disconnected; + }); + break; + case TorConnectionStatus.connecting: + // Do nothing. + break; + } + }), const SizedBox( height: 8, ), @@ -348,4 +363,49 @@ class _TorSettingsViewState extends ConsumerState { ), ); } + + Future connect() async { + // Init the Tor service if it hasn't already been. + ref.read(pTorService).init(); + + // Start the Tor service. + try { + await ref.read(pTorService).start(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = true; + } catch (e, s) { + Logging.instance.log( + "Error starting tor: $e\n$s", + level: LogLevel.Error, + ); + } + + setState(() { + _networkStatus = TorConnectionStatus.connecting; + }); + + return; + } + + Future disconnect() async { + // Stop the Tor service. + try { + await ref.read(pTorService).stop(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = false; + } catch (e, s) { + Logging.instance.log( + "Error stopping tor: $e\n$s", + level: LogLevel.Error, + ); + } + + setState(() { + _networkStatus = TorConnectionStatus.disconnected; + }); + + return; + } } From 53baad66b6a3801e4735ff4b051b8f73ecae2076 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 12 Sep 2023 15:28:16 -0500 Subject: [PATCH 223/237] cypherstack/tor ios and mac updates and toggle tor plugin _enabled more --- crypto_plugins/tor | 2 +- lib/services/tor_service.dart | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index db8b4873d..0979ac52a 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit db8b4873df443205c6f909039c0ea0ef90590093 +Subproject commit 0979ac52a783ff7b87669434b39385f27a27f952 diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index 82d507653..90930d472 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -57,6 +57,14 @@ class TorService { // is explicitly made aware of this // TODO restart tor after that's been added to the tor-ffi crate // (probably better to have a restart function separately) + + // Fire a TorConnectionStatusChangedEvent on the event bus. + GlobalEventBus.instance.fire( + TorConnectionStatusChangedEvent( + TorConnectionStatus.connected, + "Tor connection status changed: connect ($_enabled)", + ), + ); return; } From 6594e3c0cfd166b7512c301cc05226f9cd6f73ba Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 12 Sep 2023 15:47:39 -0500 Subject: [PATCH 224/237] don't await on disable and add documentation and comments --- crypto_plugins/tor | 2 +- .../tor_settings/tor_settings_view.dart | 15 +++++++++++++++ lib/services/tor_service.dart | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 0979ac52a..84ad84e07 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 0979ac52a783ff7b87669434b39385f27a27f952 +Subproject commit 84ad84e07dee5b64828ad5ce380491b3aa798cc3 diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 06944b579..b0783c9d7 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -364,6 +364,13 @@ class _TorSettingsViewState extends ConsumerState { ); } + /// Connect to the Tor network. + /// + /// This method is called when the user taps the "Connect" button. + /// + /// Throws an exception if the Tor service fails to start. + /// + /// Returns a Future that completes when the Tor service has started. Future connect() async { // Init the Tor service if it hasn't already been. ref.read(pTorService).init(); @@ -381,6 +388,7 @@ class _TorSettingsViewState extends ConsumerState { ); } + // Update the UI. setState(() { _networkStatus = TorConnectionStatus.connecting; }); @@ -388,6 +396,13 @@ class _TorSettingsViewState extends ConsumerState { return; } + /// Disconnect from the Tor network. + /// + /// This method is called when the user taps the "Disconnect" button. + /// + /// Throws an exception if the Tor service fails to stop. + /// + /// Returns a Future that completes when the Tor service has stopped. Future disconnect() async { // Stop the Tor service. try { diff --git a/lib/services/tor_service.dart b/lib/services/tor_service.dart index 90930d472..ead6ab5fa 100644 --- a/lib/services/tor_service.dart +++ b/lib/services/tor_service.dart @@ -121,7 +121,7 @@ class TorService { // Stop the Tor service. try { - await _tor!.disable(); + _tor!.disable(); // no exception or error so we can (probably?) assume tor // has started successfully _enabled = false; From 17e83a68a3e98b896c1727d1b702f6f694e3acd5 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 12 Sep 2023 15:58:30 -0500 Subject: [PATCH 225/237] hook mobile home view onion up to tor status --- lib/pages/home_view/home_view.dart | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index 7fcc9f4ca..33acd0d62 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -26,6 +26,7 @@ import 'package:stackwallet/providers/global/notifications_provider.dart'; import 'package:stackwallet/providers/ui/home_view_index_provider.dart'; import 'package:stackwallet/providers/ui/unread_notifications_provider.dart'; import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_providers.dart'; import 'package:stackwallet/utilities/assets.dart'; @@ -261,7 +262,32 @@ class _HomeViewState extends ConsumerState { color: Theme.of(context) .extension()! .backgroundAppBar, - icon: _buildTorIcon(TorConnectionStatus.disconnected), + icon: ref.watch(pTorService).enabled + ? ref.read(pTorService).proxyInfo.port == -1 + ? SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context) + .extension()! + .accentColorYellow, + width: 20, + height: 20, + ) + : SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context) + .extension()! + .accentColorGreen, + width: 20, + height: 20, + ) + : SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context) + .extension()! + .textSubtitle3, + width: 20, + height: 20, + ), onPressed: () { Navigator.of(context) .pushNamed(TorSettingsView.routeName); From 7c487c021cf8e36ac042e07e2fbd74b3202d60db Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 12 Sep 2023 16:00:39 -0500 Subject: [PATCH 226/237] match design --- .../global_settings_view/tor_settings/tor_settings_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index b0783c9d7..f271b292a 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -78,7 +78,7 @@ class _TorSettingsViewState extends ConsumerState { height: 200, ), Text( - "CONNECTED", + "STOP", style: STextStyles.smallMed14(context).copyWith( color: Theme.of(context).extension()!.popupBG), From 6fe0bfef8156e4ba36e5bbf6f4347594c58aa20a Mon Sep 17 00:00:00 2001 From: sneurlax Date: Tue, 12 Sep 2023 16:45:57 -0500 Subject: [PATCH 227/237] add tor icon to wallet view --- lib/pages/home_view/home_view.dart | 26 ---------- .../tor_settings/tor_settings_view.dart | 10 ++-- lib/pages/wallet_view/wallet_view.dart | 52 +++++++++++++++++++ 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index 33acd0d62..c2f71bf48 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -118,32 +118,6 @@ class _HomeViewState extends ConsumerState { ); } - Widget _buildTorIcon(TorConnectionStatus status) { - switch (status) { - case TorConnectionStatus.disconnected: - return SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context).extension()!.textSubtitle3, - width: 20, - height: 20, - ); - case TorConnectionStatus.connected: - return SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context).extension()!.accentColorGreen, - width: 20, - height: 20, - ); - case TorConnectionStatus.connecting: - return SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context).extension()!.accentColorYellow, - width: 20, - height: 20, - ); - } - } - @override void initState() { _pageController = PageController(); diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index f271b292a..f76d29b3e 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -375,6 +375,11 @@ class _TorSettingsViewState extends ConsumerState { // Init the Tor service if it hasn't already been. ref.read(pTorService).init(); + // Update the UI. + setState(() { + _networkStatus = TorConnectionStatus.connecting; + }); + // Start the Tor service. try { await ref.read(pTorService).start(); @@ -388,11 +393,6 @@ class _TorSettingsViewState extends ConsumerState { ); } - // Update the UI. - setState(() { - _networkStatus = TorConnectionStatus.connecting; - }); - return; } diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index c9e391320..7e15c6e7d 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -29,6 +29,7 @@ import 'package:stackwallet/pages/paynym/paynym_claim_view.dart'; import 'package:stackwallet/pages/paynym/paynym_home_view.dart'; import 'package:stackwallet/pages/receive_view/receive_view.dart'; import 'package:stackwallet/pages/send_view/send_view.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_view.dart'; import 'package:stackwallet/pages/special/firo_rescan_recovery_error_dialog.dart'; @@ -51,6 +52,7 @@ import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_ import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart'; import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_providers.dart'; @@ -552,6 +554,56 @@ class _WalletViewState extends ConsumerState { ], ), actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + semanticsLabel: + "Tor Settings Button. Takes To Tor Settings Page.", + key: const Key("walletsViewTorButton"), + size: 36, + shadows: const [], + color: Theme.of(context) + .extension()! + .backgroundAppBar, + icon: ref.watch(pTorService).enabled + ? ref.read(pTorService).proxyInfo.port == -1 + ? SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context) + .extension()! + .accentColorYellow, + width: 20, + height: 20, + ) + : SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context) + .extension()! + .accentColorGreen, + width: 20, + height: 20, + ) + : SvgPicture.asset( + Assets.svg.tor, + color: Theme.of(context) + .extension()! + .textSubtitle3, + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context) + .pushNamed(TorSettingsView.routeName); + }, + ), + ), + ), Padding( padding: const EdgeInsets.only( top: 10, From 3fa099775404b688216a0e834943a099134fffed Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Tue, 12 Sep 2023 16:59:07 -0600 Subject: [PATCH 228/237] WIP: tor enabled dialog on buy view --- lib/pages/buy_view/buy_view.dart | 72 ++++++-- .../desktop_buy/desktop_buy_view.dart | 163 ++++++++++++------ 2 files changed, 170 insertions(+), 65 deletions(-) diff --git a/lib/pages/buy_view/buy_view.dart b/lib/pages/buy_view/buy_view.dart index 3d5fe1539..beeece754 100644 --- a/lib/pages/buy_view/buy_view.dart +++ b/lib/pages/buy_view/buy_view.dart @@ -9,38 +9,82 @@ */ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; import 'package:stackwallet/pages/buy_view/buy_form.dart'; +import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/widgets/stack_dialog.dart'; -class BuyView extends StatelessWidget { +class BuyView extends ConsumerStatefulWidget { const BuyView({ Key? key, this.coin, this.tokenContract, }) : super(key: key); - static const String routeName = "/stackBuyView"; - final Coin? coin; final EthContract? tokenContract; + static const String routeName = "/stackBuyView"; + + @override + ConsumerState createState() => _BuyViewState(); +} + +class _BuyViewState extends ConsumerState { + Coin? coin; + EthContract? tokenContract; + late bool torEnabled = false; + + @override + void initState() { + coin = widget.coin; + tokenContract = widget.tokenContract; + + WidgetsBinding.instance.addPostFrameCallback((_) async { + setState(() { + torEnabled = ref.read(prefsChangeNotifierProvider).useTor; + }); + }); + + super.initState(); + } + @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - return SafeArea( - child: Padding( - padding: const EdgeInsets.only( - left: 16, - right: 16, - top: 16, + return Stack( + children: [ + SafeArea( + child: Padding( + padding: const EdgeInsets.only( + left: 16, + right: 16, + top: 16, + ), + child: BuyForm( + coin: coin, + tokenContract: tokenContract, + ), + ), ), - child: BuyForm( - coin: coin, - tokenContract: tokenContract, - ), - ), + if (torEnabled) + Container( + color: Theme.of(context) + .extension()! + .overlay + .withOpacity(0.7), + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: const StackDialog( + title: "Tor is enabled", + message: "Purchasing not available while Tor is enabled", + ), + ), + ], ); } } diff --git a/lib/pages_desktop_specific/desktop_buy/desktop_buy_view.dart b/lib/pages_desktop_specific/desktop_buy/desktop_buy_view.dart index e56d2644c..8827641fa 100644 --- a/lib/pages_desktop_specific/desktop_buy/desktop_buy_view.dart +++ b/lib/pages_desktop_specific/desktop_buy/desktop_buy_view.dart @@ -9,76 +9,137 @@ */ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/pages/buy_view/buy_form.dart'; +import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -class DesktopBuyView extends StatefulWidget { +class DesktopBuyView extends ConsumerStatefulWidget { const DesktopBuyView({Key? key}) : super(key: key); static const String routeName = "/desktopBuyView"; @override - State createState() => _DesktopBuyViewState(); + ConsumerState createState() => _DesktopBuyViewState(); } -class _DesktopBuyViewState extends State { +class _DesktopBuyViewState extends ConsumerState { + late bool torEnabled = false; + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) async { + setState(() { + torEnabled = ref.read(prefsChangeNotifierProvider).useTor; + }); + }); + super.initState(); + } + @override Widget build(BuildContext context) { - return DesktopScaffold( - appBar: DesktopAppBar( - isCompactHeight: true, - leading: Padding( - padding: const EdgeInsets.only( - left: 24, - ), - child: Text( - "Buy crypto", - style: STextStyles.desktopH3(context), - ), - ), - ), - body: Padding( - padding: const EdgeInsets.only( - left: 24, - right: 24, - bottom: 24, - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - SizedBox( - height: 16, - ), - RoundedWhiteContainer( - padding: EdgeInsets.all(24), - child: BuyForm(), - ), - ], + return Stack( + children: [ + DesktopScaffold( + appBar: DesktopAppBar( + isCompactHeight: true, + leading: Padding( + padding: const EdgeInsets.only( + left: 24, + ), + child: Text( + "Buy crypto", + style: STextStyles.desktopH3(context), ), ), - const SizedBox( - width: 16, + ), + body: Padding( + padding: const EdgeInsets.only( + left: 24, + right: 24, + bottom: 24, ), - // Expanded( - // child: Row( - // children: const [ - // Expanded( - // child: DesktopTradeHistory(), - // ), - // ], - // ), - // ), - ], + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + SizedBox( + height: 16, + ), + RoundedWhiteContainer( + padding: EdgeInsets.all(24), + child: BuyForm(), + ), + ], + ), + ), + const SizedBox( + width: 16, + ), + // Expanded( + // child: Row( + // children: const [ + // Expanded( + // child: DesktopTradeHistory(), + // ), + // ], + // ), + // ), + ], + ), + ), ), - ), + if (torEnabled) + Container( + color: Theme.of(context) + .extension()! + .overlay + .withOpacity(0.7), + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: DesktopDialog( + maxHeight: 200, + maxWidth: 350, + child: Padding( + padding: const EdgeInsets.all( + 15.0, + ), + child: Column( + // crossAxisAlignment: CrossAxisAlignment.center, + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Tor is enabled", + textAlign: TextAlign.center, + style: STextStyles.pageTitleH1(context), + ), + const SizedBox( + height: 30, + ), + Text( + "Purchasing not available while Tor is enabled", + textAlign: TextAlign.center, + style: STextStyles.desktopTextMedium(context).copyWith( + color: Theme.of(context) + .extension()! + .infoItemLabel, + ), + ), + ], + ), + ), + ), + ), + ], ); } } From 7b6e956c5bdaea5815102e4df12294f6e7b16edf Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 12 Sep 2023 17:08:59 -0600 Subject: [PATCH 229/237] update tor ref --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 84ad84e07..082e363e6 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 84ad84e07dee5b64828ad5ce380491b3aa798cc3 +Subproject commit 082e363e6a3dc952ea499da0b51f1ab48c604157 From 27a7861bada697047bd906242d87a3772c231ef8 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 13 Sep 2023 09:49:12 -0600 Subject: [PATCH 230/237] refactor mobile tor settings --- .../tor_settings/tor_settings_view.dart | 583 +++++++++++------- 1 file changed, 356 insertions(+), 227 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index f76d29b3e..e970f0158 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -8,19 +8,23 @@ * */ +import 'dart:async'; + +import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; -import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; @@ -37,122 +41,8 @@ class TorSettingsView extends ConsumerStatefulWidget { } class _TorSettingsViewState extends ConsumerState { - late TorConnectionStatus _networkStatus; - - Widget _buildTorIcon(TorConnectionStatus status) { - switch (status) { - case TorConnectionStatus.disconnected: - return GestureDetector( - child: Stack( - alignment: AlignmentDirectional.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: - Theme.of(context).extension()!.textSubtitle3, - width: 200, - height: 200, - ), - Text( - "CONNECT", - style: STextStyles.smallMed14(context).copyWith( - color: - Theme.of(context).extension()!.popupBG), - ) - ], - ), - onTap: () async { - await connect(); - }); - case TorConnectionStatus.connected: - return GestureDetector( - child: Stack( - alignment: AlignmentDirectional.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context) - .extension()! - .accentColorGreen, - width: 200, - height: 200, - ), - Text( - "STOP", - style: STextStyles.smallMed14(context).copyWith( - color: - Theme.of(context).extension()!.popupBG), - ) - ], - ), - onTap: () async { - // TODO we could make this sync. - await disconnect(); // TODO we could do away with the Future here. - }); - case TorConnectionStatus.connecting: - return Stack( - alignment: AlignmentDirectional.center, - children: [ - SvgPicture.asset( - Assets.svg.tor, - color: - Theme.of(context).extension()!.accentColorYellow, - width: 200, - height: 200, - ), - Text( - "CONNECTING", - style: STextStyles.smallMed14(context).copyWith( - color: Theme.of(context).extension()!.popupBG), - ) - ], - ); - } - } - - Widget _buildTorStatus(TorConnectionStatus status) { - switch (status) { - case TorConnectionStatus.disconnected: - return Text( - "Disconnected", - style: STextStyles.itemSubtitle(context).copyWith( - color: Theme.of(context).extension()!.textSubtitle3), - ); - case TorConnectionStatus.connected: - return Text( - "Connected", - style: STextStyles.itemSubtitle(context).copyWith( - color: - Theme.of(context).extension()!.accentColorGreen), - ); - case TorConnectionStatus.connecting: - return Text( - "Connecting", - style: STextStyles.itemSubtitle(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorYellow), - ); - } - } - - @override - void initState() { - _networkStatus = ref.read(pTorService).enabled - ? TorConnectionStatus.connected - : TorConnectionStatus.disconnected; - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - @override Widget build(BuildContext context) { - final isDesktop = Util.isDesktop; - return Background( child: Scaffold( backgroundColor: Colors.transparent, @@ -204,79 +94,19 @@ class _TorSettingsViewState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Row( + const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( - padding: const EdgeInsets.all(10.0), - child: _buildTorIcon(_networkStatus), + padding: EdgeInsets.all(10.0), + child: TorIcon(), ), ], ), const SizedBox( height: 30, ), - GestureDetector( - child: RoundedWhiteContainer( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Row( - children: [ - Text( - "Tor status", - style: STextStyles.titleBold12(context), - ), - const Spacer(), - _buildTorStatus(_networkStatus), - ], - ), - ), - ), - onTap: () async { - // Connect or disconnect when the user taps the status. - switch (_networkStatus) { - case TorConnectionStatus.disconnected: - // Update the UI. - setState(() { - _networkStatus = TorConnectionStatus.connecting; - }); - - try { - await connect(); - } catch (e, s) { - Logging.instance.log( - "Error starting tor: $e\n$s", - level: LogLevel.Error, - ); - rethrow; - } - - // Update the UI. - setState(() { - _networkStatus = TorConnectionStatus.connected; - }); - break; - case TorConnectionStatus.connected: - try { - await disconnect(); - } catch (e, s) { - Logging.instance.log( - "Error stopping tor: $e\n$s", - level: LogLevel.Error, - ); - rethrow; - } - - // Update the UI. - setState(() { - _networkStatus = TorConnectionStatus.disconnected; - }); - break; - case TorConnectionStatus.connecting: - // Do nothing. - break; - } - }), + const TorButton(), const SizedBox( height: 8, ), @@ -363,64 +193,363 @@ class _TorSettingsViewState extends ConsumerState { ), ); } +} - /// Connect to the Tor network. - /// - /// This method is called when the user taps the "Connect" button. - /// - /// Throws an exception if the Tor service fails to start. - /// - /// Returns a Future that completes when the Tor service has started. - Future connect() async { - // Init the Tor service if it hasn't already been. - ref.read(pTorService).init(); +class TorIcon extends ConsumerStatefulWidget { + const TorIcon({super.key}); - // Update the UI. - setState(() { - _networkStatus = TorConnectionStatus.connecting; - }); + @override + ConsumerState createState() => _TorIconState(); +} - // Start the Tor service. - try { - await ref.read(pTorService).start(); +class _TorIconState extends ConsumerState { + late TorConnectionStatus _status; - // Toggle the useTor preference on success. - ref.read(prefsChangeNotifierProvider).useTor = true; - } catch (e, s) { - Logging.instance.log( - "Error starting tor: $e\n$s", - level: LogLevel.Error, - ); + Color _color( + TorConnectionStatus status, + StackColors colors, + ) { + switch (status) { + case TorConnectionStatus.disconnected: + return colors.textSubtitle3; + + case TorConnectionStatus.connected: + return colors.accentColorGreen; + + case TorConnectionStatus.connecting: + return colors.accentColorYellow; } - - return; } - /// Disconnect from the Tor network. - /// - /// This method is called when the user taps the "Disconnect" button. - /// - /// Throws an exception if the Tor service fails to stop. - /// - /// Returns a Future that completes when the Tor service has stopped. - Future disconnect() async { - // Stop the Tor service. - try { - await ref.read(pTorService).stop(); + String _label( + TorConnectionStatus status, + StackColors colors, + ) { + switch (status) { + case TorConnectionStatus.disconnected: + return "CONNECT"; - // Toggle the useTor preference on success. - ref.read(prefsChangeNotifierProvider).useTor = false; - } catch (e, s) { - Logging.instance.log( - "Error stopping tor: $e\n$s", - level: LogLevel.Error, - ); + case TorConnectionStatus.connected: + return "STOP"; + + case TorConnectionStatus.connecting: + return "CONNECTING"; } + } - setState(() { - _networkStatus = TorConnectionStatus.disconnected; - }); + bool _tapLock = false; - return; + Future onTap() async { + if (_tapLock) { + return; + } + _tapLock = true; + try { + // Connect or disconnect when the user taps the status. + switch (_status) { + case TorConnectionStatus.disconnected: + await _connectTor(ref, context); + break; + + case TorConnectionStatus.connected: + await _disconnectTor(ref, context); + + break; + + case TorConnectionStatus.connecting: + // Do nothing. + break; + } + } catch (_) { + // any exceptions should already be handled with error dialogs + // this try catch is just extra protection to ensure _tapLock gets reset + // in the finally block in the event of an unknown error + } finally { + _tapLock = false; + } + } + + @override + void initState() { + _status = ref.read(pTorService).enabled + ? TorConnectionStatus.connected + : TorConnectionStatus.disconnected; + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return _TorSubscriptionBase( + onTorStatusChanged: (status) { + setState(() { + _status = status; + }); + }, + child: ConditionalParent( + condition: _status != TorConnectionStatus.connecting, + builder: (child) => GestureDetector( + onTap: onTap, + child: child, + ), + child: SizedBox( + width: 220, + height: 220, + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + SvgPicture.asset( + Assets.svg.tor, + color: _color( + _status, + Theme.of(context).extension()!, + ), + width: 200, + height: 200, + ), + Text( + _label( + _status, + Theme.of(context).extension()!, + ), + style: STextStyles.smallMed14(context).copyWith( + color: Theme.of(context).extension()!.popupBG, + ), + ), + ], + ), + ), + ), + ); + } +} + +class TorButton extends ConsumerStatefulWidget { + const TorButton({super.key}); + + @override + ConsumerState createState() => _TorButtonState(); +} + +class _TorButtonState extends ConsumerState { + late TorConnectionStatus _status; + + Color _color( + TorConnectionStatus status, + StackColors colors, + ) { + switch (status) { + case TorConnectionStatus.disconnected: + return colors.textSubtitle3; + + case TorConnectionStatus.connected: + return colors.accentColorGreen; + + case TorConnectionStatus.connecting: + return colors.accentColorYellow; + } + } + + String _label( + TorConnectionStatus status, + StackColors colors, + ) { + switch (status) { + case TorConnectionStatus.disconnected: + return "Disconnected"; + + case TorConnectionStatus.connected: + return "Connected"; + + case TorConnectionStatus.connecting: + return "Connecting"; + } + } + + bool _tapLock = false; + + Future onTap() async { + if (_tapLock) { + return; + } + _tapLock = true; + try { + // Connect or disconnect when the user taps the status. + switch (_status) { + case TorConnectionStatus.disconnected: + await _connectTor(ref, context); + break; + + case TorConnectionStatus.connected: + await _disconnectTor(ref, context); + + break; + + case TorConnectionStatus.connecting: + // Do nothing. + break; + } + } catch (_) { + // any exceptions should already be handled with error dialogs + // this try catch is just extra protection to ensure _tapLock gets reset + // in the finally block in the event of an unknown error + } finally { + _tapLock = false; + } + } + + @override + void initState() { + _status = ref.read(pTorService).enabled + ? TorConnectionStatus.connected + : TorConnectionStatus.disconnected; + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return _TorSubscriptionBase( + onTorStatusChanged: (status) { + setState(() { + _status = status; + }); + }, + child: GestureDetector( + onTap: onTap, + child: RoundedWhiteContainer( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Row( + children: [ + Text( + "Tor status", + style: STextStyles.titleBold12(context), + ), + const Spacer(), + Text( + _label( + _status, + Theme.of(context).extension()!, + ), + style: STextStyles.itemSubtitle(context).copyWith( + color: _color( + _status, + Theme.of(context).extension()!, + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} + +class _TorSubscriptionBase extends ConsumerStatefulWidget { + const _TorSubscriptionBase({ + super.key, + required this.onTorStatusChanged, + this.eventBus, + required this.child, + }); + + final Widget child; + final void Function(TorConnectionStatus) onTorStatusChanged; + final EventBus? eventBus; + + @override + ConsumerState<_TorSubscriptionBase> createState() => + _TorSubscriptionBaseState(); +} + +class _TorSubscriptionBaseState extends ConsumerState<_TorSubscriptionBase> { + /// The global event bus. + late final EventBus eventBus; + + /// Subscription to the TorConnectionStatusChangedEvent. + late StreamSubscription + _torConnectionStatusSubscription; + + @override + void initState() { + // Initialize the global event bus. + eventBus = widget.eventBus ?? GlobalEventBus.instance; + + // Subscribe to the TorConnectionStatusChangedEvent. + _torConnectionStatusSubscription = + eventBus.on().listen( + (event) async { + widget.onTorStatusChanged.call(event.newStatus); + }, + ); + + super.initState(); + } + + @override + void dispose() { + // Clean up the TorConnectionStatusChangedEvent subscription. + _torConnectionStatusSubscription.cancel(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return widget.child; + } +} + +/// Connect to the Tor network. +/// +/// This method is called when the user taps the "Connect" button. +/// +/// Throws an exception if the Tor service fails to start. +/// +/// Returns a Future that completes when the Tor service has started. +Future _connectTor(WidgetRef ref, BuildContext context) async { + // Init the Tor service if it hasn't already been. + ref.read(pTorService).init(); + + // Start the Tor service. + try { + await ref.read(pTorService).start(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = true; + } catch (e, s) { + Logging.instance.log( + "Error starting tor: $e\n$s", + level: LogLevel.Error, + ); + // TODO: show dialog with error message + } + + return; +} + +/// Disconnect from the Tor network. +/// +/// This method is called when the user taps the "Disconnect" button. +/// +/// Throws an exception if the Tor service fails to stop. +/// +/// Returns a Future that completes when the Tor service has stopped. +Future _disconnectTor(WidgetRef ref, BuildContext context) async { + // Stop the Tor service. + try { + await ref.read(pTorService).stop(); + + // Toggle the useTor preference on success. + ref.read(prefsChangeNotifierProvider).useTor = false; + } catch (e, s) { + Logging.instance.log( + "Error stopping tor: $e\n$s", + level: LogLevel.Error, + ); + // TODO: show dialog with error message } } From b0f4476fc229d36cff9fd5e6519a1c14a50b9b06 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 13 Sep 2023 10:11:14 -0600 Subject: [PATCH 231/237] refactor mobile status bar tor icon --- lib/pages/home_view/home_view.dart | 48 +----------- .../tor_settings/tor_settings_view.dart | 62 +-------------- lib/pages/wallet_view/wallet_view.dart | 48 +----------- lib/widgets/small_tor_icon.dart | 76 +++++++++++++++++++ lib/widgets/tor_subscription.dart | 61 +++++++++++++++ 5 files changed, 148 insertions(+), 147 deletions(-) create mode 100644 lib/widgets/small_tor_icon.dart create mode 100644 lib/widgets/tor_subscription.dart diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index c2f71bf48..2303333e1 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -20,13 +20,11 @@ import 'package:stackwallet/pages/home_view/sub_widgets/home_view_button_bar.dar import 'package:stackwallet/pages/notification_views/notifications_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/global_settings_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/hidden_settings.dart'; -import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages/wallets_view/wallets_view.dart'; import 'package:stackwallet/providers/global/notifications_provider.dart'; import 'package:stackwallet/providers/ui/home_view_index_provider.dart'; import 'package:stackwallet/providers/ui/unread_notifications_provider.dart'; import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; -import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_providers.dart'; import 'package:stackwallet/utilities/assets.dart'; @@ -35,6 +33,7 @@ import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/small_tor_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; class HomeView extends ConsumerStatefulWidget { @@ -219,54 +218,15 @@ class _HomeViewState extends ConsumerState { ], ), actions: [ - Padding( - padding: const EdgeInsets.only( + const Padding( + padding: EdgeInsets.only( top: 10, bottom: 10, right: 10, ), child: AspectRatio( aspectRatio: 1, - child: AppBarIconButton( - semanticsLabel: - "Tor Settings Button. Takes To Tor Settings Page.", - key: const Key("walletsViewTorButton"), - size: 36, - shadows: const [], - color: Theme.of(context) - .extension()! - .backgroundAppBar, - icon: ref.watch(pTorService).enabled - ? ref.read(pTorService).proxyInfo.port == -1 - ? SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context) - .extension()! - .accentColorYellow, - width: 20, - height: 20, - ) - : SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context) - .extension()! - .accentColorGreen, - width: 20, - height: 20, - ) - : SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context) - .extension()! - .textSubtitle3, - width: 20, - height: 20, - ), - onPressed: () { - Navigator.of(context) - .pushNamed(TorSettingsView.routeName); - }, - ), + child: SmallTorIcon(), ), ), Padding( diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index e970f0158..9df8cc8bb 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -10,13 +10,11 @@ import 'dart:async'; -import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; -import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; @@ -30,6 +28,7 @@ import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart' import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; +import 'package:stackwallet/widgets/tor_subscription.dart'; class TorSettingsView extends ConsumerStatefulWidget { const TorSettingsView({Key? key}) : super(key: key); @@ -280,7 +279,7 @@ class _TorIconState extends ConsumerState { @override Widget build(BuildContext context) { - return _TorSubscriptionBase( + return TorSubscription( onTorStatusChanged: (status) { setState(() { _status = status; @@ -409,7 +408,7 @@ class _TorButtonState extends ConsumerState { @override Widget build(BuildContext context) { - return _TorSubscriptionBase( + return TorSubscription( onTorStatusChanged: (status) { setState(() { _status = status; @@ -448,61 +447,6 @@ class _TorButtonState extends ConsumerState { } } -class _TorSubscriptionBase extends ConsumerStatefulWidget { - const _TorSubscriptionBase({ - super.key, - required this.onTorStatusChanged, - this.eventBus, - required this.child, - }); - - final Widget child; - final void Function(TorConnectionStatus) onTorStatusChanged; - final EventBus? eventBus; - - @override - ConsumerState<_TorSubscriptionBase> createState() => - _TorSubscriptionBaseState(); -} - -class _TorSubscriptionBaseState extends ConsumerState<_TorSubscriptionBase> { - /// The global event bus. - late final EventBus eventBus; - - /// Subscription to the TorConnectionStatusChangedEvent. - late StreamSubscription - _torConnectionStatusSubscription; - - @override - void initState() { - // Initialize the global event bus. - eventBus = widget.eventBus ?? GlobalEventBus.instance; - - // Subscribe to the TorConnectionStatusChangedEvent. - _torConnectionStatusSubscription = - eventBus.on().listen( - (event) async { - widget.onTorStatusChanged.call(event.newStatus); - }, - ); - - super.initState(); - } - - @override - void dispose() { - // Clean up the TorConnectionStatusChangedEvent subscription. - _torConnectionStatusSubscription.cancel(); - - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return widget.child; - } -} - /// Connect to the Tor network. /// /// This method is called when the user taps the "Connect" button. diff --git a/lib/pages/wallet_view/wallet_view.dart b/lib/pages/wallet_view/wallet_view.dart index 7e15c6e7d..cf73e8eee 100644 --- a/lib/pages/wallet_view/wallet_view.dart +++ b/lib/pages/wallet_view/wallet_view.dart @@ -29,7 +29,6 @@ import 'package:stackwallet/pages/paynym/paynym_claim_view.dart'; import 'package:stackwallet/pages/paynym/paynym_home_view.dart'; import 'package:stackwallet/pages/receive_view/receive_view.dart'; import 'package:stackwallet/pages/send_view/send_view.dart'; -import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_view.dart'; import 'package:stackwallet/pages/special/firo_rescan_recovery_error_dialog.dart'; @@ -52,7 +51,6 @@ import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_ import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart'; import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; -import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/theme_providers.dart'; @@ -73,6 +71,7 @@ import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; import 'package:stackwallet/widgets/custom_loading_overlay.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/loading_indicator.dart'; +import 'package:stackwallet/widgets/small_tor_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/wallet_navigation_bar/components/icons/buy_nav_icon.dart'; import 'package:stackwallet/widgets/wallet_navigation_bar/components/icons/coin_control_nav_icon.dart'; @@ -554,54 +553,15 @@ class _WalletViewState extends ConsumerState { ], ), actions: [ - Padding( - padding: const EdgeInsets.only( + const Padding( + padding: EdgeInsets.only( top: 10, bottom: 10, right: 10, ), child: AspectRatio( aspectRatio: 1, - child: AppBarIconButton( - semanticsLabel: - "Tor Settings Button. Takes To Tor Settings Page.", - key: const Key("walletsViewTorButton"), - size: 36, - shadows: const [], - color: Theme.of(context) - .extension()! - .backgroundAppBar, - icon: ref.watch(pTorService).enabled - ? ref.read(pTorService).proxyInfo.port == -1 - ? SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context) - .extension()! - .accentColorYellow, - width: 20, - height: 20, - ) - : SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context) - .extension()! - .accentColorGreen, - width: 20, - height: 20, - ) - : SvgPicture.asset( - Assets.svg.tor, - color: Theme.of(context) - .extension()! - .textSubtitle3, - width: 20, - height: 20, - ), - onPressed: () { - Navigator.of(context) - .pushNamed(TorSettingsView.routeName); - }, - ), + child: SmallTorIcon(), ), ), Padding( diff --git a/lib/widgets/small_tor_icon.dart b/lib/widgets/small_tor_icon.dart new file mode 100644 index 000000000..c032fbdae --- /dev/null +++ b/lib/widgets/small_tor_icon.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/tor_service.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/tor_subscription.dart'; + +class SmallTorIcon extends ConsumerStatefulWidget { + const SmallTorIcon({super.key}); + + @override + ConsumerState createState() => _SmallTorIconState(); +} + +class _SmallTorIconState extends ConsumerState { + late TorConnectionStatus _status; + + Color _color( + TorConnectionStatus status, + StackColors colors, + ) { + switch (status) { + case TorConnectionStatus.disconnected: + return colors.textSubtitle3; + + case TorConnectionStatus.connected: + return colors.accentColorGreen; + + case TorConnectionStatus.connecting: + return colors.accentColorYellow; + } + } + + @override + void initState() { + _status = ref.read(pTorService).enabled + ? TorConnectionStatus.connected + : TorConnectionStatus.disconnected; + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return TorSubscription( + onTorStatusChanged: (status) { + setState(() { + _status = status; + }); + }, + child: AppBarIconButton( + semanticsLabel: "Tor Settings Button. Takes To Tor Settings Page.", + key: const Key("walletsViewTorButton"), + size: 36, + shadows: const [], + color: Theme.of(context).extension()!.backgroundAppBar, + icon: SvgPicture.asset( + Assets.svg.tor, + color: _color( + _status, + Theme.of(context).extension()!, + ), + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context).pushNamed(TorSettingsView.routeName); + }, + ), + ); + } +} diff --git a/lib/widgets/tor_subscription.dart b/lib/widgets/tor_subscription.dart new file mode 100644 index 000000000..30904e9f4 --- /dev/null +++ b/lib/widgets/tor_subscription.dart @@ -0,0 +1,61 @@ +import 'dart:async'; + +import 'package:event_bus/event_bus.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; + +class TorSubscription extends ConsumerStatefulWidget { + const TorSubscription({ + super.key, + required this.onTorStatusChanged, + this.eventBus, + required this.child, + }); + + final Widget child; + final void Function(TorConnectionStatus) onTorStatusChanged; + final EventBus? eventBus; + + @override + ConsumerState createState() => _TorSubscriptionBaseState(); +} + +class _TorSubscriptionBaseState extends ConsumerState { + /// The global event bus. + late final EventBus eventBus; + + /// Subscription to the TorConnectionStatusChangedEvent. + late StreamSubscription + _torConnectionStatusSubscription; + + @override + void initState() { + // Initialize the global event bus. + eventBus = widget.eventBus ?? GlobalEventBus.instance; + + // Subscribe to the TorConnectionStatusChangedEvent. + _torConnectionStatusSubscription = + eventBus.on().listen( + (event) async { + widget.onTorStatusChanged.call(event.newStatus); + }, + ); + + super.initState(); + } + + @override + void dispose() { + // Clean up the TorConnectionStatusChangedEvent subscription. + _torConnectionStatusSubscription.cancel(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return widget.child; + } +} From af88673df1e564641c48106cc4fafd5db5868089 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 13 Sep 2023 10:27:21 -0600 Subject: [PATCH 232/237] remove vpn references --- .../global_settings_view/tor_settings/tor_settings_view.dart | 2 +- .../settings/settings_menu/tor_settings/tor_settings.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 9df8cc8bb..30643f605 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -144,7 +144,7 @@ class _TorSettingsViewState extends ConsumerState { title: "What is Tor killswitch?", message: "A security feature that protects your information from accidental exposure by" - " disconnecting your device from the Tor network if your virtual private network (VPN)" + " disconnecting your device from the Tor network if the" " connection is disrupted or compromised.", rightButton: SecondaryButton( label: "Close", diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index 1b18a1ee8..03c1ee841 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -347,7 +347,7 @@ class _TorSettingsState extends ConsumerState { ), Text( "A security feature that protects your information from accidental exposure by" - " disconnecting your device from the Tor network if your virtual private network (VPN)" + " disconnecting your device from the Tor network if the" " connection is disrupted or compromised.", style: STextStyles .desktopTextMedium( From 4b518243c6bb3d71624d9b15c007b24f8f0d9777 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 13 Sep 2023 10:33:44 -0600 Subject: [PATCH 233/237] Tor kill switch getter name refactor and bugfix --- lib/electrumx_rpc/electrumx.dart | 2 +- .../tor_settings/tor_settings_view.dart | 4 ++-- .../tor_settings/tor_settings.dart | 4 ++-- lib/utilities/prefs.dart | 19 ++++++++++++------- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index 7ee8063cd..292679342 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -190,7 +190,7 @@ class ElectrumX { // But Tor isn't enabled... if (!_torService.enabled) { // And the killswitch isn't set... - if (!_prefs.torKillswitch) { + if (!_prefs.torKillSwitch) { // Then we'll just proceed and connect to ElectrumX through clearnet at the bottom of this function. Logging.instance.log( "Tor preference set but Tor is not enabled, killswitch not set, connecting to ElectrumX through clearnet", diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 30643f605..097a68b93 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -170,12 +170,12 @@ class _TorSettingsViewState extends ConsumerState { child: DraggableSwitchButton( isOn: ref.watch( prefsChangeNotifierProvider - .select((value) => value.torKillswitch), + .select((value) => value.torKillSwitch), ), onValueChanged: (newValue) { ref .read(prefsChangeNotifierProvider) - .torKillswitch = newValue; + .torKillSwitch = newValue; }, ), ), diff --git a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart index 03c1ee841..212387035 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/tor_settings/tor_settings.dart @@ -383,12 +383,12 @@ class _TorSettingsState extends ConsumerState { child: DraggableSwitchButton( isOn: ref.watch( prefsChangeNotifierProvider - .select((value) => value.torKillswitch), + .select((value) => value.torKillSwitch), ), onValueChanged: (newValue) { ref .read(prefsChangeNotifierProvider) - .torKillswitch = newValue; + .torKillSwitch = newValue; }, ), ), diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart index 027c6037d..583d9804b 100644 --- a/lib/utilities/prefs.dart +++ b/lib/utilities/prefs.dart @@ -399,14 +399,17 @@ class Prefs extends ChangeNotifier { // tor - bool _torKillswitch = false; + bool _torKillswitch = true; - bool get torKillswitch => _torKillswitch; + bool get torKillSwitch => _torKillswitch; - set torKillswitch(bool torKillswitch) { - if (_torKillswitch != showTestNetCoins) { + set torKillSwitch(bool torKillswitch) { + if (_torKillswitch != torKillswitch) { DB.instance.put( - boxName: DB.boxNamePrefs, key: "torKillswitch", value: torKillswitch); + boxName: DB.boxNamePrefs, + key: "torKillswitch", + value: torKillswitch, + ); _torKillswitch = torKillswitch; notifyListeners(); } @@ -414,8 +417,10 @@ class Prefs extends ChangeNotifier { Future _getTorKillswitch() async { return await DB.instance.get( - boxName: DB.boxNamePrefs, key: "torKillswitch") as bool? ?? - false; + boxName: DB.boxNamePrefs, + key: "torKillswitch", + ) as bool? ?? + true; } // show testnet coins From 62146887689fc1aa3eb808ae1b04e6cae08f59de Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 13 Sep 2023 10:58:02 -0600 Subject: [PATCH 234/237] fix price test and update mocks --- lib/services/price.dart | 3 +- test/cached_electrumx_test.mocks.dart | 8 +- test/electrumx_test.dart | 20 +- test/electrumx_test.mocks.dart | 18 +- .../notification_card_test.mocks.dart | 107 +- .../pages/send_view/send_view_test.mocks.dart | 1279 +++++++-------- test/price_test.dart | 378 ++--- test/price_test.mocks.dart | 219 +-- .../exchange/exchange_view_test.mocks.dart | 8 +- .../favorite_toggle_test.mocks.dart | 107 +- .../custom_loading_overlay_test.mocks.dart | 107 +- .../desktop/desktop_scaffold_test.mocks.dart | 107 +- .../managed_favorite_test.mocks.dart | 1295 +++++++-------- .../node_options_sheet_test.mocks.dart | 18 +- .../table_view/table_view_row_test.mocks.dart | 1289 +++++++-------- test/widget_tests/trade_card_test.mocks.dart | 109 +- .../transaction_card_test.mocks.dart | 1361 ++++++++-------- test/widget_tests/wallet_card_test.mocks.dart | 665 ++++---- .../wallet_info_row_test.mocks.dart | 1403 +++++++++-------- 19 files changed, 4335 insertions(+), 4166 deletions(-) diff --git a/lib/services/price.dart b/lib/services/price.dart index 91e9b1db8..a4ffff961 100644 --- a/lib/services/price.dart +++ b/lib/services/price.dart @@ -33,8 +33,7 @@ class PriceAPI { static const Duration refreshIntervalDuration = Duration(seconds: refreshInterval); - // final Client client; - HTTP client = HTTP(); + final HTTP client; PriceAPI(this.client); diff --git a/test/cached_electrumx_test.mocks.dart b/test/cached_electrumx_test.mocks.dart index 8a40e9349..e44d745d9 100644 --- a/test/cached_electrumx_test.mocks.dart +++ b/test/cached_electrumx_test.mocks.dart @@ -582,14 +582,14 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs { returnValueForMissingStub: null, ); @override - bool get torKillswitch => (super.noSuchMethod( - Invocation.getter(#torKillswitch), + bool get torKillSwitch => (super.noSuchMethod( + Invocation.getter(#torKillSwitch), returnValue: false, ) as bool); @override - set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + set torKillSwitch(bool? torKillswitch) => super.noSuchMethod( Invocation.setter( - #torKillswitch, + #torKillSwitch, torKillswitch, ), returnValueForMissingStub: null, diff --git a/test/electrumx_test.dart b/test/electrumx_test.dart index c71b7549a..0d8bb93d1 100644 --- a/test/electrumx_test.dart +++ b/test/electrumx_test.dart @@ -1524,7 +1524,7 @@ void main() { final mockPrefs = MockPrefs(); when(mockPrefs.useTor).thenAnswer((_) => false); - when(mockPrefs.torKillswitch) + when(mockPrefs.torKillSwitch) .thenAnswer((_) => false); // Or true, shouldn't matter. when(mockPrefs.wifiOnly).thenAnswer((_) => false); final mockTorService = MockTorService(); @@ -1549,7 +1549,7 @@ void main() { verify(mockPrefs.wifiOnly).called(1); verify(mockPrefs.useTor).called(1); - verifyNever(mockPrefs.torKillswitch); + verifyNever(mockPrefs.torKillSwitch); verifyNoMoreInteractions(mockPrefs); verifyNever(mockTorService.enabled); verifyNoMoreInteractions(mockTorService); @@ -1571,7 +1571,7 @@ void main() { final mockPrefs = MockPrefs(); when(mockPrefs.useTor).thenAnswer((_) => true); - when(mockPrefs.torKillswitch).thenAnswer((_) => false); + when(mockPrefs.torKillSwitch).thenAnswer((_) => false); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final mockTorService = MockTorService(); @@ -1599,7 +1599,7 @@ void main() { verify(mockPrefs.wifiOnly).called(1); verify(mockPrefs.useTor).called(1); - verify(mockPrefs.torKillswitch).called(1); + verify(mockPrefs.torKillSwitch).called(1); verifyNoMoreInteractions(mockPrefs); verify(mockTorService.enabled).called(1); verifyNever(mockTorService.proxyInfo); @@ -1624,7 +1624,7 @@ void main() { final mockPrefs = MockPrefs(); when(mockPrefs.useTor).thenAnswer((_) => true); - when(mockPrefs.torKillswitch).thenAnswer((_) => false); // Or true. + when(mockPrefs.torKillSwitch).thenAnswer((_) => false); // Or true. when(mockPrefs.wifiOnly).thenAnswer((_) => false); final mockTorService = MockTorService(); @@ -1651,7 +1651,7 @@ void main() { verify(mockClient.proxyInfo).called(1); verify(mockPrefs.wifiOnly).called(1); verify(mockPrefs.useTor).called(1); - verifyNever(mockPrefs.torKillswitch); + verifyNever(mockPrefs.torKillSwitch); verifyNoMoreInteractions(mockPrefs); verify(mockTorService.enabled).called(1); verify(mockTorService.proxyInfo).called(1); @@ -1682,7 +1682,7 @@ void main() { final mockPrefs = MockPrefs(); when(mockPrefs.useTor).thenAnswer((_) => true); - when(mockPrefs.torKillswitch).thenAnswer((_) => true); + when(mockPrefs.torKillSwitch).thenAnswer((_) => true); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final mockTorService = MockTorService(); when(mockTorService.enabled).thenAnswer((_) => false); @@ -1710,7 +1710,7 @@ void main() { verify(mockPrefs.wifiOnly).called(1); verify(mockPrefs.useTor).called(1); - verify(mockPrefs.torKillswitch).called(1); + verify(mockPrefs.torKillSwitch).called(1); verifyNoMoreInteractions(mockPrefs); verify(mockTorService.enabled).called(1); verifyNoMoreInteractions(mockTorService); @@ -1737,7 +1737,7 @@ void main() { final mockPrefs = MockPrefs(); when(mockPrefs.useTor).thenAnswer((_) => true); - when(mockPrefs.torKillswitch).thenAnswer((_) => false); + when(mockPrefs.torKillSwitch).thenAnswer((_) => false); when(mockPrefs.wifiOnly).thenAnswer((_) => false); final mockTorService = MockTorService(); when(mockTorService.enabled).thenAnswer((_) => false); @@ -1761,7 +1761,7 @@ void main() { verify(mockPrefs.wifiOnly).called(1); verify(mockPrefs.useTor).called(1); - verify(mockPrefs.torKillswitch).called(1); + verify(mockPrefs.torKillSwitch).called(1); verifyNoMoreInteractions(mockPrefs); verify(mockTorService.enabled).called(1); verifyNoMoreInteractions(mockTorService); diff --git a/test/electrumx_test.mocks.dart b/test/electrumx_test.mocks.dart index 3069a2f5f..d77c3e76d 100644 --- a/test/electrumx_test.mocks.dart +++ b/test/electrumx_test.mocks.dart @@ -15,6 +15,7 @@ import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i7; import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i9; import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i6; import 'package:stackwallet/utilities/prefs.dart' as _i5; +import 'package:tor_ffi_plugin/tor_ffi_plugin.dart' as _i12; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -321,14 +322,14 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs { returnValueForMissingStub: null, ); @override - bool get torKillswitch => (super.noSuchMethod( - Invocation.getter(#torKillswitch), + bool get torKillSwitch => (super.noSuchMethod( + Invocation.getter(#torKillSwitch), returnValue: false, ) as bool); @override - set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + set torKillSwitch(bool? torKillswitch) => super.noSuchMethod( Invocation.setter( - #torKillswitch, + #torKillSwitch, torKillswitch, ), returnValueForMissingStub: null, @@ -674,6 +675,15 @@ class MockTorService extends _i1.Mock implements _i11.TorService { ), ) as ({_i3.InternetAddress host, int port})); @override + void init({_i12.Tor? mockableOverride}) => super.noSuchMethod( + Invocation.method( + #init, + [], + {#mockableOverride: mockableOverride}, + ), + returnValueForMissingStub: null, + ); + @override _i4.Future start() => (super.noSuchMethod( Invocation.method( #start, diff --git a/test/notifications/notification_card_test.mocks.dart b/test/notifications/notification_card_test.mocks.dart index 3f1f4b29c..e325b3056 100644 --- a/test/notifications/notification_card_test.mocks.dart +++ b/test/notifications/notification_card_test.mocks.dart @@ -3,13 +3,14 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; -import 'dart:typed_data' as _i6; +import 'dart:async' as _i6; +import 'dart:typed_data' as _i7; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/db/isar/main_db.dart' as _i2; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i4; -import 'package:stackwallet/themes/theme_service.dart' as _i3; +import 'package:stackwallet/db/isar/main_db.dart' as _i3; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i5; +import 'package:stackwallet/networking/http.dart' as _i2; +import 'package:stackwallet/themes/theme_service.dart' as _i4; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -22,8 +23,18 @@ import 'package:stackwallet/themes/theme_service.dart' as _i3; // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class -class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { - _FakeMainDB_0( +class _FakeHTTP_0 extends _i1.SmartFake implements _i2.HTTP { + _FakeHTTP_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMainDB_1 extends _i1.SmartFake implements _i3.MainDB { + _FakeMainDB_1( Object parent, Invocation parentInvocation, ) : super( @@ -35,26 +46,42 @@ class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i3.ThemeService { +class MockThemeService extends _i1.Mock implements _i4.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } @override - _i2.MainDB get db => (super.noSuchMethod( + _i2.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_0( + this, + Invocation.getter(#client), + ), + ) as _i2.HTTP); + @override + set client(_i2.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); + @override + _i3.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_0( + returnValue: _FakeMainDB_1( this, Invocation.getter(#db), ), - ) as _i2.MainDB); + ) as _i3.MainDB); @override - List<_i4.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i5.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i4.StackTheme>[], - ) as List<_i4.StackTheme>); + returnValue: <_i5.StackTheme>[], + ) as List<_i5.StackTheme>); @override - void init(_i2.MainDB? db) => super.noSuchMethod( + void init(_i3.MainDB? db) => super.noSuchMethod( Invocation.method( #init, [db], @@ -62,70 +89,70 @@ class MockThemeService extends _i1.Mock implements _i3.ThemeService { returnValueForMissingStub: null, ); @override - _i5.Future install({required _i6.Uint8List? themeArchiveData}) => + _i6.Future install({required _i7.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future remove({required String? themeId}) => (super.noSuchMethod( + _i6.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i6.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future verifyInstalled({required String? themeId}) => + _i6.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i6.Future.value(false), + ) as _i6.Future); @override - _i5.Future> fetchThemes() => (super.noSuchMethod( + _i6.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i5.Future>.value( - <_i3.StackThemeMetaData>[]), - ) as _i5.Future>); + returnValue: _i6.Future>.value( + <_i4.StackThemeMetaData>[]), + ) as _i6.Future>); @override - _i5.Future<_i6.Uint8List> fetchTheme( - {required _i3.StackThemeMetaData? themeMetaData}) => + _i6.Future<_i7.Uint8List> fetchTheme( + {required _i4.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i5.Future<_i6.Uint8List>.value(_i6.Uint8List(0)), - ) as _i5.Future<_i6.Uint8List>); + returnValue: _i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + ) as _i6.Future<_i7.Uint8List>); @override - _i4.StackTheme? getTheme({required String? themeId}) => + _i5.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i4.StackTheme?); + )) as _i5.StackTheme?); } diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart index 3ebe98c2e..d2d5de661 100644 --- a/test/pages/send_view/send_view_test.mocks.dart +++ b/test/pages/send_view/send_view_test.mocks.dart @@ -3,9 +3,9 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i23; -import 'dart:typed_data' as _i30; -import 'dart:ui' as _i25; +import 'dart:async' as _i24; +import 'dart:typed_data' as _i31; +import 'dart:ui' as _i26; import 'package:bip32/bip32.dart' as _i17; import 'package:bip47/bip47.dart' as _i19; @@ -18,29 +18,30 @@ import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i11; import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i10; import 'package:stackwallet/models/balance.dart' as _i12; import 'package:stackwallet/models/isar/models/isar_models.dart' as _i18; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i33; -import 'package:stackwallet/models/node_model.dart' as _i26; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i34; +import 'package:stackwallet/models/node_model.dart' as _i27; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i9; -import 'package:stackwallet/models/signing_data.dart' as _i29; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i27; -import 'package:stackwallet/services/coins/coin_service.dart' as _i20; +import 'package:stackwallet/models/signing_data.dart' as _i30; +import 'package:stackwallet/networking/http.dart' as _i20; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i28; +import 'package:stackwallet/services/coins/coin_service.dart' as _i21; import 'package:stackwallet/services/coins/manager.dart' as _i6; -import 'package:stackwallet/services/locale_service.dart' as _i31; +import 'package:stackwallet/services/locale_service.dart' as _i32; import 'package:stackwallet/services/node_service.dart' as _i3; import 'package:stackwallet/services/transaction_notification_tracker.dart' as _i8; -import 'package:stackwallet/services/wallets.dart' as _i21; +import 'package:stackwallet/services/wallets.dart' as _i22; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/themes/theme_service.dart' as _i32; +import 'package:stackwallet/themes/theme_service.dart' as _i33; import 'package:stackwallet/utilities/amount/amount.dart' as _i15; -import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i36; -import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i35; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i22; -import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i28; -import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i34; +import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i37; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i36; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i23; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i29; +import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i35; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' as _i7; -import 'package:stackwallet/utilities/prefs.dart' as _i24; +import 'package:stackwallet/utilities/prefs.dart' as _i25; import 'package:tuple/tuple.dart' as _i16; // ignore_for_file: type=lint @@ -241,9 +242,19 @@ class _FakePaymentCode_17 extends _i1.SmartFake implements _i19.PaymentCode { ); } -class _FakeCoinServiceAPI_18 extends _i1.SmartFake - implements _i20.CoinServiceAPI { - _FakeCoinServiceAPI_18( +class _FakeHTTP_18 extends _i1.SmartFake implements _i20.HTTP { + _FakeHTTP_18( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_19 extends _i1.SmartFake + implements _i21.CoinServiceAPI { + _FakeCoinServiceAPI_19( Object parent, Invocation parentInvocation, ) : super( @@ -255,7 +266,7 @@ class _FakeCoinServiceAPI_18 extends _i1.SmartFake /// A class which mocks [Wallets]. /// /// See the documentation for Mockito's code generation for more information. -class MockWallets extends _i1.Mock implements _i21.Wallets { +class MockWallets extends _i1.Mock implements _i22.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -322,7 +333,7 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i22.Coin? coin}) => + List getWalletIdsFor({required _i23.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -332,20 +343,20 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValue: [], ) as List); @override - List<_i16.Tuple2<_i22.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> + List<_i16.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i16.Tuple2<_i22.Coin, + returnValue: <_i16.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>[], ) as List< - _i16.Tuple2<_i22.Coin, + _i16.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i22.Coin? coin) => + _i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -409,17 +420,17 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - _i23.Future load(_i24.Prefs? prefs) => (super.noSuchMethod( + _i24.Future load(_i25.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future loadAfterStackRestore( - _i24.Prefs? prefs, + _i24.Future loadAfterStackRestore( + _i25.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -430,11 +441,11 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { managers, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -442,7 +453,7 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -468,19 +479,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i23.Future> get walletNames => + _i24.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i23.Future>.value( + returnValue: _i24.Future>.value( {}), - ) as _i23.Future>); + ) as _i24.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future renameWallet({ + _i24.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -495,8 +506,8 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override Map fetchWalletsData() => (super.noSuchMethod( Invocation.method( @@ -506,10 +517,10 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValue: {}, ) as Map); @override - _i23.Future addExistingStackWallet({ + _i24.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i22.Coin? coin, + required _i23.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -523,13 +534,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future addNewWallet({ + _i24.Future addNewWallet({ required String? name, - required _i22.Coin? coin, + required _i23.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -542,46 +553,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i24.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future saveFavoriteWalletIds(List? walletIds) => + _i24.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i24.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i24.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future moveFavorite({ + _i24.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -594,48 +605,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i24.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i24.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future isMnemonicVerified({required String? walletId}) => + _i24.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future setMnemonicVerified({required String? walletId}) => + _i24.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future deleteWallet( + _i24.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -647,20 +658,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future refreshWallets(bool? shouldNotifyListeners) => + _i24.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -668,7 +679,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -710,33 +721,33 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ), ) as _i7.SecureStorageInterface); @override - List<_i26.NodeModel> get primaryNodes => (super.noSuchMethod( + List<_i27.NodeModel> get primaryNodes => (super.noSuchMethod( Invocation.getter(#primaryNodes), - returnValue: <_i26.NodeModel>[], - ) as List<_i26.NodeModel>); + returnValue: <_i27.NodeModel>[], + ) as List<_i27.NodeModel>); @override - List<_i26.NodeModel> get nodes => (super.noSuchMethod( + List<_i27.NodeModel> get nodes => (super.noSuchMethod( Invocation.getter(#nodes), - returnValue: <_i26.NodeModel>[], - ) as List<_i26.NodeModel>); + returnValue: <_i27.NodeModel>[], + ) as List<_i27.NodeModel>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future updateDefaults() => (super.noSuchMethod( + _i24.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future setPrimaryNodeFor({ - required _i22.Coin? coin, - required _i26.NodeModel? node, + _i24.Future setPrimaryNodeFor({ + required _i23.Coin? coin, + required _i27.NodeModel? node, bool? shouldNotifyListeners = false, }) => (super.noSuchMethod( @@ -749,44 +760,44 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i26.NodeModel? getPrimaryNodeFor({required _i22.Coin? coin}) => + _i27.NodeModel? getPrimaryNodeFor({required _i23.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getPrimaryNodeFor, [], {#coin: coin}, - )) as _i26.NodeModel?); + )) as _i27.NodeModel?); @override - List<_i26.NodeModel> getNodesFor(_i22.Coin? coin) => (super.noSuchMethod( + List<_i27.NodeModel> getNodesFor(_i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #getNodesFor, [coin], ), - returnValue: <_i26.NodeModel>[], - ) as List<_i26.NodeModel>); + returnValue: <_i27.NodeModel>[], + ) as List<_i27.NodeModel>); @override - _i26.NodeModel? getNodeById({required String? id}) => + _i27.NodeModel? getNodeById({required String? id}) => (super.noSuchMethod(Invocation.method( #getNodeById, [], {#id: id}, - )) as _i26.NodeModel?); + )) as _i27.NodeModel?); @override - List<_i26.NodeModel> failoverNodesFor({required _i22.Coin? coin}) => + List<_i27.NodeModel> failoverNodesFor({required _i23.Coin? coin}) => (super.noSuchMethod( Invocation.method( #failoverNodesFor, [], {#coin: coin}, ), - returnValue: <_i26.NodeModel>[], - ) as List<_i26.NodeModel>); + returnValue: <_i27.NodeModel>[], + ) as List<_i27.NodeModel>); @override - _i23.Future add( - _i26.NodeModel? node, + _i24.Future add( + _i27.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => @@ -799,11 +810,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future delete( + _i24.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -815,11 +826,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future setEnabledState( + _i24.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -833,12 +844,12 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future edit( - _i26.NodeModel? editedNode, + _i24.Future edit( + _i27.NodeModel? editedNode, String? password, bool? shouldNotifyListeners, ) => @@ -851,20 +862,20 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateCommunityNodes() => (super.noSuchMethod( + _i24.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -872,7 +883,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -900,13 +911,13 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { /// A class which mocks [BitcoinWallet]. /// /// See the documentation for Mockito's code generation for more information. -class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i23.Timer? _timer) => super.noSuchMethod( + set timer(_i24.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -983,74 +994,74 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValue: false, ) as bool); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i18.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i18.UTXO>[]), + ) as _i24.Future>); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i18.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i18.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future get currentChangeAddress => (super.noSuchMethod( + _i24.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future get currentChangeAddressP2PKH => (super.noSuchMethod( + _i24.Future get currentChangeAddressP2PKH => (super.noSuchMethod( Invocation.getter(#currentChangeAddressP2PKH), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i23.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i9.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i24.Future<_i9.FeeObject>.value(_FakeFeeObject_6( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i9.FeeObject>); + ) as _i24.Future<_i9.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicString => (super.noSuchMethod( + _i24.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get chainHeight => (super.noSuchMethod( + _i24.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -1122,10 +1133,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { ), ) as _i12.Balance); @override - _i23.Future get xpub => (super.noSuchMethod( + _i24.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -1152,26 +1163,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { ), ) as _i14.NetworkType); @override - _i23.Future exit() => (super.noSuchMethod( + _i24.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i28.DerivePathType addressType({required String? address}) => + _i29.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i28.DerivePathType.bip44, - ) as _i28.DerivePathType); + returnValue: _i29.DerivePathType.bip44, + ) as _i29.DerivePathType); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -1190,47 +1201,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future getTransactionCacheEarly(List? allAddresses) => + _i24.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i24.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future getAllTxsToWatch() => (super.noSuchMethod( + _i24.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, required _i15.Amount? amount, Map? args, @@ -1246,26 +1257,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -1283,35 +1294,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateSentCachedTxData(Map? txData) => + _i24.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1321,70 +1332,70 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValue: false, ) as bool); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i10.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i24.Future<_i10.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), returnValue: - _i23.Future<_i10.ElectrumXNode>.value(_FakeElectrumXNode_12( + _i24.Future<_i10.ElectrumXNode>.value(_FakeElectrumXNode_12( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i23.Future<_i10.ElectrumXNode>); + ) as _i24.Future<_i10.ElectrumXNode>); @override - _i23.Future>> fastFetch( + _i24.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i23.Future>>.value( + returnValue: _i24.Future>>.value( >[]), - ) as _i23.Future>>); + ) as _i24.Future>>); @override - _i23.Future getTxCount({required String? address}) => + _i24.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future checkCurrentReceivingAddressesForTransactions() => + _i24.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkCurrentChangeAddressesForTransactions() => + _i24.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override int estimateTxFee({ required int? vSize, @@ -1427,7 +1438,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { }, )); @override - _i23.Future> fetchBuildTxData( + _i24.Future> fetchBuildTxData( List<_i18.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( @@ -1435,11 +1446,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { [utxosToUse], ), returnValue: - _i23.Future>.value(<_i29.SigningData>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i30.SigningData>[]), + ) as _i24.Future>); @override - _i23.Future> buildTransaction({ - required List<_i29.SigningData>? utxoSigningData, + _i24.Future> buildTransaction({ + required List<_i30.SigningData>? utxoSigningData, required List? recipients, required List? satoshiAmounts, }) => @@ -1454,10 +1465,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1469,11 +1480,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i15.Amount> estimateFeeFor( + _i24.Future<_i15.Amount> estimateFeeFor( _i15.Amount? amount, int? feeRate, ) => @@ -1485,7 +1496,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { feeRate, ], ), - returnValue: _i23.Future<_i15.Amount>.value(_FakeAmount_13( + returnValue: _i24.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -1495,7 +1506,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { ], ), )), - ) as _i23.Future<_i15.Amount>); + ) as _i24.Future<_i15.Amount>); @override _i15.Amount roughFeeEstimate( int? inputCount, @@ -1524,32 +1535,32 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { ), ) as _i15.Amount); @override - _i23.Future<_i15.Amount> sweepAllEstimate(int? feeRate) => + _i24.Future<_i15.Amount> sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i23.Future<_i15.Amount>.value(_FakeAmount_13( + returnValue: _i24.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #sweepAllEstimate, [feeRate], ), )), - ) as _i23.Future<_i15.Amount>); + ) as _i24.Future<_i15.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override void initCache( String? walletId, - _i22.Coin? coin, + _i23.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1562,14 +1573,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future updateCachedId(String? id) => (super.noSuchMethod( + _i24.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1579,14 +1590,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValue: 0, ) as int); @override - _i23.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i24.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1596,15 +1607,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValue: false, ) as bool); @override - _i23.Future updateCachedIsFavorite(bool? isFavorite) => + _i24.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override _i12.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1620,15 +1631,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { ), ) as _i12.Balance); @override - _i23.Future updateCachedBalance(_i12.Balance? balance) => + _i24.Future updateCachedBalance(_i12.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override _i12.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1644,15 +1655,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { ), ) as _i12.Balance); @override - _i23.Future updateCachedBalanceSecondary(_i12.Balance? balance) => + _i24.Future updateCachedBalanceSecondary(_i12.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override List getWalletTokenContractAddresses() => (super.noSuchMethod( Invocation.method( @@ -1662,16 +1673,16 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValue: [], ) as List); @override - _i23.Future updateWalletTokenContractAddresses( + _i24.Future updateWalletTokenContractAddresses( List? contractAddresses) => (super.noSuchMethod( Invocation.method( #updateWalletTokenContractAddresses, [contractAddresses], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override void initWalletDB({_i13.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1682,11 +1693,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>> parseTransaction( + _i24.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>> parseTransaction( Map? txData, dynamic electrumxClient, List<_i18.Address>? myAddresses, - _i22.Coin? coin, + _i23.Coin? coin, int? minConfirms, String? walletId, ) => @@ -1703,7 +1714,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { ], ), returnValue: - _i23.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>>.value( + _i24.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>>.value( _FakeTuple2_14<_i18.Transaction, _i18.Address>( this, Invocation.method( @@ -1718,37 +1729,37 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { ], ), )), - ) as _i23.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>>); + ) as _i24.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>>); @override void initPaynymWalletInterface({ required String? walletId, required String? walletName, required _i14.NetworkType? network, - required _i22.Coin? coin, + required _i23.Coin? coin, required _i13.MainDB? db, required _i10.ElectrumX? electrumXClient, required _i7.SecureStorageInterface? secureStorage, required int? dustLimit, required int? dustLimitP2PKH, required int? minConfirms, - required _i23.Future Function()? getMnemonicString, - required _i23.Future Function()? getMnemonicPassphrase, - required _i23.Future Function()? getChainHeight, - required _i23.Future Function()? getCurrentChangeAddress, + required _i24.Future Function()? getMnemonicString, + required _i24.Future Function()? getMnemonicPassphrase, + required _i24.Future Function()? getChainHeight, + required _i24.Future Function()? getCurrentChangeAddress, required int Function({ required int feeRatePerKB, required int vSize, })? estimateTxFee, - required _i23.Future> Function({ + required _i24.Future> Function({ required String address, required _i15.Amount amount, Map? args, })? prepareSend, - required _i23.Future Function({required String address})? getTxCount, - required _i23.Future> Function(List<_i18.UTXO>)? + required _i24.Future Function({required String address})? getTxCount, + required _i24.Future> Function(List<_i18.UTXO>)? fetchBuildTxData, - required _i23.Future Function()? refresh, - required _i23.Future Function()? checkChangeAddressForTransactions, + required _i24.Future Function()? refresh, + required _i24.Future Function()? checkChangeAddressForTransactions, }) => super.noSuchMethod( Invocation.method( @@ -1781,21 +1792,21 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future<_i17.BIP32> getBip47BaseNode() => (super.noSuchMethod( + _i24.Future<_i17.BIP32> getBip47BaseNode() => (super.noSuchMethod( Invocation.method( #getBip47BaseNode, [], ), - returnValue: _i23.Future<_i17.BIP32>.value(_FakeBIP32_15( + returnValue: _i24.Future<_i17.BIP32>.value(_FakeBIP32_15( this, Invocation.method( #getBip47BaseNode, [], ), )), - ) as _i23.Future<_i17.BIP32>); + ) as _i24.Future<_i17.BIP32>); @override - _i23.Future<_i30.Uint8List> getPrivateKeyForPaynymReceivingAddress({ + _i24.Future<_i31.Uint8List> getPrivateKeyForPaynymReceivingAddress({ required String? paymentCodeString, required int? index, }) => @@ -1808,10 +1819,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { #index: index, }, ), - returnValue: _i23.Future<_i30.Uint8List>.value(_i30.Uint8List(0)), - ) as _i23.Future<_i30.Uint8List>); + returnValue: _i24.Future<_i31.Uint8List>.value(_i31.Uint8List(0)), + ) as _i24.Future<_i31.Uint8List>); @override - _i23.Future<_i18.Address> currentReceivingPaynymAddress({ + _i24.Future<_i18.Address> currentReceivingPaynymAddress({ required _i19.PaymentCode? sender, required bool? isSegwit, }) => @@ -1824,7 +1835,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i23.Future<_i18.Address>.value(_FakeAddress_16( + returnValue: _i24.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #currentReceivingPaynymAddress, @@ -1835,9 +1846,9 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { }, ), )), - ) as _i23.Future<_i18.Address>); + ) as _i24.Future<_i18.Address>); @override - _i23.Future checkCurrentPaynymReceivingAddressForTransactions({ + _i24.Future checkCurrentPaynymReceivingAddressForTransactions({ required _i19.PaymentCode? sender, required bool? isSegwit, }) => @@ -1850,42 +1861,42 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => + _i24.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkAllCurrentReceivingPaynymAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i17.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( + _i24.Future<_i17.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( Invocation.method( #deriveNotificationBip32Node, [], ), - returnValue: _i23.Future<_i17.BIP32>.value(_FakeBIP32_15( + returnValue: _i24.Future<_i17.BIP32>.value(_FakeBIP32_15( this, Invocation.method( #deriveNotificationBip32Node, [], ), )), - ) as _i23.Future<_i17.BIP32>); + ) as _i24.Future<_i17.BIP32>); @override - _i23.Future<_i19.PaymentCode> getPaymentCode({required bool? isSegwit}) => + _i24.Future<_i19.PaymentCode> getPaymentCode({required bool? isSegwit}) => (super.noSuchMethod( Invocation.method( #getPaymentCode, [], {#isSegwit: isSegwit}, ), - returnValue: _i23.Future<_i19.PaymentCode>.value(_FakePaymentCode_17( + returnValue: _i24.Future<_i19.PaymentCode>.value(_FakePaymentCode_17( this, Invocation.method( #getPaymentCode, @@ -1893,27 +1904,27 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { {#isSegwit: isSegwit}, ), )), - ) as _i23.Future<_i19.PaymentCode>); + ) as _i24.Future<_i19.PaymentCode>); @override - _i23.Future<_i30.Uint8List> signWithNotificationKey(_i30.Uint8List? data) => + _i24.Future<_i31.Uint8List> signWithNotificationKey(_i31.Uint8List? data) => (super.noSuchMethod( Invocation.method( #signWithNotificationKey, [data], ), - returnValue: _i23.Future<_i30.Uint8List>.value(_i30.Uint8List(0)), - ) as _i23.Future<_i30.Uint8List>); + returnValue: _i24.Future<_i31.Uint8List>.value(_i31.Uint8List(0)), + ) as _i24.Future<_i31.Uint8List>); @override - _i23.Future signStringWithNotificationKey(String? data) => + _i24.Future signStringWithNotificationKey(String? data) => (super.noSuchMethod( Invocation.method( #signStringWithNotificationKey, [data], ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future> preparePaymentCodeSend({ + _i24.Future> preparePaymentCodeSend({ required _i19.PaymentCode? paymentCode, required bool? isSegwit, required _i15.Amount? amount, @@ -1931,10 +1942,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future<_i18.Address> nextUnusedSendAddressFrom({ + _i24.Future<_i18.Address> nextUnusedSendAddressFrom({ required _i19.PaymentCode? pCode, required bool? isSegwit, required _i17.BIP32? privateKeyNode, @@ -1951,7 +1962,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { #startIndex: startIndex, }, ), - returnValue: _i23.Future<_i18.Address>.value(_FakeAddress_16( + returnValue: _i24.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #nextUnusedSendAddressFrom, @@ -1964,9 +1975,9 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { }, ), )), - ) as _i23.Future<_i18.Address>); + ) as _i24.Future<_i18.Address>); @override - _i23.Future> prepareNotificationTx({ + _i24.Future> prepareNotificationTx({ required int? selectedTxFeeRate, required String? targetPaymentCodeString, int? additionalOutputs = 0, @@ -1984,10 +1995,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future broadcastNotificationTx( + _i24.Future broadcastNotificationTx( {required Map? preparedTx}) => (super.noSuchMethod( Invocation.method( @@ -1995,19 +2006,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { [], {#preparedTx: preparedTx}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future hasConnected(String? paymentCodeString) => + _i24.Future hasConnected(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #hasConnected, [paymentCodeString], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future<_i19.PaymentCode?> unBlindedPaymentCodeFromTransaction( + _i24.Future<_i19.PaymentCode?> unBlindedPaymentCodeFromTransaction( {required _i18.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( @@ -2015,10 +2026,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { [], {#transaction: transaction}, ), - returnValue: _i23.Future<_i19.PaymentCode?>.value(), - ) as _i23.Future<_i19.PaymentCode?>); + returnValue: _i24.Future<_i19.PaymentCode?>.value(), + ) as _i24.Future<_i19.PaymentCode?>); @override - _i23.Future<_i19.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( + _i24.Future<_i19.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( {required _i18.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( @@ -2026,31 +2037,31 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { [], {#transaction: transaction}, ), - returnValue: _i23.Future<_i19.PaymentCode?>.value(), - ) as _i23.Future<_i19.PaymentCode?>); + returnValue: _i24.Future<_i19.PaymentCode?>.value(), + ) as _i24.Future<_i19.PaymentCode?>); @override - _i23.Future> + _i24.Future> getAllPaymentCodesFromNotificationTransactions() => (super.noSuchMethod( Invocation.method( #getAllPaymentCodesFromNotificationTransactions, [], ), returnValue: - _i23.Future>.value(<_i19.PaymentCode>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i19.PaymentCode>[]), + ) as _i24.Future>); @override - _i23.Future checkForNotificationTransactionsTo( + _i24.Future checkForNotificationTransactionsTo( Set? otherCodeStrings) => (super.noSuchMethod( Invocation.method( #checkForNotificationTransactionsTo, [otherCodeStrings], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future restoreAllHistory({ + _i24.Future restoreAllHistory({ required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, required Set? paymentCodeStrings, @@ -2065,11 +2076,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { #paymentCodeStrings: paymentCodeStrings, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future restoreHistoryWith({ + _i24.Future restoreHistoryWith({ required _i19.PaymentCode? other, required bool? checkSegwitAsWell, required int? maxUnusedAddressGap, @@ -2086,58 +2097,58 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { #maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i18.Address> getMyNotificationAddress() => (super.noSuchMethod( + _i24.Future<_i18.Address> getMyNotificationAddress() => (super.noSuchMethod( Invocation.method( #getMyNotificationAddress, [], ), - returnValue: _i23.Future<_i18.Address>.value(_FakeAddress_16( + returnValue: _i24.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #getMyNotificationAddress, [], ), )), - ) as _i23.Future<_i18.Address>); + ) as _i24.Future<_i18.Address>); @override - _i23.Future> lookupKey(String? paymentCodeString) => + _i24.Future> lookupKey(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #lookupKey, [paymentCodeString], ), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future paymentCodeStringByKey(String? key) => + _i24.Future paymentCodeStringByKey(String? key) => (super.noSuchMethod( Invocation.method( #paymentCodeStringByKey, [key], ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future storeCode(String? paymentCodeString) => + _i24.Future storeCode(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #storeCode, [paymentCodeString], ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override void initCoinControlInterface({ required String? walletId, required String? walletName, - required _i22.Coin? coin, + required _i23.Coin? coin, required _i13.MainDB? db, - required _i23.Future Function()? getChainHeight, - required _i23.Future Function(_i12.Balance)? refreshedBalanceCallback, + required _i24.Future Function()? getChainHeight, + required _i24.Future Function(_i12.Balance)? refreshedBalanceCallback, }) => super.noSuchMethod( Invocation.method( @@ -2155,22 +2166,22 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future refreshBalance({bool? notify = false}) => + _i24.Future refreshBalance({bool? notify = false}) => (super.noSuchMethod( Invocation.method( #refreshBalance, [], {#notify: notify}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); } /// A class which mocks [LocaleService]. /// /// See the documentation for Mockito's code generation for more information. -class MockLocaleService extends _i1.Mock implements _i31.LocaleService { +class MockLocaleService extends _i1.Mock implements _i32.LocaleService { MockLocaleService() { _i1.throwOnMissingStub(this); } @@ -2186,17 +2197,17 @@ class MockLocaleService extends _i1.Mock implements _i31.LocaleService { returnValue: false, ) as bool); @override - _i23.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( + _i24.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( Invocation.method( #loadLocale, [], {#notify: notify}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2204,7 +2215,7 @@ class MockLocaleService extends _i1.Mock implements _i31.LocaleService { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2232,11 +2243,27 @@ class MockLocaleService extends _i1.Mock implements _i31.LocaleService { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i32.ThemeService { +class MockThemeService extends _i1.Mock implements _i33.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } + @override + _i20.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_18( + this, + Invocation.getter(#client), + ), + ) as _i20.HTTP); + @override + set client(_i20.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); @override _i13.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), @@ -2246,10 +2273,10 @@ class MockThemeService extends _i1.Mock implements _i32.ThemeService { ), ) as _i13.MainDB); @override - List<_i33.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i34.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i33.StackTheme>[], - ) as List<_i33.StackTheme>); + returnValue: <_i34.StackTheme>[], + ) as List<_i34.StackTheme>); @override void init(_i13.MainDB? db) => super.noSuchMethod( Invocation.method( @@ -2259,79 +2286,79 @@ class MockThemeService extends _i1.Mock implements _i32.ThemeService { returnValueForMissingStub: null, ); @override - _i23.Future install({required _i30.Uint8List? themeArchiveData}) => + _i24.Future install({required _i31.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future remove({required String? themeId}) => (super.noSuchMethod( + _i24.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i24.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future verifyInstalled({required String? themeId}) => + _i24.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future> fetchThemes() => + _i24.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i23.Future>.value( - <_i32.StackThemeMetaData>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value( + <_i33.StackThemeMetaData>[]), + ) as _i24.Future>); @override - _i23.Future<_i30.Uint8List> fetchTheme( - {required _i32.StackThemeMetaData? themeMetaData}) => + _i24.Future<_i31.Uint8List> fetchTheme( + {required _i33.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i23.Future<_i30.Uint8List>.value(_i30.Uint8List(0)), - ) as _i23.Future<_i30.Uint8List>); + returnValue: _i24.Future<_i31.Uint8List>.value(_i31.Uint8List(0)), + ) as _i24.Future<_i31.Uint8List>); @override - _i33.StackTheme? getTheme({required String? themeId}) => + _i34.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i33.StackTheme?); + )) as _i34.StackTheme?); } /// A class which mocks [Prefs]. /// /// See the documentation for Mockito's code generation for more information. -class MockPrefs extends _i1.Mock implements _i24.Prefs { +class MockPrefs extends _i1.Mock implements _i25.Prefs { MockPrefs() { _i1.throwOnMissingStub(this); } @@ -2387,12 +2414,12 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - _i34.SyncingType get syncType => (super.noSuchMethod( + _i35.SyncingType get syncType => (super.noSuchMethod( Invocation.getter(#syncType), - returnValue: _i34.SyncingType.currentWalletOnly, - ) as _i34.SyncingType); + returnValue: _i35.SyncingType.currentWalletOnly, + ) as _i35.SyncingType); @override - set syncType(_i34.SyncingType? syncType) => super.noSuchMethod( + set syncType(_i35.SyncingType? syncType) => super.noSuchMethod( Invocation.setter( #syncType, syncType, @@ -2504,14 +2531,14 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - bool get torKillswitch => (super.noSuchMethod( - Invocation.getter(#torKillswitch), + bool get torKillSwitch => (super.noSuchMethod( + Invocation.getter(#torKillSwitch), returnValue: false, ) as bool); @override - set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + set torKillSwitch(bool? torKillswitch) => super.noSuchMethod( Invocation.setter( - #torKillswitch, + #torKillSwitch, torKillswitch, ), returnValueForMissingStub: null, @@ -2551,12 +2578,12 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - _i35.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( + _i36.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( Invocation.getter(#backupFrequencyType), - returnValue: _i35.BackupFrequencyType.everyTenMinutes, - ) as _i35.BackupFrequencyType); + returnValue: _i36.BackupFrequencyType.everyTenMinutes, + ) as _i36.BackupFrequencyType); @override - set backupFrequencyType(_i35.BackupFrequencyType? backupFrequencyType) => + set backupFrequencyType(_i36.BackupFrequencyType? backupFrequencyType) => super.noSuchMethod( Invocation.setter( #backupFrequencyType, @@ -2707,61 +2734,61 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValue: false, ) as bool); @override - _i23.Future init() => (super.noSuchMethod( + _i24.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( + _i24.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( Invocation.method( #incrementCurrentNotificationIndex, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future isExternalCallsSet() => (super.noSuchMethod( + _i24.Future isExternalCallsSet() => (super.noSuchMethod( Invocation.method( #isExternalCallsSet, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future saveUserID(String? userId) => (super.noSuchMethod( + _i24.Future saveUserID(String? userId) => (super.noSuchMethod( Invocation.method( #saveUserID, [userId], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( + _i24.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( Invocation.method( #saveSignupEpoch, [signupEpoch], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i36.AmountUnit amountUnit(_i22.Coin? coin) => (super.noSuchMethod( + _i37.AmountUnit amountUnit(_i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #amountUnit, [coin], ), - returnValue: _i36.AmountUnit.normal, - ) as _i36.AmountUnit); + returnValue: _i37.AmountUnit.normal, + ) as _i37.AmountUnit); @override void updateAmountUnit({ - required _i22.Coin? coin, - required _i36.AmountUnit? amountUnit, + required _i23.Coin? coin, + required _i37.AmountUnit? amountUnit, }) => super.noSuchMethod( Invocation.method( @@ -2775,7 +2802,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - int maxDecimals(_i22.Coin? coin) => (super.noSuchMethod( + int maxDecimals(_i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #maxDecimals, [coin], @@ -2784,7 +2811,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { ) as int); @override void updateMaxDecimals({ - required _i22.Coin? coin, + required _i23.Coin? coin, required int? maxDecimals, }) => super.noSuchMethod( @@ -2799,7 +2826,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2807,7 +2834,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2850,23 +2877,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i20.CoinServiceAPI get wallet => (super.noSuchMethod( + _i21.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_18( + returnValue: _FakeCoinServiceAPI_19( this, Invocation.getter(#wallet), ), - ) as _i20.CoinServiceAPI); + ) as _i21.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -2899,23 +2926,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i23.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i9.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i24.Future<_i9.FeeObject>.value(_FakeFeeObject_6( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i9.FeeObject>); + ) as _i24.Future<_i9.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override _i12.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -2925,16 +2952,16 @@ class MockManager extends _i1.Mock implements _i6.Manager { ), ) as _i12.Balance); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i18.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i18.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i18.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i18.UTXO>[]), + ) as _i24.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2954,15 +2981,15 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -3009,24 +3036,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i23.Future get xpub => (super.noSuchMethod( + _i24.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -3036,7 +3063,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, required _i15.Amount? amount, Map? args, @@ -3052,27 +3079,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -3082,35 +3109,35 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -3129,20 +3156,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future exitCurrentWallet() => (super.noSuchMethod( + _i24.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -3154,11 +3181,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i15.Amount> estimateFeeFor( + _i24.Future<_i15.Amount> estimateFeeFor( _i15.Amount? amount, int? feeRate, ) => @@ -3170,7 +3197,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i23.Future<_i15.Amount>.value(_FakeAmount_13( + returnValue: _i24.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -3180,26 +3207,26 @@ class MockManager extends _i1.Mock implements _i6.Manager { ], ), )), - ) as _i23.Future<_i15.Amount>); + ) as _i24.Future<_i15.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future resetRescanOnOpen() => (super.noSuchMethod( + _i24.Future resetRescanOnOpen() => (super.noSuchMethod( Invocation.method( #resetRescanOnOpen, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -3207,7 +3234,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -3227,7 +3254,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { /// A class which mocks [CoinServiceAPI]. /// /// See the documentation for Mockito's code generation for more information. -class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i21.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -3238,10 +3265,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -3274,23 +3301,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i23.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i9.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i24.Future<_i9.FeeObject>.value(_FakeFeeObject_6( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i9.FeeObject>); + ) as _i24.Future<_i9.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override _i12.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -3300,16 +3327,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { ), ) as _i12.Balance); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i18.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i18.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i18.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i18.UTXO>[]), + ) as _i24.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -3329,20 +3356,20 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: '', ) as String); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicString => (super.noSuchMethod( + _i24.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -3359,7 +3386,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: 0, ) as int); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, required _i15.Amount? amount, Map? args, @@ -3375,36 +3402,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -3414,15 +3441,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: false, ) as bool); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -3441,40 +3468,40 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future exit() => (super.noSuchMethod( + _i24.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -3486,11 +3513,11 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i15.Amount> estimateFeeFor( + _i24.Future<_i15.Amount> estimateFeeFor( _i15.Amount? amount, int? feeRate, ) => @@ -3502,7 +3529,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { feeRate, ], ), - returnValue: _i23.Future<_i15.Amount>.value(_FakeAmount_13( + returnValue: _i24.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -3512,23 +3539,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { ], ), )), - ) as _i23.Future<_i15.Amount>); + ) as _i24.Future<_i15.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future updateSentCachedTxData(Map? txData) => + _i24.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); } diff --git a/test/price_test.dart b/test/price_test.dart index e5383bef8..dc7aaeb9e 100644 --- a/test/price_test.dart +++ b/test/price_test.dart @@ -1,17 +1,18 @@ +import 'dart:convert'; import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:hive/hive.dart'; import 'package:hive_test/hive_test.dart'; -import 'package:http/http.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:stackwallet/db/hive/db.dart'; +import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/price.dart'; import 'price_test.mocks.dart'; -@GenerateMocks([Client]) +@GenerateMocks([HTTP]) void main() { setUp(() async { await setUpTestHive(); @@ -22,10 +23,11 @@ void main() { }); test("getPricesAnd24hChange fetch", () async { - final client = MockClient(); + final client = MockHTTP(); when(client.get( - Uri.parse( + proxyInfo: null, + url: Uri.parse( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids" "=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin,bitcoin-cash" ",namecoin,wownero,ethereum,particl,nano,banano,stellar,tezos" @@ -34,63 +36,64 @@ void main() { headers: { 'Content-Type': 'application/json' })).thenAnswer((_) async => Response( - '[{"id":"bitcoin","symbol":"btc","name":"Bitcoin","image":"https://asse' - 'ts.coingecko.com/coins/images/1/large/bitcoin.png?1547033579","curr' - 'ent_price":1.0,"market_cap":19128800,"market_cap_rank":1,"fully_dil' - 'uted_valuation":21000000,"total_volume":1272132,"high_24h":1.0,"low' - '_24h":1.0,"price_change_24h":0.0,"price_change_percentage_24h":0.0,' - '"market_cap_change_24h":950.0,"market_cap_change_percentage_24h":0.0' - '0497,"circulating_supply":19128800.0,"total_supply":21000000.0,"max' - '_supply":21000000.0,"ath":1.003301,"ath_change_percentage":-0.32896' - ',"ath_date":"2019-10-15T16:00:56.136Z","atl":0.99895134,"atl_change_' - 'percentage":0.10498,"atl_date":"2019-10-21T00:00:00.000Z","roi":nul' - 'l,"last_updated":"2022-08-22T16:37:59.237Z"},{"id":"dogecoin","symb' - 'ol":"doge","name":"Dogecoin","image":"https://assets.coingecko.com/' - 'coins/images/5/large/dogecoin.png?1547792256","current_price":3.15e' - '-06,"market_cap":417916,"market_cap_rank":10,"fully_diluted_valuati' - 'on":null,"total_volume":27498,"high_24h":3.26e-06,"low_24h":3.13e-0' - '6,"price_change_24h":-8.6889947714e-08,"price_change_percentage_24h' - '":-2.68533,"market_cap_change_24h":-11370.894861206936,"market_cap_c' - 'hange_percentage_24h":-2.64879,"circulating_supply":132670764299.89' - '4,"total_supply":null,"max_supply":null,"ath":1.264e-05,"ath_change' - '_percentage":-75.05046,"ath_date":"2021-05-07T23:04:53.026Z","atl":' - '1.50936e-07,"atl_change_percentage":1989.69346,"atl_date":"2020-12-' - '17T09:18:05.654Z","roi":null,"last_updated":"2022-08-22T16:38:15.11' - '3Z"},{"id":"monero","symbol":"xmr","name":"Monero","image":"https:/' - '/assets.coingecko.com/coins/images/69/large/monero_logo.png?1547033' - '729","current_price":0.00717236,"market_cap":130002,"market_cap_ran' - 'k":29,"fully_diluted_valuation":null,"total_volume":4901,"high_24h":' - '0.00731999,"low_24h":0.00707511,"price_change_24h":-5.6133543212467' - 'e-05,"price_change_percentage_24h":-0.77656,"market_cap_change_24h"' - ':-1007.8447677436197,"market_cap_change_percentage_24h":-0.76929,"c' - 'irculating_supply":18147820.3764146,"total_supply":null,"max_supply' - '":null,"ath":0.03475393,"ath_change_percentage":-79.32037,"ath_date' - '":"2018-01-09T00:00:00.000Z","atl":0.00101492,"atl_change_percentag' - 'e":608.13327,"atl_date":"2014-12-18T00:00:00.000Z","roi":null,"las' - 't_updated":"2022-08-22T16:38:26.347Z"},{"id":"zcoin","symbol":"firo' - '","name":"Firo","image":"https://assets.coingecko.com/coins/images/' - '479/large/firocoingecko.png?1636537544","current_price":0.0001096,"' - 'market_cap":1252,"market_cap_rank":604,"fully_diluted_valuation":234' - '9,"total_volume":90.573,"high_24h":0.00011148,"low_24h":0.00010834,' - '"price_change_24h":-9.87561775002e-07,"price_change_percentage_24h' - '":-0.89304,"market_cap_change_24h":-10.046635178462793,"market_cap_' - 'change_percentage_24h":-0.79578,"circulating_supply":11411043.83546' - '97,"total_supply":21400000.0,"max_supply":21400000.0,"ath":0.016162' - '72,"ath_change_percentage":-99.3208,"ath_date":"2018-04-04T16:04:48.' - '408Z","atl":4.268e-05,"atl_change_percentage":157.22799,"atl_date":"' - '2022-05-12T07:28:47.088Z","roi":null,"last_updated":"2022-08-22T16' - ':38:47.229Z"},{"id":"epic-cash","symbol":"epic","name":"Epic Cash",' - '"image":"https://assets.coingecko.com/coins/images/9520/large/Epic_C' - 'oin_NO_drop_shadow.png?1620122642","current_price":2.803e-05,"marke' - 't_cap":415.109,"market_cap_rank":953,"fully_diluted_valuation":null' - ',"total_volume":0.2371557,"high_24h":3.053e-05,"low_24h":2.581e-05' - ',"price_change_24h":1.9e-06,"price_change_percentage_24h":7.27524,"' - 'market_cap_change_24h":28.26753,"market_cap_change_percentage_24h":' - '7.30726,"circulating_supply":14808052.0,"total_supply":21000000.0,"' - 'max_supply":null,"ath":0.00013848,"ath_change_percentage":-79.75864' - ',"ath_date":"2021-12-11T08:39:41.129Z","atl":5.74028e-07,"atl_chang' - 'e_percentage":4783.08078,"atl_date":"2020-03-13T16:55:01.177Z","roi' - '":null,"last_updated":"2022-08-22T16:38:32.826Z"}]', + utf8.encode( + '[{"id":"bitcoin","symbol":"btc","name":"Bitcoin","image":"https://asse' + 'ts.coingecko.com/coins/images/1/large/bitcoin.png?1547033579","curr' + 'ent_price":1.0,"market_cap":19128800,"market_cap_rank":1,"fully_dil' + 'uted_valuation":21000000,"total_volume":1272132,"high_24h":1.0,"low' + '_24h":1.0,"price_change_24h":0.0,"price_change_percentage_24h":0.0,' + '"market_cap_change_24h":950.0,"market_cap_change_percentage_24h":0.0' + '0497,"circulating_supply":19128800.0,"total_supply":21000000.0,"max' + '_supply":21000000.0,"ath":1.003301,"ath_change_percentage":-0.32896' + ',"ath_date":"2019-10-15T16:00:56.136Z","atl":0.99895134,"atl_change_' + 'percentage":0.10498,"atl_date":"2019-10-21T00:00:00.000Z","roi":nul' + 'l,"last_updated":"2022-08-22T16:37:59.237Z"},{"id":"dogecoin","symb' + 'ol":"doge","name":"Dogecoin","image":"https://assets.coingecko.com/' + 'coins/images/5/large/dogecoin.png?1547792256","current_price":3.15e' + '-06,"market_cap":417916,"market_cap_rank":10,"fully_diluted_valuati' + 'on":null,"total_volume":27498,"high_24h":3.26e-06,"low_24h":3.13e-0' + '6,"price_change_24h":-8.6889947714e-08,"price_change_percentage_24h' + '":-2.68533,"market_cap_change_24h":-11370.894861206936,"market_cap_c' + 'hange_percentage_24h":-2.64879,"circulating_supply":132670764299.89' + '4,"total_supply":null,"max_supply":null,"ath":1.264e-05,"ath_change' + '_percentage":-75.05046,"ath_date":"2021-05-07T23:04:53.026Z","atl":' + '1.50936e-07,"atl_change_percentage":1989.69346,"atl_date":"2020-12-' + '17T09:18:05.654Z","roi":null,"last_updated":"2022-08-22T16:38:15.11' + '3Z"},{"id":"monero","symbol":"xmr","name":"Monero","image":"https:/' + '/assets.coingecko.com/coins/images/69/large/monero_logo.png?1547033' + '729","current_price":0.00717236,"market_cap":130002,"market_cap_ran' + 'k":29,"fully_diluted_valuation":null,"total_volume":4901,"high_24h":' + '0.00731999,"low_24h":0.00707511,"price_change_24h":-5.6133543212467' + 'e-05,"price_change_percentage_24h":-0.77656,"market_cap_change_24h"' + ':-1007.8447677436197,"market_cap_change_percentage_24h":-0.76929,"c' + 'irculating_supply":18147820.3764146,"total_supply":null,"max_supply' + '":null,"ath":0.03475393,"ath_change_percentage":-79.32037,"ath_date' + '":"2018-01-09T00:00:00.000Z","atl":0.00101492,"atl_change_percentag' + 'e":608.13327,"atl_date":"2014-12-18T00:00:00.000Z","roi":null,"las' + 't_updated":"2022-08-22T16:38:26.347Z"},{"id":"zcoin","symbol":"firo' + '","name":"Firo","image":"https://assets.coingecko.com/coins/images/' + '479/large/firocoingecko.png?1636537544","current_price":0.0001096,"' + 'market_cap":1252,"market_cap_rank":604,"fully_diluted_valuation":234' + '9,"total_volume":90.573,"high_24h":0.00011148,"low_24h":0.00010834,' + '"price_change_24h":-9.87561775002e-07,"price_change_percentage_24h' + '":-0.89304,"market_cap_change_24h":-10.046635178462793,"market_cap_' + 'change_percentage_24h":-0.79578,"circulating_supply":11411043.83546' + '97,"total_supply":21400000.0,"max_supply":21400000.0,"ath":0.016162' + '72,"ath_change_percentage":-99.3208,"ath_date":"2018-04-04T16:04:48.' + '408Z","atl":4.268e-05,"atl_change_percentage":157.22799,"atl_date":"' + '2022-05-12T07:28:47.088Z","roi":null,"last_updated":"2022-08-22T16' + ':38:47.229Z"},{"id":"epic-cash","symbol":"epic","name":"Epic Cash",' + '"image":"https://assets.coingecko.com/coins/images/9520/large/Epic_C' + 'oin_NO_drop_shadow.png?1620122642","current_price":2.803e-05,"marke' + 't_cap":415.109,"market_cap_rank":953,"fully_diluted_valuation":null' + ',"total_volume":0.2371557,"high_24h":3.053e-05,"low_24h":2.581e-05' + ',"price_change_24h":1.9e-06,"price_change_percentage_24h":7.27524,"' + 'market_cap_change_24h":28.26753,"market_cap_change_percentage_24h":' + '7.30726,"circulating_supply":14808052.0,"total_supply":21000000.0,"' + 'max_supply":null,"ath":0.00013848,"ath_change_percentage":-79.75864' + ',"ath_date":"2021-12-11T08:39:41.129Z","atl":5.74028e-07,"atl_chang' + 'e_percentage":4783.08078,"atl_date":"2020-03-13T16:55:01.177Z","roi' + '":null,"last_updated":"2022-08-22T16:38:32.826Z"}]'), 200)); final priceAPI = PriceAPI(client); @@ -126,7 +129,8 @@ void main() { '}', ); verify(client.get( - Uri.parse( + proxyInfo: null, + url: Uri.parse( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc" "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" @@ -139,10 +143,11 @@ void main() { }); test("cached price fetch", () async { - final client = MockClient(); + final client = MockHTTP(); when(client.get( - Uri.parse( + proxyInfo: null, + url: Uri.parse( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&" "ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" @@ -151,63 +156,64 @@ void main() { headers: { 'Content-Type': 'application/json' })).thenAnswer((_) async => Response( - '[{"id":"bitcoin","symbol":"btc","name":"Bitcoin","image":"https://a' - 'ssets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579","c' - 'urrent_price":1.0,"market_cap":19128800,"market_cap_rank":1,"fully_' - 'diluted_valuation":21000000,"total_volume":1272132,"high_24h":1.0,"' - 'low_24h":1.0,"price_change_24h":0.0,"price_change_percentage_24h":0' - '.0,"market_cap_change_24h":950.0,"market_cap_change_percentage_24h"' - ':0.00497,"circulating_supply":19128800.0,"total_supply":21000000.0,"' - 'max_supply":21000000.0,"ath":1.003301,"ath_change_percentage":-0.32' - '896,"ath_date":"2019-10-15T16:00:56.136Z","atl":0.99895134,"atl_cha' - 'nge_percentage":0.10498,"atl_date":"2019-10-21T00:00:00.000Z","roi"' - ':null,"last_updated":"2022-08-22T16:37:59.237Z"},{"id":"dogecoin","' - 'symbol":"doge","name":"Dogecoin","image":"https://assets.coingecko.' - 'com/coins/images/5/large/dogecoin.png?1547792256","current_price":3' - '.15e-06,"market_cap":417916,"market_cap_rank":10,"fully_diluted_val' - 'uation":null,"total_volume":27498,"high_24h":3.26e-06,"low_24h":3.1' - '3e-06,"price_change_24h":-8.6889947714e-08,"price_change_percentage' - '_24h":-2.68533,"market_cap_change_24h":-11370.894861206936,"market_' - 'cap_change_percentage_24h":-2.64879,"circulating_supply":1326707642' - '99.894,"total_supply":null,"max_supply":null,"ath":1.264e-05,"ath_c' - 'hange_percentage":-75.05046,"ath_date":"2021-05-07T23:04:53.026Z","' - 'atl":1.50936e-07,"atl_change_percentage":1989.69346,"atl_date":"202' - '0-12-17T09:18:05.654Z","roi":null,"last_updated":"2022-08-22T16:38:' - '15.113Z"},{"id":"monero","symbol":"xmr","name":"Monero","image":"ht' - 'tps://assets.coingecko.com/coins/images/69/large/monero_logo.png?15' - '47033729","current_price":0.00717236,"market_cap":130002,"market_cap' - '_rank":29,"fully_diluted_valuation":null,"total_volume":4901,"high' - '_24h":0.00731999,"low_24h":0.00707511,"price_change_24h":-5.613354' - '3212467e-05,"price_change_percentage_24h":-0.77656,"market_cap_chan' - 'ge_24h":-1007.8447677436197,"market_cap_change_percentage_24h":-0.7' - '6929,"circulating_supply":18147820.3764146,"total_supply":null,"ma' - 'x_supply":null,"ath":0.03475393,"ath_change_percentage":-79.32037,"' - 'ath_date":"2018-01-09T00:00:00.000Z","atl":0.00101492,"atl_change_' - 'percentage":608.13327,"atl_date":"2014-12-18T00:00:00.000Z","roi":n' - 'ull,"last_updated":"2022-08-22T16:38:26.347Z"},{"id":"zcoin","symbo' - 'l":"firo","name":"Firo","image":"https://assets.coingecko.com/coins' - '/images/479/large/firocoingecko.png?1636537544","current_price":0.0' - '001096,"market_cap":1252,"market_cap_rank":604,"fully_diluted_valu' - 'ation":2349,"total_volume":90.573,"high_24h":0.00011148,"low_24h":0' - '.00010834,"price_change_24h":-9.87561775002e-07,"price_change_perce' - 'ntage_24h":-0.89304,"market_cap_change_24h":-10.046635178462793,"ma' - 'rket_cap_change_percentage_24h":-0.79578,"circulating_supply":11411' - '043.8354697,"total_supply":21400000.0,"max_supply":21400000.0,"ath"' - ':0.01616272,"ath_change_percentage":-99.3208,"ath_date":"2018-04-04' - 'T16:04:48.408Z","atl":4.268e-05,"atl_change_percentage":157.22799,' - '"atl_date":"2022-05-12T07:28:47.088Z","roi":null,"last_updated":"2' - '022-08-22T16:38:47.229Z"},{"id":"epic-cash","symbol":"epic","name":"' - 'Epic Cash","image":"https://assets.coingecko.com/coins/images/9520/' - 'large/Epic_Coin_NO_drop_shadow.png?1620122642","current_price":2.80' - '3e-05,"market_cap":415.109,"market_cap_rank":953,"fully_diluted_val' - 'uation":null,"total_volume":0.2371557,"high_24h":3.053e-05,"low_24h' - '":2.581e-05,"price_change_24h":1.9e-06,"price_change_percentage_24' - 'h":7.27524,"market_cap_change_24h":28.26753,"market_cap_change_perc' - 'entage_24h":7.30726,"circulating_supply":14808052.0,"total_supply":' - '21000000.0,"max_supply":null,"ath":0.00013848,"ath_change_percentag' - 'e":-79.75864,"ath_date":"2021-12-11T08:39:41.129Z","atl":5.74028e-0' - '7,"atl_change_percentage":4783.08078,"atl_date":"2020-03-13T16:55:01' - '.177Z","roi":null,"last_updated":"2022-08-22T16:38:32.826Z"}]', + utf8.encode( + '[{"id":"bitcoin","symbol":"btc","name":"Bitcoin","image":"https://a' + 'ssets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579","c' + 'urrent_price":1.0,"market_cap":19128800,"market_cap_rank":1,"fully_' + 'diluted_valuation":21000000,"total_volume":1272132,"high_24h":1.0,"' + 'low_24h":1.0,"price_change_24h":0.0,"price_change_percentage_24h":0' + '.0,"market_cap_change_24h":950.0,"market_cap_change_percentage_24h"' + ':0.00497,"circulating_supply":19128800.0,"total_supply":21000000.0,"' + 'max_supply":21000000.0,"ath":1.003301,"ath_change_percentage":-0.32' + '896,"ath_date":"2019-10-15T16:00:56.136Z","atl":0.99895134,"atl_cha' + 'nge_percentage":0.10498,"atl_date":"2019-10-21T00:00:00.000Z","roi"' + ':null,"last_updated":"2022-08-22T16:37:59.237Z"},{"id":"dogecoin","' + 'symbol":"doge","name":"Dogecoin","image":"https://assets.coingecko.' + 'com/coins/images/5/large/dogecoin.png?1547792256","current_price":3' + '.15e-06,"market_cap":417916,"market_cap_rank":10,"fully_diluted_val' + 'uation":null,"total_volume":27498,"high_24h":3.26e-06,"low_24h":3.1' + '3e-06,"price_change_24h":-8.6889947714e-08,"price_change_percentage' + '_24h":-2.68533,"market_cap_change_24h":-11370.894861206936,"market_' + 'cap_change_percentage_24h":-2.64879,"circulating_supply":1326707642' + '99.894,"total_supply":null,"max_supply":null,"ath":1.264e-05,"ath_c' + 'hange_percentage":-75.05046,"ath_date":"2021-05-07T23:04:53.026Z","' + 'atl":1.50936e-07,"atl_change_percentage":1989.69346,"atl_date":"202' + '0-12-17T09:18:05.654Z","roi":null,"last_updated":"2022-08-22T16:38:' + '15.113Z"},{"id":"monero","symbol":"xmr","name":"Monero","image":"ht' + 'tps://assets.coingecko.com/coins/images/69/large/monero_logo.png?15' + '47033729","current_price":0.00717236,"market_cap":130002,"market_cap' + '_rank":29,"fully_diluted_valuation":null,"total_volume":4901,"high' + '_24h":0.00731999,"low_24h":0.00707511,"price_change_24h":-5.613354' + '3212467e-05,"price_change_percentage_24h":-0.77656,"market_cap_chan' + 'ge_24h":-1007.8447677436197,"market_cap_change_percentage_24h":-0.7' + '6929,"circulating_supply":18147820.3764146,"total_supply":null,"ma' + 'x_supply":null,"ath":0.03475393,"ath_change_percentage":-79.32037,"' + 'ath_date":"2018-01-09T00:00:00.000Z","atl":0.00101492,"atl_change_' + 'percentage":608.13327,"atl_date":"2014-12-18T00:00:00.000Z","roi":n' + 'ull,"last_updated":"2022-08-22T16:38:26.347Z"},{"id":"zcoin","symbo' + 'l":"firo","name":"Firo","image":"https://assets.coingecko.com/coins' + '/images/479/large/firocoingecko.png?1636537544","current_price":0.0' + '001096,"market_cap":1252,"market_cap_rank":604,"fully_diluted_valu' + 'ation":2349,"total_volume":90.573,"high_24h":0.00011148,"low_24h":0' + '.00010834,"price_change_24h":-9.87561775002e-07,"price_change_perce' + 'ntage_24h":-0.89304,"market_cap_change_24h":-10.046635178462793,"ma' + 'rket_cap_change_percentage_24h":-0.79578,"circulating_supply":11411' + '043.8354697,"total_supply":21400000.0,"max_supply":21400000.0,"ath"' + ':0.01616272,"ath_change_percentage":-99.3208,"ath_date":"2018-04-04' + 'T16:04:48.408Z","atl":4.268e-05,"atl_change_percentage":157.22799,' + '"atl_date":"2022-05-12T07:28:47.088Z","roi":null,"last_updated":"2' + '022-08-22T16:38:47.229Z"},{"id":"epic-cash","symbol":"epic","name":"' + 'Epic Cash","image":"https://assets.coingecko.com/coins/images/9520/' + 'large/Epic_Coin_NO_drop_shadow.png?1620122642","current_price":2.80' + '3e-05,"market_cap":415.109,"market_cap_rank":953,"fully_diluted_val' + 'uation":null,"total_volume":0.2371557,"high_24h":3.053e-05,"low_24h' + '":2.581e-05,"price_change_24h":1.9e-06,"price_change_percentage_24' + 'h":7.27524,"market_cap_change_24h":28.26753,"market_cap_change_perc' + 'entage_24h":7.30726,"circulating_supply":14808052.0,"total_supply":' + '21000000.0,"max_supply":null,"ath":0.00013848,"ath_change_percentag' + 'e":-79.75864,"ath_date":"2021-12-11T08:39:41.129Z","atl":5.74028e-0' + '7,"atl_change_percentage":4783.08078,"atl_date":"2020-03-13T16:55:01' + '.177Z","roi":null,"last_updated":"2022-08-22T16:38:32.826Z"}]'), 200)); final priceAPI = PriceAPI(client); @@ -247,7 +253,8 @@ void main() { // verify only called once during filling of cache verify(client.get( - Uri.parse( + proxyInfo: null, + url: Uri.parse( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids" "=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" @@ -259,10 +266,11 @@ void main() { }); test("response parse failure", () async { - final client = MockClient(); + final client = MockHTTP(); when(client.get( - Uri.parse( + proxyInfo: null, + url: Uri.parse( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc" "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" @@ -271,64 +279,65 @@ void main() { headers: { 'Content-Type': 'application/json' })).thenAnswer((_) async => Response( - '[{"id":"bitcoin","symbol":"btc","name":com/coins/images/1/large/' - 'bitcoin.png?1547033579","current_price":1.0,"market_cap":19128800' - ',"market_cap_rank":1,"fully_diluted_valuation":21000000,"total_volum' - 'e":1272132,"high_24h":1.0,"low_24h":1.0,"price_change_24h":0.0,"pri' - 'ce_change_percentage_24h":0.0,"market_cap_change_24h":950.0,"market_' - 'cap_change_percentage_24h":0.00497,"circulating_supply":19128800.0,"t' - 'otal_supply":21000000.0,"max_supply":21000000.0,"ath":1.003301,"ath' - '_change_percentage":-0.32896,"ath_date":"2019-10-15T16:00:56.136Z",' - '"atl":0.99895134,"atl_change_percentage":0.10498,"atl_date":' - '"2019-10-21T00:00:00.000Z","roi":null,' - '"last_updated":"2022-08-22T16:37:59.237Z"},{"id":"dogecoin"' - ',"symbol":"doge","name":"Dogecoin","image":' - '"https://assets.coingecko.com/coins/images/5/large/dogecoin.png?1547792256",' - '"current_price":3.15e-06,"market_cap":417916,"market_cap_rank":10' - ',"fully_diluted_valuation":null,"total_volume":27498,"high_24h":3' - '.26e-06,"low_24h":3.13e-06,"price_change_24h":-8.6889947714e-08,"' - 'price_change_percentage_24h":-2.68533,"market_cap_change_24h":-11' - '370.894861206936,"market_cap_change_percentage_24h":-2.64879,"cir' - 'culating_supply":132670764299.894,"total_supply":null,"max_supply' - '":null,"ath":1.264e-05,"ath_change_percentage":-75.05046,"ath_date' - '":"2021-05-07T23:04:53.026Z","atl":1.50936e-07,"atl_change_percen' - 'tage":1989.69346,"atl_date":"2020-12-17T09:18:05.654Z","roi":null,' - '"last_updated":"2022-08-22T16:38:15.113Z"},{"id":"monero","symbol"' - ':"xmr","name":"Monero","image":"https://assets.coingecko.com/coins' - '/images/69/large/monero_logo.png?1547033729","current_price":0.007' - '17236,"market_cap":130002,"market_cap_rank":29,"fully_diluted_valu' - 'ation":null,"total_volume":4901,"high_24h":0.00731999,"low_24h":0.' - '00707511,"price_change_24h":-5.6133543212467e-05,"price_change_per' - 'centage_24h":-0.77656,"market_cap_change_24h":-1007.8447677436197' - ',"market_cap_change_percentage_24h":-0.76929,"circulating_supply":' - '18147820.3764146,"total_supply":null,"max_supply":null,"ath":0.034' - '75393,"ath_change_percentage":-79.32037,"ath_date":"2018-01-09T00:' - '00:00.000Z","atl":0.00101492,"atl_change_percentage":608.13327,"at' - 'l_date":"2014-12-18T00:00:00.000Z","roi":null,"last_updated":"2022' - '-08-22T16:38:26.347Z"},{"id":"zcoin","symbol":"firo","name":"Firo"' - ',"image":"https://assets.coingecko.com/coins/images/479/large/firo' - 'coingecko.png?1636537544","current_price":0.0001096,"market_cap":1' - '252,"market_cap_rank":604,"fully_diluted_valuation":2349,"total_vo' - 'lume":90.573,"high_24h":0.00011148,"low_24h":0.00010834,"price_chang' - 'e_24h":-9.87561775002e-07,"price_change_percentage_24h":-0.89304,' - '"market_cap_change_24h":-10.046635178462793,"market_cap_change_per' - 'centage_24h":-0.79578,"circulating_supply":11411043.8354697,"tota' - 'l_supply":21400000.0,"max_supply":21400000.0,"ath":0.01616272,"ath' - '_change_percentage":-99.3208,"ath_date":"2018-04-04T16:04:48.408Z"' - ',"atl":4.268e-05,"atl_change_percentage":157.22799,"atl_date":"202' - '2-05-12T07:28:47.088Z","roi":null,"last_updated":"2022-08-22T16:3' - '8:47.229Z"},{"id":"epic-cash","symbol":"epic","name":"Epic Cash",' - '"image":"https://assets.coingecko.com/coins/images/9520/large/' - 'Epic_Coin_NO_drop_shadow.png?1620122642","current_price":2.803e-0' - '5,"market_cap":415.109,"market_cap_rank":953,"fully_diluted_valuat' - 'ion":null,"total_volume":0.2371557,"high_24h":3.053e-05,"low_24h":' - '2.581e-05,"price_change_24h":1.9e-06,"price_change_percentage_24h"' - ':7.27524,"market_cap_change_24h":28.26753,"market_cap_change_per' - 'centage_24h":7.30726,"circulating_supply":14808052.0,"total_suppl' - 'y":21000000.0,"max_supply":null,"ath":0.00013848,"ath_change_perce' - 'ntage":-79.75864,"ath_date":"2021-12-11T08:39:41.129Z","atl":5.74' - '028e-07,"atl_change_percentage":4783.08078,"atl_date":"2020-03-13T' - '16:55:01.177Z","roi":null,"last_updated":"2022-08-22T16:38:32.826Z"}]', + utf8.encode( + '[{"id":"bitcoin","symbol":"btc","name":com/coins/images/1/large/' + 'bitcoin.png?1547033579","current_price":1.0,"market_cap":19128800' + ',"market_cap_rank":1,"fully_diluted_valuation":21000000,"total_volum' + 'e":1272132,"high_24h":1.0,"low_24h":1.0,"price_change_24h":0.0,"pri' + 'ce_change_percentage_24h":0.0,"market_cap_change_24h":950.0,"market_' + 'cap_change_percentage_24h":0.00497,"circulating_supply":19128800.0,"t' + 'otal_supply":21000000.0,"max_supply":21000000.0,"ath":1.003301,"ath' + '_change_percentage":-0.32896,"ath_date":"2019-10-15T16:00:56.136Z",' + '"atl":0.99895134,"atl_change_percentage":0.10498,"atl_date":' + '"2019-10-21T00:00:00.000Z","roi":null,' + '"last_updated":"2022-08-22T16:37:59.237Z"},{"id":"dogecoin"' + ',"symbol":"doge","name":"Dogecoin","image":' + '"https://assets.coingecko.com/coins/images/5/large/dogecoin.png?1547792256",' + '"current_price":3.15e-06,"market_cap":417916,"market_cap_rank":10' + ',"fully_diluted_valuation":null,"total_volume":27498,"high_24h":3' + '.26e-06,"low_24h":3.13e-06,"price_change_24h":-8.6889947714e-08,"' + 'price_change_percentage_24h":-2.68533,"market_cap_change_24h":-11' + '370.894861206936,"market_cap_change_percentage_24h":-2.64879,"cir' + 'culating_supply":132670764299.894,"total_supply":null,"max_supply' + '":null,"ath":1.264e-05,"ath_change_percentage":-75.05046,"ath_date' + '":"2021-05-07T23:04:53.026Z","atl":1.50936e-07,"atl_change_percen' + 'tage":1989.69346,"atl_date":"2020-12-17T09:18:05.654Z","roi":null,' + '"last_updated":"2022-08-22T16:38:15.113Z"},{"id":"monero","symbol"' + ':"xmr","name":"Monero","image":"https://assets.coingecko.com/coins' + '/images/69/large/monero_logo.png?1547033729","current_price":0.007' + '17236,"market_cap":130002,"market_cap_rank":29,"fully_diluted_valu' + 'ation":null,"total_volume":4901,"high_24h":0.00731999,"low_24h":0.' + '00707511,"price_change_24h":-5.6133543212467e-05,"price_change_per' + 'centage_24h":-0.77656,"market_cap_change_24h":-1007.8447677436197' + ',"market_cap_change_percentage_24h":-0.76929,"circulating_supply":' + '18147820.3764146,"total_supply":null,"max_supply":null,"ath":0.034' + '75393,"ath_change_percentage":-79.32037,"ath_date":"2018-01-09T00:' + '00:00.000Z","atl":0.00101492,"atl_change_percentage":608.13327,"at' + 'l_date":"2014-12-18T00:00:00.000Z","roi":null,"last_updated":"2022' + '-08-22T16:38:26.347Z"},{"id":"zcoin","symbol":"firo","name":"Firo"' + ',"image":"https://assets.coingecko.com/coins/images/479/large/firo' + 'coingecko.png?1636537544","current_price":0.0001096,"market_cap":1' + '252,"market_cap_rank":604,"fully_diluted_valuation":2349,"total_vo' + 'lume":90.573,"high_24h":0.00011148,"low_24h":0.00010834,"price_chang' + 'e_24h":-9.87561775002e-07,"price_change_percentage_24h":-0.89304,' + '"market_cap_change_24h":-10.046635178462793,"market_cap_change_per' + 'centage_24h":-0.79578,"circulating_supply":11411043.8354697,"tota' + 'l_supply":21400000.0,"max_supply":21400000.0,"ath":0.01616272,"ath' + '_change_percentage":-99.3208,"ath_date":"2018-04-04T16:04:48.408Z"' + ',"atl":4.268e-05,"atl_change_percentage":157.22799,"atl_date":"202' + '2-05-12T07:28:47.088Z","roi":null,"last_updated":"2022-08-22T16:3' + '8:47.229Z"},{"id":"epic-cash","symbol":"epic","name":"Epic Cash",' + '"image":"https://assets.coingecko.com/coins/images/9520/large/' + 'Epic_Coin_NO_drop_shadow.png?1620122642","current_price":2.803e-0' + '5,"market_cap":415.109,"market_cap_rank":953,"fully_diluted_valuat' + 'ion":null,"total_volume":0.2371557,"high_24h":3.053e-05,"low_24h":' + '2.581e-05,"price_change_24h":1.9e-06,"price_change_percentage_24h"' + ':7.27524,"market_cap_change_24h":28.26753,"market_cap_change_per' + 'centage_24h":7.30726,"circulating_supply":14808052.0,"total_suppl' + 'y":21000000.0,"max_supply":null,"ath":0.00013848,"ath_change_perce' + 'ntage":-79.75864,"ath_date":"2021-12-11T08:39:41.129Z","atl":5.74' + '028e-07,"atl_change_percentage":4783.08078,"atl_date":"2020-03-13T' + '16:55:01.177Z","roi":null,"last_updated":"2022-08-22T16:38:32.826Z"}]'), 200)); final priceAPI = PriceAPI(client); @@ -365,10 +374,11 @@ void main() { }); test("no internet available", () async { - final client = MockClient(); + final client = MockHTTP(); when(client.get( - Uri.parse( + proxyInfo: null, + url: Uri.parse( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc" "&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin," "bitcoin-cash,namecoin,wownero,ethereum,particl,nano,banano,stellar" diff --git a/test/price_test.mocks.dart b/test/price_test.mocks.dart index 8c38f59f9..59b90851e 100644 --- a/test/price_test.mocks.dart +++ b/test/price_test.mocks.dart @@ -4,11 +4,11 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; -import 'dart:convert' as _i4; -import 'dart:typed_data' as _i5; +import 'dart:convert' as _i5; +import 'dart:io' as _i4; -import 'package:http/http.dart' as _i2; import 'package:mockito/mockito.dart' as _i1; +import 'package:stackwallet/networking/http.dart' as _i2; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -31,233 +31,76 @@ class _FakeResponse_0 extends _i1.SmartFake implements _i2.Response { ); } -class _FakeStreamedResponse_1 extends _i1.SmartFake - implements _i2.StreamedResponse { - _FakeStreamedResponse_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -/// A class which mocks [Client]. +/// A class which mocks [HTTP]. /// /// See the documentation for Mockito's code generation for more information. -class MockClient extends _i1.Mock implements _i2.Client { - MockClient() { +class MockHTTP extends _i1.Mock implements _i2.HTTP { + MockHTTP() { _i1.throwOnMissingStub(this); } @override - _i3.Future<_i2.Response> head( - Uri? url, { - Map? headers, - }) => - (super.noSuchMethod( - Invocation.method( - #head, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #head, - [url], - {#headers: headers}, - ), - )), - ) as _i3.Future<_i2.Response>); - @override - _i3.Future<_i2.Response> get( - Uri? url, { + _i3.Future<_i2.Response> get({ + required Uri? url, Map? headers, + required ({_i4.InternetAddress host, int port})? proxyInfo, }) => (super.noSuchMethod( Invocation.method( #get, - [url], - {#headers: headers}, + [], + { + #url: url, + #headers: headers, + #proxyInfo: proxyInfo, + }, ), returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( this, Invocation.method( #get, - [url], - {#headers: headers}, + [], + { + #url: url, + #headers: headers, + #proxyInfo: proxyInfo, + }, ), )), ) as _i3.Future<_i2.Response>); @override - _i3.Future<_i2.Response> post( - Uri? url, { + _i3.Future<_i2.Response> post({ + required Uri? url, Map? headers, Object? body, - _i4.Encoding? encoding, + _i5.Encoding? encoding, + required ({_i4.InternetAddress host, int port})? proxyInfo, }) => (super.noSuchMethod( Invocation.method( #post, - [url], + [], { + #url: url, #headers: headers, #body: body, #encoding: encoding, + #proxyInfo: proxyInfo, }, ), returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( this, Invocation.method( #post, - [url], + [], { + #url: url, #headers: headers, #body: body, #encoding: encoding, + #proxyInfo: proxyInfo, }, ), )), ) as _i3.Future<_i2.Response>); - @override - _i3.Future<_i2.Response> put( - Uri? url, { - Map? headers, - Object? body, - _i4.Encoding? encoding, - }) => - (super.noSuchMethod( - Invocation.method( - #put, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #put, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); - @override - _i3.Future<_i2.Response> patch( - Uri? url, { - Map? headers, - Object? body, - _i4.Encoding? encoding, - }) => - (super.noSuchMethod( - Invocation.method( - #patch, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #patch, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); - @override - _i3.Future<_i2.Response> delete( - Uri? url, { - Map? headers, - Object? body, - _i4.Encoding? encoding, - }) => - (super.noSuchMethod( - Invocation.method( - #delete, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( - this, - Invocation.method( - #delete, - [url], - { - #headers: headers, - #body: body, - #encoding: encoding, - }, - ), - )), - ) as _i3.Future<_i2.Response>); - @override - _i3.Future read( - Uri? url, { - Map? headers, - }) => - (super.noSuchMethod( - Invocation.method( - #read, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future.value(''), - ) as _i3.Future); - @override - _i3.Future<_i5.Uint8List> readBytes( - Uri? url, { - Map? headers, - }) => - (super.noSuchMethod( - Invocation.method( - #readBytes, - [url], - {#headers: headers}, - ), - returnValue: _i3.Future<_i5.Uint8List>.value(_i5.Uint8List(0)), - ) as _i3.Future<_i5.Uint8List>); - @override - _i3.Future<_i2.StreamedResponse> send(_i2.BaseRequest? request) => - (super.noSuchMethod( - Invocation.method( - #send, - [request], - ), - returnValue: - _i3.Future<_i2.StreamedResponse>.value(_FakeStreamedResponse_1( - this, - Invocation.method( - #send, - [request], - ), - )), - ) as _i3.Future<_i2.StreamedResponse>); - @override - void close() => super.noSuchMethod( - Invocation.method( - #close, - [], - ), - returnValueForMissingStub: null, - ); } diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart index 5263fad93..5e23da459 100644 --- a/test/screen_tests/exchange/exchange_view_test.mocks.dart +++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart @@ -244,14 +244,14 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs { returnValueForMissingStub: null, ); @override - bool get torKillswitch => (super.noSuchMethod( - Invocation.getter(#torKillswitch), + bool get torKillSwitch => (super.noSuchMethod( + Invocation.getter(#torKillSwitch), returnValue: false, ) as bool); @override - set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + set torKillSwitch(bool? torKillswitch) => super.noSuchMethod( Invocation.setter( - #torKillswitch, + #torKillSwitch, torKillswitch, ), returnValueForMissingStub: null, diff --git a/test/widget_tests/custom_buttons/favorite_toggle_test.mocks.dart b/test/widget_tests/custom_buttons/favorite_toggle_test.mocks.dart index 0abed1954..20727e854 100644 --- a/test/widget_tests/custom_buttons/favorite_toggle_test.mocks.dart +++ b/test/widget_tests/custom_buttons/favorite_toggle_test.mocks.dart @@ -3,13 +3,14 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; -import 'dart:typed_data' as _i6; +import 'dart:async' as _i6; +import 'dart:typed_data' as _i7; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/db/isar/main_db.dart' as _i2; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i4; -import 'package:stackwallet/themes/theme_service.dart' as _i3; +import 'package:stackwallet/db/isar/main_db.dart' as _i3; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i5; +import 'package:stackwallet/networking/http.dart' as _i2; +import 'package:stackwallet/themes/theme_service.dart' as _i4; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -22,8 +23,18 @@ import 'package:stackwallet/themes/theme_service.dart' as _i3; // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class -class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { - _FakeMainDB_0( +class _FakeHTTP_0 extends _i1.SmartFake implements _i2.HTTP { + _FakeHTTP_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMainDB_1 extends _i1.SmartFake implements _i3.MainDB { + _FakeMainDB_1( Object parent, Invocation parentInvocation, ) : super( @@ -35,26 +46,42 @@ class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i3.ThemeService { +class MockThemeService extends _i1.Mock implements _i4.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } @override - _i2.MainDB get db => (super.noSuchMethod( + _i2.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_0( + this, + Invocation.getter(#client), + ), + ) as _i2.HTTP); + @override + set client(_i2.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); + @override + _i3.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_0( + returnValue: _FakeMainDB_1( this, Invocation.getter(#db), ), - ) as _i2.MainDB); + ) as _i3.MainDB); @override - List<_i4.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i5.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i4.StackTheme>[], - ) as List<_i4.StackTheme>); + returnValue: <_i5.StackTheme>[], + ) as List<_i5.StackTheme>); @override - void init(_i2.MainDB? db) => super.noSuchMethod( + void init(_i3.MainDB? db) => super.noSuchMethod( Invocation.method( #init, [db], @@ -62,70 +89,70 @@ class MockThemeService extends _i1.Mock implements _i3.ThemeService { returnValueForMissingStub: null, ); @override - _i5.Future install({required _i6.Uint8List? themeArchiveData}) => + _i6.Future install({required _i7.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future remove({required String? themeId}) => (super.noSuchMethod( + _i6.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i6.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future verifyInstalled({required String? themeId}) => + _i6.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i6.Future.value(false), + ) as _i6.Future); @override - _i5.Future> fetchThemes() => (super.noSuchMethod( + _i6.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i5.Future>.value( - <_i3.StackThemeMetaData>[]), - ) as _i5.Future>); + returnValue: _i6.Future>.value( + <_i4.StackThemeMetaData>[]), + ) as _i6.Future>); @override - _i5.Future<_i6.Uint8List> fetchTheme( - {required _i3.StackThemeMetaData? themeMetaData}) => + _i6.Future<_i7.Uint8List> fetchTheme( + {required _i4.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i5.Future<_i6.Uint8List>.value(_i6.Uint8List(0)), - ) as _i5.Future<_i6.Uint8List>); + returnValue: _i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + ) as _i6.Future<_i7.Uint8List>); @override - _i4.StackTheme? getTheme({required String? themeId}) => + _i5.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i4.StackTheme?); + )) as _i5.StackTheme?); } diff --git a/test/widget_tests/custom_loading_overlay_test.mocks.dart b/test/widget_tests/custom_loading_overlay_test.mocks.dart index c96558898..142052fa2 100644 --- a/test/widget_tests/custom_loading_overlay_test.mocks.dart +++ b/test/widget_tests/custom_loading_overlay_test.mocks.dart @@ -3,13 +3,14 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; -import 'dart:typed_data' as _i6; +import 'dart:async' as _i6; +import 'dart:typed_data' as _i7; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/db/isar/main_db.dart' as _i2; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i4; -import 'package:stackwallet/themes/theme_service.dart' as _i3; +import 'package:stackwallet/db/isar/main_db.dart' as _i3; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i5; +import 'package:stackwallet/networking/http.dart' as _i2; +import 'package:stackwallet/themes/theme_service.dart' as _i4; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -22,8 +23,18 @@ import 'package:stackwallet/themes/theme_service.dart' as _i3; // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class -class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { - _FakeMainDB_0( +class _FakeHTTP_0 extends _i1.SmartFake implements _i2.HTTP { + _FakeHTTP_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMainDB_1 extends _i1.SmartFake implements _i3.MainDB { + _FakeMainDB_1( Object parent, Invocation parentInvocation, ) : super( @@ -35,26 +46,42 @@ class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i3.ThemeService { +class MockThemeService extends _i1.Mock implements _i4.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } @override - _i2.MainDB get db => (super.noSuchMethod( + _i2.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_0( + this, + Invocation.getter(#client), + ), + ) as _i2.HTTP); + @override + set client(_i2.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); + @override + _i3.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_0( + returnValue: _FakeMainDB_1( this, Invocation.getter(#db), ), - ) as _i2.MainDB); + ) as _i3.MainDB); @override - List<_i4.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i5.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i4.StackTheme>[], - ) as List<_i4.StackTheme>); + returnValue: <_i5.StackTheme>[], + ) as List<_i5.StackTheme>); @override - void init(_i2.MainDB? db) => super.noSuchMethod( + void init(_i3.MainDB? db) => super.noSuchMethod( Invocation.method( #init, [db], @@ -62,70 +89,70 @@ class MockThemeService extends _i1.Mock implements _i3.ThemeService { returnValueForMissingStub: null, ); @override - _i5.Future install({required _i6.Uint8List? themeArchiveData}) => + _i6.Future install({required _i7.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future remove({required String? themeId}) => (super.noSuchMethod( + _i6.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i6.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future verifyInstalled({required String? themeId}) => + _i6.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i6.Future.value(false), + ) as _i6.Future); @override - _i5.Future> fetchThemes() => (super.noSuchMethod( + _i6.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i5.Future>.value( - <_i3.StackThemeMetaData>[]), - ) as _i5.Future>); + returnValue: _i6.Future>.value( + <_i4.StackThemeMetaData>[]), + ) as _i6.Future>); @override - _i5.Future<_i6.Uint8List> fetchTheme( - {required _i3.StackThemeMetaData? themeMetaData}) => + _i6.Future<_i7.Uint8List> fetchTheme( + {required _i4.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i5.Future<_i6.Uint8List>.value(_i6.Uint8List(0)), - ) as _i5.Future<_i6.Uint8List>); + returnValue: _i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + ) as _i6.Future<_i7.Uint8List>); @override - _i4.StackTheme? getTheme({required String? themeId}) => + _i5.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i4.StackTheme?); + )) as _i5.StackTheme?); } diff --git a/test/widget_tests/desktop/desktop_scaffold_test.mocks.dart b/test/widget_tests/desktop/desktop_scaffold_test.mocks.dart index 37476e4c3..8507ace66 100644 --- a/test/widget_tests/desktop/desktop_scaffold_test.mocks.dart +++ b/test/widget_tests/desktop/desktop_scaffold_test.mocks.dart @@ -3,13 +3,14 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; -import 'dart:typed_data' as _i6; +import 'dart:async' as _i6; +import 'dart:typed_data' as _i7; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/db/isar/main_db.dart' as _i2; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i4; -import 'package:stackwallet/themes/theme_service.dart' as _i3; +import 'package:stackwallet/db/isar/main_db.dart' as _i3; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i5; +import 'package:stackwallet/networking/http.dart' as _i2; +import 'package:stackwallet/themes/theme_service.dart' as _i4; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -22,8 +23,18 @@ import 'package:stackwallet/themes/theme_service.dart' as _i3; // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class -class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { - _FakeMainDB_0( +class _FakeHTTP_0 extends _i1.SmartFake implements _i2.HTTP { + _FakeHTTP_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMainDB_1 extends _i1.SmartFake implements _i3.MainDB { + _FakeMainDB_1( Object parent, Invocation parentInvocation, ) : super( @@ -35,26 +46,42 @@ class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i3.ThemeService { +class MockThemeService extends _i1.Mock implements _i4.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } @override - _i2.MainDB get db => (super.noSuchMethod( + _i2.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_0( + this, + Invocation.getter(#client), + ), + ) as _i2.HTTP); + @override + set client(_i2.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); + @override + _i3.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_0( + returnValue: _FakeMainDB_1( this, Invocation.getter(#db), ), - ) as _i2.MainDB); + ) as _i3.MainDB); @override - List<_i4.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i5.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i4.StackTheme>[], - ) as List<_i4.StackTheme>); + returnValue: <_i5.StackTheme>[], + ) as List<_i5.StackTheme>); @override - void init(_i2.MainDB? db) => super.noSuchMethod( + void init(_i3.MainDB? db) => super.noSuchMethod( Invocation.method( #init, [db], @@ -62,70 +89,70 @@ class MockThemeService extends _i1.Mock implements _i3.ThemeService { returnValueForMissingStub: null, ); @override - _i5.Future install({required _i6.Uint8List? themeArchiveData}) => + _i6.Future install({required _i7.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future remove({required String? themeId}) => (super.noSuchMethod( + _i6.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i6.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future verifyInstalled({required String? themeId}) => + _i6.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i6.Future.value(false), + ) as _i6.Future); @override - _i5.Future> fetchThemes() => (super.noSuchMethod( + _i6.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i5.Future>.value( - <_i3.StackThemeMetaData>[]), - ) as _i5.Future>); + returnValue: _i6.Future>.value( + <_i4.StackThemeMetaData>[]), + ) as _i6.Future>); @override - _i5.Future<_i6.Uint8List> fetchTheme( - {required _i3.StackThemeMetaData? themeMetaData}) => + _i6.Future<_i7.Uint8List> fetchTheme( + {required _i4.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i5.Future<_i6.Uint8List>.value(_i6.Uint8List(0)), - ) as _i5.Future<_i6.Uint8List>); + returnValue: _i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + ) as _i6.Future<_i7.Uint8List>); @override - _i4.StackTheme? getTheme({required String? themeId}) => + _i5.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i4.StackTheme?); + )) as _i5.StackTheme?); } diff --git a/test/widget_tests/managed_favorite_test.mocks.dart b/test/widget_tests/managed_favorite_test.mocks.dart index 856a2c6f5..e2232e066 100644 --- a/test/widget_tests/managed_favorite_test.mocks.dart +++ b/test/widget_tests/managed_favorite_test.mocks.dart @@ -3,9 +3,9 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i23; -import 'dart:typed_data' as _i29; -import 'dart:ui' as _i25; +import 'dart:async' as _i24; +import 'dart:typed_data' as _i30; +import 'dart:ui' as _i26; import 'package:bip32/bip32.dart' as _i16; import 'package:bip47/bip47.dart' as _i18; @@ -18,29 +18,30 @@ import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i10; import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i9; import 'package:stackwallet/models/balance.dart' as _i11; import 'package:stackwallet/models/isar/models/isar_models.dart' as _i17; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i31; -import 'package:stackwallet/models/node_model.dart' as _i36; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i32; +import 'package:stackwallet/models/node_model.dart' as _i37; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i8; -import 'package:stackwallet/models/signing_data.dart' as _i28; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i26; -import 'package:stackwallet/services/coins/coin_service.dart' as _i20; +import 'package:stackwallet/models/signing_data.dart' as _i29; +import 'package:stackwallet/networking/http.dart' as _i19; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i27; +import 'package:stackwallet/services/coins/coin_service.dart' as _i21; import 'package:stackwallet/services/coins/manager.dart' as _i6; -import 'package:stackwallet/services/locale_service.dart' as _i35; +import 'package:stackwallet/services/locale_service.dart' as _i36; import 'package:stackwallet/services/node_service.dart' as _i3; import 'package:stackwallet/services/transaction_notification_tracker.dart' as _i7; -import 'package:stackwallet/services/wallets.dart' as _i21; +import 'package:stackwallet/services/wallets.dart' as _i22; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/themes/theme_service.dart' as _i30; +import 'package:stackwallet/themes/theme_service.dart' as _i31; import 'package:stackwallet/utilities/amount/amount.dart' as _i14; -import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i34; -import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i33; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i22; -import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i27; -import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i32; +import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i35; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i34; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i23; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i28; +import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i33; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' - as _i19; -import 'package:stackwallet/utilities/prefs.dart' as _i24; + as _i20; +import 'package:stackwallet/utilities/prefs.dart' as _i25; import 'package:tuple/tuple.dart' as _i15; // ignore_for_file: type=lint @@ -229,9 +230,8 @@ class _FakePaymentCode_16 extends _i1.SmartFake implements _i18.PaymentCode { ); } -class _FakeSecureStorageInterface_17 extends _i1.SmartFake - implements _i19.SecureStorageInterface { - _FakeSecureStorageInterface_17( +class _FakeHTTP_17 extends _i1.SmartFake implements _i19.HTTP { + _FakeHTTP_17( Object parent, Invocation parentInvocation, ) : super( @@ -240,9 +240,20 @@ class _FakeSecureStorageInterface_17 extends _i1.SmartFake ); } -class _FakeCoinServiceAPI_18 extends _i1.SmartFake - implements _i20.CoinServiceAPI { - _FakeCoinServiceAPI_18( +class _FakeSecureStorageInterface_18 extends _i1.SmartFake + implements _i20.SecureStorageInterface { + _FakeSecureStorageInterface_18( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_19 extends _i1.SmartFake + implements _i21.CoinServiceAPI { + _FakeCoinServiceAPI_19( Object parent, Invocation parentInvocation, ) : super( @@ -254,7 +265,7 @@ class _FakeCoinServiceAPI_18 extends _i1.SmartFake /// A class which mocks [Wallets]. /// /// See the documentation for Mockito's code generation for more information. -class MockWallets extends _i1.Mock implements _i21.Wallets { +class MockWallets extends _i1.Mock implements _i22.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -321,7 +332,7 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i22.Coin? coin}) => + List getWalletIdsFor({required _i23.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -331,20 +342,20 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValue: [], ) as List); @override - List<_i15.Tuple2<_i22.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> + List<_i15.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i15.Tuple2<_i22.Coin, + returnValue: <_i15.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>[], ) as List< - _i15.Tuple2<_i22.Coin, + _i15.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i22.Coin? coin) => + _i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -408,17 +419,17 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - _i23.Future load(_i24.Prefs? prefs) => (super.noSuchMethod( + _i24.Future load(_i25.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future loadAfterStackRestore( - _i24.Prefs? prefs, + _i24.Future loadAfterStackRestore( + _i25.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -429,11 +440,11 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { managers, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -441,7 +452,7 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -467,19 +478,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i23.Future> get walletNames => + _i24.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i23.Future>.value( + returnValue: _i24.Future>.value( {}), - ) as _i23.Future>); + ) as _i24.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future renameWallet({ + _i24.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -494,8 +505,8 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override Map fetchWalletsData() => (super.noSuchMethod( Invocation.method( @@ -505,10 +516,10 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValue: {}, ) as Map); @override - _i23.Future addExistingStackWallet({ + _i24.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i22.Coin? coin, + required _i23.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -522,13 +533,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future addNewWallet({ + _i24.Future addNewWallet({ required String? name, - required _i22.Coin? coin, + required _i23.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -541,46 +552,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i24.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future saveFavoriteWalletIds(List? walletIds) => + _i24.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i24.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i24.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future moveFavorite({ + _i24.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -593,48 +604,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i24.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i24.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future isMnemonicVerified({required String? walletId}) => + _i24.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future setMnemonicVerified({required String? walletId}) => + _i24.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future deleteWallet( + _i24.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -646,20 +657,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future refreshWallets(bool? shouldNotifyListeners) => + _i24.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -667,7 +678,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -695,13 +706,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { /// A class which mocks [BitcoinWallet]. /// /// See the documentation for Mockito's code generation for more information. -class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i23.Timer? _timer) => super.noSuchMethod( + set timer(_i24.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -778,74 +789,74 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValue: false, ) as bool); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i17.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i17.UTXO>[]), + ) as _i24.Future>); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i17.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i17.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future get currentChangeAddress => (super.noSuchMethod( + _i24.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future get currentChangeAddressP2PKH => (super.noSuchMethod( + _i24.Future get currentChangeAddressP2PKH => (super.noSuchMethod( Invocation.getter(#currentChangeAddressP2PKH), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i23.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i24.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i8.FeeObject>); + ) as _i24.Future<_i8.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicString => (super.noSuchMethod( + _i24.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get chainHeight => (super.noSuchMethod( + _i24.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -917,10 +928,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { ), ) as _i11.Balance); @override - _i23.Future get xpub => (super.noSuchMethod( + _i24.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -947,26 +958,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { ), ) as _i13.NetworkType); @override - _i23.Future exit() => (super.noSuchMethod( + _i24.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i27.DerivePathType addressType({required String? address}) => + _i28.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i27.DerivePathType.bip44, - ) as _i27.DerivePathType); + returnValue: _i28.DerivePathType.bip44, + ) as _i28.DerivePathType); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -985,47 +996,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future getTransactionCacheEarly(List? allAddresses) => + _i24.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i24.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future getAllTxsToWatch() => (super.noSuchMethod( + _i24.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, required _i14.Amount? amount, Map? args, @@ -1041,26 +1052,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -1078,35 +1089,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateSentCachedTxData(Map? txData) => + _i24.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1116,69 +1127,69 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValue: false, ) as bool); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i24.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), - returnValue: _i23.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_11( + returnValue: _i24.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_11( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i23.Future<_i9.ElectrumXNode>); + ) as _i24.Future<_i9.ElectrumXNode>); @override - _i23.Future>> fastFetch( + _i24.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i23.Future>>.value( + returnValue: _i24.Future>>.value( >[]), - ) as _i23.Future>>); + ) as _i24.Future>>); @override - _i23.Future getTxCount({required String? address}) => + _i24.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future checkCurrentReceivingAddressesForTransactions() => + _i24.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkCurrentChangeAddressesForTransactions() => + _i24.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override int estimateTxFee({ required int? vSize, @@ -1221,7 +1232,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { }, )); @override - _i23.Future> fetchBuildTxData( + _i24.Future> fetchBuildTxData( List<_i17.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( @@ -1229,11 +1240,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { [utxosToUse], ), returnValue: - _i23.Future>.value(<_i28.SigningData>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i29.SigningData>[]), + ) as _i24.Future>); @override - _i23.Future> buildTransaction({ - required List<_i28.SigningData>? utxoSigningData, + _i24.Future> buildTransaction({ + required List<_i29.SigningData>? utxoSigningData, required List? recipients, required List? satoshiAmounts, }) => @@ -1248,10 +1259,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1263,11 +1274,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i14.Amount> estimateFeeFor( + _i24.Future<_i14.Amount> estimateFeeFor( _i14.Amount? amount, int? feeRate, ) => @@ -1279,7 +1290,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { feeRate, ], ), - returnValue: _i23.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i24.Future<_i14.Amount>.value(_FakeAmount_12( this, Invocation.method( #estimateFeeFor, @@ -1289,7 +1300,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { ], ), )), - ) as _i23.Future<_i14.Amount>); + ) as _i24.Future<_i14.Amount>); @override _i14.Amount roughFeeEstimate( int? inputCount, @@ -1318,32 +1329,32 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { ), ) as _i14.Amount); @override - _i23.Future<_i14.Amount> sweepAllEstimate(int? feeRate) => + _i24.Future<_i14.Amount> sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i23.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i24.Future<_i14.Amount>.value(_FakeAmount_12( this, Invocation.method( #sweepAllEstimate, [feeRate], ), )), - ) as _i23.Future<_i14.Amount>); + ) as _i24.Future<_i14.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override void initCache( String? walletId, - _i22.Coin? coin, + _i23.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1356,14 +1367,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future updateCachedId(String? id) => (super.noSuchMethod( + _i24.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1373,14 +1384,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValue: 0, ) as int); @override - _i23.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i24.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1390,15 +1401,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValue: false, ) as bool); @override - _i23.Future updateCachedIsFavorite(bool? isFavorite) => + _i24.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override _i11.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1414,15 +1425,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { ), ) as _i11.Balance); @override - _i23.Future updateCachedBalance(_i11.Balance? balance) => + _i24.Future updateCachedBalance(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override _i11.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1438,15 +1449,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { ), ) as _i11.Balance); @override - _i23.Future updateCachedBalanceSecondary(_i11.Balance? balance) => + _i24.Future updateCachedBalanceSecondary(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override List getWalletTokenContractAddresses() => (super.noSuchMethod( Invocation.method( @@ -1456,16 +1467,16 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValue: [], ) as List); @override - _i23.Future updateWalletTokenContractAddresses( + _i24.Future updateWalletTokenContractAddresses( List? contractAddresses) => (super.noSuchMethod( Invocation.method( #updateWalletTokenContractAddresses, [contractAddresses], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override void initWalletDB({_i12.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1476,11 +1487,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>> parseTransaction( + _i24.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>> parseTransaction( Map? txData, dynamic electrumxClient, List<_i17.Address>? myAddresses, - _i22.Coin? coin, + _i23.Coin? coin, int? minConfirms, String? walletId, ) => @@ -1497,7 +1508,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { ], ), returnValue: - _i23.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>.value( + _i24.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>.value( _FakeTuple2_13<_i17.Transaction, _i17.Address>( this, Invocation.method( @@ -1512,37 +1523,37 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { ], ), )), - ) as _i23.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>); + ) as _i24.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>); @override void initPaynymWalletInterface({ required String? walletId, required String? walletName, required _i13.NetworkType? network, - required _i22.Coin? coin, + required _i23.Coin? coin, required _i12.MainDB? db, required _i9.ElectrumX? electrumXClient, - required _i19.SecureStorageInterface? secureStorage, + required _i20.SecureStorageInterface? secureStorage, required int? dustLimit, required int? dustLimitP2PKH, required int? minConfirms, - required _i23.Future Function()? getMnemonicString, - required _i23.Future Function()? getMnemonicPassphrase, - required _i23.Future Function()? getChainHeight, - required _i23.Future Function()? getCurrentChangeAddress, + required _i24.Future Function()? getMnemonicString, + required _i24.Future Function()? getMnemonicPassphrase, + required _i24.Future Function()? getChainHeight, + required _i24.Future Function()? getCurrentChangeAddress, required int Function({ required int feeRatePerKB, required int vSize, })? estimateTxFee, - required _i23.Future> Function({ + required _i24.Future> Function({ required String address, required _i14.Amount amount, Map? args, })? prepareSend, - required _i23.Future Function({required String address})? getTxCount, - required _i23.Future> Function(List<_i17.UTXO>)? + required _i24.Future Function({required String address})? getTxCount, + required _i24.Future> Function(List<_i17.UTXO>)? fetchBuildTxData, - required _i23.Future Function()? refresh, - required _i23.Future Function()? checkChangeAddressForTransactions, + required _i24.Future Function()? refresh, + required _i24.Future Function()? checkChangeAddressForTransactions, }) => super.noSuchMethod( Invocation.method( @@ -1575,21 +1586,21 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future<_i16.BIP32> getBip47BaseNode() => (super.noSuchMethod( + _i24.Future<_i16.BIP32> getBip47BaseNode() => (super.noSuchMethod( Invocation.method( #getBip47BaseNode, [], ), - returnValue: _i23.Future<_i16.BIP32>.value(_FakeBIP32_14( + returnValue: _i24.Future<_i16.BIP32>.value(_FakeBIP32_14( this, Invocation.method( #getBip47BaseNode, [], ), )), - ) as _i23.Future<_i16.BIP32>); + ) as _i24.Future<_i16.BIP32>); @override - _i23.Future<_i29.Uint8List> getPrivateKeyForPaynymReceivingAddress({ + _i24.Future<_i30.Uint8List> getPrivateKeyForPaynymReceivingAddress({ required String? paymentCodeString, required int? index, }) => @@ -1602,10 +1613,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { #index: index, }, ), - returnValue: _i23.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), - ) as _i23.Future<_i29.Uint8List>); + returnValue: _i24.Future<_i30.Uint8List>.value(_i30.Uint8List(0)), + ) as _i24.Future<_i30.Uint8List>); @override - _i23.Future<_i17.Address> currentReceivingPaynymAddress({ + _i24.Future<_i17.Address> currentReceivingPaynymAddress({ required _i18.PaymentCode? sender, required bool? isSegwit, }) => @@ -1618,7 +1629,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i23.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i24.Future<_i17.Address>.value(_FakeAddress_15( this, Invocation.method( #currentReceivingPaynymAddress, @@ -1629,9 +1640,9 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { }, ), )), - ) as _i23.Future<_i17.Address>); + ) as _i24.Future<_i17.Address>); @override - _i23.Future checkCurrentPaynymReceivingAddressForTransactions({ + _i24.Future checkCurrentPaynymReceivingAddressForTransactions({ required _i18.PaymentCode? sender, required bool? isSegwit, }) => @@ -1644,42 +1655,42 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => + _i24.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkAllCurrentReceivingPaynymAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i16.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( + _i24.Future<_i16.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( Invocation.method( #deriveNotificationBip32Node, [], ), - returnValue: _i23.Future<_i16.BIP32>.value(_FakeBIP32_14( + returnValue: _i24.Future<_i16.BIP32>.value(_FakeBIP32_14( this, Invocation.method( #deriveNotificationBip32Node, [], ), )), - ) as _i23.Future<_i16.BIP32>); + ) as _i24.Future<_i16.BIP32>); @override - _i23.Future<_i18.PaymentCode> getPaymentCode({required bool? isSegwit}) => + _i24.Future<_i18.PaymentCode> getPaymentCode({required bool? isSegwit}) => (super.noSuchMethod( Invocation.method( #getPaymentCode, [], {#isSegwit: isSegwit}, ), - returnValue: _i23.Future<_i18.PaymentCode>.value(_FakePaymentCode_16( + returnValue: _i24.Future<_i18.PaymentCode>.value(_FakePaymentCode_16( this, Invocation.method( #getPaymentCode, @@ -1687,27 +1698,27 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { {#isSegwit: isSegwit}, ), )), - ) as _i23.Future<_i18.PaymentCode>); + ) as _i24.Future<_i18.PaymentCode>); @override - _i23.Future<_i29.Uint8List> signWithNotificationKey(_i29.Uint8List? data) => + _i24.Future<_i30.Uint8List> signWithNotificationKey(_i30.Uint8List? data) => (super.noSuchMethod( Invocation.method( #signWithNotificationKey, [data], ), - returnValue: _i23.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), - ) as _i23.Future<_i29.Uint8List>); + returnValue: _i24.Future<_i30.Uint8List>.value(_i30.Uint8List(0)), + ) as _i24.Future<_i30.Uint8List>); @override - _i23.Future signStringWithNotificationKey(String? data) => + _i24.Future signStringWithNotificationKey(String? data) => (super.noSuchMethod( Invocation.method( #signStringWithNotificationKey, [data], ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future> preparePaymentCodeSend({ + _i24.Future> preparePaymentCodeSend({ required _i18.PaymentCode? paymentCode, required bool? isSegwit, required _i14.Amount? amount, @@ -1725,10 +1736,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future<_i17.Address> nextUnusedSendAddressFrom({ + _i24.Future<_i17.Address> nextUnusedSendAddressFrom({ required _i18.PaymentCode? pCode, required bool? isSegwit, required _i16.BIP32? privateKeyNode, @@ -1745,7 +1756,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { #startIndex: startIndex, }, ), - returnValue: _i23.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i24.Future<_i17.Address>.value(_FakeAddress_15( this, Invocation.method( #nextUnusedSendAddressFrom, @@ -1758,9 +1769,9 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { }, ), )), - ) as _i23.Future<_i17.Address>); + ) as _i24.Future<_i17.Address>); @override - _i23.Future> prepareNotificationTx({ + _i24.Future> prepareNotificationTx({ required int? selectedTxFeeRate, required String? targetPaymentCodeString, int? additionalOutputs = 0, @@ -1778,10 +1789,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future broadcastNotificationTx( + _i24.Future broadcastNotificationTx( {required Map? preparedTx}) => (super.noSuchMethod( Invocation.method( @@ -1789,19 +1800,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { [], {#preparedTx: preparedTx}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future hasConnected(String? paymentCodeString) => + _i24.Future hasConnected(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #hasConnected, [paymentCodeString], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransaction( + _i24.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransaction( {required _i17.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( @@ -1809,10 +1820,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { [], {#transaction: transaction}, ), - returnValue: _i23.Future<_i18.PaymentCode?>.value(), - ) as _i23.Future<_i18.PaymentCode?>); + returnValue: _i24.Future<_i18.PaymentCode?>.value(), + ) as _i24.Future<_i18.PaymentCode?>); @override - _i23.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( + _i24.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( {required _i17.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( @@ -1820,31 +1831,31 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { [], {#transaction: transaction}, ), - returnValue: _i23.Future<_i18.PaymentCode?>.value(), - ) as _i23.Future<_i18.PaymentCode?>); + returnValue: _i24.Future<_i18.PaymentCode?>.value(), + ) as _i24.Future<_i18.PaymentCode?>); @override - _i23.Future> + _i24.Future> getAllPaymentCodesFromNotificationTransactions() => (super.noSuchMethod( Invocation.method( #getAllPaymentCodesFromNotificationTransactions, [], ), returnValue: - _i23.Future>.value(<_i18.PaymentCode>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i18.PaymentCode>[]), + ) as _i24.Future>); @override - _i23.Future checkForNotificationTransactionsTo( + _i24.Future checkForNotificationTransactionsTo( Set? otherCodeStrings) => (super.noSuchMethod( Invocation.method( #checkForNotificationTransactionsTo, [otherCodeStrings], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future restoreAllHistory({ + _i24.Future restoreAllHistory({ required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, required Set? paymentCodeStrings, @@ -1859,11 +1870,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { #paymentCodeStrings: paymentCodeStrings, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future restoreHistoryWith({ + _i24.Future restoreHistoryWith({ required _i18.PaymentCode? other, required bool? checkSegwitAsWell, required int? maxUnusedAddressGap, @@ -1880,58 +1891,58 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { #maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i17.Address> getMyNotificationAddress() => (super.noSuchMethod( + _i24.Future<_i17.Address> getMyNotificationAddress() => (super.noSuchMethod( Invocation.method( #getMyNotificationAddress, [], ), - returnValue: _i23.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i24.Future<_i17.Address>.value(_FakeAddress_15( this, Invocation.method( #getMyNotificationAddress, [], ), )), - ) as _i23.Future<_i17.Address>); + ) as _i24.Future<_i17.Address>); @override - _i23.Future> lookupKey(String? paymentCodeString) => + _i24.Future> lookupKey(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #lookupKey, [paymentCodeString], ), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future paymentCodeStringByKey(String? key) => + _i24.Future paymentCodeStringByKey(String? key) => (super.noSuchMethod( Invocation.method( #paymentCodeStringByKey, [key], ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future storeCode(String? paymentCodeString) => + _i24.Future storeCode(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #storeCode, [paymentCodeString], ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override void initCoinControlInterface({ required String? walletId, required String? walletName, - required _i22.Coin? coin, + required _i23.Coin? coin, required _i12.MainDB? db, - required _i23.Future Function()? getChainHeight, - required _i23.Future Function(_i11.Balance)? refreshedBalanceCallback, + required _i24.Future Function()? getChainHeight, + required _i24.Future Function(_i11.Balance)? refreshedBalanceCallback, }) => super.noSuchMethod( Invocation.method( @@ -1949,26 +1960,42 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future refreshBalance({bool? notify = false}) => + _i24.Future refreshBalance({bool? notify = false}) => (super.noSuchMethod( Invocation.method( #refreshBalance, [], {#notify: notify}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); } /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i30.ThemeService { +class MockThemeService extends _i1.Mock implements _i31.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } + @override + _i19.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_17( + this, + Invocation.getter(#client), + ), + ) as _i19.HTTP); + @override + set client(_i19.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); @override _i12.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), @@ -1978,10 +2005,10 @@ class MockThemeService extends _i1.Mock implements _i30.ThemeService { ), ) as _i12.MainDB); @override - List<_i31.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i32.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i31.StackTheme>[], - ) as List<_i31.StackTheme>); + returnValue: <_i32.StackTheme>[], + ) as List<_i32.StackTheme>); @override void init(_i12.MainDB? db) => super.noSuchMethod( Invocation.method( @@ -1991,79 +2018,79 @@ class MockThemeService extends _i1.Mock implements _i30.ThemeService { returnValueForMissingStub: null, ); @override - _i23.Future install({required _i29.Uint8List? themeArchiveData}) => + _i24.Future install({required _i30.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future remove({required String? themeId}) => (super.noSuchMethod( + _i24.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i24.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future verifyInstalled({required String? themeId}) => + _i24.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future> fetchThemes() => + _i24.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i23.Future>.value( - <_i30.StackThemeMetaData>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value( + <_i31.StackThemeMetaData>[]), + ) as _i24.Future>); @override - _i23.Future<_i29.Uint8List> fetchTheme( - {required _i30.StackThemeMetaData? themeMetaData}) => + _i24.Future<_i30.Uint8List> fetchTheme( + {required _i31.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i23.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), - ) as _i23.Future<_i29.Uint8List>); + returnValue: _i24.Future<_i30.Uint8List>.value(_i30.Uint8List(0)), + ) as _i24.Future<_i30.Uint8List>); @override - _i31.StackTheme? getTheme({required String? themeId}) => + _i32.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i31.StackTheme?); + )) as _i32.StackTheme?); } /// A class which mocks [Prefs]. /// /// See the documentation for Mockito's code generation for more information. -class MockPrefs extends _i1.Mock implements _i24.Prefs { +class MockPrefs extends _i1.Mock implements _i25.Prefs { MockPrefs() { _i1.throwOnMissingStub(this); } @@ -2119,12 +2146,12 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - _i32.SyncingType get syncType => (super.noSuchMethod( + _i33.SyncingType get syncType => (super.noSuchMethod( Invocation.getter(#syncType), - returnValue: _i32.SyncingType.currentWalletOnly, - ) as _i32.SyncingType); + returnValue: _i33.SyncingType.currentWalletOnly, + ) as _i33.SyncingType); @override - set syncType(_i32.SyncingType? syncType) => super.noSuchMethod( + set syncType(_i33.SyncingType? syncType) => super.noSuchMethod( Invocation.setter( #syncType, syncType, @@ -2236,14 +2263,14 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - bool get torKillswitch => (super.noSuchMethod( - Invocation.getter(#torKillswitch), + bool get torKillSwitch => (super.noSuchMethod( + Invocation.getter(#torKillSwitch), returnValue: false, ) as bool); @override - set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + set torKillSwitch(bool? torKillswitch) => super.noSuchMethod( Invocation.setter( - #torKillswitch, + #torKillSwitch, torKillswitch, ), returnValueForMissingStub: null, @@ -2283,12 +2310,12 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - _i33.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( + _i34.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( Invocation.getter(#backupFrequencyType), - returnValue: _i33.BackupFrequencyType.everyTenMinutes, - ) as _i33.BackupFrequencyType); + returnValue: _i34.BackupFrequencyType.everyTenMinutes, + ) as _i34.BackupFrequencyType); @override - set backupFrequencyType(_i33.BackupFrequencyType? backupFrequencyType) => + set backupFrequencyType(_i34.BackupFrequencyType? backupFrequencyType) => super.noSuchMethod( Invocation.setter( #backupFrequencyType, @@ -2439,61 +2466,61 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValue: false, ) as bool); @override - _i23.Future init() => (super.noSuchMethod( + _i24.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( + _i24.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( Invocation.method( #incrementCurrentNotificationIndex, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future isExternalCallsSet() => (super.noSuchMethod( + _i24.Future isExternalCallsSet() => (super.noSuchMethod( Invocation.method( #isExternalCallsSet, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future saveUserID(String? userId) => (super.noSuchMethod( + _i24.Future saveUserID(String? userId) => (super.noSuchMethod( Invocation.method( #saveUserID, [userId], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( + _i24.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( Invocation.method( #saveSignupEpoch, [signupEpoch], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i34.AmountUnit amountUnit(_i22.Coin? coin) => (super.noSuchMethod( + _i35.AmountUnit amountUnit(_i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #amountUnit, [coin], ), - returnValue: _i34.AmountUnit.normal, - ) as _i34.AmountUnit); + returnValue: _i35.AmountUnit.normal, + ) as _i35.AmountUnit); @override void updateAmountUnit({ - required _i22.Coin? coin, - required _i34.AmountUnit? amountUnit, + required _i23.Coin? coin, + required _i35.AmountUnit? amountUnit, }) => super.noSuchMethod( Invocation.method( @@ -2507,7 +2534,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - int maxDecimals(_i22.Coin? coin) => (super.noSuchMethod( + int maxDecimals(_i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #maxDecimals, [coin], @@ -2516,7 +2543,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { ) as int); @override void updateMaxDecimals({ - required _i22.Coin? coin, + required _i23.Coin? coin, required int? maxDecimals, }) => super.noSuchMethod( @@ -2531,7 +2558,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2539,7 +2566,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2567,7 +2594,7 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs { /// A class which mocks [LocaleService]. /// /// See the documentation for Mockito's code generation for more information. -class MockLocaleService extends _i1.Mock implements _i35.LocaleService { +class MockLocaleService extends _i1.Mock implements _i36.LocaleService { MockLocaleService() { _i1.throwOnMissingStub(this); } @@ -2583,17 +2610,17 @@ class MockLocaleService extends _i1.Mock implements _i35.LocaleService { returnValue: false, ) as bool); @override - _i23.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( + _i24.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( Invocation.method( #loadLocale, [], {#notify: notify}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2601,7 +2628,7 @@ class MockLocaleService extends _i1.Mock implements _i35.LocaleService { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2631,41 +2658,41 @@ class MockLocaleService extends _i1.Mock implements _i35.LocaleService { /// See the documentation for Mockito's code generation for more information. class MockNodeService extends _i1.Mock implements _i3.NodeService { @override - _i19.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( + _i20.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( Invocation.getter(#secureStorageInterface), - returnValue: _FakeSecureStorageInterface_17( + returnValue: _FakeSecureStorageInterface_18( this, Invocation.getter(#secureStorageInterface), ), - ) as _i19.SecureStorageInterface); + ) as _i20.SecureStorageInterface); @override - List<_i36.NodeModel> get primaryNodes => (super.noSuchMethod( + List<_i37.NodeModel> get primaryNodes => (super.noSuchMethod( Invocation.getter(#primaryNodes), - returnValue: <_i36.NodeModel>[], - ) as List<_i36.NodeModel>); + returnValue: <_i37.NodeModel>[], + ) as List<_i37.NodeModel>); @override - List<_i36.NodeModel> get nodes => (super.noSuchMethod( + List<_i37.NodeModel> get nodes => (super.noSuchMethod( Invocation.getter(#nodes), - returnValue: <_i36.NodeModel>[], - ) as List<_i36.NodeModel>); + returnValue: <_i37.NodeModel>[], + ) as List<_i37.NodeModel>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future updateDefaults() => (super.noSuchMethod( + _i24.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future setPrimaryNodeFor({ - required _i22.Coin? coin, - required _i36.NodeModel? node, + _i24.Future setPrimaryNodeFor({ + required _i23.Coin? coin, + required _i37.NodeModel? node, bool? shouldNotifyListeners = false, }) => (super.noSuchMethod( @@ -2678,44 +2705,44 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i36.NodeModel? getPrimaryNodeFor({required _i22.Coin? coin}) => + _i37.NodeModel? getPrimaryNodeFor({required _i23.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getPrimaryNodeFor, [], {#coin: coin}, - )) as _i36.NodeModel?); + )) as _i37.NodeModel?); @override - List<_i36.NodeModel> getNodesFor(_i22.Coin? coin) => (super.noSuchMethod( + List<_i37.NodeModel> getNodesFor(_i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #getNodesFor, [coin], ), - returnValue: <_i36.NodeModel>[], - ) as List<_i36.NodeModel>); + returnValue: <_i37.NodeModel>[], + ) as List<_i37.NodeModel>); @override - _i36.NodeModel? getNodeById({required String? id}) => + _i37.NodeModel? getNodeById({required String? id}) => (super.noSuchMethod(Invocation.method( #getNodeById, [], {#id: id}, - )) as _i36.NodeModel?); + )) as _i37.NodeModel?); @override - List<_i36.NodeModel> failoverNodesFor({required _i22.Coin? coin}) => + List<_i37.NodeModel> failoverNodesFor({required _i23.Coin? coin}) => (super.noSuchMethod( Invocation.method( #failoverNodesFor, [], {#coin: coin}, ), - returnValue: <_i36.NodeModel>[], - ) as List<_i36.NodeModel>); + returnValue: <_i37.NodeModel>[], + ) as List<_i37.NodeModel>); @override - _i23.Future add( - _i36.NodeModel? node, + _i24.Future add( + _i37.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => @@ -2728,11 +2755,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future delete( + _i24.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -2744,11 +2771,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future setEnabledState( + _i24.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -2762,12 +2789,12 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future edit( - _i36.NodeModel? editedNode, + _i24.Future edit( + _i37.NodeModel? editedNode, String? password, bool? shouldNotifyListeners, ) => @@ -2780,20 +2807,20 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateCommunityNodes() => (super.noSuchMethod( + _i24.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2801,7 +2828,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2844,23 +2871,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i20.CoinServiceAPI get wallet => (super.noSuchMethod( + _i21.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_18( + returnValue: _FakeCoinServiceAPI_19( this, Invocation.getter(#wallet), ), - ) as _i20.CoinServiceAPI); + ) as _i21.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -2893,23 +2920,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i23.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i24.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i8.FeeObject>); + ) as _i24.Future<_i8.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -2919,16 +2946,16 @@ class MockManager extends _i1.Mock implements _i6.Manager { ), ) as _i11.Balance); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i17.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i17.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i17.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i17.UTXO>[]), + ) as _i24.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2948,15 +2975,15 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -3003,24 +3030,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i23.Future get xpub => (super.noSuchMethod( + _i24.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -3030,7 +3057,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, required _i14.Amount? amount, Map? args, @@ -3046,27 +3073,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -3076,35 +3103,35 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -3123,20 +3150,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future exitCurrentWallet() => (super.noSuchMethod( + _i24.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -3148,11 +3175,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i14.Amount> estimateFeeFor( + _i24.Future<_i14.Amount> estimateFeeFor( _i14.Amount? amount, int? feeRate, ) => @@ -3164,7 +3191,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i23.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i24.Future<_i14.Amount>.value(_FakeAmount_12( this, Invocation.method( #estimateFeeFor, @@ -3174,26 +3201,26 @@ class MockManager extends _i1.Mock implements _i6.Manager { ], ), )), - ) as _i23.Future<_i14.Amount>); + ) as _i24.Future<_i14.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future resetRescanOnOpen() => (super.noSuchMethod( + _i24.Future resetRescanOnOpen() => (super.noSuchMethod( Invocation.method( #resetRescanOnOpen, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -3201,7 +3228,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -3221,7 +3248,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { /// A class which mocks [CoinServiceAPI]. /// /// See the documentation for Mockito's code generation for more information. -class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i21.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -3232,10 +3259,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -3268,23 +3295,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i23.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i24.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i8.FeeObject>); + ) as _i24.Future<_i8.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -3294,16 +3321,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { ), ) as _i11.Balance); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i17.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i17.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i17.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i17.UTXO>[]), + ) as _i24.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -3323,20 +3350,20 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: '', ) as String); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicString => (super.noSuchMethod( + _i24.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -3353,7 +3380,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: 0, ) as int); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, required _i14.Amount? amount, Map? args, @@ -3369,36 +3396,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -3408,15 +3435,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: false, ) as bool); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -3435,40 +3462,40 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future exit() => (super.noSuchMethod( + _i24.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -3480,11 +3507,11 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i14.Amount> estimateFeeFor( + _i24.Future<_i14.Amount> estimateFeeFor( _i14.Amount? amount, int? feeRate, ) => @@ -3496,7 +3523,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { feeRate, ], ), - returnValue: _i23.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i24.Future<_i14.Amount>.value(_FakeAmount_12( this, Invocation.method( #estimateFeeFor, @@ -3506,23 +3533,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { ], ), )), - ) as _i23.Future<_i14.Amount>); + ) as _i24.Future<_i14.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future updateSentCachedTxData(Map? txData) => + _i24.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); } diff --git a/test/widget_tests/node_options_sheet_test.mocks.dart b/test/widget_tests/node_options_sheet_test.mocks.dart index 047792e59..203e196a0 100644 --- a/test/widget_tests/node_options_sheet_test.mocks.dart +++ b/test/widget_tests/node_options_sheet_test.mocks.dart @@ -23,6 +23,7 @@ import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i15; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' as _i7; import 'package:stackwallet/utilities/prefs.dart' as _i13; +import 'package:tor_ffi_plugin/tor_ffi_plugin.dart' as _i20; import 'package:tuple/tuple.dart' as _i11; // ignore_for_file: type=lint @@ -483,14 +484,14 @@ class MockPrefs extends _i1.Mock implements _i13.Prefs { returnValueForMissingStub: null, ); @override - bool get torKillswitch => (super.noSuchMethod( - Invocation.getter(#torKillswitch), + bool get torKillSwitch => (super.noSuchMethod( + Invocation.getter(#torKillSwitch), returnValue: false, ) as bool); @override - set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + set torKillSwitch(bool? torKillswitch) => super.noSuchMethod( Invocation.setter( - #torKillswitch, + #torKillSwitch, torKillswitch, ), returnValueForMissingStub: null, @@ -1040,6 +1041,15 @@ class MockTorService extends _i1.Mock implements _i19.TorService { ), ) as ({_i8.InternetAddress host, int port})); @override + void init({_i20.Tor? mockableOverride}) => super.noSuchMethod( + Invocation.method( + #init, + [], + {#mockableOverride: mockableOverride}, + ), + returnValueForMissingStub: null, + ); + @override _i12.Future start() => (super.noSuchMethod( Invocation.method( #start, diff --git a/test/widget_tests/table_view/table_view_row_test.mocks.dart b/test/widget_tests/table_view/table_view_row_test.mocks.dart index 982bd16b1..afb3f48c9 100644 --- a/test/widget_tests/table_view/table_view_row_test.mocks.dart +++ b/test/widget_tests/table_view/table_view_row_test.mocks.dart @@ -3,40 +3,41 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i22; -import 'dart:typed_data' as _i27; -import 'dart:ui' as _i24; +import 'dart:async' as _i23; +import 'dart:typed_data' as _i28; +import 'dart:ui' as _i25; -import 'package:bip32/bip32.dart' as _i16; -import 'package:bip47/bip47.dart' as _i18; -import 'package:bitcoindart/bitcoindart.dart' as _i13; +import 'package:bip32/bip32.dart' as _i17; +import 'package:bip47/bip47.dart' as _i19; +import 'package:bitcoindart/bitcoindart.dart' as _i14; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/db/isar/main_db.dart' as _i7; -import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i11; -import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i10; -import 'package:stackwallet/models/balance.dart' as _i12; -import 'package:stackwallet/models/isar/models/isar_models.dart' as _i17; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i26; -import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i9; -import 'package:stackwallet/models/signing_data.dart' as _i30; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i28; -import 'package:stackwallet/services/coins/coin_service.dart' as _i19; +import 'package:stackwallet/db/isar/main_db.dart' as _i8; +import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i12; +import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i11; +import 'package:stackwallet/models/balance.dart' as _i13; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i18; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i27; +import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i10; +import 'package:stackwallet/models/signing_data.dart' as _i31; +import 'package:stackwallet/networking/http.dart' as _i7; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i29; +import 'package:stackwallet/services/coins/coin_service.dart' as _i20; import 'package:stackwallet/services/coins/manager.dart' as _i6; import 'package:stackwallet/services/node_service.dart' as _i3; import 'package:stackwallet/services/transaction_notification_tracker.dart' - as _i8; -import 'package:stackwallet/services/wallets.dart' as _i20; + as _i9; +import 'package:stackwallet/services/wallets.dart' as _i21; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/themes/theme_service.dart' as _i25; -import 'package:stackwallet/utilities/amount/amount.dart' as _i14; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i21; -import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i29; +import 'package:stackwallet/themes/theme_service.dart' as _i26; +import 'package:stackwallet/utilities/amount/amount.dart' as _i15; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i22; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i30; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' - as _i31; -import 'package:stackwallet/utilities/prefs.dart' as _i23; -import 'package:tuple/tuple.dart' as _i15; + as _i32; +import 'package:stackwallet/utilities/prefs.dart' as _i24; +import 'package:tuple/tuple.dart' as _i16; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -91,8 +92,8 @@ class _FakeManager_3 extends _i1.SmartFake implements _i6.Manager { ); } -class _FakeMainDB_4 extends _i1.SmartFake implements _i7.MainDB { - _FakeMainDB_4( +class _FakeHTTP_4 extends _i1.SmartFake implements _i7.HTTP { + _FakeHTTP_4( Object parent, Invocation parentInvocation, ) : super( @@ -101,9 +102,8 @@ class _FakeMainDB_4 extends _i1.SmartFake implements _i7.MainDB { ); } -class _FakeTransactionNotificationTracker_5 extends _i1.SmartFake - implements _i8.TransactionNotificationTracker { - _FakeTransactionNotificationTracker_5( +class _FakeMainDB_5 extends _i1.SmartFake implements _i8.MainDB { + _FakeMainDB_5( Object parent, Invocation parentInvocation, ) : super( @@ -112,8 +112,9 @@ class _FakeTransactionNotificationTracker_5 extends _i1.SmartFake ); } -class _FakeFeeObject_6 extends _i1.SmartFake implements _i9.FeeObject { - _FakeFeeObject_6( +class _FakeTransactionNotificationTracker_6 extends _i1.SmartFake + implements _i9.TransactionNotificationTracker { + _FakeTransactionNotificationTracker_6( Object parent, Invocation parentInvocation, ) : super( @@ -122,8 +123,8 @@ class _FakeFeeObject_6 extends _i1.SmartFake implements _i9.FeeObject { ); } -class _FakeElectrumX_7 extends _i1.SmartFake implements _i10.ElectrumX { - _FakeElectrumX_7( +class _FakeFeeObject_7 extends _i1.SmartFake implements _i10.FeeObject { + _FakeFeeObject_7( Object parent, Invocation parentInvocation, ) : super( @@ -132,9 +133,8 @@ class _FakeElectrumX_7 extends _i1.SmartFake implements _i10.ElectrumX { ); } -class _FakeCachedElectrumX_8 extends _i1.SmartFake - implements _i11.CachedElectrumX { - _FakeCachedElectrumX_8( +class _FakeElectrumX_8 extends _i1.SmartFake implements _i11.ElectrumX { + _FakeElectrumX_8( Object parent, Invocation parentInvocation, ) : super( @@ -143,8 +143,9 @@ class _FakeCachedElectrumX_8 extends _i1.SmartFake ); } -class _FakeBalance_9 extends _i1.SmartFake implements _i12.Balance { - _FakeBalance_9( +class _FakeCachedElectrumX_9 extends _i1.SmartFake + implements _i12.CachedElectrumX { + _FakeCachedElectrumX_9( Object parent, Invocation parentInvocation, ) : super( @@ -153,8 +154,8 @@ class _FakeBalance_9 extends _i1.SmartFake implements _i12.Balance { ); } -class _FakeNetworkType_10 extends _i1.SmartFake implements _i13.NetworkType { - _FakeNetworkType_10( +class _FakeBalance_10 extends _i1.SmartFake implements _i13.Balance { + _FakeBalance_10( Object parent, Invocation parentInvocation, ) : super( @@ -163,9 +164,8 @@ class _FakeNetworkType_10 extends _i1.SmartFake implements _i13.NetworkType { ); } -class _FakeElectrumXNode_11 extends _i1.SmartFake - implements _i10.ElectrumXNode { - _FakeElectrumXNode_11( +class _FakeNetworkType_11 extends _i1.SmartFake implements _i14.NetworkType { + _FakeNetworkType_11( Object parent, Invocation parentInvocation, ) : super( @@ -174,8 +174,9 @@ class _FakeElectrumXNode_11 extends _i1.SmartFake ); } -class _FakeAmount_12 extends _i1.SmartFake implements _i14.Amount { - _FakeAmount_12( +class _FakeElectrumXNode_12 extends _i1.SmartFake + implements _i11.ElectrumXNode { + _FakeElectrumXNode_12( Object parent, Invocation parentInvocation, ) : super( @@ -184,9 +185,8 @@ class _FakeAmount_12 extends _i1.SmartFake implements _i14.Amount { ); } -class _FakeTuple2_13 extends _i1.SmartFake - implements _i15.Tuple2 { - _FakeTuple2_13( +class _FakeAmount_13 extends _i1.SmartFake implements _i15.Amount { + _FakeAmount_13( Object parent, Invocation parentInvocation, ) : super( @@ -195,8 +195,9 @@ class _FakeTuple2_13 extends _i1.SmartFake ); } -class _FakeBIP32_14 extends _i1.SmartFake implements _i16.BIP32 { - _FakeBIP32_14( +class _FakeTuple2_14 extends _i1.SmartFake + implements _i16.Tuple2 { + _FakeTuple2_14( Object parent, Invocation parentInvocation, ) : super( @@ -205,8 +206,8 @@ class _FakeBIP32_14 extends _i1.SmartFake implements _i16.BIP32 { ); } -class _FakeAddress_15 extends _i1.SmartFake implements _i17.Address { - _FakeAddress_15( +class _FakeBIP32_15 extends _i1.SmartFake implements _i17.BIP32 { + _FakeBIP32_15( Object parent, Invocation parentInvocation, ) : super( @@ -215,8 +216,8 @@ class _FakeAddress_15 extends _i1.SmartFake implements _i17.Address { ); } -class _FakePaymentCode_16 extends _i1.SmartFake implements _i18.PaymentCode { - _FakePaymentCode_16( +class _FakeAddress_16 extends _i1.SmartFake implements _i18.Address { + _FakeAddress_16( Object parent, Invocation parentInvocation, ) : super( @@ -225,9 +226,19 @@ class _FakePaymentCode_16 extends _i1.SmartFake implements _i18.PaymentCode { ); } -class _FakeCoinServiceAPI_17 extends _i1.SmartFake - implements _i19.CoinServiceAPI { - _FakeCoinServiceAPI_17( +class _FakePaymentCode_17 extends _i1.SmartFake implements _i19.PaymentCode { + _FakePaymentCode_17( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_18 extends _i1.SmartFake + implements _i20.CoinServiceAPI { + _FakeCoinServiceAPI_18( Object parent, Invocation parentInvocation, ) : super( @@ -239,7 +250,7 @@ class _FakeCoinServiceAPI_17 extends _i1.SmartFake /// A class which mocks [Wallets]. /// /// See the documentation for Mockito's code generation for more information. -class MockWallets extends _i1.Mock implements _i20.Wallets { +class MockWallets extends _i1.Mock implements _i21.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -306,7 +317,7 @@ class MockWallets extends _i1.Mock implements _i20.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i21.Coin? coin}) => + List getWalletIdsFor({required _i22.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -316,20 +327,20 @@ class MockWallets extends _i1.Mock implements _i20.Wallets { returnValue: [], ) as List); @override - List<_i15.Tuple2<_i21.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> + List<_i16.Tuple2<_i22.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i15.Tuple2<_i21.Coin, + returnValue: <_i16.Tuple2<_i22.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>[], ) as List< - _i15.Tuple2<_i21.Coin, + _i16.Tuple2<_i22.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i21.Coin? coin) => + _i22.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -393,17 +404,17 @@ class MockWallets extends _i1.Mock implements _i20.Wallets { returnValueForMissingStub: null, ); @override - _i22.Future load(_i23.Prefs? prefs) => (super.noSuchMethod( + _i23.Future load(_i24.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future loadAfterStackRestore( - _i23.Prefs? prefs, + _i23.Future loadAfterStackRestore( + _i24.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -414,11 +425,11 @@ class MockWallets extends _i1.Mock implements _i20.Wallets { managers, ], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - void addListener(_i24.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -426,7 +437,7 @@ class MockWallets extends _i1.Mock implements _i20.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i24.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -452,19 +463,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i22.Future> get walletNames => + _i23.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i22.Future>.value( + returnValue: _i23.Future>.value( {}), - ) as _i22.Future>); + ) as _i23.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i22.Future renameWallet({ + _i23.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -479,8 +490,8 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override Map fetchWalletsData() => (super.noSuchMethod( Invocation.method( @@ -490,10 +501,10 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValue: {}, ) as Map); @override - _i22.Future addExistingStackWallet({ + _i23.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i21.Coin? coin, + required _i22.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -507,13 +518,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future addNewWallet({ + _i23.Future addNewWallet({ required String? name, - required _i21.Coin? coin, + required _i22.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -526,46 +537,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i23.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i22.Future>.value([]), - ) as _i22.Future>); + returnValue: _i23.Future>.value([]), + ) as _i23.Future>); @override - _i22.Future saveFavoriteWalletIds(List? walletIds) => + _i23.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i23.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i23.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future moveFavorite({ + _i23.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -578,48 +589,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i23.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i23.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future isMnemonicVerified({required String? walletId}) => + _i23.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future setMnemonicVerified({required String? walletId}) => + _i23.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future deleteWallet( + _i23.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -631,20 +642,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i22.Future.value(0), - ) as _i22.Future); + returnValue: _i23.Future.value(0), + ) as _i23.Future); @override - _i22.Future refreshWallets(bool? shouldNotifyListeners) => + _i23.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - void addListener(_i24.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -652,7 +663,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i24.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -680,26 +691,42 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i25.ThemeService { +class MockThemeService extends _i1.Mock implements _i26.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } @override - _i7.MainDB get db => (super.noSuchMethod( + _i7.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_4( + this, + Invocation.getter(#client), + ), + ) as _i7.HTTP); + @override + set client(_i7.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); + @override + _i8.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_4( + returnValue: _FakeMainDB_5( this, Invocation.getter(#db), ), - ) as _i7.MainDB); + ) as _i8.MainDB); @override - List<_i26.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i27.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i26.StackTheme>[], - ) as List<_i26.StackTheme>); + returnValue: <_i27.StackTheme>[], + ) as List<_i27.StackTheme>); @override - void init(_i7.MainDB? db) => super.noSuchMethod( + void init(_i8.MainDB? db) => super.noSuchMethod( Invocation.method( #init, [db], @@ -707,85 +734,85 @@ class MockThemeService extends _i1.Mock implements _i25.ThemeService { returnValueForMissingStub: null, ); @override - _i22.Future install({required _i27.Uint8List? themeArchiveData}) => + _i23.Future install({required _i28.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future remove({required String? themeId}) => (super.noSuchMethod( + _i23.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i23.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future verifyInstalled({required String? themeId}) => + _i23.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future> fetchThemes() => + _i23.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i22.Future>.value( - <_i25.StackThemeMetaData>[]), - ) as _i22.Future>); + returnValue: _i23.Future>.value( + <_i26.StackThemeMetaData>[]), + ) as _i23.Future>); @override - _i22.Future<_i27.Uint8List> fetchTheme( - {required _i25.StackThemeMetaData? themeMetaData}) => + _i23.Future<_i28.Uint8List> fetchTheme( + {required _i26.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i22.Future<_i27.Uint8List>.value(_i27.Uint8List(0)), - ) as _i22.Future<_i27.Uint8List>); + returnValue: _i23.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), + ) as _i23.Future<_i28.Uint8List>); @override - _i26.StackTheme? getTheme({required String? themeId}) => + _i27.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i26.StackTheme?); + )) as _i27.StackTheme?); } /// A class which mocks [BitcoinWallet]. /// /// See the documentation for Mockito's code generation for more information. -class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i22.Timer? _timer) => super.noSuchMethod( + set timer(_i23.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -793,15 +820,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i8.TransactionNotificationTracker get txTracker => (super.noSuchMethod( + _i9.TransactionNotificationTracker get txTracker => (super.noSuchMethod( Invocation.getter(#txTracker), - returnValue: _FakeTransactionNotificationTracker_5( + returnValue: _FakeTransactionNotificationTracker_6( this, Invocation.getter(#txTracker), ), - ) as _i8.TransactionNotificationTracker); + ) as _i9.TransactionNotificationTracker); @override - set txTracker(_i8.TransactionNotificationTracker? _txTracker) => + set txTracker(_i9.TransactionNotificationTracker? _txTracker) => super.noSuchMethod( Invocation.setter( #txTracker, @@ -862,74 +889,74 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValue: false, ) as bool); @override - _i21.Coin get coin => (super.noSuchMethod( + _i22.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i21.Coin.bitcoin, - ) as _i21.Coin); + returnValue: _i22.Coin.bitcoin, + ) as _i22.Coin); @override - _i22.Future> get utxos => (super.noSuchMethod( + _i23.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i22.Future>.value(<_i17.UTXO>[]), - ) as _i22.Future>); + returnValue: _i23.Future>.value(<_i18.UTXO>[]), + ) as _i23.Future>); @override - _i22.Future> get transactions => (super.noSuchMethod( + _i23.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i22.Future>.value(<_i17.Transaction>[]), - ) as _i22.Future>); + _i23.Future>.value(<_i18.Transaction>[]), + ) as _i23.Future>); @override - _i22.Future get currentReceivingAddress => (super.noSuchMethod( + _i23.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i22.Future get currentChangeAddress => (super.noSuchMethod( + _i23.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i22.Future get currentChangeAddressP2PKH => (super.noSuchMethod( + _i23.Future get currentChangeAddressP2PKH => (super.noSuchMethod( Invocation.getter(#currentChangeAddressP2PKH), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i22.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i23.Future<_i10.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i22.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i23.Future<_i10.FeeObject>.value(_FakeFeeObject_7( this, Invocation.getter(#fees), )), - ) as _i22.Future<_i9.FeeObject>); + ) as _i23.Future<_i10.FeeObject>); @override - _i22.Future get maxFee => (super.noSuchMethod( + _i23.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i22.Future.value(0), - ) as _i22.Future); + returnValue: _i23.Future.value(0), + ) as _i23.Future); @override - _i22.Future> get mnemonic => (super.noSuchMethod( + _i23.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i22.Future>.value([]), - ) as _i22.Future>); + returnValue: _i23.Future>.value([]), + ) as _i23.Future>); @override - _i22.Future get mnemonicString => (super.noSuchMethod( + _i23.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future get mnemonicPassphrase => (super.noSuchMethod( + _i23.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future get chainHeight => (super.noSuchMethod( + _i23.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i22.Future.value(0), - ) as _i22.Future); + returnValue: _i23.Future.value(0), + ) as _i23.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -977,34 +1004,34 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i10.ElectrumX get electrumXClient => (super.noSuchMethod( + _i11.ElectrumX get electrumXClient => (super.noSuchMethod( Invocation.getter(#electrumXClient), - returnValue: _FakeElectrumX_7( + returnValue: _FakeElectrumX_8( this, Invocation.getter(#electrumXClient), ), - ) as _i10.ElectrumX); + ) as _i11.ElectrumX); @override - _i11.CachedElectrumX get cachedElectrumXClient => (super.noSuchMethod( + _i12.CachedElectrumX get cachedElectrumXClient => (super.noSuchMethod( Invocation.getter(#cachedElectrumXClient), - returnValue: _FakeCachedElectrumX_8( + returnValue: _FakeCachedElectrumX_9( this, Invocation.getter(#cachedElectrumXClient), ), - ) as _i11.CachedElectrumX); + ) as _i12.CachedElectrumX); @override - _i12.Balance get balance => (super.noSuchMethod( + _i13.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.getter(#balance), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i22.Future get xpub => (super.noSuchMethod( + _i23.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -1015,42 +1042,42 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i7.MainDB get db => (super.noSuchMethod( + _i8.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_4( + returnValue: _FakeMainDB_5( this, Invocation.getter(#db), ), - ) as _i7.MainDB); + ) as _i8.MainDB); @override - _i13.NetworkType get networkType => (super.noSuchMethod( + _i14.NetworkType get networkType => (super.noSuchMethod( Invocation.getter(#networkType), - returnValue: _FakeNetworkType_10( + returnValue: _FakeNetworkType_11( this, Invocation.getter(#networkType), ), - ) as _i13.NetworkType); + ) as _i14.NetworkType); @override - _i22.Future exit() => (super.noSuchMethod( + _i23.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i29.DerivePathType addressType({required String? address}) => + _i30.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i29.DerivePathType.bip44, - ) as _i29.DerivePathType); + returnValue: _i30.DerivePathType.bip44, + ) as _i30.DerivePathType); @override - _i22.Future recoverFromMnemonic({ + _i23.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -1069,49 +1096,49 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { #height: height, }, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future getTransactionCacheEarly(List? allAddresses) => + _i23.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i23.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future getAllTxsToWatch() => (super.noSuchMethod( + _i23.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future refresh() => (super.noSuchMethod( + _i23.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future> prepareSend({ + _i23.Future> prepareSend({ required String? address, - required _i14.Amount? amount, + required _i15.Amount? amount, Map? args, }) => (super.noSuchMethod( @@ -1125,26 +1152,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { }, ), returnValue: - _i22.Future>.value({}), - ) as _i22.Future>); + _i23.Future>.value({}), + ) as _i23.Future>); @override - _i22.Future confirmSend({required Map? txData}) => + _i23.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i22.Future testNetworkConnection() => (super.noSuchMethod( + _i23.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -1162,35 +1189,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i22.Future initializeNew( + _i23.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future initializeExisting() => (super.noSuchMethod( + _i23.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future updateSentCachedTxData(Map? txData) => + _i23.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1200,70 +1227,70 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValue: false, ) as bool); @override - _i22.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future<_i10.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i23.Future<_i11.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), returnValue: - _i22.Future<_i10.ElectrumXNode>.value(_FakeElectrumXNode_11( + _i23.Future<_i11.ElectrumXNode>.value(_FakeElectrumXNode_12( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i22.Future<_i10.ElectrumXNode>); + ) as _i23.Future<_i11.ElectrumXNode>); @override - _i22.Future>> fastFetch( + _i23.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i22.Future>>.value( + returnValue: _i23.Future>>.value( >[]), - ) as _i22.Future>>); + ) as _i23.Future>>); @override - _i22.Future getTxCount({required String? address}) => + _i23.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i22.Future.value(0), - ) as _i22.Future); + returnValue: _i23.Future.value(0), + ) as _i23.Future); @override - _i22.Future checkCurrentReceivingAddressesForTransactions() => + _i23.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future checkCurrentChangeAddressesForTransactions() => + _i23.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override int estimateTxFee({ required int? vSize, @@ -1289,7 +1316,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { required bool? isSendAll, int? satsPerVByte, int? additionalOutputs = 0, - List<_i17.UTXO>? utxos, + List<_i18.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -1306,19 +1333,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { }, )); @override - _i22.Future> fetchBuildTxData( - List<_i17.UTXO>? utxosToUse) => + _i23.Future> fetchBuildTxData( + List<_i18.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i22.Future>.value(<_i30.SigningData>[]), - ) as _i22.Future>); + _i23.Future>.value(<_i31.SigningData>[]), + ) as _i23.Future>); @override - _i22.Future> buildTransaction({ - required List<_i30.SigningData>? utxoSigningData, + _i23.Future> buildTransaction({ + required List<_i31.SigningData>? utxoSigningData, required List? recipients, required List? satoshiAmounts, }) => @@ -1333,10 +1360,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { }, ), returnValue: - _i22.Future>.value({}), - ) as _i22.Future>); + _i23.Future>.value({}), + ) as _i23.Future>); @override - _i22.Future fullRescan( + _i23.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1348,12 +1375,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future<_i14.Amount> estimateFeeFor( - _i14.Amount? amount, + _i23.Future<_i15.Amount> estimateFeeFor( + _i15.Amount? amount, int? feeRate, ) => (super.noSuchMethod( @@ -1364,7 +1391,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { feeRate, ], ), - returnValue: _i22.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i23.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -1374,9 +1401,9 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { ], ), )), - ) as _i22.Future<_i14.Amount>); + ) as _i23.Future<_i15.Amount>); @override - _i14.Amount roughFeeEstimate( + _i15.Amount roughFeeEstimate( int? inputCount, int? outputCount, int? feeRatePerKB, @@ -1390,7 +1417,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { feeRatePerKB, ], ), - returnValue: _FakeAmount_12( + returnValue: _FakeAmount_13( this, Invocation.method( #roughFeeEstimate, @@ -1401,34 +1428,34 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { ], ), ), - ) as _i14.Amount); + ) as _i15.Amount); @override - _i22.Future<_i14.Amount> sweepAllEstimate(int? feeRate) => + _i23.Future<_i15.Amount> sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i22.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i23.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #sweepAllEstimate, [feeRate], ), )), - ) as _i22.Future<_i14.Amount>); + ) as _i23.Future<_i15.Amount>); @override - _i22.Future generateNewAddress() => (super.noSuchMethod( + _i23.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override void initCache( String? walletId, - _i21.Coin? coin, + _i22.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1441,14 +1468,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i22.Future updateCachedId(String? id) => (super.noSuchMethod( + _i23.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1458,14 +1485,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValue: 0, ) as int); @override - _i22.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i23.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1475,63 +1502,63 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValue: false, ) as bool); @override - _i22.Future updateCachedIsFavorite(bool? isFavorite) => + _i23.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i12.Balance getCachedBalance() => (super.noSuchMethod( + _i13.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( #getCachedBalance, [], ), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.method( #getCachedBalance, [], ), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i22.Future updateCachedBalance(_i12.Balance? balance) => + _i23.Future updateCachedBalance(_i13.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i12.Balance getCachedBalanceSecondary() => (super.noSuchMethod( + _i13.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( #getCachedBalanceSecondary, [], ), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.method( #getCachedBalanceSecondary, [], ), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i22.Future updateCachedBalanceSecondary(_i12.Balance? balance) => + _i23.Future updateCachedBalanceSecondary(_i13.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override List getWalletTokenContractAddresses() => (super.noSuchMethod( Invocation.method( @@ -1541,18 +1568,18 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValue: [], ) as List); @override - _i22.Future updateWalletTokenContractAddresses( + _i23.Future updateWalletTokenContractAddresses( List? contractAddresses) => (super.noSuchMethod( Invocation.method( #updateWalletTokenContractAddresses, [contractAddresses], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - void initWalletDB({_i7.MainDB? mockableOverride}) => super.noSuchMethod( + void initWalletDB({_i8.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( #initWalletDB, [], @@ -1561,11 +1588,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i22.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>> parseTransaction( + _i23.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>> parseTransaction( Map? txData, dynamic electrumxClient, - List<_i17.Address>? myAddresses, - _i21.Coin? coin, + List<_i18.Address>? myAddresses, + _i22.Coin? coin, int? minConfirms, String? walletId, ) => @@ -1582,8 +1609,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { ], ), returnValue: - _i22.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>.value( - _FakeTuple2_13<_i17.Transaction, _i17.Address>( + _i23.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>>.value( + _FakeTuple2_14<_i18.Transaction, _i18.Address>( this, Invocation.method( #parseTransaction, @@ -1597,37 +1624,37 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { ], ), )), - ) as _i22.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>); + ) as _i23.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>>); @override void initPaynymWalletInterface({ required String? walletId, required String? walletName, - required _i13.NetworkType? network, - required _i21.Coin? coin, - required _i7.MainDB? db, - required _i10.ElectrumX? electrumXClient, - required _i31.SecureStorageInterface? secureStorage, + required _i14.NetworkType? network, + required _i22.Coin? coin, + required _i8.MainDB? db, + required _i11.ElectrumX? electrumXClient, + required _i32.SecureStorageInterface? secureStorage, required int? dustLimit, required int? dustLimitP2PKH, required int? minConfirms, - required _i22.Future Function()? getMnemonicString, - required _i22.Future Function()? getMnemonicPassphrase, - required _i22.Future Function()? getChainHeight, - required _i22.Future Function()? getCurrentChangeAddress, + required _i23.Future Function()? getMnemonicString, + required _i23.Future Function()? getMnemonicPassphrase, + required _i23.Future Function()? getChainHeight, + required _i23.Future Function()? getCurrentChangeAddress, required int Function({ required int feeRatePerKB, required int vSize, })? estimateTxFee, - required _i22.Future> Function({ + required _i23.Future> Function({ required String address, - required _i14.Amount amount, + required _i15.Amount amount, Map? args, })? prepareSend, - required _i22.Future Function({required String address})? getTxCount, - required _i22.Future> Function(List<_i17.UTXO>)? + required _i23.Future Function({required String address})? getTxCount, + required _i23.Future> Function(List<_i18.UTXO>)? fetchBuildTxData, - required _i22.Future Function()? refresh, - required _i22.Future Function()? checkChangeAddressForTransactions, + required _i23.Future Function()? refresh, + required _i23.Future Function()? checkChangeAddressForTransactions, }) => super.noSuchMethod( Invocation.method( @@ -1660,21 +1687,21 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i22.Future<_i16.BIP32> getBip47BaseNode() => (super.noSuchMethod( + _i23.Future<_i17.BIP32> getBip47BaseNode() => (super.noSuchMethod( Invocation.method( #getBip47BaseNode, [], ), - returnValue: _i22.Future<_i16.BIP32>.value(_FakeBIP32_14( + returnValue: _i23.Future<_i17.BIP32>.value(_FakeBIP32_15( this, Invocation.method( #getBip47BaseNode, [], ), )), - ) as _i22.Future<_i16.BIP32>); + ) as _i23.Future<_i17.BIP32>); @override - _i22.Future<_i27.Uint8List> getPrivateKeyForPaynymReceivingAddress({ + _i23.Future<_i28.Uint8List> getPrivateKeyForPaynymReceivingAddress({ required String? paymentCodeString, required int? index, }) => @@ -1687,11 +1714,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { #index: index, }, ), - returnValue: _i22.Future<_i27.Uint8List>.value(_i27.Uint8List(0)), - ) as _i22.Future<_i27.Uint8List>); + returnValue: _i23.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), + ) as _i23.Future<_i28.Uint8List>); @override - _i22.Future<_i17.Address> currentReceivingPaynymAddress({ - required _i18.PaymentCode? sender, + _i23.Future<_i18.Address> currentReceivingPaynymAddress({ + required _i19.PaymentCode? sender, required bool? isSegwit, }) => (super.noSuchMethod( @@ -1703,7 +1730,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i22.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i23.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #currentReceivingPaynymAddress, @@ -1714,10 +1741,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { }, ), )), - ) as _i22.Future<_i17.Address>); + ) as _i23.Future<_i18.Address>); @override - _i22.Future checkCurrentPaynymReceivingAddressForTransactions({ - required _i18.PaymentCode? sender, + _i23.Future checkCurrentPaynymReceivingAddressForTransactions({ + required _i19.PaymentCode? sender, required bool? isSegwit, }) => (super.noSuchMethod( @@ -1729,42 +1756,42 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => + _i23.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkAllCurrentReceivingPaynymAddressesForTransactions, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future<_i16.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( + _i23.Future<_i17.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( Invocation.method( #deriveNotificationBip32Node, [], ), - returnValue: _i22.Future<_i16.BIP32>.value(_FakeBIP32_14( + returnValue: _i23.Future<_i17.BIP32>.value(_FakeBIP32_15( this, Invocation.method( #deriveNotificationBip32Node, [], ), )), - ) as _i22.Future<_i16.BIP32>); + ) as _i23.Future<_i17.BIP32>); @override - _i22.Future<_i18.PaymentCode> getPaymentCode({required bool? isSegwit}) => + _i23.Future<_i19.PaymentCode> getPaymentCode({required bool? isSegwit}) => (super.noSuchMethod( Invocation.method( #getPaymentCode, [], {#isSegwit: isSegwit}, ), - returnValue: _i22.Future<_i18.PaymentCode>.value(_FakePaymentCode_16( + returnValue: _i23.Future<_i19.PaymentCode>.value(_FakePaymentCode_17( this, Invocation.method( #getPaymentCode, @@ -1772,30 +1799,30 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { {#isSegwit: isSegwit}, ), )), - ) as _i22.Future<_i18.PaymentCode>); + ) as _i23.Future<_i19.PaymentCode>); @override - _i22.Future<_i27.Uint8List> signWithNotificationKey(_i27.Uint8List? data) => + _i23.Future<_i28.Uint8List> signWithNotificationKey(_i28.Uint8List? data) => (super.noSuchMethod( Invocation.method( #signWithNotificationKey, [data], ), - returnValue: _i22.Future<_i27.Uint8List>.value(_i27.Uint8List(0)), - ) as _i22.Future<_i27.Uint8List>); + returnValue: _i23.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), + ) as _i23.Future<_i28.Uint8List>); @override - _i22.Future signStringWithNotificationKey(String? data) => + _i23.Future signStringWithNotificationKey(String? data) => (super.noSuchMethod( Invocation.method( #signStringWithNotificationKey, [data], ), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i22.Future> preparePaymentCodeSend({ - required _i18.PaymentCode? paymentCode, + _i23.Future> preparePaymentCodeSend({ + required _i19.PaymentCode? paymentCode, required bool? isSegwit, - required _i14.Amount? amount, + required _i15.Amount? amount, Map? args, }) => (super.noSuchMethod( @@ -1810,13 +1837,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { }, ), returnValue: - _i22.Future>.value({}), - ) as _i22.Future>); + _i23.Future>.value({}), + ) as _i23.Future>); @override - _i22.Future<_i17.Address> nextUnusedSendAddressFrom({ - required _i18.PaymentCode? pCode, + _i23.Future<_i18.Address> nextUnusedSendAddressFrom({ + required _i19.PaymentCode? pCode, required bool? isSegwit, - required _i16.BIP32? privateKeyNode, + required _i17.BIP32? privateKeyNode, int? startIndex = 0, }) => (super.noSuchMethod( @@ -1830,7 +1857,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { #startIndex: startIndex, }, ), - returnValue: _i22.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i23.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #nextUnusedSendAddressFrom, @@ -1843,13 +1870,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { }, ), )), - ) as _i22.Future<_i17.Address>); + ) as _i23.Future<_i18.Address>); @override - _i22.Future> prepareNotificationTx({ + _i23.Future> prepareNotificationTx({ required int? selectedTxFeeRate, required String? targetPaymentCodeString, int? additionalOutputs = 0, - List<_i17.UTXO>? utxos, + List<_i18.UTXO>? utxos, }) => (super.noSuchMethod( Invocation.method( @@ -1863,10 +1890,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { }, ), returnValue: - _i22.Future>.value({}), - ) as _i22.Future>); + _i23.Future>.value({}), + ) as _i23.Future>); @override - _i22.Future broadcastNotificationTx( + _i23.Future broadcastNotificationTx( {required Map? preparedTx}) => (super.noSuchMethod( Invocation.method( @@ -1874,62 +1901,62 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { [], {#preparedTx: preparedTx}, ), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i22.Future hasConnected(String? paymentCodeString) => + _i23.Future hasConnected(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #hasConnected, [paymentCodeString], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransaction( - {required _i17.Transaction? transaction}) => + _i23.Future<_i19.PaymentCode?> unBlindedPaymentCodeFromTransaction( + {required _i18.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( #unBlindedPaymentCodeFromTransaction, [], {#transaction: transaction}, ), - returnValue: _i22.Future<_i18.PaymentCode?>.value(), - ) as _i22.Future<_i18.PaymentCode?>); + returnValue: _i23.Future<_i19.PaymentCode?>.value(), + ) as _i23.Future<_i19.PaymentCode?>); @override - _i22.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( - {required _i17.Transaction? transaction}) => + _i23.Future<_i19.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( + {required _i18.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( #unBlindedPaymentCodeFromTransactionBad, [], {#transaction: transaction}, ), - returnValue: _i22.Future<_i18.PaymentCode?>.value(), - ) as _i22.Future<_i18.PaymentCode?>); + returnValue: _i23.Future<_i19.PaymentCode?>.value(), + ) as _i23.Future<_i19.PaymentCode?>); @override - _i22.Future> + _i23.Future> getAllPaymentCodesFromNotificationTransactions() => (super.noSuchMethod( Invocation.method( #getAllPaymentCodesFromNotificationTransactions, [], ), returnValue: - _i22.Future>.value(<_i18.PaymentCode>[]), - ) as _i22.Future>); + _i23.Future>.value(<_i19.PaymentCode>[]), + ) as _i23.Future>); @override - _i22.Future checkForNotificationTransactionsTo( + _i23.Future checkForNotificationTransactionsTo( Set? otherCodeStrings) => (super.noSuchMethod( Invocation.method( #checkForNotificationTransactionsTo, [otherCodeStrings], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future restoreAllHistory({ + _i23.Future restoreAllHistory({ required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, required Set? paymentCodeStrings, @@ -1944,12 +1971,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { #paymentCodeStrings: paymentCodeStrings, }, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future restoreHistoryWith({ - required _i18.PaymentCode? other, + _i23.Future restoreHistoryWith({ + required _i19.PaymentCode? other, required bool? checkSegwitAsWell, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -1965,58 +1992,58 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { #maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, }, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future<_i17.Address> getMyNotificationAddress() => (super.noSuchMethod( + _i23.Future<_i18.Address> getMyNotificationAddress() => (super.noSuchMethod( Invocation.method( #getMyNotificationAddress, [], ), - returnValue: _i22.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i23.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #getMyNotificationAddress, [], ), )), - ) as _i22.Future<_i17.Address>); + ) as _i23.Future<_i18.Address>); @override - _i22.Future> lookupKey(String? paymentCodeString) => + _i23.Future> lookupKey(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #lookupKey, [paymentCodeString], ), - returnValue: _i22.Future>.value([]), - ) as _i22.Future>); + returnValue: _i23.Future>.value([]), + ) as _i23.Future>); @override - _i22.Future paymentCodeStringByKey(String? key) => + _i23.Future paymentCodeStringByKey(String? key) => (super.noSuchMethod( Invocation.method( #paymentCodeStringByKey, [key], ), - returnValue: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future storeCode(String? paymentCodeString) => + _i23.Future storeCode(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #storeCode, [paymentCodeString], ), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override void initCoinControlInterface({ required String? walletId, required String? walletName, - required _i21.Coin? coin, - required _i7.MainDB? db, - required _i22.Future Function()? getChainHeight, - required _i22.Future Function(_i12.Balance)? refreshedBalanceCallback, + required _i22.Coin? coin, + required _i8.MainDB? db, + required _i23.Future Function()? getChainHeight, + required _i23.Future Function(_i13.Balance)? refreshedBalanceCallback, }) => super.noSuchMethod( Invocation.method( @@ -2034,16 +2061,16 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i22.Future refreshBalance({bool? notify = false}) => + _i23.Future refreshBalance({bool? notify = false}) => (super.noSuchMethod( Invocation.method( #refreshBalance, [], {#notify: notify}, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); } /// A class which mocks [Manager]. @@ -2064,23 +2091,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i19.CoinServiceAPI get wallet => (super.noSuchMethod( + _i20.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_17( + returnValue: _FakeCoinServiceAPI_18( this, Invocation.getter(#wallet), ), - ) as _i19.CoinServiceAPI); + ) as _i20.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i21.Coin get coin => (super.noSuchMethod( + _i22.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i21.Coin.bitcoin, - ) as _i21.Coin); + returnValue: _i22.Coin.bitcoin, + ) as _i22.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -2113,42 +2140,42 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i22.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i23.Future<_i10.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i22.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i23.Future<_i10.FeeObject>.value(_FakeFeeObject_7( this, Invocation.getter(#fees), )), - ) as _i22.Future<_i9.FeeObject>); + ) as _i23.Future<_i10.FeeObject>); @override - _i22.Future get maxFee => (super.noSuchMethod( + _i23.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i22.Future.value(0), - ) as _i22.Future); + returnValue: _i23.Future.value(0), + ) as _i23.Future); @override - _i22.Future get currentReceivingAddress => (super.noSuchMethod( + _i23.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i12.Balance get balance => (super.noSuchMethod( + _i13.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.getter(#balance), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i22.Future> get transactions => (super.noSuchMethod( + _i23.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i22.Future>.value(<_i17.Transaction>[]), - ) as _i22.Future>); + _i23.Future>.value(<_i18.Transaction>[]), + ) as _i23.Future>); @override - _i22.Future> get utxos => (super.noSuchMethod( + _i23.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i22.Future>.value(<_i17.UTXO>[]), - ) as _i22.Future>); + returnValue: _i23.Future>.value(<_i18.UTXO>[]), + ) as _i23.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2168,15 +2195,15 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i22.Future> get mnemonic => (super.noSuchMethod( + _i23.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i22.Future>.value([]), - ) as _i22.Future>); + returnValue: _i23.Future>.value([]), + ) as _i23.Future>); @override - _i22.Future get mnemonicPassphrase => (super.noSuchMethod( + _i23.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + ) as _i23.Future); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -2223,24 +2250,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i22.Future get xpub => (super.noSuchMethod( + _i23.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i22.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -2250,9 +2277,9 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i22.Future> prepareSend({ + _i23.Future> prepareSend({ required String? address, - required _i14.Amount? amount, + required _i15.Amount? amount, Map? args, }) => (super.noSuchMethod( @@ -2266,27 +2293,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i22.Future>.value({}), - ) as _i22.Future>); + _i23.Future>.value({}), + ) as _i23.Future>); @override - _i22.Future confirmSend({required Map? txData}) => + _i23.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i22.Future refresh() => (super.noSuchMethod( + _i23.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2296,35 +2323,35 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i22.Future testNetworkConnection() => (super.noSuchMethod( + _i23.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future initializeNew( + _i23.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future initializeExisting() => (super.noSuchMethod( + _i23.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future recoverFromMnemonic({ + _i23.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -2343,20 +2370,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future exitCurrentWallet() => (super.noSuchMethod( + _i23.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future fullRescan( + _i23.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2368,12 +2395,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future<_i14.Amount> estimateFeeFor( - _i14.Amount? amount, + _i23.Future<_i15.Amount> estimateFeeFor( + _i15.Amount? amount, int? feeRate, ) => (super.noSuchMethod( @@ -2384,7 +2411,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i22.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i23.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -2394,26 +2421,26 @@ class MockManager extends _i1.Mock implements _i6.Manager { ], ), )), - ) as _i22.Future<_i14.Amount>); + ) as _i23.Future<_i15.Amount>); @override - _i22.Future generateNewAddress() => (super.noSuchMethod( + _i23.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future resetRescanOnOpen() => (super.noSuchMethod( + _i23.Future resetRescanOnOpen() => (super.noSuchMethod( Invocation.method( #resetRescanOnOpen, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - void addListener(_i24.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2421,7 +2448,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i24.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2441,7 +2468,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { /// A class which mocks [CoinServiceAPI]. /// /// See the documentation for Mockito's code generation for more information. -class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -2452,10 +2479,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i21.Coin get coin => (super.noSuchMethod( + _i22.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i21.Coin.bitcoin, - ) as _i21.Coin); + returnValue: _i22.Coin.bitcoin, + ) as _i22.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -2488,42 +2515,42 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i22.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i23.Future<_i10.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i22.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i23.Future<_i10.FeeObject>.value(_FakeFeeObject_7( this, Invocation.getter(#fees), )), - ) as _i22.Future<_i9.FeeObject>); + ) as _i23.Future<_i10.FeeObject>); @override - _i22.Future get maxFee => (super.noSuchMethod( + _i23.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i22.Future.value(0), - ) as _i22.Future); + returnValue: _i23.Future.value(0), + ) as _i23.Future); @override - _i22.Future get currentReceivingAddress => (super.noSuchMethod( + _i23.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i12.Balance get balance => (super.noSuchMethod( + _i13.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.getter(#balance), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i22.Future> get transactions => (super.noSuchMethod( + _i23.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i22.Future>.value(<_i17.Transaction>[]), - ) as _i22.Future>); + _i23.Future>.value(<_i18.Transaction>[]), + ) as _i23.Future>); @override - _i22.Future> get utxos => (super.noSuchMethod( + _i23.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i22.Future>.value(<_i17.UTXO>[]), - ) as _i22.Future>); + returnValue: _i23.Future>.value(<_i18.UTXO>[]), + ) as _i23.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2543,20 +2570,20 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { returnValue: '', ) as String); @override - _i22.Future> get mnemonic => (super.noSuchMethod( + _i23.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i22.Future>.value([]), - ) as _i22.Future>); + returnValue: _i23.Future>.value([]), + ) as _i23.Future>); @override - _i22.Future get mnemonicString => (super.noSuchMethod( + _i23.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future get mnemonicPassphrase => (super.noSuchMethod( + _i23.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + ) as _i23.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -2573,9 +2600,9 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { returnValue: 0, ) as int); @override - _i22.Future> prepareSend({ + _i23.Future> prepareSend({ required String? address, - required _i14.Amount? amount, + required _i15.Amount? amount, Map? args, }) => (super.noSuchMethod( @@ -2589,36 +2616,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { }, ), returnValue: - _i22.Future>.value({}), - ) as _i22.Future>); + _i23.Future>.value({}), + ) as _i23.Future>); @override - _i22.Future confirmSend({required Map? txData}) => + _i23.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i22.Future.value(''), - ) as _i22.Future); + returnValue: _i23.Future.value(''), + ) as _i23.Future); @override - _i22.Future refresh() => (super.noSuchMethod( + _i23.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2628,15 +2655,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { returnValue: false, ) as bool); @override - _i22.Future testNetworkConnection() => (super.noSuchMethod( + _i23.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future recoverFromMnemonic({ + _i23.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -2655,40 +2682,40 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { #height: height, }, ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future initializeNew( + _i23.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future initializeExisting() => (super.noSuchMethod( + _i23.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future exit() => (super.noSuchMethod( + _i23.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future fullRescan( + _i23.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2700,12 +2727,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); @override - _i22.Future<_i14.Amount> estimateFeeFor( - _i14.Amount? amount, + _i23.Future<_i15.Amount> estimateFeeFor( + _i15.Amount? amount, int? feeRate, ) => (super.noSuchMethod( @@ -2716,7 +2743,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { feeRate, ], ), - returnValue: _i22.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i23.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -2726,23 +2753,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI { ], ), )), - ) as _i22.Future<_i14.Amount>); + ) as _i23.Future<_i15.Amount>); @override - _i22.Future generateNewAddress() => (super.noSuchMethod( + _i23.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i22.Future.value(false), - ) as _i22.Future); + returnValue: _i23.Future.value(false), + ) as _i23.Future); @override - _i22.Future updateSentCachedTxData(Map? txData) => + _i23.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i22.Future.value(), - returnValueForMissingStub: _i22.Future.value(), - ) as _i22.Future); + returnValue: _i23.Future.value(), + returnValueForMissingStub: _i23.Future.value(), + ) as _i23.Future); } diff --git a/test/widget_tests/trade_card_test.mocks.dart b/test/widget_tests/trade_card_test.mocks.dart index 88b3eb240..e8bb7f552 100644 --- a/test/widget_tests/trade_card_test.mocks.dart +++ b/test/widget_tests/trade_card_test.mocks.dart @@ -3,13 +3,14 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; -import 'dart:typed_data' as _i6; +import 'dart:async' as _i6; +import 'dart:typed_data' as _i7; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/db/isar/main_db.dart' as _i2; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i4; -import 'package:stackwallet/themes/theme_service.dart' as _i3; +import 'package:stackwallet/db/isar/main_db.dart' as _i3; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i5; +import 'package:stackwallet/networking/http.dart' as _i2; +import 'package:stackwallet/themes/theme_service.dart' as _i4; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -22,8 +23,18 @@ import 'package:stackwallet/themes/theme_service.dart' as _i3; // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class -class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { - _FakeMainDB_0( +class _FakeHTTP_0 extends _i1.SmartFake implements _i2.HTTP { + _FakeHTTP_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMainDB_1 extends _i1.SmartFake implements _i3.MainDB { + _FakeMainDB_1( Object parent, Invocation parentInvocation, ) : super( @@ -35,26 +46,42 @@ class _FakeMainDB_0 extends _i1.SmartFake implements _i2.MainDB { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i3.ThemeService { +class MockThemeService extends _i1.Mock implements _i4.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } @override - _i2.MainDB get db => (super.noSuchMethod( + _i2.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_0( + this, + Invocation.getter(#client), + ), + ) as _i2.HTTP); + @override + set client(_i2.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); + @override + _i3.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_0( + returnValue: _FakeMainDB_1( this, Invocation.getter(#db), ), - ) as _i2.MainDB); + ) as _i3.MainDB); @override - List<_i4.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i5.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i4.StackTheme>[], - ) as List<_i4.StackTheme>); + returnValue: <_i5.StackTheme>[], + ) as List<_i5.StackTheme>); @override - void init(_i2.MainDB? db) => super.noSuchMethod( + void init(_i3.MainDB? db) => super.noSuchMethod( Invocation.method( #init, [db], @@ -62,78 +89,78 @@ class MockThemeService extends _i1.Mock implements _i3.ThemeService { returnValueForMissingStub: null, ); @override - _i5.Future install({required _i6.Uint8List? themeArchiveData}) => + _i6.Future install({required _i7.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future remove({required String? themeId}) => (super.noSuchMethod( + _i6.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i6.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future verifyInstalled({required String? themeId}) => + _i6.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i6.Future.value(false), + ) as _i6.Future); @override - _i5.Future> fetchThemes() => (super.noSuchMethod( + _i6.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i5.Future>.value( - <_i3.StackThemeMetaData>[]), - ) as _i5.Future>); + returnValue: _i6.Future>.value( + <_i4.StackThemeMetaData>[]), + ) as _i6.Future>); @override - _i5.Future<_i6.Uint8List> fetchTheme( - {required _i3.StackThemeMetaData? themeMetaData}) => + _i6.Future<_i7.Uint8List> fetchTheme( + {required _i4.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i5.Future<_i6.Uint8List>.value(_i6.Uint8List(0)), - ) as _i5.Future<_i6.Uint8List>); + returnValue: _i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + ) as _i6.Future<_i7.Uint8List>); @override - _i4.StackTheme? getTheme({required String? themeId}) => + _i5.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i4.StackTheme?); + )) as _i5.StackTheme?); } /// A class which mocks [IThemeAssets]. /// /// See the documentation for Mockito's code generation for more information. -class MockIThemeAssets extends _i1.Mock implements _i4.IThemeAssets { +class MockIThemeAssets extends _i1.Mock implements _i5.IThemeAssets { MockIThemeAssets() { _i1.throwOnMissingStub(this); } diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index ee4d3d9d7..5ef7ef5a1 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -3,43 +3,44 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i19; -import 'dart:typed_data' as _i34; -import 'dart:ui' as _i21; +import 'dart:async' as _i20; +import 'dart:typed_data' as _i35; +import 'dart:ui' as _i22; -import 'package:decimal/decimal.dart' as _i30; +import 'package:decimal/decimal.dart' as _i31; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; -import 'package:isar/isar.dart' as _i16; +import 'package:isar/isar.dart' as _i17; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/db/isar/main_db.dart' as _i14; import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i13; import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i12; import 'package:stackwallet/models/balance.dart' as _i9; -import 'package:stackwallet/models/isar/models/block_explorer.dart' as _i36; -import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i35; -import 'package:stackwallet/models/isar/models/isar_models.dart' as _i22; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i33; +import 'package:stackwallet/models/isar/models/block_explorer.dart' as _i37; +import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i36; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i23; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i34; import 'package:stackwallet/models/models.dart' as _i8; -import 'package:stackwallet/models/signing_data.dart' as _i24; +import 'package:stackwallet/models/signing_data.dart' as _i25; +import 'package:stackwallet/networking/http.dart' as _i16; import 'package:stackwallet/services/coins/coin_service.dart' as _i7; -import 'package:stackwallet/services/coins/firo/firo_wallet.dart' as _i23; +import 'package:stackwallet/services/coins/firo/firo_wallet.dart' as _i24; import 'package:stackwallet/services/coins/manager.dart' as _i6; -import 'package:stackwallet/services/locale_service.dart' as _i25; +import 'package:stackwallet/services/locale_service.dart' as _i26; import 'package:stackwallet/services/node_service.dart' as _i3; -import 'package:stackwallet/services/notes_service.dart' as _i31; -import 'package:stackwallet/services/price_service.dart' as _i29; +import 'package:stackwallet/services/notes_service.dart' as _i32; +import 'package:stackwallet/services/price_service.dart' as _i30; import 'package:stackwallet/services/transaction_notification_tracker.dart' as _i11; -import 'package:stackwallet/services/wallets.dart' as _i17; +import 'package:stackwallet/services/wallets.dart' as _i18; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/themes/theme_service.dart' as _i32; +import 'package:stackwallet/themes/theme_service.dart' as _i33; import 'package:stackwallet/utilities/amount/amount.dart' as _i10; -import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i28; -import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i27; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i18; -import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i26; -import 'package:stackwallet/utilities/prefs.dart' as _i20; +import 'package:stackwallet/utilities/amount/amount_unit.dart' as _i29; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i28; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i19; +import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i27; +import 'package:stackwallet/utilities/prefs.dart' as _i21; import 'package:tuple/tuple.dart' as _i15; // ignore_for_file: type=lint @@ -199,8 +200,8 @@ class _FakeTuple2_13 extends _i1.SmartFake ); } -class _FakeIsar_14 extends _i1.SmartFake implements _i16.Isar { - _FakeIsar_14( +class _FakeHTTP_14 extends _i1.SmartFake implements _i16.HTTP { + _FakeHTTP_14( Object parent, Invocation parentInvocation, ) : super( @@ -209,9 +210,19 @@ class _FakeIsar_14 extends _i1.SmartFake implements _i16.Isar { ); } -class _FakeQueryBuilder_15 extends _i1.SmartFake - implements _i16.QueryBuilder { - _FakeQueryBuilder_15( +class _FakeIsar_15 extends _i1.SmartFake implements _i17.Isar { + _FakeIsar_15( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeQueryBuilder_16 extends _i1.SmartFake + implements _i17.QueryBuilder { + _FakeQueryBuilder_16( Object parent, Invocation parentInvocation, ) : super( @@ -223,7 +234,7 @@ class _FakeQueryBuilder_15 extends _i1.SmartFake /// A class which mocks [Wallets]. /// /// See the documentation for Mockito's code generation for more information. -class MockWallets extends _i1.Mock implements _i17.Wallets { +class MockWallets extends _i1.Mock implements _i18.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -290,7 +301,7 @@ class MockWallets extends _i1.Mock implements _i17.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i18.Coin? coin}) => + List getWalletIdsFor({required _i19.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -300,20 +311,20 @@ class MockWallets extends _i1.Mock implements _i17.Wallets { returnValue: [], ) as List); @override - List<_i15.Tuple2<_i18.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> + List<_i15.Tuple2<_i19.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i15.Tuple2<_i18.Coin, + returnValue: <_i15.Tuple2<_i19.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>[], ) as List< - _i15.Tuple2<_i18.Coin, + _i15.Tuple2<_i19.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i18.Coin? coin) => + _i19.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -377,17 +388,17 @@ class MockWallets extends _i1.Mock implements _i17.Wallets { returnValueForMissingStub: null, ); @override - _i19.Future load(_i20.Prefs? prefs) => (super.noSuchMethod( + _i20.Future load(_i21.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future loadAfterStackRestore( - _i20.Prefs? prefs, + _i20.Future loadAfterStackRestore( + _i21.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -398,11 +409,11 @@ class MockWallets extends _i1.Mock implements _i17.Wallets { managers, ], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - void addListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -410,7 +421,7 @@ class MockWallets extends _i1.Mock implements _i17.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -462,10 +473,10 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i18.Coin get coin => (super.noSuchMethod( + _i19.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i18.Coin.bitcoin, - ) as _i18.Coin); + returnValue: _i19.Coin.bitcoin, + ) as _i19.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -498,23 +509,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i19.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i20.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i19.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i20.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i19.Future<_i8.FeeObject>); + ) as _i20.Future<_i8.FeeObject>); @override - _i19.Future get maxFee => (super.noSuchMethod( + _i20.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future get currentReceivingAddress => (super.noSuchMethod( + _i20.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override _i9.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -524,16 +535,16 @@ class MockManager extends _i1.Mock implements _i6.Manager { ), ) as _i9.Balance); @override - _i19.Future> get transactions => (super.noSuchMethod( + _i20.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i19.Future>.value(<_i22.Transaction>[]), - ) as _i19.Future>); + _i20.Future>.value(<_i23.Transaction>[]), + ) as _i20.Future>); @override - _i19.Future> get utxos => (super.noSuchMethod( + _i20.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i19.Future>.value(<_i22.UTXO>[]), - ) as _i19.Future>); + returnValue: _i20.Future>.value(<_i23.UTXO>[]), + ) as _i20.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -553,15 +564,15 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i19.Future> get mnemonic => (super.noSuchMethod( + _i20.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i19.Future>.value([]), - ) as _i19.Future>); + returnValue: _i20.Future>.value([]), + ) as _i20.Future>); @override - _i19.Future get mnemonicPassphrase => (super.noSuchMethod( + _i20.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -608,24 +619,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i19.Future get xpub => (super.noSuchMethod( + _i20.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i19.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i20.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -635,7 +646,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i19.Future> prepareSend({ + _i20.Future> prepareSend({ required String? address, required _i10.Amount? amount, Map? args, @@ -651,27 +662,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i19.Future>.value({}), - ) as _i19.Future>); + _i20.Future>.value({}), + ) as _i20.Future>); @override - _i19.Future confirmSend({required Map? txData}) => + _i20.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future refresh() => (super.noSuchMethod( + _i20.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -681,35 +692,35 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i19.Future testNetworkConnection() => (super.noSuchMethod( + _i20.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future initializeNew( + _i20.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future initializeExisting() => (super.noSuchMethod( + _i20.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future recoverFromMnemonic({ + _i20.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -728,20 +739,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future exitCurrentWallet() => (super.noSuchMethod( + _i20.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future fullRescan( + _i20.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -753,11 +764,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future<_i10.Amount> estimateFeeFor( + _i20.Future<_i10.Amount> estimateFeeFor( _i10.Amount? amount, int? feeRate, ) => @@ -769,7 +780,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i19.Future<_i10.Amount>.value(_FakeAmount_7( + returnValue: _i20.Future<_i10.Amount>.value(_FakeAmount_7( this, Invocation.method( #estimateFeeFor, @@ -779,26 +790,26 @@ class MockManager extends _i1.Mock implements _i6.Manager { ], ), )), - ) as _i19.Future<_i10.Amount>); + ) as _i20.Future<_i10.Amount>); @override - _i19.Future generateNewAddress() => (super.noSuchMethod( + _i20.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future resetRescanOnOpen() => (super.noSuchMethod( + _i20.Future resetRescanOnOpen() => (super.noSuchMethod( Invocation.method( #resetRescanOnOpen, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - void addListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -806,7 +817,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -841,10 +852,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i18.Coin get coin => (super.noSuchMethod( + _i19.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i18.Coin.bitcoin, - ) as _i18.Coin); + returnValue: _i19.Coin.bitcoin, + ) as _i19.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -877,23 +888,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i19.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i20.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i19.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i20.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i19.Future<_i8.FeeObject>); + ) as _i20.Future<_i8.FeeObject>); @override - _i19.Future get maxFee => (super.noSuchMethod( + _i20.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future get currentReceivingAddress => (super.noSuchMethod( + _i20.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override _i9.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -903,16 +914,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { ), ) as _i9.Balance); @override - _i19.Future> get transactions => (super.noSuchMethod( + _i20.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i19.Future>.value(<_i22.Transaction>[]), - ) as _i19.Future>); + _i20.Future>.value(<_i23.Transaction>[]), + ) as _i20.Future>); @override - _i19.Future> get utxos => (super.noSuchMethod( + _i20.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i19.Future>.value(<_i22.UTXO>[]), - ) as _i19.Future>); + returnValue: _i20.Future>.value(<_i23.UTXO>[]), + ) as _i20.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -932,20 +943,20 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { returnValue: '', ) as String); @override - _i19.Future> get mnemonic => (super.noSuchMethod( + _i20.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i19.Future>.value([]), - ) as _i19.Future>); + returnValue: _i20.Future>.value([]), + ) as _i20.Future>); @override - _i19.Future get mnemonicString => (super.noSuchMethod( + _i20.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future get mnemonicPassphrase => (super.noSuchMethod( + _i20.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -962,7 +973,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { returnValue: 0, ) as int); @override - _i19.Future> prepareSend({ + _i20.Future> prepareSend({ required String? address, required _i10.Amount? amount, Map? args, @@ -978,36 +989,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { }, ), returnValue: - _i19.Future>.value({}), - ) as _i19.Future>); + _i20.Future>.value({}), + ) as _i20.Future>); @override - _i19.Future confirmSend({required Map? txData}) => + _i20.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future refresh() => (super.noSuchMethod( + _i20.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i20.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1017,15 +1028,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { returnValue: false, ) as bool); @override - _i19.Future testNetworkConnection() => (super.noSuchMethod( + _i20.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future recoverFromMnemonic({ + _i20.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -1044,40 +1055,40 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { #height: height, }, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future initializeNew( + _i20.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future initializeExisting() => (super.noSuchMethod( + _i20.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future exit() => (super.noSuchMethod( + _i20.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future fullRescan( + _i20.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1089,11 +1100,11 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future<_i10.Amount> estimateFeeFor( + _i20.Future<_i10.Amount> estimateFeeFor( _i10.Amount? amount, int? feeRate, ) => @@ -1105,7 +1116,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { feeRate, ], ), - returnValue: _i19.Future<_i10.Amount>.value(_FakeAmount_7( + returnValue: _i20.Future<_i10.Amount>.value(_FakeAmount_7( this, Invocation.method( #estimateFeeFor, @@ -1115,37 +1126,37 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI { ], ), )), - ) as _i19.Future<_i10.Amount>); + ) as _i20.Future<_i10.Amount>); @override - _i19.Future generateNewAddress() => (super.noSuchMethod( + _i20.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future updateSentCachedTxData(Map? txData) => + _i20.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); } /// A class which mocks [FiroWallet]. /// /// See the documentation for Mockito's code generation for more information. -class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { +class MockFiroWallet extends _i1.Mock implements _i24.FiroWallet { MockFiroWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i19.Timer? _timer) => super.noSuchMethod( + set timer(_i20.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -1235,48 +1246,48 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValue: false, ) as bool); @override - _i18.Coin get coin => (super.noSuchMethod( + _i19.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i18.Coin.bitcoin, - ) as _i18.Coin); + returnValue: _i19.Coin.bitcoin, + ) as _i19.Coin); @override - _i19.Future> get mnemonic => (super.noSuchMethod( + _i20.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i19.Future>.value([]), - ) as _i19.Future>); + returnValue: _i20.Future>.value([]), + ) as _i20.Future>); @override - _i19.Future get mnemonicString => (super.noSuchMethod( + _i20.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future get mnemonicPassphrase => (super.noSuchMethod( + _i20.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future get maxFee => (super.noSuchMethod( + _i20.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i20.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i19.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i20.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i19.Future<_i8.FeeObject>); + ) as _i20.Future<_i8.FeeObject>); @override - _i19.Future get currentReceivingAddress => (super.noSuchMethod( + _i20.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future get currentChangeAddress => (super.noSuchMethod( + _i20.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override String get walletName => (super.noSuchMethod( Invocation.getter(#walletName), @@ -1332,10 +1343,10 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValue: false, ) as bool); @override - _i19.Future get chainHeight => (super.noSuchMethod( + _i20.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -1358,21 +1369,21 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { ), ) as _i9.Balance); @override - _i19.Future> get utxos => (super.noSuchMethod( + _i20.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i19.Future>.value(<_i22.UTXO>[]), - ) as _i19.Future>); + returnValue: _i20.Future>.value(<_i23.UTXO>[]), + ) as _i20.Future>); @override - _i19.Future> get transactions => (super.noSuchMethod( + _i20.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i19.Future>.value(<_i22.Transaction>[]), - ) as _i19.Future>); + _i20.Future>.value(<_i23.Transaction>[]), + ) as _i20.Future>); @override - _i19.Future get xpub => (super.noSuchMethod( + _i20.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -1399,23 +1410,23 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValue: false, ) as bool); @override - _i19.Future updateSentCachedTxData(Map? txData) => + _i20.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future testNetworkConnection() => (super.noSuchMethod( + _i20.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -1433,7 +1444,7 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValueForMissingStub: null, ); @override - _i19.Future> prepareSendPublic({ + _i20.Future> prepareSendPublic({ required String? address, required _i10.Amount? amount, Map? args, @@ -1449,20 +1460,20 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { }, ), returnValue: - _i19.Future>.value({}), - ) as _i19.Future>); + _i20.Future>.value({}), + ) as _i20.Future>); @override - _i19.Future confirmSendPublic({dynamic txData}) => + _i20.Future confirmSendPublic({dynamic txData}) => (super.noSuchMethod( Invocation.method( #confirmSendPublic, [], {#txData: txData}, ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future> prepareSend({ + _i20.Future> prepareSend({ required String? address, required _i10.Amount? amount, Map? args, @@ -1478,18 +1489,18 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { }, ), returnValue: - _i19.Future>.value({}), - ) as _i19.Future>); + _i20.Future>.value({}), + ) as _i20.Future>); @override - _i19.Future confirmSend({required Map? txData}) => + _i20.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override int estimateTxFee({ required int? vSize, @@ -1514,7 +1525,7 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { bool? isSendAll, { int? satsPerVByte, int? additionalOutputs = 0, - List<_i22.UTXO>? utxos, + List<_i23.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -1531,19 +1542,19 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { }, )); @override - _i19.Future> fetchBuildTxData( - List<_i22.UTXO>? utxosToUse) => + _i20.Future> fetchBuildTxData( + List<_i23.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i19.Future>.value(<_i24.SigningData>[]), - ) as _i19.Future>); + _i20.Future>.value(<_i25.SigningData>[]), + ) as _i20.Future>); @override - _i19.Future> buildTransaction({ - required List<_i24.SigningData>? utxoSigningData, + _i20.Future> buildTransaction({ + required List<_i25.SigningData>? utxoSigningData, required List? recipients, required List? satoshiAmounts, }) => @@ -1558,111 +1569,111 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { }, ), returnValue: - _i19.Future>.value({}), - ) as _i19.Future>); + _i20.Future>.value({}), + ) as _i20.Future>); @override - _i19.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i20.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future initializeNew( + _i20.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future setLelantusCoinIsarRescanRequiredDone() => + _i20.Future setLelantusCoinIsarRescanRequiredDone() => (super.noSuchMethod( Invocation.method( #setLelantusCoinIsarRescanRequiredDone, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future firoRescanRecovery() => (super.noSuchMethod( + _i20.Future firoRescanRecovery() => (super.noSuchMethod( Invocation.method( #firoRescanRecovery, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future initializeExisting() => (super.noSuchMethod( + _i20.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i20.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future getAllTxsToWatch() => (super.noSuchMethod( + _i20.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future refresh() => (super.noSuchMethod( + _i20.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future anonymizeAllPublicFunds() => (super.noSuchMethod( + _i20.Future anonymizeAllPublicFunds() => (super.noSuchMethod( Invocation.method( #anonymizeAllPublicFunds, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future>> createMintsFromAmount(int? total) => + _i20.Future>> createMintsFromAmount(int? total) => (super.noSuchMethod( Invocation.method( #createMintsFromAmount, [total], ), - returnValue: _i19.Future>>.value( + returnValue: _i20.Future>>.value( >[]), - ) as _i19.Future>>); + ) as _i20.Future>>); @override - _i19.Future submitHexToNetwork(String? hex) => (super.noSuchMethod( + _i20.Future submitHexToNetwork(String? hex) => (super.noSuchMethod( Invocation.method( #submitHexToNetwork, [hex], ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future> buildMintTransaction( - List<_i22.UTXO>? utxosToUse, + _i20.Future> buildMintTransaction( + List<_i23.UTXO>? utxosToUse, int? satoshisPerRecipient, List>? mintsMap, ) => @@ -1676,29 +1687,29 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { ], ), returnValue: - _i19.Future>.value({}), - ) as _i19.Future>); + _i20.Future>.value({}), + ) as _i20.Future>); @override - _i19.Future checkReceivingAddressForTransactions() => + _i20.Future checkReceivingAddressForTransactions() => (super.noSuchMethod( Invocation.method( #checkReceivingAddressForTransactions, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future checkChangeAddressForTransactions() => (super.noSuchMethod( + _i20.Future checkChangeAddressForTransactions() => (super.noSuchMethod( Invocation.method( #checkChangeAddressForTransactions, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future fullRescan( + _i20.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1710,11 +1721,11 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future recoverFromMnemonic({ + _i20.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -1733,74 +1744,74 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { #height: height, }, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future> getSetDataMap(int? latestSetId) => + _i20.Future> getSetDataMap(int? latestSetId) => (super.noSuchMethod( Invocation.method( #getSetDataMap, [latestSetId], ), - returnValue: _i19.Future>.value({}), - ) as _i19.Future>); + returnValue: _i20.Future>.value({}), + ) as _i20.Future>); @override - _i19.Future getTransactionCacheEarly(List? allAddresses) => + _i20.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future>> fetchAnonymitySets() => + _i20.Future>> fetchAnonymitySets() => (super.noSuchMethod( Invocation.method( #fetchAnonymitySets, [], ), - returnValue: _i19.Future>>.value( + returnValue: _i20.Future>>.value( >[]), - ) as _i19.Future>>); + ) as _i20.Future>>); @override - _i19.Future getLatestSetId() => (super.noSuchMethod( + _i20.Future getLatestSetId() => (super.noSuchMethod( Invocation.method( #getLatestSetId, [], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future> getUsedCoinSerials() => (super.noSuchMethod( + _i20.Future> getUsedCoinSerials() => (super.noSuchMethod( Invocation.method( #getUsedCoinSerials, [], ), - returnValue: _i19.Future>.value([]), - ) as _i19.Future>); + returnValue: _i20.Future>.value([]), + ) as _i20.Future>); @override - _i19.Future exit() => (super.noSuchMethod( + _i20.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future estimateJoinSplitFee(int? spendAmount) => + _i20.Future estimateJoinSplitFee(int? spendAmount) => (super.noSuchMethod( Invocation.method( #estimateJoinSplitFee, [spendAmount], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future<_i10.Amount> estimateFeeFor( + _i20.Future<_i10.Amount> estimateFeeFor( _i10.Amount? amount, int? feeRate, ) => @@ -1812,7 +1823,7 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { feeRate, ], ), - returnValue: _i19.Future<_i10.Amount>.value(_FakeAmount_7( + returnValue: _i20.Future<_i10.Amount>.value(_FakeAmount_7( this, Invocation.method( #estimateFeeFor, @@ -1822,9 +1833,9 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { ], ), )), - ) as _i19.Future<_i10.Amount>); + ) as _i20.Future<_i10.Amount>); @override - _i19.Future<_i10.Amount> estimateFeeForPublic( + _i20.Future<_i10.Amount> estimateFeeForPublic( _i10.Amount? amount, int? feeRate, ) => @@ -1836,7 +1847,7 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { feeRate, ], ), - returnValue: _i19.Future<_i10.Amount>.value(_FakeAmount_7( + returnValue: _i20.Future<_i10.Amount>.value(_FakeAmount_7( this, Invocation.method( #estimateFeeForPublic, @@ -1846,7 +1857,7 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { ], ), )), - ) as _i19.Future<_i10.Amount>); + ) as _i20.Future<_i10.Amount>); @override _i10.Amount roughFeeEstimate( int? inputCount, @@ -1875,36 +1886,36 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { ), ) as _i10.Amount); @override - _i19.Future<_i10.Amount> sweepAllEstimate(int? feeRate) => + _i20.Future<_i10.Amount> sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i19.Future<_i10.Amount>.value(_FakeAmount_7( + returnValue: _i20.Future<_i10.Amount>.value(_FakeAmount_7( this, Invocation.method( #sweepAllEstimate, [feeRate], ), )), - ) as _i19.Future<_i10.Amount>); + ) as _i20.Future<_i10.Amount>); @override - _i19.Future>> fastFetch( + _i20.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i19.Future>>.value( + returnValue: _i20.Future>>.value( >[]), - ) as _i19.Future>>); + ) as _i20.Future>>); @override - _i19.Future> getJMintTransactions( + _i20.Future> getJMintTransactions( _i13.CachedElectrumX? cachedClient, List? transactions, - _i18.Coin? coin, + _i19.Coin? coin, ) => (super.noSuchMethod( Invocation.method( @@ -1915,17 +1926,17 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { coin, ], ), - returnValue: _i19.Future>.value( - <_i22.Address, _i22.Transaction>{}), - ) as _i19.Future>); + returnValue: _i20.Future>.value( + <_i23.Address, _i23.Transaction>{}), + ) as _i20.Future>); @override - _i19.Future generateNewAddress() => (super.noSuchMethod( + _i20.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override _i10.Amount availablePrivateBalance() => (super.noSuchMethod( Invocation.method( @@ -1957,7 +1968,7 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { @override void initCache( String? walletId, - _i18.Coin? coin, + _i19.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1970,14 +1981,14 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValueForMissingStub: null, ); @override - _i19.Future updateCachedId(String? id) => (super.noSuchMethod( + _i20.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1987,14 +1998,14 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValue: 0, ) as int); @override - _i19.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i20.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -2004,15 +2015,15 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValue: false, ) as bool); @override - _i19.Future updateCachedIsFavorite(bool? isFavorite) => + _i20.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override _i9.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -2028,15 +2039,15 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { ), ) as _i9.Balance); @override - _i19.Future updateCachedBalance(_i9.Balance? balance) => + _i20.Future updateCachedBalance(_i9.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override _i9.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -2052,15 +2063,15 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { ), ) as _i9.Balance); @override - _i19.Future updateCachedBalanceSecondary(_i9.Balance? balance) => + _i20.Future updateCachedBalanceSecondary(_i9.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override List getWalletTokenContractAddresses() => (super.noSuchMethod( Invocation.method( @@ -2070,16 +2081,16 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { returnValue: [], ) as List); @override - _i19.Future updateWalletTokenContractAddresses( + _i20.Future updateWalletTokenContractAddresses( List? contractAddresses) => (super.noSuchMethod( Invocation.method( #updateWalletTokenContractAddresses, [contractAddresses], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override void initWalletDB({_i14.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -2094,7 +2105,7 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet { /// A class which mocks [LocaleService]. /// /// See the documentation for Mockito's code generation for more information. -class MockLocaleService extends _i1.Mock implements _i25.LocaleService { +class MockLocaleService extends _i1.Mock implements _i26.LocaleService { MockLocaleService() { _i1.throwOnMissingStub(this); } @@ -2110,17 +2121,17 @@ class MockLocaleService extends _i1.Mock implements _i25.LocaleService { returnValue: false, ) as bool); @override - _i19.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( + _i20.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( Invocation.method( #loadLocale, [], {#notify: notify}, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - void addListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2128,7 +2139,7 @@ class MockLocaleService extends _i1.Mock implements _i25.LocaleService { returnValueForMissingStub: null, ); @override - void removeListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2156,7 +2167,7 @@ class MockLocaleService extends _i1.Mock implements _i25.LocaleService { /// A class which mocks [Prefs]. /// /// See the documentation for Mockito's code generation for more information. -class MockPrefs extends _i1.Mock implements _i20.Prefs { +class MockPrefs extends _i1.Mock implements _i21.Prefs { MockPrefs() { _i1.throwOnMissingStub(this); } @@ -2212,12 +2223,12 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValueForMissingStub: null, ); @override - _i26.SyncingType get syncType => (super.noSuchMethod( + _i27.SyncingType get syncType => (super.noSuchMethod( Invocation.getter(#syncType), - returnValue: _i26.SyncingType.currentWalletOnly, - ) as _i26.SyncingType); + returnValue: _i27.SyncingType.currentWalletOnly, + ) as _i27.SyncingType); @override - set syncType(_i26.SyncingType? syncType) => super.noSuchMethod( + set syncType(_i27.SyncingType? syncType) => super.noSuchMethod( Invocation.setter( #syncType, syncType, @@ -2329,14 +2340,14 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValueForMissingStub: null, ); @override - bool get torKillswitch => (super.noSuchMethod( - Invocation.getter(#torKillswitch), + bool get torKillSwitch => (super.noSuchMethod( + Invocation.getter(#torKillSwitch), returnValue: false, ) as bool); @override - set torKillswitch(bool? torKillswitch) => super.noSuchMethod( + set torKillSwitch(bool? torKillswitch) => super.noSuchMethod( Invocation.setter( - #torKillswitch, + #torKillSwitch, torKillswitch, ), returnValueForMissingStub: null, @@ -2376,12 +2387,12 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValueForMissingStub: null, ); @override - _i27.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( + _i28.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( Invocation.getter(#backupFrequencyType), - returnValue: _i27.BackupFrequencyType.everyTenMinutes, - ) as _i27.BackupFrequencyType); + returnValue: _i28.BackupFrequencyType.everyTenMinutes, + ) as _i28.BackupFrequencyType); @override - set backupFrequencyType(_i27.BackupFrequencyType? backupFrequencyType) => + set backupFrequencyType(_i28.BackupFrequencyType? backupFrequencyType) => super.noSuchMethod( Invocation.setter( #backupFrequencyType, @@ -2532,61 +2543,61 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValue: false, ) as bool); @override - _i19.Future init() => (super.noSuchMethod( + _i20.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( + _i20.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( Invocation.method( #incrementCurrentNotificationIndex, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future isExternalCallsSet() => (super.noSuchMethod( + _i20.Future isExternalCallsSet() => (super.noSuchMethod( Invocation.method( #isExternalCallsSet, [], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future saveUserID(String? userId) => (super.noSuchMethod( + _i20.Future saveUserID(String? userId) => (super.noSuchMethod( Invocation.method( #saveUserID, [userId], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( + _i20.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod( Invocation.method( #saveSignupEpoch, [signupEpoch], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i28.AmountUnit amountUnit(_i18.Coin? coin) => (super.noSuchMethod( + _i29.AmountUnit amountUnit(_i19.Coin? coin) => (super.noSuchMethod( Invocation.method( #amountUnit, [coin], ), - returnValue: _i28.AmountUnit.normal, - ) as _i28.AmountUnit); + returnValue: _i29.AmountUnit.normal, + ) as _i29.AmountUnit); @override void updateAmountUnit({ - required _i18.Coin? coin, - required _i28.AmountUnit? amountUnit, + required _i19.Coin? coin, + required _i29.AmountUnit? amountUnit, }) => super.noSuchMethod( Invocation.method( @@ -2600,7 +2611,7 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValueForMissingStub: null, ); @override - int maxDecimals(_i18.Coin? coin) => (super.noSuchMethod( + int maxDecimals(_i19.Coin? coin) => (super.noSuchMethod( Invocation.method( #maxDecimals, [coin], @@ -2609,7 +2620,7 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { ) as int); @override void updateMaxDecimals({ - required _i18.Coin? coin, + required _i19.Coin? coin, required int? maxDecimals, }) => super.noSuchMethod( @@ -2624,7 +2635,7 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValueForMissingStub: null, ); @override - void addListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2632,7 +2643,7 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { returnValueForMissingStub: null, ); @override - void removeListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2660,7 +2671,7 @@ class MockPrefs extends _i1.Mock implements _i20.Prefs { /// A class which mocks [PriceService]. /// /// See the documentation for Mockito's code generation for more information. -class MockPriceService extends _i1.Mock implements _i29.PriceService { +class MockPriceService extends _i1.Mock implements _i30.PriceService { MockPriceService() { _i1.throwOnMissingStub(this); } @@ -2697,44 +2708,44 @@ class MockPriceService extends _i1.Mock implements _i29.PriceService { returnValue: false, ) as bool); @override - _i15.Tuple2<_i30.Decimal, double> getPrice(_i18.Coin? coin) => + _i15.Tuple2<_i31.Decimal, double> getPrice(_i19.Coin? coin) => (super.noSuchMethod( Invocation.method( #getPrice, [coin], ), - returnValue: _FakeTuple2_13<_i30.Decimal, double>( + returnValue: _FakeTuple2_13<_i31.Decimal, double>( this, Invocation.method( #getPrice, [coin], ), ), - ) as _i15.Tuple2<_i30.Decimal, double>); + ) as _i15.Tuple2<_i31.Decimal, double>); @override - _i15.Tuple2<_i30.Decimal, double> getTokenPrice(String? contractAddress) => + _i15.Tuple2<_i31.Decimal, double> getTokenPrice(String? contractAddress) => (super.noSuchMethod( Invocation.method( #getTokenPrice, [contractAddress], ), - returnValue: _FakeTuple2_13<_i30.Decimal, double>( + returnValue: _FakeTuple2_13<_i31.Decimal, double>( this, Invocation.method( #getTokenPrice, [contractAddress], ), ), - ) as _i15.Tuple2<_i30.Decimal, double>); + ) as _i15.Tuple2<_i31.Decimal, double>); @override - _i19.Future updatePrice() => (super.noSuchMethod( + _i20.Future updatePrice() => (super.noSuchMethod( Invocation.method( #updatePrice, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override void cancel() => super.noSuchMethod( Invocation.method( @@ -2760,7 +2771,7 @@ class MockPriceService extends _i1.Mock implements _i29.PriceService { returnValueForMissingStub: null, ); @override - void addListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2768,7 +2779,7 @@ class MockPriceService extends _i1.Mock implements _i29.PriceService { returnValueForMissingStub: null, ); @override - void removeListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2788,7 +2799,7 @@ class MockPriceService extends _i1.Mock implements _i29.PriceService { /// A class which mocks [NotesService]. /// /// See the documentation for Mockito's code generation for more information. -class MockNotesService extends _i1.Mock implements _i31.NotesService { +class MockNotesService extends _i1.Mock implements _i32.NotesService { MockNotesService() { _i1.throwOnMissingStub(this); } @@ -2804,35 +2815,35 @@ class MockNotesService extends _i1.Mock implements _i31.NotesService { returnValue: {}, ) as Map); @override - _i19.Future> get notes => (super.noSuchMethod( + _i20.Future> get notes => (super.noSuchMethod( Invocation.getter(#notes), - returnValue: _i19.Future>.value({}), - ) as _i19.Future>); + returnValue: _i20.Future>.value({}), + ) as _i20.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i19.Future> search(String? text) => (super.noSuchMethod( + _i20.Future> search(String? text) => (super.noSuchMethod( Invocation.method( #search, [text], ), - returnValue: _i19.Future>.value({}), - ) as _i19.Future>); + returnValue: _i20.Future>.value({}), + ) as _i20.Future>); @override - _i19.Future getNoteFor({required String? txid}) => + _i20.Future getNoteFor({required String? txid}) => (super.noSuchMethod( Invocation.method( #getNoteFor, [], {#txid: txid}, ), - returnValue: _i19.Future.value(''), - ) as _i19.Future); + returnValue: _i20.Future.value(''), + ) as _i20.Future); @override - _i19.Future editOrAddNote({ + _i20.Future editOrAddNote({ required String? txid, required String? note, }) => @@ -2845,21 +2856,21 @@ class MockNotesService extends _i1.Mock implements _i31.NotesService { #note: note, }, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future deleteNote({required String? txid}) => (super.noSuchMethod( + _i20.Future deleteNote({required String? txid}) => (super.noSuchMethod( Invocation.method( #deleteNote, [], {#txid: txid}, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - void addListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2867,7 +2878,7 @@ class MockNotesService extends _i1.Mock implements _i31.NotesService { returnValueForMissingStub: null, ); @override - void removeListener(_i21.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i22.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2895,11 +2906,27 @@ class MockNotesService extends _i1.Mock implements _i31.NotesService { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i32.ThemeService { +class MockThemeService extends _i1.Mock implements _i33.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } + @override + _i16.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_14( + this, + Invocation.getter(#client), + ), + ) as _i16.HTTP); + @override + set client(_i16.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); @override _i14.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), @@ -2909,10 +2936,10 @@ class MockThemeService extends _i1.Mock implements _i32.ThemeService { ), ) as _i14.MainDB); @override - List<_i33.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i34.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i33.StackTheme>[], - ) as List<_i33.StackTheme>); + returnValue: <_i34.StackTheme>[], + ) as List<_i34.StackTheme>); @override void init(_i14.MainDB? db) => super.noSuchMethod( Invocation.method( @@ -2922,73 +2949,73 @@ class MockThemeService extends _i1.Mock implements _i32.ThemeService { returnValueForMissingStub: null, ); @override - _i19.Future install({required _i34.Uint8List? themeArchiveData}) => + _i20.Future install({required _i35.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future remove({required String? themeId}) => (super.noSuchMethod( + _i20.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i20.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future verifyInstalled({required String? themeId}) => + _i20.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future> fetchThemes() => + _i20.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i19.Future>.value( - <_i32.StackThemeMetaData>[]), - ) as _i19.Future>); + returnValue: _i20.Future>.value( + <_i33.StackThemeMetaData>[]), + ) as _i20.Future>); @override - _i19.Future<_i34.Uint8List> fetchTheme( - {required _i32.StackThemeMetaData? themeMetaData}) => + _i20.Future<_i35.Uint8List> fetchTheme( + {required _i33.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i19.Future<_i34.Uint8List>.value(_i34.Uint8List(0)), - ) as _i19.Future<_i34.Uint8List>); + returnValue: _i20.Future<_i35.Uint8List>.value(_i35.Uint8List(0)), + ) as _i20.Future<_i35.Uint8List>); @override - _i33.StackTheme? getTheme({required String? themeId}) => + _i34.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i33.StackTheme?); + )) as _i34.StackTheme?); } /// A class which mocks [MainDB]. @@ -3000,131 +3027,131 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { } @override - _i16.Isar get isar => (super.noSuchMethod( + _i17.Isar get isar => (super.noSuchMethod( Invocation.getter(#isar), - returnValue: _FakeIsar_14( + returnValue: _FakeIsar_15( this, Invocation.getter(#isar), ), - ) as _i16.Isar); + ) as _i17.Isar); @override - _i19.Future initMainDB({_i16.Isar? mock}) => (super.noSuchMethod( + _i20.Future initMainDB({_i17.Isar? mock}) => (super.noSuchMethod( Invocation.method( #initMainDB, [], {#mock: mock}, ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - List<_i35.ContactEntry> getContactEntries() => (super.noSuchMethod( + List<_i36.ContactEntry> getContactEntries() => (super.noSuchMethod( Invocation.method( #getContactEntries, [], ), - returnValue: <_i35.ContactEntry>[], - ) as List<_i35.ContactEntry>); + returnValue: <_i36.ContactEntry>[], + ) as List<_i36.ContactEntry>); @override - _i19.Future deleteContactEntry({required String? id}) => + _i20.Future deleteContactEntry({required String? id}) => (super.noSuchMethod( Invocation.method( #deleteContactEntry, [], {#id: id}, ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Future isContactEntryExists({required String? id}) => + _i20.Future isContactEntryExists({required String? id}) => (super.noSuchMethod( Invocation.method( #isContactEntryExists, [], {#id: id}, ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i35.ContactEntry? getContactEntry({required String? id}) => + _i36.ContactEntry? getContactEntry({required String? id}) => (super.noSuchMethod(Invocation.method( #getContactEntry, [], {#id: id}, - )) as _i35.ContactEntry?); + )) as _i36.ContactEntry?); @override - _i19.Future putContactEntry( - {required _i35.ContactEntry? contactEntry}) => + _i20.Future putContactEntry( + {required _i36.ContactEntry? contactEntry}) => (super.noSuchMethod( Invocation.method( #putContactEntry, [], {#contactEntry: contactEntry}, ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i36.TransactionBlockExplorer? getTransactionBlockExplorer( - {required _i18.Coin? coin}) => + _i37.TransactionBlockExplorer? getTransactionBlockExplorer( + {required _i19.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getTransactionBlockExplorer, [], {#coin: coin}, - )) as _i36.TransactionBlockExplorer?); + )) as _i37.TransactionBlockExplorer?); @override - _i19.Future putTransactionBlockExplorer( - _i36.TransactionBlockExplorer? explorer) => + _i20.Future putTransactionBlockExplorer( + _i37.TransactionBlockExplorer? explorer) => (super.noSuchMethod( Invocation.method( #putTransactionBlockExplorer, [explorer], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i16.QueryBuilder<_i22.Address, _i22.Address, _i16.QAfterWhereClause> + _i17.QueryBuilder<_i23.Address, _i23.Address, _i17.QAfterWhereClause> getAddresses(String? walletId) => (super.noSuchMethod( Invocation.method( #getAddresses, [walletId], ), - returnValue: _FakeQueryBuilder_15<_i22.Address, _i22.Address, - _i16.QAfterWhereClause>( + returnValue: _FakeQueryBuilder_16<_i23.Address, _i23.Address, + _i17.QAfterWhereClause>( this, Invocation.method( #getAddresses, [walletId], ), ), - ) as _i16.QueryBuilder<_i22.Address, _i22.Address, - _i16.QAfterWhereClause>); + ) as _i17.QueryBuilder<_i23.Address, _i23.Address, + _i17.QAfterWhereClause>); @override - _i19.Future putAddress(_i22.Address? address) => (super.noSuchMethod( + _i20.Future putAddress(_i23.Address? address) => (super.noSuchMethod( Invocation.method( #putAddress, [address], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future> putAddresses(List<_i22.Address>? addresses) => + _i20.Future> putAddresses(List<_i23.Address>? addresses) => (super.noSuchMethod( Invocation.method( #putAddresses, [addresses], ), - returnValue: _i19.Future>.value([]), - ) as _i19.Future>); + returnValue: _i20.Future>.value([]), + ) as _i20.Future>); @override - _i19.Future> updateOrPutAddresses(List<_i22.Address>? addresses) => + _i20.Future> updateOrPutAddresses(List<_i23.Address>? addresses) => (super.noSuchMethod( Invocation.method( #updateOrPutAddresses, [addresses], ), - returnValue: _i19.Future>.value([]), - ) as _i19.Future>); + returnValue: _i20.Future>.value([]), + ) as _i20.Future>); @override - _i19.Future<_i22.Address?> getAddress( + _i20.Future<_i23.Address?> getAddress( String? walletId, String? address, ) => @@ -3136,12 +3163,12 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { address, ], ), - returnValue: _i19.Future<_i22.Address?>.value(), - ) as _i19.Future<_i22.Address?>); + returnValue: _i20.Future<_i23.Address?>.value(), + ) as _i20.Future<_i23.Address?>); @override - _i19.Future updateAddress( - _i22.Address? oldAddress, - _i22.Address? newAddress, + _i20.Future updateAddress( + _i23.Address? oldAddress, + _i23.Address? newAddress, ) => (super.noSuchMethod( Invocation.method( @@ -3151,46 +3178,46 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { newAddress, ], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i16.QueryBuilder<_i22.Transaction, _i22.Transaction, _i16.QAfterWhereClause> + _i17.QueryBuilder<_i23.Transaction, _i23.Transaction, _i17.QAfterWhereClause> getTransactions(String? walletId) => (super.noSuchMethod( Invocation.method( #getTransactions, [walletId], ), - returnValue: _FakeQueryBuilder_15<_i22.Transaction, - _i22.Transaction, _i16.QAfterWhereClause>( + returnValue: _FakeQueryBuilder_16<_i23.Transaction, + _i23.Transaction, _i17.QAfterWhereClause>( this, Invocation.method( #getTransactions, [walletId], ), ), - ) as _i16.QueryBuilder<_i22.Transaction, _i22.Transaction, - _i16.QAfterWhereClause>); + ) as _i17.QueryBuilder<_i23.Transaction, _i23.Transaction, + _i17.QAfterWhereClause>); @override - _i19.Future putTransaction(_i22.Transaction? transaction) => + _i20.Future putTransaction(_i23.Transaction? transaction) => (super.noSuchMethod( Invocation.method( #putTransaction, [transaction], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future> putTransactions( - List<_i22.Transaction>? transactions) => + _i20.Future> putTransactions( + List<_i23.Transaction>? transactions) => (super.noSuchMethod( Invocation.method( #putTransactions, [transactions], ), - returnValue: _i19.Future>.value([]), - ) as _i19.Future>); + returnValue: _i20.Future>.value([]), + ) as _i20.Future>); @override - _i19.Future<_i22.Transaction?> getTransaction( + _i20.Future<_i23.Transaction?> getTransaction( String? walletId, String? txid, ) => @@ -3202,10 +3229,10 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { txid, ], ), - returnValue: _i19.Future<_i22.Transaction?>.value(), - ) as _i19.Future<_i22.Transaction?>); + returnValue: _i20.Future<_i23.Transaction?>.value(), + ) as _i20.Future<_i23.Transaction?>); @override - _i19.Stream<_i22.Transaction?> watchTransaction({ + _i20.Stream<_i23.Transaction?> watchTransaction({ required int? id, bool? fireImmediately = false, }) => @@ -3218,10 +3245,10 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { #fireImmediately: fireImmediately, }, ), - returnValue: _i19.Stream<_i22.Transaction?>.empty(), - ) as _i19.Stream<_i22.Transaction?>); + returnValue: _i20.Stream<_i23.Transaction?>.empty(), + ) as _i20.Stream<_i23.Transaction?>); @override - _i16.QueryBuilder<_i22.UTXO, _i22.UTXO, _i16.QAfterWhereClause> getUTXOs( + _i17.QueryBuilder<_i23.UTXO, _i23.UTXO, _i17.QAfterWhereClause> getUTXOs( String? walletId) => (super.noSuchMethod( Invocation.method( @@ -3229,36 +3256,36 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { [walletId], ), returnValue: - _FakeQueryBuilder_15<_i22.UTXO, _i22.UTXO, _i16.QAfterWhereClause>( + _FakeQueryBuilder_16<_i23.UTXO, _i23.UTXO, _i17.QAfterWhereClause>( this, Invocation.method( #getUTXOs, [walletId], ), ), - ) as _i16.QueryBuilder<_i22.UTXO, _i22.UTXO, _i16.QAfterWhereClause>); + ) as _i17.QueryBuilder<_i23.UTXO, _i23.UTXO, _i17.QAfterWhereClause>); @override - _i19.Future putUTXO(_i22.UTXO? utxo) => (super.noSuchMethod( + _i20.Future putUTXO(_i23.UTXO? utxo) => (super.noSuchMethod( Invocation.method( #putUTXO, [utxo], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future putUTXOs(List<_i22.UTXO>? utxos) => (super.noSuchMethod( + _i20.Future putUTXOs(List<_i23.UTXO>? utxos) => (super.noSuchMethod( Invocation.method( #putUTXOs, [utxos], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future updateUTXOs( + _i20.Future updateUTXOs( String? walletId, - List<_i22.UTXO>? utxos, + List<_i23.UTXO>? utxos, ) => (super.noSuchMethod( Invocation.method( @@ -3268,10 +3295,10 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { utxos, ], ), - returnValue: _i19.Future.value(false), - ) as _i19.Future); + returnValue: _i20.Future.value(false), + ) as _i20.Future); @override - _i19.Stream<_i22.UTXO?> watchUTXO({ + _i20.Stream<_i23.UTXO?> watchUTXO({ required int? id, bool? fireImmediately = false, }) => @@ -3284,50 +3311,50 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { #fireImmediately: fireImmediately, }, ), - returnValue: _i19.Stream<_i22.UTXO?>.empty(), - ) as _i19.Stream<_i22.UTXO?>); + returnValue: _i20.Stream<_i23.UTXO?>.empty(), + ) as _i20.Stream<_i23.UTXO?>); @override - _i16.QueryBuilder<_i22.TransactionNote, _i22.TransactionNote, - _i16.QAfterWhereClause> getTransactionNotes( + _i17.QueryBuilder<_i23.TransactionNote, _i23.TransactionNote, + _i17.QAfterWhereClause> getTransactionNotes( String? walletId) => (super.noSuchMethod( Invocation.method( #getTransactionNotes, [walletId], ), - returnValue: _FakeQueryBuilder_15<_i22.TransactionNote, - _i22.TransactionNote, _i16.QAfterWhereClause>( + returnValue: _FakeQueryBuilder_16<_i23.TransactionNote, + _i23.TransactionNote, _i17.QAfterWhereClause>( this, Invocation.method( #getTransactionNotes, [walletId], ), ), - ) as _i16.QueryBuilder<_i22.TransactionNote, _i22.TransactionNote, - _i16.QAfterWhereClause>); + ) as _i17.QueryBuilder<_i23.TransactionNote, _i23.TransactionNote, + _i17.QAfterWhereClause>); @override - _i19.Future putTransactionNote(_i22.TransactionNote? transactionNote) => + _i20.Future putTransactionNote(_i23.TransactionNote? transactionNote) => (super.noSuchMethod( Invocation.method( #putTransactionNote, [transactionNote], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future putTransactionNotes( - List<_i22.TransactionNote>? transactionNotes) => + _i20.Future putTransactionNotes( + List<_i23.TransactionNote>? transactionNotes) => (super.noSuchMethod( Invocation.method( #putTransactionNotes, [transactionNotes], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future<_i22.TransactionNote?> getTransactionNote( + _i20.Future<_i23.TransactionNote?> getTransactionNote( String? walletId, String? txid, ) => @@ -3339,10 +3366,10 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { txid, ], ), - returnValue: _i19.Future<_i22.TransactionNote?>.value(), - ) as _i19.Future<_i22.TransactionNote?>); + returnValue: _i20.Future<_i23.TransactionNote?>.value(), + ) as _i20.Future<_i23.TransactionNote?>); @override - _i19.Stream<_i22.TransactionNote?> watchTransactionNote({ + _i20.Stream<_i23.TransactionNote?> watchTransactionNote({ required int? id, bool? fireImmediately = false, }) => @@ -3355,38 +3382,38 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { #fireImmediately: fireImmediately, }, ), - returnValue: _i19.Stream<_i22.TransactionNote?>.empty(), - ) as _i19.Stream<_i22.TransactionNote?>); + returnValue: _i20.Stream<_i23.TransactionNote?>.empty(), + ) as _i20.Stream<_i23.TransactionNote?>); @override - _i16.QueryBuilder<_i22.AddressLabel, _i22.AddressLabel, - _i16.QAfterWhereClause> getAddressLabels( + _i17.QueryBuilder<_i23.AddressLabel, _i23.AddressLabel, + _i17.QAfterWhereClause> getAddressLabels( String? walletId) => (super.noSuchMethod( Invocation.method( #getAddressLabels, [walletId], ), - returnValue: _FakeQueryBuilder_15<_i22.AddressLabel, _i22.AddressLabel, - _i16.QAfterWhereClause>( + returnValue: _FakeQueryBuilder_16<_i23.AddressLabel, _i23.AddressLabel, + _i17.QAfterWhereClause>( this, Invocation.method( #getAddressLabels, [walletId], ), ), - ) as _i16.QueryBuilder<_i22.AddressLabel, _i22.AddressLabel, - _i16.QAfterWhereClause>); + ) as _i17.QueryBuilder<_i23.AddressLabel, _i23.AddressLabel, + _i17.QAfterWhereClause>); @override - _i19.Future putAddressLabel(_i22.AddressLabel? addressLabel) => + _i20.Future putAddressLabel(_i23.AddressLabel? addressLabel) => (super.noSuchMethod( Invocation.method( #putAddressLabel, [addressLabel], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - int putAddressLabelSync(_i22.AddressLabel? addressLabel) => + int putAddressLabelSync(_i23.AddressLabel? addressLabel) => (super.noSuchMethod( Invocation.method( #putAddressLabelSync, @@ -3395,17 +3422,17 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { returnValue: 0, ) as int); @override - _i19.Future putAddressLabels(List<_i22.AddressLabel>? addressLabels) => + _i20.Future putAddressLabels(List<_i23.AddressLabel>? addressLabels) => (super.noSuchMethod( Invocation.method( #putAddressLabels, [addressLabels], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future<_i22.AddressLabel?> getAddressLabel( + _i20.Future<_i23.AddressLabel?> getAddressLabel( String? walletId, String? addressString, ) => @@ -3417,10 +3444,10 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { addressString, ], ), - returnValue: _i19.Future<_i22.AddressLabel?>.value(), - ) as _i19.Future<_i22.AddressLabel?>); + returnValue: _i20.Future<_i23.AddressLabel?>.value(), + ) as _i20.Future<_i23.AddressLabel?>); @override - _i22.AddressLabel? getAddressLabelSync( + _i23.AddressLabel? getAddressLabelSync( String? walletId, String? addressString, ) => @@ -3430,9 +3457,9 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { walletId, addressString, ], - )) as _i22.AddressLabel?); + )) as _i23.AddressLabel?); @override - _i19.Stream<_i22.AddressLabel?> watchAddressLabel({ + _i20.Stream<_i23.AddressLabel?> watchAddressLabel({ required int? id, bool? fireImmediately = false, }) => @@ -3445,50 +3472,50 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { #fireImmediately: fireImmediately, }, ), - returnValue: _i19.Stream<_i22.AddressLabel?>.empty(), - ) as _i19.Stream<_i22.AddressLabel?>); + returnValue: _i20.Stream<_i23.AddressLabel?>.empty(), + ) as _i20.Stream<_i23.AddressLabel?>); @override - _i19.Future updateAddressLabel(_i22.AddressLabel? addressLabel) => + _i20.Future updateAddressLabel(_i23.AddressLabel? addressLabel) => (super.noSuchMethod( Invocation.method( #updateAddressLabel, [addressLabel], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future deleteWalletBlockchainData(String? walletId) => + _i20.Future deleteWalletBlockchainData(String? walletId) => (super.noSuchMethod( Invocation.method( #deleteWalletBlockchainData, [walletId], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future deleteAddressLabels(String? walletId) => + _i20.Future deleteAddressLabels(String? walletId) => (super.noSuchMethod( Invocation.method( #deleteAddressLabels, [walletId], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future deleteTransactionNotes(String? walletId) => + _i20.Future deleteTransactionNotes(String? walletId) => (super.noSuchMethod( Invocation.method( #deleteTransactionNotes, [walletId], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future addNewTransactionData( - List<_i15.Tuple2<_i22.Transaction, _i22.Address?>>? transactionsData, + _i20.Future addNewTransactionData( + List<_i15.Tuple2<_i23.Transaction, _i23.Address?>>? transactionsData, String? walletId, ) => (super.noSuchMethod( @@ -3499,76 +3526,76 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB { walletId, ], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i16.QueryBuilder<_i22.EthContract, _i22.EthContract, _i16.QWhere> + _i17.QueryBuilder<_i23.EthContract, _i23.EthContract, _i17.QWhere> getEthContracts() => (super.noSuchMethod( Invocation.method( #getEthContracts, [], ), - returnValue: _FakeQueryBuilder_15<_i22.EthContract, - _i22.EthContract, _i16.QWhere>( + returnValue: _FakeQueryBuilder_16<_i23.EthContract, + _i23.EthContract, _i17.QWhere>( this, Invocation.method( #getEthContracts, [], ), ), - ) as _i16 - .QueryBuilder<_i22.EthContract, _i22.EthContract, _i16.QWhere>); + ) as _i17 + .QueryBuilder<_i23.EthContract, _i23.EthContract, _i17.QWhere>); @override - _i19.Future<_i22.EthContract?> getEthContract(String? contractAddress) => + _i20.Future<_i23.EthContract?> getEthContract(String? contractAddress) => (super.noSuchMethod( Invocation.method( #getEthContract, [contractAddress], ), - returnValue: _i19.Future<_i22.EthContract?>.value(), - ) as _i19.Future<_i22.EthContract?>); + returnValue: _i20.Future<_i23.EthContract?>.value(), + ) as _i20.Future<_i23.EthContract?>); @override - _i22.EthContract? getEthContractSync(String? contractAddress) => + _i23.EthContract? getEthContractSync(String? contractAddress) => (super.noSuchMethod(Invocation.method( #getEthContractSync, [contractAddress], - )) as _i22.EthContract?); + )) as _i23.EthContract?); @override - _i19.Future putEthContract(_i22.EthContract? contract) => + _i20.Future putEthContract(_i23.EthContract? contract) => (super.noSuchMethod( Invocation.method( #putEthContract, [contract], ), - returnValue: _i19.Future.value(0), - ) as _i19.Future); + returnValue: _i20.Future.value(0), + ) as _i20.Future); @override - _i19.Future putEthContracts(List<_i22.EthContract>? contracts) => + _i20.Future putEthContracts(List<_i23.EthContract>? contracts) => (super.noSuchMethod( Invocation.method( #putEthContracts, [contracts], ), - returnValue: _i19.Future.value(), - returnValueForMissingStub: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + returnValueForMissingStub: _i20.Future.value(), + ) as _i20.Future); @override - _i19.Future getHighestUsedMintIndex({required String? walletId}) => + _i20.Future getHighestUsedMintIndex({required String? walletId}) => (super.noSuchMethod( Invocation.method( #getHighestUsedMintIndex, [], {#walletId: walletId}, ), - returnValue: _i19.Future.value(), - ) as _i19.Future); + returnValue: _i20.Future.value(), + ) as _i20.Future); } /// A class which mocks [IThemeAssets]. /// /// See the documentation for Mockito's code generation for more information. -class MockIThemeAssets extends _i1.Mock implements _i33.IThemeAssets { +class MockIThemeAssets extends _i1.Mock implements _i34.IThemeAssets { MockIThemeAssets() { _i1.throwOnMissingStub(this); } diff --git a/test/widget_tests/wallet_card_test.mocks.dart b/test/widget_tests/wallet_card_test.mocks.dart index 14744fc3f..5ed295d28 100644 --- a/test/widget_tests/wallet_card_test.mocks.dart +++ b/test/widget_tests/wallet_card_test.mocks.dart @@ -3,9 +3,9 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i21; -import 'dart:typed_data' as _i28; -import 'dart:ui' as _i23; +import 'dart:async' as _i22; +import 'dart:typed_data' as _i29; +import 'dart:ui' as _i24; import 'package:bip32/bip32.dart' as _i16; import 'package:bip47/bip47.dart' as _i18; @@ -18,24 +18,25 @@ import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i10; import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i9; import 'package:stackwallet/models/balance.dart' as _i11; import 'package:stackwallet/models/isar/models/isar_models.dart' as _i17; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i31; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i32; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i8; -import 'package:stackwallet/models/signing_data.dart' as _i26; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i24; +import 'package:stackwallet/models/signing_data.dart' as _i27; +import 'package:stackwallet/networking/http.dart' as _i19; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i25; import 'package:stackwallet/services/coins/manager.dart' as _i6; -import 'package:stackwallet/services/locale_service.dart' as _i29; +import 'package:stackwallet/services/locale_service.dart' as _i30; import 'package:stackwallet/services/node_service.dart' as _i3; import 'package:stackwallet/services/transaction_notification_tracker.dart' as _i7; -import 'package:stackwallet/services/wallets.dart' as _i19; +import 'package:stackwallet/services/wallets.dart' as _i20; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/themes/theme_service.dart' as _i30; +import 'package:stackwallet/themes/theme_service.dart' as _i31; import 'package:stackwallet/utilities/amount/amount.dart' as _i14; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i20; -import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i25; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i21; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i26; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' - as _i27; -import 'package:stackwallet/utilities/prefs.dart' as _i22; + as _i28; +import 'package:stackwallet/utilities/prefs.dart' as _i23; import 'package:tuple/tuple.dart' as _i15; // ignore_for_file: type=lint @@ -224,10 +225,20 @@ class _FakePaymentCode_16 extends _i1.SmartFake implements _i18.PaymentCode { ); } +class _FakeHTTP_17 extends _i1.SmartFake implements _i19.HTTP { + _FakeHTTP_17( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + /// A class which mocks [Wallets]. /// /// See the documentation for Mockito's code generation for more information. -class MockWallets extends _i1.Mock implements _i19.Wallets { +class MockWallets extends _i1.Mock implements _i20.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -294,7 +305,7 @@ class MockWallets extends _i1.Mock implements _i19.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i20.Coin? coin}) => + List getWalletIdsFor({required _i21.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -304,20 +315,20 @@ class MockWallets extends _i1.Mock implements _i19.Wallets { returnValue: [], ) as List); @override - List<_i15.Tuple2<_i20.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> + List<_i15.Tuple2<_i21.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i15.Tuple2<_i20.Coin, + returnValue: <_i15.Tuple2<_i21.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>[], ) as List< - _i15.Tuple2<_i20.Coin, + _i15.Tuple2<_i21.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i20.Coin? coin) => + _i21.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -381,17 +392,17 @@ class MockWallets extends _i1.Mock implements _i19.Wallets { returnValueForMissingStub: null, ); @override - _i21.Future load(_i22.Prefs? prefs) => (super.noSuchMethod( + _i22.Future load(_i23.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future loadAfterStackRestore( - _i22.Prefs? prefs, + _i22.Future loadAfterStackRestore( + _i23.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -402,11 +413,11 @@ class MockWallets extends _i1.Mock implements _i19.Wallets { managers, ], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - void addListener(_i23.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i24.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -414,7 +425,7 @@ class MockWallets extends _i1.Mock implements _i19.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i23.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i24.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -434,13 +445,13 @@ class MockWallets extends _i1.Mock implements _i19.Wallets { /// A class which mocks [BitcoinWallet]. /// /// See the documentation for Mockito's code generation for more information. -class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i25.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i21.Timer? _timer) => super.noSuchMethod( + set timer(_i22.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -517,74 +528,74 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValue: false, ) as bool); @override - _i20.Coin get coin => (super.noSuchMethod( + _i21.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i20.Coin.bitcoin, - ) as _i20.Coin); + returnValue: _i21.Coin.bitcoin, + ) as _i21.Coin); @override - _i21.Future> get utxos => (super.noSuchMethod( + _i22.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i21.Future>.value(<_i17.UTXO>[]), - ) as _i21.Future>); + returnValue: _i22.Future>.value(<_i17.UTXO>[]), + ) as _i22.Future>); @override - _i21.Future> get transactions => (super.noSuchMethod( + _i22.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i21.Future>.value(<_i17.Transaction>[]), - ) as _i21.Future>); + _i22.Future>.value(<_i17.Transaction>[]), + ) as _i22.Future>); @override - _i21.Future get currentReceivingAddress => (super.noSuchMethod( + _i22.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i21.Future.value(''), - ) as _i21.Future); + returnValue: _i22.Future.value(''), + ) as _i22.Future); @override - _i21.Future get currentChangeAddress => (super.noSuchMethod( + _i22.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i21.Future.value(''), - ) as _i21.Future); + returnValue: _i22.Future.value(''), + ) as _i22.Future); @override - _i21.Future get currentChangeAddressP2PKH => (super.noSuchMethod( + _i22.Future get currentChangeAddressP2PKH => (super.noSuchMethod( Invocation.getter(#currentChangeAddressP2PKH), - returnValue: _i21.Future.value(''), - ) as _i21.Future); + returnValue: _i22.Future.value(''), + ) as _i22.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i21.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i22.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i21.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i22.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i21.Future<_i8.FeeObject>); + ) as _i22.Future<_i8.FeeObject>); @override - _i21.Future get maxFee => (super.noSuchMethod( + _i22.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i21.Future.value(0), - ) as _i21.Future); + returnValue: _i22.Future.value(0), + ) as _i22.Future); @override - _i21.Future> get mnemonic => (super.noSuchMethod( + _i22.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i21.Future>.value([]), - ) as _i21.Future>); + returnValue: _i22.Future>.value([]), + ) as _i22.Future>); @override - _i21.Future get mnemonicString => (super.noSuchMethod( + _i22.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future get mnemonicPassphrase => (super.noSuchMethod( + _i22.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future get chainHeight => (super.noSuchMethod( + _i22.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i21.Future.value(0), - ) as _i21.Future); + returnValue: _i22.Future.value(0), + ) as _i22.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -656,10 +667,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { ), ) as _i11.Balance); @override - _i21.Future get xpub => (super.noSuchMethod( + _i22.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i21.Future.value(''), - ) as _i21.Future); + returnValue: _i22.Future.value(''), + ) as _i22.Future); @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -686,26 +697,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { ), ) as _i13.NetworkType); @override - _i21.Future exit() => (super.noSuchMethod( + _i22.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i25.DerivePathType addressType({required String? address}) => + _i26.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i25.DerivePathType.bip44, - ) as _i25.DerivePathType); + returnValue: _i26.DerivePathType.bip44, + ) as _i26.DerivePathType); @override - _i21.Future recoverFromMnemonic({ + _i22.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -724,47 +735,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { #height: height, }, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future getTransactionCacheEarly(List? allAddresses) => + _i22.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i22.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i21.Future.value(false), - ) as _i21.Future); + returnValue: _i22.Future.value(false), + ) as _i22.Future); @override - _i21.Future getAllTxsToWatch() => (super.noSuchMethod( + _i22.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future refresh() => (super.noSuchMethod( + _i22.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future> prepareSend({ + _i22.Future> prepareSend({ required String? address, required _i14.Amount? amount, Map? args, @@ -780,26 +791,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { }, ), returnValue: - _i21.Future>.value({}), - ) as _i21.Future>); + _i22.Future>.value({}), + ) as _i22.Future>); @override - _i21.Future confirmSend({required Map? txData}) => + _i22.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i21.Future.value(''), - ) as _i21.Future); + returnValue: _i22.Future.value(''), + ) as _i22.Future); @override - _i21.Future testNetworkConnection() => (super.noSuchMethod( + _i22.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i21.Future.value(false), - ) as _i21.Future); + returnValue: _i22.Future.value(false), + ) as _i22.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -817,35 +828,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i21.Future initializeNew( + _i22.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future initializeExisting() => (super.noSuchMethod( + _i22.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future updateSentCachedTxData(Map? txData) => + _i22.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -855,69 +866,69 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValue: false, ) as bool); @override - _i21.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i22.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i22.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), - returnValue: _i21.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_11( + returnValue: _i22.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_11( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i21.Future<_i9.ElectrumXNode>); + ) as _i22.Future<_i9.ElectrumXNode>); @override - _i21.Future>> fastFetch( + _i22.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i21.Future>>.value( + returnValue: _i22.Future>>.value( >[]), - ) as _i21.Future>>); + ) as _i22.Future>>); @override - _i21.Future getTxCount({required String? address}) => + _i22.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i21.Future.value(0), - ) as _i21.Future); + returnValue: _i22.Future.value(0), + ) as _i22.Future); @override - _i21.Future checkCurrentReceivingAddressesForTransactions() => + _i22.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future checkCurrentChangeAddressesForTransactions() => + _i22.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override int estimateTxFee({ required int? vSize, @@ -960,7 +971,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { }, )); @override - _i21.Future> fetchBuildTxData( + _i22.Future> fetchBuildTxData( List<_i17.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( @@ -968,11 +979,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { [utxosToUse], ), returnValue: - _i21.Future>.value(<_i26.SigningData>[]), - ) as _i21.Future>); + _i22.Future>.value(<_i27.SigningData>[]), + ) as _i22.Future>); @override - _i21.Future> buildTransaction({ - required List<_i26.SigningData>? utxoSigningData, + _i22.Future> buildTransaction({ + required List<_i27.SigningData>? utxoSigningData, required List? recipients, required List? satoshiAmounts, }) => @@ -987,10 +998,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { }, ), returnValue: - _i21.Future>.value({}), - ) as _i21.Future>); + _i22.Future>.value({}), + ) as _i22.Future>); @override - _i21.Future fullRescan( + _i22.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1002,11 +1013,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future<_i14.Amount> estimateFeeFor( + _i22.Future<_i14.Amount> estimateFeeFor( _i14.Amount? amount, int? feeRate, ) => @@ -1018,7 +1029,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { feeRate, ], ), - returnValue: _i21.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i22.Future<_i14.Amount>.value(_FakeAmount_12( this, Invocation.method( #estimateFeeFor, @@ -1028,7 +1039,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { ], ), )), - ) as _i21.Future<_i14.Amount>); + ) as _i22.Future<_i14.Amount>); @override _i14.Amount roughFeeEstimate( int? inputCount, @@ -1057,32 +1068,32 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { ), ) as _i14.Amount); @override - _i21.Future<_i14.Amount> sweepAllEstimate(int? feeRate) => + _i22.Future<_i14.Amount> sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i21.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i22.Future<_i14.Amount>.value(_FakeAmount_12( this, Invocation.method( #sweepAllEstimate, [feeRate], ), )), - ) as _i21.Future<_i14.Amount>); + ) as _i22.Future<_i14.Amount>); @override - _i21.Future generateNewAddress() => (super.noSuchMethod( + _i22.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i21.Future.value(false), - ) as _i21.Future); + returnValue: _i22.Future.value(false), + ) as _i22.Future); @override void initCache( String? walletId, - _i20.Coin? coin, + _i21.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1095,14 +1106,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i21.Future updateCachedId(String? id) => (super.noSuchMethod( + _i22.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1112,14 +1123,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValue: 0, ) as int); @override - _i21.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i22.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1129,15 +1140,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValue: false, ) as bool); @override - _i21.Future updateCachedIsFavorite(bool? isFavorite) => + _i22.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override _i11.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1153,15 +1164,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { ), ) as _i11.Balance); @override - _i21.Future updateCachedBalance(_i11.Balance? balance) => + _i22.Future updateCachedBalance(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override _i11.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1177,15 +1188,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { ), ) as _i11.Balance); @override - _i21.Future updateCachedBalanceSecondary(_i11.Balance? balance) => + _i22.Future updateCachedBalanceSecondary(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override List getWalletTokenContractAddresses() => (super.noSuchMethod( Invocation.method( @@ -1195,16 +1206,16 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValue: [], ) as List); @override - _i21.Future updateWalletTokenContractAddresses( + _i22.Future updateWalletTokenContractAddresses( List? contractAddresses) => (super.noSuchMethod( Invocation.method( #updateWalletTokenContractAddresses, [contractAddresses], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override void initWalletDB({_i12.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1215,11 +1226,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i21.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>> parseTransaction( + _i22.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>> parseTransaction( Map? txData, dynamic electrumxClient, List<_i17.Address>? myAddresses, - _i20.Coin? coin, + _i21.Coin? coin, int? minConfirms, String? walletId, ) => @@ -1236,7 +1247,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { ], ), returnValue: - _i21.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>.value( + _i22.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>.value( _FakeTuple2_13<_i17.Transaction, _i17.Address>( this, Invocation.method( @@ -1251,37 +1262,37 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { ], ), )), - ) as _i21.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>); + ) as _i22.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>); @override void initPaynymWalletInterface({ required String? walletId, required String? walletName, required _i13.NetworkType? network, - required _i20.Coin? coin, + required _i21.Coin? coin, required _i12.MainDB? db, required _i9.ElectrumX? electrumXClient, - required _i27.SecureStorageInterface? secureStorage, + required _i28.SecureStorageInterface? secureStorage, required int? dustLimit, required int? dustLimitP2PKH, required int? minConfirms, - required _i21.Future Function()? getMnemonicString, - required _i21.Future Function()? getMnemonicPassphrase, - required _i21.Future Function()? getChainHeight, - required _i21.Future Function()? getCurrentChangeAddress, + required _i22.Future Function()? getMnemonicString, + required _i22.Future Function()? getMnemonicPassphrase, + required _i22.Future Function()? getChainHeight, + required _i22.Future Function()? getCurrentChangeAddress, required int Function({ required int feeRatePerKB, required int vSize, })? estimateTxFee, - required _i21.Future> Function({ + required _i22.Future> Function({ required String address, required _i14.Amount amount, Map? args, })? prepareSend, - required _i21.Future Function({required String address})? getTxCount, - required _i21.Future> Function(List<_i17.UTXO>)? + required _i22.Future Function({required String address})? getTxCount, + required _i22.Future> Function(List<_i17.UTXO>)? fetchBuildTxData, - required _i21.Future Function()? refresh, - required _i21.Future Function()? checkChangeAddressForTransactions, + required _i22.Future Function()? refresh, + required _i22.Future Function()? checkChangeAddressForTransactions, }) => super.noSuchMethod( Invocation.method( @@ -1314,21 +1325,21 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i21.Future<_i16.BIP32> getBip47BaseNode() => (super.noSuchMethod( + _i22.Future<_i16.BIP32> getBip47BaseNode() => (super.noSuchMethod( Invocation.method( #getBip47BaseNode, [], ), - returnValue: _i21.Future<_i16.BIP32>.value(_FakeBIP32_14( + returnValue: _i22.Future<_i16.BIP32>.value(_FakeBIP32_14( this, Invocation.method( #getBip47BaseNode, [], ), )), - ) as _i21.Future<_i16.BIP32>); + ) as _i22.Future<_i16.BIP32>); @override - _i21.Future<_i28.Uint8List> getPrivateKeyForPaynymReceivingAddress({ + _i22.Future<_i29.Uint8List> getPrivateKeyForPaynymReceivingAddress({ required String? paymentCodeString, required int? index, }) => @@ -1341,10 +1352,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { #index: index, }, ), - returnValue: _i21.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), - ) as _i21.Future<_i28.Uint8List>); + returnValue: _i22.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), + ) as _i22.Future<_i29.Uint8List>); @override - _i21.Future<_i17.Address> currentReceivingPaynymAddress({ + _i22.Future<_i17.Address> currentReceivingPaynymAddress({ required _i18.PaymentCode? sender, required bool? isSegwit, }) => @@ -1357,7 +1368,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i21.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i22.Future<_i17.Address>.value(_FakeAddress_15( this, Invocation.method( #currentReceivingPaynymAddress, @@ -1368,9 +1379,9 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { }, ), )), - ) as _i21.Future<_i17.Address>); + ) as _i22.Future<_i17.Address>); @override - _i21.Future checkCurrentPaynymReceivingAddressForTransactions({ + _i22.Future checkCurrentPaynymReceivingAddressForTransactions({ required _i18.PaymentCode? sender, required bool? isSegwit, }) => @@ -1383,42 +1394,42 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => + _i22.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkAllCurrentReceivingPaynymAddressesForTransactions, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future<_i16.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( + _i22.Future<_i16.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( Invocation.method( #deriveNotificationBip32Node, [], ), - returnValue: _i21.Future<_i16.BIP32>.value(_FakeBIP32_14( + returnValue: _i22.Future<_i16.BIP32>.value(_FakeBIP32_14( this, Invocation.method( #deriveNotificationBip32Node, [], ), )), - ) as _i21.Future<_i16.BIP32>); + ) as _i22.Future<_i16.BIP32>); @override - _i21.Future<_i18.PaymentCode> getPaymentCode({required bool? isSegwit}) => + _i22.Future<_i18.PaymentCode> getPaymentCode({required bool? isSegwit}) => (super.noSuchMethod( Invocation.method( #getPaymentCode, [], {#isSegwit: isSegwit}, ), - returnValue: _i21.Future<_i18.PaymentCode>.value(_FakePaymentCode_16( + returnValue: _i22.Future<_i18.PaymentCode>.value(_FakePaymentCode_16( this, Invocation.method( #getPaymentCode, @@ -1426,27 +1437,27 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { {#isSegwit: isSegwit}, ), )), - ) as _i21.Future<_i18.PaymentCode>); + ) as _i22.Future<_i18.PaymentCode>); @override - _i21.Future<_i28.Uint8List> signWithNotificationKey(_i28.Uint8List? data) => + _i22.Future<_i29.Uint8List> signWithNotificationKey(_i29.Uint8List? data) => (super.noSuchMethod( Invocation.method( #signWithNotificationKey, [data], ), - returnValue: _i21.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), - ) as _i21.Future<_i28.Uint8List>); + returnValue: _i22.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), + ) as _i22.Future<_i29.Uint8List>); @override - _i21.Future signStringWithNotificationKey(String? data) => + _i22.Future signStringWithNotificationKey(String? data) => (super.noSuchMethod( Invocation.method( #signStringWithNotificationKey, [data], ), - returnValue: _i21.Future.value(''), - ) as _i21.Future); + returnValue: _i22.Future.value(''), + ) as _i22.Future); @override - _i21.Future> preparePaymentCodeSend({ + _i22.Future> preparePaymentCodeSend({ required _i18.PaymentCode? paymentCode, required bool? isSegwit, required _i14.Amount? amount, @@ -1464,10 +1475,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { }, ), returnValue: - _i21.Future>.value({}), - ) as _i21.Future>); + _i22.Future>.value({}), + ) as _i22.Future>); @override - _i21.Future<_i17.Address> nextUnusedSendAddressFrom({ + _i22.Future<_i17.Address> nextUnusedSendAddressFrom({ required _i18.PaymentCode? pCode, required bool? isSegwit, required _i16.BIP32? privateKeyNode, @@ -1484,7 +1495,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { #startIndex: startIndex, }, ), - returnValue: _i21.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i22.Future<_i17.Address>.value(_FakeAddress_15( this, Invocation.method( #nextUnusedSendAddressFrom, @@ -1497,9 +1508,9 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { }, ), )), - ) as _i21.Future<_i17.Address>); + ) as _i22.Future<_i17.Address>); @override - _i21.Future> prepareNotificationTx({ + _i22.Future> prepareNotificationTx({ required int? selectedTxFeeRate, required String? targetPaymentCodeString, int? additionalOutputs = 0, @@ -1517,10 +1528,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { }, ), returnValue: - _i21.Future>.value({}), - ) as _i21.Future>); + _i22.Future>.value({}), + ) as _i22.Future>); @override - _i21.Future broadcastNotificationTx( + _i22.Future broadcastNotificationTx( {required Map? preparedTx}) => (super.noSuchMethod( Invocation.method( @@ -1528,19 +1539,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { [], {#preparedTx: preparedTx}, ), - returnValue: _i21.Future.value(''), - ) as _i21.Future); + returnValue: _i22.Future.value(''), + ) as _i22.Future); @override - _i21.Future hasConnected(String? paymentCodeString) => + _i22.Future hasConnected(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #hasConnected, [paymentCodeString], ), - returnValue: _i21.Future.value(false), - ) as _i21.Future); + returnValue: _i22.Future.value(false), + ) as _i22.Future); @override - _i21.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransaction( + _i22.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransaction( {required _i17.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( @@ -1548,10 +1559,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { [], {#transaction: transaction}, ), - returnValue: _i21.Future<_i18.PaymentCode?>.value(), - ) as _i21.Future<_i18.PaymentCode?>); + returnValue: _i22.Future<_i18.PaymentCode?>.value(), + ) as _i22.Future<_i18.PaymentCode?>); @override - _i21.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( + _i22.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( {required _i17.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( @@ -1559,31 +1570,31 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { [], {#transaction: transaction}, ), - returnValue: _i21.Future<_i18.PaymentCode?>.value(), - ) as _i21.Future<_i18.PaymentCode?>); + returnValue: _i22.Future<_i18.PaymentCode?>.value(), + ) as _i22.Future<_i18.PaymentCode?>); @override - _i21.Future> + _i22.Future> getAllPaymentCodesFromNotificationTransactions() => (super.noSuchMethod( Invocation.method( #getAllPaymentCodesFromNotificationTransactions, [], ), returnValue: - _i21.Future>.value(<_i18.PaymentCode>[]), - ) as _i21.Future>); + _i22.Future>.value(<_i18.PaymentCode>[]), + ) as _i22.Future>); @override - _i21.Future checkForNotificationTransactionsTo( + _i22.Future checkForNotificationTransactionsTo( Set? otherCodeStrings) => (super.noSuchMethod( Invocation.method( #checkForNotificationTransactionsTo, [otherCodeStrings], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future restoreAllHistory({ + _i22.Future restoreAllHistory({ required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, required Set? paymentCodeStrings, @@ -1598,11 +1609,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { #paymentCodeStrings: paymentCodeStrings, }, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future restoreHistoryWith({ + _i22.Future restoreHistoryWith({ required _i18.PaymentCode? other, required bool? checkSegwitAsWell, required int? maxUnusedAddressGap, @@ -1619,58 +1630,58 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { #maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, }, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future<_i17.Address> getMyNotificationAddress() => (super.noSuchMethod( + _i22.Future<_i17.Address> getMyNotificationAddress() => (super.noSuchMethod( Invocation.method( #getMyNotificationAddress, [], ), - returnValue: _i21.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i22.Future<_i17.Address>.value(_FakeAddress_15( this, Invocation.method( #getMyNotificationAddress, [], ), )), - ) as _i21.Future<_i17.Address>); + ) as _i22.Future<_i17.Address>); @override - _i21.Future> lookupKey(String? paymentCodeString) => + _i22.Future> lookupKey(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #lookupKey, [paymentCodeString], ), - returnValue: _i21.Future>.value([]), - ) as _i21.Future>); + returnValue: _i22.Future>.value([]), + ) as _i22.Future>); @override - _i21.Future paymentCodeStringByKey(String? key) => + _i22.Future paymentCodeStringByKey(String? key) => (super.noSuchMethod( Invocation.method( #paymentCodeStringByKey, [key], ), - returnValue: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future storeCode(String? paymentCodeString) => + _i22.Future storeCode(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #storeCode, [paymentCodeString], ), - returnValue: _i21.Future.value(''), - ) as _i21.Future); + returnValue: _i22.Future.value(''), + ) as _i22.Future); @override void initCoinControlInterface({ required String? walletId, required String? walletName, - required _i20.Coin? coin, + required _i21.Coin? coin, required _i12.MainDB? db, - required _i21.Future Function()? getChainHeight, - required _i21.Future Function(_i11.Balance)? refreshedBalanceCallback, + required _i22.Future Function()? getChainHeight, + required _i22.Future Function(_i11.Balance)? refreshedBalanceCallback, }) => super.noSuchMethod( Invocation.method( @@ -1688,22 +1699,22 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i21.Future refreshBalance({bool? notify = false}) => + _i22.Future refreshBalance({bool? notify = false}) => (super.noSuchMethod( Invocation.method( #refreshBalance, [], {#notify: notify}, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); } /// A class which mocks [LocaleService]. /// /// See the documentation for Mockito's code generation for more information. -class MockLocaleService extends _i1.Mock implements _i29.LocaleService { +class MockLocaleService extends _i1.Mock implements _i30.LocaleService { MockLocaleService() { _i1.throwOnMissingStub(this); } @@ -1719,17 +1730,17 @@ class MockLocaleService extends _i1.Mock implements _i29.LocaleService { returnValue: false, ) as bool); @override - _i21.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( + _i22.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( Invocation.method( #loadLocale, [], {#notify: notify}, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - void addListener(_i23.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i24.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1737,7 +1748,7 @@ class MockLocaleService extends _i1.Mock implements _i29.LocaleService { returnValueForMissingStub: null, ); @override - void removeListener(_i23.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i24.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1765,11 +1776,27 @@ class MockLocaleService extends _i1.Mock implements _i29.LocaleService { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i30.ThemeService { +class MockThemeService extends _i1.Mock implements _i31.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } + @override + _i19.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_17( + this, + Invocation.getter(#client), + ), + ) as _i19.HTTP); + @override + set client(_i19.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); @override _i12.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), @@ -1779,10 +1806,10 @@ class MockThemeService extends _i1.Mock implements _i30.ThemeService { ), ) as _i12.MainDB); @override - List<_i31.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i32.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i31.StackTheme>[], - ) as List<_i31.StackTheme>); + returnValue: <_i32.StackTheme>[], + ) as List<_i32.StackTheme>); @override void init(_i12.MainDB? db) => super.noSuchMethod( Invocation.method( @@ -1792,71 +1819,71 @@ class MockThemeService extends _i1.Mock implements _i30.ThemeService { returnValueForMissingStub: null, ); @override - _i21.Future install({required _i28.Uint8List? themeArchiveData}) => + _i22.Future install({required _i29.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future remove({required String? themeId}) => (super.noSuchMethod( + _i22.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i22.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i21.Future.value(), - returnValueForMissingStub: _i21.Future.value(), - ) as _i21.Future); + returnValue: _i22.Future.value(), + returnValueForMissingStub: _i22.Future.value(), + ) as _i22.Future); @override - _i21.Future verifyInstalled({required String? themeId}) => + _i22.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i21.Future.value(false), - ) as _i21.Future); + returnValue: _i22.Future.value(false), + ) as _i22.Future); @override - _i21.Future> fetchThemes() => + _i22.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i21.Future>.value( - <_i30.StackThemeMetaData>[]), - ) as _i21.Future>); + returnValue: _i22.Future>.value( + <_i31.StackThemeMetaData>[]), + ) as _i22.Future>); @override - _i21.Future<_i28.Uint8List> fetchTheme( - {required _i30.StackThemeMetaData? themeMetaData}) => + _i22.Future<_i29.Uint8List> fetchTheme( + {required _i31.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i21.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), - ) as _i21.Future<_i28.Uint8List>); + returnValue: _i22.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), + ) as _i22.Future<_i29.Uint8List>); @override - _i31.StackTheme? getTheme({required String? themeId}) => + _i32.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i31.StackTheme?); + )) as _i32.StackTheme?); } diff --git a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart index 16b4aa49e..7a14a4547 100644 --- a/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart +++ b/test/widget_tests/wallet_info_row/wallet_info_row_test.mocks.dart @@ -3,41 +3,42 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i23; -import 'dart:typed_data' as _i28; -import 'dart:ui' as _i25; +import 'dart:async' as _i24; +import 'dart:typed_data' as _i29; +import 'dart:ui' as _i26; -import 'package:bip32/bip32.dart' as _i16; -import 'package:bip47/bip47.dart' as _i18; -import 'package:bitcoindart/bitcoindart.dart' as _i13; +import 'package:bip32/bip32.dart' as _i17; +import 'package:bip47/bip47.dart' as _i19; +import 'package:bitcoindart/bitcoindart.dart' as _i14; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; -import 'package:stackwallet/db/isar/main_db.dart' as _i7; -import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i11; -import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i10; -import 'package:stackwallet/models/balance.dart' as _i12; -import 'package:stackwallet/models/isar/models/isar_models.dart' as _i17; -import 'package:stackwallet/models/isar/stack_theme.dart' as _i27; -import 'package:stackwallet/models/node_model.dart' as _i32; -import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i9; -import 'package:stackwallet/models/signing_data.dart' as _i31; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i29; -import 'package:stackwallet/services/coins/coin_service.dart' as _i20; +import 'package:stackwallet/db/isar/main_db.dart' as _i8; +import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i12; +import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i11; +import 'package:stackwallet/models/balance.dart' as _i13; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i18; +import 'package:stackwallet/models/isar/stack_theme.dart' as _i28; +import 'package:stackwallet/models/node_model.dart' as _i33; +import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i10; +import 'package:stackwallet/models/signing_data.dart' as _i32; +import 'package:stackwallet/networking/http.dart' as _i7; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i30; +import 'package:stackwallet/services/coins/coin_service.dart' as _i21; import 'package:stackwallet/services/coins/manager.dart' as _i6; import 'package:stackwallet/services/node_service.dart' as _i3; import 'package:stackwallet/services/transaction_notification_tracker.dart' - as _i8; -import 'package:stackwallet/services/wallets.dart' as _i21; + as _i9; +import 'package:stackwallet/services/wallets.dart' as _i22; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/themes/theme_service.dart' as _i26; -import 'package:stackwallet/utilities/amount/amount.dart' as _i14; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i22; -import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i30; +import 'package:stackwallet/themes/theme_service.dart' as _i27; +import 'package:stackwallet/utilities/amount/amount.dart' as _i15; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i23; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i31; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' - as _i19; -import 'package:stackwallet/utilities/prefs.dart' as _i24; -import 'package:tuple/tuple.dart' as _i15; + as _i20; +import 'package:stackwallet/utilities/prefs.dart' as _i25; +import 'package:tuple/tuple.dart' as _i16; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -92,8 +93,8 @@ class _FakeManager_3 extends _i1.SmartFake implements _i6.Manager { ); } -class _FakeMainDB_4 extends _i1.SmartFake implements _i7.MainDB { - _FakeMainDB_4( +class _FakeHTTP_4 extends _i1.SmartFake implements _i7.HTTP { + _FakeHTTP_4( Object parent, Invocation parentInvocation, ) : super( @@ -102,9 +103,8 @@ class _FakeMainDB_4 extends _i1.SmartFake implements _i7.MainDB { ); } -class _FakeTransactionNotificationTracker_5 extends _i1.SmartFake - implements _i8.TransactionNotificationTracker { - _FakeTransactionNotificationTracker_5( +class _FakeMainDB_5 extends _i1.SmartFake implements _i8.MainDB { + _FakeMainDB_5( Object parent, Invocation parentInvocation, ) : super( @@ -113,8 +113,9 @@ class _FakeTransactionNotificationTracker_5 extends _i1.SmartFake ); } -class _FakeFeeObject_6 extends _i1.SmartFake implements _i9.FeeObject { - _FakeFeeObject_6( +class _FakeTransactionNotificationTracker_6 extends _i1.SmartFake + implements _i9.TransactionNotificationTracker { + _FakeTransactionNotificationTracker_6( Object parent, Invocation parentInvocation, ) : super( @@ -123,8 +124,8 @@ class _FakeFeeObject_6 extends _i1.SmartFake implements _i9.FeeObject { ); } -class _FakeElectrumX_7 extends _i1.SmartFake implements _i10.ElectrumX { - _FakeElectrumX_7( +class _FakeFeeObject_7 extends _i1.SmartFake implements _i10.FeeObject { + _FakeFeeObject_7( Object parent, Invocation parentInvocation, ) : super( @@ -133,9 +134,8 @@ class _FakeElectrumX_7 extends _i1.SmartFake implements _i10.ElectrumX { ); } -class _FakeCachedElectrumX_8 extends _i1.SmartFake - implements _i11.CachedElectrumX { - _FakeCachedElectrumX_8( +class _FakeElectrumX_8 extends _i1.SmartFake implements _i11.ElectrumX { + _FakeElectrumX_8( Object parent, Invocation parentInvocation, ) : super( @@ -144,8 +144,9 @@ class _FakeCachedElectrumX_8 extends _i1.SmartFake ); } -class _FakeBalance_9 extends _i1.SmartFake implements _i12.Balance { - _FakeBalance_9( +class _FakeCachedElectrumX_9 extends _i1.SmartFake + implements _i12.CachedElectrumX { + _FakeCachedElectrumX_9( Object parent, Invocation parentInvocation, ) : super( @@ -154,8 +155,8 @@ class _FakeBalance_9 extends _i1.SmartFake implements _i12.Balance { ); } -class _FakeNetworkType_10 extends _i1.SmartFake implements _i13.NetworkType { - _FakeNetworkType_10( +class _FakeBalance_10 extends _i1.SmartFake implements _i13.Balance { + _FakeBalance_10( Object parent, Invocation parentInvocation, ) : super( @@ -164,9 +165,8 @@ class _FakeNetworkType_10 extends _i1.SmartFake implements _i13.NetworkType { ); } -class _FakeElectrumXNode_11 extends _i1.SmartFake - implements _i10.ElectrumXNode { - _FakeElectrumXNode_11( +class _FakeNetworkType_11 extends _i1.SmartFake implements _i14.NetworkType { + _FakeNetworkType_11( Object parent, Invocation parentInvocation, ) : super( @@ -175,8 +175,9 @@ class _FakeElectrumXNode_11 extends _i1.SmartFake ); } -class _FakeAmount_12 extends _i1.SmartFake implements _i14.Amount { - _FakeAmount_12( +class _FakeElectrumXNode_12 extends _i1.SmartFake + implements _i11.ElectrumXNode { + _FakeElectrumXNode_12( Object parent, Invocation parentInvocation, ) : super( @@ -185,9 +186,8 @@ class _FakeAmount_12 extends _i1.SmartFake implements _i14.Amount { ); } -class _FakeTuple2_13 extends _i1.SmartFake - implements _i15.Tuple2 { - _FakeTuple2_13( +class _FakeAmount_13 extends _i1.SmartFake implements _i15.Amount { + _FakeAmount_13( Object parent, Invocation parentInvocation, ) : super( @@ -196,8 +196,9 @@ class _FakeTuple2_13 extends _i1.SmartFake ); } -class _FakeBIP32_14 extends _i1.SmartFake implements _i16.BIP32 { - _FakeBIP32_14( +class _FakeTuple2_14 extends _i1.SmartFake + implements _i16.Tuple2 { + _FakeTuple2_14( Object parent, Invocation parentInvocation, ) : super( @@ -206,8 +207,8 @@ class _FakeBIP32_14 extends _i1.SmartFake implements _i16.BIP32 { ); } -class _FakeAddress_15 extends _i1.SmartFake implements _i17.Address { - _FakeAddress_15( +class _FakeBIP32_15 extends _i1.SmartFake implements _i17.BIP32 { + _FakeBIP32_15( Object parent, Invocation parentInvocation, ) : super( @@ -216,8 +217,8 @@ class _FakeAddress_15 extends _i1.SmartFake implements _i17.Address { ); } -class _FakePaymentCode_16 extends _i1.SmartFake implements _i18.PaymentCode { - _FakePaymentCode_16( +class _FakeAddress_16 extends _i1.SmartFake implements _i18.Address { + _FakeAddress_16( Object parent, Invocation parentInvocation, ) : super( @@ -226,9 +227,8 @@ class _FakePaymentCode_16 extends _i1.SmartFake implements _i18.PaymentCode { ); } -class _FakeSecureStorageInterface_17 extends _i1.SmartFake - implements _i19.SecureStorageInterface { - _FakeSecureStorageInterface_17( +class _FakePaymentCode_17 extends _i1.SmartFake implements _i19.PaymentCode { + _FakePaymentCode_17( Object parent, Invocation parentInvocation, ) : super( @@ -237,9 +237,20 @@ class _FakeSecureStorageInterface_17 extends _i1.SmartFake ); } -class _FakeCoinServiceAPI_18 extends _i1.SmartFake - implements _i20.CoinServiceAPI { - _FakeCoinServiceAPI_18( +class _FakeSecureStorageInterface_18 extends _i1.SmartFake + implements _i20.SecureStorageInterface { + _FakeSecureStorageInterface_18( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_19 extends _i1.SmartFake + implements _i21.CoinServiceAPI { + _FakeCoinServiceAPI_19( Object parent, Invocation parentInvocation, ) : super( @@ -251,7 +262,7 @@ class _FakeCoinServiceAPI_18 extends _i1.SmartFake /// A class which mocks [Wallets]. /// /// See the documentation for Mockito's code generation for more information. -class MockWallets extends _i1.Mock implements _i21.Wallets { +class MockWallets extends _i1.Mock implements _i22.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -318,7 +329,7 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i22.Coin? coin}) => + List getWalletIdsFor({required _i23.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -328,20 +339,20 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValue: [], ) as List); @override - List<_i15.Tuple2<_i22.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> + List<_i16.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i15.Tuple2<_i22.Coin, + returnValue: <_i16.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>[], ) as List< - _i15.Tuple2<_i22.Coin, + _i16.Tuple2<_i23.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i22.Coin? coin) => + _i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -405,17 +416,17 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - _i23.Future load(_i24.Prefs? prefs) => (super.noSuchMethod( + _i24.Future load(_i25.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future loadAfterStackRestore( - _i24.Prefs? prefs, + _i24.Future loadAfterStackRestore( + _i25.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -426,11 +437,11 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { managers, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -438,7 +449,7 @@ class MockWallets extends _i1.Mock implements _i21.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -464,19 +475,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i23.Future> get walletNames => + _i24.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i23.Future>.value( + returnValue: _i24.Future>.value( {}), - ) as _i23.Future>); + ) as _i24.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future renameWallet({ + _i24.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -491,8 +502,8 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override Map fetchWalletsData() => (super.noSuchMethod( Invocation.method( @@ -502,10 +513,10 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValue: {}, ) as Map); @override - _i23.Future addExistingStackWallet({ + _i24.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i22.Coin? coin, + required _i23.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -519,13 +530,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future addNewWallet({ + _i24.Future addNewWallet({ required String? name, - required _i22.Coin? coin, + required _i23.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -538,46 +549,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i24.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future saveFavoriteWalletIds(List? walletIds) => + _i24.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i24.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i24.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future moveFavorite({ + _i24.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -590,48 +601,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i24.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i24.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future isMnemonicVerified({required String? walletId}) => + _i24.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future setMnemonicVerified({required String? walletId}) => + _i24.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future deleteWallet( + _i24.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -643,20 +654,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future refreshWallets(bool? shouldNotifyListeners) => + _i24.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -664,7 +675,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -692,26 +703,42 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { /// A class which mocks [ThemeService]. /// /// See the documentation for Mockito's code generation for more information. -class MockThemeService extends _i1.Mock implements _i26.ThemeService { +class MockThemeService extends _i1.Mock implements _i27.ThemeService { MockThemeService() { _i1.throwOnMissingStub(this); } @override - _i7.MainDB get db => (super.noSuchMethod( + _i7.HTTP get client => (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeHTTP_4( + this, + Invocation.getter(#client), + ), + ) as _i7.HTTP); + @override + set client(_i7.HTTP? _client) => super.noSuchMethod( + Invocation.setter( + #client, + _client, + ), + returnValueForMissingStub: null, + ); + @override + _i8.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_4( + returnValue: _FakeMainDB_5( this, Invocation.getter(#db), ), - ) as _i7.MainDB); + ) as _i8.MainDB); @override - List<_i27.StackTheme> get installedThemes => (super.noSuchMethod( + List<_i28.StackTheme> get installedThemes => (super.noSuchMethod( Invocation.getter(#installedThemes), - returnValue: <_i27.StackTheme>[], - ) as List<_i27.StackTheme>); + returnValue: <_i28.StackTheme>[], + ) as List<_i28.StackTheme>); @override - void init(_i7.MainDB? db) => super.noSuchMethod( + void init(_i8.MainDB? db) => super.noSuchMethod( Invocation.method( #init, [db], @@ -719,85 +746,85 @@ class MockThemeService extends _i1.Mock implements _i26.ThemeService { returnValueForMissingStub: null, ); @override - _i23.Future install({required _i28.Uint8List? themeArchiveData}) => + _i24.Future install({required _i29.Uint8List? themeArchiveData}) => (super.noSuchMethod( Invocation.method( #install, [], {#themeArchiveData: themeArchiveData}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future remove({required String? themeId}) => (super.noSuchMethod( + _i24.Future remove({required String? themeId}) => (super.noSuchMethod( Invocation.method( #remove, [], {#themeId: themeId}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( + _i24.Future checkDefaultThemesOnStartup() => (super.noSuchMethod( Invocation.method( #checkDefaultThemesOnStartup, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future verifyInstalled({required String? themeId}) => + _i24.Future verifyInstalled({required String? themeId}) => (super.noSuchMethod( Invocation.method( #verifyInstalled, [], {#themeId: themeId}, ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future> fetchThemes() => + _i24.Future> fetchThemes() => (super.noSuchMethod( Invocation.method( #fetchThemes, [], ), - returnValue: _i23.Future>.value( - <_i26.StackThemeMetaData>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value( + <_i27.StackThemeMetaData>[]), + ) as _i24.Future>); @override - _i23.Future<_i28.Uint8List> fetchTheme( - {required _i26.StackThemeMetaData? themeMetaData}) => + _i24.Future<_i29.Uint8List> fetchTheme( + {required _i27.StackThemeMetaData? themeMetaData}) => (super.noSuchMethod( Invocation.method( #fetchTheme, [], {#themeMetaData: themeMetaData}, ), - returnValue: _i23.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), - ) as _i23.Future<_i28.Uint8List>); + returnValue: _i24.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), + ) as _i24.Future<_i29.Uint8List>); @override - _i27.StackTheme? getTheme({required String? themeId}) => + _i28.StackTheme? getTheme({required String? themeId}) => (super.noSuchMethod(Invocation.method( #getTheme, [], {#themeId: themeId}, - )) as _i27.StackTheme?); + )) as _i28.StackTheme?); } /// A class which mocks [BitcoinWallet]. /// /// See the documentation for Mockito's code generation for more information. -class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i30.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i23.Timer? _timer) => super.noSuchMethod( + set timer(_i24.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -805,15 +832,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i8.TransactionNotificationTracker get txTracker => (super.noSuchMethod( + _i9.TransactionNotificationTracker get txTracker => (super.noSuchMethod( Invocation.getter(#txTracker), - returnValue: _FakeTransactionNotificationTracker_5( + returnValue: _FakeTransactionNotificationTracker_6( this, Invocation.getter(#txTracker), ), - ) as _i8.TransactionNotificationTracker); + ) as _i9.TransactionNotificationTracker); @override - set txTracker(_i8.TransactionNotificationTracker? _txTracker) => + set txTracker(_i9.TransactionNotificationTracker? _txTracker) => super.noSuchMethod( Invocation.setter( #txTracker, @@ -874,74 +901,74 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValue: false, ) as bool); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i17.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i18.UTXO>[]), + ) as _i24.Future>); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i17.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i18.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future get currentChangeAddress => (super.noSuchMethod( + _i24.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future get currentChangeAddressP2PKH => (super.noSuchMethod( + _i24.Future get currentChangeAddressP2PKH => (super.noSuchMethod( Invocation.getter(#currentChangeAddressP2PKH), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i23.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i10.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i24.Future<_i10.FeeObject>.value(_FakeFeeObject_7( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i9.FeeObject>); + ) as _i24.Future<_i10.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicString => (super.noSuchMethod( + _i24.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get chainHeight => (super.noSuchMethod( + _i24.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -989,34 +1016,34 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i10.ElectrumX get electrumXClient => (super.noSuchMethod( + _i11.ElectrumX get electrumXClient => (super.noSuchMethod( Invocation.getter(#electrumXClient), - returnValue: _FakeElectrumX_7( + returnValue: _FakeElectrumX_8( this, Invocation.getter(#electrumXClient), ), - ) as _i10.ElectrumX); + ) as _i11.ElectrumX); @override - _i11.CachedElectrumX get cachedElectrumXClient => (super.noSuchMethod( + _i12.CachedElectrumX get cachedElectrumXClient => (super.noSuchMethod( Invocation.getter(#cachedElectrumXClient), - returnValue: _FakeCachedElectrumX_8( + returnValue: _FakeCachedElectrumX_9( this, Invocation.getter(#cachedElectrumXClient), ), - ) as _i11.CachedElectrumX); + ) as _i12.CachedElectrumX); @override - _i12.Balance get balance => (super.noSuchMethod( + _i13.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.getter(#balance), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i23.Future get xpub => (super.noSuchMethod( + _i24.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -1027,42 +1054,42 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i7.MainDB get db => (super.noSuchMethod( + _i8.MainDB get db => (super.noSuchMethod( Invocation.getter(#db), - returnValue: _FakeMainDB_4( + returnValue: _FakeMainDB_5( this, Invocation.getter(#db), ), - ) as _i7.MainDB); + ) as _i8.MainDB); @override - _i13.NetworkType get networkType => (super.noSuchMethod( + _i14.NetworkType get networkType => (super.noSuchMethod( Invocation.getter(#networkType), - returnValue: _FakeNetworkType_10( + returnValue: _FakeNetworkType_11( this, Invocation.getter(#networkType), ), - ) as _i13.NetworkType); + ) as _i14.NetworkType); @override - _i23.Future exit() => (super.noSuchMethod( + _i24.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i30.DerivePathType addressType({required String? address}) => + _i31.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i30.DerivePathType.bip44, - ) as _i30.DerivePathType); + returnValue: _i31.DerivePathType.bip44, + ) as _i31.DerivePathType); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -1081,49 +1108,49 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future getTransactionCacheEarly(List? allAddresses) => + _i24.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i24.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future getAllTxsToWatch() => (super.noSuchMethod( + _i24.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, - required _i14.Amount? amount, + required _i15.Amount? amount, Map? args, }) => (super.noSuchMethod( @@ -1137,26 +1164,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -1174,35 +1201,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateSentCachedTxData(Map? txData) => + _i24.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1212,70 +1239,70 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValue: false, ) as bool); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i10.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i24.Future<_i11.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), returnValue: - _i23.Future<_i10.ElectrumXNode>.value(_FakeElectrumXNode_11( + _i24.Future<_i11.ElectrumXNode>.value(_FakeElectrumXNode_12( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i23.Future<_i10.ElectrumXNode>); + ) as _i24.Future<_i11.ElectrumXNode>); @override - _i23.Future>> fastFetch( + _i24.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i23.Future>>.value( + returnValue: _i24.Future>>.value( >[]), - ) as _i23.Future>>); + ) as _i24.Future>>); @override - _i23.Future getTxCount({required String? address}) => + _i24.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future checkCurrentReceivingAddressesForTransactions() => + _i24.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkCurrentChangeAddressesForTransactions() => + _i24.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override int estimateTxFee({ required int? vSize, @@ -1301,7 +1328,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { required bool? isSendAll, int? satsPerVByte, int? additionalOutputs = 0, - List<_i17.UTXO>? utxos, + List<_i18.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -1318,19 +1345,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { }, )); @override - _i23.Future> fetchBuildTxData( - List<_i17.UTXO>? utxosToUse) => + _i24.Future> fetchBuildTxData( + List<_i18.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i23.Future>.value(<_i31.SigningData>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i32.SigningData>[]), + ) as _i24.Future>); @override - _i23.Future> buildTransaction({ - required List<_i31.SigningData>? utxoSigningData, + _i24.Future> buildTransaction({ + required List<_i32.SigningData>? utxoSigningData, required List? recipients, required List? satoshiAmounts, }) => @@ -1345,10 +1372,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1360,12 +1387,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i14.Amount> estimateFeeFor( - _i14.Amount? amount, + _i24.Future<_i15.Amount> estimateFeeFor( + _i15.Amount? amount, int? feeRate, ) => (super.noSuchMethod( @@ -1376,7 +1403,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { feeRate, ], ), - returnValue: _i23.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i24.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -1386,9 +1413,9 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { ], ), )), - ) as _i23.Future<_i14.Amount>); + ) as _i24.Future<_i15.Amount>); @override - _i14.Amount roughFeeEstimate( + _i15.Amount roughFeeEstimate( int? inputCount, int? outputCount, int? feeRatePerKB, @@ -1402,7 +1429,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { feeRatePerKB, ], ), - returnValue: _FakeAmount_12( + returnValue: _FakeAmount_13( this, Invocation.method( #roughFeeEstimate, @@ -1413,34 +1440,34 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { ], ), ), - ) as _i14.Amount); + ) as _i15.Amount); @override - _i23.Future<_i14.Amount> sweepAllEstimate(int? feeRate) => + _i24.Future<_i15.Amount> sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i23.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i24.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #sweepAllEstimate, [feeRate], ), )), - ) as _i23.Future<_i14.Amount>); + ) as _i24.Future<_i15.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override void initCache( String? walletId, - _i22.Coin? coin, + _i23.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1453,14 +1480,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future updateCachedId(String? id) => (super.noSuchMethod( + _i24.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1470,14 +1497,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValue: 0, ) as int); @override - _i23.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i24.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1487,63 +1514,63 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValue: false, ) as bool); @override - _i23.Future updateCachedIsFavorite(bool? isFavorite) => + _i24.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i12.Balance getCachedBalance() => (super.noSuchMethod( + _i13.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( #getCachedBalance, [], ), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.method( #getCachedBalance, [], ), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i23.Future updateCachedBalance(_i12.Balance? balance) => + _i24.Future updateCachedBalance(_i13.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i12.Balance getCachedBalanceSecondary() => (super.noSuchMethod( + _i13.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( #getCachedBalanceSecondary, [], ), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.method( #getCachedBalanceSecondary, [], ), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i23.Future updateCachedBalanceSecondary(_i12.Balance? balance) => + _i24.Future updateCachedBalanceSecondary(_i13.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override List getWalletTokenContractAddresses() => (super.noSuchMethod( Invocation.method( @@ -1553,18 +1580,18 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValue: [], ) as List); @override - _i23.Future updateWalletTokenContractAddresses( + _i24.Future updateWalletTokenContractAddresses( List? contractAddresses) => (super.noSuchMethod( Invocation.method( #updateWalletTokenContractAddresses, [contractAddresses], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void initWalletDB({_i7.MainDB? mockableOverride}) => super.noSuchMethod( + void initWalletDB({_i8.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( #initWalletDB, [], @@ -1573,11 +1600,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>> parseTransaction( + _i24.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>> parseTransaction( Map? txData, dynamic electrumxClient, - List<_i17.Address>? myAddresses, - _i22.Coin? coin, + List<_i18.Address>? myAddresses, + _i23.Coin? coin, int? minConfirms, String? walletId, ) => @@ -1594,8 +1621,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { ], ), returnValue: - _i23.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>.value( - _FakeTuple2_13<_i17.Transaction, _i17.Address>( + _i24.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>>.value( + _FakeTuple2_14<_i18.Transaction, _i18.Address>( this, Invocation.method( #parseTransaction, @@ -1609,37 +1636,37 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { ], ), )), - ) as _i23.Future<_i15.Tuple2<_i17.Transaction, _i17.Address>>); + ) as _i24.Future<_i16.Tuple2<_i18.Transaction, _i18.Address>>); @override void initPaynymWalletInterface({ required String? walletId, required String? walletName, - required _i13.NetworkType? network, - required _i22.Coin? coin, - required _i7.MainDB? db, - required _i10.ElectrumX? electrumXClient, - required _i19.SecureStorageInterface? secureStorage, + required _i14.NetworkType? network, + required _i23.Coin? coin, + required _i8.MainDB? db, + required _i11.ElectrumX? electrumXClient, + required _i20.SecureStorageInterface? secureStorage, required int? dustLimit, required int? dustLimitP2PKH, required int? minConfirms, - required _i23.Future Function()? getMnemonicString, - required _i23.Future Function()? getMnemonicPassphrase, - required _i23.Future Function()? getChainHeight, - required _i23.Future Function()? getCurrentChangeAddress, + required _i24.Future Function()? getMnemonicString, + required _i24.Future Function()? getMnemonicPassphrase, + required _i24.Future Function()? getChainHeight, + required _i24.Future Function()? getCurrentChangeAddress, required int Function({ required int feeRatePerKB, required int vSize, })? estimateTxFee, - required _i23.Future> Function({ + required _i24.Future> Function({ required String address, - required _i14.Amount amount, + required _i15.Amount amount, Map? args, })? prepareSend, - required _i23.Future Function({required String address})? getTxCount, - required _i23.Future> Function(List<_i17.UTXO>)? + required _i24.Future Function({required String address})? getTxCount, + required _i24.Future> Function(List<_i18.UTXO>)? fetchBuildTxData, - required _i23.Future Function()? refresh, - required _i23.Future Function()? checkChangeAddressForTransactions, + required _i24.Future Function()? refresh, + required _i24.Future Function()? checkChangeAddressForTransactions, }) => super.noSuchMethod( Invocation.method( @@ -1672,21 +1699,21 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future<_i16.BIP32> getBip47BaseNode() => (super.noSuchMethod( + _i24.Future<_i17.BIP32> getBip47BaseNode() => (super.noSuchMethod( Invocation.method( #getBip47BaseNode, [], ), - returnValue: _i23.Future<_i16.BIP32>.value(_FakeBIP32_14( + returnValue: _i24.Future<_i17.BIP32>.value(_FakeBIP32_15( this, Invocation.method( #getBip47BaseNode, [], ), )), - ) as _i23.Future<_i16.BIP32>); + ) as _i24.Future<_i17.BIP32>); @override - _i23.Future<_i28.Uint8List> getPrivateKeyForPaynymReceivingAddress({ + _i24.Future<_i29.Uint8List> getPrivateKeyForPaynymReceivingAddress({ required String? paymentCodeString, required int? index, }) => @@ -1699,11 +1726,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { #index: index, }, ), - returnValue: _i23.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), - ) as _i23.Future<_i28.Uint8List>); + returnValue: _i24.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), + ) as _i24.Future<_i29.Uint8List>); @override - _i23.Future<_i17.Address> currentReceivingPaynymAddress({ - required _i18.PaymentCode? sender, + _i24.Future<_i18.Address> currentReceivingPaynymAddress({ + required _i19.PaymentCode? sender, required bool? isSegwit, }) => (super.noSuchMethod( @@ -1715,7 +1742,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i23.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i24.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #currentReceivingPaynymAddress, @@ -1726,10 +1753,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { }, ), )), - ) as _i23.Future<_i17.Address>); + ) as _i24.Future<_i18.Address>); @override - _i23.Future checkCurrentPaynymReceivingAddressForTransactions({ - required _i18.PaymentCode? sender, + _i24.Future checkCurrentPaynymReceivingAddressForTransactions({ + required _i19.PaymentCode? sender, required bool? isSegwit, }) => (super.noSuchMethod( @@ -1741,42 +1768,42 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { #isSegwit: isSegwit, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => + _i24.Future checkAllCurrentReceivingPaynymAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkAllCurrentReceivingPaynymAddressesForTransactions, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i16.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( + _i24.Future<_i17.BIP32> deriveNotificationBip32Node() => (super.noSuchMethod( Invocation.method( #deriveNotificationBip32Node, [], ), - returnValue: _i23.Future<_i16.BIP32>.value(_FakeBIP32_14( + returnValue: _i24.Future<_i17.BIP32>.value(_FakeBIP32_15( this, Invocation.method( #deriveNotificationBip32Node, [], ), )), - ) as _i23.Future<_i16.BIP32>); + ) as _i24.Future<_i17.BIP32>); @override - _i23.Future<_i18.PaymentCode> getPaymentCode({required bool? isSegwit}) => + _i24.Future<_i19.PaymentCode> getPaymentCode({required bool? isSegwit}) => (super.noSuchMethod( Invocation.method( #getPaymentCode, [], {#isSegwit: isSegwit}, ), - returnValue: _i23.Future<_i18.PaymentCode>.value(_FakePaymentCode_16( + returnValue: _i24.Future<_i19.PaymentCode>.value(_FakePaymentCode_17( this, Invocation.method( #getPaymentCode, @@ -1784,30 +1811,30 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { {#isSegwit: isSegwit}, ), )), - ) as _i23.Future<_i18.PaymentCode>); + ) as _i24.Future<_i19.PaymentCode>); @override - _i23.Future<_i28.Uint8List> signWithNotificationKey(_i28.Uint8List? data) => + _i24.Future<_i29.Uint8List> signWithNotificationKey(_i29.Uint8List? data) => (super.noSuchMethod( Invocation.method( #signWithNotificationKey, [data], ), - returnValue: _i23.Future<_i28.Uint8List>.value(_i28.Uint8List(0)), - ) as _i23.Future<_i28.Uint8List>); + returnValue: _i24.Future<_i29.Uint8List>.value(_i29.Uint8List(0)), + ) as _i24.Future<_i29.Uint8List>); @override - _i23.Future signStringWithNotificationKey(String? data) => + _i24.Future signStringWithNotificationKey(String? data) => (super.noSuchMethod( Invocation.method( #signStringWithNotificationKey, [data], ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future> preparePaymentCodeSend({ - required _i18.PaymentCode? paymentCode, + _i24.Future> preparePaymentCodeSend({ + required _i19.PaymentCode? paymentCode, required bool? isSegwit, - required _i14.Amount? amount, + required _i15.Amount? amount, Map? args, }) => (super.noSuchMethod( @@ -1822,13 +1849,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future<_i17.Address> nextUnusedSendAddressFrom({ - required _i18.PaymentCode? pCode, + _i24.Future<_i18.Address> nextUnusedSendAddressFrom({ + required _i19.PaymentCode? pCode, required bool? isSegwit, - required _i16.BIP32? privateKeyNode, + required _i17.BIP32? privateKeyNode, int? startIndex = 0, }) => (super.noSuchMethod( @@ -1842,7 +1869,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { #startIndex: startIndex, }, ), - returnValue: _i23.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i24.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #nextUnusedSendAddressFrom, @@ -1855,13 +1882,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { }, ), )), - ) as _i23.Future<_i17.Address>); + ) as _i24.Future<_i18.Address>); @override - _i23.Future> prepareNotificationTx({ + _i24.Future> prepareNotificationTx({ required int? selectedTxFeeRate, required String? targetPaymentCodeString, int? additionalOutputs = 0, - List<_i17.UTXO>? utxos, + List<_i18.UTXO>? utxos, }) => (super.noSuchMethod( Invocation.method( @@ -1875,10 +1902,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future broadcastNotificationTx( + _i24.Future broadcastNotificationTx( {required Map? preparedTx}) => (super.noSuchMethod( Invocation.method( @@ -1886,62 +1913,62 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { [], {#preparedTx: preparedTx}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future hasConnected(String? paymentCodeString) => + _i24.Future hasConnected(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #hasConnected, [paymentCodeString], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransaction( - {required _i17.Transaction? transaction}) => + _i24.Future<_i19.PaymentCode?> unBlindedPaymentCodeFromTransaction( + {required _i18.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( #unBlindedPaymentCodeFromTransaction, [], {#transaction: transaction}, ), - returnValue: _i23.Future<_i18.PaymentCode?>.value(), - ) as _i23.Future<_i18.PaymentCode?>); + returnValue: _i24.Future<_i19.PaymentCode?>.value(), + ) as _i24.Future<_i19.PaymentCode?>); @override - _i23.Future<_i18.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( - {required _i17.Transaction? transaction}) => + _i24.Future<_i19.PaymentCode?> unBlindedPaymentCodeFromTransactionBad( + {required _i18.Transaction? transaction}) => (super.noSuchMethod( Invocation.method( #unBlindedPaymentCodeFromTransactionBad, [], {#transaction: transaction}, ), - returnValue: _i23.Future<_i18.PaymentCode?>.value(), - ) as _i23.Future<_i18.PaymentCode?>); + returnValue: _i24.Future<_i19.PaymentCode?>.value(), + ) as _i24.Future<_i19.PaymentCode?>); @override - _i23.Future> + _i24.Future> getAllPaymentCodesFromNotificationTransactions() => (super.noSuchMethod( Invocation.method( #getAllPaymentCodesFromNotificationTransactions, [], ), returnValue: - _i23.Future>.value(<_i18.PaymentCode>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i19.PaymentCode>[]), + ) as _i24.Future>); @override - _i23.Future checkForNotificationTransactionsTo( + _i24.Future checkForNotificationTransactionsTo( Set? otherCodeStrings) => (super.noSuchMethod( Invocation.method( #checkForNotificationTransactionsTo, [otherCodeStrings], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future restoreAllHistory({ + _i24.Future restoreAllHistory({ required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, required Set? paymentCodeStrings, @@ -1956,12 +1983,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { #paymentCodeStrings: paymentCodeStrings, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future restoreHistoryWith({ - required _i18.PaymentCode? other, + _i24.Future restoreHistoryWith({ + required _i19.PaymentCode? other, required bool? checkSegwitAsWell, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -1977,58 +2004,58 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { #maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i17.Address> getMyNotificationAddress() => (super.noSuchMethod( + _i24.Future<_i18.Address> getMyNotificationAddress() => (super.noSuchMethod( Invocation.method( #getMyNotificationAddress, [], ), - returnValue: _i23.Future<_i17.Address>.value(_FakeAddress_15( + returnValue: _i24.Future<_i18.Address>.value(_FakeAddress_16( this, Invocation.method( #getMyNotificationAddress, [], ), )), - ) as _i23.Future<_i17.Address>); + ) as _i24.Future<_i18.Address>); @override - _i23.Future> lookupKey(String? paymentCodeString) => + _i24.Future> lookupKey(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #lookupKey, [paymentCodeString], ), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future paymentCodeStringByKey(String? key) => + _i24.Future paymentCodeStringByKey(String? key) => (super.noSuchMethod( Invocation.method( #paymentCodeStringByKey, [key], ), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future storeCode(String? paymentCodeString) => + _i24.Future storeCode(String? paymentCodeString) => (super.noSuchMethod( Invocation.method( #storeCode, [paymentCodeString], ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override void initCoinControlInterface({ required String? walletId, required String? walletName, - required _i22.Coin? coin, - required _i7.MainDB? db, - required _i23.Future Function()? getChainHeight, - required _i23.Future Function(_i12.Balance)? refreshedBalanceCallback, + required _i23.Coin? coin, + required _i8.MainDB? db, + required _i24.Future Function()? getChainHeight, + required _i24.Future Function(_i13.Balance)? refreshedBalanceCallback, }) => super.noSuchMethod( Invocation.method( @@ -2046,16 +2073,16 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i23.Future refreshBalance({bool? notify = false}) => + _i24.Future refreshBalance({bool? notify = false}) => (super.noSuchMethod( Invocation.method( #refreshBalance, [], {#notify: notify}, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); } /// A class which mocks [NodeService]. @@ -2063,41 +2090,41 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet { /// See the documentation for Mockito's code generation for more information. class MockNodeService extends _i1.Mock implements _i3.NodeService { @override - _i19.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( + _i20.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( Invocation.getter(#secureStorageInterface), - returnValue: _FakeSecureStorageInterface_17( + returnValue: _FakeSecureStorageInterface_18( this, Invocation.getter(#secureStorageInterface), ), - ) as _i19.SecureStorageInterface); + ) as _i20.SecureStorageInterface); @override - List<_i32.NodeModel> get primaryNodes => (super.noSuchMethod( + List<_i33.NodeModel> get primaryNodes => (super.noSuchMethod( Invocation.getter(#primaryNodes), - returnValue: <_i32.NodeModel>[], - ) as List<_i32.NodeModel>); + returnValue: <_i33.NodeModel>[], + ) as List<_i33.NodeModel>); @override - List<_i32.NodeModel> get nodes => (super.noSuchMethod( + List<_i33.NodeModel> get nodes => (super.noSuchMethod( Invocation.getter(#nodes), - returnValue: <_i32.NodeModel>[], - ) as List<_i32.NodeModel>); + returnValue: <_i33.NodeModel>[], + ) as List<_i33.NodeModel>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future updateDefaults() => (super.noSuchMethod( + _i24.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future setPrimaryNodeFor({ - required _i22.Coin? coin, - required _i32.NodeModel? node, + _i24.Future setPrimaryNodeFor({ + required _i23.Coin? coin, + required _i33.NodeModel? node, bool? shouldNotifyListeners = false, }) => (super.noSuchMethod( @@ -2110,44 +2137,44 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i32.NodeModel? getPrimaryNodeFor({required _i22.Coin? coin}) => + _i33.NodeModel? getPrimaryNodeFor({required _i23.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getPrimaryNodeFor, [], {#coin: coin}, - )) as _i32.NodeModel?); + )) as _i33.NodeModel?); @override - List<_i32.NodeModel> getNodesFor(_i22.Coin? coin) => (super.noSuchMethod( + List<_i33.NodeModel> getNodesFor(_i23.Coin? coin) => (super.noSuchMethod( Invocation.method( #getNodesFor, [coin], ), - returnValue: <_i32.NodeModel>[], - ) as List<_i32.NodeModel>); + returnValue: <_i33.NodeModel>[], + ) as List<_i33.NodeModel>); @override - _i32.NodeModel? getNodeById({required String? id}) => + _i33.NodeModel? getNodeById({required String? id}) => (super.noSuchMethod(Invocation.method( #getNodeById, [], {#id: id}, - )) as _i32.NodeModel?); + )) as _i33.NodeModel?); @override - List<_i32.NodeModel> failoverNodesFor({required _i22.Coin? coin}) => + List<_i33.NodeModel> failoverNodesFor({required _i23.Coin? coin}) => (super.noSuchMethod( Invocation.method( #failoverNodesFor, [], {#coin: coin}, ), - returnValue: <_i32.NodeModel>[], - ) as List<_i32.NodeModel>); + returnValue: <_i33.NodeModel>[], + ) as List<_i33.NodeModel>); @override - _i23.Future add( - _i32.NodeModel? node, + _i24.Future add( + _i33.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => @@ -2160,11 +2187,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future delete( + _i24.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -2176,11 +2203,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future setEnabledState( + _i24.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -2194,12 +2221,12 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future edit( - _i32.NodeModel? editedNode, + _i24.Future edit( + _i33.NodeModel? editedNode, String? password, bool? shouldNotifyListeners, ) => @@ -2212,20 +2239,20 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateCommunityNodes() => (super.noSuchMethod( + _i24.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2233,7 +2260,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2276,23 +2303,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i20.CoinServiceAPI get wallet => (super.noSuchMethod( + _i21.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_18( + returnValue: _FakeCoinServiceAPI_19( this, Invocation.getter(#wallet), ), - ) as _i20.CoinServiceAPI); + ) as _i21.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -2325,42 +2352,42 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i23.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i10.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i24.Future<_i10.FeeObject>.value(_FakeFeeObject_7( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i9.FeeObject>); + ) as _i24.Future<_i10.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i12.Balance get balance => (super.noSuchMethod( + _i13.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.getter(#balance), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i17.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i18.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i17.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i18.UTXO>[]), + ) as _i24.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2380,15 +2407,15 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -2435,24 +2462,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i23.Future get xpub => (super.noSuchMethod( + _i24.Future get xpub => (super.noSuchMethod( Invocation.getter(#xpub), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -2462,9 +2489,9 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, - required _i14.Amount? amount, + required _i15.Amount? amount, Map? args, }) => (super.noSuchMethod( @@ -2478,27 +2505,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2508,35 +2535,35 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -2555,20 +2582,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future exitCurrentWallet() => (super.noSuchMethod( + _i24.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2580,12 +2607,12 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i14.Amount> estimateFeeFor( - _i14.Amount? amount, + _i24.Future<_i15.Amount> estimateFeeFor( + _i15.Amount? amount, int? feeRate, ) => (super.noSuchMethod( @@ -2596,7 +2623,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i23.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i24.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -2606,26 +2633,26 @@ class MockManager extends _i1.Mock implements _i6.Manager { ], ), )), - ) as _i23.Future<_i14.Amount>); + ) as _i24.Future<_i15.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future resetRescanOnOpen() => (super.noSuchMethod( + _i24.Future resetRescanOnOpen() => (super.noSuchMethod( Invocation.method( #resetRescanOnOpen, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2633,7 +2660,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i26.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2653,7 +2680,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { /// A class which mocks [CoinServiceAPI]. /// /// See the documentation for Mockito's code generation for more information. -class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i21.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -2664,10 +2691,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i22.Coin get coin => (super.noSuchMethod( + _i23.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i22.Coin.bitcoin, - ) as _i22.Coin); + returnValue: _i23.Coin.bitcoin, + ) as _i23.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -2700,42 +2727,42 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i23.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i24.Future<_i10.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i23.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i24.Future<_i10.FeeObject>.value(_FakeFeeObject_7( this, Invocation.getter(#fees), )), - ) as _i23.Future<_i9.FeeObject>); + ) as _i24.Future<_i10.FeeObject>); @override - _i23.Future get maxFee => (super.noSuchMethod( + _i24.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i23.Future.value(0), - ) as _i23.Future); + returnValue: _i24.Future.value(0), + ) as _i24.Future); @override - _i23.Future get currentReceivingAddress => (super.noSuchMethod( + _i24.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i12.Balance get balance => (super.noSuchMethod( + _i13.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), - returnValue: _FakeBalance_9( + returnValue: _FakeBalance_10( this, Invocation.getter(#balance), ), - ) as _i12.Balance); + ) as _i13.Balance); @override - _i23.Future> get transactions => (super.noSuchMethod( + _i24.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i23.Future>.value(<_i17.Transaction>[]), - ) as _i23.Future>); + _i24.Future>.value(<_i18.Transaction>[]), + ) as _i24.Future>); @override - _i23.Future> get utxos => (super.noSuchMethod( + _i24.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i23.Future>.value(<_i17.UTXO>[]), - ) as _i23.Future>); + returnValue: _i24.Future>.value(<_i18.UTXO>[]), + ) as _i24.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2755,20 +2782,20 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: '', ) as String); @override - _i23.Future> get mnemonic => (super.noSuchMethod( + _i24.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i23.Future>.value([]), - ) as _i23.Future>); + returnValue: _i24.Future>.value([]), + ) as _i24.Future>); @override - _i23.Future get mnemonicString => (super.noSuchMethod( + _i24.Future get mnemonicString => (super.noSuchMethod( Invocation.getter(#mnemonicString), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future get mnemonicPassphrase => (super.noSuchMethod( + _i24.Future get mnemonicPassphrase => (super.noSuchMethod( Invocation.getter(#mnemonicPassphrase), - returnValue: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + ) as _i24.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -2785,9 +2812,9 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: 0, ) as int); @override - _i23.Future> prepareSend({ + _i24.Future> prepareSend({ required String? address, - required _i14.Amount? amount, + required _i15.Amount? amount, Map? args, }) => (super.noSuchMethod( @@ -2801,36 +2828,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { }, ), returnValue: - _i23.Future>.value({}), - ) as _i23.Future>); + _i24.Future>.value({}), + ) as _i24.Future>); @override - _i23.Future confirmSend({required Map? txData}) => + _i24.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i23.Future.value(''), - ) as _i23.Future); + returnValue: _i24.Future.value(''), + ) as _i24.Future); @override - _i23.Future refresh() => (super.noSuchMethod( + _i24.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i24.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2840,15 +2867,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { returnValue: false, ) as bool); @override - _i23.Future testNetworkConnection() => (super.noSuchMethod( + _i24.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future recoverFromMnemonic({ + _i24.Future recoverFromMnemonic({ required String? mnemonic, String? mnemonicPassphrase, required int? maxUnusedAddressGap, @@ -2867,40 +2894,40 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { #height: height, }, ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeNew( + _i24.Future initializeNew( ({String mnemonicPassphrase, int wordCount})? data) => (super.noSuchMethod( Invocation.method( #initializeNew, [data], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future initializeExisting() => (super.noSuchMethod( + _i24.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future exit() => (super.noSuchMethod( + _i24.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future fullRescan( + _i24.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2912,12 +2939,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); @override - _i23.Future<_i14.Amount> estimateFeeFor( - _i14.Amount? amount, + _i24.Future<_i15.Amount> estimateFeeFor( + _i15.Amount? amount, int? feeRate, ) => (super.noSuchMethod( @@ -2928,7 +2955,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { feeRate, ], ), - returnValue: _i23.Future<_i14.Amount>.value(_FakeAmount_12( + returnValue: _i24.Future<_i15.Amount>.value(_FakeAmount_13( this, Invocation.method( #estimateFeeFor, @@ -2938,23 +2965,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI { ], ), )), - ) as _i23.Future<_i14.Amount>); + ) as _i24.Future<_i15.Amount>); @override - _i23.Future generateNewAddress() => (super.noSuchMethod( + _i24.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i23.Future.value(false), - ) as _i23.Future); + returnValue: _i24.Future.value(false), + ) as _i24.Future); @override - _i23.Future updateSentCachedTxData(Map? txData) => + _i24.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i23.Future.value(), - returnValueForMissingStub: _i23.Future.value(), - ) as _i23.Future); + returnValue: _i24.Future.value(), + returnValueForMissingStub: _i24.Future.value(), + ) as _i24.Future); } From 7370ef1148f55a4cd6555c36982bdf57a5335818 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 13 Sep 2023 11:02:17 -0600 Subject: [PATCH 235/237] update tor ref --- crypto_plugins/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_plugins/tor b/crypto_plugins/tor index 082e363e6..a819223b2 160000 --- a/crypto_plugins/tor +++ b/crypto_plugins/tor @@ -1 +1 @@ -Subproject commit 082e363e6a3dc952ea499da0b51f1ab48c604157 +Subproject commit a819223b23e9fa1d76bde82ed9109651e96f2ad3 From 88f805230c588e9ac2f40814c8c2979056445bac Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 13 Sep 2023 16:49:04 -0500 Subject: [PATCH 236/237] fix paynym headers bug --- lib/networking/http.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/networking/http.dart b/lib/networking/http.dart index e6b3b22c5..ad15b659c 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -42,7 +42,7 @@ class HTTP { ); if (headers != null) { - headers.forEach((key, value) => request.headers.add); + headers.forEach((key, value) => request.headers.add(key, value)); } final response = await request.close(); @@ -87,7 +87,7 @@ class HTTP { ); if (headers != null) { - headers.forEach((key, value) => request.headers.add); + headers.forEach((key, value) => request.headers.add(key, value)); } request.write(body); From 5ac7ae95cb473349f75946190686319517c196d1 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 13 Sep 2023 16:49:37 -0500 Subject: [PATCH 237/237] formatting --- lib/utilities/paynym_is_api.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/utilities/paynym_is_api.dart b/lib/utilities/paynym_is_api.dart index 629a88f7e..860848cac 100644 --- a/lib/utilities/paynym_is_api.dart +++ b/lib/utilities/paynym_is_api.dart @@ -45,7 +45,8 @@ class PaynymIsApi { final headers = { 'Content-Type': 'application/json; charset=UTF-8', - 'Content-Length': contentLength.toString(), // Set the Content-Length header. + 'content-length': + contentLength.toString(), // Set the Content-Length header. }..addAll(additionalHeaders); final response = await client.post( url: uri,