From 6baa0afff730f05412c553c96d6dfecc7cf82cc4 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 10 Jan 2023 10:05:22 -0600 Subject: [PATCH 01/55] update dogecoin test --- test/services/coins/dogecoin/dogecoin_wallet_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.dart index e04eb5cdd..ac863bd2a 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.dart @@ -28,7 +28,7 @@ import 'dogecoin_wallet_test_parameters.dart'; void main() { group("dogecoin constants", () { test("dogecoin minimum confirmations", () async { - expect(MINIMUM_CONFIRMATIONS, 3); + expect(MINIMUM_CONFIRMATIONS, 1); }); test("dogecoin dust limit", () async { expect(DUST_LIMIT, 1000000); From 5c66b0380b4564b4773c70e6ab94e49850aad318 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 20 Jan 2023 12:16:27 -0600 Subject: [PATCH 02/55] move standard electrum x transaction parsing function into a mixin --- .../coins/bitcoin/bitcoin_wallet.dart | 5 +- lib/services/coins/coin_paynym_extension.dart | 195 ----------------- .../coins/dogecoin/dogecoin_wallet.dart | 5 +- .../coins/litecoin/litecoin_wallet.dart | 5 +- .../coins/namecoin/namecoin_wallet.dart | 5 +- lib/services/mixins/electrum_x_parsing.dart | 202 ++++++++++++++++++ 6 files changed, 214 insertions(+), 203 deletions(-) create mode 100644 lib/services/mixins/electrum_x_parsing.dart diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart index b3ea2485f..4afec573b 100644 --- a/lib/services/coins/bitcoin/bitcoin_wallet.dart +++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart @@ -16,13 +16,13 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models; import 'package:stackwallet/models/paymint/fee_object_model.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.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/refresh_percent_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/electrum_x_parsing.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; @@ -138,7 +138,8 @@ bip32.BIP32 getBip32RootWrapper(Tuple2 args) { return getBip32Root(args.item1, args.item2); } -class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB { +class BitcoinWallet extends CoinServiceAPI + with WalletCache, WalletDB, ElectrumXParsing { static const integrationTestFlag = bool.fromEnvironment("IS_INTEGRATION_TEST"); diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index a5e8a07d5..7cebca9ca 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -6,14 +6,12 @@ import 'package:bip47/src/util.dart'; import 'package:bitcoindart/bitcoindart.dart' as btc_dart; import 'package:bitcoindart/src/utils/constants/op.dart' as op; import 'package:bitcoindart/src/utils/script.dart' as bscript; -import 'package:decimal/decimal.dart'; import 'package:isar/isar.dart'; import 'package:pointycastle/digests/sha256.dart'; import 'package:stackwallet/hive/db.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/utilities/address_utils.dart'; -import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:tuple/tuple.dart'; @@ -561,196 +559,3 @@ extension PayNym on DogecoinWallet { ); } } - -Future, List, Address>> - parseTransaction( - Map txData, - dynamic electrumxClient, - List
myAddresses, - Coin coin, - int minConfirms, - String walletId, -) async { - Set receivingAddresses = myAddresses - .where((e) => e.subType == AddressSubType.receiving) - .map((e) => e.value) - .toSet(); - Set changeAddresses = myAddresses - .where((e) => e.subType == AddressSubType.change) - .map((e) => e.value) - .toSet(); - - Set inputAddresses = {}; - Set outputAddresses = {}; - - int totalInputValue = 0; - int totalOutputValue = 0; - - int amountSentFromWallet = 0; - int amountReceivedInWallet = 0; - int changeAmount = 0; - - // parse inputs - for (final input in txData["vin"] as List) { - final prevTxid = input["txid"] as String; - final prevOut = input["vout"] as int; - - // fetch input tx to get address - final inputTx = await electrumxClient.getTransaction( - txHash: prevTxid, - coin: coin, - ); - - for (final output in inputTx["vout"] as List) { - // check matching output - if (prevOut == output["n"]) { - // get value - final value = Format.decimalAmountToSatoshis( - Decimal.parse(output["value"].toString()), - coin, - ); - - // add value to total - totalInputValue += value; - - // get input(prevOut) address - final address = output["scriptPubKey"]?["addresses"]?[0] as String? ?? - output["scriptPubKey"]?["address"] as String?; - - if (address != null) { - inputAddresses.add(address); - - // if input was from my wallet, add value to amount sent - if (receivingAddresses.contains(address) || - changeAddresses.contains(address)) { - amountSentFromWallet += value; - } - } - } - } - } - - // parse outputs - for (final output in txData["vout"] as List) { - // get value - final value = Format.decimalAmountToSatoshis( - Decimal.parse(output["value"].toString()), - coin, - ); - - // add value to total - totalOutputValue += value; - - // get output address - final address = output["scriptPubKey"]?["addresses"]?[0] as String? ?? - output["scriptPubKey"]?["address"] as String?; - if (address != null) { - outputAddresses.add(address); - - // if output was to my wallet, add value to amount received - if (receivingAddresses.contains(address)) { - amountReceivedInWallet += value; - } else if (changeAddresses.contains(address)) { - changeAmount += value; - } - } - } - - final mySentFromAddresses = [ - ...receivingAddresses.intersection(inputAddresses), - ...changeAddresses.intersection(inputAddresses) - ]; - final myReceivedOnAddresses = - receivingAddresses.intersection(outputAddresses); - final myChangeReceivedOnAddresses = - changeAddresses.intersection(outputAddresses); - - final fee = totalInputValue - totalOutputValue; - - // this is the address initially used to fetch the txid - Address transactionAddress = txData["address"] as Address; - - TransactionType type; - int amount; - if (mySentFromAddresses.isNotEmpty && myReceivedOnAddresses.isNotEmpty) { - // tx is sent to self - type = TransactionType.sentToSelf; - - // should be 0 - amount = amountSentFromWallet - amountReceivedInWallet - fee - changeAmount; - } else if (mySentFromAddresses.isNotEmpty) { - // outgoing tx - type = TransactionType.outgoing; - amount = amountSentFromWallet - changeAmount - fee; - - final possible = - outputAddresses.difference(myChangeReceivedOnAddresses).first; - - if (transactionAddress.value != possible) { - transactionAddress = Address( - walletId: walletId, - value: possible, - derivationIndex: -1, - subType: AddressSubType.nonWallet, - type: AddressType.nonWallet, - publicKey: [], - ); - } - } else { - // incoming tx - type = TransactionType.incoming; - amount = amountReceivedInWallet; - } - - final tx = Transaction( - walletId: walletId, - txid: txData["txid"] as String, - timestamp: txData["blocktime"] as int? ?? - (DateTime.now().millisecondsSinceEpoch ~/ 1000), - type: type, - subType: TransactionSubType.none, - amount: amount, - fee: fee, - height: txData["height"] as int?, - isCancelled: false, - isLelantus: false, - slateId: null, - otherData: null, - ); - - List outs = []; - List ins = []; - - for (final json in txData["vin"] as List) { - bool isCoinBase = json['coinbase'] != null; - final input = Input( - walletId: walletId, - txid: json['txid'] as String, - vout: json['vout'] as int? ?? -1, - scriptSig: json['scriptSig']?['hex'] as String?, - scriptSigAsm: json['scriptSig']?['asm'] as String?, - isCoinbase: isCoinBase ? isCoinBase : json['is_coinbase'] as bool?, - sequence: json['sequence'] as int?, - innerRedeemScriptAsm: json['innerRedeemscriptAsm'] as String?, - ); - ins.add(input); - } - - for (final json in txData["vout"] as List) { - final output = Output( - walletId: walletId, - scriptPubKey: json['scriptPubKey']?['hex'] as String?, - scriptPubKeyAsm: json['scriptPubKey']?['asm'] as String?, - scriptPubKeyType: json['scriptPubKey']?['type'] as String?, - scriptPubKeyAddress: json["scriptPubKey"]?["addresses"]?[0] as String? ?? - json['scriptPubKey']['type'] as String, - value: Format.decimalAmountToSatoshis( - Decimal.parse(json["value"].toString()), - coin, - ), - ); - outs.add(output); - } - - return Tuple4(tx, outs, ins, transactionAddress); -} diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 9fc5d2f04..c878101b6 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -17,13 +17,13 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models; import 'package:stackwallet/models/paymint/fee_object_model.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.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/refresh_percent_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/electrum_x_parsing.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; @@ -125,7 +125,8 @@ bip32.BIP32 getBip32RootWrapper(Tuple2 args) { return getBip32Root(args.item1, args.item2); } -class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB { +class DogecoinWallet extends CoinServiceAPI + with WalletCache, WalletDB, ElectrumXParsing { static const integrationTestFlag = bool.fromEnvironment("IS_INTEGRATION_TEST"); final _prefs = Prefs.instance; diff --git a/lib/services/coins/litecoin/litecoin_wallet.dart b/lib/services/coins/litecoin/litecoin_wallet.dart index 25e963b4b..44383443f 100644 --- a/lib/services/coins/litecoin/litecoin_wallet.dart +++ b/lib/services/coins/litecoin/litecoin_wallet.dart @@ -17,13 +17,13 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models; import 'package:stackwallet/models/paymint/fee_object_model.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.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/refresh_percent_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/electrum_x_parsing.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; @@ -138,7 +138,8 @@ bip32.BIP32 getBip32RootWrapper(Tuple2 args) { return getBip32Root(args.item1, args.item2); } -class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB { +class LitecoinWallet extends CoinServiceAPI + with WalletCache, WalletDB, ElectrumXParsing { static const integrationTestFlag = bool.fromEnvironment("IS_INTEGRATION_TEST"); diff --git a/lib/services/coins/namecoin/namecoin_wallet.dart b/lib/services/coins/namecoin/namecoin_wallet.dart index 34728bcc3..8af9d8a59 100644 --- a/lib/services/coins/namecoin/namecoin_wallet.dart +++ b/lib/services/coins/namecoin/namecoin_wallet.dart @@ -17,13 +17,13 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models; import 'package:stackwallet/models/paymint/fee_object_model.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.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/refresh_percent_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/electrum_x_parsing.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; @@ -135,7 +135,8 @@ bip32.BIP32 getBip32RootWrapper(Tuple2 args) { return getBip32Root(args.item1, args.item2); } -class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB { +class NamecoinWallet extends CoinServiceAPI + with WalletCache, WalletDB, ElectrumXParsing { static const integrationTestFlag = bool.fromEnvironment("IS_INTEGRATION_TEST"); diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart new file mode 100644 index 000000000..9a2c950d6 --- /dev/null +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -0,0 +1,202 @@ +import 'package:decimal/decimal.dart'; +import 'package:stackwallet/models/isar/models/isar_models.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/format.dart'; +import 'package:tuple/tuple.dart'; + +mixin ElectrumXParsing { + Future, List, Address>> + parseTransaction( + Map txData, + dynamic electrumxClient, + List
myAddresses, + Coin coin, + int minConfirms, + String walletId, + ) async { + Set receivingAddresses = myAddresses + .where((e) => e.subType == AddressSubType.receiving) + .map((e) => e.value) + .toSet(); + Set changeAddresses = myAddresses + .where((e) => e.subType == AddressSubType.change) + .map((e) => e.value) + .toSet(); + + Set inputAddresses = {}; + Set outputAddresses = {}; + + int totalInputValue = 0; + int totalOutputValue = 0; + + int amountSentFromWallet = 0; + int amountReceivedInWallet = 0; + int changeAmount = 0; + + // parse inputs + for (final input in txData["vin"] as List) { + final prevTxid = input["txid"] as String; + final prevOut = input["vout"] as int; + + // fetch input tx to get address + final inputTx = await electrumxClient.getTransaction( + txHash: prevTxid, + coin: coin, + ); + + for (final output in inputTx["vout"] as List) { + // check matching output + if (prevOut == output["n"]) { + // get value + final value = Format.decimalAmountToSatoshis( + Decimal.parse(output["value"].toString()), + coin, + ); + + // add value to total + totalInputValue += value; + + // get input(prevOut) address + final address = output["scriptPubKey"]?["addresses"]?[0] as String? ?? + output["scriptPubKey"]?["address"] as String?; + + if (address != null) { + inputAddresses.add(address); + + // if input was from my wallet, add value to amount sent + if (receivingAddresses.contains(address) || + changeAddresses.contains(address)) { + amountSentFromWallet += value; + } + } + } + } + } + + // parse outputs + for (final output in txData["vout"] as List) { + // get value + final value = Format.decimalAmountToSatoshis( + Decimal.parse(output["value"].toString()), + coin, + ); + + // add value to total + totalOutputValue += value; + + // get output address + final address = output["scriptPubKey"]?["addresses"]?[0] as String? ?? + output["scriptPubKey"]?["address"] as String?; + if (address != null) { + outputAddresses.add(address); + + // if output was to my wallet, add value to amount received + if (receivingAddresses.contains(address)) { + amountReceivedInWallet += value; + } else if (changeAddresses.contains(address)) { + changeAmount += value; + } + } + } + + final mySentFromAddresses = [ + ...receivingAddresses.intersection(inputAddresses), + ...changeAddresses.intersection(inputAddresses) + ]; + final myReceivedOnAddresses = + receivingAddresses.intersection(outputAddresses); + final myChangeReceivedOnAddresses = + changeAddresses.intersection(outputAddresses); + + final fee = totalInputValue - totalOutputValue; + + // this is the address initially used to fetch the txid + Address transactionAddress = txData["address"] as Address; + + TransactionType type; + int amount; + if (mySentFromAddresses.isNotEmpty && myReceivedOnAddresses.isNotEmpty) { + // tx is sent to self + type = TransactionType.sentToSelf; + + // should be 0 + amount = + amountSentFromWallet - amountReceivedInWallet - fee - changeAmount; + } else if (mySentFromAddresses.isNotEmpty) { + // outgoing tx + type = TransactionType.outgoing; + amount = amountSentFromWallet - changeAmount - fee; + + final possible = + outputAddresses.difference(myChangeReceivedOnAddresses).first; + + if (transactionAddress.value != possible) { + transactionAddress = Address( + walletId: walletId, + value: possible, + derivationIndex: -1, + subType: AddressSubType.nonWallet, + type: AddressType.nonWallet, + publicKey: [], + ); + } + } else { + // incoming tx + type = TransactionType.incoming; + amount = amountReceivedInWallet; + } + + final tx = Transaction( + walletId: walletId, + txid: txData["txid"] as String, + timestamp: txData["blocktime"] as int? ?? + (DateTime.now().millisecondsSinceEpoch ~/ 1000), + type: type, + subType: TransactionSubType.none, + amount: amount, + fee: fee, + height: txData["height"] as int?, + isCancelled: false, + isLelantus: false, + slateId: null, + otherData: null, + ); + + List outs = []; + List ins = []; + + for (final json in txData["vin"] as List) { + bool isCoinBase = json['coinbase'] != null; + final input = Input( + walletId: walletId, + txid: json['txid'] as String, + vout: json['vout'] as int? ?? -1, + scriptSig: json['scriptSig']?['hex'] as String?, + scriptSigAsm: json['scriptSig']?['asm'] as String?, + isCoinbase: isCoinBase ? isCoinBase : json['is_coinbase'] as bool?, + sequence: json['sequence'] as int?, + innerRedeemScriptAsm: json['innerRedeemscriptAsm'] as String?, + ); + ins.add(input); + } + + for (final json in txData["vout"] as List) { + final output = Output( + walletId: walletId, + scriptPubKey: json['scriptPubKey']?['hex'] as String?, + scriptPubKeyAsm: json['scriptPubKey']?['asm'] as String?, + scriptPubKeyType: json['scriptPubKey']?['type'] as String?, + scriptPubKeyAddress: + json["scriptPubKey"]?["addresses"]?[0] as String? ?? + json['scriptPubKey']['type'] as String, + value: Format.decimalAmountToSatoshis( + Decimal.parse(json["value"].toString()), + coin, + ), + ); + outs.add(output); + } + + return Tuple4(tx, outs, ins, transactionAddress); + } +} From c1182f61bc3c37a00b4b0998ead7682fbc957766 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 20 Jan 2023 12:25:32 -0600 Subject: [PATCH 03/55] start centralizing custom exceptions --- lib/exceptions/address/address_exception.dart | 5 +++++ lib/exceptions/sw_exception.dart | 11 +++++++++++ .../insufficient_balance_exception.dart | 5 +++++ .../wallet/paynym_send_exception.dart | 5 +++++ lib/models/isar/models/address/address.dart | 6 +----- .../paynym/dialogs/paynym_details_popup.dart | 1 + .../subwidgets/desktop_paynym_details.dart | 1 + lib/services/coins/coin_paynym_extension.dart | 19 ++----------------- 8 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 lib/exceptions/address/address_exception.dart create mode 100644 lib/exceptions/sw_exception.dart create mode 100644 lib/exceptions/wallet/insufficient_balance_exception.dart create mode 100644 lib/exceptions/wallet/paynym_send_exception.dart diff --git a/lib/exceptions/address/address_exception.dart b/lib/exceptions/address/address_exception.dart new file mode 100644 index 000000000..3331bef99 --- /dev/null +++ b/lib/exceptions/address/address_exception.dart @@ -0,0 +1,5 @@ +import 'package:stackwallet/exceptions/sw_exception.dart'; + +class AddressException extends SWException { + AddressException(super.message); +} diff --git a/lib/exceptions/sw_exception.dart b/lib/exceptions/sw_exception.dart new file mode 100644 index 000000000..34ab664f2 --- /dev/null +++ b/lib/exceptions/sw_exception.dart @@ -0,0 +1,11 @@ +// generic stack wallet exception which all other custom exceptions should +// extend from + +class SWException with Exception { + SWException(this.message); + + final String message; + + @override + toString() => message; +} diff --git a/lib/exceptions/wallet/insufficient_balance_exception.dart b/lib/exceptions/wallet/insufficient_balance_exception.dart new file mode 100644 index 000000000..219ef6a76 --- /dev/null +++ b/lib/exceptions/wallet/insufficient_balance_exception.dart @@ -0,0 +1,5 @@ +import 'package:stackwallet/exceptions/sw_exception.dart'; + +class InsufficientBalanceException extends SWException { + InsufficientBalanceException(super.message); +} diff --git a/lib/exceptions/wallet/paynym_send_exception.dart b/lib/exceptions/wallet/paynym_send_exception.dart new file mode 100644 index 000000000..9980e6790 --- /dev/null +++ b/lib/exceptions/wallet/paynym_send_exception.dart @@ -0,0 +1,5 @@ +import 'package:stackwallet/exceptions/sw_exception.dart'; + +class PaynymSendException extends SWException { + PaynymSendException(super.message); +} diff --git a/lib/models/isar/models/address/address.dart b/lib/models/isar/models/address/address.dart index df6d06fa7..c3e885f3e 100644 --- a/lib/models/isar/models/address/address.dart +++ b/lib/models/isar/models/address/address.dart @@ -1,14 +1,10 @@ import 'package:isar/isar.dart'; +import 'package:stackwallet/exceptions/address/address_exception.dart'; import 'package:stackwallet/models/isar/models/address/crypto_currency_address.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; part 'address.g.dart'; -class AddressException extends SWException { - AddressException(super.message); -} - @Collection(accessor: "addresses") class Address extends CryptoCurrencyAddress { Address({ diff --git a/lib/pages/paynym/dialogs/paynym_details_popup.dart b/lib/pages/paynym/dialogs/paynym_details_popup.dart index 72c4a2f46..350b02ead 100644 --- a/lib/pages/paynym/dialogs/paynym_details_popup.dart +++ b/lib/pages/paynym/dialogs/paynym_details_popup.dart @@ -5,6 +5,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:qr_flutter/qr_flutter.dart'; +import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; import 'package:stackwallet/models/paynym/paynym_account_lite.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/paynym/dialogs/confirm_paynym_connect_dialog.dart'; diff --git a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart index d51a0fecd..ee4996a9d 100644 --- a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart +++ b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart @@ -5,6 +5,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:qr_flutter/qr_flutter.dart'; +import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; import 'package:stackwallet/models/paynym/paynym_account_lite.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/paynym/dialogs/confirm_paynym_connect_dialog.dart'; diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index 7cebca9ca..d8f5c535e 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -8,6 +8,8 @@ import 'package:bitcoindart/src/utils/constants/op.dart' as op; import 'package:bitcoindart/src/utils/script.dart' as bscript; import 'package:isar/isar.dart'; import 'package:pointycastle/digests/sha256.dart'; +import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; +import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; import 'package:stackwallet/hive/db.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; @@ -16,23 +18,6 @@ import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:tuple/tuple.dart'; -class SWException with Exception { - SWException(this.message); - - final String message; - - @override - toString() => message; -} - -class InsufficientBalanceException extends SWException { - InsufficientBalanceException(super.message); -} - -class PaynymSendException extends SWException { - PaynymSendException(super.message); -} - extension PayNym on DogecoinWallet { // fetch or generate this wallet's bip47 payment code Future getPaymentCode() async { From 6790f702c2b6b10d268944d3135dc3ba71cefe6d Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 09:37:14 -0600 Subject: [PATCH 04/55] migrate bugfix --- lib/utilities/db_version_migration.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utilities/db_version_migration.dart b/lib/utilities/db_version_migration.dart index eab9a8966..21378c8b5 100644 --- a/lib/utilities/db_version_migration.dart +++ b/lib/utilities/db_version_migration.dart @@ -503,7 +503,7 @@ class DbVersionMigrator with WalletDB { type: isar_models.AddressType.unknown, subType: type == isar_models.TransactionType.incoming ? isar_models.AddressSubType.receiving - : isar_models.AddressSubType.change, + : isar_models.AddressSubType.unknown, ); } } From f3325807e0f994c89e2f6f04377cfb8687d602b1 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 10:32:53 -0600 Subject: [PATCH 05/55] null address fix --- .../coins/bitcoin/bitcoin_wallet.dart | 52 +++++++++--------- .../coins/bitcoincash/bitcoincash_wallet.dart | 52 +++++++++--------- .../coins/dogecoin/dogecoin_wallet.dart | 52 +++++++++--------- lib/services/coins/firo/firo_wallet.dart | 52 +++++++++--------- .../coins/litecoin/litecoin_wallet.dart | 52 +++++++++--------- lib/services/coins/monero/monero_wallet.dart | 2 + .../coins/namecoin/namecoin_wallet.dart | 53 ++++++++++--------- .../coins/particl/particl_wallet.dart | 52 +++++++++--------- .../coins/wownero/wownero_wallet.dart | 9 ++-- 9 files changed, 189 insertions(+), 187 deletions(-) diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart index 9e8702ea3..d0b114829 100644 --- a/lib/services/coins/bitcoin/bitcoin_wallet.dart +++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart @@ -186,24 +186,28 @@ class BitcoinWallet extends CoinServiceAPI Future get currentReceivingAddress async => (await _currentReceivingAddress).value; - Future get _currentReceivingAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2wpkh) - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentReceivingAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2wpkh) + .subTypeEqualTo(isar_models.AddressSubType.receiving) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(0, 0, DerivePathType.bip84); Future get currentChangeAddress async => (await _currentChangeAddress).value; - Future get _currentChangeAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2wpkh) - .subTypeEqualTo(isar_models.AddressSubType.change) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentChangeAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2wpkh) + .subTypeEqualTo(isar_models.AddressSubType.change) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(1, 0, DerivePathType.bip84); @override Future exit() async { @@ -1164,6 +1168,8 @@ class BitcoinWallet extends CoinServiceAPI } await _prefs.init(); + await _checkCurrentChangeAddressesForTransactions(); + await _checkCurrentReceivingAddressesForTransactions(); } // hack to add tx to txData before refresh completes @@ -1857,7 +1863,7 @@ class BitcoinWallet extends CoinServiceAPI 'Number of txs for current receiving address $currentReceiving: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentReceiving.derivationIndex < 0) { // First increment the receiving index final newReceivingIndex = currentReceiving.derivationIndex + 1; @@ -1876,12 +1882,9 @@ class BitcoinWallet extends CoinServiceAPI } else { // we need to update the address await db.updateAddress(existing, newReceivingAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkReceivingAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkReceivingAddressForTransactions(); } } catch (e, s) { Logging.instance.log( @@ -1899,7 +1902,7 @@ class BitcoinWallet extends CoinServiceAPI 'Number of txs for current change address $currentChange: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentChange.derivationIndex < 0) { // First increment the change index final newChangeIndex = currentChange.derivationIndex + 1; @@ -1918,12 +1921,9 @@ class BitcoinWallet extends CoinServiceAPI } else { // we need to update the address await db.updateAddress(existing, newChangeAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkChangeAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkChangeAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index 1a6587e6b..70e3a5d55 100644 --- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart +++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart @@ -162,24 +162,28 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { Future get currentReceivingAddress async => (await _currentReceivingAddress).value; - Future get _currentReceivingAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2pkh) - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentReceivingAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2pkh) + .subTypeEqualTo(isar_models.AddressSubType.receiving) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(0, 0, DerivePathType.bip44); Future get currentChangeAddress async => (await _currentChangeAddress).value; - Future get _currentChangeAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2pkh) - .subTypeEqualTo(isar_models.AddressSubType.change) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentChangeAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2pkh) + .subTypeEqualTo(isar_models.AddressSubType.change) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(1, 0, DerivePathType.bip44); @override Future exit() async { @@ -1093,6 +1097,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { } await _prefs.init(); + await _checkCurrentChangeAddressesForTransactions(); + await _checkCurrentReceivingAddressesForTransactions(); } // hack to add tx to txData before refresh completes @@ -1740,7 +1746,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { 'Number of txs for current receiving address $currentReceiving: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentReceiving.derivationIndex < 0) { // First increment the receiving index final newReceivingIndex = currentReceiving.derivationIndex + 1; @@ -1759,12 +1765,9 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { } else { // we need to update the address await db.updateAddress(existing, newReceivingAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkReceivingAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkReceivingAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( @@ -1787,7 +1790,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { 'Number of txs for current change address $currentChange: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentChange.derivationIndex < 0) { // First increment the change index final newChangeIndex = currentChange.derivationIndex + 1; @@ -1806,12 +1809,9 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { } else { // we need to update the address await db.updateAddress(existing, newChangeAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkChangeAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkChangeAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 63568cc59..1c083d3bd 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -161,25 +161,29 @@ class DogecoinWallet extends CoinServiceAPI Future get currentReceivingAddress async => (await _currentReceivingAddress).value; - Future get _currentReceivingAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2pkh) - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentReceivingAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2pkh) + .subTypeEqualTo(isar_models.AddressSubType.receiving) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(0, 0, DerivePathType.bip44); // @override Future get currentChangeAddress async => (await _currentChangeAddress).value; - Future get _currentChangeAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2pkh) - .subTypeEqualTo(isar_models.AddressSubType.change) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentChangeAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2pkh) + .subTypeEqualTo(isar_models.AddressSubType.change) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(1, 0, DerivePathType.bip44); @override Future exit() async { @@ -999,6 +1003,8 @@ class DogecoinWallet extends CoinServiceAPI } await _prefs.init(); + await _checkCurrentChangeAddressesForTransactions(); + await _checkCurrentReceivingAddressesForTransactions(); } // hack to add tx to txData before refresh completes @@ -1645,7 +1651,7 @@ class DogecoinWallet extends CoinServiceAPI 'Number of txs for current receiving address $currentReceiving: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentReceiving.derivationIndex < 0) { // First increment the receiving index final newReceivingIndex = currentReceiving.derivationIndex + 1; @@ -1664,12 +1670,9 @@ class DogecoinWallet extends CoinServiceAPI } else { // we need to update the address await db.updateAddress(existing, newReceivingAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkReceivingAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkReceivingAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( @@ -1692,7 +1695,7 @@ class DogecoinWallet extends CoinServiceAPI 'Number of txs for current change address $currentChange: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentChange.derivationIndex < 0) { // First increment the change index final newChangeIndex = currentChange.derivationIndex + 1; @@ -1711,12 +1714,9 @@ class DogecoinWallet extends CoinServiceAPI } else { // we need to update the address await db.updateAddress(existing, newChangeAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await checkChangeAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await checkChangeAddressForTransactions(); } } catch (e, s) { Logging.instance.log( diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart index 0962e6fdc..ec63db186 100644 --- a/lib/services/coins/firo/firo_wallet.dart +++ b/lib/services/coins/firo/firo_wallet.dart @@ -871,24 +871,28 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { Future get currentReceivingAddress async => (await _currentReceivingAddress).value; - Future get _currentReceivingAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2pkh) - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentReceivingAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2pkh) + .subTypeEqualTo(isar_models.AddressSubType.receiving) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(0, 0); Future get currentChangeAddress async => (await _currentChangeAddress).value; - Future get _currentChangeAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2pkh) - .subTypeEqualTo(isar_models.AddressSubType.change) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentChangeAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2pkh) + .subTypeEqualTo(isar_models.AddressSubType.change) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(1, 0); late String _walletName; @override @@ -1831,6 +1835,8 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { "Attempted to initialize an existing wallet using an unknown wallet ID!"); } await _prefs.init(); + await checkChangeAddressForTransactions(); + await checkReceivingAddressForTransactions(); } Future refreshIfThereIsNewData() async { @@ -3144,7 +3150,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { 'Number of txs for current receiving address $currentReceiving: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentReceiving.derivationIndex < 0) { // First increment the receiving index final newReceivingIndex = currentReceiving.derivationIndex + 1; @@ -3165,12 +3171,9 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { } else { // we need to update the address await db.updateAddress(existing, newReceivingAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await checkReceivingAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await checkReceivingAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( @@ -3194,7 +3197,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { 'Number of txs for current change address: $currentChange: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentChange.derivationIndex < 0) { // First increment the change index final newChangeIndex = currentChange.derivationIndex + 1; @@ -3215,12 +3218,9 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { } else { // we need to update the address await db.updateAddress(existing, newChangeAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await checkChangeAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await checkChangeAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( diff --git a/lib/services/coins/litecoin/litecoin_wallet.dart b/lib/services/coins/litecoin/litecoin_wallet.dart index d0c922afa..fe1fdf13c 100644 --- a/lib/services/coins/litecoin/litecoin_wallet.dart +++ b/lib/services/coins/litecoin/litecoin_wallet.dart @@ -186,24 +186,28 @@ class LitecoinWallet extends CoinServiceAPI Future get currentReceivingAddress async => (await _currentReceivingAddress).value; - Future get _currentReceivingAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2wpkh) - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentReceivingAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2wpkh) + .subTypeEqualTo(isar_models.AddressSubType.receiving) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(0, 0, DerivePathType.bip84); Future get currentChangeAddress async => (await _currentChangeAddress).value; - Future get _currentChangeAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2wpkh) - .subTypeEqualTo(isar_models.AddressSubType.change) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentChangeAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2wpkh) + .subTypeEqualTo(isar_models.AddressSubType.change) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(1, 0, DerivePathType.bip84); @override Future exit() async { @@ -1182,6 +1186,8 @@ class LitecoinWallet extends CoinServiceAPI "Attempted to initialize an existing wallet using an unknown wallet ID!"); } await _prefs.init(); + await _checkCurrentChangeAddressesForTransactions(); + await _checkCurrentReceivingAddressesForTransactions(); } // hack to add tx to txData before refresh completes @@ -1880,7 +1886,7 @@ class LitecoinWallet extends CoinServiceAPI 'Number of txs for current receiving address $currentReceiving: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentReceiving.derivationIndex < 0) { // First increment the receiving index final newReceivingIndex = currentReceiving.derivationIndex + 1; @@ -1899,12 +1905,9 @@ class LitecoinWallet extends CoinServiceAPI } else { // we need to update the address await db.updateAddress(existing, newReceivingAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkReceivingAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkReceivingAddressForTransactions(); } } catch (e, s) { Logging.instance.log( @@ -1922,7 +1925,7 @@ class LitecoinWallet extends CoinServiceAPI 'Number of txs for current change address $currentChange: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentChange.derivationIndex < 0) { // First increment the change index final newChangeIndex = currentChange.derivationIndex + 1; @@ -1941,12 +1944,9 @@ class LitecoinWallet extends CoinServiceAPI } else { // we need to update the address await db.updateAddress(existing, newChangeAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkChangeAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkChangeAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( diff --git a/lib/services/coins/monero/monero_wallet.dart b/lib/services/coins/monero/monero_wallet.dart index ee3807163..d46595ec4 100644 --- a/lib/services/coins/monero/monero_wallet.dart +++ b/lib/services/coins/monero/monero_wallet.dart @@ -288,6 +288,8 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB { } walletBase = (await walletService!.openWallet(_walletId, password)) as MoneroWalletBase; + + await _checkCurrentReceivingAddressesForTransactions(); // walletBase!.onNewBlock = onNewBlock; // walletBase!.onNewTransaction = onNewTransaction; // walletBase!.syncStatusChanged = syncStatusChanged; diff --git a/lib/services/coins/namecoin/namecoin_wallet.dart b/lib/services/coins/namecoin/namecoin_wallet.dart index e9ef15b90..cae6cf29a 100644 --- a/lib/services/coins/namecoin/namecoin_wallet.dart +++ b/lib/services/coins/namecoin/namecoin_wallet.dart @@ -181,24 +181,28 @@ class NamecoinWallet extends CoinServiceAPI Future get currentReceivingAddress async => (await _currentReceivingAddress).value; - Future get _currentReceivingAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2wpkh) - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentReceivingAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2wpkh) + .subTypeEqualTo(isar_models.AddressSubType.receiving) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(0, 0, DerivePathType.bip84); Future get currentChangeAddress async => (await _currentChangeAddress).value; - Future get _currentChangeAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2wpkh) - .subTypeEqualTo(isar_models.AddressSubType.change) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentChangeAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2wpkh) + .subTypeEqualTo(isar_models.AddressSubType.change) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(1, 0, DerivePathType.bip84); @override Future exit() async { @@ -1171,6 +1175,8 @@ class NamecoinWallet extends CoinServiceAPI "Attempted to initialize an existing wallet using an unknown wallet ID!"); } await _prefs.init(); + await _checkCurrentChangeAddressesForTransactions(); + await _checkCurrentReceivingAddressesForTransactions(); } // hack to add tx to txData before refresh completes @@ -1862,7 +1868,7 @@ class NamecoinWallet extends CoinServiceAPI 'Number of txs for current receiving address $currentReceiving: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentReceiving.derivationIndex < 0) { // First increment the receiving index final newReceivingIndex = currentReceiving.derivationIndex + 1; @@ -1881,12 +1887,9 @@ class NamecoinWallet extends CoinServiceAPI } else { // we need to update the address await db.updateAddress(existing, newReceivingAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkReceivingAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkReceivingAddressForTransactions(); } } catch (e, s) { Logging.instance.log( @@ -1904,7 +1907,7 @@ class NamecoinWallet extends CoinServiceAPI 'Number of txs for current change address $currentChange: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentChange.derivationIndex < 0) { // First increment the change index final newChangeIndex = currentChange.derivationIndex + 1; @@ -1923,12 +1926,10 @@ class NamecoinWallet extends CoinServiceAPI } else { // we need to update the address await db.updateAddress(existing, newChangeAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkChangeAddressForTransactions(); } + + // keep checking until address with no tx history is set as current + await _checkChangeAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( diff --git a/lib/services/coins/particl/particl_wallet.dart b/lib/services/coins/particl/particl_wallet.dart index e705a6178..d19fdf769 100644 --- a/lib/services/coins/particl/particl_wallet.dart +++ b/lib/services/coins/particl/particl_wallet.dart @@ -176,24 +176,28 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { Future get currentReceivingAddress async => (await _currentReceivingAddress).value; - Future get _currentReceivingAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2wpkh) - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentReceivingAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2wpkh) + .subTypeEqualTo(isar_models.AddressSubType.receiving) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(0, 0, DerivePathType.bip84); Future get currentChangeAddress async => (await _currentChangeAddress).value; - Future get _currentChangeAddress async => (await db - .getAddresses(walletId) - .filter() - .typeEqualTo(isar_models.AddressType.p2wpkh) - .subTypeEqualTo(isar_models.AddressSubType.change) - .sortByDerivationIndexDesc() - .findFirst())!; + Future get _currentChangeAddress async => + (await db + .getAddresses(walletId) + .filter() + .typeEqualTo(isar_models.AddressType.p2wpkh) + .subTypeEqualTo(isar_models.AddressSubType.change) + .sortByDerivationIndexDesc() + .findFirst()) ?? + await _generateAddressForChain(1, 0, DerivePathType.bip84); @override Future exit() async { @@ -1100,6 +1104,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { "Attempted to initialize an existing wallet using an unknown wallet ID!"); } await _prefs.init(); + await _checkCurrentChangeAddressesForTransactions(); + await _checkCurrentReceivingAddressesForTransactions(); } // TODO make sure this copied implementation from bitcoin_wallet.dart applies for particl just as well--or import it @@ -1749,7 +1755,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { 'Number of txs for current receiving address $currentReceiving: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentReceiving.derivationIndex < 0) { // First increment the receiving index final newReceivingIndex = currentReceiving.derivationIndex + 1; @@ -1768,12 +1774,9 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { } else { // we need to update the address await db.updateAddress(existing, newReceivingAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkReceivingAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkReceivingAddressForTransactions(); } } catch (e, s) { Logging.instance.log( @@ -1791,7 +1794,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { 'Number of txs for current change address $currentChange: $txCount', level: LogLevel.Info); - if (txCount >= 1) { + if (txCount >= 1 || currentChange.derivationIndex < 0) { // First increment the change index final newChangeIndex = currentChange.derivationIndex + 1; @@ -1810,12 +1813,9 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { } else { // we need to update the address await db.updateAddress(existing, newChangeAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkChangeAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkChangeAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( diff --git a/lib/services/coins/wownero/wownero_wallet.dart b/lib/services/coins/wownero/wownero_wallet.dart index d471208cd..b1afa561d 100644 --- a/lib/services/coins/wownero/wownero_wallet.dart +++ b/lib/services/coins/wownero/wownero_wallet.dart @@ -306,6 +306,8 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB { walletBase = (await walletService?.openWallet(_walletId, password!)) as WowneroWalletBase; + await _checkCurrentReceivingAddressesForTransactions(); + Logging.instance.log( "Opened existing ${coin.prettyName} wallet $walletName", level: LogLevel.Info, @@ -1245,12 +1247,9 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB { } else { // we need to update the address await db.updateAddress(existing, newReceivingAddress); - - // since we updated an existing address there is a chance it has - // some tx history. To prevent address reuse we will call check again - // recursively - await _checkReceivingAddressForTransactions(); } + // keep checking until address with no tx history is set as current + await _checkReceivingAddressForTransactions(); } } on SocketException catch (se, s) { Logging.instance.log( From abf803afed92901a52771cc1ca03b0c17fa9c504 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 10:33:36 -0600 Subject: [PATCH 06/55] increment build number --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a4ba77948..134132e5f 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.5.30+104 +version: 1.5.30+105 environment: sdk: ">=2.17.0 <3.0.0" From 69dfbb5873561ba267c9a33754def1af7034b11a Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 12:19:13 -0600 Subject: [PATCH 07/55] paynym clean up to use isar transaction and address upgrades --- .../paynym/dialogs/paynym_details_popup.dart | 10 +- .../subwidgets/desktop_paynym_details.dart | 10 +- .../send_view/confirm_transaction_view.dart | 2 +- lib/services/coins/coin_paynym_extension.dart | 230 ++----- .../coins/dogecoin/dogecoin_wallet.dart | 4 +- lib/services/mixins/electrum_x_parsing.dart | 12 +- lib/services/mixins/paynym_support.dart | 569 ++++++++++++++++++ lib/utilities/bip32_utils.dart | 32 + 8 files changed, 682 insertions(+), 187 deletions(-) create mode 100644 lib/services/mixins/paynym_support.dart create mode 100644 lib/utilities/bip32_utils.dart diff --git a/lib/pages/paynym/dialogs/paynym_details_popup.dart b/lib/pages/paynym/dialogs/paynym_details_popup.dart index 350b02ead..4190aab8d 100644 --- a/lib/pages/paynym/dialogs/paynym_details_popup.dart +++ b/lib/pages/paynym/dialogs/paynym_details_popup.dart @@ -63,13 +63,7 @@ class _PaynymDetailsPopupState extends ConsumerState { .getManager(widget.walletId) .wallet as DogecoinWallet; - // sanity check to prevent second notifcation tx - if (wallet.hasConnectedConfirmed(widget.accountLite.code)) { - canPop = true; - Navigator.of(context).pop(); - // TODO show info popup - return; - } else if (wallet.hasConnected(widget.accountLite.code)) { + if (wallet.hasConnected(widget.accountLite.code)) { canPop = true; Navigator.of(context).pop(); // TODO show info popup @@ -81,7 +75,7 @@ class _PaynymDetailsPopupState extends ConsumerState { Map preparedTx; try { - preparedTx = await wallet.buildNotificationTx( + preparedTx = await wallet.prepareNotificationTx( selectedTxFeeRate: rates.medium, targetPaymentCodeString: widget.accountLite.code, ); diff --git a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart index ee4996a9d..4e69a7586 100644 --- a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart +++ b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart @@ -63,13 +63,7 @@ class _PaynymDetailsPopupState extends ConsumerState { .getManager(widget.walletId) .wallet as DogecoinWallet; - // sanity check to prevent second notification tx - if (wallet.hasConnectedConfirmed(widget.accountLite.code)) { - canPop = true; - Navigator.of(context, rootNavigator: true).pop(); - // TODO show info popup - return; - } else if (wallet.hasConnected(widget.accountLite.code)) { + if (wallet.hasConnected(widget.accountLite.code)) { canPop = true; Navigator.of(context, rootNavigator: true).pop(); // TODO show info popup @@ -81,7 +75,7 @@ class _PaynymDetailsPopupState extends ConsumerState { Map preparedTx; try { - preparedTx = await wallet.buildNotificationTx( + preparedTx = await wallet.prepareNotificationTx( selectedTxFeeRate: rates.medium, targetPaymentCodeString: widget.accountLite.code, ); diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 1164e0418..3ed4de63c 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -93,7 +93,7 @@ class _ConfirmTransactionViewState String txid; if (widget.isPaynymNotificationTransaction) { txid = await (manager.wallet as DogecoinWallet) - .confirmNotificationTx(preparedTx: transactionInfo); + .broadcastNotificationTx(preparedTx: transactionInfo); } else if (widget.isPaynymTransaction) { // throw UnimplementedError("paynym send not implemented yet"); diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index d8f5c535e..2ad0e4475 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:bip32/bip32.dart' as bip32; import 'package:bip47/bip47.dart'; import 'package:bip47/src/util.dart'; import 'package:bitcoindart/bitcoindart.dart' as btc_dart; @@ -10,38 +11,57 @@ import 'package:isar/isar.dart'; import 'package:pointycastle/digests/sha256.dart'; import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; -import 'package:stackwallet/hive/db.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/utilities/address_utils.dart'; +import 'package:stackwallet/utilities/bip32_utils.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:tuple/tuple.dart'; +const kPaynymDerivePath = "m/47'/0'/0'"; + extension PayNym on DogecoinWallet { + // generate bip32 payment code root + Future getRootNode({required List mnemonic}) async { + final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), network); + return root; + } + // fetch or generate this wallet's bip47 payment code Future getPaymentCode() async { - final paymentCodeString = DB.instance - .get(boxName: walletId, key: "paymentCodeString") as String?; + final address = await db + .getAddresses(walletId) + .filter() + .subTypeEqualTo(AddressSubType.paynymNotification) + .findFirst(); PaymentCode paymentCode; - if (paymentCodeString == null) { - final node = getBip32Root((await mnemonic).join(" "), network) - .derivePath("m/47'/0'/0'"); + if (address == null) { + final root = await getRootNode(mnemonic: await mnemonic); + final node = root.derivePath(kPaynymDerivePath); paymentCode = PaymentCode.initFromPubKey(node.publicKey, node.chainCode, network); - await DB.instance.put( - boxName: walletId, - key: "paymentCodeString", - value: paymentCode.toString()); + + await db.putAddress( + Address( + walletId: walletId, + value: paymentCode.notificationAddress(), + publicKey: paymentCode.getPubKey(), + derivationIndex: 0, + type: AddressType.p2pkh, // todo change this for btc + subType: AddressSubType.paynymNotification, + otherData: paymentCode.toString(), + ), + ); } else { - paymentCode = PaymentCode.fromPaymentCode(paymentCodeString, network); + paymentCode = PaymentCode.fromPaymentCode(address.otherData!, network); } return paymentCode; } Future signWithNotificationKey(Uint8List data) async { - final node = getBip32Root((await mnemonic).join(" "), network) - .derivePath("m/47'/0'/0'"); + final root = await getRootNode(mnemonic: await mnemonic); + final node = root.derivePath(kPaynymDerivePath); final pair = btc_dart.ECPair.fromPrivateKey(node.privateKey!, network: network); final signed = pair.sign(SHA256Digest().process(data)); @@ -52,92 +72,17 @@ extension PayNym on DogecoinWallet { final bytes = await signWithNotificationKey(Uint8List.fromList(utf8.encode(data))); return Format.uint8listToString(bytes); - // final bytes = - // await signWithNotificationKey(Uint8List.fromList(utf8.encode(data))); - // return Format.uint8listToString(bytes); - } - - /// Update cached lists of notification transaction IDs. - /// Returns true if there are new notification transactions found since last - /// checked. - Future checkForNotificationTransactions() async { - final myPCode = await getPaymentCode(); - - final transactionIds = await electrumXClient.getHistory( - scripthash: AddressUtils.convertToScriptHash( - myPCode.notificationAddress(), - network, - ), - ); - - final confirmedNotificationTransactionIds = DB.instance.get( - boxName: walletId, - key: "confirmedNotificationTransactionIds", - ) as Set? ?? - {}; - - final unconfirmedNotificationTransactionIds = DB.instance.get( - boxName: walletId, - key: "unconfirmedNotificationTransactionIds", - ) as Set? ?? - {}; - - // since we are only checking for newly found transactions here we can use the sum - final totalCount = confirmedNotificationTransactionIds.length + - unconfirmedNotificationTransactionIds.length; - - for (final entry in transactionIds) { - final txid = entry["tx_hash"] as String; - - final tx = await cachedElectrumXClient.getTransaction( - txHash: txid, - coin: coin, - ); - - // check if tx is confirmed - if ((tx["confirmations"] as int? ?? 0) > MINIMUM_CONFIRMATIONS) { - // remove it from unconfirmed set - unconfirmedNotificationTransactionIds.remove(txid); - - // add it to confirmed set - confirmedNotificationTransactionIds.add(txid); - } else { - // otherwise add it to the unconfirmed set - unconfirmedNotificationTransactionIds.add(txid); - } - } - - final newTotalCount = confirmedNotificationTransactionIds.length + - unconfirmedNotificationTransactionIds.length; - - return newTotalCount > totalCount; - } - - /// return the notification tx sent from my wallet if it exists - Future hasSentNotificationTx(PaymentCode pCode) async { - final tx = await db - .getTransactions(walletId) - .filter() - .address((q) => q.valueEqualTo(pCode.notificationAddress())) - .findFirst(); - return tx; } void preparePaymentCodeSend(PaymentCode pCode) async { - final notifTx = await hasSentNotificationTx(pCode); - final currentHeight = await chainHeight; - - if (notifTx == null) { + if (!hasConnected(pCode.notificationAddress())) { throw PaynymSendException("No notification transaction sent to $pCode"); - } else if (!notifTx.isConfirmed(currentHeight, MINIMUM_CONFIRMATIONS)) { - throw PaynymSendException( - "Notification transaction sent to $pCode has not confirmed yet"); } else { - final node = getBip32Root((await mnemonic).join(" "), network) - .derivePath("m/47'/0'/0'"); + final root = await getRootNode(mnemonic: await mnemonic); + final node = root.derivePath(kPaynymDerivePath); final sendToAddress = await nextUnusedSendAddressFrom( - pCode, - node.derive(0).privateKey!, + pCode: pCode, + privateKey: node.derive(0).privateKey!, ); // todo: Actual transaction build @@ -146,22 +91,21 @@ extension PayNym on DogecoinWallet { /// get the next unused address to send to given the receiver's payment code /// and your own private key - Future nextUnusedSendAddressFrom( - PaymentCode pCode, - Uint8List privateKey, - ) async { + Future nextUnusedSendAddressFrom({ + required PaymentCode pCode, + required Uint8List privateKey, + int startIndex = 0, + }) async { // https://en.bitcoin.it/wiki/BIP_0047#Path_levels const maxCount = 2147483647; final paymentAddress = PaymentAddress.initWithPrivateKey( privateKey, pCode, - 0, // initial index to check + startIndex, // initial index to check ); - for (paymentAddress.index = 0; - paymentAddress.index <= maxCount; - paymentAddress.index++) { + for (; paymentAddress.index <= maxCount; paymentAddress.index++) { final address = paymentAddress.getSendAddress(); final transactionIds = await electrumXClient.getHistory( @@ -208,7 +152,7 @@ extension PayNym on DogecoinWallet { return result; } - Future> buildNotificationTx({ + Future> prepareNotificationTx({ required int selectedTxFeeRate, required String targetPaymentCodeString, int additionalOutputs = 0, @@ -370,7 +314,7 @@ extension PayNym on DogecoinWallet { // if we get here we do not have enough funds to cover the tx total so we // check if we have any more available outputs and try again if (spendableOutputs.length > outputsBeingUsed) { - return buildNotificationTx( + return prepareNotificationTx( selectedTxFeeRate: selectedTxFeeRate, targetPaymentCodeString: targetPaymentCodeString, additionalOutputs: additionalOutputs + 1, @@ -462,7 +406,7 @@ extension PayNym on DogecoinWallet { return Tuple2(builtTx.toHex(), builtTx.virtualSize()); } - Future confirmNotificationTx( + Future broadcastNotificationTx( {required Map preparedTx}) async { try { Logging.instance.log("confirmNotificationTx txData: $preparedTx", @@ -471,11 +415,16 @@ extension PayNym on DogecoinWallet { rawTx: preparedTx["hex"] as String); Logging.instance.log("Sent txHash: $txHash", level: LogLevel.Info); - await updatePaynymNotificationInfo( - txid: txHash, - confirmed: false, - paymentCodeString: preparedTx["address"] as String, - ); + // TODO: only refresh transaction data + try { + await refresh(); + } catch (e) { + Logging.instance.log( + "refresh() failed in confirmNotificationTx ($walletName::$walletId): $e", + level: LogLevel.Error, + ); + } + return txHash; } catch (e, s) { Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s", @@ -484,63 +433,12 @@ extension PayNym on DogecoinWallet { } } - // Future hasConfirmedNotificationTxSentTo( - // String paymentCodeString) async { - // final targetPaymentCode = - // PaymentCode.fromPaymentCode(paymentCodeString, network); - // final targetNotificationAddress = targetPaymentCode.notificationAddress(); - // - // final myTxHistory = (await transactionData) - // .getAllTransactions() - // .entries - // .map((e) => e.value) - // .where((e) => - // e.txType == "Sent" && e.address == targetNotificationAddress); - // - // return myTxHistory.isNotEmpty; - // } - bool hasConnected(String paymentCodeString) { - return getPaynymNotificationTxInfo() - .values - .where((e) => e["paymentCodeString"] == paymentCodeString) - .isNotEmpty; - } - - bool hasConnectedConfirmed(String paymentCodeString) { - return getPaynymNotificationTxInfo() - .values - .where((e) => - e["paymentCodeString"] == paymentCodeString && - e["confirmed"] == true) - .isNotEmpty; - } - - // fetch paynym notification tx meta data - Map getPaynymNotificationTxInfo() { - final map = DB.instance.get( - boxName: walletId, key: "paynymNotificationTxInfo") as Map? ?? - {}; - - return Map.from(map); - } - - // add/update paynym notification tx meta data entry - Future updatePaynymNotificationInfo({ - required String txid, - required bool confirmed, - required String paymentCodeString, - }) async { - final data = getPaynymNotificationTxInfo(); - data[txid] = { - "txid": txid, - "confirmed": confirmed, - "paymentCodeString": paymentCodeString, - }; - await DB.instance.put( - boxName: walletId, - key: "paynymNotificationTxInfo", - value: data, - ); + return db + .getTransactions(walletId) + .filter() + .address((q) => q.valueEqualTo(paymentCodeString)) + .countSync() > + 0; } } diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 1c083d3bd..7d0fdea6f 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -2776,7 +2776,7 @@ class DogecoinWallet extends CoinServiceAPI // Dogecoin Network final dogecoin = NetworkType( messagePrefix: '\x18Dogecoin Signed Message:\n', - bech32: 'bc', + // bech32: 'bc', bip32: Bip32Type(public: 0x02facafd, private: 0x02fac398), pubKeyHash: 0x1e, scriptHash: 0x16, @@ -2784,7 +2784,7 @@ final dogecoin = NetworkType( final dogecointestnet = NetworkType( messagePrefix: '\x18Dogecoin Signed Message:\n', - bech32: 'tb', + // bech32: 'tb', bip32: Bip32Type(public: 0x043587cf, private: 0x04358394), pubKeyHash: 0x71, scriptHash: 0xc4, diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart index 9a2c950d6..b8e40bb52 100644 --- a/lib/services/mixins/electrum_x_parsing.dart +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -15,7 +15,9 @@ mixin ElectrumXParsing { String walletId, ) async { Set receivingAddresses = myAddresses - .where((e) => e.subType == AddressSubType.receiving) + .where((e) => + e.subType == AddressSubType.receiving || + e.subType == AddressSubType.paynymNotification) .map((e) => e.value) .toSet(); Set changeAddresses = myAddresses @@ -146,13 +148,19 @@ mixin ElectrumXParsing { amount = amountReceivedInWallet; } + bool isNotificationTx = coin.hasPaynymSupport && + type == TransactionType.incoming && + transactionAddress.subType == AddressSubType.paynymNotification; + final tx = Transaction( walletId: walletId, txid: txData["txid"] as String, timestamp: txData["blocktime"] as int? ?? (DateTime.now().millisecondsSinceEpoch ~/ 1000), type: type, - subType: TransactionSubType.none, + subType: isNotificationTx + ? TransactionSubType.bip47Notification + : TransactionSubType.none, amount: amount, fee: fee, height: txData["height"] as int?, diff --git a/lib/services/mixins/paynym_support.dart b/lib/services/mixins/paynym_support.dart new file mode 100644 index 000000000..3bea5aee6 --- /dev/null +++ b/lib/services/mixins/paynym_support.dart @@ -0,0 +1,569 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:bip32/bip32.dart' as bip32; +import 'package:bip47/bip47.dart'; +import 'package:bip47/src/util.dart'; +import 'package:bitcoindart/bitcoindart.dart' as btc_dart; +import 'package:bitcoindart/src/utils/constants/op.dart' as op; +import 'package:bitcoindart/src/utils/script.dart' as bscript; +import 'package:isar/isar.dart'; +import 'package:pointycastle/digests/sha256.dart'; +import 'package:stackwallet/db/main_db.dart'; +import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart'; +import 'package:stackwallet/electrumx_rpc/electrumx.dart'; +import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; +import 'package:stackwallet/models/isar/models/isar_models.dart'; +import 'package:stackwallet/utilities/address_utils.dart'; +import 'package:stackwallet/utilities/bip32_utils.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/format.dart'; +import 'package:stackwallet/utilities/logger.dart'; +import 'package:tuple/tuple.dart'; +import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; + +mixin PaynymSupport { + late final btc_dart.NetworkType network; + late final MainDB db; + late final Coin coin; + late final String walletId; + void initPaynymSupport({ + required btc_dart.NetworkType network, + required MainDB db, + required Coin coin, + required String walletId, + }) { + this.network = network; + this.db = db; + this.coin = coin; + this.walletId = walletId; + } + + // generate bip32 payment code root + Future getRootNode({required List mnemonic}) async { + final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), network); + return root; + } + + // fetch or generate this wallet's bip47 payment code + Future getPaymentCode({ + required List mnemonic, + }) async { + // TODO: cache elsewhere + // final paymentCodeString = DB.instance + // .get(boxName: walletId, key: "paymentCodeString") as String?; + PaymentCode paymentCode; + // if (paymentCodeString == null) { + final root = await getRootNode(mnemonic: mnemonic); + final node = root.derivePath("m/47'/0'/0'"); + paymentCode = + PaymentCode.initFromPubKey(node.publicKey, node.chainCode, network); + // await DB.instance.put( + // boxName: walletId, + // key: "paymentCodeString", + // value: paymentCode.toString()); + // } else { + // paymentCode = PaymentCode.fromPaymentCode(paymentCodeString, network); + // } + return paymentCode; + } + + Future signWithNotificationKey({ + required Uint8List data, + required List mnemonic, + }) async { + final root = await getRootNode( + mnemonic: mnemonic, + ); + final node = root.derivePath("m/47'/0'/0'"); + final pair = btc_dart.ECPair.fromPrivateKey(node.privateKey!, network: network); + final signed = pair.sign(SHA256Digest().process(data)); + return signed; + } + + Future signStringWithNotificationKey({ + required String data, + required List mnemonic, + }) async { + final bytes = await signWithNotificationKey( + data: Uint8List.fromList(utf8.encode(data)), + mnemonic: mnemonic, + ); + return Format.uint8listToString(bytes); + // final bytes = + // await signWithNotificationKey(Uint8List.fromList(utf8.encode(data))); + // return Format.uint8listToString(bytes); + } + + /// Update cached lists of notification transaction IDs. + /// Returns true if there are new notification transactions found since last + /// checked. + Future checkForNotificationTransactions({ + required Coin coin, + required PaymentCode paymentCode, + required ElectrumX electrumXClient, + required CachedElectrumX cachedElectrumXClient, + required int currentChainHeight, + }) async { + final notificationAddress = paymentCode.notificationAddress(); + + final receivedNotificationTransactions = await db + .getTransactions(walletId) + .filter() + .address((q) => q.valueEqualTo(notificationAddress)) + .findAll(); + + + final unconfirmedTransactions = receivedNotificationTransactions.where( + (e) => !e.isConfirmed( + currentChainHeight, + coin.requiredConfirmations, + ), + ); + + final totalStoredCount = receivedNotificationTransactions.length; + final storedUnconfirmedCount = unconfirmedTransactions.length; + + // for (final txid in transactionIds) { + // final tx = await cachedElectrumXClient.getTransaction( + // txHash: txid, + // coin: coin, + // ); + // + // // check if tx is confirmed + // if ((tx["confirmations"] as int? ?? 0) > coin.requiredConfirmations) { + // // remove it from unconfirmed set + // unconfirmedNotificationTransactionIds.remove(txid); + // + // // add it to confirmed set + // confirmedNotificationTransactionIds.add(txid); + // } else { + // // otherwise add it to the unconfirmed set + // unconfirmedNotificationTransactionIds.add(txid); + // } + // } + // + // final newTotalCount = confirmedNotificationTransactionIds.length + + // unconfirmedNotificationTransactionIds.length; + // + // return newTotalCount > totalCount; + return false; + } + + // bool hasConnected(String paymentCodeString) { + // return getPaynymNotificationTxInfo() + // .values + // .where((e) => e["paymentCodeString"] == paymentCodeString) + // .isNotEmpty; + // } + // + // bool hasConnectedConfirmed(String paymentCodeString) { + // return getPaynymNotificationTxInfo() + // .values + // .where((e) => + // e["paymentCodeString"] == paymentCodeString && + // e["confirmed"] == true) + // .isNotEmpty; + // } + // + // // fetch paynym notification tx meta data + // Map getPaynymNotificationTxInfo() { + // final map = DB.instance.get( + // boxName: walletId, key: "paynymNotificationTxInfo") as Map? ?? + // {}; + // + // return Map.from(map); + // } + + // // add/update paynym notification tx meta data entry + // Future updatePaynymNotificationInfo({ + // required String txid, + // required bool confirmed, + // required String paymentCodeString, + // }) async { + // final data = getPaynymNotificationTxInfo(); + // data[txid] = { + // "txid": txid, + // "confirmed": confirmed, + // "paymentCodeString": paymentCodeString, + // }; + // await DB.instance.put( + // boxName: walletId, + // key: "paynymNotificationTxInfo", + // value: data, + // ); + // } + + Future hasSentNotificationTx(PaymentCode pCode) async { + final tx = await db + .getTransactions(walletId) + .filter() + .address((q) => q.valueEqualTo(pCode.notificationAddress())).countSync() + .findFirst(); + return tx; + } + + void preparePaymentCodeSend(PaymentCode pCode) async { + final notifTx = await hasSentNotificationTx(pCode); + final currentHeight = await chainHeight; + + if (notifTx == null) { + throw PaynymSendException("No notification transaction sent to $pCode"); + } else if (!notifTx.isConfirmed(currentHeight, MINIMUM_CONFIRMATIONS)) { + throw PaynymSendException( + "Notification transaction sent to $pCode has not confirmed yet"); + } else { + final node = getBip32Root((await mnemonic).join(" "), network) + .derivePath("m/47'/0'/0'"); + final sendToAddress = await nextUnusedSendAddressFrom( + pCode, + node.derive(0).privateKey!, + ); + + // todo: Actual transaction build + } + } + + /// get the next unused address to send to given the receiver's payment code + /// and your own private key + Future nextUnusedSendAddressFrom( + PaymentCode pCode, + Uint8List privateKey, + ) async { + // https://en.bitcoin.it/wiki/BIP_0047#Path_levels + const maxCount = 2147483647; + + final paymentAddress = PaymentAddress.initWithPrivateKey( + privateKey, + pCode, + 0, // initial index to check + ); + + for ( ; + paymentAddress.index <= maxCount; + paymentAddress.index++) { + final address = paymentAddress.getSendAddress(); + + final transactionIds = await electrumXClient.getHistory( + scripthash: AddressUtils.convertToScriptHash( + address, + network, + ), + ); + + if (transactionIds.isEmpty) { + return address; + } + } + + throw PaynymSendException("Exhausted unused send addresses!"); + } + + /// get your receiving addresses given the sender's payment code and your own + /// private key + List deriveReceivingAddressesFor( + PaymentCode pCode, + Uint8List privateKey, + int count, + ) { + // https://en.bitcoin.it/wiki/BIP_0047#Path_levels + const maxCount = 2147483647; + assert(count <= maxCount); + + final paymentAddress = PaymentAddress.initWithPrivateKey( + privateKey, + pCode, + 0, // initial index + ); + + final List result = []; + for (paymentAddress.index = 0; + paymentAddress.index < count; + paymentAddress.index++) { + final address = paymentAddress.getReceiveAddress(); + + result.add(address); + } + + return result; + } + + Future> buildNotificationTx({ + required int selectedTxFeeRate, + required String targetPaymentCodeString, + required PaymentCode myPaymentCode, + int additionalOutputs = 0, + required List utxos, + required int dustLimit, + required int chainHeight, + required Future> Function( + List< UTXO> + ) fetchBuildTxData, + }) async { + final amountToSend = dustLimit; + final List availableOutputs = utxos ; + final List spendableOutputs = []; + int spendableSatoshiValue = 0; + + // Build list of spendable outputs and totaling their satoshi amount + for (var i = 0; i < availableOutputs.length; i++) { + if (availableOutputs[i].isBlocked == false && + availableOutputs[i] + .isConfirmed( chainHeight, coin.requiredConfirmations) == + true) { + spendableOutputs.add(availableOutputs[i]); + spendableSatoshiValue += availableOutputs[i].value; + } + } + + if (spendableSatoshiValue < amountToSend) { + // insufficient balance + throw InsufficientBalanceException( + "Spendable balance is less than the minimum required for a notification transaction."); + } else if (spendableSatoshiValue == amountToSend) { + // insufficient balance due to missing amount to cover fee + throw InsufficientBalanceException( + "Remaining balance does not cover the network fee."); + } + + // sort spendable by age (oldest first) + spendableOutputs.sort((a, b) => b.blockTime!.compareTo(a.blockTime!)); + + int satoshisBeingUsed = 0; + int outputsBeingUsed = 0; + List utxoObjectsToUse = []; + + for (int i = 0; + satoshisBeingUsed < amountToSend && i < spendableOutputs.length; + i++) { + utxoObjectsToUse.add(spendableOutputs[i]); + satoshisBeingUsed += spendableOutputs[i].value; + outputsBeingUsed += 1; + } + + // add additional outputs if required + for (int i = 0; + i < additionalOutputs && outputsBeingUsed < spendableOutputs.length; + i++) { + utxoObjectsToUse.add(spendableOutputs[outputsBeingUsed]); + satoshisBeingUsed += spendableOutputs[outputsBeingUsed].value; + outputsBeingUsed += 1; + } + + // gather required signing data + final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); + + final int vSizeForNoChange = (await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: 0, myPaymentCode: myPaymentCode, dustLimit: dustLimit, changeAddress: )) + .item2; + + final int vSizeForWithChange = (await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: satoshisBeingUsed - amountToSend, myPaymentCode: myPaymentCode, dustLimit: dustLimit, changeAddress: ch,)) + .item2; + + // Assume 2 outputs, for recipient and payment code script + int feeForNoChange = estimateTxFee( + vSize: vSizeForNoChange, + feeRatePerKB: selectedTxFeeRate, + ); + + // Assume 3 outputs, for recipient, payment code script, and change + int feeForWithChange = estimateTxFee( + vSize: vSizeForWithChange, + feeRatePerKB: selectedTxFeeRate, + ); + + if (feeForNoChange < vSizeForNoChange * 1000) { + feeForNoChange = vSizeForNoChange * 1000; + } + if (feeForWithChange < vSizeForWithChange * 1000) { + feeForWithChange = vSizeForWithChange * 1000; + } + + if (satoshisBeingUsed - amountToSend > feeForNoChange + dustLimit) { + // try to add change output due to "left over" amount being greater than + // the estimated fee + the dust limit + int changeAmount = satoshisBeingUsed - amountToSend - feeForWithChange; + + // check estimates are correct and build notification tx + if (changeAmount >= dustLimit && + satoshisBeingUsed - amountToSend - changeAmount == feeForWithChange) { + final txn = await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: changeAmount, + ); + + int feeBeingPaid = satoshisBeingUsed - amountToSend - changeAmount; + + Map transactionObject = { + "hex": txn.item1, + "recipientPaynym": targetPaymentCodeString, + "amount": amountToSend, + "fee": feeBeingPaid, + "vSize": txn.item2, + }; + return transactionObject; + } else { + // something broke during fee estimation or the change amount is smaller + // than the dust limit. Try without change + final txn = await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: 0, + ); + + int feeBeingPaid = satoshisBeingUsed - amountToSend; + + Map transactionObject = { + "hex": txn.item1, + "recipientPaynym": targetPaymentCodeString, + "amount": amountToSend, + "fee": feeBeingPaid, + "vSize": txn.item2, + }; + return transactionObject; + } + } else if (satoshisBeingUsed - amountToSend >= feeForNoChange) { + // since we already checked if we need to add a change output we can just + // build without change here + final txn = await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: 0, myPaymentCode: null, + ); + + int feeBeingPaid = satoshisBeingUsed - amountToSend; + + Map transactionObject = { + "hex": txn.item1, + "recipientPaynym": targetPaymentCodeString, + "amount": amountToSend, + "fee": feeBeingPaid, + "vSize": txn.item2, + }; + return transactionObject; + } else { + // if we get here we do not have enough funds to cover the tx total so we + // check if we have any more available outputs and try again + if (spendableOutputs.length > outputsBeingUsed) { + return buildNotificationTx( + selectedTxFeeRate: selectedTxFeeRate, + targetPaymentCodeString: targetPaymentCodeString, + additionalOutputs: additionalOutputs + 1, utxos: utxos, dustLimit: dustLimit, chainHeight: chainHeight, fetchBuildTxData: fetchBuildTxData, + ); + } else { + throw InsufficientBalanceException( + "Remaining balance does not cover the network fee."); + } + } + } + + // return tuple with string value equal to the raw tx hex and the int value + // equal to its vSize + Future> _createNotificationTx({ + required String targetPaymentCodeString, + required PaymentCode myPaymentCode, + required List utxosToUse, + required Map utxoSigningData, + required int change, + required int dustLimit, + required Address changeAddress, + }) async { + final targetPaymentCode = + PaymentCode.fromPaymentCode(targetPaymentCodeString, network); + + final utxo = utxosToUse.first; + final txPoint = utxo.txid.fromHex.toList(); + final txPointIndex = utxo.vout; + + final rev = Uint8List(txPoint.length + 4); + Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); + final buffer = rev.buffer.asByteData(); + buffer.setUint32(txPoint.length, txPointIndex, Endian.little); + + final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as btc_dart.ECPair; + + final S = SecretPoint( + myKeyPair.privateKey!, + targetPaymentCode.notificationPublicKey(), + ); + + final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev); + + final blindedPaymentCode = PaymentCode.blind( + myPaymentCode.getPayload(), + blindingMask, + ); + + final opReturnScript = bscript.compile([ + (op.OPS["OP_RETURN"] as int), + blindedPaymentCode, + ]); + + // build a notification tx + final txb = btc_dart.TransactionBuilder(network: network); + txb.setVersion(1); + + txb.addInput( + utxo.txid, + txPointIndex, + ); + + txb.addOutput(targetPaymentCode.notificationAddress(), dustLimit); + txb.addOutput(opReturnScript, 0); + + // TODO: add possible change output and mark output as dangerous + if (change > 0) { + final String changeAddressString = changeAddress.value; + txb.addOutput(changeAddressString, change); + } + + txb.sign( + vin: 0, + keyPair: myKeyPair, + ); + + // sign rest of possible inputs + for (var i = 1; i < utxosToUse.length - 1; i++) { + final txid = utxosToUse[i].txid; + txb.sign( + vin: i, + keyPair: utxoSigningData[txid]["keyPair"] as ECPair, + // witnessValue: utxosToUse[i].value, + ); + } + + final builtTx = txb.build(); + + return Tuple2(builtTx.toHex(), builtTx.virtualSize()); + } + + Future confirmSendNotificationTx( + {required Map preparedTx, required ElectrumX electrumXClient,}) async { + try { + Logging.instance.log("confirmNotificationTx txData: $preparedTx", + level: LogLevel.Info); + final txHash = await electrumXClient.broadcastTransaction( + rawTx: preparedTx["hex"] as String); + Logging.instance.log("Sent txHash: $txHash", level: LogLevel.Info); + + + return txHash; + } catch (e, s) { + Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s", + level: LogLevel.Error); + rethrow; + } + } + +} diff --git a/lib/utilities/bip32_utils.dart b/lib/utilities/bip32_utils.dart new file mode 100644 index 000000000..50549938f --- /dev/null +++ b/lib/utilities/bip32_utils.dart @@ -0,0 +1,32 @@ +import 'package:bip32/bip32.dart' as bip32; +import 'package:bip39/bip39.dart' as bip39; +import 'package:bitcoindart/bitcoindart.dart'; +import 'package:flutter/foundation.dart'; +import 'package:tuple/tuple.dart'; + +abstract class Bip32Utils { + static bip32.BIP32 getBip32RootSync(String mnemonic, NetworkType network) { + final seed = bip39.mnemonicToSeed(mnemonic); + final networkType = bip32.NetworkType( + wif: network.wif, + bip32: bip32.Bip32Type( + public: network.bip32.public, + private: network.bip32.private, + ), + ); + + final root = bip32.BIP32.fromSeed(seed, networkType); + return root; + } + + static Future getBip32Root( + String mnemonic, NetworkType network) async { + final root = await compute(_getBip32RootWrapper, Tuple2(mnemonic, network)); + return root; + } + + /// wrapper for compute() + static bip32.BIP32 _getBip32RootWrapper(Tuple2 args) { + return getBip32RootSync(args.item1, args.item2); + } +} From 5eb4b3bff5a57015d219f5ac3fd688f02fc40cbf Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 13:46:56 -0600 Subject: [PATCH 08/55] move tx creation after ins/outs and added another null check --- lib/services/mixins/electrum_x_parsing.dart | 39 +++++++++++---------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart index b8e40bb52..49f28a50c 100644 --- a/lib/services/mixins/electrum_x_parsing.dart +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -152,24 +152,6 @@ mixin ElectrumXParsing { type == TransactionType.incoming && transactionAddress.subType == AddressSubType.paynymNotification; - final tx = Transaction( - walletId: walletId, - txid: txData["txid"] as String, - timestamp: txData["blocktime"] as int? ?? - (DateTime.now().millisecondsSinceEpoch ~/ 1000), - type: type, - subType: isNotificationTx - ? TransactionSubType.bip47Notification - : TransactionSubType.none, - amount: amount, - fee: fee, - height: txData["height"] as int?, - isCancelled: false, - isLelantus: false, - slateId: null, - otherData: null, - ); - List outs = []; List ins = []; @@ -196,7 +178,8 @@ mixin ElectrumXParsing { scriptPubKeyType: json['scriptPubKey']?['type'] as String?, scriptPubKeyAddress: json["scriptPubKey"]?["addresses"]?[0] as String? ?? - json['scriptPubKey']['type'] as String, + json['scriptPubKey']?['type'] as String? ?? + "", value: Format.decimalAmountToSatoshis( Decimal.parse(json["value"].toString()), coin, @@ -205,6 +188,24 @@ mixin ElectrumXParsing { outs.add(output); } + final tx = Transaction( + walletId: walletId, + txid: txData["txid"] as String, + timestamp: txData["blocktime"] as int? ?? + (DateTime.now().millisecondsSinceEpoch ~/ 1000), + type: type, + subType: isNotificationTx + ? TransactionSubType.bip47Notification + : TransactionSubType.none, + amount: amount, + fee: fee, + height: txData["height"] as int?, + isCancelled: false, + isLelantus: false, + slateId: null, + otherData: null, + ); + return Tuple4(tx, outs, ins, transactionAddress); } } From 8a7d669b62c1b93162104d85ac4af03a6a9cc633 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 15:39:05 -0600 Subject: [PATCH 09/55] async hasConnected ui update --- .../paynym/dialogs/paynym_details_popup.dart | 66 +++++++++++---- .../subwidgets/desktop_paynym_details.dart | 81 +++++++++++-------- 2 files changed, 98 insertions(+), 49 deletions(-) diff --git a/lib/pages/paynym/dialogs/paynym_details_popup.dart b/lib/pages/paynym/dialogs/paynym_details_popup.dart index 4190aab8d..5150d9bb2 100644 --- a/lib/pages/paynym/dialogs/paynym_details_popup.dart +++ b/lib/pages/paynym/dialogs/paynym_details_popup.dart @@ -44,6 +44,10 @@ class PaynymDetailsPopup extends ConsumerStatefulWidget { class _PaynymDetailsPopupState extends ConsumerState { bool _showInsufficientFundsInfo = false; + Future _onSend() async { + // todo send + } + Future _onConnectPressed() async { bool canPop = false; unawaited( @@ -63,7 +67,7 @@ class _PaynymDetailsPopupState extends ConsumerState { .getManager(widget.walletId) .wallet as DogecoinWallet; - if (wallet.hasConnected(widget.accountLite.code)) { + if (await wallet.hasConnected(widget.accountLite.code)) { canPop = true; Navigator.of(context).pop(); // TODO show info popup @@ -136,6 +140,9 @@ class _PaynymDetailsPopupState extends ConsumerState { @override Widget build(BuildContext context) { + final wallet = ref.watch(walletsChangeNotifierProvider.select( + (value) => value.getManager(widget.walletId).wallet as DogecoinWallet)); + return DesktopDialog( maxWidth: MediaQuery.of(context).size.width - 32, maxHeight: double.infinity, @@ -168,20 +175,49 @@ class _PaynymDetailsPopupState extends ConsumerState { ), ], ), - PrimaryButton( - label: "Connect", - buttonHeight: ButtonHeight.l, - icon: SvgPicture.asset( - Assets.svg.circlePlusFilled, - width: 10, - height: 10, - color: Theme.of(context) - .extension()! - .buttonTextPrimary, - ), - iconSpacing: 4, - width: 86, - onPressed: _onConnectPressed, + FutureBuilder( + future: wallet.hasConnected(widget.accountLite.code), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + if (snapshot.data!) { + return PrimaryButton( + label: "Send", + buttonHeight: ButtonHeight.s, + icon: SvgPicture.asset( + Assets.svg.circleArrowUpRight, + width: 16, + height: 16, + color: Theme.of(context) + .extension()! + .buttonTextPrimary, + ), + iconSpacing: 6, + onPressed: _onSend, + ); + } else { + return PrimaryButton( + label: "Connect", + buttonHeight: ButtonHeight.s, + icon: SvgPicture.asset( + Assets.svg.circlePlusFilled, + width: 16, + height: 16, + color: Theme.of(context) + .extension()! + .buttonTextPrimary, + ), + iconSpacing: 6, + onPressed: _onConnectPressed, + ); + } + } else { + return const SizedBox( + height: 100, + child: LoadingIndicator(), + ); + } + }, ), ], ), diff --git a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart index 4e69a7586..ac33ce475 100644 --- a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart +++ b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart @@ -63,7 +63,7 @@ class _PaynymDetailsPopupState extends ConsumerState { .getManager(widget.walletId) .wallet as DogecoinWallet; - if (wallet.hasConnected(widget.accountLite.code)) { + if (await wallet.hasConnected(widget.accountLite.code)) { canPop = true; Navigator.of(context, rootNavigator: true).pop(); // TODO show info popup @@ -187,40 +187,53 @@ class _PaynymDetailsPopupState extends ConsumerState { ), Row( children: [ - if (!wallet.hasConnected(widget.accountLite.code)) - Expanded( - child: PrimaryButton( - label: "Connect", - buttonHeight: ButtonHeight.s, - icon: SvgPicture.asset( - Assets.svg.circlePlusFilled, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .buttonTextPrimary, - ), - iconSpacing: 6, - onPressed: _onConnectPressed, - ), - ), - if (wallet.hasConnected(widget.accountLite.code)) - Expanded( - child: PrimaryButton( - label: "Send", - buttonHeight: ButtonHeight.s, - icon: SvgPicture.asset( - Assets.svg.circleArrowUpRight, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .buttonTextPrimary, - ), - iconSpacing: 6, - onPressed: _onSend, - ), + Expanded( + child: FutureBuilder( + future: wallet.hasConnected(widget.accountLite.code), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + if (snapshot.data!) { + return PrimaryButton( + label: "Send", + buttonHeight: ButtonHeight.s, + icon: SvgPicture.asset( + Assets.svg.circleArrowUpRight, + width: 16, + height: 16, + color: Theme.of(context) + .extension()! + .buttonTextPrimary, + ), + iconSpacing: 6, + onPressed: _onSend, + ); + } else { + return PrimaryButton( + label: "Connect", + buttonHeight: ButtonHeight.s, + icon: SvgPicture.asset( + Assets.svg.circlePlusFilled, + width: 16, + height: 16, + color: Theme.of(context) + .extension()! + .buttonTextPrimary, + ), + iconSpacing: 6, + onPressed: _onConnectPressed, + ); + } + } else { + return const SizedBox( + height: 100, + child: LoadingIndicator(), + ); + } + }, ), + ), const SizedBox( width: 20, ), From 2259e15da88798ddf0c3f0c766e77aecace0d999 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 15:39:19 -0600 Subject: [PATCH 10/55] re enable paynym --- lib/utilities/enums/coin_enum.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index 2f952651d..a517992de 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -190,8 +190,7 @@ extension CoinExt on Coin { case Coin.dogecoin: case Coin.dogecoinTestNet: - // return true; - return false; + return true; } } From 6498e1926cbaa3284acb8e2faf88808d547e6a29 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 15:42:39 -0600 Subject: [PATCH 11/55] size fixes --- .../paynym/dialogs/paynym_details_popup.dart | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/pages/paynym/dialogs/paynym_details_popup.dart b/lib/pages/paynym/dialogs/paynym_details_popup.dart index 5150d9bb2..295eff134 100644 --- a/lib/pages/paynym/dialogs/paynym_details_popup.dart +++ b/lib/pages/paynym/dialogs/paynym_details_popup.dart @@ -183,37 +183,39 @@ class _PaynymDetailsPopupState extends ConsumerState { if (snapshot.data!) { return PrimaryButton( label: "Send", - buttonHeight: ButtonHeight.s, + buttonHeight: ButtonHeight.l, icon: SvgPicture.asset( Assets.svg.circleArrowUpRight, - width: 16, - height: 16, + width: 10, + height: 10, color: Theme.of(context) .extension()! .buttonTextPrimary, ), - iconSpacing: 6, + iconSpacing: 4, + width: 86, onPressed: _onSend, ); } else { return PrimaryButton( label: "Connect", - buttonHeight: ButtonHeight.s, + buttonHeight: ButtonHeight.l, icon: SvgPicture.asset( Assets.svg.circlePlusFilled, - width: 16, - height: 16, + width: 10, + height: 10, color: Theme.of(context) .extension()! .buttonTextPrimary, ), - iconSpacing: 6, + iconSpacing: 4, + width: 86, onPressed: _onConnectPressed, ); } } else { return const SizedBox( - height: 100, + height: 32, child: LoadingIndicator(), ); } From 6253652c21cfe4d175e0ea2898585a1cdeb821c8 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 23 Jan 2023 16:11:24 -0600 Subject: [PATCH 12/55] detect paynym notification transactions --- lib/services/coins/coin_paynym_extension.dart | 62 ++++++++++++++++--- .../coins/dogecoin/dogecoin_wallet.dart | 6 +- lib/services/mixins/electrum_x_parsing.dart | 23 ++++--- 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index 2ad0e4475..b2ccfda9e 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -28,7 +28,7 @@ extension PayNym on DogecoinWallet { return root; } - // fetch or generate this wallet's bip47 payment code + /// fetch or generate this wallet's bip47 payment code Future getPaymentCode() async { final address = await db .getAddresses(walletId) @@ -75,7 +75,7 @@ extension PayNym on DogecoinWallet { } void preparePaymentCodeSend(PaymentCode pCode) async { - if (!hasConnected(pCode.notificationAddress())) { + if (!(await hasConnected(pCode.notificationAddress()))) { throw PaynymSendException("No notification transaction sent to $pCode"); } else { final root = await getRootNode(mnemonic: await mnemonic); @@ -433,12 +433,56 @@ extension PayNym on DogecoinWallet { } } - bool hasConnected(String paymentCodeString) { - return db - .getTransactions(walletId) - .filter() - .address((q) => q.valueEqualTo(paymentCodeString)) - .countSync() > - 0; + // TODO optimize + Future hasConnected(String paymentCodeString) async { + final myCode = await getPaymentCode(); + final myNotificationAddress = myCode.notificationAddress(); + + final txns = await db + .getTransactions(walletId) + .filter() + .subTypeEqualTo(TransactionSubType.bip47Notification) + .findAll(); + + for (final tx in txns) { + if (tx.address.value?.value == myNotificationAddress) { + return true; + } + + final blindedCode = + tx.outputs.elementAt(1).scriptPubKeyAsm!.split(" ")[1]; + + final designatedInput = tx.inputs.first; + + final txPoint = designatedInput.txid.fromHex.toList(); + final txPointIndex = designatedInput.vout; + + final rev = Uint8List(txPoint.length + 4); + Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); + final buffer = rev.buffer.asByteData(); + buffer.setUint32(txPoint.length, txPointIndex, Endian.little); + + final pubKey = designatedInput.scriptSigAsm!.split(" ")[1].fromHex; + + final root = await getRootNode(mnemonic: await mnemonic); + final myPrivateKey = + root.derivePath(kPaynymDerivePath).derive(0).privateKey!; + + final S = SecretPoint(myPrivateKey, pubKey); + + final mask = PaymentCode.getMask(S.ecdhSecret(), rev); + + final unBlindedPayload = PaymentCode.blind(blindedCode.fromHex, mask); + + final unBlindedPaymentCode = + PaymentCode.initFromPayload(unBlindedPayload); + + if (paymentCodeString == unBlindedPaymentCode.toString()) { + return true; + } + } + + // otherwise return no + return false; } } diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 7d0fdea6f..c47ad8947 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -1162,10 +1162,8 @@ class DogecoinWallet extends CoinServiceAPI .not() .typeEqualTo(isar_models.AddressType.nonWallet) .and() - .group((q) => q - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .or() - .subTypeEqualTo(isar_models.AddressSubType.change)) + .not() + .subTypeEqualTo(isar_models.AddressSubType.nonWallet) .findAll(); return allAddresses; } diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart index 49f28a50c..b9b815594 100644 --- a/lib/services/mixins/electrum_x_parsing.dart +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -1,3 +1,4 @@ +import 'package:bip47/src/util.dart'; import 'package:decimal/decimal.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; @@ -148,10 +149,6 @@ mixin ElectrumXParsing { amount = amountReceivedInWallet; } - bool isNotificationTx = coin.hasPaynymSupport && - type == TransactionType.incoming && - transactionAddress.subType == AddressSubType.paynymNotification; - List outs = []; List ins = []; @@ -188,15 +185,27 @@ mixin ElectrumXParsing { outs.add(output); } + TransactionSubType txSubType = TransactionSubType.none; + if (coin.hasPaynymSupport && outs.length > 1) { + List? scriptChunks = outs[1].scriptPubKeyAsm?.split(" "); + if (scriptChunks?.length == 2 && scriptChunks?[0] == "OP_RETURN") { + final blindedPaymentCode = scriptChunks![1]; + final bytes = blindedPaymentCode.fromHex; + + // https://en.bitcoin.it/wiki/BIP_0047#Sending + if (bytes.length == 80 && bytes.first == 1) { + txSubType = TransactionSubType.bip47Notification; + } + } + } + final tx = Transaction( walletId: walletId, txid: txData["txid"] as String, timestamp: txData["blocktime"] as int? ?? (DateTime.now().millisecondsSinceEpoch ~/ 1000), type: type, - subType: isNotificationTx - ? TransactionSubType.bip47Notification - : TransactionSubType.none, + subType: txSubType, amount: amount, fee: fee, height: txData["height"] as int?, From 83c0beb2ee03aa6a47c03b532997570226f77f15 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 24 Jan 2023 15:29:45 -0600 Subject: [PATCH 13/55] disable libmonero tests in sw --- .../coins/monero/monero_wallet_test.dart | 449 +++++------ .../coins/wownero/wownero_wallet_test.dart | 727 +++++++++--------- 2 files changed, 591 insertions(+), 585 deletions(-) diff --git a/test/services/coins/monero/monero_wallet_test.dart b/test/services/coins/monero/monero_wallet_test.dart index 4f45c4224..d33c1b460 100644 --- a/test/services/coins/monero/monero_wallet_test.dart +++ b/test/services/coins/monero/monero_wallet_test.dart @@ -1,228 +1,231 @@ import 'dart:core'; -import 'dart:io'; -import 'dart:math'; - -import 'package:cw_core/node.dart'; -import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/wallet_service.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cw_monero/monero_wallet.dart'; -import 'package:flutter_libmonero/core/key_service.dart'; -import 'package:flutter_libmonero/core/wallet_creation_service.dart'; -import 'package:flutter_libmonero/monero/monero.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:hive/hive.dart'; -import 'package:hive_test/hive_test.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:stackwallet/services/wallets.dart'; -import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; - -import 'monero_wallet_test_data.dart'; - -FakeSecureStorage? storage; -WalletService? walletService; -KeyService? keysStorage; -MoneroWalletBase? walletBase; -late WalletCreationService _walletCreationService; -dynamic _walletInfoSource; -Wallets? walletsService; - -String path = ''; - -String name = 'namee${Random().nextInt(10000000)}'; -int nettype = 0; -WalletType type = WalletType.monero; +// import 'dart:io'; +// import 'dart:math'; +// +// TODO: move these tests to libmonero +// TODO: use temp dir for wallets testing and not production location +// +// import 'package:cw_core/node.dart'; +// import 'package:cw_core/unspent_coins_info.dart'; +// import 'package:cw_core/wallet_base.dart'; +// import 'package:cw_core/wallet_credentials.dart'; +// import 'package:cw_core/wallet_info.dart'; +// import 'package:cw_core/wallet_service.dart'; +// import 'package:cw_core/wallet_type.dart'; +// import 'package:cw_monero/monero_wallet.dart'; +// import 'package:flutter_libmonero/core/key_service.dart'; +// import 'package:flutter_libmonero/core/wallet_creation_service.dart'; +// import 'package:flutter_libmonero/monero/monero.dart'; +// import 'package:flutter_test/flutter_test.dart'; +// import 'package:hive/hive.dart'; +// import 'package:hive_test/hive_test.dart'; +// import 'package:path_provider/path_provider.dart'; +// import 'package:stackwallet/services/wallets.dart'; +// import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; +// +// import 'monero_wallet_test_data.dart'; +// +// FakeSecureStorage? storage; +// WalletService? walletService; +// KeyService? keysStorage; +// MoneroWalletBase? walletBase; +// late WalletCreationService _walletCreationService; +// dynamic _walletInfoSource; +// Wallets? walletsService; +// +// String path = ''; +// +// String name = 'namee${Random().nextInt(10000000)}'; +// int nettype = 0; +// WalletType type = WalletType.monero; void main() async { - storage = FakeSecureStorage(); - keysStorage = KeyService(storage!); - WalletInfo walletInfo = WalletInfo.external( - id: '', - name: '', - type: type, - isRecovery: false, - restoreHeight: 0, - date: DateTime.now(), - path: '', - address: '', - dirPath: ''); - late WalletCredentials credentials; - - monero.onStartup(); - - bool hiveAdaptersRegistered = false; - - group("Mainnet tests", () { - setUp(() async { - await setUpTestHive(); - if (!hiveAdaptersRegistered) { - hiveAdaptersRegistered = true; - - Hive.registerAdapter(NodeAdapter()); - Hive.registerAdapter(WalletInfoAdapter()); - Hive.registerAdapter(WalletTypeAdapter()); - Hive.registerAdapter(UnspentCoinsInfoAdapter()); - - final wallets = await Hive.openBox('wallets'); - await wallets.put('currentWalletName', name); - - _walletInfoSource = await Hive.openBox(WalletInfo.boxName); - walletService = monero - .createMoneroWalletService(_walletInfoSource as Box); - } - - try { - // if (name?.isEmpty ?? true) { - // name = await generateName(); - // } - final dirPath = await pathForWalletDir(name: name, type: type); - path = await pathForWallet(name: name, type: type); - credentials = - // // creating a new wallet - // monero.createMoneroNewWalletCredentials( - // name: name, language: "English"); - // restoring a previous wallet - monero.createMoneroRestoreWalletFromSeedCredentials( - name: name, height: 2580000, mnemonic: testMnemonic); - - walletInfo = WalletInfo.external( - id: WalletBase.idFor(name, type), - name: name, - type: type, - isRecovery: false, - restoreHeight: credentials.height ?? 0, - date: DateTime.now(), - path: path, - address: "", - dirPath: dirPath); - credentials.walletInfo = walletInfo; - - _walletCreationService = WalletCreationService( - secureStorage: storage, - walletService: walletService, - keyService: keysStorage, - ); - _walletCreationService.changeWalletType(); - } catch (e, s) { - print(e); - print(s); - } - }); - - test("Test mainnet address generation from seed", () async { - final wallet = await - // _walletCreationService.create(credentials); - _walletCreationService.restoreFromSeed(credentials); - walletInfo.address = wallet.walletAddresses.address; - //print(walletInfo.address); - - await _walletInfoSource.add(walletInfo); - walletBase?.close(); - walletBase = wallet as MoneroWalletBase; - //print("${walletBase?.seed}"); - - expect(await walletBase!.validateAddress(walletInfo.address ?? ''), true); - - // print(walletBase); - // loggerPrint(walletBase.toString()); - // loggerPrint("name: ${walletBase!.name} seed: ${walletBase!.seed} id: " - // "${walletBase!.id} walletinfo: ${toStringForinfo(walletBase!.walletInfo)} type: ${walletBase!.type} balance: " - // "${walletBase!.balance.entries.first.value.available} currency: ${walletBase!.currency}"); - - expect(walletInfo.address, mainnetTestData[0][0]); - expect(walletBase!.getTransactionAddress(0, 0), mainnetTestData[0][0]); - expect(walletBase!.getTransactionAddress(0, 1), mainnetTestData[0][1]); - expect(walletBase!.getTransactionAddress(0, 2), mainnetTestData[0][2]); - expect(walletBase!.getTransactionAddress(1, 0), mainnetTestData[1][0]); - expect(walletBase!.getTransactionAddress(1, 1), mainnetTestData[1][1]); - expect(walletBase!.getTransactionAddress(1, 2), mainnetTestData[1][2]); - - expect(walletBase!.validateAddress(''), false); - expect( - walletBase!.validateAddress( - '4AeRgkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gp4nn'), - true); - expect( - walletBase!.validateAddress( - '4asdfkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gpjkl'), - false); - expect( - walletBase!.validateAddress( - '8AeRgkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gp4nn'), - false); - expect( - walletBase!.validateAddress( - '84kYPuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenvHy'), - true); - expect( - walletBase!.validateAddress( - '8asdfuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenjkl'), - false); - expect( - walletBase!.validateAddress( - '44kYPuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenvHy'), - false); - }); - }); - /* - // Not needed; only folder created, wallet files not saved yet. TODO test saving and deleting wallet files and make sure to clean up leftover folder afterwards - group("Mainnet wallet deletion test", () { - test("Test mainnet wallet existence", () { - expect(monero_wallet_manager.isWalletExistSync(path: path), true); - }); - - test("Test mainnet wallet deletion", () { - // Remove wallet from wallet service - walletService?.remove(name); - walletsService?.removeWallet(walletId: name); - expect(monero_wallet_manager.isWalletExistSync(path: path), false); - }); - }); - - group("Mainnet node tests", () { - test("Test mainnet node connection", () async { - await walletBase?.connectToNode( - node: Node( - uri: "monero-stagenet.stackwallet.com:38081", - type: WalletType.moneroStageNet)); - await walletBase!.rescan( - height: - credentials.height); // Probably shouldn't be rescanning from 0... - await walletBase!.getNodeHeight(); - int height = await walletBase!.getNodeHeight(); - print('height: $height'); - bool connected = await walletBase!.isConnected(); - print('connected: $connected'); - - //expect... - }); - }); - */ - - // TODO test deletion of wallets ... and delete them + // storage = FakeSecureStorage(); + // keysStorage = KeyService(storage!); + // WalletInfo walletInfo = WalletInfo.external( + // id: '', + // name: '', + // type: type, + // isRecovery: false, + // restoreHeight: 0, + // date: DateTime.now(), + // path: '', + // address: '', + // dirPath: ''); + // late WalletCredentials credentials; + // + // monero.onStartup(); + // + // bool hiveAdaptersRegistered = false; + // + // group("Mainnet tests", () { + // setUp(() async { + // await setUpTestHive(); + // if (!hiveAdaptersRegistered) { + // hiveAdaptersRegistered = true; + // + // Hive.registerAdapter(NodeAdapter()); + // Hive.registerAdapter(WalletInfoAdapter()); + // Hive.registerAdapter(WalletTypeAdapter()); + // Hive.registerAdapter(UnspentCoinsInfoAdapter()); + // + // final wallets = await Hive.openBox('wallets'); + // await wallets.put('currentWalletName', name); + // + // _walletInfoSource = await Hive.openBox(WalletInfo.boxName); + // walletService = monero + // .createMoneroWalletService(_walletInfoSource as Box); + // } + // + // try { + // // if (name?.isEmpty ?? true) { + // // name = await generateName(); + // // } + // final dirPath = await pathForWalletDir(name: name, type: type); + // path = await pathForWallet(name: name, type: type); + // credentials = + // // // creating a new wallet + // // monero.createMoneroNewWalletCredentials( + // // name: name, language: "English"); + // // restoring a previous wallet + // monero.createMoneroRestoreWalletFromSeedCredentials( + // name: name, height: 2580000, mnemonic: testMnemonic); + // + // walletInfo = WalletInfo.external( + // id: WalletBase.idFor(name, type), + // name: name, + // type: type, + // isRecovery: false, + // restoreHeight: credentials.height ?? 0, + // date: DateTime.now(), + // path: path, + // address: "", + // dirPath: dirPath); + // credentials.walletInfo = walletInfo; + // + // _walletCreationService = WalletCreationService( + // secureStorage: storage, + // walletService: walletService, + // keyService: keysStorage, + // ); + // _walletCreationService.changeWalletType(); + // } catch (e, s) { + // print(e); + // print(s); + // } + // }); + // + // test("Test mainnet address generation from seed", () async { + // final wallet = await + // // _walletCreationService.create(credentials); + // _walletCreationService.restoreFromSeed(credentials); + // walletInfo.address = wallet.walletAddresses.address; + // //print(walletInfo.address); + // + // await _walletInfoSource.add(walletInfo); + // walletBase?.close(); + // walletBase = wallet as MoneroWalletBase; + // //print("${walletBase?.seed}"); + // + // expect(await walletBase!.validateAddress(walletInfo.address ?? ''), true); + // + // // print(walletBase); + // // loggerPrint(walletBase.toString()); + // // loggerPrint("name: ${walletBase!.name} seed: ${walletBase!.seed} id: " + // // "${walletBase!.id} walletinfo: ${toStringForinfo(walletBase!.walletInfo)} type: ${walletBase!.type} balance: " + // // "${walletBase!.balance.entries.first.value.available} currency: ${walletBase!.currency}"); + // + // expect(walletInfo.address, mainnetTestData[0][0]); + // expect(walletBase!.getTransactionAddress(0, 0), mainnetTestData[0][0]); + // expect(walletBase!.getTransactionAddress(0, 1), mainnetTestData[0][1]); + // expect(walletBase!.getTransactionAddress(0, 2), mainnetTestData[0][2]); + // expect(walletBase!.getTransactionAddress(1, 0), mainnetTestData[1][0]); + // expect(walletBase!.getTransactionAddress(1, 1), mainnetTestData[1][1]); + // expect(walletBase!.getTransactionAddress(1, 2), mainnetTestData[1][2]); + // + // expect(walletBase!.validateAddress(''), false); + // expect( + // walletBase!.validateAddress( + // '4AeRgkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gp4nn'), + // true); + // expect( + // walletBase!.validateAddress( + // '4asdfkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gpjkl'), + // false); + // expect( + // walletBase!.validateAddress( + // '8AeRgkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gp4nn'), + // false); + // expect( + // walletBase!.validateAddress( + // '84kYPuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenvHy'), + // true); + // expect( + // walletBase!.validateAddress( + // '8asdfuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenjkl'), + // false); + // expect( + // walletBase!.validateAddress( + // '44kYPuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenvHy'), + // false); + // }); + // }); + // /* + // // Not needed; only folder created, wallet files not saved yet. TODO test saving and deleting wallet files and make sure to clean up leftover folder afterwards + // group("Mainnet wallet deletion test", () { + // test("Test mainnet wallet existence", () { + // expect(monero_wallet_manager.isWalletExistSync(path: path), true); + // }); + // + // test("Test mainnet wallet deletion", () { + // // Remove wallet from wallet service + // walletService?.remove(name); + // walletsService?.removeWallet(walletId: name); + // expect(monero_wallet_manager.isWalletExistSync(path: path), false); + // }); + // }); + // + // group("Mainnet node tests", () { + // test("Test mainnet node connection", () async { + // await walletBase?.connectToNode( + // node: Node( + // uri: "monero-stagenet.stackwallet.com:38081", + // type: WalletType.moneroStageNet)); + // await walletBase!.rescan( + // height: + // credentials.height); // Probably shouldn't be rescanning from 0... + // await walletBase!.getNodeHeight(); + // int height = await walletBase!.getNodeHeight(); + // print('height: $height'); + // bool connected = await walletBase!.isConnected(); + // print('connected: $connected'); + // + // //expect... + // }); + // }); + // */ + // + // // TODO test deletion of wallets ... and delete them } -Future pathForWalletDir( - {required String name, required WalletType type}) async { - Directory root = (await getApplicationDocumentsDirectory()); - if (Platform.isIOS) { - root = (await getLibraryDirectory()); - } - final prefix = walletTypeToString(type).toLowerCase(); - final walletsDir = Directory('${root.path}/wallets'); - final walletDire = Directory('${walletsDir.path}/$prefix/$name'); - - if (!walletDire.existsSync()) { - walletDire.createSync(recursive: true); - } - - return walletDire.path; -} - -Future pathForWallet( - {required String name, required WalletType type}) async => - await pathForWalletDir(name: name, type: type) - .then((path) => '$path/$name'); +// Future pathForWalletDir( +// {required String name, required WalletType type}) async { +// Directory root = (await getApplicationDocumentsDirectory()); +// if (Platform.isIOS) { +// root = (await getLibraryDirectory()); +// } +// final prefix = walletTypeToString(type).toLowerCase(); +// final walletsDir = Directory('${root.path}/wallets'); +// final walletDire = Directory('${walletsDir.path}/$prefix/$name'); +// +// if (!walletDire.existsSync()) { +// walletDire.createSync(recursive: true); +// } +// +// return walletDire.path; +// } +// +// Future pathForWallet( +// {required String name, required WalletType type}) async => +// await pathForWalletDir(name: name, type: type) +// .then((path) => '$path/$name'); diff --git a/test/services/coins/wownero/wownero_wallet_test.dart b/test/services/coins/wownero/wownero_wallet_test.dart index 42d9e0696..a14fbf3ad 100644 --- a/test/services/coins/wownero/wownero_wallet_test.dart +++ b/test/services/coins/wownero/wownero_wallet_test.dart @@ -1,367 +1,370 @@ import 'dart:core'; -import 'dart:io'; -import 'dart:math'; - -import 'package:cw_core/node.dart'; -import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/wallet_service.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cw_wownero/wownero_wallet.dart'; -import 'package:flutter_libmonero/core/key_service.dart'; -import 'package:flutter_libmonero/core/wallet_creation_service.dart'; -import 'package:flutter_libmonero/wownero/wownero.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:hive/hive.dart'; -import 'package:hive_test/hive_test.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; - -import 'wownero_wallet_test_data.dart'; - -FakeSecureStorage? storage; -WalletService? walletService; -KeyService? keysStorage; -WowneroWalletBase? walletBase; -late WalletCreationService _walletCreationService; -dynamic _walletInfoSource; - -String path = ''; - -String name = ''; -int nettype = 0; -WalletType type = WalletType.wownero; +// import 'dart:io'; +// import 'dart:math'; +// +// TODO: move these tests to libmonero +// TODO: use temp dir for wallets testing and not production location +// +// import 'package:cw_core/node.dart'; +// import 'package:cw_core/unspent_coins_info.dart'; +// import 'package:cw_core/wallet_base.dart'; +// import 'package:cw_core/wallet_credentials.dart'; +// import 'package:cw_core/wallet_info.dart'; +// import 'package:cw_core/wallet_service.dart'; +// import 'package:cw_core/wallet_type.dart'; +// import 'package:cw_wownero/wownero_wallet.dart'; +// import 'package:flutter_libmonero/core/key_service.dart'; +// import 'package:flutter_libmonero/core/wallet_creation_service.dart'; +// import 'package:flutter_libmonero/wownero/wownero.dart'; +// import 'package:flutter_test/flutter_test.dart'; +// import 'package:hive/hive.dart'; +// import 'package:hive_test/hive_test.dart'; +// import 'package:path_provider/path_provider.dart'; +// import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; +// +// import 'wownero_wallet_test_data.dart'; +// +// FakeSecureStorage? storage; +// WalletService? walletService; +// KeyService? keysStorage; +// WowneroWalletBase? walletBase; +// late WalletCreationService _walletCreationService; +// dynamic _walletInfoSource; +// +// String path = ''; +// +// String name = ''; +// int nettype = 0; +// WalletType type = WalletType.wownero; void main() async { - storage = FakeSecureStorage(); - keysStorage = KeyService(storage!); - WalletInfo walletInfo = WalletInfo.external( - id: '', - name: '', - type: type, - isRecovery: false, - restoreHeight: 0, - date: DateTime.now(), - path: '', - address: '', - dirPath: ''); - late WalletCredentials credentials; - - wownero.onStartup(); - - bool hiveAdaptersRegistered = false; - - group("Wownero 14 word seed generation", () { - setUp(() async { - await setUpTestHive(); - if (!hiveAdaptersRegistered) { - hiveAdaptersRegistered = true; - - Hive.registerAdapter(NodeAdapter()); - Hive.registerAdapter(WalletInfoAdapter()); - Hive.registerAdapter(WalletTypeAdapter()); - Hive.registerAdapter(UnspentCoinsInfoAdapter()); - - final wallets = await Hive.openBox('wallets'); - await wallets.put('currentWalletName', name); - - _walletInfoSource = await Hive.openBox(WalletInfo.boxName); - walletService = wownero - .createWowneroWalletService(_walletInfoSource as Box); - } - - bool hasThrown = false; - try { - name = 'namee${Random().nextInt(10000000)}'; - final dirPath = await pathForWalletDir(name: name, type: type); - path = await pathForWallet(name: name, type: type); - credentials = wownero.createWowneroNewWalletCredentials( - name: name, - language: "English", - seedWordsLength: 14); // TODO catch failure - - walletInfo = WalletInfo.external( - id: WalletBase.idFor(name, type), - name: name, - type: type, - isRecovery: false, - restoreHeight: credentials.height ?? 0, - date: DateTime.now(), - path: path, - address: "", - dirPath: dirPath); - credentials.walletInfo = walletInfo; - - _walletCreationService = WalletCreationService( - secureStorage: storage, - walletService: walletService, - keyService: keysStorage, - ); - _walletCreationService.changeWalletType(); - } catch (e, s) { - print(e); - print(s); - hasThrown = true; - } - expect(hasThrown, false); - }); - - test("Wownero 14 word seed address generation", () async { - final wallet = await _walletCreationService.create(credentials); - // TODO validate mnemonic - walletInfo.address = wallet.walletAddresses.address; - - bool hasThrown = false; - try { - await _walletInfoSource.add(walletInfo); - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - - expect( - await walletBase! - .validateAddress(wallet.walletAddresses.address ?? ''), - true); - } catch (_) { - hasThrown = true; - } - expect(hasThrown, false); - - // Address validation - expect(walletBase!.validateAddress(''), false); - expect( - walletBase!.validateAddress( - 'Wo3jmHvTMLwE6h29fpgcb8PbJSpaKuqM7XTXVfiiu8bLCZsJvrQCbQSJR48Vo3BWNQKsMsXZ4VixndXTH25QtorC27NCjmsEi'), - true); - expect( - walletBase!.validateAddress( - 'WasdfHvTMLwE6h29fpgcb8PbJSpaKuqM7XTXVfiiu8bLCZsJvrQCbQSJR48Vo3BWNQKsMsXZ4VixndXTH25QtorC27NCjmjkl'), - false); - - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - }); - - // TODO delete left over wallet file with name: name - }); - - group("Wownero 14 word seed restoration", () { - setUp(() async { - bool hasThrown = false; - try { - name = 'namee${Random().nextInt(10000000)}'; - final dirPath = await pathForWalletDir(name: name, type: type); - path = await pathForWallet(name: name, type: type); - credentials = wownero.createWowneroRestoreWalletFromSeedCredentials( - name: name, - height: 465760, - mnemonic: testMnemonic14); // TODO catch failure - - walletInfo = WalletInfo.external( - id: WalletBase.idFor(name, type), - name: name, - type: type, - isRecovery: false, - restoreHeight: credentials.height ?? 0, - date: DateTime.now(), - path: path, - address: "", - dirPath: dirPath); - credentials.walletInfo = walletInfo; - - _walletCreationService = WalletCreationService( - secureStorage: storage, - walletService: walletService, - keyService: keysStorage, - ); - _walletCreationService.changeWalletType(); - } catch (e, s) { - print(e); - print(s); - hasThrown = true; - } - expect(hasThrown, false); - }); - - test("Wownero 14 word seed address generation", () async { - final wallet = await _walletCreationService.restoreFromSeed(credentials); - walletInfo.address = wallet.walletAddresses.address; - - bool hasThrown = false; - try { - await _walletInfoSource.add(walletInfo); - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - - expect(walletInfo.address, mainnetTestData14[0][0]); - expect( - walletBase!.getTransactionAddress(0, 0), mainnetTestData14[0][0]); - expect( - walletBase!.getTransactionAddress(0, 1), mainnetTestData14[0][1]); - expect( - walletBase!.getTransactionAddress(0, 2), mainnetTestData14[0][2]); - expect( - walletBase!.getTransactionAddress(1, 0), mainnetTestData14[1][0]); - expect( - walletBase!.getTransactionAddress(1, 1), mainnetTestData14[1][1]); - expect( - walletBase!.getTransactionAddress(1, 2), mainnetTestData14[1][2]); - } catch (_) { - hasThrown = true; - } - expect(hasThrown, false); - - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - }); - - // TODO delete left over wallet file with name: name - }); - - group("Wownero 25 word seed generation", () { - setUp(() async { - bool hasThrown = false; - try { - name = 'namee${Random().nextInt(10000000)}'; - final dirPath = await pathForWalletDir(name: name, type: type); - path = await pathForWallet(name: name, type: type); - credentials = wownero.createWowneroNewWalletCredentials( - name: name, - language: "English", - seedWordsLength: 25); // TODO catch failure - - walletInfo = WalletInfo.external( - id: WalletBase.idFor(name, type), - name: name, - type: type, - isRecovery: false, - restoreHeight: credentials.height ?? 0, - date: DateTime.now(), - path: path, - address: "", - dirPath: dirPath); - credentials.walletInfo = walletInfo; - - _walletCreationService = WalletCreationService( - secureStorage: storage, - walletService: walletService, - keyService: keysStorage, - ); - _walletCreationService.changeWalletType(); - } catch (e, s) { - print(e); - print(s); - hasThrown = true; - } - expect(hasThrown, false); - }); - - test("Wownero 25 word seed address generation", () async { - final wallet = await _walletCreationService.create(credentials); - // TODO validate mnemonic - walletInfo.address = wallet.walletAddresses.address; - - bool hasThrown = false; - try { - await _walletInfoSource.add(walletInfo); - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - - // TODO validate - //expect(walletInfo.address, mainnetTestData14[0][0]); - } catch (_) { - hasThrown = true; - } - expect(hasThrown, false); - - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - }); - - // TODO delete left over wallet file with name: name - }); - - group("Wownero 25 word seed restoration", () { - setUp(() async { - bool hasThrown = false; - try { - name = 'namee${Random().nextInt(10000000)}'; - final dirPath = await pathForWalletDir(name: name, type: type); - path = await pathForWallet(name: name, type: type); - credentials = wownero.createWowneroRestoreWalletFromSeedCredentials( - name: name, - height: 465760, - mnemonic: testMnemonic25); // TODO catch failure - - walletInfo = WalletInfo.external( - id: WalletBase.idFor(name, type), - name: name, - type: type, - isRecovery: false, - restoreHeight: credentials.height ?? 0, - date: DateTime.now(), - path: path, - address: "", - dirPath: dirPath); - credentials.walletInfo = walletInfo; - - _walletCreationService = WalletCreationService( - secureStorage: storage, - walletService: walletService, - keyService: keysStorage, - ); - _walletCreationService.changeWalletType(); - } catch (e, s) { - print(e); - print(s); - hasThrown = true; - } - expect(hasThrown, false); - }); - - test("Wownero 25 word seed address generation", () async { - final wallet = await _walletCreationService.restoreFromSeed(credentials); - walletInfo.address = wallet.walletAddresses.address; - - bool hasThrown = false; - try { - await _walletInfoSource.add(walletInfo); - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - - expect(walletInfo.address, mainnetTestData25[0][0]); - } catch (_) { - hasThrown = true; - } - expect(hasThrown, false); - - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - }); - - // TODO delete left over wallet file with name: name - }); + // storage = FakeSecureStorage(); + // keysStorage = KeyService(storage!); + // WalletInfo walletInfo = WalletInfo.external( + // id: '', + // name: '', + // type: type, + // isRecovery: false, + // restoreHeight: 0, + // date: DateTime.now(), + // path: '', + // address: '', + // dirPath: ''); + // late WalletCredentials credentials; + // + // wownero.onStartup(); + // + // bool hiveAdaptersRegistered = false; + // + // group("Wownero 14 word seed generation", () { + // setUp(() async { + // await setUpTestHive(); + // if (!hiveAdaptersRegistered) { + // hiveAdaptersRegistered = true; + // + // Hive.registerAdapter(NodeAdapter()); + // Hive.registerAdapter(WalletInfoAdapter()); + // Hive.registerAdapter(WalletTypeAdapter()); + // Hive.registerAdapter(UnspentCoinsInfoAdapter()); + // + // final wallets = await Hive.openBox('wallets'); + // await wallets.put('currentWalletName', name); + // + // _walletInfoSource = await Hive.openBox(WalletInfo.boxName); + // walletService = wownero + // .createWowneroWalletService(_walletInfoSource as Box); + // } + // + // bool hasThrown = false; + // try { + // name = 'namee${Random().nextInt(10000000)}'; + // final dirPath = await pathForWalletDir(name: name, type: type); + // path = await pathForWallet(name: name, type: type); + // credentials = wownero.createWowneroNewWalletCredentials( + // name: name, + // language: "English", + // seedWordsLength: 14); // TODO catch failure + // + // walletInfo = WalletInfo.external( + // id: WalletBase.idFor(name, type), + // name: name, + // type: type, + // isRecovery: false, + // restoreHeight: credentials.height ?? 0, + // date: DateTime.now(), + // path: path, + // address: "", + // dirPath: dirPath); + // credentials.walletInfo = walletInfo; + // + // _walletCreationService = WalletCreationService( + // secureStorage: storage, + // walletService: walletService, + // keyService: keysStorage, + // ); + // _walletCreationService.changeWalletType(); + // } catch (e, s) { + // print(e); + // print(s); + // hasThrown = true; + // } + // expect(hasThrown, false); + // }); + // + // test("Wownero 14 word seed address generation", () async { + // final wallet = await _walletCreationService.create(credentials); + // // TODO validate mnemonic + // walletInfo.address = wallet.walletAddresses.address; + // + // bool hasThrown = false; + // try { + // await _walletInfoSource.add(walletInfo); + // walletBase?.close(); + // walletBase = wallet as WowneroWalletBase; + // + // expect( + // await walletBase! + // .validateAddress(wallet.walletAddresses.address ?? ''), + // true); + // } catch (_) { + // hasThrown = true; + // } + // expect(hasThrown, false); + // + // // Address validation + // expect(walletBase!.validateAddress(''), false); + // expect( + // walletBase!.validateAddress( + // 'Wo3jmHvTMLwE6h29fpgcb8PbJSpaKuqM7XTXVfiiu8bLCZsJvrQCbQSJR48Vo3BWNQKsMsXZ4VixndXTH25QtorC27NCjmsEi'), + // true); + // expect( + // walletBase!.validateAddress( + // 'WasdfHvTMLwE6h29fpgcb8PbJSpaKuqM7XTXVfiiu8bLCZsJvrQCbQSJR48Vo3BWNQKsMsXZ4VixndXTH25QtorC27NCjmjkl'), + // false); + // + // walletBase?.close(); + // walletBase = wallet as WowneroWalletBase; + // }); + // + // // TODO delete left over wallet file with name: name + // }); + // + // group("Wownero 14 word seed restoration", () { + // setUp(() async { + // bool hasThrown = false; + // try { + // name = 'namee${Random().nextInt(10000000)}'; + // final dirPath = await pathForWalletDir(name: name, type: type); + // path = await pathForWallet(name: name, type: type); + // credentials = wownero.createWowneroRestoreWalletFromSeedCredentials( + // name: name, + // height: 465760, + // mnemonic: testMnemonic14); // TODO catch failure + // + // walletInfo = WalletInfo.external( + // id: WalletBase.idFor(name, type), + // name: name, + // type: type, + // isRecovery: false, + // restoreHeight: credentials.height ?? 0, + // date: DateTime.now(), + // path: path, + // address: "", + // dirPath: dirPath); + // credentials.walletInfo = walletInfo; + // + // _walletCreationService = WalletCreationService( + // secureStorage: storage, + // walletService: walletService, + // keyService: keysStorage, + // ); + // _walletCreationService.changeWalletType(); + // } catch (e, s) { + // print(e); + // print(s); + // hasThrown = true; + // } + // expect(hasThrown, false); + // }); + // + // test("Wownero 14 word seed address generation", () async { + // final wallet = await _walletCreationService.restoreFromSeed(credentials); + // walletInfo.address = wallet.walletAddresses.address; + // + // bool hasThrown = false; + // try { + // await _walletInfoSource.add(walletInfo); + // walletBase?.close(); + // walletBase = wallet as WowneroWalletBase; + // + // expect(walletInfo.address, mainnetTestData14[0][0]); + // expect( + // walletBase!.getTransactionAddress(0, 0), mainnetTestData14[0][0]); + // expect( + // walletBase!.getTransactionAddress(0, 1), mainnetTestData14[0][1]); + // expect( + // walletBase!.getTransactionAddress(0, 2), mainnetTestData14[0][2]); + // expect( + // walletBase!.getTransactionAddress(1, 0), mainnetTestData14[1][0]); + // expect( + // walletBase!.getTransactionAddress(1, 1), mainnetTestData14[1][1]); + // expect( + // walletBase!.getTransactionAddress(1, 2), mainnetTestData14[1][2]); + // } catch (_) { + // hasThrown = true; + // } + // expect(hasThrown, false); + // + // walletBase?.close(); + // walletBase = wallet as WowneroWalletBase; + // }); + // + // // TODO delete left over wallet file with name: name + // }); + // + // group("Wownero 25 word seed generation", () { + // setUp(() async { + // bool hasThrown = false; + // try { + // name = 'namee${Random().nextInt(10000000)}'; + // final dirPath = await pathForWalletDir(name: name, type: type); + // path = await pathForWallet(name: name, type: type); + // credentials = wownero.createWowneroNewWalletCredentials( + // name: name, + // language: "English", + // seedWordsLength: 25); // TODO catch failure + // + // walletInfo = WalletInfo.external( + // id: WalletBase.idFor(name, type), + // name: name, + // type: type, + // isRecovery: false, + // restoreHeight: credentials.height ?? 0, + // date: DateTime.now(), + // path: path, + // address: "", + // dirPath: dirPath); + // credentials.walletInfo = walletInfo; + // + // _walletCreationService = WalletCreationService( + // secureStorage: storage, + // walletService: walletService, + // keyService: keysStorage, + // ); + // _walletCreationService.changeWalletType(); + // } catch (e, s) { + // print(e); + // print(s); + // hasThrown = true; + // } + // expect(hasThrown, false); + // }); + // + // test("Wownero 25 word seed address generation", () async { + // final wallet = await _walletCreationService.create(credentials); + // // TODO validate mnemonic + // walletInfo.address = wallet.walletAddresses.address; + // + // bool hasThrown = false; + // try { + // await _walletInfoSource.add(walletInfo); + // walletBase?.close(); + // walletBase = wallet as WowneroWalletBase; + // + // // TODO validate + // //expect(walletInfo.address, mainnetTestData14[0][0]); + // } catch (_) { + // hasThrown = true; + // } + // expect(hasThrown, false); + // + // walletBase?.close(); + // walletBase = wallet as WowneroWalletBase; + // }); + // + // // TODO delete left over wallet file with name: name + // }); + // + // group("Wownero 25 word seed restoration", () { + // setUp(() async { + // bool hasThrown = false; + // try { + // name = 'namee${Random().nextInt(10000000)}'; + // final dirPath = await pathForWalletDir(name: name, type: type); + // path = await pathForWallet(name: name, type: type); + // credentials = wownero.createWowneroRestoreWalletFromSeedCredentials( + // name: name, + // height: 465760, + // mnemonic: testMnemonic25); // TODO catch failure + // + // walletInfo = WalletInfo.external( + // id: WalletBase.idFor(name, type), + // name: name, + // type: type, + // isRecovery: false, + // restoreHeight: credentials.height ?? 0, + // date: DateTime.now(), + // path: path, + // address: "", + // dirPath: dirPath); + // credentials.walletInfo = walletInfo; + // + // _walletCreationService = WalletCreationService( + // secureStorage: storage, + // walletService: walletService, + // keyService: keysStorage, + // ); + // _walletCreationService.changeWalletType(); + // } catch (e, s) { + // print(e); + // print(s); + // hasThrown = true; + // } + // expect(hasThrown, false); + // }); + // + // test("Wownero 25 word seed address generation", () async { + // final wallet = await _walletCreationService.restoreFromSeed(credentials); + // walletInfo.address = wallet.walletAddresses.address; + // + // bool hasThrown = false; + // try { + // await _walletInfoSource.add(walletInfo); + // walletBase?.close(); + // walletBase = wallet as WowneroWalletBase; + // + // expect(walletInfo.address, mainnetTestData25[0][0]); + // } catch (_) { + // hasThrown = true; + // } + // expect(hasThrown, false); + // + // walletBase?.close(); + // walletBase = wallet as WowneroWalletBase; + // }); + // + // // TODO delete left over wallet file with name: name + // }); } -Future pathForWalletDir( - {required String name, required WalletType type}) async { - Directory root = (await getApplicationDocumentsDirectory()); - if (Platform.isIOS) { - root = (await getLibraryDirectory()); - } - final prefix = walletTypeToString(type).toLowerCase(); - final walletsDir = Directory('${root.path}/wallets'); - final walletDire = Directory('${walletsDir.path}/$prefix/$name'); - - if (!walletDire.existsSync()) { - walletDire.createSync(recursive: true); - } - - return walletDire.path; -} - -Future pathForWallet( - {required String name, required WalletType type}) async => - await pathForWalletDir(name: name, type: type) - .then((path) => '$path/$name'); +// Future pathForWalletDir( +// {required String name, required WalletType type}) async { +// Directory root = (await getApplicationDocumentsDirectory()); +// if (Platform.isIOS) { +// root = (await getLibraryDirectory()); +// } +// final prefix = walletTypeToString(type).toLowerCase(); +// final walletsDir = Directory('${root.path}/wallets'); +// final walletDire = Directory('${walletsDir.path}/$prefix/$name'); +// +// if (!walletDire.existsSync()) { +// walletDire.createSync(recursive: true); +// } +// +// return walletDire.path; +// } +// +// Future pathForWallet( +// {required String name, required WalletType type}) async => +// await pathForWalletDir(name: name, type: type) +// .then((path) => '$path/$name'); From 37fa5e9d198badbc870fbbffca873a644e0fd128 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 24 Jan 2023 16:18:17 -0600 Subject: [PATCH 14/55] remove old file and add todos --- lib/services/coins/coin_paynym_extension.dart | 2 + lib/services/mixins/paynym_support.dart | 569 ------------------ 2 files changed, 2 insertions(+), 569 deletions(-) delete mode 100644 lib/services/mixins/paynym_support.dart diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index b2ccfda9e..8810621ec 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -64,6 +64,8 @@ extension PayNym on DogecoinWallet { final node = root.derivePath(kPaynymDerivePath); final pair = btc_dart.ECPair.fromPrivateKey(node.privateKey!, network: network); + // TODO: is pair same as priv key from node? + // todo: should this priv key be used or priv key of derive(0)? final signed = pair.sign(SHA256Digest().process(data)); return signed; } diff --git a/lib/services/mixins/paynym_support.dart b/lib/services/mixins/paynym_support.dart deleted file mode 100644 index 3bea5aee6..000000000 --- a/lib/services/mixins/paynym_support.dart +++ /dev/null @@ -1,569 +0,0 @@ -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:bip32/bip32.dart' as bip32; -import 'package:bip47/bip47.dart'; -import 'package:bip47/src/util.dart'; -import 'package:bitcoindart/bitcoindart.dart' as btc_dart; -import 'package:bitcoindart/src/utils/constants/op.dart' as op; -import 'package:bitcoindart/src/utils/script.dart' as bscript; -import 'package:isar/isar.dart'; -import 'package:pointycastle/digests/sha256.dart'; -import 'package:stackwallet/db/main_db.dart'; -import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart'; -import 'package:stackwallet/electrumx_rpc/electrumx.dart'; -import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; -import 'package:stackwallet/models/isar/models/isar_models.dart'; -import 'package:stackwallet/utilities/address_utils.dart'; -import 'package:stackwallet/utilities/bip32_utils.dart'; -import 'package:stackwallet/utilities/enums/coin_enum.dart'; -import 'package:stackwallet/utilities/format.dart'; -import 'package:stackwallet/utilities/logger.dart'; -import 'package:tuple/tuple.dart'; -import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; - -mixin PaynymSupport { - late final btc_dart.NetworkType network; - late final MainDB db; - late final Coin coin; - late final String walletId; - void initPaynymSupport({ - required btc_dart.NetworkType network, - required MainDB db, - required Coin coin, - required String walletId, - }) { - this.network = network; - this.db = db; - this.coin = coin; - this.walletId = walletId; - } - - // generate bip32 payment code root - Future getRootNode({required List mnemonic}) async { - final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), network); - return root; - } - - // fetch or generate this wallet's bip47 payment code - Future getPaymentCode({ - required List mnemonic, - }) async { - // TODO: cache elsewhere - // final paymentCodeString = DB.instance - // .get(boxName: walletId, key: "paymentCodeString") as String?; - PaymentCode paymentCode; - // if (paymentCodeString == null) { - final root = await getRootNode(mnemonic: mnemonic); - final node = root.derivePath("m/47'/0'/0'"); - paymentCode = - PaymentCode.initFromPubKey(node.publicKey, node.chainCode, network); - // await DB.instance.put( - // boxName: walletId, - // key: "paymentCodeString", - // value: paymentCode.toString()); - // } else { - // paymentCode = PaymentCode.fromPaymentCode(paymentCodeString, network); - // } - return paymentCode; - } - - Future signWithNotificationKey({ - required Uint8List data, - required List mnemonic, - }) async { - final root = await getRootNode( - mnemonic: mnemonic, - ); - final node = root.derivePath("m/47'/0'/0'"); - final pair = btc_dart.ECPair.fromPrivateKey(node.privateKey!, network: network); - final signed = pair.sign(SHA256Digest().process(data)); - return signed; - } - - Future signStringWithNotificationKey({ - required String data, - required List mnemonic, - }) async { - final bytes = await signWithNotificationKey( - data: Uint8List.fromList(utf8.encode(data)), - mnemonic: mnemonic, - ); - return Format.uint8listToString(bytes); - // final bytes = - // await signWithNotificationKey(Uint8List.fromList(utf8.encode(data))); - // return Format.uint8listToString(bytes); - } - - /// Update cached lists of notification transaction IDs. - /// Returns true if there are new notification transactions found since last - /// checked. - Future checkForNotificationTransactions({ - required Coin coin, - required PaymentCode paymentCode, - required ElectrumX electrumXClient, - required CachedElectrumX cachedElectrumXClient, - required int currentChainHeight, - }) async { - final notificationAddress = paymentCode.notificationAddress(); - - final receivedNotificationTransactions = await db - .getTransactions(walletId) - .filter() - .address((q) => q.valueEqualTo(notificationAddress)) - .findAll(); - - - final unconfirmedTransactions = receivedNotificationTransactions.where( - (e) => !e.isConfirmed( - currentChainHeight, - coin.requiredConfirmations, - ), - ); - - final totalStoredCount = receivedNotificationTransactions.length; - final storedUnconfirmedCount = unconfirmedTransactions.length; - - // for (final txid in transactionIds) { - // final tx = await cachedElectrumXClient.getTransaction( - // txHash: txid, - // coin: coin, - // ); - // - // // check if tx is confirmed - // if ((tx["confirmations"] as int? ?? 0) > coin.requiredConfirmations) { - // // remove it from unconfirmed set - // unconfirmedNotificationTransactionIds.remove(txid); - // - // // add it to confirmed set - // confirmedNotificationTransactionIds.add(txid); - // } else { - // // otherwise add it to the unconfirmed set - // unconfirmedNotificationTransactionIds.add(txid); - // } - // } - // - // final newTotalCount = confirmedNotificationTransactionIds.length + - // unconfirmedNotificationTransactionIds.length; - // - // return newTotalCount > totalCount; - return false; - } - - // bool hasConnected(String paymentCodeString) { - // return getPaynymNotificationTxInfo() - // .values - // .where((e) => e["paymentCodeString"] == paymentCodeString) - // .isNotEmpty; - // } - // - // bool hasConnectedConfirmed(String paymentCodeString) { - // return getPaynymNotificationTxInfo() - // .values - // .where((e) => - // e["paymentCodeString"] == paymentCodeString && - // e["confirmed"] == true) - // .isNotEmpty; - // } - // - // // fetch paynym notification tx meta data - // Map getPaynymNotificationTxInfo() { - // final map = DB.instance.get( - // boxName: walletId, key: "paynymNotificationTxInfo") as Map? ?? - // {}; - // - // return Map.from(map); - // } - - // // add/update paynym notification tx meta data entry - // Future updatePaynymNotificationInfo({ - // required String txid, - // required bool confirmed, - // required String paymentCodeString, - // }) async { - // final data = getPaynymNotificationTxInfo(); - // data[txid] = { - // "txid": txid, - // "confirmed": confirmed, - // "paymentCodeString": paymentCodeString, - // }; - // await DB.instance.put( - // boxName: walletId, - // key: "paynymNotificationTxInfo", - // value: data, - // ); - // } - - Future hasSentNotificationTx(PaymentCode pCode) async { - final tx = await db - .getTransactions(walletId) - .filter() - .address((q) => q.valueEqualTo(pCode.notificationAddress())).countSync() - .findFirst(); - return tx; - } - - void preparePaymentCodeSend(PaymentCode pCode) async { - final notifTx = await hasSentNotificationTx(pCode); - final currentHeight = await chainHeight; - - if (notifTx == null) { - throw PaynymSendException("No notification transaction sent to $pCode"); - } else if (!notifTx.isConfirmed(currentHeight, MINIMUM_CONFIRMATIONS)) { - throw PaynymSendException( - "Notification transaction sent to $pCode has not confirmed yet"); - } else { - final node = getBip32Root((await mnemonic).join(" "), network) - .derivePath("m/47'/0'/0'"); - final sendToAddress = await nextUnusedSendAddressFrom( - pCode, - node.derive(0).privateKey!, - ); - - // todo: Actual transaction build - } - } - - /// get the next unused address to send to given the receiver's payment code - /// and your own private key - Future nextUnusedSendAddressFrom( - PaymentCode pCode, - Uint8List privateKey, - ) async { - // https://en.bitcoin.it/wiki/BIP_0047#Path_levels - const maxCount = 2147483647; - - final paymentAddress = PaymentAddress.initWithPrivateKey( - privateKey, - pCode, - 0, // initial index to check - ); - - for ( ; - paymentAddress.index <= maxCount; - paymentAddress.index++) { - final address = paymentAddress.getSendAddress(); - - final transactionIds = await electrumXClient.getHistory( - scripthash: AddressUtils.convertToScriptHash( - address, - network, - ), - ); - - if (transactionIds.isEmpty) { - return address; - } - } - - throw PaynymSendException("Exhausted unused send addresses!"); - } - - /// get your receiving addresses given the sender's payment code and your own - /// private key - List deriveReceivingAddressesFor( - PaymentCode pCode, - Uint8List privateKey, - int count, - ) { - // https://en.bitcoin.it/wiki/BIP_0047#Path_levels - const maxCount = 2147483647; - assert(count <= maxCount); - - final paymentAddress = PaymentAddress.initWithPrivateKey( - privateKey, - pCode, - 0, // initial index - ); - - final List result = []; - for (paymentAddress.index = 0; - paymentAddress.index < count; - paymentAddress.index++) { - final address = paymentAddress.getReceiveAddress(); - - result.add(address); - } - - return result; - } - - Future> buildNotificationTx({ - required int selectedTxFeeRate, - required String targetPaymentCodeString, - required PaymentCode myPaymentCode, - int additionalOutputs = 0, - required List utxos, - required int dustLimit, - required int chainHeight, - required Future> Function( - List< UTXO> - ) fetchBuildTxData, - }) async { - final amountToSend = dustLimit; - final List availableOutputs = utxos ; - final List spendableOutputs = []; - int spendableSatoshiValue = 0; - - // Build list of spendable outputs and totaling their satoshi amount - for (var i = 0; i < availableOutputs.length; i++) { - if (availableOutputs[i].isBlocked == false && - availableOutputs[i] - .isConfirmed( chainHeight, coin.requiredConfirmations) == - true) { - spendableOutputs.add(availableOutputs[i]); - spendableSatoshiValue += availableOutputs[i].value; - } - } - - if (spendableSatoshiValue < amountToSend) { - // insufficient balance - throw InsufficientBalanceException( - "Spendable balance is less than the minimum required for a notification transaction."); - } else if (spendableSatoshiValue == amountToSend) { - // insufficient balance due to missing amount to cover fee - throw InsufficientBalanceException( - "Remaining balance does not cover the network fee."); - } - - // sort spendable by age (oldest first) - spendableOutputs.sort((a, b) => b.blockTime!.compareTo(a.blockTime!)); - - int satoshisBeingUsed = 0; - int outputsBeingUsed = 0; - List utxoObjectsToUse = []; - - for (int i = 0; - satoshisBeingUsed < amountToSend && i < spendableOutputs.length; - i++) { - utxoObjectsToUse.add(spendableOutputs[i]); - satoshisBeingUsed += spendableOutputs[i].value; - outputsBeingUsed += 1; - } - - // add additional outputs if required - for (int i = 0; - i < additionalOutputs && outputsBeingUsed < spendableOutputs.length; - i++) { - utxoObjectsToUse.add(spendableOutputs[outputsBeingUsed]); - satoshisBeingUsed += spendableOutputs[outputsBeingUsed].value; - outputsBeingUsed += 1; - } - - // gather required signing data - final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); - - final int vSizeForNoChange = (await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: 0, myPaymentCode: myPaymentCode, dustLimit: dustLimit, changeAddress: )) - .item2; - - final int vSizeForWithChange = (await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: satoshisBeingUsed - amountToSend, myPaymentCode: myPaymentCode, dustLimit: dustLimit, changeAddress: ch,)) - .item2; - - // Assume 2 outputs, for recipient and payment code script - int feeForNoChange = estimateTxFee( - vSize: vSizeForNoChange, - feeRatePerKB: selectedTxFeeRate, - ); - - // Assume 3 outputs, for recipient, payment code script, and change - int feeForWithChange = estimateTxFee( - vSize: vSizeForWithChange, - feeRatePerKB: selectedTxFeeRate, - ); - - if (feeForNoChange < vSizeForNoChange * 1000) { - feeForNoChange = vSizeForNoChange * 1000; - } - if (feeForWithChange < vSizeForWithChange * 1000) { - feeForWithChange = vSizeForWithChange * 1000; - } - - if (satoshisBeingUsed - amountToSend > feeForNoChange + dustLimit) { - // try to add change output due to "left over" amount being greater than - // the estimated fee + the dust limit - int changeAmount = satoshisBeingUsed - amountToSend - feeForWithChange; - - // check estimates are correct and build notification tx - if (changeAmount >= dustLimit && - satoshisBeingUsed - amountToSend - changeAmount == feeForWithChange) { - final txn = await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: changeAmount, - ); - - int feeBeingPaid = satoshisBeingUsed - amountToSend - changeAmount; - - Map transactionObject = { - "hex": txn.item1, - "recipientPaynym": targetPaymentCodeString, - "amount": amountToSend, - "fee": feeBeingPaid, - "vSize": txn.item2, - }; - return transactionObject; - } else { - // something broke during fee estimation or the change amount is smaller - // than the dust limit. Try without change - final txn = await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: 0, - ); - - int feeBeingPaid = satoshisBeingUsed - amountToSend; - - Map transactionObject = { - "hex": txn.item1, - "recipientPaynym": targetPaymentCodeString, - "amount": amountToSend, - "fee": feeBeingPaid, - "vSize": txn.item2, - }; - return transactionObject; - } - } else if (satoshisBeingUsed - amountToSend >= feeForNoChange) { - // since we already checked if we need to add a change output we can just - // build without change here - final txn = await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: 0, myPaymentCode: null, - ); - - int feeBeingPaid = satoshisBeingUsed - amountToSend; - - Map transactionObject = { - "hex": txn.item1, - "recipientPaynym": targetPaymentCodeString, - "amount": amountToSend, - "fee": feeBeingPaid, - "vSize": txn.item2, - }; - return transactionObject; - } else { - // if we get here we do not have enough funds to cover the tx total so we - // check if we have any more available outputs and try again - if (spendableOutputs.length > outputsBeingUsed) { - return buildNotificationTx( - selectedTxFeeRate: selectedTxFeeRate, - targetPaymentCodeString: targetPaymentCodeString, - additionalOutputs: additionalOutputs + 1, utxos: utxos, dustLimit: dustLimit, chainHeight: chainHeight, fetchBuildTxData: fetchBuildTxData, - ); - } else { - throw InsufficientBalanceException( - "Remaining balance does not cover the network fee."); - } - } - } - - // return tuple with string value equal to the raw tx hex and the int value - // equal to its vSize - Future> _createNotificationTx({ - required String targetPaymentCodeString, - required PaymentCode myPaymentCode, - required List utxosToUse, - required Map utxoSigningData, - required int change, - required int dustLimit, - required Address changeAddress, - }) async { - final targetPaymentCode = - PaymentCode.fromPaymentCode(targetPaymentCodeString, network); - - final utxo = utxosToUse.first; - final txPoint = utxo.txid.fromHex.toList(); - final txPointIndex = utxo.vout; - - final rev = Uint8List(txPoint.length + 4); - Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); - final buffer = rev.buffer.asByteData(); - buffer.setUint32(txPoint.length, txPointIndex, Endian.little); - - final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as btc_dart.ECPair; - - final S = SecretPoint( - myKeyPair.privateKey!, - targetPaymentCode.notificationPublicKey(), - ); - - final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev); - - final blindedPaymentCode = PaymentCode.blind( - myPaymentCode.getPayload(), - blindingMask, - ); - - final opReturnScript = bscript.compile([ - (op.OPS["OP_RETURN"] as int), - blindedPaymentCode, - ]); - - // build a notification tx - final txb = btc_dart.TransactionBuilder(network: network); - txb.setVersion(1); - - txb.addInput( - utxo.txid, - txPointIndex, - ); - - txb.addOutput(targetPaymentCode.notificationAddress(), dustLimit); - txb.addOutput(opReturnScript, 0); - - // TODO: add possible change output and mark output as dangerous - if (change > 0) { - final String changeAddressString = changeAddress.value; - txb.addOutput(changeAddressString, change); - } - - txb.sign( - vin: 0, - keyPair: myKeyPair, - ); - - // sign rest of possible inputs - for (var i = 1; i < utxosToUse.length - 1; i++) { - final txid = utxosToUse[i].txid; - txb.sign( - vin: i, - keyPair: utxoSigningData[txid]["keyPair"] as ECPair, - // witnessValue: utxosToUse[i].value, - ); - } - - final builtTx = txb.build(); - - return Tuple2(builtTx.toHex(), builtTx.virtualSize()); - } - - Future confirmSendNotificationTx( - {required Map preparedTx, required ElectrumX electrumXClient,}) async { - try { - Logging.instance.log("confirmNotificationTx txData: $preparedTx", - level: LogLevel.Info); - final txHash = await electrumXClient.broadcastTransaction( - rawTx: preparedTx["hex"] as String); - Logging.instance.log("Sent txHash: $txHash", level: LogLevel.Info); - - - return txHash; - } catch (e, s) { - Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s", - level: LogLevel.Error); - rethrow; - } - } - -} From 26245517acb57d2fbd06a2e6e5d7c544c0067886 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 09:26:50 -0600 Subject: [PATCH 15/55] add paynym send functionality to paynym extension --- lib/services/coins/coin_paynym_extension.dart | 108 ++++++++++++------ 1 file changed, 72 insertions(+), 36 deletions(-) diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index 8810621ec..77173aadd 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -13,7 +13,6 @@ import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dar import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; -import 'package:stackwallet/utilities/address_utils.dart'; import 'package:stackwallet/utilities/bip32_utils.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/logger.dart'; @@ -23,24 +22,40 @@ const kPaynymDerivePath = "m/47'/0'/0'"; extension PayNym on DogecoinWallet { // generate bip32 payment code root - Future getRootNode({required List mnemonic}) async { + Future getRootNode({ + required List mnemonic, + }) async { final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), network); return root; } + Future deriveNotificationPrivateKey({ + required List mnemonic, + }) async { + final root = await getRootNode(mnemonic: mnemonic); + final node = root.derivePath(kPaynymDerivePath).derive(0); + return node.privateKey!; + } + /// fetch or generate this wallet's bip47 payment code Future getPaymentCode() async { final address = await db .getAddresses(walletId) .filter() .subTypeEqualTo(AddressSubType.paynymNotification) + .and() + .not() + .typeEqualTo(AddressType.nonWallet) .findFirst(); PaymentCode paymentCode; if (address == null) { final root = await getRootNode(mnemonic: await mnemonic); final node = root.derivePath(kPaynymDerivePath); - paymentCode = - PaymentCode.initFromPubKey(node.publicKey, node.chainCode, network); + paymentCode = PaymentCode.initFromPubKey( + node.publicKey, + node.chainCode, + network, + ); await db.putAddress( Address( @@ -60,12 +75,9 @@ extension PayNym on DogecoinWallet { } Future signWithNotificationKey(Uint8List data) async { - final root = await getRootNode(mnemonic: await mnemonic); - final node = root.derivePath(kPaynymDerivePath); - final pair = - btc_dart.ECPair.fromPrivateKey(node.privateKey!, network: network); - // TODO: is pair same as priv key from node? - // todo: should this priv key be used or priv key of derive(0)? + final privateKey = + await deriveNotificationPrivateKey(mnemonic: await mnemonic); + final pair = btc_dart.ECPair.fromPrivateKey(privateKey, network: network); final signed = pair.sign(SHA256Digest().process(data)); return signed; } @@ -76,24 +88,27 @@ extension PayNym on DogecoinWallet { return Format.uint8listToString(bytes); } - void preparePaymentCodeSend(PaymentCode pCode) async { - if (!(await hasConnected(pCode.notificationAddress()))) { - throw PaynymSendException("No notification transaction sent to $pCode"); + Future>> preparePaymentCodeSend( + PaymentCode paymentCode, int satoshiAmount) async { + if (!(await hasConnected(paymentCode.notificationAddress()))) { + throw PaynymSendException( + "No notification transaction sent to $paymentCode"); } else { - final root = await getRootNode(mnemonic: await mnemonic); - final node = root.derivePath(kPaynymDerivePath); + final myPrivateKey = + await deriveNotificationPrivateKey(mnemonic: await mnemonic); final sendToAddress = await nextUnusedSendAddressFrom( - pCode: pCode, - privateKey: node.derive(0).privateKey!, + pCode: paymentCode, + privateKey: myPrivateKey, ); - // todo: Actual transaction build + return prepareSend( + address: sendToAddress.value, satoshiAmount: satoshiAmount); } } /// get the next unused address to send to given the receiver's payment code /// and your own private key - Future nextUnusedSendAddressFrom({ + Future
nextUnusedSendAddressFrom({ required PaymentCode pCode, required Uint8List privateKey, int startIndex = 0, @@ -101,24 +116,46 @@ extension PayNym on DogecoinWallet { // https://en.bitcoin.it/wiki/BIP_0047#Path_levels const maxCount = 2147483647; - final paymentAddress = PaymentAddress.initWithPrivateKey( - privateKey, - pCode, - startIndex, // initial index to check - ); + for (int i = startIndex; i < maxCount; i++) { + final address = await db + .getAddresses(walletId) + .filter() + .subTypeEqualTo(AddressSubType.paynymSend) + .and() + .otherDataEqualTo(pCode.toString()) + .and() + .derivationIndexEqualTo(i) + .findFirst(); - for (; paymentAddress.index <= maxCount; paymentAddress.index++) { - final address = paymentAddress.getSendAddress(); + if (address != null) { + final count = await getTxCount(address: address.value); + // return address if unused, otherwise continue to next index + if (count == 0) { + return address; + } + } else { + final paymentAddress = PaymentAddress.initWithPrivateKey( + privateKey, + pCode, + i, // index to use + ).getSendAddress(); - final transactionIds = await electrumXClient.getHistory( - scripthash: AddressUtils.convertToScriptHash( - address, - network, - ), - ); + // add address to local db + final address = Address( + walletId: walletId, + value: paymentAddress, + publicKey: [], + derivationIndex: i, + type: AddressType.p2pkh, + subType: AddressSubType.paynymSend, + ); + await db.putAddress(address); - if (transactionIds.isEmpty) { - return address; + final count = await getTxCount(address: address.value); + // return address if unused, otherwise continue to next index + if (count == 0) { + return address; + } } } @@ -466,9 +503,8 @@ extension PayNym on DogecoinWallet { final pubKey = designatedInput.scriptSigAsm!.split(" ")[1].fromHex; - final root = await getRootNode(mnemonic: await mnemonic); final myPrivateKey = - root.derivePath(kPaynymDerivePath).derive(0).privateKey!; + await deriveNotificationPrivateKey(mnemonic: await mnemonic); final S = SecretPoint(myPrivateKey, pubKey); From 1965501bf8d45f6b90e406f0a00f54e090b30936 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 11:13:21 -0600 Subject: [PATCH 16/55] added address scanning for send and receiving addresses given the context of your own payment code and another, address type choice also added for send/receive address generation --- lib/services/coins/coin_paynym_extension.dart | 269 +++++++++++++++--- lib/services/mixins/electrum_x_parsing.dart | 2 +- pubspec.lock | 4 +- pubspec.yaml | 2 +- 4 files changed, 229 insertions(+), 48 deletions(-) diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index 77173aadd..a97ccd355 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -134,20 +134,18 @@ extension PayNym on DogecoinWallet { return address; } } else { - final paymentAddress = PaymentAddress.initWithPrivateKey( + final pair = PaymentAddress.initWithPrivateKey( privateKey, pCode, i, // index to use - ).getSendAddress(); + ).getSendAddressKeyPair(); // add address to local db - final address = Address( - walletId: walletId, - value: paymentAddress, - publicKey: [], + final address = generatePaynymSendAddressFromKeyPair( + pair: pair, derivationIndex: i, - type: AddressType.p2pkh, - subType: AddressSubType.paynymSend, + derivePathType: DerivePathType.bip44, + toPaymentCode: pCode, ); await db.putAddress(address); @@ -162,35 +160,6 @@ extension PayNym on DogecoinWallet { throw PaynymSendException("Exhausted unused send addresses!"); } - /// get your receiving addresses given the sender's payment code and your own - /// private key - List deriveReceivingAddressesFor( - PaymentCode pCode, - Uint8List privateKey, - int count, - ) { - // https://en.bitcoin.it/wiki/BIP_0047#Path_levels - const maxCount = 2147483647; - assert(count <= maxCount); - - final paymentAddress = PaymentAddress.initWithPrivateKey( - privateKey, - pCode, - 0, // initial index - ); - - final List result = []; - for (paymentAddress.index = 0; - paymentAddress.index < count; - paymentAddress.index++) { - final address = paymentAddress.getReceiveAddress(); - - result.add(address); - } - - return result; - } - Future> prepareNotificationTx({ required int selectedTxFeeRate, required String targetPaymentCodeString, @@ -484,14 +453,39 @@ extension PayNym on DogecoinWallet { .findAll(); for (final tx in txns) { + // quick check that may cause problems? if (tx.address.value?.value == myNotificationAddress) { return true; } - final blindedCode = - tx.outputs.elementAt(1).scriptPubKeyAsm!.split(" ")[1]; + final unBlindedPaymentCode = await unBlindedPaymentCodeFromTransaction( + transaction: tx, + myCode: myCode, + ); - final designatedInput = tx.inputs.first; + if (paymentCodeString == unBlindedPaymentCode.toString()) { + return true; + } + } + + // otherwise return no + return false; + } + + Future unBlindedPaymentCodeFromTransaction({ + required Transaction transaction, + required PaymentCode myCode, + }) async { + if (transaction.address.value != null && + transaction.address.value!.value != myCode.notificationAddress()) { + return null; + } + + try { + final blindedCode = + transaction.outputs.elementAt(1).scriptPubKeyAsm!.split(" ")[1]; + + final designatedInput = transaction.inputs.first; final txPoint = designatedInput.txid.fromHex.toList(); final txPointIndex = designatedInput.vout; @@ -515,12 +509,199 @@ extension PayNym on DogecoinWallet { final unBlindedPaymentCode = PaymentCode.initFromPayload(unBlindedPayload); - if (paymentCodeString == unBlindedPaymentCode.toString()) { - return true; + return unBlindedPaymentCode; + } catch (e) { + Logging.instance.log( + "unBlindedPaymentCodeFromTransaction() failed: $e", + level: LogLevel.Warning, + ); + return null; + } + } + + Future> + getAllPaymentCodesFromNotificationTransactions() async { + final myCode = await getPaymentCode(); + final txns = await db + .getTransactions(walletId) + .filter() + .subTypeEqualTo(TransactionSubType.bip47Notification) + .findAll(); + + List unBlindedList = []; + + for (final tx in txns) { + final unBlinded = await unBlindedPaymentCodeFromTransaction( + transaction: tx, + myCode: myCode, + ); + if (unBlinded != null) { + unBlindedList.add(unBlinded); } } - // otherwise return no - return false; + return unBlindedList; + } + + Future restoreHistoryWith( + PaymentCode other, + int maxUnusedAddressGap, + int maxNumberOfIndexesToCheck, + ) async { + // https://en.bitcoin.it/wiki/BIP_0047#Path_levels + const maxCount = 2147483647; + assert(maxNumberOfIndexesToCheck < maxCount); + + final myPrivateKey = + await deriveNotificationPrivateKey(mnemonic: await mnemonic); + + List
addresses = []; + int receivingGapCounter = 0; + int outgoingGapCounter = 0; + + for (int i = 0; + i < maxNumberOfIndexesToCheck && + (receivingGapCounter < maxUnusedAddressGap || + outgoingGapCounter < maxUnusedAddressGap); + i++) { + final paymentAddress = PaymentAddress.initWithPrivateKey( + myPrivateKey, + other, + i, // index to use + ); + + if (receivingGapCounter < maxUnusedAddressGap) { + final pair = paymentAddress.getSendAddressKeyPair(); + final address = generatePaynymSendAddressFromKeyPair( + pair: pair, + derivationIndex: i, + derivePathType: DerivePathType.bip44, + toPaymentCode: other, + ); + addresses.add(address); + + final count = await getTxCount(address: address.value); + + if (count > 0) { + receivingGapCounter++; + } else { + receivingGapCounter = 0; + } + } + + if (outgoingGapCounter < maxUnusedAddressGap) { + final pair = paymentAddress.getReceiveAddressKeyPair(); + final address = generatePaynymReceivingAddressFromKeyPair( + pair: pair, + derivationIndex: i, + derivePathType: DerivePathType.bip44, + fromPaymentCode: other, + ); + addresses.add(address); + + final count = await getTxCount(address: address.value); + + if (count > 0) { + outgoingGapCounter++; + } else { + outgoingGapCounter = 0; + } + } + } + await db.putAddresses(addresses); + } + + Address generatePaynymSendAddressFromKeyPair({ + required btc_dart.ECPair pair, + required int derivationIndex, + required DerivePathType derivePathType, + required PaymentCode toPaymentCode, + }) { + final data = btc_dart.PaymentData(pubkey: pair.publicKey); + + String addressString; + switch (derivePathType) { + case DerivePathType.bip44: + addressString = + btc_dart.P2PKH(data: data, network: network).data.address!; + break; + + // The following doesn't apply to doge currently + // + // case DerivePathType.bip49: + // addressString = btc_dart.P2SH( + // data: btc_dart.PaymentData( + // redeem: btc_dart.P2WPKH(data: data, network: network).data), + // network: network) + // .data + // .address!; + // addrType = AddressType.p2sh; + // break; + // case DerivePathType.bip84: + // addressString = btc_dart.P2WPKH(network: network, data: data).data.address!; + // addrType = AddressType.p2wpkh; + // break; + + } + + final address = Address( + walletId: walletId, + value: addressString, + publicKey: pair.publicKey, + derivationIndex: derivationIndex, + type: AddressType.nonWallet, + subType: AddressSubType.paynymSend, + otherData: toPaymentCode.toString(), + ); + + return address; + } + + Address generatePaynymReceivingAddressFromKeyPair({ + required btc_dart.ECPair pair, + required int derivationIndex, + required DerivePathType derivePathType, + required PaymentCode fromPaymentCode, + }) { + final data = btc_dart.PaymentData(pubkey: pair.publicKey); + + String addressString; + AddressType addrType; + switch (derivePathType) { + case DerivePathType.bip44: + addressString = + btc_dart.P2PKH(data: data, network: network).data.address!; + addrType = AddressType.p2pkh; + break; + + // The following doesn't apply to doge currently + // + // case DerivePathType.bip49: + // addressString = btc_dart.P2SH( + // data: btc_dart.PaymentData( + // redeem: btc_dart.P2WPKH(data: data, network: network).data), + // network: network) + // .data + // .address!; + // addrType = AddressType.p2sh; + // break; + // case DerivePathType.bip84: + // addressString = btc_dart.P2WPKH(network: network, data: data).data.address!; + // addrType = AddressType.p2wpkh; + // break; + + } + + final address = Address( + walletId: walletId, + value: addressString, + publicKey: pair.publicKey, + derivationIndex: derivationIndex, + type: addrType, + subType: AddressSubType.paynymReceive, + otherData: fromPaymentCode.toString(), + ); + + return address; } } diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart index b9b815594..deac690f7 100644 --- a/lib/services/mixins/electrum_x_parsing.dart +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -186,7 +186,7 @@ mixin ElectrumXParsing { } TransactionSubType txSubType = TransactionSubType.none; - if (coin.hasPaynymSupport && outs.length > 1) { + if (coin.hasPaynymSupport && outs.length > 1 && ins.isNotEmpty) { List? scriptChunks = outs[1].scriptPubKeyAsm?.split(" "); if (scriptChunks?.length == 2 && scriptChunks?[0] == "OP_RETURN") { final blindedPaymentCode = scriptChunks![1]; diff --git a/pubspec.lock b/pubspec.lock index 8364e6ec9..0c8768e2a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -100,8 +100,8 @@ packages: dependency: "direct main" description: path: "." - ref: testing - resolved-ref: "8ed2f6245c71a4457ed4ffdd3a74e4bcb9f9d2d0" + ref: "2d800225329498841affa1386d96d2696c62b713" + resolved-ref: "2d800225329498841affa1386d96d2696c62b713" url: "https://github.com/cypherstack/bip47.git" source: git version: "1.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 058021b9f..967c9cba4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,7 +59,7 @@ dependencies: bip47: git: url: https://github.com/cypherstack/bip47.git - ref: testing + ref: 2d800225329498841affa1386d96d2696c62b713 # Utility plugins # provider: ^6.0.1 From 6b08acf225b10f5ac71f7784d3d8155d464acec6 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 12:08:48 -0600 Subject: [PATCH 17/55] single DerivePathType enum declaration --- lib/services/coins/bitcoin/bitcoin_wallet.dart | 3 +-- .../coins/bitcoincash/bitcoincash_wallet.dart | 14 +++++++++----- lib/services/coins/dogecoin/dogecoin_wallet.dart | 16 ++++++++++------ lib/services/coins/litecoin/litecoin_wallet.dart | 3 +-- lib/services/coins/namecoin/namecoin_wallet.dart | 3 +-- lib/services/coins/particl/particl_wallet.dart | 11 +++++++++-- lib/utilities/enums/derive_path_type_enum.dart | 1 + 7 files changed, 32 insertions(+), 19 deletions(-) create mode 100644 lib/utilities/enums/derive_path_type_enum.dart diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart index d0b114829..2194c5a19 100644 --- a/lib/services/coins/bitcoin/bitcoin_wallet.dart +++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart @@ -33,6 +33,7 @@ import 'package:stackwallet/utilities/assets.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/derive_path_type_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/format.dart'; @@ -50,8 +51,6 @@ const String GENESIS_HASH_MAINNET = const String GENESIS_HASH_TESTNET = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"; -enum DerivePathType { bip44, bip49, bip84 } - bip32.BIP32 getBip32Node( int chain, int index, diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index 70e3a5d55..84f302dec 100644 --- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart +++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart @@ -34,6 +34,7 @@ import 'package:stackwallet/utilities/assets.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/derive_path_type_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/format.dart'; @@ -50,8 +51,6 @@ const String GENESIS_HASH_MAINNET = const String GENESIS_HASH_TESTNET = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"; -enum DerivePathType { bip44, bip49 } - bip32.BIP32 getBip32Node(int chain, int index, String mnemonic, NetworkType network, DerivePathType derivePathType) { final root = getBip32Root(mnemonic, network); @@ -1421,9 +1420,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { .address!; addrType = isar_models.AddressType.p2sh; break; - // default: - // // should never hit this due to all enum cases handled - // return null; + case DerivePathType.bip84: + throw UnsupportedError("bip84 not supported by BCH"); } // add generated address & info to derivations @@ -1466,6 +1464,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { case DerivePathType.bip49: type = isar_models.AddressType.p2sh; break; + case DerivePathType.bip84: + throw UnsupportedError("bip84 not supported by BCH"); } final address = await db @@ -1491,6 +1491,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { case DerivePathType.bip49: key = "${walletId}_${chainId}DerivationsP2SH"; break; + case DerivePathType.bip84: + throw UnsupportedError("bip84 not supported by BCH"); } return key; } @@ -2611,6 +2613,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { case DerivePathType.bip49: addressesP2SH.add(address); break; + case DerivePathType.bip84: + throw UnsupportedError("bip84 not supported by BCH"); } } } diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index c47ad8947..c8cc68f8e 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -34,6 +34,7 @@ import 'package:stackwallet/utilities/assets.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/derive_path_type_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/format.dart'; @@ -50,8 +51,6 @@ const String GENESIS_HASH_MAINNET = const String GENESIS_HASH_TESTNET = "bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e"; -enum DerivePathType { bip44 } - bip32.BIP32 getBip32Node(int chain, int index, String mnemonic, NetworkType network, DerivePathType derivePathType) { final root = getBip32Root(mnemonic, network); @@ -90,7 +89,7 @@ bip32.BIP32 getBip32NodeFromRoot( case DerivePathType.bip44: return root.derivePath("m/44'/$coinType'/0'/$chain/$index"); default: - throw Exception("DerivePathType must not be null."); + throw Exception("Unsupported DerivePathType"); } } @@ -1273,9 +1272,8 @@ class DogecoinWallet extends CoinServiceAPI case DerivePathType.bip44: address = P2PKH(data: data, network: network).data.address!; break; - // default: - // // should never hit this due to all enum cases handled - // return null; + default: + throw Exception("Unsupported DerivePathType"); } // add generated address & info to derivations @@ -1320,6 +1318,8 @@ class DogecoinWallet extends CoinServiceAPI .sortByDerivationIndexDesc() .findFirst(); break; + default: + throw Exception("Unsupported DerivePathType"); } return address!.value; } @@ -1332,6 +1332,8 @@ class DogecoinWallet extends CoinServiceAPI case DerivePathType.bip44: key = "${walletId}_${chainId}DerivationsP2PKH"; break; + default: + throw Exception("Unsupported DerivePathType"); } return key; } @@ -2339,6 +2341,8 @@ class DogecoinWallet extends CoinServiceAPI case DerivePathType.bip44: addressesP2PKH.add(address); break; + default: + throw Exception("Unsupported DerivePathType"); } } } diff --git a/lib/services/coins/litecoin/litecoin_wallet.dart b/lib/services/coins/litecoin/litecoin_wallet.dart index fe1fdf13c..aed4182a8 100644 --- a/lib/services/coins/litecoin/litecoin_wallet.dart +++ b/lib/services/coins/litecoin/litecoin_wallet.dart @@ -33,6 +33,7 @@ import 'package:stackwallet/utilities/assets.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/derive_path_type_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/format.dart'; @@ -50,8 +51,6 @@ const String GENESIS_HASH_MAINNET = const String GENESIS_HASH_TESTNET = "4966625a4b2851d9fdee139e56211a0d88575f59ed816ff5e6a63deb4e3e29a0"; -enum DerivePathType { bip44, bip49, bip84 } - bip32.BIP32 getBip32Node( int chain, int index, diff --git a/lib/services/coins/namecoin/namecoin_wallet.dart b/lib/services/coins/namecoin/namecoin_wallet.dart index cae6cf29a..2805f5412 100644 --- a/lib/services/coins/namecoin/namecoin_wallet.dart +++ b/lib/services/coins/namecoin/namecoin_wallet.dart @@ -33,6 +33,7 @@ import 'package:stackwallet/utilities/assets.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/derive_path_type_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/format.dart'; @@ -50,8 +51,6 @@ const String GENESIS_HASH_MAINNET = const String GENESIS_HASH_TESTNET = "00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008"; -enum DerivePathType { bip44, bip49, bip84 } - bip32.BIP32 getBip32Node( int chain, int index, diff --git a/lib/services/coins/particl/particl_wallet.dart b/lib/services/coins/particl/particl_wallet.dart index d19fdf769..22b90d05f 100644 --- a/lib/services/coins/particl/particl_wallet.dart +++ b/lib/services/coins/particl/particl_wallet.dart @@ -32,6 +32,7 @@ import 'package:stackwallet/utilities/assets.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/derive_path_type_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/format.dart'; @@ -48,8 +49,6 @@ const String GENESIS_HASH_MAINNET = const String GENESIS_HASH_TESTNET = "0000594ada5310b367443ee0afd4fa3d0bbd5850ea4e33cdc7d6a904a7ec7c90"; -enum DerivePathType { bip44, bip84 } - bip32.BIP32 getBip32Node( int chain, int index, @@ -1407,6 +1406,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { address = P2WPKH(network: _network, data: data).data.address!; addrType = isar_models.AddressType.p2wpkh; break; + default: + throw Exception("Unsupported DerivePathType"); } // add generated address & info to derivations @@ -1450,6 +1451,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { case DerivePathType.bip84: type = isar_models.AddressType.p2wpkh; break; + default: + throw Exception("Unsupported DerivePathType"); } address = await db .getAddresses(walletId) @@ -1475,6 +1478,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { case DerivePathType.bip84: key = "${walletId}_${chainId}DerivationsP2WPKH"; break; + default: + throw Exception("Unsupported DerivePathType"); } return key; } @@ -2743,6 +2748,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { case DerivePathType.bip84: addressesP2WPKH.add(address); break; + default: + throw Exception("Unsupported DerivePathType"); } } } diff --git a/lib/utilities/enums/derive_path_type_enum.dart b/lib/utilities/enums/derive_path_type_enum.dart new file mode 100644 index 000000000..694b9158f --- /dev/null +++ b/lib/utilities/enums/derive_path_type_enum.dart @@ -0,0 +1 @@ +enum DerivePathType { bip44, bip49, bip84 } From 35ba2f9d793b275707ace72a38a884f54523fd02 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 12:13:01 -0600 Subject: [PATCH 18/55] use derive path type in paynym extension --- lib/services/coins/coin_paynym_extension.dart | 200 ++++++++++++------ 1 file changed, 134 insertions(+), 66 deletions(-) diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index a97ccd355..f80f78961 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -18,6 +18,8 @@ import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:tuple/tuple.dart'; +import '../../utilities/enums/derive_path_type_enum.dart'; + const kPaynymDerivePath = "m/47'/0'/0'"; extension PayNym on DogecoinWallet { @@ -38,39 +40,14 @@ extension PayNym on DogecoinWallet { } /// fetch or generate this wallet's bip47 payment code - Future getPaymentCode() async { - final address = await db - .getAddresses(walletId) - .filter() - .subTypeEqualTo(AddressSubType.paynymNotification) - .and() - .not() - .typeEqualTo(AddressType.nonWallet) - .findFirst(); - PaymentCode paymentCode; - if (address == null) { - final root = await getRootNode(mnemonic: await mnemonic); - final node = root.derivePath(kPaynymDerivePath); - paymentCode = PaymentCode.initFromPubKey( - node.publicKey, - node.chainCode, - network, - ); - - await db.putAddress( - Address( - walletId: walletId, - value: paymentCode.notificationAddress(), - publicKey: paymentCode.getPubKey(), - derivationIndex: 0, - type: AddressType.p2pkh, // todo change this for btc - subType: AddressSubType.paynymNotification, - otherData: paymentCode.toString(), - ), - ); - } else { - paymentCode = PaymentCode.fromPaymentCode(address.otherData!, network); - } + Future getPaymentCode( + DerivePathType derivePathType, + ) async { + final address = await getMyNotificationAddress(derivePathType); + final paymentCode = PaymentCode.fromPaymentCode( + address.otherData!, + network, + ); return paymentCode; } @@ -344,7 +321,7 @@ extension PayNym on DogecoinWallet { }) async { final targetPaymentCode = PaymentCode.fromPaymentCode(targetPaymentCodeString, network); - final myCode = await getPaymentCode(); + final myCode = await getPaymentCode(DerivePathType.bip44); final utxo = utxosToUse.first; final txPoint = utxo.txid.fromHex.toList(); @@ -443,7 +420,7 @@ extension PayNym on DogecoinWallet { // TODO optimize Future hasConnected(String paymentCodeString) async { - final myCode = await getPaymentCode(); + final myCode = await getPaymentCode(DerivePathType.bip44); final myNotificationAddress = myCode.notificationAddress(); final txns = await db @@ -521,7 +498,7 @@ extension PayNym on DogecoinWallet { Future> getAllPaymentCodesFromNotificationTransactions() async { - final myCode = await getPaymentCode(); + final myCode = await getPaymentCode(DerivePathType.bip44); final txns = await db .getTransactions(walletId) .filter() @@ -627,21 +604,31 @@ extension PayNym on DogecoinWallet { break; // The following doesn't apply to doge currently - // - // case DerivePathType.bip49: - // addressString = btc_dart.P2SH( - // data: btc_dart.PaymentData( - // redeem: btc_dart.P2WPKH(data: data, network: network).data), - // network: network) - // .data - // .address!; - // addrType = AddressType.p2sh; - // break; - // case DerivePathType.bip84: - // addressString = btc_dart.P2WPKH(network: network, data: data).data.address!; - // addrType = AddressType.p2wpkh; - // break; + case DerivePathType.bip49: + addressString = btc_dart + .P2SH( + data: btc_dart.PaymentData( + redeem: btc_dart + .P2WPKH( + data: data, + network: network, + ) + .data), + network: network, + ) + .data + .address!; + break; + case DerivePathType.bip84: + addressString = btc_dart + .P2WPKH( + network: network, + data: data, + ) + .data + .address!; + break; } final address = Address( @@ -669,27 +656,44 @@ extension PayNym on DogecoinWallet { AddressType addrType; switch (derivePathType) { case DerivePathType.bip44: - addressString = - btc_dart.P2PKH(data: data, network: network).data.address!; + addressString = btc_dart + .P2PKH( + data: data, + network: network, + ) + .data + .address!; addrType = AddressType.p2pkh; break; // The following doesn't apply to doge currently - // - // case DerivePathType.bip49: - // addressString = btc_dart.P2SH( - // data: btc_dart.PaymentData( - // redeem: btc_dart.P2WPKH(data: data, network: network).data), - // network: network) - // .data - // .address!; - // addrType = AddressType.p2sh; - // break; - // case DerivePathType.bip84: - // addressString = btc_dart.P2WPKH(network: network, data: data).data.address!; - // addrType = AddressType.p2wpkh; - // break; + case DerivePathType.bip49: + addressString = btc_dart + .P2SH( + data: btc_dart.PaymentData( + redeem: btc_dart + .P2WPKH( + data: data, + network: network, + ) + .data), + network: network, + ) + .data + .address!; + addrType = AddressType.p2sh; + break; + case DerivePathType.bip84: + addressString = btc_dart + .P2WPKH( + network: network, + data: data, + ) + .data + .address!; + addrType = AddressType.p2wpkh; + break; } final address = Address( @@ -704,4 +708,68 @@ extension PayNym on DogecoinWallet { return address; } + + Future
getMyNotificationAddress( + DerivePathType derivePathType, + ) async { + AddressType type; + switch (derivePathType) { + case DerivePathType.bip44: + type = AddressType.p2pkh; + break; + case DerivePathType.bip49: + type = AddressType.p2sh; + break; + case DerivePathType.bip84: + type = AddressType.p2wpkh; + break; + } + + final storedAddress = await db + .getAddresses(walletId) + .filter() + .subTypeEqualTo(AddressSubType.paynymNotification) + .and() + .typeEqualTo(type) + .and() + .not() + .typeEqualTo(AddressType.nonWallet) + .findFirst(); + + if (storedAddress != null) { + return storedAddress; + } else { + final root = await getRootNode(mnemonic: await mnemonic); + final node = root.derivePath(kPaynymDerivePath); + final paymentCode = PaymentCode.initFromPubKey( + node.publicKey, + node.chainCode, + network, + ); + + String addressString; + switch (derivePathType) { + case DerivePathType.bip44: + addressString = paymentCode.notificationAddress(); + break; + case DerivePathType.bip49: + throw Exception("DerivePathType not supported."); + case DerivePathType.bip84: + throw Exception("DerivePathType not supported."); + } + + final address = Address( + walletId: walletId, + value: addressString, + publicKey: paymentCode.getPubKey(), + derivationIndex: 0, + type: type, + subType: AddressSubType.paynymNotification, + otherData: paymentCode.toString(), + ); + + await db.putAddress(address); + return address; + } + } } From 79db4f048cdacc3d40bc74d69c1f026ab9283c29 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 13:49:14 -0600 Subject: [PATCH 19/55] use derive path type extension method per coin --- .../coins/bitcoin/bitcoin_wallet.dart | 22 ++++++------ .../coins/bitcoincash/bitcoincash_wallet.dart | 24 ++++++------- .../coins/dogecoin/dogecoin_wallet.dart | 22 ++++++------ .../coins/litecoin/litecoin_wallet.dart | 22 ++++++------ .../coins/namecoin/namecoin_wallet.dart | 22 ++++++------ .../coins/particl/particl_wallet.dart | 22 ++++++------ .../enums/derive_path_type_enum.dart | 36 ++++++++++++++++++- 7 files changed, 102 insertions(+), 68 deletions(-) diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart index 2194c5a19..82e5f646d 100644 --- a/lib/services/coins/bitcoin/bitcoin_wallet.dart +++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart @@ -193,7 +193,7 @@ class BitcoinWallet extends CoinServiceAPI .subTypeEqualTo(isar_models.AddressSubType.receiving) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(0, 0, DerivePathType.bip84); + await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin)); Future get currentChangeAddress async => (await _currentChangeAddress).value; @@ -206,7 +206,7 @@ class BitcoinWallet extends CoinServiceAPI .subTypeEqualTo(isar_models.AddressSubType.change) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(1, 0, DerivePathType.bip84); + await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin)); @override Future exit() async { @@ -1868,7 +1868,7 @@ class BitcoinWallet extends CoinServiceAPI // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip84); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1887,7 +1887,7 @@ class BitcoinWallet extends CoinServiceAPI } } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -1907,7 +1907,7 @@ class BitcoinWallet extends CoinServiceAPI // Use new index to derive a new change address final newChangeAddress = await _generateAddressForChain( - 1, newChangeIndex, DerivePathType.bip84); + 1, newChangeIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1926,12 +1926,12 @@ class BitcoinWallet extends CoinServiceAPI } } on SocketException catch (se, s) { Logging.instance.log( - "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $se\n$s", + "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s", level: LogLevel.Error); return; } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -2269,7 +2269,7 @@ class BitcoinWallet extends CoinServiceAPI utxoSigningData: utxoSigningData, recipients: [ _recipientAddress, - await _getCurrentAddressForChain(1, DerivePathType.bip84), + await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)), ], satoshiAmounts: [ satoshiAmountToSend, @@ -2308,8 +2308,8 @@ class BitcoinWallet extends CoinServiceAPI feeForTwoOutputs) { // generate new change address if current change address has been used await _checkChangeAddressForTransactions(); - final String newChangeAddress = - await _getCurrentAddressForChain(1, DerivePathType.bip84); + final String newChangeAddress = await _getCurrentAddressForChain( + 1, DerivePathTypeExt.primaryFor(coin)); int feeBeingPaid = satoshisBeingUsed - satoshiAmountToSend - changeOutputSize; @@ -3035,7 +3035,7 @@ class BitcoinWallet extends CoinServiceAPI // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip84); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); // Add that new receiving address await db.putAddress(newReceivingAddress); diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index 84f302dec..969eb1815 100644 --- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart +++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart @@ -169,7 +169,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { .subTypeEqualTo(isar_models.AddressSubType.receiving) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(0, 0, DerivePathType.bip44); + await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin)); Future get currentChangeAddress async => (await _currentChangeAddress).value; @@ -182,7 +182,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { .subTypeEqualTo(isar_models.AddressSubType.change) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(1, 0, DerivePathType.bip44); + await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin)); @override Future exit() async { @@ -1754,7 +1754,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip44); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1773,12 +1773,12 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { } } on SocketException catch (se, s) { Logging.instance.log( - "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip44}): $se\n$s", + "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s", level: LogLevel.Error); return; } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip44}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -1798,7 +1798,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { // Use new index to derive a new change address final newChangeAddress = await _generateAddressForChain( - 1, newChangeIndex, DerivePathType.bip44); + 1, newChangeIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1817,12 +1817,12 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { } } on SocketException catch (se, s) { Logging.instance.log( - "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip44}): $se\n$s", + "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s", level: LogLevel.Error); return; } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip44}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -2348,7 +2348,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { utxoSigningData: utxoSigningData, recipients: [ _recipientAddress, - await _getCurrentAddressForChain(1, DerivePathType.bip44), + await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)), ], satoshiAmounts: [ satoshiAmountToSend, @@ -2401,8 +2401,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { feeForTwoOutputs) { // generate new change address if current change address has been used await _checkChangeAddressForTransactions(); - final String newChangeAddress = - await _getCurrentAddressForChain(1, DerivePathType.bip44); + final String newChangeAddress = await _getCurrentAddressForChain( + 1, DerivePathTypeExt.primaryFor(coin)); int feeBeingPaid = satoshisBeingUsed - satoshiAmountToSend - changeOutputSize; @@ -3001,7 +3001,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB { // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip44); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); // Add that new receiving address await db.putAddress(newReceivingAddress); diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index c8cc68f8e..b276af965 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -168,7 +168,7 @@ class DogecoinWallet extends CoinServiceAPI .subTypeEqualTo(isar_models.AddressSubType.receiving) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(0, 0, DerivePathType.bip44); + await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin)); // @override Future get currentChangeAddress async => @@ -182,7 +182,7 @@ class DogecoinWallet extends CoinServiceAPI .subTypeEqualTo(isar_models.AddressSubType.change) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(1, 0, DerivePathType.bip44); + await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin)); @override Future exit() async { @@ -1657,7 +1657,7 @@ class DogecoinWallet extends CoinServiceAPI // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip44); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1676,12 +1676,12 @@ class DogecoinWallet extends CoinServiceAPI } } on SocketException catch (se, s) { Logging.instance.log( - "SocketException caught in _checkReceivingAddressForTransactions($DerivePathType.bip44): $se\n$s", + "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s", level: LogLevel.Error); return; } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions($DerivePathType.bip44): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -1701,7 +1701,7 @@ class DogecoinWallet extends CoinServiceAPI // Use new index to derive a new change address final newChangeAddress = await _generateAddressForChain( - 1, newChangeIndex, DerivePathType.bip44); + 1, newChangeIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1720,7 +1720,7 @@ class DogecoinWallet extends CoinServiceAPI } } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkChangeAddressForTransactions(${DerivePathType.bip44}): $e\n$s", + "Exception rethrown from _checkChangeAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -2089,7 +2089,7 @@ class DogecoinWallet extends CoinServiceAPI utxoSigningData: utxoSigningData, recipients: [ _recipientAddress, - await _getCurrentAddressForChain(1, DerivePathType.bip44), + await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)), ], satoshiAmounts: [ satoshiAmountToSend, @@ -2142,8 +2142,8 @@ class DogecoinWallet extends CoinServiceAPI feeForTwoOutputs) { // generate new change address if current change address has been used await checkChangeAddressForTransactions(); - final String newChangeAddress = - await _getCurrentAddressForChain(1, DerivePathType.bip44); + final String newChangeAddress = await _getCurrentAddressForChain( + 1, DerivePathTypeExt.primaryFor(coin)); int feeBeingPaid = satoshisBeingUsed - satoshiAmountToSend - changeOutputSize; @@ -2760,7 +2760,7 @@ class DogecoinWallet extends CoinServiceAPI // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip44); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); // Add that new receiving address await db.putAddress(newReceivingAddress); diff --git a/lib/services/coins/litecoin/litecoin_wallet.dart b/lib/services/coins/litecoin/litecoin_wallet.dart index aed4182a8..be93d478f 100644 --- a/lib/services/coins/litecoin/litecoin_wallet.dart +++ b/lib/services/coins/litecoin/litecoin_wallet.dart @@ -193,7 +193,7 @@ class LitecoinWallet extends CoinServiceAPI .subTypeEqualTo(isar_models.AddressSubType.receiving) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(0, 0, DerivePathType.bip84); + await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin)); Future get currentChangeAddress async => (await _currentChangeAddress).value; @@ -206,7 +206,7 @@ class LitecoinWallet extends CoinServiceAPI .subTypeEqualTo(isar_models.AddressSubType.change) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(1, 0, DerivePathType.bip84); + await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin)); @override Future exit() async { @@ -1891,7 +1891,7 @@ class LitecoinWallet extends CoinServiceAPI // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip84); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1910,7 +1910,7 @@ class LitecoinWallet extends CoinServiceAPI } } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -1930,7 +1930,7 @@ class LitecoinWallet extends CoinServiceAPI // Use new index to derive a new change address final newChangeAddress = await _generateAddressForChain( - 1, newChangeIndex, DerivePathType.bip84); + 1, newChangeIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1949,12 +1949,12 @@ class LitecoinWallet extends CoinServiceAPI } } on SocketException catch (se, s) { Logging.instance.log( - "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $se\n$s", + "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s", level: LogLevel.Error); return; } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -2349,7 +2349,7 @@ class LitecoinWallet extends CoinServiceAPI utxoSigningData: utxoSigningData, recipients: [ _recipientAddress, - await _getCurrentAddressForChain(1, DerivePathType.bip84), + await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)), ], satoshiAmounts: [ satoshiAmountToSend, @@ -2388,8 +2388,8 @@ class LitecoinWallet extends CoinServiceAPI feeForTwoOutputs) { // generate new change address if current change address has been used await _checkChangeAddressForTransactions(); - final String newChangeAddress = - await _getCurrentAddressForChain(1, DerivePathType.bip84); + final String newChangeAddress = await _getCurrentAddressForChain( + 1, DerivePathTypeExt.primaryFor(coin)); int feeBeingPaid = satoshisBeingUsed - satoshiAmountToSend - changeOutputSize; @@ -3345,7 +3345,7 @@ class LitecoinWallet extends CoinServiceAPI // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip84); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); // Add that new receiving address await db.putAddress(newReceivingAddress); diff --git a/lib/services/coins/namecoin/namecoin_wallet.dart b/lib/services/coins/namecoin/namecoin_wallet.dart index 2805f5412..2cf0e8ef5 100644 --- a/lib/services/coins/namecoin/namecoin_wallet.dart +++ b/lib/services/coins/namecoin/namecoin_wallet.dart @@ -188,7 +188,7 @@ class NamecoinWallet extends CoinServiceAPI .subTypeEqualTo(isar_models.AddressSubType.receiving) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(0, 0, DerivePathType.bip84); + await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin)); Future get currentChangeAddress async => (await _currentChangeAddress).value; @@ -201,7 +201,7 @@ class NamecoinWallet extends CoinServiceAPI .subTypeEqualTo(isar_models.AddressSubType.change) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(1, 0, DerivePathType.bip84); + await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin)); @override Future exit() async { @@ -1873,7 +1873,7 @@ class NamecoinWallet extends CoinServiceAPI // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip84); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1892,7 +1892,7 @@ class NamecoinWallet extends CoinServiceAPI } } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -1912,7 +1912,7 @@ class NamecoinWallet extends CoinServiceAPI // Use new index to derive a new change address final newChangeAddress = await _generateAddressForChain( - 1, newChangeIndex, DerivePathType.bip84); + 1, newChangeIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1932,12 +1932,12 @@ class NamecoinWallet extends CoinServiceAPI } } on SocketException catch (se, s) { Logging.instance.log( - "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $se\n$s", + "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s", level: LogLevel.Error); return; } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -2336,7 +2336,7 @@ class NamecoinWallet extends CoinServiceAPI utxoSigningData: utxoSigningData, recipients: [ _recipientAddress, - await _getCurrentAddressForChain(1, DerivePathType.bip84), + await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)), ], satoshiAmounts: [ satoshiAmountToSend, @@ -2375,8 +2375,8 @@ class NamecoinWallet extends CoinServiceAPI feeForTwoOutputs) { // generate new change address if current change address has been used await _checkChangeAddressForTransactions(); - final String newChangeAddress = - await _getCurrentAddressForChain(1, DerivePathType.bip84); + final String newChangeAddress = await _getCurrentAddressForChain( + 1, DerivePathTypeExt.primaryFor(coin)); int feeBeingPaid = satoshisBeingUsed - satoshiAmountToSend - changeOutputSize; @@ -3336,7 +3336,7 @@ class NamecoinWallet extends CoinServiceAPI // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip84); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); // Add that new receiving address await db.putAddress(newReceivingAddress); diff --git a/lib/services/coins/particl/particl_wallet.dart b/lib/services/coins/particl/particl_wallet.dart index 22b90d05f..4f822d87a 100644 --- a/lib/services/coins/particl/particl_wallet.dart +++ b/lib/services/coins/particl/particl_wallet.dart @@ -183,7 +183,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { .subTypeEqualTo(isar_models.AddressSubType.receiving) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(0, 0, DerivePathType.bip84); + await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin)); Future get currentChangeAddress async => (await _currentChangeAddress).value; @@ -196,7 +196,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { .subTypeEqualTo(isar_models.AddressSubType.change) .sortByDerivationIndexDesc() .findFirst()) ?? - await _generateAddressForChain(1, 0, DerivePathType.bip84); + await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin)); @override Future exit() async { @@ -1766,7 +1766,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip84); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1785,7 +1785,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { } } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -1805,7 +1805,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { // Use new index to derive a new change address final newChangeAddress = await _generateAddressForChain( - 1, newChangeIndex, DerivePathType.bip84); + 1, newChangeIndex, DerivePathTypeExt.primaryFor(coin)); final existing = await db .getAddresses(walletId) @@ -1824,12 +1824,12 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { } } on SocketException catch (se, s) { Logging.instance.log( - "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $se\n$s", + "SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s", level: LogLevel.Error); return; } catch (e, s) { Logging.instance.log( - "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s", + "Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s", level: LogLevel.Error); rethrow; } @@ -2506,7 +2506,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { utxoSigningData: utxoSigningData, recipients: [ _recipientAddress, - await _getCurrentAddressForChain(1, DerivePathType.bip84), + await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)), ], satoshiAmounts: [ satoshiAmountToSend, @@ -2545,8 +2545,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { feeForTwoOutputs) { // generate new change address if current change address has been used await _checkChangeAddressForTransactions(); - final String newChangeAddress = - await _getCurrentAddressForChain(1, DerivePathType.bip84); + final String newChangeAddress = await _getCurrentAddressForChain( + 1, DerivePathTypeExt.primaryFor(coin)); int feeBeingPaid = satoshisBeingUsed - satoshiAmountToSend - changeOutputSize; @@ -3335,7 +3335,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB { // Use new index to derive a new receiving address final newReceivingAddress = await _generateAddressForChain( - 0, newReceivingIndex, DerivePathType.bip84); + 0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin)); // Add that new receiving address await db.putAddress(newReceivingAddress); diff --git a/lib/utilities/enums/derive_path_type_enum.dart b/lib/utilities/enums/derive_path_type_enum.dart index 694b9158f..55f103d45 100644 --- a/lib/utilities/enums/derive_path_type_enum.dart +++ b/lib/utilities/enums/derive_path_type_enum.dart @@ -1 +1,35 @@ -enum DerivePathType { bip44, bip49, bip84 } +import 'package:stackwallet/utilities/enums/coin_enum.dart'; + +enum DerivePathType { + bip44, + bip49, + bip84, +} + +extension DerivePathTypeExt on DerivePathType { + static DerivePathType primaryFor(Coin coin) { + switch (coin) { + case Coin.bitcoincash: + case Coin.bitcoincashTestnet: + case Coin.dogecoin: + case Coin.dogecoinTestNet: + case Coin.firo: + case Coin.firoTestNet: + return DerivePathType.bip44; + + case Coin.bitcoin: + case Coin.bitcoinTestNet: + case Coin.litecoin: + case Coin.litecoinTestNet: + case Coin.namecoin: + case Coin.particl: + return DerivePathType.bip84; + + case Coin.epicCash: + case Coin.monero: + case Coin.wownero: + throw UnsupportedError( + "$coin does not use bitcoin style derivation paths"); + } + } +} From 9c44dc6c6b31ff766a676bc401269481e84cba49 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 14:33:59 -0600 Subject: [PATCH 20/55] add support to make adding segwit paynym support simple once implemented --- lib/pages/paynym/paynym_claim_view.dart | 4 +- .../sub_widgets/wallet_navigation_bar.dart | 4 +- .../wallet_view/desktop_wallet_view.dart | 4 +- lib/services/coins/coin_paynym_extension.dart | 184 +++++++++++------- .../paynym_follow_toggle_button.dart | 7 +- pubspec.lock | 4 +- pubspec.yaml | 2 +- 7 files changed, 129 insertions(+), 80 deletions(-) diff --git a/lib/pages/paynym/paynym_claim_view.dart b/lib/pages/paynym/paynym_claim_view.dart index cf5ffc671..f141e04a4 100644 --- a/lib/pages/paynym/paynym_claim_view.dart +++ b/lib/pages/paynym/paynym_claim_view.dart @@ -12,6 +12,7 @@ import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.da import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; @@ -168,7 +169,8 @@ class _PaynymClaimViewState extends ConsumerState { if (shouldCancel) return; // get payment code - final pCode = await wallet.getPaymentCode(); + final pCode = await wallet.getPaymentCode( + DerivePathTypeExt.primaryFor(wallet.coin)); if (shouldCancel) return; diff --git a/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart b/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart index 28b4e735c..f251dedd4 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart @@ -12,6 +12,7 @@ import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; @@ -120,7 +121,8 @@ class _WalletNavigationBarState extends State { .getManager(widget.walletId) .wallet as DogecoinWallet); - final code = await wallet.getPaymentCode(); + final code = await wallet.getPaymentCode( + DerivePathTypeExt.primaryFor(wallet.coin)); final account = await ref .read(paynymAPIProvider) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart index d4a77bae8..d48646860 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -31,6 +31,7 @@ import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; @@ -304,7 +305,8 @@ class _DesktopWalletViewState extends ConsumerState { .getManager(widget.walletId) .wallet as DogecoinWallet); - final code = await wallet.getPaymentCode(); + final code = + await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(wallet.coin)); final account = await ref.read(paynymAPIProvider).nym(code.toString()); diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index f80f78961..7a631e154 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -14,12 +14,11 @@ import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/utilities/bip32_utils.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:tuple/tuple.dart'; -import '../../utilities/enums/derive_path_type_enum.dart'; - const kPaynymDerivePath = "m/47'/0'/0'"; extension PayNym on DogecoinWallet { @@ -66,8 +65,10 @@ extension PayNym on DogecoinWallet { } Future>> preparePaymentCodeSend( - PaymentCode paymentCode, int satoshiAmount) async { - if (!(await hasConnected(paymentCode.notificationAddress()))) { + {required PaymentCode paymentCode, + required int satoshiAmount, + Map? args}) async { + if (!(await hasConnected(paymentCode.notificationAddressP2PKH()))) { throw PaynymSendException( "No notification transaction sent to $paymentCode"); } else { @@ -360,7 +361,8 @@ extension PayNym on DogecoinWallet { txPointIndex, ); - txb.addOutput(targetPaymentCode.notificationAddress(), DUST_LIMIT); + // todo: modify address once segwit support is in our bip47 + txb.addOutput(targetPaymentCode.notificationAddressP2PKH(), DUST_LIMIT); txb.addOutput(opReturnScript, 0); // TODO: add possible change output and mark output as dangerous @@ -420,8 +422,8 @@ extension PayNym on DogecoinWallet { // TODO optimize Future hasConnected(String paymentCodeString) async { - final myCode = await getPaymentCode(DerivePathType.bip44); - final myNotificationAddress = myCode.notificationAddress(); + final myNotificationAddress = + await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); final txns = await db .getTransactions(walletId) @@ -431,13 +433,13 @@ extension PayNym on DogecoinWallet { for (final tx in txns) { // quick check that may cause problems? - if (tx.address.value?.value == myNotificationAddress) { + if (tx.address.value?.value == myNotificationAddress.value) { return true; } final unBlindedPaymentCode = await unBlindedPaymentCodeFromTransaction( transaction: tx, - myCode: myCode, + myNotificationAddress: myNotificationAddress, ); if (paymentCodeString == unBlindedPaymentCode.toString()) { @@ -451,10 +453,10 @@ extension PayNym on DogecoinWallet { Future unBlindedPaymentCodeFromTransaction({ required Transaction transaction, - required PaymentCode myCode, + required Address myNotificationAddress, }) async { if (transaction.address.value != null && - transaction.address.value!.value != myCode.notificationAddress()) { + transaction.address.value!.value != myNotificationAddress.value) { return null; } @@ -498,7 +500,8 @@ extension PayNym on DogecoinWallet { Future> getAllPaymentCodesFromNotificationTransactions() async { - final myCode = await getPaymentCode(DerivePathType.bip44); + final myAddress = + await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); final txns = await db .getTransactions(walletId) .filter() @@ -510,7 +513,7 @@ extension PayNym on DogecoinWallet { for (final tx in txns) { final unBlinded = await unBlindedPaymentCodeFromTransaction( transaction: tx, - myCode: myCode, + myNotificationAddress: myAddress, ); if (unBlinded != null) { unBlindedList.add(unBlinded); @@ -603,32 +606,34 @@ extension PayNym on DogecoinWallet { btc_dart.P2PKH(data: data, network: network).data.address!; break; - // The following doesn't apply to doge currently - case DerivePathType.bip49: - addressString = btc_dart - .P2SH( - data: btc_dart.PaymentData( - redeem: btc_dart - .P2WPKH( - data: data, - network: network, - ) - .data), - network: network, - ) - .data - .address!; - break; - - case DerivePathType.bip84: - addressString = btc_dart - .P2WPKH( - network: network, - data: data, - ) - .data - .address!; - break; + // The following doesn't apply currently + // case DerivePathType.bip49: + // addressString = btc_dart + // .P2SH( + // data: btc_dart.PaymentData( + // redeem: btc_dart + // .P2WPKH( + // data: data, + // network: network, + // ) + // .data), + // network: network, + // ) + // .data + // .address!; + // break; + // + // case DerivePathType.bip84: + // addressString = btc_dart + // .P2WPKH( + // network: network, + // data: data, + // ) + // .data + // .address!; + // break; + default: + throw UnimplementedError("segwit paynyms not implemented yet"); } final address = Address( @@ -666,34 +671,36 @@ extension PayNym on DogecoinWallet { addrType = AddressType.p2pkh; break; - // The following doesn't apply to doge currently - case DerivePathType.bip49: - addressString = btc_dart - .P2SH( - data: btc_dart.PaymentData( - redeem: btc_dart - .P2WPKH( - data: data, - network: network, - ) - .data), - network: network, - ) - .data - .address!; - addrType = AddressType.p2sh; - break; - - case DerivePathType.bip84: - addressString = btc_dart - .P2WPKH( - network: network, - data: data, - ) - .data - .address!; - addrType = AddressType.p2wpkh; - break; + // The following doesn't apply currently + // case DerivePathType.bip49: + // addressString = btc_dart + // .P2SH( + // data: btc_dart.PaymentData( + // redeem: btc_dart + // .P2WPKH( + // data: data, + // network: network, + // ) + // .data), + // network: network, + // ) + // .data + // .address!; + // addrType = AddressType.p2sh; + // break; + // + // case DerivePathType.bip84: + // addressString = btc_dart + // .P2WPKH( + // network: network, + // data: data, + // ) + // .data + // .address!; + // addrType = AddressType.p2wpkh; + // break; + default: + throw UnimplementedError("segwit paynyms not implemented yet"); } final address = Address( @@ -712,6 +719,9 @@ extension PayNym on DogecoinWallet { Future
getMyNotificationAddress( DerivePathType derivePathType, ) async { + // TODO: fix when segwit is here + derivePathType = DerivePathType.bip44; + AddressType type; switch (derivePathType) { case DerivePathType.bip44: @@ -748,14 +758,44 @@ extension PayNym on DogecoinWallet { ); String addressString; + final data = + btc_dart.PaymentData(pubkey: paymentCode.notificationPublicKey()); switch (derivePathType) { case DerivePathType.bip44: - addressString = paymentCode.notificationAddress(); + addressString = btc_dart + .P2PKH( + data: data, + network: network, + ) + .data + .address!; break; - case DerivePathType.bip49: - throw Exception("DerivePathType not supported."); - case DerivePathType.bip84: - throw Exception("DerivePathType not supported."); + // case DerivePathType.bip49: + // addressString = btc_dart + // .P2SH( + // data: btc_dart.PaymentData( + // redeem: btc_dart + // .P2WPKH( + // data: data, + // network: network, + // ) + // .data), + // network: network, + // ) + // .data + // .address!; + // break; + // case DerivePathType.bip84: + // addressString = btc_dart + // .P2WPKH( + // network: network, + // data: data, + // ) + // .data + // .address!; + // break; + default: + throw UnimplementedError("segwit paynyms not implemented yet"); } final address = Address( diff --git a/lib/widgets/custom_buttons/paynym_follow_toggle_button.dart b/lib/widgets/custom_buttons/paynym_follow_toggle_button.dart index ea3771d95..a93a4510c 100644 --- a/lib/widgets/custom_buttons/paynym_follow_toggle_button.dart +++ b/lib/widgets/custom_buttons/paynym_follow_toggle_button.dart @@ -12,6 +12,7 @@ import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.da import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; @@ -67,7 +68,8 @@ class _PaynymFollowToggleButtonState .read(paynymAPIProvider) .nym(widget.paymentCodeStringToFollow, true); - final myPCode = await wallet.getPaymentCode(); + final myPCode = + await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(wallet.coin)); PaynymResponse token = await ref.read(paynymAPIProvider).token(myPCode.toString()); @@ -167,7 +169,8 @@ class _PaynymFollowToggleButtonState .read(paynymAPIProvider) .nym(widget.paymentCodeStringToFollow, true); - final myPCode = await wallet.getPaymentCode(); + final myPCode = + await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(wallet.coin)); PaynymResponse token = await ref.read(paynymAPIProvider).token(myPCode.toString()); diff --git a/pubspec.lock b/pubspec.lock index 0c8768e2a..8721ccc48 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -100,8 +100,8 @@ packages: dependency: "direct main" description: path: "." - ref: "2d800225329498841affa1386d96d2696c62b713" - resolved-ref: "2d800225329498841affa1386d96d2696c62b713" + ref: "87bb760be323228aed6ca7bd4532a709a4f10690" + resolved-ref: "87bb760be323228aed6ca7bd4532a709a4f10690" url: "https://github.com/cypherstack/bip47.git" source: git version: "1.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 967c9cba4..759fc51f5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,7 +59,7 @@ dependencies: bip47: git: url: https://github.com/cypherstack/bip47.git - ref: 2d800225329498841affa1386d96d2696c62b713 + ref: 87bb760be323228aed6ca7bd4532a709a4f10690 # Utility plugins # provider: ^6.0.1 From 907c380812be5ac485efb44645df5dcf425264a6 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 15:07:44 -0600 Subject: [PATCH 21/55] copy extension into a mixin --- lib/services/mixins/paynym_support.dart | 899 ++++++++++++++++++++++++ 1 file changed, 899 insertions(+) create mode 100644 lib/services/mixins/paynym_support.dart diff --git a/lib/services/mixins/paynym_support.dart b/lib/services/mixins/paynym_support.dart new file mode 100644 index 000000000..3db2ec602 --- /dev/null +++ b/lib/services/mixins/paynym_support.dart @@ -0,0 +1,899 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:bip32/bip32.dart' as bip32; +import 'package:bip47/bip47.dart'; +import 'package:bip47/src/util.dart'; +import 'package:bitcoindart/bitcoindart.dart' as btc_dart; +import 'package:bitcoindart/src/utils/constants/op.dart' as op; +import 'package:bitcoindart/src/utils/script.dart' as bscript; +import 'package:isar/isar.dart'; +import 'package:pointycastle/digests/sha256.dart'; +import 'package:stackwallet/db/main_db.dart'; +import 'package:stackwallet/electrumx_rpc/electrumx.dart'; +import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; +import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; +import 'package:stackwallet/models/isar/models/isar_models.dart'; +import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; +import 'package:stackwallet/utilities/bip32_utils.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; +import 'package:stackwallet/utilities/format.dart'; +import 'package:stackwallet/utilities/logger.dart'; +import 'package:tuple/tuple.dart'; + +const kPaynymDerivePath = "m/47'/0'/0'"; + +mixin PaynymSupport { + // passed in wallet data + late final String walletId; + late final String walletName; + late final btc_dart.NetworkType network; + late final Coin coin; + late final MainDB db; + late final ElectrumX electrumXClient; + + // passed in wallet functions + late final Future> Function() getMnemonic; + late final Future Function() getChainHeight; + late final Future Function() getCurrentChangeAddress; + late final int Function({ + required int vSize, + required int feeRatePerKB, + }) estimateTxFee; + late final Future> Function({ + required String address, + required int satoshiAmount, + Map? args, + }) prepareSend; + late final Future Function({ + required String address, + }) getTxCount; + late final Future> Function( + List utxosToUse, + ) fetchBuildTxData; + late final Future Function() refresh; + late final Future Function() checkChangeAddressForTransactions; + + // initializer + void initPaynymSupport({ + required String walletId, + required String walletName, + required btc_dart.NetworkType network, + required Coin coin, + required MainDB db, + required ElectrumX electrumXClient, + required Future> Function() getMnemonic, + required Future Function() getChainHeight, + required Future Function() getCurrentChangeAddress, + required int Function({ + required int vSize, + required int feeRatePerKB, + }) + estimateTxFee, + required Future> Function({ + required String address, + required int satoshiAmount, + Map? args, + }) + prepareSend, + required Future Function({ + required String address, + }) + getTxCount, + required Future> Function( + List utxosToUse, + ) + fetchBuildTxData, + required Future Function() refresh, + required Future Function() checkChangeAddressForTransactions, + }) { + this.walletId = walletId; + this.walletName = walletName; + this.network = network; + this.coin = coin; + this.db = db; + this.electrumXClient = electrumXClient; + this.getMnemonic = getMnemonic; + this.getChainHeight = getChainHeight; + this.getCurrentChangeAddress = getCurrentChangeAddress; + this.estimateTxFee = estimateTxFee; + this.prepareSend = prepareSend; + this.getTxCount = getTxCount; + this.fetchBuildTxData = fetchBuildTxData; + this.refresh = refresh; + this.checkChangeAddressForTransactions = checkChangeAddressForTransactions; + } + + // generate bip32 payment code root + Future getRootNode({ + required List mnemonic, + }) async { + final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), network); + return root; + } + + Future deriveNotificationPrivateKey({ + required List mnemonic, + }) async { + final root = await getRootNode(mnemonic: mnemonic); + final node = root.derivePath(kPaynymDerivePath).derive(0); + return node.privateKey!; + } + + /// fetch or generate this wallet's bip47 payment code + Future getPaymentCode( + DerivePathType derivePathType, + ) async { + final address = await getMyNotificationAddress(derivePathType); + final paymentCode = PaymentCode.fromPaymentCode( + address.otherData!, + network, + ); + return paymentCode; + } + + Future signWithNotificationKey(Uint8List data) async { + final privateKey = + await deriveNotificationPrivateKey(mnemonic: await getMnemonic()); + final pair = btc_dart.ECPair.fromPrivateKey(privateKey, network: network); + final signed = pair.sign(SHA256Digest().process(data)); + return signed; + } + + Future signStringWithNotificationKey(String data) async { + final bytes = + await signWithNotificationKey(Uint8List.fromList(utf8.encode(data))); + return Format.uint8listToString(bytes); + } + + Future>> preparePaymentCodeSend( + {required PaymentCode paymentCode, + required int satoshiAmount, + Map? args}) async { + if (!(await hasConnected(paymentCode.notificationAddressP2PKH()))) { + throw PaynymSendException( + "No notification transaction sent to $paymentCode"); + } else { + final myPrivateKey = + await deriveNotificationPrivateKey(mnemonic: await getMnemonic()); + final sendToAddress = await nextUnusedSendAddressFrom( + pCode: paymentCode, + privateKey: myPrivateKey, + ); + + return prepareSend( + address: sendToAddress.value, satoshiAmount: satoshiAmount); + } + } + + /// get the next unused address to send to given the receiver's payment code + /// and your own private key + Future
nextUnusedSendAddressFrom({ + required PaymentCode pCode, + required Uint8List privateKey, + int startIndex = 0, + }) async { + // https://en.bitcoin.it/wiki/BIP_0047#Path_levels + const maxCount = 2147483647; + + for (int i = startIndex; i < maxCount; i++) { + final address = await db + .getAddresses(walletId) + .filter() + .subTypeEqualTo(AddressSubType.paynymSend) + .and() + .otherDataEqualTo(pCode.toString()) + .and() + .derivationIndexEqualTo(i) + .findFirst(); + + if (address != null) { + final count = await getTxCount(address: address.value); + // return address if unused, otherwise continue to next index + if (count == 0) { + return address; + } + } else { + final pair = PaymentAddress.initWithPrivateKey( + privateKey, + pCode, + i, // index to use + ).getSendAddressKeyPair(); + + // add address to local db + final address = generatePaynymSendAddressFromKeyPair( + pair: pair, + derivationIndex: i, + derivePathType: DerivePathType.bip44, + toPaymentCode: pCode, + ); + await db.putAddress(address); + + final count = await getTxCount(address: address.value); + // return address if unused, otherwise continue to next index + if (count == 0) { + return address; + } + } + } + + throw PaynymSendException("Exhausted unused send addresses!"); + } + + Future> prepareNotificationTx({ + required int selectedTxFeeRate, + required String targetPaymentCodeString, + int additionalOutputs = 0, + List? utxos, + }) async { + const amountToSend = DUST_LIMIT; + final List availableOutputs = + utxos ?? await db.getUTXOs(walletId).findAll(); + final List spendableOutputs = []; + int spendableSatoshiValue = 0; + + // Build list of spendable outputs and totaling their satoshi amount + for (var i = 0; i < availableOutputs.length; i++) { + if (availableOutputs[i].isBlocked == false && + availableOutputs[i] + .isConfirmed(await getChainHeight(), MINIMUM_CONFIRMATIONS) == + true) { + spendableOutputs.add(availableOutputs[i]); + spendableSatoshiValue += availableOutputs[i].value; + } + } + + if (spendableSatoshiValue < amountToSend) { + // insufficient balance + throw InsufficientBalanceException( + "Spendable balance is less than the minimum required for a notification transaction."); + } else if (spendableSatoshiValue == amountToSend) { + // insufficient balance due to missing amount to cover fee + throw InsufficientBalanceException( + "Remaining balance does not cover the network fee."); + } + + // sort spendable by age (oldest first) + spendableOutputs.sort((a, b) => b.blockTime!.compareTo(a.blockTime!)); + + int satoshisBeingUsed = 0; + int outputsBeingUsed = 0; + List utxoObjectsToUse = []; + + for (int i = 0; + satoshisBeingUsed < amountToSend && i < spendableOutputs.length; + i++) { + utxoObjectsToUse.add(spendableOutputs[i]); + satoshisBeingUsed += spendableOutputs[i].value; + outputsBeingUsed += 1; + } + + // add additional outputs if required + for (int i = 0; + i < additionalOutputs && outputsBeingUsed < spendableOutputs.length; + i++) { + utxoObjectsToUse.add(spendableOutputs[outputsBeingUsed]); + satoshisBeingUsed += spendableOutputs[outputsBeingUsed].value; + outputsBeingUsed += 1; + } + + // gather required signing data + final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); + + final int vSizeForNoChange = (await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: 0)) + .item2; + + final int vSizeForWithChange = (await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: satoshisBeingUsed - amountToSend)) + .item2; + + // Assume 2 outputs, for recipient and payment code script + int feeForNoChange = estimateTxFee( + vSize: vSizeForNoChange, + feeRatePerKB: selectedTxFeeRate, + ); + + // Assume 3 outputs, for recipient, payment code script, and change + int feeForWithChange = estimateTxFee( + vSize: vSizeForWithChange, + feeRatePerKB: selectedTxFeeRate, + ); + + if (feeForNoChange < vSizeForNoChange * 1000) { + feeForNoChange = vSizeForNoChange * 1000; + } + if (feeForWithChange < vSizeForWithChange * 1000) { + feeForWithChange = vSizeForWithChange * 1000; + } + + if (satoshisBeingUsed - amountToSend > feeForNoChange + DUST_LIMIT) { + // try to add change output due to "left over" amount being greater than + // the estimated fee + the dust limit + int changeAmount = satoshisBeingUsed - amountToSend - feeForWithChange; + + // check estimates are correct and build notification tx + if (changeAmount >= DUST_LIMIT && + satoshisBeingUsed - amountToSend - changeAmount == feeForWithChange) { + final txn = await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: changeAmount, + ); + + int feeBeingPaid = satoshisBeingUsed - amountToSend - changeAmount; + + Map transactionObject = { + "hex": txn.item1, + "recipientPaynym": targetPaymentCodeString, + "amount": amountToSend, + "fee": feeBeingPaid, + "vSize": txn.item2, + }; + return transactionObject; + } else { + // something broke during fee estimation or the change amount is smaller + // than the dust limit. Try without change + final txn = await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: 0, + ); + + int feeBeingPaid = satoshisBeingUsed - amountToSend; + + Map transactionObject = { + "hex": txn.item1, + "recipientPaynym": targetPaymentCodeString, + "amount": amountToSend, + "fee": feeBeingPaid, + "vSize": txn.item2, + }; + return transactionObject; + } + } else if (satoshisBeingUsed - amountToSend >= feeForNoChange) { + // since we already checked if we need to add a change output we can just + // build without change here + final txn = await _createNotificationTx( + targetPaymentCodeString: targetPaymentCodeString, + utxosToUse: utxoObjectsToUse, + utxoSigningData: utxoSigningData, + change: 0, + ); + + int feeBeingPaid = satoshisBeingUsed - amountToSend; + + Map transactionObject = { + "hex": txn.item1, + "recipientPaynym": targetPaymentCodeString, + "amount": amountToSend, + "fee": feeBeingPaid, + "vSize": txn.item2, + }; + return transactionObject; + } else { + // if we get here we do not have enough funds to cover the tx total so we + // check if we have any more available outputs and try again + if (spendableOutputs.length > outputsBeingUsed) { + return prepareNotificationTx( + selectedTxFeeRate: selectedTxFeeRate, + targetPaymentCodeString: targetPaymentCodeString, + additionalOutputs: additionalOutputs + 1, + ); + } else { + throw InsufficientBalanceException( + "Remaining balance does not cover the network fee."); + } + } + } + + // return tuple with string value equal to the raw tx hex and the int value + // equal to its vSize + Future> _createNotificationTx({ + required String targetPaymentCodeString, + required List utxosToUse, + required Map utxoSigningData, + required int change, + }) async { + final targetPaymentCode = + PaymentCode.fromPaymentCode(targetPaymentCodeString, network); + final myCode = await getPaymentCode(DerivePathType.bip44); + + final utxo = utxosToUse.first; + final txPoint = utxo.txid.fromHex.toList(); + final txPointIndex = utxo.vout; + + final rev = Uint8List(txPoint.length + 4); + Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); + final buffer = rev.buffer.asByteData(); + buffer.setUint32(txPoint.length, txPointIndex, Endian.little); + + final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as btc_dart.ECPair; + + final S = SecretPoint( + myKeyPair.privateKey!, + targetPaymentCode.notificationPublicKey(), + ); + + final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev); + + final blindedPaymentCode = PaymentCode.blind( + myCode.getPayload(), + blindingMask, + ); + + final opReturnScript = bscript.compile([ + (op.OPS["OP_RETURN"] as int), + blindedPaymentCode, + ]); + + // build a notification tx + final txb = btc_dart.TransactionBuilder(network: network); + txb.setVersion(1); + + txb.addInput( + utxo.txid, + txPointIndex, + ); + + // todo: modify address once segwit support is in our bip47 + txb.addOutput(targetPaymentCode.notificationAddressP2PKH(), DUST_LIMIT); + txb.addOutput(opReturnScript, 0); + + // TODO: add possible change output and mark output as dangerous + if (change > 0) { + // generate new change address if current change address has been used + await checkChangeAddressForTransactions(); + final String changeAddress = await getCurrentChangeAddress(); + txb.addOutput(changeAddress, change); + } + + txb.sign( + vin: 0, + keyPair: myKeyPair, + ); + + // sign rest of possible inputs + for (var i = 1; i < utxosToUse.length - 1; i++) { + final txid = utxosToUse[i].txid; + txb.sign( + vin: i, + keyPair: utxoSigningData[txid]["keyPair"] as btc_dart.ECPair, + // witnessValue: utxosToUse[i].value, + ); + } + + final builtTx = txb.build(); + + return Tuple2(builtTx.toHex(), builtTx.virtualSize()); + } + + Future broadcastNotificationTx( + {required Map preparedTx}) async { + try { + Logging.instance.log("confirmNotificationTx txData: $preparedTx", + level: LogLevel.Info); + final txHash = await electrumXClient.broadcastTransaction( + rawTx: preparedTx["hex"] as String); + Logging.instance.log("Sent txHash: $txHash", level: LogLevel.Info); + + // TODO: only refresh transaction data + try { + await refresh(); + } catch (e) { + Logging.instance.log( + "refresh() failed in confirmNotificationTx ($walletName::$walletId): $e", + level: LogLevel.Error, + ); + } + + return txHash; + } catch (e, s) { + Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s", + level: LogLevel.Error); + rethrow; + } + } + + // TODO optimize + Future hasConnected(String paymentCodeString) async { + final myNotificationAddress = + await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); + + final txns = await db + .getTransactions(walletId) + .filter() + .subTypeEqualTo(TransactionSubType.bip47Notification) + .findAll(); + + for (final tx in txns) { + // quick check that may cause problems? + if (tx.address.value?.value == myNotificationAddress.value) { + return true; + } + + final unBlindedPaymentCode = await unBlindedPaymentCodeFromTransaction( + transaction: tx, + myNotificationAddress: myNotificationAddress, + ); + + if (paymentCodeString == unBlindedPaymentCode.toString()) { + return true; + } + } + + // otherwise return no + return false; + } + + Future unBlindedPaymentCodeFromTransaction({ + required Transaction transaction, + required Address myNotificationAddress, + }) async { + if (transaction.address.value != null && + transaction.address.value!.value != myNotificationAddress.value) { + return null; + } + + try { + final blindedCode = + transaction.outputs.elementAt(1).scriptPubKeyAsm!.split(" ")[1]; + + final designatedInput = transaction.inputs.first; + + final txPoint = designatedInput.txid.fromHex.toList(); + final txPointIndex = designatedInput.vout; + + final rev = Uint8List(txPoint.length + 4); + Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); + final buffer = rev.buffer.asByteData(); + buffer.setUint32(txPoint.length, txPointIndex, Endian.little); + + final pubKey = designatedInput.scriptSigAsm!.split(" ")[1].fromHex; + + final myPrivateKey = + await deriveNotificationPrivateKey(mnemonic: await getMnemonic()); + + final S = SecretPoint(myPrivateKey, pubKey); + + final mask = PaymentCode.getMask(S.ecdhSecret(), rev); + + final unBlindedPayload = PaymentCode.blind(blindedCode.fromHex, mask); + + final unBlindedPaymentCode = + PaymentCode.initFromPayload(unBlindedPayload); + + return unBlindedPaymentCode; + } catch (e) { + Logging.instance.log( + "unBlindedPaymentCodeFromTransaction() failed: $e", + level: LogLevel.Warning, + ); + return null; + } + } + + Future> + getAllPaymentCodesFromNotificationTransactions() async { + final myAddress = + await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); + final txns = await db + .getTransactions(walletId) + .filter() + .subTypeEqualTo(TransactionSubType.bip47Notification) + .findAll(); + + List unBlindedList = []; + + for (final tx in txns) { + final unBlinded = await unBlindedPaymentCodeFromTransaction( + transaction: tx, + myNotificationAddress: myAddress, + ); + if (unBlinded != null) { + unBlindedList.add(unBlinded); + } + } + + return unBlindedList; + } + + Future restoreHistoryWith( + PaymentCode other, + int maxUnusedAddressGap, + int maxNumberOfIndexesToCheck, + ) async { + // https://en.bitcoin.it/wiki/BIP_0047#Path_levels + const maxCount = 2147483647; + assert(maxNumberOfIndexesToCheck < maxCount); + + final myPrivateKey = + await deriveNotificationPrivateKey(mnemonic: await getMnemonic()); + + List
addresses = []; + int receivingGapCounter = 0; + int outgoingGapCounter = 0; + + for (int i = 0; + i < maxNumberOfIndexesToCheck && + (receivingGapCounter < maxUnusedAddressGap || + outgoingGapCounter < maxUnusedAddressGap); + i++) { + final paymentAddress = PaymentAddress.initWithPrivateKey( + myPrivateKey, + other, + i, // index to use + ); + + if (receivingGapCounter < maxUnusedAddressGap) { + final pair = paymentAddress.getSendAddressKeyPair(); + final address = generatePaynymSendAddressFromKeyPair( + pair: pair, + derivationIndex: i, + derivePathType: DerivePathType.bip44, + toPaymentCode: other, + ); + addresses.add(address); + + final count = await getTxCount(address: address.value); + + if (count > 0) { + receivingGapCounter++; + } else { + receivingGapCounter = 0; + } + } + + if (outgoingGapCounter < maxUnusedAddressGap) { + final pair = paymentAddress.getReceiveAddressKeyPair(); + final address = generatePaynymReceivingAddressFromKeyPair( + pair: pair, + derivationIndex: i, + derivePathType: DerivePathType.bip44, + fromPaymentCode: other, + ); + addresses.add(address); + + final count = await getTxCount(address: address.value); + + if (count > 0) { + outgoingGapCounter++; + } else { + outgoingGapCounter = 0; + } + } + } + await db.putAddresses(addresses); + } + + Address generatePaynymSendAddressFromKeyPair({ + required btc_dart.ECPair pair, + required int derivationIndex, + required DerivePathType derivePathType, + required PaymentCode toPaymentCode, + }) { + final data = btc_dart.PaymentData(pubkey: pair.publicKey); + + String addressString; + switch (derivePathType) { + case DerivePathType.bip44: + addressString = + btc_dart.P2PKH(data: data, network: network).data.address!; + break; + + // The following doesn't apply currently + // case DerivePathType.bip49: + // addressString = btc_dart + // .P2SH( + // data: btc_dart.PaymentData( + // redeem: btc_dart + // .P2WPKH( + // data: data, + // network: network, + // ) + // .data), + // network: network, + // ) + // .data + // .address!; + // break; + // + // case DerivePathType.bip84: + // addressString = btc_dart + // .P2WPKH( + // network: network, + // data: data, + // ) + // .data + // .address!; + // break; + default: + throw UnimplementedError("segwit paynyms not implemented yet"); + } + + final address = Address( + walletId: walletId, + value: addressString, + publicKey: pair.publicKey, + derivationIndex: derivationIndex, + type: AddressType.nonWallet, + subType: AddressSubType.paynymSend, + otherData: toPaymentCode.toString(), + ); + + return address; + } + + Address generatePaynymReceivingAddressFromKeyPair({ + required btc_dart.ECPair pair, + required int derivationIndex, + required DerivePathType derivePathType, + required PaymentCode fromPaymentCode, + }) { + final data = btc_dart.PaymentData(pubkey: pair.publicKey); + + String addressString; + AddressType addrType; + switch (derivePathType) { + case DerivePathType.bip44: + addressString = btc_dart + .P2PKH( + data: data, + network: network, + ) + .data + .address!; + addrType = AddressType.p2pkh; + break; + + // The following doesn't apply currently + // case DerivePathType.bip49: + // addressString = btc_dart + // .P2SH( + // data: btc_dart.PaymentData( + // redeem: btc_dart + // .P2WPKH( + // data: data, + // network: network, + // ) + // .data), + // network: network, + // ) + // .data + // .address!; + // addrType = AddressType.p2sh; + // break; + // + // case DerivePathType.bip84: + // addressString = btc_dart + // .P2WPKH( + // network: network, + // data: data, + // ) + // .data + // .address!; + // addrType = AddressType.p2wpkh; + // break; + default: + throw UnimplementedError("segwit paynyms not implemented yet"); + } + + final address = Address( + walletId: walletId, + value: addressString, + publicKey: pair.publicKey, + derivationIndex: derivationIndex, + type: addrType, + subType: AddressSubType.paynymReceive, + otherData: fromPaymentCode.toString(), + ); + + return address; + } + + Future
getMyNotificationAddress( + DerivePathType derivePathType, + ) async { + // TODO: fix when segwit is here + derivePathType = DerivePathType.bip44; + + AddressType type; + switch (derivePathType) { + case DerivePathType.bip44: + type = AddressType.p2pkh; + break; + case DerivePathType.bip49: + type = AddressType.p2sh; + break; + case DerivePathType.bip84: + type = AddressType.p2wpkh; + break; + } + + final storedAddress = await db + .getAddresses(walletId) + .filter() + .subTypeEqualTo(AddressSubType.paynymNotification) + .and() + .typeEqualTo(type) + .and() + .not() + .typeEqualTo(AddressType.nonWallet) + .findFirst(); + + if (storedAddress != null) { + return storedAddress; + } else { + final root = await getRootNode(mnemonic: await getMnemonic()); + final node = root.derivePath(kPaynymDerivePath); + final paymentCode = PaymentCode.initFromPubKey( + node.publicKey, + node.chainCode, + network, + ); + + String addressString; + final data = + btc_dart.PaymentData(pubkey: paymentCode.notificationPublicKey()); + switch (derivePathType) { + case DerivePathType.bip44: + addressString = btc_dart + .P2PKH( + data: data, + network: network, + ) + .data + .address!; + break; + // case DerivePathType.bip49: + // addressString = btc_dart + // .P2SH( + // data: btc_dart.PaymentData( + // redeem: btc_dart + // .P2WPKH( + // data: data, + // network: network, + // ) + // .data), + // network: network, + // ) + // .data + // .address!; + // break; + // case DerivePathType.bip84: + // addressString = btc_dart + // .P2WPKH( + // network: network, + // data: data, + // ) + // .data + // .address!; + // break; + default: + throw UnimplementedError("segwit paynyms not implemented yet"); + } + + final address = Address( + walletId: walletId, + value: addressString, + publicKey: paymentCode.getPubKey(), + derivationIndex: 0, + type: type, + subType: AddressSubType.paynymNotification, + otherData: paymentCode.toString(), + ); + + await db.putAddress(address); + return address; + } + } +} From 7cb497f4f770ec6cb57408b9bf2cba76b804751e Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 15:46:48 -0600 Subject: [PATCH 22/55] remove coin enum hasPaynymSupport getter in favor of type checking --- .../sub_widgets/wallet_navigation_bar.dart | 26 ++++++++++--------- .../wallet_view/desktop_wallet_view.dart | 4 +-- lib/services/coins/manager.dart | 3 +++ lib/services/mixins/electrum_x_parsing.dart | 3 ++- lib/utilities/enums/coin_enum.dart | 23 ---------------- 5 files changed, 21 insertions(+), 38 deletions(-) diff --git a/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart b/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart index f251dedd4..bb070f3e3 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart @@ -8,8 +8,7 @@ import 'package:stackwallet/pages/paynym/paynym_home_view.dart'; import 'package:stackwallet/providers/global/paynym_api_provider.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; -import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; +import 'package:stackwallet/services/mixins/paynym_support.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; @@ -18,7 +17,7 @@ import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/loading_indicator.dart'; -class WalletNavigationBar extends StatefulWidget { +class WalletNavigationBar extends ConsumerStatefulWidget { const WalletNavigationBar({ Key? key, required this.onReceivePressed, @@ -41,10 +40,11 @@ class WalletNavigationBar extends StatefulWidget { final String walletId; @override - State createState() => _WalletNavigationBarState(); + ConsumerState createState() => + _WalletNavigationBarState(); } -class _WalletNavigationBarState extends State { +class _WalletNavigationBarState extends ConsumerState { double scale = 0; final duration = const Duration(milliseconds: 200); @@ -115,14 +115,15 @@ class _WalletNavigationBarState extends State { ), ); - // todo make generic and not doge specific - final wallet = (ref + final manager = ref .read(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .wallet as DogecoinWallet); + .getManager(widget.walletId); - final code = await wallet.getPaymentCode( - DerivePathTypeExt.primaryFor(wallet.coin)); + final paynymInterface = + manager.wallet as PaynymWalletInterface; + + final code = await paynymInterface.getPaymentCode( + DerivePathTypeExt.primaryFor(manager.coin)); final account = await ref .read(paynymAPIProvider) @@ -359,7 +360,8 @@ class _WalletNavigationBarState extends State { ), ), ), - if (widget.coin.hasPaynymSupport) + if (ref.watch(walletsChangeNotifierProvider.select((value) => + value.getManager(widget.walletId).hasPaynymSupport))) RawMaterialButton( constraints: const BoxConstraints( minWidth: 66, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart index d48646860..5c1e048a0 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -21,7 +21,6 @@ import 'package:stackwallet/providers/global/paynym_api_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/ui/transaction_filter_provider.dart'; import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; @@ -536,7 +535,8 @@ class _DesktopWalletViewState extends ConsumerState { ); }, ), - if (coin.hasPaynymSupport) + if (ref.watch(walletsChangeNotifierProvider.select((value) => + value.getManager(widget.walletId).hasPaynymSupport))) SecondaryButton( label: "PayNym", width: 160, diff --git a/lib/services/coins/manager.dart b/lib/services/coins/manager.dart index a590752e0..65ba54c36 100644 --- a/lib/services/coins/manager.dart +++ b/lib/services/coins/manager.dart @@ -9,6 +9,7 @@ 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/global_event_bus.dart'; +import 'package:stackwallet/services/mixins/paynym_support.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/logger.dart'; @@ -214,4 +215,6 @@ class Manager with ChangeNotifier { } int get currentHeight => _currentWallet.storedChainHeight; + + bool get hasPaynymSupport => _currentWallet is PaynymWalletInterface; } diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart index deac690f7..b95a749f1 100644 --- a/lib/services/mixins/electrum_x_parsing.dart +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -1,6 +1,7 @@ import 'package:bip47/src/util.dart'; import 'package:decimal/decimal.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; +import 'package:stackwallet/services/mixins/paynym_support.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:tuple/tuple.dart'; @@ -186,7 +187,7 @@ mixin ElectrumXParsing { } TransactionSubType txSubType = TransactionSubType.none; - if (coin.hasPaynymSupport && outs.length > 1 && ins.isNotEmpty) { + if (this is PaynymWalletInterface && outs.length > 1 && ins.isNotEmpty) { List? scriptChunks = outs[1].scriptPubKeyAsm?.split(" "); if (scriptChunks?.length == 2 && scriptChunks?[0] == "OP_RETURN") { final blindedPaymentCode = scriptChunks![1]; diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index a517992de..df586ebf5 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -171,29 +171,6 @@ extension CoinExt on Coin { } } - bool get hasPaynymSupport { - switch (this) { - case Coin.bitcoin: - case Coin.litecoin: - case Coin.bitcoincash: - case Coin.firo: - case Coin.namecoin: - case Coin.particl: - case Coin.bitcoinTestNet: - case Coin.litecoinTestNet: - case Coin.bitcoincashTestnet: - case Coin.firoTestNet: - case Coin.epicCash: - case Coin.monero: - case Coin.wownero: - return false; - - case Coin.dogecoin: - case Coin.dogecoinTestNet: - return true; - } - } - int get requiredConfirmations { switch (this) { case Coin.bitcoin: From fb3f430edc87f1ccd6362fd24938dd9d534f4230 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 15:49:57 -0600 Subject: [PATCH 23/55] disable PaynymSupport extension and use PaynymWalletInterface instead --- .../sub_widgets/wallet_navigation_bar.dart | 2 +- lib/services/coins/coin_paynym_extension.dart | 1630 ++++++++--------- .../coins/dogecoin/dogecoin_wallet.dart | 20 +- lib/services/coins/manager.dart | 2 +- lib/services/mixins/electrum_x_parsing.dart | 2 +- ...port.dart => paynym_wallet_interface.dart} | 156 +- 6 files changed, 915 insertions(+), 897 deletions(-) rename lib/services/mixins/{paynym_support.dart => paynym_wallet_interface.dart} (88%) diff --git a/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart b/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart index bb070f3e3..d8ca42192 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart @@ -8,7 +8,7 @@ import 'package:stackwallet/pages/paynym/paynym_home_view.dart'; import 'package:stackwallet/providers/global/paynym_api_provider.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; -import 'package:stackwallet/services/mixins/paynym_support.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; diff --git a/lib/services/coins/coin_paynym_extension.dart b/lib/services/coins/coin_paynym_extension.dart index 7a631e154..082976f67 100644 --- a/lib/services/coins/coin_paynym_extension.dart +++ b/lib/services/coins/coin_paynym_extension.dart @@ -1,815 +1,815 @@ -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:bip32/bip32.dart' as bip32; -import 'package:bip47/bip47.dart'; -import 'package:bip47/src/util.dart'; -import 'package:bitcoindart/bitcoindart.dart' as btc_dart; -import 'package:bitcoindart/src/utils/constants/op.dart' as op; -import 'package:bitcoindart/src/utils/script.dart' as bscript; -import 'package:isar/isar.dart'; -import 'package:pointycastle/digests/sha256.dart'; -import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; -import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; -import 'package:stackwallet/models/isar/models/isar_models.dart'; -import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; -import 'package:stackwallet/utilities/bip32_utils.dart'; -import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; -import 'package:stackwallet/utilities/format.dart'; -import 'package:stackwallet/utilities/logger.dart'; -import 'package:tuple/tuple.dart'; - -const kPaynymDerivePath = "m/47'/0'/0'"; - -extension PayNym on DogecoinWallet { - // generate bip32 payment code root - Future getRootNode({ - required List mnemonic, - }) async { - final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), network); - return root; - } - - Future deriveNotificationPrivateKey({ - required List mnemonic, - }) async { - final root = await getRootNode(mnemonic: mnemonic); - final node = root.derivePath(kPaynymDerivePath).derive(0); - return node.privateKey!; - } - - /// fetch or generate this wallet's bip47 payment code - Future getPaymentCode( - DerivePathType derivePathType, - ) async { - final address = await getMyNotificationAddress(derivePathType); - final paymentCode = PaymentCode.fromPaymentCode( - address.otherData!, - network, - ); - return paymentCode; - } - - Future signWithNotificationKey(Uint8List data) async { - final privateKey = - await deriveNotificationPrivateKey(mnemonic: await mnemonic); - final pair = btc_dart.ECPair.fromPrivateKey(privateKey, network: network); - final signed = pair.sign(SHA256Digest().process(data)); - return signed; - } - - Future signStringWithNotificationKey(String data) async { - final bytes = - await signWithNotificationKey(Uint8List.fromList(utf8.encode(data))); - return Format.uint8listToString(bytes); - } - - Future>> preparePaymentCodeSend( - {required PaymentCode paymentCode, - required int satoshiAmount, - Map? args}) async { - if (!(await hasConnected(paymentCode.notificationAddressP2PKH()))) { - throw PaynymSendException( - "No notification transaction sent to $paymentCode"); - } else { - final myPrivateKey = - await deriveNotificationPrivateKey(mnemonic: await mnemonic); - final sendToAddress = await nextUnusedSendAddressFrom( - pCode: paymentCode, - privateKey: myPrivateKey, - ); - - return prepareSend( - address: sendToAddress.value, satoshiAmount: satoshiAmount); - } - } - - /// get the next unused address to send to given the receiver's payment code - /// and your own private key - Future
nextUnusedSendAddressFrom({ - required PaymentCode pCode, - required Uint8List privateKey, - int startIndex = 0, - }) async { - // https://en.bitcoin.it/wiki/BIP_0047#Path_levels - const maxCount = 2147483647; - - for (int i = startIndex; i < maxCount; i++) { - final address = await db - .getAddresses(walletId) - .filter() - .subTypeEqualTo(AddressSubType.paynymSend) - .and() - .otherDataEqualTo(pCode.toString()) - .and() - .derivationIndexEqualTo(i) - .findFirst(); - - if (address != null) { - final count = await getTxCount(address: address.value); - // return address if unused, otherwise continue to next index - if (count == 0) { - return address; - } - } else { - final pair = PaymentAddress.initWithPrivateKey( - privateKey, - pCode, - i, // index to use - ).getSendAddressKeyPair(); - - // add address to local db - final address = generatePaynymSendAddressFromKeyPair( - pair: pair, - derivationIndex: i, - derivePathType: DerivePathType.bip44, - toPaymentCode: pCode, - ); - await db.putAddress(address); - - final count = await getTxCount(address: address.value); - // return address if unused, otherwise continue to next index - if (count == 0) { - return address; - } - } - } - - throw PaynymSendException("Exhausted unused send addresses!"); - } - - Future> prepareNotificationTx({ - required int selectedTxFeeRate, - required String targetPaymentCodeString, - int additionalOutputs = 0, - List? utxos, - }) async { - const amountToSend = DUST_LIMIT; - final List availableOutputs = utxos ?? await this.utxos; - final List spendableOutputs = []; - int spendableSatoshiValue = 0; - - // Build list of spendable outputs and totaling their satoshi amount - for (var i = 0; i < availableOutputs.length; i++) { - if (availableOutputs[i].isBlocked == false && - availableOutputs[i] - .isConfirmed(await chainHeight, MINIMUM_CONFIRMATIONS) == - true) { - spendableOutputs.add(availableOutputs[i]); - spendableSatoshiValue += availableOutputs[i].value; - } - } - - if (spendableSatoshiValue < amountToSend) { - // insufficient balance - throw InsufficientBalanceException( - "Spendable balance is less than the minimum required for a notification transaction."); - } else if (spendableSatoshiValue == amountToSend) { - // insufficient balance due to missing amount to cover fee - throw InsufficientBalanceException( - "Remaining balance does not cover the network fee."); - } - - // sort spendable by age (oldest first) - spendableOutputs.sort((a, b) => b.blockTime!.compareTo(a.blockTime!)); - - int satoshisBeingUsed = 0; - int outputsBeingUsed = 0; - List utxoObjectsToUse = []; - - for (int i = 0; - satoshisBeingUsed < amountToSend && i < spendableOutputs.length; - i++) { - utxoObjectsToUse.add(spendableOutputs[i]); - satoshisBeingUsed += spendableOutputs[i].value; - outputsBeingUsed += 1; - } - - // add additional outputs if required - for (int i = 0; - i < additionalOutputs && outputsBeingUsed < spendableOutputs.length; - i++) { - utxoObjectsToUse.add(spendableOutputs[outputsBeingUsed]); - satoshisBeingUsed += spendableOutputs[outputsBeingUsed].value; - outputsBeingUsed += 1; - } - - // gather required signing data - final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); - - final int vSizeForNoChange = (await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: 0)) - .item2; - - final int vSizeForWithChange = (await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: satoshisBeingUsed - amountToSend)) - .item2; - - // Assume 2 outputs, for recipient and payment code script - int feeForNoChange = estimateTxFee( - vSize: vSizeForNoChange, - feeRatePerKB: selectedTxFeeRate, - ); - - // Assume 3 outputs, for recipient, payment code script, and change - int feeForWithChange = estimateTxFee( - vSize: vSizeForWithChange, - feeRatePerKB: selectedTxFeeRate, - ); - - if (feeForNoChange < vSizeForNoChange * 1000) { - feeForNoChange = vSizeForNoChange * 1000; - } - if (feeForWithChange < vSizeForWithChange * 1000) { - feeForWithChange = vSizeForWithChange * 1000; - } - - if (satoshisBeingUsed - amountToSend > feeForNoChange + DUST_LIMIT) { - // try to add change output due to "left over" amount being greater than - // the estimated fee + the dust limit - int changeAmount = satoshisBeingUsed - amountToSend - feeForWithChange; - - // check estimates are correct and build notification tx - if (changeAmount >= DUST_LIMIT && - satoshisBeingUsed - amountToSend - changeAmount == feeForWithChange) { - final txn = await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: changeAmount, - ); - - int feeBeingPaid = satoshisBeingUsed - amountToSend - changeAmount; - - Map transactionObject = { - "hex": txn.item1, - "recipientPaynym": targetPaymentCodeString, - "amount": amountToSend, - "fee": feeBeingPaid, - "vSize": txn.item2, - }; - return transactionObject; - } else { - // something broke during fee estimation or the change amount is smaller - // than the dust limit. Try without change - final txn = await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: 0, - ); - - int feeBeingPaid = satoshisBeingUsed - amountToSend; - - Map transactionObject = { - "hex": txn.item1, - "recipientPaynym": targetPaymentCodeString, - "amount": amountToSend, - "fee": feeBeingPaid, - "vSize": txn.item2, - }; - return transactionObject; - } - } else if (satoshisBeingUsed - amountToSend >= feeForNoChange) { - // since we already checked if we need to add a change output we can just - // build without change here - final txn = await _createNotificationTx( - targetPaymentCodeString: targetPaymentCodeString, - utxosToUse: utxoObjectsToUse, - utxoSigningData: utxoSigningData, - change: 0, - ); - - int feeBeingPaid = satoshisBeingUsed - amountToSend; - - Map transactionObject = { - "hex": txn.item1, - "recipientPaynym": targetPaymentCodeString, - "amount": amountToSend, - "fee": feeBeingPaid, - "vSize": txn.item2, - }; - return transactionObject; - } else { - // if we get here we do not have enough funds to cover the tx total so we - // check if we have any more available outputs and try again - if (spendableOutputs.length > outputsBeingUsed) { - return prepareNotificationTx( - selectedTxFeeRate: selectedTxFeeRate, - targetPaymentCodeString: targetPaymentCodeString, - additionalOutputs: additionalOutputs + 1, - ); - } else { - throw InsufficientBalanceException( - "Remaining balance does not cover the network fee."); - } - } - } - - // return tuple with string value equal to the raw tx hex and the int value - // equal to its vSize - Future> _createNotificationTx({ - required String targetPaymentCodeString, - required List utxosToUse, - required Map utxoSigningData, - required int change, - }) async { - final targetPaymentCode = - PaymentCode.fromPaymentCode(targetPaymentCodeString, network); - final myCode = await getPaymentCode(DerivePathType.bip44); - - final utxo = utxosToUse.first; - final txPoint = utxo.txid.fromHex.toList(); - final txPointIndex = utxo.vout; - - final rev = Uint8List(txPoint.length + 4); - Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); - final buffer = rev.buffer.asByteData(); - buffer.setUint32(txPoint.length, txPointIndex, Endian.little); - - final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as btc_dart.ECPair; - - final S = SecretPoint( - myKeyPair.privateKey!, - targetPaymentCode.notificationPublicKey(), - ); - - final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev); - - final blindedPaymentCode = PaymentCode.blind( - myCode.getPayload(), - blindingMask, - ); - - final opReturnScript = bscript.compile([ - (op.OPS["OP_RETURN"] as int), - blindedPaymentCode, - ]); - - // build a notification tx - final txb = btc_dart.TransactionBuilder(network: network); - txb.setVersion(1); - - txb.addInput( - utxo.txid, - txPointIndex, - ); - - // todo: modify address once segwit support is in our bip47 - txb.addOutput(targetPaymentCode.notificationAddressP2PKH(), DUST_LIMIT); - txb.addOutput(opReturnScript, 0); - - // TODO: add possible change output and mark output as dangerous - if (change > 0) { - // generate new change address if current change address has been used - await checkChangeAddressForTransactions(); - final String changeAddress = await currentChangeAddress; - txb.addOutput(changeAddress, change); - } - - txb.sign( - vin: 0, - keyPair: myKeyPair, - ); - - // sign rest of possible inputs - for (var i = 1; i < utxosToUse.length - 1; i++) { - final txid = utxosToUse[i].txid; - txb.sign( - vin: i, - keyPair: utxoSigningData[txid]["keyPair"] as btc_dart.ECPair, - // witnessValue: utxosToUse[i].value, - ); - } - - final builtTx = txb.build(); - - return Tuple2(builtTx.toHex(), builtTx.virtualSize()); - } - - Future broadcastNotificationTx( - {required Map preparedTx}) async { - try { - Logging.instance.log("confirmNotificationTx txData: $preparedTx", - level: LogLevel.Info); - final txHash = await electrumXClient.broadcastTransaction( - rawTx: preparedTx["hex"] as String); - Logging.instance.log("Sent txHash: $txHash", level: LogLevel.Info); - - // TODO: only refresh transaction data - try { - await refresh(); - } catch (e) { - Logging.instance.log( - "refresh() failed in confirmNotificationTx ($walletName::$walletId): $e", - level: LogLevel.Error, - ); - } - - return txHash; - } catch (e, s) { - Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s", - level: LogLevel.Error); - rethrow; - } - } - - // TODO optimize - Future hasConnected(String paymentCodeString) async { - final myNotificationAddress = - await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); - - final txns = await db - .getTransactions(walletId) - .filter() - .subTypeEqualTo(TransactionSubType.bip47Notification) - .findAll(); - - for (final tx in txns) { - // quick check that may cause problems? - if (tx.address.value?.value == myNotificationAddress.value) { - return true; - } - - final unBlindedPaymentCode = await unBlindedPaymentCodeFromTransaction( - transaction: tx, - myNotificationAddress: myNotificationAddress, - ); - - if (paymentCodeString == unBlindedPaymentCode.toString()) { - return true; - } - } - - // otherwise return no - return false; - } - - Future unBlindedPaymentCodeFromTransaction({ - required Transaction transaction, - required Address myNotificationAddress, - }) async { - if (transaction.address.value != null && - transaction.address.value!.value != myNotificationAddress.value) { - return null; - } - - try { - final blindedCode = - transaction.outputs.elementAt(1).scriptPubKeyAsm!.split(" ")[1]; - - final designatedInput = transaction.inputs.first; - - final txPoint = designatedInput.txid.fromHex.toList(); - final txPointIndex = designatedInput.vout; - - final rev = Uint8List(txPoint.length + 4); - Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); - final buffer = rev.buffer.asByteData(); - buffer.setUint32(txPoint.length, txPointIndex, Endian.little); - - final pubKey = designatedInput.scriptSigAsm!.split(" ")[1].fromHex; - - final myPrivateKey = - await deriveNotificationPrivateKey(mnemonic: await mnemonic); - - final S = SecretPoint(myPrivateKey, pubKey); - - final mask = PaymentCode.getMask(S.ecdhSecret(), rev); - - final unBlindedPayload = PaymentCode.blind(blindedCode.fromHex, mask); - - final unBlindedPaymentCode = - PaymentCode.initFromPayload(unBlindedPayload); - - return unBlindedPaymentCode; - } catch (e) { - Logging.instance.log( - "unBlindedPaymentCodeFromTransaction() failed: $e", - level: LogLevel.Warning, - ); - return null; - } - } - - Future> - getAllPaymentCodesFromNotificationTransactions() async { - final myAddress = - await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); - final txns = await db - .getTransactions(walletId) - .filter() - .subTypeEqualTo(TransactionSubType.bip47Notification) - .findAll(); - - List unBlindedList = []; - - for (final tx in txns) { - final unBlinded = await unBlindedPaymentCodeFromTransaction( - transaction: tx, - myNotificationAddress: myAddress, - ); - if (unBlinded != null) { - unBlindedList.add(unBlinded); - } - } - - return unBlindedList; - } - - Future restoreHistoryWith( - PaymentCode other, - int maxUnusedAddressGap, - int maxNumberOfIndexesToCheck, - ) async { - // https://en.bitcoin.it/wiki/BIP_0047#Path_levels - const maxCount = 2147483647; - assert(maxNumberOfIndexesToCheck < maxCount); - - final myPrivateKey = - await deriveNotificationPrivateKey(mnemonic: await mnemonic); - - List
addresses = []; - int receivingGapCounter = 0; - int outgoingGapCounter = 0; - - for (int i = 0; - i < maxNumberOfIndexesToCheck && - (receivingGapCounter < maxUnusedAddressGap || - outgoingGapCounter < maxUnusedAddressGap); - i++) { - final paymentAddress = PaymentAddress.initWithPrivateKey( - myPrivateKey, - other, - i, // index to use - ); - - if (receivingGapCounter < maxUnusedAddressGap) { - final pair = paymentAddress.getSendAddressKeyPair(); - final address = generatePaynymSendAddressFromKeyPair( - pair: pair, - derivationIndex: i, - derivePathType: DerivePathType.bip44, - toPaymentCode: other, - ); - addresses.add(address); - - final count = await getTxCount(address: address.value); - - if (count > 0) { - receivingGapCounter++; - } else { - receivingGapCounter = 0; - } - } - - if (outgoingGapCounter < maxUnusedAddressGap) { - final pair = paymentAddress.getReceiveAddressKeyPair(); - final address = generatePaynymReceivingAddressFromKeyPair( - pair: pair, - derivationIndex: i, - derivePathType: DerivePathType.bip44, - fromPaymentCode: other, - ); - addresses.add(address); - - final count = await getTxCount(address: address.value); - - if (count > 0) { - outgoingGapCounter++; - } else { - outgoingGapCounter = 0; - } - } - } - await db.putAddresses(addresses); - } - - Address generatePaynymSendAddressFromKeyPair({ - required btc_dart.ECPair pair, - required int derivationIndex, - required DerivePathType derivePathType, - required PaymentCode toPaymentCode, - }) { - final data = btc_dart.PaymentData(pubkey: pair.publicKey); - - String addressString; - switch (derivePathType) { - case DerivePathType.bip44: - addressString = - btc_dart.P2PKH(data: data, network: network).data.address!; - break; - - // The following doesn't apply currently - // case DerivePathType.bip49: - // addressString = btc_dart - // .P2SH( - // data: btc_dart.PaymentData( - // redeem: btc_dart - // .P2WPKH( - // data: data, - // network: network, - // ) - // .data), - // network: network, - // ) - // .data - // .address!; - // break; - // - // case DerivePathType.bip84: - // addressString = btc_dart - // .P2WPKH( - // network: network, - // data: data, - // ) - // .data - // .address!; - // break; - default: - throw UnimplementedError("segwit paynyms not implemented yet"); - } - - final address = Address( - walletId: walletId, - value: addressString, - publicKey: pair.publicKey, - derivationIndex: derivationIndex, - type: AddressType.nonWallet, - subType: AddressSubType.paynymSend, - otherData: toPaymentCode.toString(), - ); - - return address; - } - - Address generatePaynymReceivingAddressFromKeyPair({ - required btc_dart.ECPair pair, - required int derivationIndex, - required DerivePathType derivePathType, - required PaymentCode fromPaymentCode, - }) { - final data = btc_dart.PaymentData(pubkey: pair.publicKey); - - String addressString; - AddressType addrType; - switch (derivePathType) { - case DerivePathType.bip44: - addressString = btc_dart - .P2PKH( - data: data, - network: network, - ) - .data - .address!; - addrType = AddressType.p2pkh; - break; - - // The following doesn't apply currently - // case DerivePathType.bip49: - // addressString = btc_dart - // .P2SH( - // data: btc_dart.PaymentData( - // redeem: btc_dart - // .P2WPKH( - // data: data, - // network: network, - // ) - // .data), - // network: network, - // ) - // .data - // .address!; - // addrType = AddressType.p2sh; - // break; - // - // case DerivePathType.bip84: - // addressString = btc_dart - // .P2WPKH( - // network: network, - // data: data, - // ) - // .data - // .address!; - // addrType = AddressType.p2wpkh; - // break; - default: - throw UnimplementedError("segwit paynyms not implemented yet"); - } - - final address = Address( - walletId: walletId, - value: addressString, - publicKey: pair.publicKey, - derivationIndex: derivationIndex, - type: addrType, - subType: AddressSubType.paynymReceive, - otherData: fromPaymentCode.toString(), - ); - - return address; - } - - Future
getMyNotificationAddress( - DerivePathType derivePathType, - ) async { - // TODO: fix when segwit is here - derivePathType = DerivePathType.bip44; - - AddressType type; - switch (derivePathType) { - case DerivePathType.bip44: - type = AddressType.p2pkh; - break; - case DerivePathType.bip49: - type = AddressType.p2sh; - break; - case DerivePathType.bip84: - type = AddressType.p2wpkh; - break; - } - - final storedAddress = await db - .getAddresses(walletId) - .filter() - .subTypeEqualTo(AddressSubType.paynymNotification) - .and() - .typeEqualTo(type) - .and() - .not() - .typeEqualTo(AddressType.nonWallet) - .findFirst(); - - if (storedAddress != null) { - return storedAddress; - } else { - final root = await getRootNode(mnemonic: await mnemonic); - final node = root.derivePath(kPaynymDerivePath); - final paymentCode = PaymentCode.initFromPubKey( - node.publicKey, - node.chainCode, - network, - ); - - String addressString; - final data = - btc_dart.PaymentData(pubkey: paymentCode.notificationPublicKey()); - switch (derivePathType) { - case DerivePathType.bip44: - addressString = btc_dart - .P2PKH( - data: data, - network: network, - ) - .data - .address!; - break; - // case DerivePathType.bip49: - // addressString = btc_dart - // .P2SH( - // data: btc_dart.PaymentData( - // redeem: btc_dart - // .P2WPKH( - // data: data, - // network: network, - // ) - // .data), - // network: network, - // ) - // .data - // .address!; - // break; - // case DerivePathType.bip84: - // addressString = btc_dart - // .P2WPKH( - // network: network, - // data: data, - // ) - // .data - // .address!; - // break; - default: - throw UnimplementedError("segwit paynyms not implemented yet"); - } - - final address = Address( - walletId: walletId, - value: addressString, - publicKey: paymentCode.getPubKey(), - derivationIndex: 0, - type: type, - subType: AddressSubType.paynymNotification, - otherData: paymentCode.toString(), - ); - - await db.putAddress(address); - return address; - } - } -} +// import 'dart:convert'; +// import 'dart:typed_data'; +// +// import 'package:bip32/bip32.dart' as bip32; +// import 'package:bip47/bip47.dart'; +// import 'package:bip47/src/util.dart'; +// import 'package:bitcoindart/bitcoindart.dart' as btc_dart; +// import 'package:bitcoindart/src/utils/constants/op.dart' as op; +// import 'package:bitcoindart/src/utils/script.dart' as bscript; +// import 'package:isar/isar.dart'; +// import 'package:pointycastle/digests/sha256.dart'; +// import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart'; +// import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart'; +// import 'package:stackwallet/models/isar/models/isar_models.dart'; +// import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; +// import 'package:stackwallet/utilities/bip32_utils.dart'; +// import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; +// import 'package:stackwallet/utilities/format.dart'; +// import 'package:stackwallet/utilities/logger.dart'; +// import 'package:tuple/tuple.dart'; +// +// const kPaynymDerivePath = "m/47'/0'/0'"; +// +// extension PayNym on DogecoinWallet { +// // generate bip32 payment code root +// Future getRootNode({ +// required List mnemonic, +// }) async { +// final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), network); +// return root; +// } +// +// Future deriveNotificationPrivateKey({ +// required List mnemonic, +// }) async { +// final root = await getRootNode(mnemonic: mnemonic); +// final node = root.derivePath(kPaynymDerivePath).derive(0); +// return node.privateKey!; +// } +// +// /// fetch or generate this wallet's bip47 payment code +// Future getPaymentCode( +// DerivePathType derivePathType, +// ) async { +// final address = await getMyNotificationAddress(derivePathType); +// final paymentCode = PaymentCode.fromPaymentCode( +// address.otherData!, +// network, +// ); +// return paymentCode; +// } +// +// Future signWithNotificationKey(Uint8List data) async { +// final privateKey = +// await deriveNotificationPrivateKey(mnemonic: await mnemonic); +// final pair = btc_dart.ECPair.fromPrivateKey(privateKey, network: network); +// final signed = pair.sign(SHA256Digest().process(data)); +// return signed; +// } +// +// Future signStringWithNotificationKey(String data) async { +// final bytes = +// await signWithNotificationKey(Uint8List.fromList(utf8.encode(data))); +// return Format.uint8listToString(bytes); +// } +// +// Future>> preparePaymentCodeSend( +// {required PaymentCode paymentCode, +// required int satoshiAmount, +// Map? args}) async { +// if (!(await hasConnected(paymentCode.notificationAddressP2PKH()))) { +// throw PaynymSendException( +// "No notification transaction sent to $paymentCode"); +// } else { +// final myPrivateKey = +// await deriveNotificationPrivateKey(mnemonic: await mnemonic); +// final sendToAddress = await nextUnusedSendAddressFrom( +// pCode: paymentCode, +// privateKey: myPrivateKey, +// ); +// +// return prepareSend( +// address: sendToAddress.value, satoshiAmount: satoshiAmount); +// } +// } +// +// /// get the next unused address to send to given the receiver's payment code +// /// and your own private key +// Future
nextUnusedSendAddressFrom({ +// required PaymentCode pCode, +// required Uint8List privateKey, +// int startIndex = 0, +// }) async { +// // https://en.bitcoin.it/wiki/BIP_0047#Path_levels +// const maxCount = 2147483647; +// +// for (int i = startIndex; i < maxCount; i++) { +// final address = await db +// .getAddresses(walletId) +// .filter() +// .subTypeEqualTo(AddressSubType.paynymSend) +// .and() +// .otherDataEqualTo(pCode.toString()) +// .and() +// .derivationIndexEqualTo(i) +// .findFirst(); +// +// if (address != null) { +// final count = await getTxCount(address: address.value); +// // return address if unused, otherwise continue to next index +// if (count == 0) { +// return address; +// } +// } else { +// final pair = PaymentAddress.initWithPrivateKey( +// privateKey, +// pCode, +// i, // index to use +// ).getSendAddressKeyPair(); +// +// // add address to local db +// final address = generatePaynymSendAddressFromKeyPair( +// pair: pair, +// derivationIndex: i, +// derivePathType: DerivePathType.bip44, +// toPaymentCode: pCode, +// ); +// await db.putAddress(address); +// +// final count = await getTxCount(address: address.value); +// // return address if unused, otherwise continue to next index +// if (count == 0) { +// return address; +// } +// } +// } +// +// throw PaynymSendException("Exhausted unused send addresses!"); +// } +// +// Future> prepareNotificationTx({ +// required int selectedTxFeeRate, +// required String targetPaymentCodeString, +// int additionalOutputs = 0, +// List? utxos, +// }) async { +// const amountToSend = DUST_LIMIT; +// final List availableOutputs = utxos ?? await this.utxos; +// final List spendableOutputs = []; +// int spendableSatoshiValue = 0; +// +// // Build list of spendable outputs and totaling their satoshi amount +// for (var i = 0; i < availableOutputs.length; i++) { +// if (availableOutputs[i].isBlocked == false && +// availableOutputs[i] +// .isConfirmed(await chainHeight, MINIMUM_CONFIRMATIONS) == +// true) { +// spendableOutputs.add(availableOutputs[i]); +// spendableSatoshiValue += availableOutputs[i].value; +// } +// } +// +// if (spendableSatoshiValue < amountToSend) { +// // insufficient balance +// throw InsufficientBalanceException( +// "Spendable balance is less than the minimum required for a notification transaction."); +// } else if (spendableSatoshiValue == amountToSend) { +// // insufficient balance due to missing amount to cover fee +// throw InsufficientBalanceException( +// "Remaining balance does not cover the network fee."); +// } +// +// // sort spendable by age (oldest first) +// spendableOutputs.sort((a, b) => b.blockTime!.compareTo(a.blockTime!)); +// +// int satoshisBeingUsed = 0; +// int outputsBeingUsed = 0; +// List utxoObjectsToUse = []; +// +// for (int i = 0; +// satoshisBeingUsed < amountToSend && i < spendableOutputs.length; +// i++) { +// utxoObjectsToUse.add(spendableOutputs[i]); +// satoshisBeingUsed += spendableOutputs[i].value; +// outputsBeingUsed += 1; +// } +// +// // add additional outputs if required +// for (int i = 0; +// i < additionalOutputs && outputsBeingUsed < spendableOutputs.length; +// i++) { +// utxoObjectsToUse.add(spendableOutputs[outputsBeingUsed]); +// satoshisBeingUsed += spendableOutputs[outputsBeingUsed].value; +// outputsBeingUsed += 1; +// } +// +// // gather required signing data +// final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); +// +// final int vSizeForNoChange = (await _createNotificationTx( +// targetPaymentCodeString: targetPaymentCodeString, +// utxosToUse: utxoObjectsToUse, +// utxoSigningData: utxoSigningData, +// change: 0)) +// .item2; +// +// final int vSizeForWithChange = (await _createNotificationTx( +// targetPaymentCodeString: targetPaymentCodeString, +// utxosToUse: utxoObjectsToUse, +// utxoSigningData: utxoSigningData, +// change: satoshisBeingUsed - amountToSend)) +// .item2; +// +// // Assume 2 outputs, for recipient and payment code script +// int feeForNoChange = estimateTxFee( +// vSize: vSizeForNoChange, +// feeRatePerKB: selectedTxFeeRate, +// ); +// +// // Assume 3 outputs, for recipient, payment code script, and change +// int feeForWithChange = estimateTxFee( +// vSize: vSizeForWithChange, +// feeRatePerKB: selectedTxFeeRate, +// ); +// +// if (feeForNoChange < vSizeForNoChange * 1000) { +// feeForNoChange = vSizeForNoChange * 1000; +// } +// if (feeForWithChange < vSizeForWithChange * 1000) { +// feeForWithChange = vSizeForWithChange * 1000; +// } +// +// if (satoshisBeingUsed - amountToSend > feeForNoChange + DUST_LIMIT) { +// // try to add change output due to "left over" amount being greater than +// // the estimated fee + the dust limit +// int changeAmount = satoshisBeingUsed - amountToSend - feeForWithChange; +// +// // check estimates are correct and build notification tx +// if (changeAmount >= DUST_LIMIT && +// satoshisBeingUsed - amountToSend - changeAmount == feeForWithChange) { +// final txn = await _createNotificationTx( +// targetPaymentCodeString: targetPaymentCodeString, +// utxosToUse: utxoObjectsToUse, +// utxoSigningData: utxoSigningData, +// change: changeAmount, +// ); +// +// int feeBeingPaid = satoshisBeingUsed - amountToSend - changeAmount; +// +// Map transactionObject = { +// "hex": txn.item1, +// "recipientPaynym": targetPaymentCodeString, +// "amount": amountToSend, +// "fee": feeBeingPaid, +// "vSize": txn.item2, +// }; +// return transactionObject; +// } else { +// // something broke during fee estimation or the change amount is smaller +// // than the dust limit. Try without change +// final txn = await _createNotificationTx( +// targetPaymentCodeString: targetPaymentCodeString, +// utxosToUse: utxoObjectsToUse, +// utxoSigningData: utxoSigningData, +// change: 0, +// ); +// +// int feeBeingPaid = satoshisBeingUsed - amountToSend; +// +// Map transactionObject = { +// "hex": txn.item1, +// "recipientPaynym": targetPaymentCodeString, +// "amount": amountToSend, +// "fee": feeBeingPaid, +// "vSize": txn.item2, +// }; +// return transactionObject; +// } +// } else if (satoshisBeingUsed - amountToSend >= feeForNoChange) { +// // since we already checked if we need to add a change output we can just +// // build without change here +// final txn = await _createNotificationTx( +// targetPaymentCodeString: targetPaymentCodeString, +// utxosToUse: utxoObjectsToUse, +// utxoSigningData: utxoSigningData, +// change: 0, +// ); +// +// int feeBeingPaid = satoshisBeingUsed - amountToSend; +// +// Map transactionObject = { +// "hex": txn.item1, +// "recipientPaynym": targetPaymentCodeString, +// "amount": amountToSend, +// "fee": feeBeingPaid, +// "vSize": txn.item2, +// }; +// return transactionObject; +// } else { +// // if we get here we do not have enough funds to cover the tx total so we +// // check if we have any more available outputs and try again +// if (spendableOutputs.length > outputsBeingUsed) { +// return prepareNotificationTx( +// selectedTxFeeRate: selectedTxFeeRate, +// targetPaymentCodeString: targetPaymentCodeString, +// additionalOutputs: additionalOutputs + 1, +// ); +// } else { +// throw InsufficientBalanceException( +// "Remaining balance does not cover the network fee."); +// } +// } +// } +// +// // return tuple with string value equal to the raw tx hex and the int value +// // equal to its vSize +// Future> _createNotificationTx({ +// required String targetPaymentCodeString, +// required List utxosToUse, +// required Map utxoSigningData, +// required int change, +// }) async { +// final targetPaymentCode = +// PaymentCode.fromPaymentCode(targetPaymentCodeString, network); +// final myCode = await getPaymentCode(DerivePathType.bip44); +// +// final utxo = utxosToUse.first; +// final txPoint = utxo.txid.fromHex.toList(); +// final txPointIndex = utxo.vout; +// +// final rev = Uint8List(txPoint.length + 4); +// Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); +// final buffer = rev.buffer.asByteData(); +// buffer.setUint32(txPoint.length, txPointIndex, Endian.little); +// +// final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as btc_dart.ECPair; +// +// final S = SecretPoint( +// myKeyPair.privateKey!, +// targetPaymentCode.notificationPublicKey(), +// ); +// +// final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev); +// +// final blindedPaymentCode = PaymentCode.blind( +// myCode.getPayload(), +// blindingMask, +// ); +// +// final opReturnScript = bscript.compile([ +// (op.OPS["OP_RETURN"] as int), +// blindedPaymentCode, +// ]); +// +// // build a notification tx +// final txb = btc_dart.TransactionBuilder(network: network); +// txb.setVersion(1); +// +// txb.addInput( +// utxo.txid, +// txPointIndex, +// ); +// +// // todo: modify address once segwit support is in our bip47 +// txb.addOutput(targetPaymentCode.notificationAddressP2PKH(), DUST_LIMIT); +// txb.addOutput(opReturnScript, 0); +// +// // TODO: add possible change output and mark output as dangerous +// if (change > 0) { +// // generate new change address if current change address has been used +// await checkChangeAddressForTransactions(); +// final String changeAddress = await currentChangeAddress; +// txb.addOutput(changeAddress, change); +// } +// +// txb.sign( +// vin: 0, +// keyPair: myKeyPair, +// ); +// +// // sign rest of possible inputs +// for (var i = 1; i < utxosToUse.length - 1; i++) { +// final txid = utxosToUse[i].txid; +// txb.sign( +// vin: i, +// keyPair: utxoSigningData[txid]["keyPair"] as btc_dart.ECPair, +// // witnessValue: utxosToUse[i].value, +// ); +// } +// +// final builtTx = txb.build(); +// +// return Tuple2(builtTx.toHex(), builtTx.virtualSize()); +// } +// +// Future broadcastNotificationTx( +// {required Map preparedTx}) async { +// try { +// Logging.instance.log("confirmNotificationTx txData: $preparedTx", +// level: LogLevel.Info); +// final txHash = await electrumXClient.broadcastTransaction( +// rawTx: preparedTx["hex"] as String); +// Logging.instance.log("Sent txHash: $txHash", level: LogLevel.Info); +// +// // TODO: only refresh transaction data +// try { +// await refresh(); +// } catch (e) { +// Logging.instance.log( +// "refresh() failed in confirmNotificationTx ($walletName::$walletId): $e", +// level: LogLevel.Error, +// ); +// } +// +// return txHash; +// } catch (e, s) { +// Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s", +// level: LogLevel.Error); +// rethrow; +// } +// } +// +// // TODO optimize +// Future hasConnected(String paymentCodeString) async { +// final myNotificationAddress = +// await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); +// +// final txns = await db +// .getTransactions(walletId) +// .filter() +// .subTypeEqualTo(TransactionSubType.bip47Notification) +// .findAll(); +// +// for (final tx in txns) { +// // quick check that may cause problems? +// if (tx.address.value?.value == myNotificationAddress.value) { +// return true; +// } +// +// final unBlindedPaymentCode = await unBlindedPaymentCodeFromTransaction( +// transaction: tx, +// myNotificationAddress: myNotificationAddress, +// ); +// +// if (paymentCodeString == unBlindedPaymentCode.toString()) { +// return true; +// } +// } +// +// // otherwise return no +// return false; +// } +// +// Future unBlindedPaymentCodeFromTransaction({ +// required Transaction transaction, +// required Address myNotificationAddress, +// }) async { +// if (transaction.address.value != null && +// transaction.address.value!.value != myNotificationAddress.value) { +// return null; +// } +// +// try { +// final blindedCode = +// transaction.outputs.elementAt(1).scriptPubKeyAsm!.split(" ")[1]; +// +// final designatedInput = transaction.inputs.first; +// +// final txPoint = designatedInput.txid.fromHex.toList(); +// final txPointIndex = designatedInput.vout; +// +// final rev = Uint8List(txPoint.length + 4); +// Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length); +// final buffer = rev.buffer.asByteData(); +// buffer.setUint32(txPoint.length, txPointIndex, Endian.little); +// +// final pubKey = designatedInput.scriptSigAsm!.split(" ")[1].fromHex; +// +// final myPrivateKey = +// await deriveNotificationPrivateKey(mnemonic: await mnemonic); +// +// final S = SecretPoint(myPrivateKey, pubKey); +// +// final mask = PaymentCode.getMask(S.ecdhSecret(), rev); +// +// final unBlindedPayload = PaymentCode.blind(blindedCode.fromHex, mask); +// +// final unBlindedPaymentCode = +// PaymentCode.initFromPayload(unBlindedPayload); +// +// return unBlindedPaymentCode; +// } catch (e) { +// Logging.instance.log( +// "unBlindedPaymentCodeFromTransaction() failed: $e", +// level: LogLevel.Warning, +// ); +// return null; +// } +// } +// +// Future> +// getAllPaymentCodesFromNotificationTransactions() async { +// final myAddress = +// await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); +// final txns = await db +// .getTransactions(walletId) +// .filter() +// .subTypeEqualTo(TransactionSubType.bip47Notification) +// .findAll(); +// +// List unBlindedList = []; +// +// for (final tx in txns) { +// final unBlinded = await unBlindedPaymentCodeFromTransaction( +// transaction: tx, +// myNotificationAddress: myAddress, +// ); +// if (unBlinded != null) { +// unBlindedList.add(unBlinded); +// } +// } +// +// return unBlindedList; +// } +// +// Future restoreHistoryWith( +// PaymentCode other, +// int maxUnusedAddressGap, +// int maxNumberOfIndexesToCheck, +// ) async { +// // https://en.bitcoin.it/wiki/BIP_0047#Path_levels +// const maxCount = 2147483647; +// assert(maxNumberOfIndexesToCheck < maxCount); +// +// final myPrivateKey = +// await deriveNotificationPrivateKey(mnemonic: await mnemonic); +// +// List
addresses = []; +// int receivingGapCounter = 0; +// int outgoingGapCounter = 0; +// +// for (int i = 0; +// i < maxNumberOfIndexesToCheck && +// (receivingGapCounter < maxUnusedAddressGap || +// outgoingGapCounter < maxUnusedAddressGap); +// i++) { +// final paymentAddress = PaymentAddress.initWithPrivateKey( +// myPrivateKey, +// other, +// i, // index to use +// ); +// +// if (receivingGapCounter < maxUnusedAddressGap) { +// final pair = paymentAddress.getSendAddressKeyPair(); +// final address = generatePaynymSendAddressFromKeyPair( +// pair: pair, +// derivationIndex: i, +// derivePathType: DerivePathType.bip44, +// toPaymentCode: other, +// ); +// addresses.add(address); +// +// final count = await getTxCount(address: address.value); +// +// if (count > 0) { +// receivingGapCounter++; +// } else { +// receivingGapCounter = 0; +// } +// } +// +// if (outgoingGapCounter < maxUnusedAddressGap) { +// final pair = paymentAddress.getReceiveAddressKeyPair(); +// final address = generatePaynymReceivingAddressFromKeyPair( +// pair: pair, +// derivationIndex: i, +// derivePathType: DerivePathType.bip44, +// fromPaymentCode: other, +// ); +// addresses.add(address); +// +// final count = await getTxCount(address: address.value); +// +// if (count > 0) { +// outgoingGapCounter++; +// } else { +// outgoingGapCounter = 0; +// } +// } +// } +// await db.putAddresses(addresses); +// } +// +// Address generatePaynymSendAddressFromKeyPair({ +// required btc_dart.ECPair pair, +// required int derivationIndex, +// required DerivePathType derivePathType, +// required PaymentCode toPaymentCode, +// }) { +// final data = btc_dart.PaymentData(pubkey: pair.publicKey); +// +// String addressString; +// switch (derivePathType) { +// case DerivePathType.bip44: +// addressString = +// btc_dart.P2PKH(data: data, network: network).data.address!; +// break; +// +// // The following doesn't apply currently +// // case DerivePathType.bip49: +// // addressString = btc_dart +// // .P2SH( +// // data: btc_dart.PaymentData( +// // redeem: btc_dart +// // .P2WPKH( +// // data: data, +// // network: network, +// // ) +// // .data), +// // network: network, +// // ) +// // .data +// // .address!; +// // break; +// // +// // case DerivePathType.bip84: +// // addressString = btc_dart +// // .P2WPKH( +// // network: network, +// // data: data, +// // ) +// // .data +// // .address!; +// // break; +// default: +// throw UnimplementedError("segwit paynyms not implemented yet"); +// } +// +// final address = Address( +// walletId: walletId, +// value: addressString, +// publicKey: pair.publicKey, +// derivationIndex: derivationIndex, +// type: AddressType.nonWallet, +// subType: AddressSubType.paynymSend, +// otherData: toPaymentCode.toString(), +// ); +// +// return address; +// } +// +// Address generatePaynymReceivingAddressFromKeyPair({ +// required btc_dart.ECPair pair, +// required int derivationIndex, +// required DerivePathType derivePathType, +// required PaymentCode fromPaymentCode, +// }) { +// final data = btc_dart.PaymentData(pubkey: pair.publicKey); +// +// String addressString; +// AddressType addrType; +// switch (derivePathType) { +// case DerivePathType.bip44: +// addressString = btc_dart +// .P2PKH( +// data: data, +// network: network, +// ) +// .data +// .address!; +// addrType = AddressType.p2pkh; +// break; +// +// // The following doesn't apply currently +// // case DerivePathType.bip49: +// // addressString = btc_dart +// // .P2SH( +// // data: btc_dart.PaymentData( +// // redeem: btc_dart +// // .P2WPKH( +// // data: data, +// // network: network, +// // ) +// // .data), +// // network: network, +// // ) +// // .data +// // .address!; +// // addrType = AddressType.p2sh; +// // break; +// // +// // case DerivePathType.bip84: +// // addressString = btc_dart +// // .P2WPKH( +// // network: network, +// // data: data, +// // ) +// // .data +// // .address!; +// // addrType = AddressType.p2wpkh; +// // break; +// default: +// throw UnimplementedError("segwit paynyms not implemented yet"); +// } +// +// final address = Address( +// walletId: walletId, +// value: addressString, +// publicKey: pair.publicKey, +// derivationIndex: derivationIndex, +// type: addrType, +// subType: AddressSubType.paynymReceive, +// otherData: fromPaymentCode.toString(), +// ); +// +// return address; +// } +// +// Future
getMyNotificationAddress( +// DerivePathType derivePathType, +// ) async { +// // TODO: fix when segwit is here +// derivePathType = DerivePathType.bip44; +// +// AddressType type; +// switch (derivePathType) { +// case DerivePathType.bip44: +// type = AddressType.p2pkh; +// break; +// case DerivePathType.bip49: +// type = AddressType.p2sh; +// break; +// case DerivePathType.bip84: +// type = AddressType.p2wpkh; +// break; +// } +// +// final storedAddress = await db +// .getAddresses(walletId) +// .filter() +// .subTypeEqualTo(AddressSubType.paynymNotification) +// .and() +// .typeEqualTo(type) +// .and() +// .not() +// .typeEqualTo(AddressType.nonWallet) +// .findFirst(); +// +// if (storedAddress != null) { +// return storedAddress; +// } else { +// final root = await getRootNode(mnemonic: await mnemonic); +// final node = root.derivePath(kPaynymDerivePath); +// final paymentCode = PaymentCode.initFromPubKey( +// node.publicKey, +// node.chainCode, +// network, +// ); +// +// String addressString; +// final data = +// btc_dart.PaymentData(pubkey: paymentCode.notificationPublicKey()); +// switch (derivePathType) { +// case DerivePathType.bip44: +// addressString = btc_dart +// .P2PKH( +// data: data, +// network: network, +// ) +// .data +// .address!; +// break; +// // case DerivePathType.bip49: +// // addressString = btc_dart +// // .P2SH( +// // data: btc_dart.PaymentData( +// // redeem: btc_dart +// // .P2WPKH( +// // data: data, +// // network: network, +// // ) +// // .data), +// // network: network, +// // ) +// // .data +// // .address!; +// // break; +// // case DerivePathType.bip84: +// // addressString = btc_dart +// // .P2WPKH( +// // network: network, +// // data: data, +// // ) +// // .data +// // .address!; +// // break; +// default: +// throw UnimplementedError("segwit paynyms not implemented yet"); +// } +// +// final address = Address( +// walletId: walletId, +// value: addressString, +// publicKey: paymentCode.getPubKey(), +// derivationIndex: 0, +// type: type, +// subType: AddressSubType.paynymNotification, +// otherData: paymentCode.toString(), +// ); +// +// await db.putAddress(address); +// return address; +// } +// } +// } diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index b276af965..f5a057500 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -24,6 +24,7 @@ import 'package:stackwallet/services/event_bus/events/global/updated_in_backgrou 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/electrum_x_parsing.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; @@ -125,7 +126,7 @@ bip32.BIP32 getBip32RootWrapper(Tuple2 args) { } class DogecoinWallet extends CoinServiceAPI - with WalletCache, WalletDB, ElectrumXParsing { + with WalletCache, WalletDB, ElectrumXParsing, PaynymWalletInterface { static const integrationTestFlag = bool.fromEnvironment("IS_INTEGRATION_TEST"); final _prefs = Prefs.instance; @@ -1099,6 +1100,23 @@ class DogecoinWallet extends CoinServiceAPI _secureStore = secureStore; initCache(walletId, coin); initWalletDB(mockableOverride: mockableOverride); + initPaynymWalletInterface( + walletId: walletId, + walletName: walletName, + network: network, + coin: coin, + db: db, + electrumXClient: electrumXClient, + getMnemonic: () => mnemonic, + getChainHeight: () => chainHeight, + getCurrentChangeAddress: () => currentChangeAddress, + estimateTxFee: estimateTxFee, + prepareSend: prepareSend, + getTxCount: getTxCount, + fetchBuildTxData: fetchBuildTxData, + refresh: refresh, + checkChangeAddressForTransactions: checkChangeAddressForTransactions, + ); } @override diff --git a/lib/services/coins/manager.dart b/lib/services/coins/manager.dart index 65ba54c36..892766cf5 100644 --- a/lib/services/coins/manager.dart +++ b/lib/services/coins/manager.dart @@ -9,7 +9,7 @@ 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/global_event_bus.dart'; -import 'package:stackwallet/services/mixins/paynym_support.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/logger.dart'; diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart index b95a749f1..61bc03beb 100644 --- a/lib/services/mixins/electrum_x_parsing.dart +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -1,7 +1,7 @@ import 'package:bip47/src/util.dart'; import 'package:decimal/decimal.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; -import 'package:stackwallet/services/mixins/paynym_support.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:tuple/tuple.dart'; diff --git a/lib/services/mixins/paynym_support.dart b/lib/services/mixins/paynym_wallet_interface.dart similarity index 88% rename from lib/services/mixins/paynym_support.dart rename to lib/services/mixins/paynym_wallet_interface.dart index 3db2ec602..1073c3c40 100644 --- a/lib/services/mixins/paynym_support.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -24,39 +24,39 @@ import 'package:tuple/tuple.dart'; const kPaynymDerivePath = "m/47'/0'/0'"; -mixin PaynymSupport { +mixin PaynymWalletInterface { // passed in wallet data - late final String walletId; - late final String walletName; - late final btc_dart.NetworkType network; - late final Coin coin; - late final MainDB db; - late final ElectrumX electrumXClient; + late final String _walletId; + late final String _walletName; + late final btc_dart.NetworkType _network; + late final Coin _coin; + late final MainDB _db; + late final ElectrumX _electrumXClient; // passed in wallet functions - late final Future> Function() getMnemonic; - late final Future Function() getChainHeight; - late final Future Function() getCurrentChangeAddress; + late final Future> Function() _getMnemonic; + late final Future Function() _getChainHeight; + late final Future Function() _getCurrentChangeAddress; late final int Function({ required int vSize, required int feeRatePerKB, - }) estimateTxFee; + }) _estimateTxFee; late final Future> Function({ required String address, required int satoshiAmount, Map? args, - }) prepareSend; + }) _prepareSend; late final Future Function({ required String address, - }) getTxCount; + }) _getTxCount; late final Future> Function( List utxosToUse, - ) fetchBuildTxData; - late final Future Function() refresh; - late final Future Function() checkChangeAddressForTransactions; + ) _fetchBuildTxData; + late final Future Function() _refresh; + late final Future Function() _checkChangeAddressForTransactions; // initializer - void initPaynymSupport({ + void initPaynymWalletInterface({ required String walletId, required String walletName, required btc_dart.NetworkType network, @@ -88,28 +88,28 @@ mixin PaynymSupport { required Future Function() refresh, required Future Function() checkChangeAddressForTransactions, }) { - this.walletId = walletId; - this.walletName = walletName; - this.network = network; - this.coin = coin; - this.db = db; - this.electrumXClient = electrumXClient; - this.getMnemonic = getMnemonic; - this.getChainHeight = getChainHeight; - this.getCurrentChangeAddress = getCurrentChangeAddress; - this.estimateTxFee = estimateTxFee; - this.prepareSend = prepareSend; - this.getTxCount = getTxCount; - this.fetchBuildTxData = fetchBuildTxData; - this.refresh = refresh; - this.checkChangeAddressForTransactions = checkChangeAddressForTransactions; + _walletId = walletId; + _walletName = walletName; + _network = network; + _coin = coin; + _db = db; + _electrumXClient = electrumXClient; + _getMnemonic = getMnemonic; + _getChainHeight = getChainHeight; + _getCurrentChangeAddress = getCurrentChangeAddress; + _estimateTxFee = estimateTxFee; + _prepareSend = prepareSend; + _getTxCount = getTxCount; + _fetchBuildTxData = fetchBuildTxData; + _refresh = refresh; + _checkChangeAddressForTransactions = checkChangeAddressForTransactions; } // generate bip32 payment code root Future getRootNode({ required List mnemonic, }) async { - final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), network); + final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), _network); return root; } @@ -128,15 +128,15 @@ mixin PaynymSupport { final address = await getMyNotificationAddress(derivePathType); final paymentCode = PaymentCode.fromPaymentCode( address.otherData!, - network, + _network, ); return paymentCode; } Future signWithNotificationKey(Uint8List data) async { final privateKey = - await deriveNotificationPrivateKey(mnemonic: await getMnemonic()); - final pair = btc_dart.ECPair.fromPrivateKey(privateKey, network: network); + await deriveNotificationPrivateKey(mnemonic: await _getMnemonic()); + final pair = btc_dart.ECPair.fromPrivateKey(privateKey, network: _network); final signed = pair.sign(SHA256Digest().process(data)); return signed; } @@ -156,13 +156,13 @@ mixin PaynymSupport { "No notification transaction sent to $paymentCode"); } else { final myPrivateKey = - await deriveNotificationPrivateKey(mnemonic: await getMnemonic()); + await deriveNotificationPrivateKey(mnemonic: await _getMnemonic()); final sendToAddress = await nextUnusedSendAddressFrom( pCode: paymentCode, privateKey: myPrivateKey, ); - return prepareSend( + return _prepareSend( address: sendToAddress.value, satoshiAmount: satoshiAmount); } } @@ -178,8 +178,8 @@ mixin PaynymSupport { const maxCount = 2147483647; for (int i = startIndex; i < maxCount; i++) { - final address = await db - .getAddresses(walletId) + final address = await _db + .getAddresses(_walletId) .filter() .subTypeEqualTo(AddressSubType.paynymSend) .and() @@ -189,7 +189,7 @@ mixin PaynymSupport { .findFirst(); if (address != null) { - final count = await getTxCount(address: address.value); + final count = await _getTxCount(address: address.value); // return address if unused, otherwise continue to next index if (count == 0) { return address; @@ -208,9 +208,9 @@ mixin PaynymSupport { derivePathType: DerivePathType.bip44, toPaymentCode: pCode, ); - await db.putAddress(address); + await _db.putAddress(address); - final count = await getTxCount(address: address.value); + final count = await _getTxCount(address: address.value); // return address if unused, otherwise continue to next index if (count == 0) { return address; @@ -229,15 +229,15 @@ mixin PaynymSupport { }) async { const amountToSend = DUST_LIMIT; final List availableOutputs = - utxos ?? await db.getUTXOs(walletId).findAll(); + utxos ?? await _db.getUTXOs(_walletId).findAll(); final List spendableOutputs = []; int spendableSatoshiValue = 0; // Build list of spendable outputs and totaling their satoshi amount for (var i = 0; i < availableOutputs.length; i++) { if (availableOutputs[i].isBlocked == false && - availableOutputs[i] - .isConfirmed(await getChainHeight(), MINIMUM_CONFIRMATIONS) == + availableOutputs[i].isConfirmed( + await _getChainHeight(), MINIMUM_CONFIRMATIONS) == true) { spendableOutputs.add(availableOutputs[i]); spendableSatoshiValue += availableOutputs[i].value; @@ -279,7 +279,7 @@ mixin PaynymSupport { } // gather required signing data - final utxoSigningData = await fetchBuildTxData(utxoObjectsToUse); + final utxoSigningData = await _fetchBuildTxData(utxoObjectsToUse); final int vSizeForNoChange = (await _createNotificationTx( targetPaymentCodeString: targetPaymentCodeString, @@ -296,13 +296,13 @@ mixin PaynymSupport { .item2; // Assume 2 outputs, for recipient and payment code script - int feeForNoChange = estimateTxFee( + int feeForNoChange = _estimateTxFee( vSize: vSizeForNoChange, feeRatePerKB: selectedTxFeeRate, ); // Assume 3 outputs, for recipient, payment code script, and change - int feeForWithChange = estimateTxFee( + int feeForWithChange = _estimateTxFee( vSize: vSizeForWithChange, feeRatePerKB: selectedTxFeeRate, ); @@ -405,7 +405,7 @@ mixin PaynymSupport { required int change, }) async { final targetPaymentCode = - PaymentCode.fromPaymentCode(targetPaymentCodeString, network); + PaymentCode.fromPaymentCode(targetPaymentCodeString, _network); final myCode = await getPaymentCode(DerivePathType.bip44); final utxo = utxosToUse.first; @@ -437,7 +437,7 @@ mixin PaynymSupport { ]); // build a notification tx - final txb = btc_dart.TransactionBuilder(network: network); + final txb = btc_dart.TransactionBuilder(network: _network); txb.setVersion(1); txb.addInput( @@ -452,8 +452,8 @@ mixin PaynymSupport { // TODO: add possible change output and mark output as dangerous if (change > 0) { // generate new change address if current change address has been used - await checkChangeAddressForTransactions(); - final String changeAddress = await getCurrentChangeAddress(); + await _checkChangeAddressForTransactions(); + final String changeAddress = await _getCurrentChangeAddress(); txb.addOutput(changeAddress, change); } @@ -482,16 +482,16 @@ mixin PaynymSupport { try { Logging.instance.log("confirmNotificationTx txData: $preparedTx", level: LogLevel.Info); - final txHash = await electrumXClient.broadcastTransaction( + final txHash = await _electrumXClient.broadcastTransaction( rawTx: preparedTx["hex"] as String); Logging.instance.log("Sent txHash: $txHash", level: LogLevel.Info); // TODO: only refresh transaction data try { - await refresh(); + await _refresh(); } catch (e) { Logging.instance.log( - "refresh() failed in confirmNotificationTx ($walletName::$walletId): $e", + "refresh() failed in confirmNotificationTx ($_walletName::$_walletId): $e", level: LogLevel.Error, ); } @@ -507,10 +507,10 @@ mixin PaynymSupport { // TODO optimize Future hasConnected(String paymentCodeString) async { final myNotificationAddress = - await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); + await getMyNotificationAddress(DerivePathTypeExt.primaryFor(_coin)); - final txns = await db - .getTransactions(walletId) + final txns = await _db + .getTransactions(_walletId) .filter() .subTypeEqualTo(TransactionSubType.bip47Notification) .findAll(); @@ -561,7 +561,7 @@ mixin PaynymSupport { final pubKey = designatedInput.scriptSigAsm!.split(" ")[1].fromHex; final myPrivateKey = - await deriveNotificationPrivateKey(mnemonic: await getMnemonic()); + await deriveNotificationPrivateKey(mnemonic: await _getMnemonic()); final S = SecretPoint(myPrivateKey, pubKey); @@ -585,9 +585,9 @@ mixin PaynymSupport { Future> getAllPaymentCodesFromNotificationTransactions() async { final myAddress = - await getMyNotificationAddress(DerivePathTypeExt.primaryFor(coin)); - final txns = await db - .getTransactions(walletId) + await getMyNotificationAddress(DerivePathTypeExt.primaryFor(_coin)); + final txns = await _db + .getTransactions(_walletId) .filter() .subTypeEqualTo(TransactionSubType.bip47Notification) .findAll(); @@ -617,7 +617,7 @@ mixin PaynymSupport { assert(maxNumberOfIndexesToCheck < maxCount); final myPrivateKey = - await deriveNotificationPrivateKey(mnemonic: await getMnemonic()); + await deriveNotificationPrivateKey(mnemonic: await _getMnemonic()); List
addresses = []; int receivingGapCounter = 0; @@ -644,7 +644,7 @@ mixin PaynymSupport { ); addresses.add(address); - final count = await getTxCount(address: address.value); + final count = await _getTxCount(address: address.value); if (count > 0) { receivingGapCounter++; @@ -663,7 +663,7 @@ mixin PaynymSupport { ); addresses.add(address); - final count = await getTxCount(address: address.value); + final count = await _getTxCount(address: address.value); if (count > 0) { outgoingGapCounter++; @@ -672,7 +672,7 @@ mixin PaynymSupport { } } } - await db.putAddresses(addresses); + await _db.putAddresses(addresses); } Address generatePaynymSendAddressFromKeyPair({ @@ -687,7 +687,7 @@ mixin PaynymSupport { switch (derivePathType) { case DerivePathType.bip44: addressString = - btc_dart.P2PKH(data: data, network: network).data.address!; + btc_dart.P2PKH(data: data, network: _network).data.address!; break; // The following doesn't apply currently @@ -721,7 +721,7 @@ mixin PaynymSupport { } final address = Address( - walletId: walletId, + walletId: _walletId, value: addressString, publicKey: pair.publicKey, derivationIndex: derivationIndex, @@ -748,7 +748,7 @@ mixin PaynymSupport { addressString = btc_dart .P2PKH( data: data, - network: network, + network: _network, ) .data .address!; @@ -788,7 +788,7 @@ mixin PaynymSupport { } final address = Address( - walletId: walletId, + walletId: _walletId, value: addressString, publicKey: pair.publicKey, derivationIndex: derivationIndex, @@ -819,8 +819,8 @@ mixin PaynymSupport { break; } - final storedAddress = await db - .getAddresses(walletId) + final storedAddress = await _db + .getAddresses(_walletId) .filter() .subTypeEqualTo(AddressSubType.paynymNotification) .and() @@ -833,12 +833,12 @@ mixin PaynymSupport { if (storedAddress != null) { return storedAddress; } else { - final root = await getRootNode(mnemonic: await getMnemonic()); + final root = await getRootNode(mnemonic: await _getMnemonic()); final node = root.derivePath(kPaynymDerivePath); final paymentCode = PaymentCode.initFromPubKey( node.publicKey, node.chainCode, - network, + _network, ); String addressString; @@ -849,7 +849,7 @@ mixin PaynymSupport { addressString = btc_dart .P2PKH( data: data, - network: network, + network: _network, ) .data .address!; @@ -883,7 +883,7 @@ mixin PaynymSupport { } final address = Address( - walletId: walletId, + walletId: _walletId, value: addressString, publicKey: paymentCode.getPubKey(), derivationIndex: 0, @@ -892,7 +892,7 @@ mixin PaynymSupport { otherData: paymentCode.toString(), ); - await db.putAddress(address); + await _db.putAddress(address); return address; } } From 700084f70839bb91c3c42e2586a3013f68be7431 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 16:11:06 -0600 Subject: [PATCH 24/55] remove wallet specific derivePathType tests as it was removed from the wallet files --- test/services/coins/bitcoin/bitcoin_wallet_test.dart | 7 +------ .../coins/bitcoincash/bitcoincash_wallet_test.dart | 7 +------ test/services/coins/dogecoin/dogecoin_wallet_test.dart | 6 +----- test/services/coins/namecoin/namecoin_wallet_test.dart | 7 +------ test/services/coins/particl/particl_wallet_test.dart | 7 +------ 5 files changed, 5 insertions(+), 29 deletions(-) diff --git a/test/services/coins/bitcoin/bitcoin_wallet_test.dart b/test/services/coins/bitcoin/bitcoin_wallet_test.dart index 6fdea3d03..2efce36f3 100644 --- a/test/services/coins/bitcoin/bitcoin_wallet_test.dart +++ b/test/services/coins/bitcoin/bitcoin_wallet_test.dart @@ -11,6 +11,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'bitcoin_wallet_test.mocks.dart'; @@ -39,12 +40,6 @@ void main() async { }); }); - test("bitcoin DerivePathType enum", () { - expect(DerivePathType.values.length, 3); - expect(DerivePathType.values.toString(), - "[DerivePathType.bip44, DerivePathType.bip49, DerivePathType.bip84]"); - }); - group("bip32 node/root", () { test("getBip32Root", () { final root = getBip32Root(TEST_MNEMONIC, bitcoin); diff --git a/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart b/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart index c4cdede86..93d85c324 100644 --- a/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart +++ b/test/services/coins/bitcoincash/bitcoincash_wallet_test.dart @@ -11,6 +11,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'bitcoincash_wallet_test.mocks.dart'; @@ -40,12 +41,6 @@ void main() async { }); }); - test("bitcoincash DerivePathType enum", () { - expect(DerivePathType.values.length, 2); - expect(DerivePathType.values.toString(), - "[DerivePathType.bip44, DerivePathType.bip49]"); - }); - group("bip32 node/root", () { test("getBip32Root", () { final root = getBip32Root(TEST_MNEMONIC, bitcoincash); diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.dart index e9f166736..7a025e760 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.dart @@ -11,6 +11,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'dogecoin_wallet_test.mocks.dart'; @@ -39,11 +40,6 @@ void main() { }); }); - test("dogecoin DerivePathType enum", () { - expect(DerivePathType.values.length, 1); - expect(DerivePathType.values.toString(), "[DerivePathType.bip44]"); - }); - group("bip32 node/root", () { test("getBip32Root", () { final root = getBip32Root(TEST_MNEMONIC, dogecoin); diff --git a/test/services/coins/namecoin/namecoin_wallet_test.dart b/test/services/coins/namecoin/namecoin_wallet_test.dart index 53ce2edbd..22750a935 100644 --- a/test/services/coins/namecoin/namecoin_wallet_test.dart +++ b/test/services/coins/namecoin/namecoin_wallet_test.dart @@ -10,6 +10,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'namecoin_wallet_test.mocks.dart'; @@ -38,12 +39,6 @@ void main() { }); }); - test("namecoin DerivePathType enum", () { - expect(DerivePathType.values.length, 3); - expect(DerivePathType.values.toString(), - "[DerivePathType.bip44, DerivePathType.bip49, DerivePathType.bip84]"); - }); - group("bip32 node/root", () { test("getBip32Root", () { final root = getBip32Root(TEST_MNEMONIC, namecoin); diff --git a/test/services/coins/particl/particl_wallet_test.dart b/test/services/coins/particl/particl_wallet_test.dart index 698a5f657..4f4d0e81b 100644 --- a/test/services/coins/particl/particl_wallet_test.dart +++ b/test/services/coins/particl/particl_wallet_test.dart @@ -10,6 +10,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/services/coins/particl/particl_wallet.dart'; import 'package:stackwallet/services/transaction_notification_tracker.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'particl_wallet_test.mocks.dart'; @@ -39,12 +40,6 @@ void main() { }); }); - test("particl DerivePathType enum", () { - expect(DerivePathType.values.length, 2); - expect(DerivePathType.values.toString(), - "[DerivePathType.bip44, DerivePathType.bip84]"); - }); - group("bip32 node/root", () { test("getBip32Root", () { final root = getBip32Root(TEST_MNEMONIC, particl); From 8cd34fc228b14a72a6dbf751e4a4affb19acb8e5 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 16:16:20 -0600 Subject: [PATCH 25/55] build runner update mocks --- .../pages/send_view/send_view_test.mocks.dart | 981 ++++++++++-------- ...d_address_book_view_screen_test.mocks.dart | 5 + ..._entry_details_view_screen_test.mocks.dart | 5 + ...ess_book_entry_view_screen_test.mocks.dart | 5 + .../lockscreen_view_screen_test.mocks.dart | 5 + .../main_view_screen_testA_test.mocks.dart | 5 + .../main_view_screen_testB_test.mocks.dart | 5 + .../main_view_screen_testC_test.mocks.dart | 5 + .../backup_key_view_screen_test.mocks.dart | 5 + ...up_key_warning_view_screen_test.mocks.dart | 5 + .../create_pin_view_screen_test.mocks.dart | 5 + ...restore_wallet_view_screen_test.mocks.dart | 5 + ...ify_backup_key_view_screen_test.mocks.dart | 5 + .../currency_view_screen_test.mocks.dart | 5 + ...dd_custom_node_view_screen_test.mocks.dart | 5 + .../node_details_view_screen_test.mocks.dart | 5 + .../wallet_backup_view_screen_test.mocks.dart | 5 + ...rescan_warning_view_screen_test.mocks.dart | 5 + ...elete_mnemonic_view_screen_test.mocks.dart | 5 + ...allet_settings_view_screen_test.mocks.dart | 5 + .../settings_view_screen_test.mocks.dart | 5 + ...search_results_view_screen_test.mocks.dart | 5 + .../confirm_send_view_screen_test.mocks.dart | 5 + .../receive_view_screen_test.mocks.dart | 5 + .../send_view_screen_test.mocks.dart | 5 + .../wallet_view_screen_test.mocks.dart | 5 + .../managed_favorite_test.mocks.dart | 937 +++++++++-------- .../table_view/table_view_row_test.mocks.dart | 805 +++++++------- .../transaction_card_test.mocks.dart | 5 + test/widget_tests/wallet_card_test.mocks.dart | 420 ++++---- ...et_info_row_balance_future_test.mocks.dart | 921 ++++++++-------- .../wallet_info_row_test.mocks.dart | 921 ++++++++-------- 32 files changed, 2803 insertions(+), 2312 deletions(-) diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart index bcd5f44fc..12548c513 100644 --- a/test/pages/send_view/send_view_test.mocks.dart +++ b/test/pages/send_view/send_view_test.mocks.dart @@ -3,8 +3,8 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i17; -import 'dart:ui' as _i19; +import 'dart:async' as _i18; +import 'dart:ui' as _i20; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; @@ -13,26 +13,28 @@ import 'package:stackwallet/db/main_db.dart' as _i13; 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 _i22; -import 'package:stackwallet/models/node_model.dart' as _i20; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i23; +import 'package:stackwallet/models/node_model.dart' as _i21; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i9; import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart' - as _i25; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i21; -import 'package:stackwallet/services/coins/coin_service.dart' as _i14; + as _i27; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i22; +import 'package:stackwallet/services/coins/coin_service.dart' as _i15; import 'package:stackwallet/services/coins/manager.dart' as _i6; -import 'package:stackwallet/services/locale_service.dart' as _i23; +import 'package:stackwallet/services/locale_service.dart' as _i25; 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 _i15; +import 'package:stackwallet/services/wallets.dart' as _i16; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i26; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i16; -import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i24; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i28; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i17; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i24; +import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i26; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' as _i7; -import 'package:stackwallet/utilities/prefs.dart' as _i18; +import 'package:stackwallet/utilities/prefs.dart' as _i19; +import 'package:tuple/tuple.dart' as _i14; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -171,9 +173,20 @@ class _FakeElectrumXNode_11 extends _i1.SmartFake ); } -class _FakeCoinServiceAPI_12 extends _i1.SmartFake - implements _i14.CoinServiceAPI { - _FakeCoinServiceAPI_12( +class _FakeTuple4_12 extends _i1.SmartFake + implements _i14.Tuple4 { + _FakeTuple4_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_13 extends _i1.SmartFake + implements _i15.CoinServiceAPI { + _FakeCoinServiceAPI_13( Object parent, Invocation parentInvocation, ) : super( @@ -185,7 +198,7 @@ class _FakeCoinServiceAPI_12 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 _i15.Wallets { +class MockWallets extends _i1.Mock implements _i16.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -252,7 +265,7 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i16.Coin? coin}) => + List getWalletIdsFor({required _i17.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -262,18 +275,18 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValue: [], ) as List); @override - Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> + Map<_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i16.Coin, + returnValue: <_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>{}, - ) as Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); + ) as Map<_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i16.Coin? coin) => + _i17.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -337,17 +350,17 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - _i17.Future load(_i18.Prefs? prefs) => (super.noSuchMethod( + _i18.Future load(_i19.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future loadAfterStackRestore( - _i18.Prefs? prefs, + _i18.Future loadAfterStackRestore( + _i19.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -358,11 +371,11 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { managers, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -370,7 +383,7 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -396,19 +409,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i17.Future> get walletNames => + _i18.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i17.Future>.value( + returnValue: _i18.Future>.value( {}), - ) as _i17.Future>); + ) as _i18.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future renameWallet({ + _i18.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -423,13 +436,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future addExistingStackWallet({ + _i18.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i16.Coin? coin, + required _i17.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -443,13 +456,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addNewWallet({ + _i18.Future addNewWallet({ required String? name, - required _i16.Coin? coin, + required _i17.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -462,46 +475,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i18.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override - _i17.Future saveFavoriteWalletIds(List? walletIds) => + _i18.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i18.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i18.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future moveFavorite({ + _i18.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -514,48 +527,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i18.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i18.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future isMnemonicVerified({required String? walletId}) => + _i18.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future setMnemonicVerified({required String? walletId}) => + _i18.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future deleteWallet( + _i18.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -567,20 +580,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future refreshWallets(bool? shouldNotifyListeners) => + _i18.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -588,7 +601,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -630,33 +643,33 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { ), ) as _i7.SecureStorageInterface); @override - List<_i20.NodeModel> get primaryNodes => (super.noSuchMethod( + List<_i21.NodeModel> get primaryNodes => (super.noSuchMethod( Invocation.getter(#primaryNodes), - returnValue: <_i20.NodeModel>[], - ) as List<_i20.NodeModel>); + returnValue: <_i21.NodeModel>[], + ) as List<_i21.NodeModel>); @override - List<_i20.NodeModel> get nodes => (super.noSuchMethod( + List<_i21.NodeModel> get nodes => (super.noSuchMethod( Invocation.getter(#nodes), - returnValue: <_i20.NodeModel>[], - ) as List<_i20.NodeModel>); + returnValue: <_i21.NodeModel>[], + ) as List<_i21.NodeModel>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future updateDefaults() => (super.noSuchMethod( + _i18.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future setPrimaryNodeFor({ - required _i16.Coin? coin, - required _i20.NodeModel? node, + _i18.Future setPrimaryNodeFor({ + required _i17.Coin? coin, + required _i21.NodeModel? node, bool? shouldNotifyListeners = false, }) => (super.noSuchMethod( @@ -669,44 +682,44 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i20.NodeModel? getPrimaryNodeFor({required _i16.Coin? coin}) => + _i21.NodeModel? getPrimaryNodeFor({required _i17.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getPrimaryNodeFor, [], {#coin: coin}, - )) as _i20.NodeModel?); + )) as _i21.NodeModel?); @override - List<_i20.NodeModel> getNodesFor(_i16.Coin? coin) => (super.noSuchMethod( + List<_i21.NodeModel> getNodesFor(_i17.Coin? coin) => (super.noSuchMethod( Invocation.method( #getNodesFor, [coin], ), - returnValue: <_i20.NodeModel>[], - ) as List<_i20.NodeModel>); + returnValue: <_i21.NodeModel>[], + ) as List<_i21.NodeModel>); @override - _i20.NodeModel? getNodeById({required String? id}) => + _i21.NodeModel? getNodeById({required String? id}) => (super.noSuchMethod(Invocation.method( #getNodeById, [], {#id: id}, - )) as _i20.NodeModel?); + )) as _i21.NodeModel?); @override - List<_i20.NodeModel> failoverNodesFor({required _i16.Coin? coin}) => + List<_i21.NodeModel> failoverNodesFor({required _i17.Coin? coin}) => (super.noSuchMethod( Invocation.method( #failoverNodesFor, [], {#coin: coin}, ), - returnValue: <_i20.NodeModel>[], - ) as List<_i20.NodeModel>); + returnValue: <_i21.NodeModel>[], + ) as List<_i21.NodeModel>); @override - _i17.Future add( - _i20.NodeModel? node, + _i18.Future add( + _i21.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => @@ -719,11 +732,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future delete( + _i18.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -735,11 +748,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future setEnabledState( + _i18.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -753,12 +766,12 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future edit( - _i20.NodeModel? editedNode, + _i18.Future edit( + _i21.NodeModel? editedNode, String? password, bool? shouldNotifyListeners, ) => @@ -771,20 +784,20 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateCommunityNodes() => (super.noSuchMethod( + _i18.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -792,7 +805,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -820,13 +833,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 _i21.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i22.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i17.Timer? _timer) => super.noSuchMethod( + set timer(_i18.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -903,59 +916,59 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { returnValue: false, ) as bool); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i22.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i23.UTXO>[]), + ) as _i18.Future>); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i22.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i23.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future get currentChangeAddress => (super.noSuchMethod( + _i18.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i17.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i9.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i18.Future<_i9.FeeObject>.value(_FakeFeeObject_6( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i9.FeeObject>); + ) as _i18.Future<_i9.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override - _i17.Future get chainHeight => (super.noSuchMethod( + _i18.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -1044,26 +1057,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { ), ) as _i13.MainDB); @override - _i17.Future exit() => (super.noSuchMethod( + _i18.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i21.DerivePathType addressType({required String? address}) => + _i24.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i21.DerivePathType.bip44, - ) as _i21.DerivePathType); + returnValue: _i24.DerivePathType.bip44, + ) as _i24.DerivePathType); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -1080,47 +1093,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future getTransactionCacheEarly(List? allAddresses) => + _i18.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i18.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future getAllTxsToWatch() => (super.noSuchMethod( + _i18.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -1136,26 +1149,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -1173,33 +1186,33 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateSentCachedTxData(Map? txData) => + _i18.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1209,36 +1222,36 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { returnValue: false, ) as bool); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future<_i10.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i18.Future<_i10.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), returnValue: - _i17.Future<_i10.ElectrumXNode>.value(_FakeElectrumXNode_11( + _i18.Future<_i10.ElectrumXNode>.value(_FakeElectrumXNode_11( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i17.Future<_i10.ElectrumXNode>); + ) as _i18.Future<_i10.ElectrumXNode>); @override - _i17.Future addDerivation({ + _i18.Future addDerivation({ required int? chain, required String? address, required String? pubKey, required String? wif, - required _i21.DerivePathType? derivePathType, + required _i24.DerivePathType? derivePathType, }) => (super.noSuchMethod( Invocation.method( @@ -1252,13 +1265,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { #derivePathType: derivePathType, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addDerivations({ + _i18.Future addDerivations({ required int? chain, - required _i21.DerivePathType? derivePathType, + required _i24.DerivePathType? derivePathType, required Map? derivationsToAdd, }) => (super.noSuchMethod( @@ -1271,50 +1284,50 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { #derivationsToAdd: derivationsToAdd, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future>> fastFetch( + _i18.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i17.Future>>.value( + returnValue: _i18.Future>>.value( >[]), - ) as _i17.Future>>); + ) as _i18.Future>>); @override - _i17.Future getTxCount({required String? address}) => + _i18.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future checkCurrentReceivingAddressesForTransactions() => + _i18.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future checkCurrentChangeAddressesForTransactions() => + _i18.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override int estimateTxFee({ required int? vSize, @@ -1338,7 +1351,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { String? _recipientAddress, bool? isSendAll, { int? additionalOutputs = 0, - List<_i22.UTXO>? utxos, + List<_i23.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -1354,19 +1367,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { }, )); @override - _i17.Future> fetchBuildTxData( - List<_i22.UTXO>? utxosToUse) => + _i18.Future> fetchBuildTxData( + List<_i23.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future> buildTransaction({ - required List<_i22.UTXO>? utxosToUse, + _i18.Future> buildTransaction({ + required List<_i23.UTXO>? utxosToUse, required Map? utxoSigningData, required List? recipients, required List? satoshiAmounts, @@ -1383,10 +1396,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1398,11 +1411,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1414,8 +1427,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override int roughFeeEstimate( int? inputCount, @@ -1434,25 +1447,25 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { returnValue: 0, ) as int); @override - _i17.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( + _i18.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override void initCache( String? walletId, - _i16.Coin? coin, + _i17.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1465,14 +1478,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i17.Future updateCachedId(String? id) => (super.noSuchMethod( + _i18.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1482,14 +1495,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { returnValue: 0, ) as int); @override - _i17.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i18.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1499,15 +1512,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { returnValue: false, ) as bool); @override - _i17.Future updateCachedIsFavorite(bool? isFavorite) => + _i18.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override _i12.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1523,15 +1536,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { ), ) as _i12.Balance); @override - _i17.Future updateCachedBalance(_i12.Balance? balance) => + _i18.Future updateCachedBalance(_i12.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override _i12.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1547,15 +1560,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { ), ) as _i12.Balance); @override - _i17.Future updateCachedBalanceSecondary(_i12.Balance? balance) => + _i18.Future updateCachedBalanceSecondary(_i12.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override void initWalletDB({_i13.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1565,12 +1578,55 @@ class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { ), returnValueForMissingStub: null, ); + @override + _i18.Future< + _i14.Tuple4<_i23.Transaction, List<_i23.Output>, List<_i23.Input>, + _i23.Address>> parseTransaction( + Map? txData, + dynamic electrumxClient, + List<_i23.Address>? myAddresses, + _i17.Coin? coin, + int? minConfirms, + String? walletId, + ) => + (super.noSuchMethod( + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + returnValue: _i18.Future< + _i14.Tuple4<_i23.Transaction, List<_i23.Output>, List<_i23.Input>, + _i23.Address>>.value(_FakeTuple4_12<_i23.Transaction, + List<_i23.Output>, List<_i23.Input>, _i23.Address>( + this, + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + )), + ) as _i18.Future< + _i14.Tuple4<_i23.Transaction, List<_i23.Output>, List<_i23.Input>, + _i23.Address>>); } /// A class which mocks [LocaleService]. /// /// See the documentation for Mockito's code generation for more information. -class MockLocaleService extends _i1.Mock implements _i23.LocaleService { +class MockLocaleService extends _i1.Mock implements _i25.LocaleService { MockLocaleService() { _i1.throwOnMissingStub(this); } @@ -1586,17 +1642,17 @@ class MockLocaleService extends _i1.Mock implements _i23.LocaleService { returnValue: false, ) as bool); @override - _i17.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( + _i18.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( Invocation.method( #loadLocale, [], {#notify: notify}, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1604,7 +1660,7 @@ class MockLocaleService extends _i1.Mock implements _i23.LocaleService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1632,7 +1688,7 @@ class MockLocaleService extends _i1.Mock implements _i23.LocaleService { /// A class which mocks [Prefs]. /// /// See the documentation for Mockito's code generation for more information. -class MockPrefs extends _i1.Mock implements _i18.Prefs { +class MockPrefs extends _i1.Mock implements _i19.Prefs { MockPrefs() { _i1.throwOnMissingStub(this); } @@ -1688,12 +1744,12 @@ class MockPrefs extends _i1.Mock implements _i18.Prefs { returnValueForMissingStub: null, ); @override - _i24.SyncingType get syncType => (super.noSuchMethod( + _i26.SyncingType get syncType => (super.noSuchMethod( Invocation.getter(#syncType), - returnValue: _i24.SyncingType.currentWalletOnly, - ) as _i24.SyncingType); + returnValue: _i26.SyncingType.currentWalletOnly, + ) as _i26.SyncingType); @override - set syncType(_i24.SyncingType? syncType) => super.noSuchMethod( + set syncType(_i26.SyncingType? syncType) => super.noSuchMethod( Invocation.setter( #syncType, syncType, @@ -1753,12 +1809,12 @@ class MockPrefs extends _i1.Mock implements _i18.Prefs { returnValueForMissingStub: null, ); @override - _i25.ExchangeRateType get exchangeRateType => (super.noSuchMethod( + _i27.ExchangeRateType get exchangeRateType => (super.noSuchMethod( Invocation.getter(#exchangeRateType), - returnValue: _i25.ExchangeRateType.estimated, - ) as _i25.ExchangeRateType); + returnValue: _i27.ExchangeRateType.estimated, + ) as _i27.ExchangeRateType); @override - set exchangeRateType(_i25.ExchangeRateType? exchangeRateType) => + set exchangeRateType(_i27.ExchangeRateType? exchangeRateType) => super.noSuchMethod( Invocation.setter( #exchangeRateType, @@ -1840,12 +1896,12 @@ class MockPrefs extends _i1.Mock implements _i18.Prefs { returnValueForMissingStub: null, ); @override - _i26.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( + _i28.BackupFrequencyType get backupFrequencyType => (super.noSuchMethod( Invocation.getter(#backupFrequencyType), - returnValue: _i26.BackupFrequencyType.everyTenMinutes, - ) as _i26.BackupFrequencyType); + returnValue: _i28.BackupFrequencyType.everyTenMinutes, + ) as _i28.BackupFrequencyType); @override - set backupFrequencyType(_i26.BackupFrequencyType? backupFrequencyType) => + set backupFrequencyType(_i28.BackupFrequencyType? backupFrequencyType) => super.noSuchMethod( Invocation.setter( #backupFrequencyType, @@ -1915,33 +1971,33 @@ class MockPrefs extends _i1.Mock implements _i18.Prefs { returnValue: false, ) as bool); @override - _i17.Future init() => (super.noSuchMethod( + _i18.Future init() => (super.noSuchMethod( Invocation.method( #init, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( + _i18.Future incrementCurrentNotificationIndex() => (super.noSuchMethod( Invocation.method( #incrementCurrentNotificationIndex, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future isExternalCallsSet() => (super.noSuchMethod( + _i18.Future isExternalCallsSet() => (super.noSuchMethod( Invocation.method( #isExternalCallsSet, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1949,7 +2005,7 @@ class MockPrefs extends _i1.Mock implements _i18.Prefs { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1992,23 +2048,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i14.CoinServiceAPI get wallet => (super.noSuchMethod( + _i15.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_12( + returnValue: _FakeCoinServiceAPI_13( this, Invocation.getter(#wallet), ), - ) as _i14.CoinServiceAPI); + ) as _i15.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -2041,23 +2097,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i17.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i9.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i18.Future<_i9.FeeObject>.value(_FakeFeeObject_6( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i9.FeeObject>); + ) as _i18.Future<_i9.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override _i12.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -2067,16 +2123,16 @@ class MockManager extends _i1.Mock implements _i6.Manager { ), ) as _i12.Balance); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i22.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i23.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i22.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i23.UTXO>[]), + ) as _i18.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2096,10 +2152,10 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -2111,19 +2167,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -2133,7 +2194,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -2149,27 +2210,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2179,33 +2240,33 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -2222,20 +2283,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future exitCurrentWallet() => (super.noSuchMethod( + _i18.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2247,11 +2308,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -2263,18 +2324,18 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -2282,7 +2343,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -2302,7 +2363,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 _i14.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i15.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -2313,10 +2374,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -2349,23 +2410,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i17.Future<_i9.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i9.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i9.FeeObject>.value(_FakeFeeObject_6( + returnValue: _i18.Future<_i9.FeeObject>.value(_FakeFeeObject_6( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i9.FeeObject>); + ) as _i18.Future<_i9.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override _i12.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -2375,16 +2436,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { ), ) as _i12.Balance); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i22.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i23.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i22.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i23.UTXO>[]), + ) as _i18.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2404,10 +2465,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: '', ) as String); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -2424,7 +2485,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: 0, ) as int); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -2440,36 +2501,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2479,15 +2540,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: false, ) as bool); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -2504,38 +2565,38 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future exit() => (super.noSuchMethod( + _i18.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2547,11 +2608,11 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -2563,24 +2624,24 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future updateSentCachedTxData(Map? txData) => + _i18.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); } 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 bb5c5c408..54ade45c2 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 @@ -363,6 +363,11 @@ class MockManager extends _i1.Mock implements _i11.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 f0c334e7e..84fc1bf4e 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 @@ -324,6 +324,11 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 f0c11b04a..7d23a2dd7 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 @@ -322,6 +322,11 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, diff --git a/test/screen_tests/lockscreen_view_screen_test.mocks.dart b/test/screen_tests/lockscreen_view_screen_test.mocks.dart index 6328b6881..92518048b 100644 --- a/test/screen_tests/lockscreen_view_screen_test.mocks.dart +++ b/test/screen_tests/lockscreen_view_screen_test.mocks.dart @@ -631,6 +631,11 @@ class MockManager extends _i1.Mock implements _i12.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 c0c6f6902..01f47579b 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 @@ -418,6 +418,11 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 aef163b0e..106485fdb 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 @@ -418,6 +418,11 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 7f31b64c4..419b72e3f 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 @@ -418,6 +418,11 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 56e72d944..50cd7afd8 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 @@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 a7467d9be..ba5f52688 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 @@ -416,6 +416,11 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 9267a9fba..7a1afa588 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 @@ -631,6 +631,11 @@ class MockManager extends _i1.Mock implements _i12.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 13aa6edb8..31fb8546c 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 @@ -472,6 +472,11 @@ class MockManager extends _i1.Mock implements _i12.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 b8c7f3cbd..742498415 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 @@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 68f2eeb10..b4c96f70c 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 @@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 8b60863ab..9fe30a1cb 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 @@ -408,6 +408,11 @@ class MockManager extends _i1.Mock implements _i11.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 09d59deb2..f0b37d032 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 @@ -408,6 +408,11 @@ class MockManager extends _i1.Mock implements _i11.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 a958461b8..3711513b4 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 @@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 284065eba..fc733ad66 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 @@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 24da7d388..b36f289d8 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 @@ -416,6 +416,11 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 0bf926563..dc382ee73 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 @@ -673,6 +673,11 @@ class MockManager extends _i1.Mock implements _i15.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 487f2f2bf..e469b8be4 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 @@ -416,6 +416,11 @@ class MockManager extends _i1.Mock implements _i9.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 31bda1f65..bd3520e44 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 @@ -195,6 +195,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 161b63e1d..cbfc6644f 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 @@ -194,6 +194,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 7172f3e29..a4936c793 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 @@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 ba206a8c6..3126e4580 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 @@ -235,6 +235,11 @@ class MockManager extends _i1.Mock implements _i8.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, 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 ae6a2d1f9..135802891 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 @@ -195,6 +195,11 @@ class MockManager extends _i1.Mock implements _i5.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, diff --git a/test/widget_tests/managed_favorite_test.mocks.dart b/test/widget_tests/managed_favorite_test.mocks.dart index a5ee69930..a51988ce0 100644 --- a/test/widget_tests/managed_favorite_test.mocks.dart +++ b/test/widget_tests/managed_favorite_test.mocks.dart @@ -3,8 +3,8 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i17; -import 'dart:ui' as _i19; +import 'dart:async' as _i18; +import 'dart:ui' as _i20; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; @@ -13,22 +13,24 @@ import 'package:stackwallet/db/main_db.dart' as _i12; 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 _i21; -import 'package:stackwallet/models/node_model.dart' as _i23; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i22; +import 'package:stackwallet/models/node_model.dart' as _i25; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i8; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i20; -import 'package:stackwallet/services/coins/coin_service.dart' as _i14; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i21; +import 'package:stackwallet/services/coins/coin_service.dart' as _i15; import 'package:stackwallet/services/coins/manager.dart' as _i6; -import 'package:stackwallet/services/locale_service.dart' as _i22; +import 'package:stackwallet/services/locale_service.dart' as _i24; 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 _i15; +import 'package:stackwallet/services/wallets.dart' as _i16; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i16; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i17; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i23; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' - as _i13; -import 'package:stackwallet/utilities/prefs.dart' as _i18; + as _i14; +import 'package:stackwallet/utilities/prefs.dart' as _i19; +import 'package:tuple/tuple.dart' as _i13; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -155,9 +157,9 @@ class _FakeElectrumXNode_10 extends _i1.SmartFake implements _i9.ElectrumXNode { ); } -class _FakeSecureStorageInterface_11 extends _i1.SmartFake - implements _i13.SecureStorageInterface { - _FakeSecureStorageInterface_11( +class _FakeTuple4_11 extends _i1.SmartFake + implements _i13.Tuple4 { + _FakeTuple4_11( Object parent, Invocation parentInvocation, ) : super( @@ -166,9 +168,20 @@ class _FakeSecureStorageInterface_11 extends _i1.SmartFake ); } -class _FakeCoinServiceAPI_12 extends _i1.SmartFake - implements _i14.CoinServiceAPI { - _FakeCoinServiceAPI_12( +class _FakeSecureStorageInterface_12 extends _i1.SmartFake + implements _i14.SecureStorageInterface { + _FakeSecureStorageInterface_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_13 extends _i1.SmartFake + implements _i15.CoinServiceAPI { + _FakeCoinServiceAPI_13( Object parent, Invocation parentInvocation, ) : super( @@ -180,7 +193,7 @@ class _FakeCoinServiceAPI_12 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 _i15.Wallets { +class MockWallets extends _i1.Mock implements _i16.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -247,7 +260,7 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i16.Coin? coin}) => + List getWalletIdsFor({required _i17.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -257,18 +270,18 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValue: [], ) as List); @override - Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> + Map<_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i16.Coin, + returnValue: <_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>{}, - ) as Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); + ) as Map<_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i16.Coin? coin) => + _i17.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -332,17 +345,17 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - _i17.Future load(_i18.Prefs? prefs) => (super.noSuchMethod( + _i18.Future load(_i19.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future loadAfterStackRestore( - _i18.Prefs? prefs, + _i18.Future loadAfterStackRestore( + _i19.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -353,11 +366,11 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { managers, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -365,7 +378,7 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -391,19 +404,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i17.Future> get walletNames => + _i18.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i17.Future>.value( + returnValue: _i18.Future>.value( {}), - ) as _i17.Future>); + ) as _i18.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future renameWallet({ + _i18.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -418,13 +431,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future addExistingStackWallet({ + _i18.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i16.Coin? coin, + required _i17.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -438,13 +451,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addNewWallet({ + _i18.Future addNewWallet({ required String? name, - required _i16.Coin? coin, + required _i17.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -457,46 +470,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i18.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override - _i17.Future saveFavoriteWalletIds(List? walletIds) => + _i18.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i18.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i18.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future moveFavorite({ + _i18.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -509,48 +522,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i18.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i18.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future isMnemonicVerified({required String? walletId}) => + _i18.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future setMnemonicVerified({required String? walletId}) => + _i18.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future deleteWallet( + _i18.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -562,20 +575,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future refreshWallets(bool? shouldNotifyListeners) => + _i18.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -583,7 +596,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -611,13 +624,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 _i20.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i17.Timer? _timer) => super.noSuchMethod( + set timer(_i18.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -694,59 +707,59 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future get currentChangeAddress => (super.noSuchMethod( + _i18.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override - _i17.Future get chainHeight => (super.noSuchMethod( + _i18.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -835,26 +848,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i12.MainDB); @override - _i17.Future exit() => (super.noSuchMethod( + _i18.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i20.DerivePathType addressType({required String? address}) => + _i23.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i20.DerivePathType.bip44, - ) as _i20.DerivePathType); + returnValue: _i23.DerivePathType.bip44, + ) as _i23.DerivePathType); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -871,47 +884,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future getTransactionCacheEarly(List? allAddresses) => + _i18.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i18.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future getAllTxsToWatch() => (super.noSuchMethod( + _i18.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -927,26 +940,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -964,33 +977,33 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateSentCachedTxData(Map? txData) => + _i18.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1000,35 +1013,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i18.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), - returnValue: _i17.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( + returnValue: _i18.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i17.Future<_i9.ElectrumXNode>); + ) as _i18.Future<_i9.ElectrumXNode>); @override - _i17.Future addDerivation({ + _i18.Future addDerivation({ required int? chain, required String? address, required String? pubKey, required String? wif, - required _i20.DerivePathType? derivePathType, + required _i23.DerivePathType? derivePathType, }) => (super.noSuchMethod( Invocation.method( @@ -1042,13 +1055,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #derivePathType: derivePathType, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addDerivations({ + _i18.Future addDerivations({ required int? chain, - required _i20.DerivePathType? derivePathType, + required _i23.DerivePathType? derivePathType, required Map? derivationsToAdd, }) => (super.noSuchMethod( @@ -1061,50 +1074,50 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #derivationsToAdd: derivationsToAdd, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future>> fastFetch( + _i18.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i17.Future>>.value( + returnValue: _i18.Future>>.value( >[]), - ) as _i17.Future>>); + ) as _i18.Future>>); @override - _i17.Future getTxCount({required String? address}) => + _i18.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future checkCurrentReceivingAddressesForTransactions() => + _i18.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future checkCurrentChangeAddressesForTransactions() => + _i18.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override int estimateTxFee({ required int? vSize, @@ -1128,7 +1141,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { String? _recipientAddress, bool? isSendAll, { int? additionalOutputs = 0, - List<_i21.UTXO>? utxos, + List<_i22.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -1144,19 +1157,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, )); @override - _i17.Future> fetchBuildTxData( - List<_i21.UTXO>? utxosToUse) => + _i18.Future> fetchBuildTxData( + List<_i22.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future> buildTransaction({ - required List<_i21.UTXO>? utxosToUse, + _i18.Future> buildTransaction({ + required List<_i22.UTXO>? utxosToUse, required Map? utxoSigningData, required List? recipients, required List? satoshiAmounts, @@ -1173,10 +1186,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1188,11 +1201,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1204,8 +1217,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override int roughFeeEstimate( int? inputCount, @@ -1224,25 +1237,25 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: 0, ) as int); @override - _i17.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( + _i18.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override void initCache( String? walletId, - _i16.Coin? coin, + _i17.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1255,14 +1268,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i17.Future updateCachedId(String? id) => (super.noSuchMethod( + _i18.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1272,14 +1285,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: 0, ) as int); @override - _i17.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i18.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1289,15 +1302,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i17.Future updateCachedIsFavorite(bool? isFavorite) => + _i18.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override _i11.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1313,15 +1326,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i11.Balance); @override - _i17.Future updateCachedBalance(_i11.Balance? balance) => + _i18.Future updateCachedBalance(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override _i11.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1337,15 +1350,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i11.Balance); @override - _i17.Future updateCachedBalanceSecondary(_i11.Balance? balance) => + _i18.Future updateCachedBalanceSecondary(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override void initWalletDB({_i12.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1355,12 +1368,55 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), returnValueForMissingStub: null, ); + @override + _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>> parseTransaction( + Map? txData, + dynamic electrumxClient, + List<_i22.Address>? myAddresses, + _i17.Coin? coin, + int? minConfirms, + String? walletId, + ) => + (super.noSuchMethod( + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + returnValue: _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>>.value(_FakeTuple4_11<_i22.Transaction, + List<_i22.Output>, List<_i22.Input>, _i22.Address>( + this, + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + )), + ) as _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>>); } /// A class which mocks [LocaleService]. /// /// See the documentation for Mockito's code generation for more information. -class MockLocaleService extends _i1.Mock implements _i22.LocaleService { +class MockLocaleService extends _i1.Mock implements _i24.LocaleService { MockLocaleService() { _i1.throwOnMissingStub(this); } @@ -1376,17 +1432,17 @@ class MockLocaleService extends _i1.Mock implements _i22.LocaleService { returnValue: false, ) as bool); @override - _i17.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( + _i18.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( Invocation.method( #loadLocale, [], {#notify: notify}, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1394,7 +1450,7 @@ class MockLocaleService extends _i1.Mock implements _i22.LocaleService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1424,41 +1480,41 @@ class MockLocaleService extends _i1.Mock implements _i22.LocaleService { /// See the documentation for Mockito's code generation for more information. class MockNodeService extends _i1.Mock implements _i3.NodeService { @override - _i13.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( + _i14.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( Invocation.getter(#secureStorageInterface), - returnValue: _FakeSecureStorageInterface_11( + returnValue: _FakeSecureStorageInterface_12( this, Invocation.getter(#secureStorageInterface), ), - ) as _i13.SecureStorageInterface); + ) as _i14.SecureStorageInterface); @override - List<_i23.NodeModel> get primaryNodes => (super.noSuchMethod( + List<_i25.NodeModel> get primaryNodes => (super.noSuchMethod( Invocation.getter(#primaryNodes), - returnValue: <_i23.NodeModel>[], - ) as List<_i23.NodeModel>); + returnValue: <_i25.NodeModel>[], + ) as List<_i25.NodeModel>); @override - List<_i23.NodeModel> get nodes => (super.noSuchMethod( + List<_i25.NodeModel> get nodes => (super.noSuchMethod( Invocation.getter(#nodes), - returnValue: <_i23.NodeModel>[], - ) as List<_i23.NodeModel>); + returnValue: <_i25.NodeModel>[], + ) as List<_i25.NodeModel>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future updateDefaults() => (super.noSuchMethod( + _i18.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future setPrimaryNodeFor({ - required _i16.Coin? coin, - required _i23.NodeModel? node, + _i18.Future setPrimaryNodeFor({ + required _i17.Coin? coin, + required _i25.NodeModel? node, bool? shouldNotifyListeners = false, }) => (super.noSuchMethod( @@ -1471,44 +1527,44 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i23.NodeModel? getPrimaryNodeFor({required _i16.Coin? coin}) => + _i25.NodeModel? getPrimaryNodeFor({required _i17.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getPrimaryNodeFor, [], {#coin: coin}, - )) as _i23.NodeModel?); + )) as _i25.NodeModel?); @override - List<_i23.NodeModel> getNodesFor(_i16.Coin? coin) => (super.noSuchMethod( + List<_i25.NodeModel> getNodesFor(_i17.Coin? coin) => (super.noSuchMethod( Invocation.method( #getNodesFor, [coin], ), - returnValue: <_i23.NodeModel>[], - ) as List<_i23.NodeModel>); + returnValue: <_i25.NodeModel>[], + ) as List<_i25.NodeModel>); @override - _i23.NodeModel? getNodeById({required String? id}) => + _i25.NodeModel? getNodeById({required String? id}) => (super.noSuchMethod(Invocation.method( #getNodeById, [], {#id: id}, - )) as _i23.NodeModel?); + )) as _i25.NodeModel?); @override - List<_i23.NodeModel> failoverNodesFor({required _i16.Coin? coin}) => + List<_i25.NodeModel> failoverNodesFor({required _i17.Coin? coin}) => (super.noSuchMethod( Invocation.method( #failoverNodesFor, [], {#coin: coin}, ), - returnValue: <_i23.NodeModel>[], - ) as List<_i23.NodeModel>); + returnValue: <_i25.NodeModel>[], + ) as List<_i25.NodeModel>); @override - _i17.Future add( - _i23.NodeModel? node, + _i18.Future add( + _i25.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => @@ -1521,11 +1577,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future delete( + _i18.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -1537,11 +1593,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future setEnabledState( + _i18.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -1555,12 +1611,12 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future edit( - _i23.NodeModel? editedNode, + _i18.Future edit( + _i25.NodeModel? editedNode, String? password, bool? shouldNotifyListeners, ) => @@ -1573,20 +1629,20 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateCommunityNodes() => (super.noSuchMethod( + _i18.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1594,7 +1650,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1637,23 +1693,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i14.CoinServiceAPI get wallet => (super.noSuchMethod( + _i15.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_12( + returnValue: _FakeCoinServiceAPI_13( this, Invocation.getter(#wallet), ), - ) as _i14.CoinServiceAPI); + ) as _i15.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -1686,23 +1742,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -1712,16 +1768,16 @@ class MockManager extends _i1.Mock implements _i6.Manager { ), ) as _i11.Balance); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -1741,10 +1797,10 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -1756,19 +1812,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -1778,7 +1839,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -1794,27 +1855,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1824,33 +1885,33 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -1867,20 +1928,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future exitCurrentWallet() => (super.noSuchMethod( + _i18.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1892,11 +1953,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1908,18 +1969,18 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1927,7 +1988,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1947,7 +2008,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 _i14.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i15.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -1958,10 +2019,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -1994,23 +2055,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -2020,16 +2081,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { ), ) as _i11.Balance); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -2049,10 +2110,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: '', ) as String); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -2069,7 +2130,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: 0, ) as int); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -2085,36 +2146,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2124,15 +2185,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: false, ) as bool); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -2149,38 +2210,38 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future exit() => (super.noSuchMethod( + _i18.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2192,11 +2253,11 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -2208,24 +2269,24 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future updateSentCachedTxData(Map? txData) => + _i18.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); } 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 d31019d37..aeefa1a27 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,8 +3,8 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i16; -import 'dart:ui' as _i18; +import 'dart:async' as _i17; +import 'dart:ui' as _i19; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; @@ -13,18 +13,20 @@ import 'package:stackwallet/db/main_db.dart' as _i12; 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 _i20; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i21; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i8; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i19; -import 'package:stackwallet/services/coins/coin_service.dart' as _i13; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i20; +import 'package:stackwallet/services/coins/coin_service.dart' as _i14; 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 _i7; -import 'package:stackwallet/services/wallets.dart' as _i14; +import 'package:stackwallet/services/wallets.dart' as _i15; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i15; -import 'package:stackwallet/utilities/prefs.dart' as _i17; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i16; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i22; +import 'package:stackwallet/utilities/prefs.dart' as _i18; +import 'package:tuple/tuple.dart' as _i13; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -151,9 +153,20 @@ class _FakeElectrumXNode_10 extends _i1.SmartFake implements _i9.ElectrumXNode { ); } -class _FakeCoinServiceAPI_11 extends _i1.SmartFake - implements _i13.CoinServiceAPI { - _FakeCoinServiceAPI_11( +class _FakeTuple4_11 extends _i1.SmartFake + implements _i13.Tuple4 { + _FakeTuple4_11( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_12 extends _i1.SmartFake + implements _i14.CoinServiceAPI { + _FakeCoinServiceAPI_12( Object parent, Invocation parentInvocation, ) : super( @@ -165,7 +178,7 @@ class _FakeCoinServiceAPI_11 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 _i14.Wallets { +class MockWallets extends _i1.Mock implements _i15.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -232,7 +245,7 @@ class MockWallets extends _i1.Mock implements _i14.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i15.Coin? coin}) => + List getWalletIdsFor({required _i16.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -242,18 +255,18 @@ class MockWallets extends _i1.Mock implements _i14.Wallets { returnValue: [], ) as List); @override - Map<_i15.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> + Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i15.Coin, + returnValue: <_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>{}, - ) as Map<_i15.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); + ) as Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i15.Coin? coin) => + _i16.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -317,17 +330,17 @@ class MockWallets extends _i1.Mock implements _i14.Wallets { returnValueForMissingStub: null, ); @override - _i16.Future load(_i17.Prefs? prefs) => (super.noSuchMethod( + _i17.Future load(_i18.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future loadAfterStackRestore( - _i17.Prefs? prefs, + _i17.Future loadAfterStackRestore( + _i18.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -338,11 +351,11 @@ class MockWallets extends _i1.Mock implements _i14.Wallets { managers, ], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - void addListener(_i18.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -350,7 +363,7 @@ class MockWallets extends _i1.Mock implements _i14.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i18.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -376,19 +389,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i16.Future> get walletNames => + _i17.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i16.Future>.value( + returnValue: _i17.Future>.value( {}), - ) as _i16.Future>); + ) as _i17.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i16.Future renameWallet({ + _i17.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -403,13 +416,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override - _i16.Future addExistingStackWallet({ + _i17.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i15.Coin? coin, + required _i16.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -423,13 +436,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future addNewWallet({ + _i17.Future addNewWallet({ required String? name, - required _i15.Coin? coin, + required _i16.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -442,46 +455,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i17.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i16.Future>.value([]), - ) as _i16.Future>); + returnValue: _i17.Future>.value([]), + ) as _i17.Future>); @override - _i16.Future saveFavoriteWalletIds(List? walletIds) => + _i17.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i17.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i17.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future moveFavorite({ + _i17.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -494,48 +507,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i17.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override - _i16.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i17.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future isMnemonicVerified({required String? walletId}) => + _i17.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override - _i16.Future setMnemonicVerified({required String? walletId}) => + _i17.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future deleteWallet( + _i17.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -547,20 +560,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override - _i16.Future refreshWallets(bool? shouldNotifyListeners) => + _i17.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - void addListener(_i18.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -568,7 +581,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i18.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -596,13 +609,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 _i19.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i16.Timer? _timer) => super.noSuchMethod( + set timer(_i17.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -679,59 +692,59 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { returnValue: false, ) as bool); @override - _i15.Coin get coin => (super.noSuchMethod( + _i16.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i15.Coin.bitcoin, - ) as _i15.Coin); + returnValue: _i16.Coin.bitcoin, + ) as _i16.Coin); @override - _i16.Future> get utxos => (super.noSuchMethod( + _i17.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i16.Future>.value(<_i20.UTXO>[]), - ) as _i16.Future>); + returnValue: _i17.Future>.value(<_i21.UTXO>[]), + ) as _i17.Future>); @override - _i16.Future> get transactions => (super.noSuchMethod( + _i17.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i16.Future>.value(<_i20.Transaction>[]), - ) as _i16.Future>); + _i17.Future>.value(<_i21.Transaction>[]), + ) as _i17.Future>); @override - _i16.Future get currentReceivingAddress => (super.noSuchMethod( + _i17.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i16.Future.value(''), - ) as _i16.Future); + returnValue: _i17.Future.value(''), + ) as _i17.Future); @override - _i16.Future get currentChangeAddress => (super.noSuchMethod( + _i17.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i16.Future.value(''), - ) as _i16.Future); + returnValue: _i17.Future.value(''), + ) as _i17.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i16.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i16.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i16.Future<_i8.FeeObject>); + ) as _i17.Future<_i8.FeeObject>); @override - _i16.Future get maxFee => (super.noSuchMethod( + _i17.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override - _i16.Future> get mnemonic => (super.noSuchMethod( + _i17.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i16.Future>.value([]), - ) as _i16.Future>); + returnValue: _i17.Future>.value([]), + ) as _i17.Future>); @override - _i16.Future get chainHeight => (super.noSuchMethod( + _i17.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -820,26 +833,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { ), ) as _i12.MainDB); @override - _i16.Future exit() => (super.noSuchMethod( + _i17.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i19.DerivePathType addressType({required String? address}) => + _i22.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i19.DerivePathType.bip44, - ) as _i19.DerivePathType); + returnValue: _i22.DerivePathType.bip44, + ) as _i22.DerivePathType); @override - _i16.Future recoverFromMnemonic({ + _i17.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -856,47 +869,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { #height: height, }, ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future getTransactionCacheEarly(List? allAddresses) => + _i17.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i17.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override - _i16.Future getAllTxsToWatch() => (super.noSuchMethod( + _i17.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future refresh() => (super.noSuchMethod( + _i17.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future> prepareSend({ + _i17.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -912,26 +925,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { }, ), returnValue: - _i16.Future>.value({}), - ) as _i16.Future>); + _i17.Future>.value({}), + ) as _i17.Future>); @override - _i16.Future confirmSend({required Map? txData}) => + _i17.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i16.Future.value(''), - ) as _i16.Future); + returnValue: _i17.Future.value(''), + ) as _i17.Future); @override - _i16.Future testNetworkConnection() => (super.noSuchMethod( + _i17.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -949,33 +962,33 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i16.Future initializeNew() => (super.noSuchMethod( + _i17.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future initializeExisting() => (super.noSuchMethod( + _i17.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future updateSentCachedTxData(Map? txData) => + _i17.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -985,35 +998,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { returnValue: false, ) as bool); @override - _i16.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i17.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), - returnValue: _i16.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( + returnValue: _i17.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i16.Future<_i9.ElectrumXNode>); + ) as _i17.Future<_i9.ElectrumXNode>); @override - _i16.Future addDerivation({ + _i17.Future addDerivation({ required int? chain, required String? address, required String? pubKey, required String? wif, - required _i19.DerivePathType? derivePathType, + required _i22.DerivePathType? derivePathType, }) => (super.noSuchMethod( Invocation.method( @@ -1027,13 +1040,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { #derivePathType: derivePathType, }, ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future addDerivations({ + _i17.Future addDerivations({ required int? chain, - required _i19.DerivePathType? derivePathType, + required _i22.DerivePathType? derivePathType, required Map? derivationsToAdd, }) => (super.noSuchMethod( @@ -1046,50 +1059,50 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { #derivationsToAdd: derivationsToAdd, }, ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future>> fastFetch( + _i17.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i16.Future>>.value( + returnValue: _i17.Future>>.value( >[]), - ) as _i16.Future>>); + ) as _i17.Future>>); @override - _i16.Future getTxCount({required String? address}) => + _i17.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override - _i16.Future checkCurrentReceivingAddressesForTransactions() => + _i17.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future checkCurrentChangeAddressesForTransactions() => + _i17.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override int estimateTxFee({ required int? vSize, @@ -1113,7 +1126,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { String? _recipientAddress, bool? isSendAll, { int? additionalOutputs = 0, - List<_i20.UTXO>? utxos, + List<_i21.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -1129,19 +1142,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { }, )); @override - _i16.Future> fetchBuildTxData( - List<_i20.UTXO>? utxosToUse) => + _i17.Future> fetchBuildTxData( + List<_i21.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i16.Future>.value({}), - ) as _i16.Future>); + _i17.Future>.value({}), + ) as _i17.Future>); @override - _i16.Future> buildTransaction({ - required List<_i20.UTXO>? utxosToUse, + _i17.Future> buildTransaction({ + required List<_i21.UTXO>? utxosToUse, required Map? utxoSigningData, required List? recipients, required List? satoshiAmounts, @@ -1158,10 +1171,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { }, ), returnValue: - _i16.Future>.value({}), - ) as _i16.Future>); + _i17.Future>.value({}), + ) as _i17.Future>); @override - _i16.Future fullRescan( + _i17.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1173,11 +1186,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future estimateFeeFor( + _i17.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1189,8 +1202,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { feeRate, ], ), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override int roughFeeEstimate( int? inputCount, @@ -1209,25 +1222,25 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { returnValue: 0, ) as int); @override - _i16.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( + _i17.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override - _i16.Future generateNewAddress() => (super.noSuchMethod( + _i17.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override void initCache( String? walletId, - _i15.Coin? coin, + _i16.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1240,14 +1253,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i16.Future updateCachedId(String? id) => (super.noSuchMethod( + _i17.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1257,14 +1270,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { returnValue: 0, ) as int); @override - _i16.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i17.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1274,15 +1287,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { returnValue: false, ) as bool); @override - _i16.Future updateCachedIsFavorite(bool? isFavorite) => + _i17.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override _i11.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1298,15 +1311,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { ), ) as _i11.Balance); @override - _i16.Future updateCachedBalance(_i11.Balance? balance) => + _i17.Future updateCachedBalance(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override _i11.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1322,15 +1335,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { ), ) as _i11.Balance); @override - _i16.Future updateCachedBalanceSecondary(_i11.Balance? balance) => + _i17.Future updateCachedBalanceSecondary(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override void initWalletDB({_i12.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1340,6 +1353,49 @@ class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { ), returnValueForMissingStub: null, ); + @override + _i17.Future< + _i13.Tuple4<_i21.Transaction, List<_i21.Output>, List<_i21.Input>, + _i21.Address>> parseTransaction( + Map? txData, + dynamic electrumxClient, + List<_i21.Address>? myAddresses, + _i16.Coin? coin, + int? minConfirms, + String? walletId, + ) => + (super.noSuchMethod( + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + returnValue: _i17.Future< + _i13.Tuple4<_i21.Transaction, List<_i21.Output>, List<_i21.Input>, + _i21.Address>>.value(_FakeTuple4_11<_i21.Transaction, + List<_i21.Output>, List<_i21.Input>, _i21.Address>( + this, + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + )), + ) as _i17.Future< + _i13.Tuple4<_i21.Transaction, List<_i21.Output>, List<_i21.Input>, + _i21.Address>>); } /// A class which mocks [Manager]. @@ -1360,23 +1416,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i13.CoinServiceAPI get wallet => (super.noSuchMethod( + _i14.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_11( + returnValue: _FakeCoinServiceAPI_12( this, Invocation.getter(#wallet), ), - ) as _i13.CoinServiceAPI); + ) as _i14.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i15.Coin get coin => (super.noSuchMethod( + _i16.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i15.Coin.bitcoin, - ) as _i15.Coin); + returnValue: _i16.Coin.bitcoin, + ) as _i16.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -1409,23 +1465,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i16.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i16.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i16.Future<_i8.FeeObject>); + ) as _i17.Future<_i8.FeeObject>); @override - _i16.Future get maxFee => (super.noSuchMethod( + _i17.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override - _i16.Future get currentReceivingAddress => (super.noSuchMethod( + _i17.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i16.Future.value(''), - ) as _i16.Future); + returnValue: _i17.Future.value(''), + ) as _i17.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -1435,16 +1491,16 @@ class MockManager extends _i1.Mock implements _i6.Manager { ), ) as _i11.Balance); @override - _i16.Future> get transactions => (super.noSuchMethod( + _i17.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i16.Future>.value(<_i20.Transaction>[]), - ) as _i16.Future>); + _i17.Future>.value(<_i21.Transaction>[]), + ) as _i17.Future>); @override - _i16.Future> get utxos => (super.noSuchMethod( + _i17.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i16.Future>.value(<_i20.UTXO>[]), - ) as _i16.Future>); + returnValue: _i17.Future>.value(<_i21.UTXO>[]), + ) as _i17.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -1464,10 +1520,10 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i16.Future> get mnemonic => (super.noSuchMethod( + _i17.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i16.Future>.value([]), - ) as _i16.Future>); + returnValue: _i17.Future>.value([]), + ) as _i17.Future>); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -1479,19 +1535,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i16.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -1501,7 +1562,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i16.Future> prepareSend({ + _i17.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -1517,27 +1578,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i16.Future>.value({}), - ) as _i16.Future>); + _i17.Future>.value({}), + ) as _i17.Future>); @override - _i16.Future confirmSend({required Map? txData}) => + _i17.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i16.Future.value(''), - ) as _i16.Future); + returnValue: _i17.Future.value(''), + ) as _i17.Future); @override - _i16.Future refresh() => (super.noSuchMethod( + _i17.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1547,33 +1608,33 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i16.Future testNetworkConnection() => (super.noSuchMethod( + _i17.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override - _i16.Future initializeNew() => (super.noSuchMethod( + _i17.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future initializeExisting() => (super.noSuchMethod( + _i17.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future recoverFromMnemonic({ + _i17.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -1590,20 +1651,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future exitCurrentWallet() => (super.noSuchMethod( + _i17.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future fullRescan( + _i17.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1615,11 +1676,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future estimateFeeFor( + _i17.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1631,18 +1692,18 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override - _i16.Future generateNewAddress() => (super.noSuchMethod( + _i17.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override - void addListener(_i18.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1650,7 +1711,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i18.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1670,7 +1731,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 _i13.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -1681,10 +1742,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i15.Coin get coin => (super.noSuchMethod( + _i16.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i15.Coin.bitcoin, - ) as _i15.Coin); + returnValue: _i16.Coin.bitcoin, + ) as _i16.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -1717,23 +1778,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i16.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i16.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i16.Future<_i8.FeeObject>); + ) as _i17.Future<_i8.FeeObject>); @override - _i16.Future get maxFee => (super.noSuchMethod( + _i17.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override - _i16.Future get currentReceivingAddress => (super.noSuchMethod( + _i17.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i16.Future.value(''), - ) as _i16.Future); + returnValue: _i17.Future.value(''), + ) as _i17.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -1743,16 +1804,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { ), ) as _i11.Balance); @override - _i16.Future> get transactions => (super.noSuchMethod( + _i17.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i16.Future>.value(<_i20.Transaction>[]), - ) as _i16.Future>); + _i17.Future>.value(<_i21.Transaction>[]), + ) as _i17.Future>); @override - _i16.Future> get utxos => (super.noSuchMethod( + _i17.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i16.Future>.value(<_i20.UTXO>[]), - ) as _i16.Future>); + returnValue: _i17.Future>.value(<_i21.UTXO>[]), + ) as _i17.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -1772,10 +1833,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { returnValue: '', ) as String); @override - _i16.Future> get mnemonic => (super.noSuchMethod( + _i17.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i16.Future>.value([]), - ) as _i16.Future>); + returnValue: _i17.Future>.value([]), + ) as _i17.Future>); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -1792,7 +1853,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { returnValue: 0, ) as int); @override - _i16.Future> prepareSend({ + _i17.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -1808,36 +1869,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { }, ), returnValue: - _i16.Future>.value({}), - ) as _i16.Future>); + _i17.Future>.value({}), + ) as _i17.Future>); @override - _i16.Future confirmSend({required Map? txData}) => + _i17.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i16.Future.value(''), - ) as _i16.Future); + returnValue: _i17.Future.value(''), + ) as _i17.Future); @override - _i16.Future refresh() => (super.noSuchMethod( + _i17.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1847,15 +1908,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { returnValue: false, ) as bool); @override - _i16.Future testNetworkConnection() => (super.noSuchMethod( + _i17.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override - _i16.Future recoverFromMnemonic({ + _i17.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -1872,38 +1933,38 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { #height: height, }, ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future initializeNew() => (super.noSuchMethod( + _i17.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future initializeExisting() => (super.noSuchMethod( + _i17.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future exit() => (super.noSuchMethod( + _i17.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future fullRescan( + _i17.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1915,11 +1976,11 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); @override - _i16.Future estimateFeeFor( + _i17.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1931,24 +1992,24 @@ class MockCoinServiceAPI extends _i1.Mock implements _i13.CoinServiceAPI { feeRate, ], ), - returnValue: _i16.Future.value(0), - ) as _i16.Future); + returnValue: _i17.Future.value(0), + ) as _i17.Future); @override - _i16.Future generateNewAddress() => (super.noSuchMethod( + _i17.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i16.Future.value(false), - ) as _i16.Future); + returnValue: _i17.Future.value(false), + ) as _i17.Future); @override - _i16.Future updateSentCachedTxData(Map? txData) => + _i17.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i16.Future.value(), - returnValueForMissingStub: _i16.Future.value(), - ) as _i16.Future); + returnValue: _i17.Future.value(), + returnValueForMissingStub: _i17.Future.value(), + ) as _i17.Future); } diff --git a/test/widget_tests/transaction_card_test.mocks.dart b/test/widget_tests/transaction_card_test.mocks.dart index c3b2cce4b..1ef218b2d 100644 --- a/test/widget_tests/transaction_card_test.mocks.dart +++ b/test/widget_tests/transaction_card_test.mocks.dart @@ -538,6 +538,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, diff --git a/test/widget_tests/wallet_card_test.mocks.dart b/test/widget_tests/wallet_card_test.mocks.dart index 5a5d048b3..2bffe7a06 100644 --- a/test/widget_tests/wallet_card_test.mocks.dart +++ b/test/widget_tests/wallet_card_test.mocks.dart @@ -3,8 +3,8 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i15; -import 'dart:ui' as _i17; +import 'dart:async' as _i16; +import 'dart:ui' as _i18; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; @@ -13,18 +13,20 @@ import 'package:stackwallet/db/main_db.dart' as _i12; 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 _i19; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i20; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i8; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i18; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i19; import 'package:stackwallet/services/coins/manager.dart' as _i6; -import 'package:stackwallet/services/locale_service.dart' as _i20; +import 'package:stackwallet/services/locale_service.dart' as _i22; 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 _i13; +import 'package:stackwallet/services/wallets.dart' as _i14; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i14; -import 'package:stackwallet/utilities/prefs.dart' as _i16; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i15; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i21; +import 'package:stackwallet/utilities/prefs.dart' as _i17; +import 'package:tuple/tuple.dart' as _i13; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -151,10 +153,21 @@ class _FakeElectrumXNode_10 extends _i1.SmartFake implements _i9.ElectrumXNode { ); } +class _FakeTuple4_11 extends _i1.SmartFake + implements _i13.Tuple4 { + _FakeTuple4_11( + 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 _i13.Wallets { +class MockWallets extends _i1.Mock implements _i14.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -221,7 +234,7 @@ class MockWallets extends _i1.Mock implements _i13.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i14.Coin? coin}) => + List getWalletIdsFor({required _i15.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -231,18 +244,18 @@ class MockWallets extends _i1.Mock implements _i13.Wallets { returnValue: [], ) as List); @override - Map<_i14.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> + Map<_i15.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i14.Coin, + returnValue: <_i15.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>{}, - ) as Map<_i14.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); + ) as Map<_i15.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i14.Coin? coin) => + _i15.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -306,17 +319,17 @@ class MockWallets extends _i1.Mock implements _i13.Wallets { returnValueForMissingStub: null, ); @override - _i15.Future load(_i16.Prefs? prefs) => (super.noSuchMethod( + _i16.Future load(_i17.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future loadAfterStackRestore( - _i16.Prefs? prefs, + _i16.Future loadAfterStackRestore( + _i17.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -327,11 +340,11 @@ class MockWallets extends _i1.Mock implements _i13.Wallets { managers, ], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - void addListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i18.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -339,7 +352,7 @@ class MockWallets extends _i1.Mock implements _i13.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i18.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -359,13 +372,13 @@ class MockWallets extends _i1.Mock implements _i13.Wallets { /// A class which mocks [BitcoinWallet]. /// /// See the documentation for Mockito's code generation for more information. -class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i15.Timer? _timer) => super.noSuchMethod( + set timer(_i16.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -442,59 +455,59 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { returnValue: false, ) as bool); @override - _i14.Coin get coin => (super.noSuchMethod( + _i15.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i14.Coin.bitcoin, - ) as _i14.Coin); + returnValue: _i15.Coin.bitcoin, + ) as _i15.Coin); @override - _i15.Future> get utxos => (super.noSuchMethod( + _i16.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i15.Future>.value(<_i19.UTXO>[]), - ) as _i15.Future>); + returnValue: _i16.Future>.value(<_i20.UTXO>[]), + ) as _i16.Future>); @override - _i15.Future> get transactions => (super.noSuchMethod( + _i16.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i15.Future>.value(<_i19.Transaction>[]), - ) as _i15.Future>); + _i16.Future>.value(<_i20.Transaction>[]), + ) as _i16.Future>); @override - _i15.Future get currentReceivingAddress => (super.noSuchMethod( + _i16.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i15.Future.value(''), - ) as _i15.Future); + returnValue: _i16.Future.value(''), + ) as _i16.Future); @override - _i15.Future get currentChangeAddress => (super.noSuchMethod( + _i16.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i15.Future.value(''), - ) as _i15.Future); + returnValue: _i16.Future.value(''), + ) as _i16.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i15.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i16.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i15.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i16.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i15.Future<_i8.FeeObject>); + ) as _i16.Future<_i8.FeeObject>); @override - _i15.Future get maxFee => (super.noSuchMethod( + _i16.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i15.Future.value(0), - ) as _i15.Future); + returnValue: _i16.Future.value(0), + ) as _i16.Future); @override - _i15.Future> get mnemonic => (super.noSuchMethod( + _i16.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i15.Future>.value([]), - ) as _i15.Future>); + returnValue: _i16.Future>.value([]), + ) as _i16.Future>); @override - _i15.Future get chainHeight => (super.noSuchMethod( + _i16.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i15.Future.value(0), - ) as _i15.Future); + returnValue: _i16.Future.value(0), + ) as _i16.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -583,26 +596,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { ), ) as _i12.MainDB); @override - _i15.Future exit() => (super.noSuchMethod( + _i16.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i18.DerivePathType addressType({required String? address}) => + _i21.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i18.DerivePathType.bip44, - ) as _i18.DerivePathType); + returnValue: _i21.DerivePathType.bip44, + ) as _i21.DerivePathType); @override - _i15.Future recoverFromMnemonic({ + _i16.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -619,47 +632,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { #height: height, }, ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future getTransactionCacheEarly(List? allAddresses) => + _i16.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i16.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i15.Future.value(false), - ) as _i15.Future); + returnValue: _i16.Future.value(false), + ) as _i16.Future); @override - _i15.Future getAllTxsToWatch() => (super.noSuchMethod( + _i16.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future refresh() => (super.noSuchMethod( + _i16.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future> prepareSend({ + _i16.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -675,26 +688,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { }, ), returnValue: - _i15.Future>.value({}), - ) as _i15.Future>); + _i16.Future>.value({}), + ) as _i16.Future>); @override - _i15.Future confirmSend({required Map? txData}) => + _i16.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i15.Future.value(''), - ) as _i15.Future); + returnValue: _i16.Future.value(''), + ) as _i16.Future); @override - _i15.Future testNetworkConnection() => (super.noSuchMethod( + _i16.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i15.Future.value(false), - ) as _i15.Future); + returnValue: _i16.Future.value(false), + ) as _i16.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -712,33 +725,33 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i15.Future initializeNew() => (super.noSuchMethod( + _i16.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future initializeExisting() => (super.noSuchMethod( + _i16.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future updateSentCachedTxData(Map? txData) => + _i16.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -748,35 +761,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { returnValue: false, ) as bool); @override - _i15.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i16.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i16.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), - returnValue: _i15.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( + returnValue: _i16.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i15.Future<_i9.ElectrumXNode>); + ) as _i16.Future<_i9.ElectrumXNode>); @override - _i15.Future addDerivation({ + _i16.Future addDerivation({ required int? chain, required String? address, required String? pubKey, required String? wif, - required _i18.DerivePathType? derivePathType, + required _i21.DerivePathType? derivePathType, }) => (super.noSuchMethod( Invocation.method( @@ -790,13 +803,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { #derivePathType: derivePathType, }, ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future addDerivations({ + _i16.Future addDerivations({ required int? chain, - required _i18.DerivePathType? derivePathType, + required _i21.DerivePathType? derivePathType, required Map? derivationsToAdd, }) => (super.noSuchMethod( @@ -809,50 +822,50 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { #derivationsToAdd: derivationsToAdd, }, ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future>> fastFetch( + _i16.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i15.Future>>.value( + returnValue: _i16.Future>>.value( >[]), - ) as _i15.Future>>); + ) as _i16.Future>>); @override - _i15.Future getTxCount({required String? address}) => + _i16.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i15.Future.value(0), - ) as _i15.Future); + returnValue: _i16.Future.value(0), + ) as _i16.Future); @override - _i15.Future checkCurrentReceivingAddressesForTransactions() => + _i16.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future checkCurrentChangeAddressesForTransactions() => + _i16.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override int estimateTxFee({ required int? vSize, @@ -876,7 +889,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { String? _recipientAddress, bool? isSendAll, { int? additionalOutputs = 0, - List<_i19.UTXO>? utxos, + List<_i20.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -892,19 +905,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { }, )); @override - _i15.Future> fetchBuildTxData( - List<_i19.UTXO>? utxosToUse) => + _i16.Future> fetchBuildTxData( + List<_i20.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i15.Future>.value({}), - ) as _i15.Future>); + _i16.Future>.value({}), + ) as _i16.Future>); @override - _i15.Future> buildTransaction({ - required List<_i19.UTXO>? utxosToUse, + _i16.Future> buildTransaction({ + required List<_i20.UTXO>? utxosToUse, required Map? utxoSigningData, required List? recipients, required List? satoshiAmounts, @@ -921,10 +934,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { }, ), returnValue: - _i15.Future>.value({}), - ) as _i15.Future>); + _i16.Future>.value({}), + ) as _i16.Future>); @override - _i15.Future fullRescan( + _i16.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -936,11 +949,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - _i15.Future estimateFeeFor( + _i16.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -952,8 +965,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { feeRate, ], ), - returnValue: _i15.Future.value(0), - ) as _i15.Future); + returnValue: _i16.Future.value(0), + ) as _i16.Future); @override int roughFeeEstimate( int? inputCount, @@ -972,25 +985,25 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { returnValue: 0, ) as int); @override - _i15.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( + _i16.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i15.Future.value(0), - ) as _i15.Future); + returnValue: _i16.Future.value(0), + ) as _i16.Future); @override - _i15.Future generateNewAddress() => (super.noSuchMethod( + _i16.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i15.Future.value(false), - ) as _i15.Future); + returnValue: _i16.Future.value(false), + ) as _i16.Future); @override void initCache( String? walletId, - _i14.Coin? coin, + _i15.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1003,14 +1016,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i15.Future updateCachedId(String? id) => (super.noSuchMethod( + _i16.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1020,14 +1033,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { returnValue: 0, ) as int); @override - _i15.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i16.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1037,15 +1050,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { returnValue: false, ) as bool); @override - _i15.Future updateCachedIsFavorite(bool? isFavorite) => + _i16.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override _i11.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1061,15 +1074,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { ), ) as _i11.Balance); @override - _i15.Future updateCachedBalance(_i11.Balance? balance) => + _i16.Future updateCachedBalance(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override _i11.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1085,15 +1098,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { ), ) as _i11.Balance); @override - _i15.Future updateCachedBalanceSecondary(_i11.Balance? balance) => + _i16.Future updateCachedBalanceSecondary(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override void initWalletDB({_i12.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1103,12 +1116,55 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet { ), returnValueForMissingStub: null, ); + @override + _i16.Future< + _i13.Tuple4<_i20.Transaction, List<_i20.Output>, List<_i20.Input>, + _i20.Address>> parseTransaction( + Map? txData, + dynamic electrumxClient, + List<_i20.Address>? myAddresses, + _i15.Coin? coin, + int? minConfirms, + String? walletId, + ) => + (super.noSuchMethod( + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + returnValue: _i16.Future< + _i13.Tuple4<_i20.Transaction, List<_i20.Output>, List<_i20.Input>, + _i20.Address>>.value(_FakeTuple4_11<_i20.Transaction, + List<_i20.Output>, List<_i20.Input>, _i20.Address>( + this, + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + )), + ) as _i16.Future< + _i13.Tuple4<_i20.Transaction, List<_i20.Output>, List<_i20.Input>, + _i20.Address>>); } /// A class which mocks [LocaleService]. /// /// See the documentation for Mockito's code generation for more information. -class MockLocaleService extends _i1.Mock implements _i20.LocaleService { +class MockLocaleService extends _i1.Mock implements _i22.LocaleService { MockLocaleService() { _i1.throwOnMissingStub(this); } @@ -1124,17 +1180,17 @@ class MockLocaleService extends _i1.Mock implements _i20.LocaleService { returnValue: false, ) as bool); @override - _i15.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( + _i16.Future loadLocale({bool? notify = true}) => (super.noSuchMethod( Invocation.method( #loadLocale, [], {#notify: notify}, ), - returnValue: _i15.Future.value(), - returnValueForMissingStub: _i15.Future.value(), - ) as _i15.Future); + returnValue: _i16.Future.value(), + returnValueForMissingStub: _i16.Future.value(), + ) as _i16.Future); @override - void addListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i18.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1142,7 +1198,7 @@ class MockLocaleService extends _i1.Mock implements _i20.LocaleService { returnValueForMissingStub: null, ); @override - void removeListener(_i17.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i18.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], 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 41f874146..5f2b9b7f5 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 @@ -3,8 +3,8 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i17; -import 'dart:ui' as _i19; +import 'dart:async' as _i18; +import 'dart:ui' as _i20; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; @@ -13,21 +13,23 @@ import 'package:stackwallet/db/main_db.dart' as _i12; 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 _i21; -import 'package:stackwallet/models/node_model.dart' as _i22; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i22; +import 'package:stackwallet/models/node_model.dart' as _i24; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i8; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i20; -import 'package:stackwallet/services/coins/coin_service.dart' as _i14; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i21; +import 'package:stackwallet/services/coins/coin_service.dart' as _i15; 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 _i7; -import 'package:stackwallet/services/wallets.dart' as _i15; +import 'package:stackwallet/services/wallets.dart' as _i16; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i16; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i17; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i23; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' - as _i13; -import 'package:stackwallet/utilities/prefs.dart' as _i18; + as _i14; +import 'package:stackwallet/utilities/prefs.dart' as _i19; +import 'package:tuple/tuple.dart' as _i13; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -154,9 +156,9 @@ class _FakeElectrumXNode_10 extends _i1.SmartFake implements _i9.ElectrumXNode { ); } -class _FakeSecureStorageInterface_11 extends _i1.SmartFake - implements _i13.SecureStorageInterface { - _FakeSecureStorageInterface_11( +class _FakeTuple4_11 extends _i1.SmartFake + implements _i13.Tuple4 { + _FakeTuple4_11( Object parent, Invocation parentInvocation, ) : super( @@ -165,9 +167,20 @@ class _FakeSecureStorageInterface_11 extends _i1.SmartFake ); } -class _FakeCoinServiceAPI_12 extends _i1.SmartFake - implements _i14.CoinServiceAPI { - _FakeCoinServiceAPI_12( +class _FakeSecureStorageInterface_12 extends _i1.SmartFake + implements _i14.SecureStorageInterface { + _FakeSecureStorageInterface_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_13 extends _i1.SmartFake + implements _i15.CoinServiceAPI { + _FakeCoinServiceAPI_13( Object parent, Invocation parentInvocation, ) : super( @@ -179,7 +192,7 @@ class _FakeCoinServiceAPI_12 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 _i15.Wallets { +class MockWallets extends _i1.Mock implements _i16.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -246,7 +259,7 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i16.Coin? coin}) => + List getWalletIdsFor({required _i17.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -256,18 +269,18 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValue: [], ) as List); @override - Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> + Map<_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i16.Coin, + returnValue: <_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>{}, - ) as Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); + ) as Map<_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i16.Coin? coin) => + _i17.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -331,17 +344,17 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - _i17.Future load(_i18.Prefs? prefs) => (super.noSuchMethod( + _i18.Future load(_i19.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future loadAfterStackRestore( - _i18.Prefs? prefs, + _i18.Future loadAfterStackRestore( + _i19.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -352,11 +365,11 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { managers, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -364,7 +377,7 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -390,19 +403,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i17.Future> get walletNames => + _i18.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i17.Future>.value( + returnValue: _i18.Future>.value( {}), - ) as _i17.Future>); + ) as _i18.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future renameWallet({ + _i18.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -417,13 +430,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future addExistingStackWallet({ + _i18.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i16.Coin? coin, + required _i17.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -437,13 +450,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addNewWallet({ + _i18.Future addNewWallet({ required String? name, - required _i16.Coin? coin, + required _i17.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -456,46 +469,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i18.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override - _i17.Future saveFavoriteWalletIds(List? walletIds) => + _i18.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i18.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i18.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future moveFavorite({ + _i18.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -508,48 +521,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i18.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i18.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future isMnemonicVerified({required String? walletId}) => + _i18.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future setMnemonicVerified({required String? walletId}) => + _i18.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future deleteWallet( + _i18.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -561,20 +574,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future refreshWallets(bool? shouldNotifyListeners) => + _i18.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -582,7 +595,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -610,13 +623,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 _i20.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i17.Timer? _timer) => super.noSuchMethod( + set timer(_i18.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -693,59 +706,59 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future get currentChangeAddress => (super.noSuchMethod( + _i18.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override - _i17.Future get chainHeight => (super.noSuchMethod( + _i18.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -834,26 +847,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i12.MainDB); @override - _i17.Future exit() => (super.noSuchMethod( + _i18.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i20.DerivePathType addressType({required String? address}) => + _i23.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i20.DerivePathType.bip44, - ) as _i20.DerivePathType); + returnValue: _i23.DerivePathType.bip44, + ) as _i23.DerivePathType); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -870,47 +883,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future getTransactionCacheEarly(List? allAddresses) => + _i18.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i18.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future getAllTxsToWatch() => (super.noSuchMethod( + _i18.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -926,26 +939,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -963,33 +976,33 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateSentCachedTxData(Map? txData) => + _i18.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -999,35 +1012,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i18.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), - returnValue: _i17.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( + returnValue: _i18.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i17.Future<_i9.ElectrumXNode>); + ) as _i18.Future<_i9.ElectrumXNode>); @override - _i17.Future addDerivation({ + _i18.Future addDerivation({ required int? chain, required String? address, required String? pubKey, required String? wif, - required _i20.DerivePathType? derivePathType, + required _i23.DerivePathType? derivePathType, }) => (super.noSuchMethod( Invocation.method( @@ -1041,13 +1054,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #derivePathType: derivePathType, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addDerivations({ + _i18.Future addDerivations({ required int? chain, - required _i20.DerivePathType? derivePathType, + required _i23.DerivePathType? derivePathType, required Map? derivationsToAdd, }) => (super.noSuchMethod( @@ -1060,50 +1073,50 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #derivationsToAdd: derivationsToAdd, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future>> fastFetch( + _i18.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i17.Future>>.value( + returnValue: _i18.Future>>.value( >[]), - ) as _i17.Future>>); + ) as _i18.Future>>); @override - _i17.Future getTxCount({required String? address}) => + _i18.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future checkCurrentReceivingAddressesForTransactions() => + _i18.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future checkCurrentChangeAddressesForTransactions() => + _i18.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override int estimateTxFee({ required int? vSize, @@ -1127,7 +1140,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { String? _recipientAddress, bool? isSendAll, { int? additionalOutputs = 0, - List<_i21.UTXO>? utxos, + List<_i22.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -1143,19 +1156,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, )); @override - _i17.Future> fetchBuildTxData( - List<_i21.UTXO>? utxosToUse) => + _i18.Future> fetchBuildTxData( + List<_i22.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future> buildTransaction({ - required List<_i21.UTXO>? utxosToUse, + _i18.Future> buildTransaction({ + required List<_i22.UTXO>? utxosToUse, required Map? utxoSigningData, required List? recipients, required List? satoshiAmounts, @@ -1172,10 +1185,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1187,11 +1200,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1203,8 +1216,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override int roughFeeEstimate( int? inputCount, @@ -1223,25 +1236,25 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: 0, ) as int); @override - _i17.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( + _i18.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override void initCache( String? walletId, - _i16.Coin? coin, + _i17.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1254,14 +1267,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i17.Future updateCachedId(String? id) => (super.noSuchMethod( + _i18.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1271,14 +1284,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: 0, ) as int); @override - _i17.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i18.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1288,15 +1301,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i17.Future updateCachedIsFavorite(bool? isFavorite) => + _i18.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override _i11.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1312,15 +1325,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i11.Balance); @override - _i17.Future updateCachedBalance(_i11.Balance? balance) => + _i18.Future updateCachedBalance(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override _i11.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1336,15 +1349,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i11.Balance); @override - _i17.Future updateCachedBalanceSecondary(_i11.Balance? balance) => + _i18.Future updateCachedBalanceSecondary(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override void initWalletDB({_i12.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1354,6 +1367,49 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), returnValueForMissingStub: null, ); + @override + _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>> parseTransaction( + Map? txData, + dynamic electrumxClient, + List<_i22.Address>? myAddresses, + _i17.Coin? coin, + int? minConfirms, + String? walletId, + ) => + (super.noSuchMethod( + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + returnValue: _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>>.value(_FakeTuple4_11<_i22.Transaction, + List<_i22.Output>, List<_i22.Input>, _i22.Address>( + this, + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + )), + ) as _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>>); } /// A class which mocks [NodeService]. @@ -1361,41 +1417,41 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { /// See the documentation for Mockito's code generation for more information. class MockNodeService extends _i1.Mock implements _i3.NodeService { @override - _i13.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( + _i14.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( Invocation.getter(#secureStorageInterface), - returnValue: _FakeSecureStorageInterface_11( + returnValue: _FakeSecureStorageInterface_12( this, Invocation.getter(#secureStorageInterface), ), - ) as _i13.SecureStorageInterface); + ) as _i14.SecureStorageInterface); @override - List<_i22.NodeModel> get primaryNodes => (super.noSuchMethod( + List<_i24.NodeModel> get primaryNodes => (super.noSuchMethod( Invocation.getter(#primaryNodes), - returnValue: <_i22.NodeModel>[], - ) as List<_i22.NodeModel>); + returnValue: <_i24.NodeModel>[], + ) as List<_i24.NodeModel>); @override - List<_i22.NodeModel> get nodes => (super.noSuchMethod( + List<_i24.NodeModel> get nodes => (super.noSuchMethod( Invocation.getter(#nodes), - returnValue: <_i22.NodeModel>[], - ) as List<_i22.NodeModel>); + returnValue: <_i24.NodeModel>[], + ) as List<_i24.NodeModel>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future updateDefaults() => (super.noSuchMethod( + _i18.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future setPrimaryNodeFor({ - required _i16.Coin? coin, - required _i22.NodeModel? node, + _i18.Future setPrimaryNodeFor({ + required _i17.Coin? coin, + required _i24.NodeModel? node, bool? shouldNotifyListeners = false, }) => (super.noSuchMethod( @@ -1408,44 +1464,44 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i22.NodeModel? getPrimaryNodeFor({required _i16.Coin? coin}) => + _i24.NodeModel? getPrimaryNodeFor({required _i17.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getPrimaryNodeFor, [], {#coin: coin}, - )) as _i22.NodeModel?); + )) as _i24.NodeModel?); @override - List<_i22.NodeModel> getNodesFor(_i16.Coin? coin) => (super.noSuchMethod( + List<_i24.NodeModel> getNodesFor(_i17.Coin? coin) => (super.noSuchMethod( Invocation.method( #getNodesFor, [coin], ), - returnValue: <_i22.NodeModel>[], - ) as List<_i22.NodeModel>); + returnValue: <_i24.NodeModel>[], + ) as List<_i24.NodeModel>); @override - _i22.NodeModel? getNodeById({required String? id}) => + _i24.NodeModel? getNodeById({required String? id}) => (super.noSuchMethod(Invocation.method( #getNodeById, [], {#id: id}, - )) as _i22.NodeModel?); + )) as _i24.NodeModel?); @override - List<_i22.NodeModel> failoverNodesFor({required _i16.Coin? coin}) => + List<_i24.NodeModel> failoverNodesFor({required _i17.Coin? coin}) => (super.noSuchMethod( Invocation.method( #failoverNodesFor, [], {#coin: coin}, ), - returnValue: <_i22.NodeModel>[], - ) as List<_i22.NodeModel>); + returnValue: <_i24.NodeModel>[], + ) as List<_i24.NodeModel>); @override - _i17.Future add( - _i22.NodeModel? node, + _i18.Future add( + _i24.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => @@ -1458,11 +1514,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future delete( + _i18.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -1474,11 +1530,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future setEnabledState( + _i18.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -1492,12 +1548,12 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future edit( - _i22.NodeModel? editedNode, + _i18.Future edit( + _i24.NodeModel? editedNode, String? password, bool? shouldNotifyListeners, ) => @@ -1510,20 +1566,20 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateCommunityNodes() => (super.noSuchMethod( + _i18.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1531,7 +1587,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1574,23 +1630,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i14.CoinServiceAPI get wallet => (super.noSuchMethod( + _i15.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_12( + returnValue: _FakeCoinServiceAPI_13( this, Invocation.getter(#wallet), ), - ) as _i14.CoinServiceAPI); + ) as _i15.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -1623,23 +1679,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -1649,16 +1705,16 @@ class MockManager extends _i1.Mock implements _i6.Manager { ), ) as _i11.Balance); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -1678,10 +1734,10 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -1693,19 +1749,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -1715,7 +1776,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -1731,27 +1792,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1761,33 +1822,33 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -1804,20 +1865,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future exitCurrentWallet() => (super.noSuchMethod( + _i18.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1829,11 +1890,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1845,18 +1906,18 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1864,7 +1925,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1884,7 +1945,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 _i14.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i15.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -1895,10 +1956,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -1931,23 +1992,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -1957,16 +2018,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { ), ) as _i11.Balance); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -1986,10 +2047,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: '', ) as String); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -2006,7 +2067,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: 0, ) as int); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -2022,36 +2083,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2061,15 +2122,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: false, ) as bool); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -2086,38 +2147,38 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future exit() => (super.noSuchMethod( + _i18.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2129,11 +2190,11 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -2145,24 +2206,24 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future updateSentCachedTxData(Map? txData) => + _i18.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); } 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 3e88ef129..f510bde29 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,8 +3,8 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i17; -import 'dart:ui' as _i19; +import 'dart:async' as _i18; +import 'dart:ui' as _i20; import 'package:flutter/foundation.dart' as _i4; import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5; @@ -13,21 +13,23 @@ import 'package:stackwallet/db/main_db.dart' as _i12; 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 _i21; -import 'package:stackwallet/models/node_model.dart' as _i22; +import 'package:stackwallet/models/isar/models/isar_models.dart' as _i22; +import 'package:stackwallet/models/node_model.dart' as _i24; import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i8; -import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i20; -import 'package:stackwallet/services/coins/coin_service.dart' as _i14; +import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i21; +import 'package:stackwallet/services/coins/coin_service.dart' as _i15; 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 _i7; -import 'package:stackwallet/services/wallets.dart' as _i15; +import 'package:stackwallet/services/wallets.dart' as _i16; import 'package:stackwallet/services/wallets_service.dart' as _i2; -import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i16; +import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i17; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i23; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart' - as _i13; -import 'package:stackwallet/utilities/prefs.dart' as _i18; + as _i14; +import 'package:stackwallet/utilities/prefs.dart' as _i19; +import 'package:tuple/tuple.dart' as _i13; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -154,9 +156,9 @@ class _FakeElectrumXNode_10 extends _i1.SmartFake implements _i9.ElectrumXNode { ); } -class _FakeSecureStorageInterface_11 extends _i1.SmartFake - implements _i13.SecureStorageInterface { - _FakeSecureStorageInterface_11( +class _FakeTuple4_11 extends _i1.SmartFake + implements _i13.Tuple4 { + _FakeTuple4_11( Object parent, Invocation parentInvocation, ) : super( @@ -165,9 +167,20 @@ class _FakeSecureStorageInterface_11 extends _i1.SmartFake ); } -class _FakeCoinServiceAPI_12 extends _i1.SmartFake - implements _i14.CoinServiceAPI { - _FakeCoinServiceAPI_12( +class _FakeSecureStorageInterface_12 extends _i1.SmartFake + implements _i14.SecureStorageInterface { + _FakeSecureStorageInterface_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCoinServiceAPI_13 extends _i1.SmartFake + implements _i15.CoinServiceAPI { + _FakeCoinServiceAPI_13( Object parent, Invocation parentInvocation, ) : super( @@ -179,7 +192,7 @@ class _FakeCoinServiceAPI_12 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 _i15.Wallets { +class MockWallets extends _i1.Mock implements _i16.Wallets { MockWallets() { _i1.throwOnMissingStub(this); } @@ -246,7 +259,7 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - List getWalletIdsFor({required _i16.Coin? coin}) => + List getWalletIdsFor({required _i17.Coin? coin}) => (super.noSuchMethod( Invocation.method( #getWalletIdsFor, @@ -256,18 +269,18 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValue: [], ) as List); @override - Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> + Map<_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>> getManagerProvidersByCoin() => (super.noSuchMethod( Invocation.method( #getManagerProvidersByCoin, [], ), - returnValue: <_i16.Coin, + returnValue: <_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>{}, - ) as Map<_i16.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); + ) as Map<_i17.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>); @override List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin( - _i16.Coin? coin) => + _i17.Coin? coin) => (super.noSuchMethod( Invocation.method( #getManagerProvidersForCoin, @@ -331,17 +344,17 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - _i17.Future load(_i18.Prefs? prefs) => (super.noSuchMethod( + _i18.Future load(_i19.Prefs? prefs) => (super.noSuchMethod( Invocation.method( #load, [prefs], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future loadAfterStackRestore( - _i18.Prefs? prefs, + _i18.Future loadAfterStackRestore( + _i19.Prefs? prefs, List<_i6.Manager>? managers, ) => (super.noSuchMethod( @@ -352,11 +365,11 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { managers, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -364,7 +377,7 @@ class MockWallets extends _i1.Mock implements _i15.Wallets { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -390,19 +403,19 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { } @override - _i17.Future> get walletNames => + _i18.Future> get walletNames => (super.noSuchMethod( Invocation.getter(#walletNames), - returnValue: _i17.Future>.value( + returnValue: _i18.Future>.value( {}), - ) as _i17.Future>); + ) as _i18.Future>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future renameWallet({ + _i18.Future renameWallet({ required String? from, required String? to, required bool? shouldNotifyListeners, @@ -417,13 +430,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future addExistingStackWallet({ + _i18.Future addExistingStackWallet({ required String? name, required String? walletId, - required _i16.Coin? coin, + required _i17.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -437,13 +450,13 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addNewWallet({ + _i18.Future addNewWallet({ required String? name, - required _i16.Coin? coin, + required _i17.Coin? coin, required bool? shouldNotifyListeners, }) => (super.noSuchMethod( @@ -456,46 +469,46 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future> getFavoriteWalletIds() => (super.noSuchMethod( + _i18.Future> getFavoriteWalletIds() => (super.noSuchMethod( Invocation.method( #getFavoriteWalletIds, [], ), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override - _i17.Future saveFavoriteWalletIds(List? walletIds) => + _i18.Future saveFavoriteWalletIds(List? walletIds) => (super.noSuchMethod( Invocation.method( #saveFavoriteWalletIds, [walletIds], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addFavorite(String? walletId) => (super.noSuchMethod( + _i18.Future addFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #addFavorite, [walletId], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future removeFavorite(String? walletId) => (super.noSuchMethod( + _i18.Future removeFavorite(String? walletId) => (super.noSuchMethod( Invocation.method( #removeFavorite, [walletId], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future moveFavorite({ + _i18.Future moveFavorite({ required int? fromIndex, required int? toIndex, }) => @@ -508,48 +521,48 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { #toIndex: toIndex, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future checkForDuplicate(String? name) => (super.noSuchMethod( + _i18.Future checkForDuplicate(String? name) => (super.noSuchMethod( Invocation.method( #checkForDuplicate, [name], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future getWalletId(String? walletName) => (super.noSuchMethod( + _i18.Future getWalletId(String? walletName) => (super.noSuchMethod( Invocation.method( #getWalletId, [walletName], ), - returnValue: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future isMnemonicVerified({required String? walletId}) => + _i18.Future isMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #isMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future setMnemonicVerified({required String? walletId}) => + _i18.Future setMnemonicVerified({required String? walletId}) => (super.noSuchMethod( Invocation.method( #setMnemonicVerified, [], {#walletId: walletId}, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future deleteWallet( + _i18.Future deleteWallet( String? name, bool? shouldNotifyListeners, ) => @@ -561,20 +574,20 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future refreshWallets(bool? shouldNotifyListeners) => + _i18.Future refreshWallets(bool? shouldNotifyListeners) => (super.noSuchMethod( Invocation.method( #refreshWallets, [shouldNotifyListeners], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -582,7 +595,7 @@ class MockWalletsService extends _i1.Mock implements _i2.WalletsService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -610,13 +623,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 _i20.BitcoinWallet { +class MockBitcoinWallet extends _i1.Mock implements _i21.BitcoinWallet { MockBitcoinWallet() { _i1.throwOnMissingStub(this); } @override - set timer(_i17.Timer? _timer) => super.noSuchMethod( + set timer(_i18.Timer? _timer) => super.noSuchMethod( Invocation.setter( #timer, _timer, @@ -693,59 +706,59 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future get currentChangeAddress => (super.noSuchMethod( + _i18.Future get currentChangeAddress => (super.noSuchMethod( Invocation.getter(#currentChangeAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), returnValue: false, ) as bool); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override - _i17.Future get chainHeight => (super.noSuchMethod( + _i18.Future get chainHeight => (super.noSuchMethod( Invocation.getter(#chainHeight), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override int get storedChainHeight => (super.noSuchMethod( Invocation.getter(#storedChainHeight), @@ -834,26 +847,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i12.MainDB); @override - _i17.Future exit() => (super.noSuchMethod( + _i18.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i20.DerivePathType addressType({required String? address}) => + _i23.DerivePathType addressType({required String? address}) => (super.noSuchMethod( Invocation.method( #addressType, [], {#address: address}, ), - returnValue: _i20.DerivePathType.bip44, - ) as _i20.DerivePathType); + returnValue: _i23.DerivePathType.bip44, + ) as _i23.DerivePathType); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -870,47 +883,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future getTransactionCacheEarly(List? allAddresses) => + _i18.Future getTransactionCacheEarly(List? allAddresses) => (super.noSuchMethod( Invocation.method( #getTransactionCacheEarly, [allAddresses], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future refreshIfThereIsNewData() => (super.noSuchMethod( + _i18.Future refreshIfThereIsNewData() => (super.noSuchMethod( Invocation.method( #refreshIfThereIsNewData, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future getAllTxsToWatch() => (super.noSuchMethod( + _i18.Future getAllTxsToWatch() => (super.noSuchMethod( Invocation.method( #getAllTxsToWatch, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -926,26 +939,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override void startNetworkAlivePinging() => super.noSuchMethod( Invocation.method( @@ -963,33 +976,33 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateSentCachedTxData(Map? txData) => + _i18.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -999,35 +1012,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( + _i18.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod( Invocation.method( #getCurrentNode, [], ), - returnValue: _i17.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( + returnValue: _i18.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10( this, Invocation.method( #getCurrentNode, [], ), )), - ) as _i17.Future<_i9.ElectrumXNode>); + ) as _i18.Future<_i9.ElectrumXNode>); @override - _i17.Future addDerivation({ + _i18.Future addDerivation({ required int? chain, required String? address, required String? pubKey, required String? wif, - required _i20.DerivePathType? derivePathType, + required _i23.DerivePathType? derivePathType, }) => (super.noSuchMethod( Invocation.method( @@ -1041,13 +1054,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #derivePathType: derivePathType, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future addDerivations({ + _i18.Future addDerivations({ required int? chain, - required _i20.DerivePathType? derivePathType, + required _i23.DerivePathType? derivePathType, required Map? derivationsToAdd, }) => (super.noSuchMethod( @@ -1060,50 +1073,50 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { #derivationsToAdd: derivationsToAdd, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future>> fastFetch( + _i18.Future>> fastFetch( List? allTxHashes) => (super.noSuchMethod( Invocation.method( #fastFetch, [allTxHashes], ), - returnValue: _i17.Future>>.value( + returnValue: _i18.Future>>.value( >[]), - ) as _i17.Future>>); + ) as _i18.Future>>); @override - _i17.Future getTxCount({required String? address}) => + _i18.Future getTxCount({required String? address}) => (super.noSuchMethod( Invocation.method( #getTxCount, [], {#address: address}, ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future checkCurrentReceivingAddressesForTransactions() => + _i18.Future checkCurrentReceivingAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentReceivingAddressesForTransactions, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future checkCurrentChangeAddressesForTransactions() => + _i18.Future checkCurrentChangeAddressesForTransactions() => (super.noSuchMethod( Invocation.method( #checkCurrentChangeAddressesForTransactions, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override int estimateTxFee({ required int? vSize, @@ -1127,7 +1140,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { String? _recipientAddress, bool? isSendAll, { int? additionalOutputs = 0, - List<_i21.UTXO>? utxos, + List<_i22.UTXO>? utxos, }) => super.noSuchMethod(Invocation.method( #coinSelection, @@ -1143,19 +1156,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, )); @override - _i17.Future> fetchBuildTxData( - List<_i21.UTXO>? utxosToUse) => + _i18.Future> fetchBuildTxData( + List<_i22.UTXO>? utxosToUse) => (super.noSuchMethod( Invocation.method( #fetchBuildTxData, [utxosToUse], ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future> buildTransaction({ - required List<_i21.UTXO>? utxosToUse, + _i18.Future> buildTransaction({ + required List<_i22.UTXO>? utxosToUse, required Map? utxoSigningData, required List? recipients, required List? satoshiAmounts, @@ -1172,10 +1185,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1187,11 +1200,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1203,8 +1216,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override int roughFeeEstimate( int? inputCount, @@ -1223,25 +1236,25 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: 0, ) as int); @override - _i17.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( + _i18.Future sweepAllEstimate(int? feeRate) => (super.noSuchMethod( Invocation.method( #sweepAllEstimate, [feeRate], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override void initCache( String? walletId, - _i16.Coin? coin, + _i17.Coin? coin, ) => super.noSuchMethod( Invocation.method( @@ -1254,14 +1267,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValueForMissingStub: null, ); @override - _i17.Future updateCachedId(String? id) => (super.noSuchMethod( + _i18.Future updateCachedId(String? id) => (super.noSuchMethod( Invocation.method( #updateCachedId, [id], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override int getCachedChainHeight() => (super.noSuchMethod( Invocation.method( @@ -1271,14 +1284,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: 0, ) as int); @override - _i17.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( + _i18.Future updateCachedChainHeight(int? height) => (super.noSuchMethod( Invocation.method( #updateCachedChainHeight, [height], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool getCachedIsFavorite() => (super.noSuchMethod( Invocation.method( @@ -1288,15 +1301,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { returnValue: false, ) as bool); @override - _i17.Future updateCachedIsFavorite(bool? isFavorite) => + _i18.Future updateCachedIsFavorite(bool? isFavorite) => (super.noSuchMethod( Invocation.method( #updateCachedIsFavorite, [isFavorite], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override _i11.Balance getCachedBalance() => (super.noSuchMethod( Invocation.method( @@ -1312,15 +1325,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i11.Balance); @override - _i17.Future updateCachedBalance(_i11.Balance? balance) => + _i18.Future updateCachedBalance(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalance, [balance], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override _i11.Balance getCachedBalanceSecondary() => (super.noSuchMethod( Invocation.method( @@ -1336,15 +1349,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), ) as _i11.Balance); @override - _i17.Future updateCachedBalanceSecondary(_i11.Balance? balance) => + _i18.Future updateCachedBalanceSecondary(_i11.Balance? balance) => (super.noSuchMethod( Invocation.method( #updateCachedBalanceSecondary, [balance], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override void initWalletDB({_i12.MainDB? mockableOverride}) => super.noSuchMethod( Invocation.method( @@ -1354,6 +1367,49 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { ), returnValueForMissingStub: null, ); + @override + _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>> parseTransaction( + Map? txData, + dynamic electrumxClient, + List<_i22.Address>? myAddresses, + _i17.Coin? coin, + int? minConfirms, + String? walletId, + ) => + (super.noSuchMethod( + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + returnValue: _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>>.value(_FakeTuple4_11<_i22.Transaction, + List<_i22.Output>, List<_i22.Input>, _i22.Address>( + this, + Invocation.method( + #parseTransaction, + [ + txData, + electrumxClient, + myAddresses, + coin, + minConfirms, + walletId, + ], + ), + )), + ) as _i18.Future< + _i13.Tuple4<_i22.Transaction, List<_i22.Output>, List<_i22.Input>, + _i22.Address>>); } /// A class which mocks [NodeService]. @@ -1361,41 +1417,41 @@ class MockBitcoinWallet extends _i1.Mock implements _i20.BitcoinWallet { /// See the documentation for Mockito's code generation for more information. class MockNodeService extends _i1.Mock implements _i3.NodeService { @override - _i13.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( + _i14.SecureStorageInterface get secureStorageInterface => (super.noSuchMethod( Invocation.getter(#secureStorageInterface), - returnValue: _FakeSecureStorageInterface_11( + returnValue: _FakeSecureStorageInterface_12( this, Invocation.getter(#secureStorageInterface), ), - ) as _i13.SecureStorageInterface); + ) as _i14.SecureStorageInterface); @override - List<_i22.NodeModel> get primaryNodes => (super.noSuchMethod( + List<_i24.NodeModel> get primaryNodes => (super.noSuchMethod( Invocation.getter(#primaryNodes), - returnValue: <_i22.NodeModel>[], - ) as List<_i22.NodeModel>); + returnValue: <_i24.NodeModel>[], + ) as List<_i24.NodeModel>); @override - List<_i22.NodeModel> get nodes => (super.noSuchMethod( + List<_i24.NodeModel> get nodes => (super.noSuchMethod( Invocation.getter(#nodes), - returnValue: <_i22.NodeModel>[], - ) as List<_i22.NodeModel>); + returnValue: <_i24.NodeModel>[], + ) as List<_i24.NodeModel>); @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future updateDefaults() => (super.noSuchMethod( + _i18.Future updateDefaults() => (super.noSuchMethod( Invocation.method( #updateDefaults, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future setPrimaryNodeFor({ - required _i16.Coin? coin, - required _i22.NodeModel? node, + _i18.Future setPrimaryNodeFor({ + required _i17.Coin? coin, + required _i24.NodeModel? node, bool? shouldNotifyListeners = false, }) => (super.noSuchMethod( @@ -1408,44 +1464,44 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { #shouldNotifyListeners: shouldNotifyListeners, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i22.NodeModel? getPrimaryNodeFor({required _i16.Coin? coin}) => + _i24.NodeModel? getPrimaryNodeFor({required _i17.Coin? coin}) => (super.noSuchMethod(Invocation.method( #getPrimaryNodeFor, [], {#coin: coin}, - )) as _i22.NodeModel?); + )) as _i24.NodeModel?); @override - List<_i22.NodeModel> getNodesFor(_i16.Coin? coin) => (super.noSuchMethod( + List<_i24.NodeModel> getNodesFor(_i17.Coin? coin) => (super.noSuchMethod( Invocation.method( #getNodesFor, [coin], ), - returnValue: <_i22.NodeModel>[], - ) as List<_i22.NodeModel>); + returnValue: <_i24.NodeModel>[], + ) as List<_i24.NodeModel>); @override - _i22.NodeModel? getNodeById({required String? id}) => + _i24.NodeModel? getNodeById({required String? id}) => (super.noSuchMethod(Invocation.method( #getNodeById, [], {#id: id}, - )) as _i22.NodeModel?); + )) as _i24.NodeModel?); @override - List<_i22.NodeModel> failoverNodesFor({required _i16.Coin? coin}) => + List<_i24.NodeModel> failoverNodesFor({required _i17.Coin? coin}) => (super.noSuchMethod( Invocation.method( #failoverNodesFor, [], {#coin: coin}, ), - returnValue: <_i22.NodeModel>[], - ) as List<_i22.NodeModel>); + returnValue: <_i24.NodeModel>[], + ) as List<_i24.NodeModel>); @override - _i17.Future add( - _i22.NodeModel? node, + _i18.Future add( + _i24.NodeModel? node, String? password, bool? shouldNotifyListeners, ) => @@ -1458,11 +1514,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future delete( + _i18.Future delete( String? id, bool? shouldNotifyListeners, ) => @@ -1474,11 +1530,11 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future setEnabledState( + _i18.Future setEnabledState( String? id, bool? enabled, bool? shouldNotifyListeners, @@ -1492,12 +1548,12 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future edit( - _i22.NodeModel? editedNode, + _i18.Future edit( + _i24.NodeModel? editedNode, String? password, bool? shouldNotifyListeners, ) => @@ -1510,20 +1566,20 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { shouldNotifyListeners, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateCommunityNodes() => (super.noSuchMethod( + _i18.Future updateCommunityNodes() => (super.noSuchMethod( Invocation.method( #updateCommunityNodes, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1531,7 +1587,7 @@ class MockNodeService extends _i1.Mock implements _i3.NodeService { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1574,23 +1630,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i14.CoinServiceAPI get wallet => (super.noSuchMethod( + _i15.CoinServiceAPI get wallet => (super.noSuchMethod( Invocation.getter(#wallet), - returnValue: _FakeCoinServiceAPI_12( + returnValue: _FakeCoinServiceAPI_13( this, Invocation.getter(#wallet), ), - ) as _i14.CoinServiceAPI); + ) as _i15.CoinServiceAPI); @override bool get hasBackgroundRefreshListener => (super.noSuchMethod( Invocation.getter(#hasBackgroundRefreshListener), returnValue: false, ) as bool); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -1623,23 +1679,23 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -1649,16 +1705,16 @@ class MockManager extends _i1.Mock implements _i6.Manager { ), ) as _i11.Balance); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -1678,10 +1734,10 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: '', ) as String); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override bool get isConnected => (super.noSuchMethod( Invocation.getter(#isConnected), @@ -1693,19 +1749,24 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: 0, ) as int); @override + bool get hasPaynymSupport => (super.noSuchMethod( + Invocation.getter(#hasPaynymSupport), + returnValue: false, + ) as bool); + @override bool get hasListeners => (super.noSuchMethod( Invocation.getter(#hasListeners), returnValue: false, ) as bool); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override void dispose() => super.noSuchMethod( Invocation.method( @@ -1715,7 +1776,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -1731,27 +1792,27 @@ class MockManager extends _i1.Mock implements _i6.Manager { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -1761,33 +1822,33 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValue: false, ) as bool); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -1804,20 +1865,20 @@ class MockManager extends _i1.Mock implements _i6.Manager { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future exitCurrentWallet() => (super.noSuchMethod( + _i18.Future exitCurrentWallet() => (super.noSuchMethod( Invocation.method( #exitCurrentWallet, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -1829,11 +1890,11 @@ class MockManager extends _i1.Mock implements _i6.Manager { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -1845,18 +1906,18 @@ class MockManager extends _i1.Mock implements _i6.Manager { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - void addListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1864,7 +1925,7 @@ class MockManager extends _i1.Mock implements _i6.Manager { returnValueForMissingStub: null, ); @override - void removeListener(_i19.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i20.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -1884,7 +1945,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 _i14.CoinServiceAPI { +class MockCoinServiceAPI extends _i1.Mock implements _i15.CoinServiceAPI { @override set onIsActiveWalletChanged(void Function(bool)? _onIsActiveWalletChanged) => super.noSuchMethod( @@ -1895,10 +1956,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i16.Coin get coin => (super.noSuchMethod( + _i17.Coin get coin => (super.noSuchMethod( Invocation.getter(#coin), - returnValue: _i16.Coin.bitcoin, - ) as _i16.Coin); + returnValue: _i17.Coin.bitcoin, + ) as _i17.Coin); @override bool get isRefreshing => (super.noSuchMethod( Invocation.getter(#isRefreshing), @@ -1931,23 +1992,23 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValueForMissingStub: null, ); @override - _i17.Future<_i8.FeeObject> get fees => (super.noSuchMethod( + _i18.Future<_i8.FeeObject> get fees => (super.noSuchMethod( Invocation.getter(#fees), - returnValue: _i17.Future<_i8.FeeObject>.value(_FakeFeeObject_5( + returnValue: _i18.Future<_i8.FeeObject>.value(_FakeFeeObject_5( this, Invocation.getter(#fees), )), - ) as _i17.Future<_i8.FeeObject>); + ) as _i18.Future<_i8.FeeObject>); @override - _i17.Future get maxFee => (super.noSuchMethod( + _i18.Future get maxFee => (super.noSuchMethod( Invocation.getter(#maxFee), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future get currentReceivingAddress => (super.noSuchMethod( + _i18.Future get currentReceivingAddress => (super.noSuchMethod( Invocation.getter(#currentReceivingAddress), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override _i11.Balance get balance => (super.noSuchMethod( Invocation.getter(#balance), @@ -1957,16 +2018,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { ), ) as _i11.Balance); @override - _i17.Future> get transactions => (super.noSuchMethod( + _i18.Future> get transactions => (super.noSuchMethod( Invocation.getter(#transactions), returnValue: - _i17.Future>.value(<_i21.Transaction>[]), - ) as _i17.Future>); + _i18.Future>.value(<_i22.Transaction>[]), + ) as _i18.Future>); @override - _i17.Future> get utxos => (super.noSuchMethod( + _i18.Future> get utxos => (super.noSuchMethod( Invocation.getter(#utxos), - returnValue: _i17.Future>.value(<_i21.UTXO>[]), - ) as _i17.Future>); + returnValue: _i18.Future>.value(<_i22.UTXO>[]), + ) as _i18.Future>); @override set walletName(String? newName) => super.noSuchMethod( Invocation.setter( @@ -1986,10 +2047,10 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: '', ) as String); @override - _i17.Future> get mnemonic => (super.noSuchMethod( + _i18.Future> get mnemonic => (super.noSuchMethod( Invocation.getter(#mnemonic), - returnValue: _i17.Future>.value([]), - ) as _i17.Future>); + returnValue: _i18.Future>.value([]), + ) as _i18.Future>); @override bool get hasCalledExit => (super.noSuchMethod( Invocation.getter(#hasCalledExit), @@ -2006,7 +2067,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: 0, ) as int); @override - _i17.Future> prepareSend({ + _i18.Future> prepareSend({ required String? address, required int? satoshiAmount, Map? args, @@ -2022,36 +2083,36 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { }, ), returnValue: - _i17.Future>.value({}), - ) as _i17.Future>); + _i18.Future>.value({}), + ) as _i18.Future>); @override - _i17.Future confirmSend({required Map? txData}) => + _i18.Future confirmSend({required Map? txData}) => (super.noSuchMethod( Invocation.method( #confirmSend, [], {#txData: txData}, ), - returnValue: _i17.Future.value(''), - ) as _i17.Future); + returnValue: _i18.Future.value(''), + ) as _i18.Future); @override - _i17.Future refresh() => (super.noSuchMethod( + _i18.Future refresh() => (super.noSuchMethod( Invocation.method( #refresh, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( + _i18.Future updateNode(bool? shouldRefresh) => (super.noSuchMethod( Invocation.method( #updateNode, [shouldRefresh], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override bool validateAddress(String? address) => (super.noSuchMethod( Invocation.method( @@ -2061,15 +2122,15 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { returnValue: false, ) as bool); @override - _i17.Future testNetworkConnection() => (super.noSuchMethod( + _i18.Future testNetworkConnection() => (super.noSuchMethod( Invocation.method( #testNetworkConnection, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future recoverFromMnemonic({ + _i18.Future recoverFromMnemonic({ required String? mnemonic, required int? maxUnusedAddressGap, required int? maxNumberOfIndexesToCheck, @@ -2086,38 +2147,38 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { #height: height, }, ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeNew() => (super.noSuchMethod( + _i18.Future initializeNew() => (super.noSuchMethod( Invocation.method( #initializeNew, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future initializeExisting() => (super.noSuchMethod( + _i18.Future initializeExisting() => (super.noSuchMethod( Invocation.method( #initializeExisting, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future exit() => (super.noSuchMethod( + _i18.Future exit() => (super.noSuchMethod( Invocation.method( #exit, [], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future fullRescan( + _i18.Future fullRescan( int? maxUnusedAddressGap, int? maxNumberOfIndexesToCheck, ) => @@ -2129,11 +2190,11 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { maxNumberOfIndexesToCheck, ], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); @override - _i17.Future estimateFeeFor( + _i18.Future estimateFeeFor( int? satoshiAmount, int? feeRate, ) => @@ -2145,24 +2206,24 @@ class MockCoinServiceAPI extends _i1.Mock implements _i14.CoinServiceAPI { feeRate, ], ), - returnValue: _i17.Future.value(0), - ) as _i17.Future); + returnValue: _i18.Future.value(0), + ) as _i18.Future); @override - _i17.Future generateNewAddress() => (super.noSuchMethod( + _i18.Future generateNewAddress() => (super.noSuchMethod( Invocation.method( #generateNewAddress, [], ), - returnValue: _i17.Future.value(false), - ) as _i17.Future); + returnValue: _i18.Future.value(false), + ) as _i18.Future); @override - _i17.Future updateSentCachedTxData(Map? txData) => + _i18.Future updateSentCachedTxData(Map? txData) => (super.noSuchMethod( Invocation.method( #updateSentCachedTxData, [txData], ), - returnValue: _i17.Future.value(), - returnValueForMissingStub: _i17.Future.value(), - ) as _i17.Future); + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) as _i18.Future); } From cbf969ef545bcad68990fbf8a982fa640174f5b8 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 25 Jan 2023 17:42:20 -0600 Subject: [PATCH 26/55] desktop xmr/wow single wallet opening bug fix --- .../my_stack_view/wallet_summary_table.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_summary_table.dart b/lib/pages_desktop_specific/my_stack_view/wallet_summary_table.dart index b638d72a1..9b98d4aa8 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_summary_table.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_summary_table.dart @@ -46,10 +46,15 @@ class _WalletTableState extends ConsumerState { VoidCallback? expandOverride; if (providers.length == 1) { - expandOverride = () { - Navigator.of(context).pushNamed( + expandOverride = () async { + final manager = ref.read(providers.first); + if (manager.coin == Coin.monero || + manager.coin == Coin.wownero) { + await manager.initializeExisting(); + } + await Navigator.of(context).pushNamed( DesktopWalletView.routeName, - arguments: ref.read(providers.first).walletId, + arguments: manager.walletId, ); }; } From 3c9aa827bf80fcf4fa397d296ea107e653e9d264 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 09:18:07 -0600 Subject: [PATCH 27/55] update to versioned desktop secure storage and login key blob --- crypto_plugins/flutter_libmonero | 2 +- lib/utilities/desktop_password_service.dart | 59 +++++++++++++++++++-- pubspec.lock | 4 +- pubspec.yaml | 2 +- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/crypto_plugins/flutter_libmonero b/crypto_plugins/flutter_libmonero index c1b403ccf..af88796d5 160000 --- a/crypto_plugins/flutter_libmonero +++ b/crypto_plugins/flutter_libmonero @@ -1 +1 @@ -Subproject commit c1b403ccf6f4fffc9f7c233038c3df40f997c2b3 +Subproject commit af88796d5e4988c03422320c3842af5cf6c049ef diff --git a/lib/utilities/desktop_password_service.dart b/lib/utilities/desktop_password_service.dart index 9ef83932b..6263eb33b 100644 --- a/lib/utilities/desktop_password_service.dart +++ b/lib/utilities/desktop_password_service.dart @@ -4,9 +4,12 @@ import 'package:stackwallet/hive/db.dart'; import 'package:stackwallet/utilities/logger.dart'; const String _kKeyBlobKey = "swbKeyBlobKeyStringID"; +const String _kKeyBlobVersionKey = "swbKeyBlobVersionKeyStringID"; + +const int kLatestBlobVersion = 2; String _getMessageFromException(Object exception) { - if (exception is IncorrectPassphrase) { + if (exception is IncorrectPassphraseOrVersion) { return exception.errMsg(); } if (exception is BadDecryption) { @@ -18,6 +21,9 @@ String _getMessageFromException(Object exception) { if (exception is EncodingError) { return exception.errMsg(); } + if (exception is VersionError) { + return exception.errMsg(); + } return exception.toString(); } @@ -41,7 +47,10 @@ class DPS { } try { - _handler = await StorageCryptoHandler.fromNewPassphrase(passphrase); + _handler = await StorageCryptoHandler.fromNewPassphrase( + passphrase, + kLatestBlobVersion, + ); final box = await Hive.openBox(DB.boxNameDesktopData); await DB.instance.put( @@ -49,6 +58,7 @@ class DPS { key: _kKeyBlobKey, value: await _handler!.getKeyBlob(), ); + await _updateStoredKeyBlobVersion(kLatestBlobVersion); await box.close(); } catch (e, s) { Logging.instance.log( @@ -78,7 +88,24 @@ class DPS { } try { - _handler = await StorageCryptoHandler.fromExisting(passphrase, keyBlob); + final blobVersion = await _getStoredKeyBlobVersion(); + _handler = await StorageCryptoHandler.fromExisting( + passphrase, + keyBlob, + blobVersion, + ); + if (blobVersion < kLatestBlobVersion) { + // update blob + await _handler!.resetPassphrase(passphrase, kLatestBlobVersion); + final box = await Hive.openBox(DB.boxNameDesktopData); + await DB.instance.put( + boxName: DB.boxNameDesktopData, + key: _kKeyBlobKey, + value: await _handler!.getKeyBlob(), + ); + await _updateStoredKeyBlobVersion(kLatestBlobVersion); + await box.close(); + } } catch (e, s) { Logging.instance.log( "${_getMessageFromException(e)}\n$s", @@ -102,7 +129,8 @@ class DPS { } try { - await StorageCryptoHandler.fromExisting(passphrase, keyBlob); + final blobVersion = await _getStoredKeyBlobVersion(); + await StorageCryptoHandler.fromExisting(passphrase, keyBlob, blobVersion); // existing passphrase matches key blob return true; } catch (e, s) { @@ -135,8 +163,10 @@ class DPS { return false; } + final blobVersion = await _getStoredKeyBlobVersion(); + try { - await _handler!.resetPassphrase(passphraseNew); + await _handler!.resetPassphrase(passphraseNew, blobVersion); final box = await Hive.openBox(DB.boxNameDesktopData); await DB.instance.put( @@ -144,6 +174,7 @@ class DPS { key: _kKeyBlobKey, value: await _handler!.getKeyBlob(), ); + await _updateStoredKeyBlobVersion(blobVersion); await box.close(); // successfully updated passphrase @@ -164,4 +195,22 @@ class DPS { ); return keyBlob != null; } + + Future _getStoredKeyBlobVersion() async { + final box = await Hive.openBox(DB.boxNameDesktopData); + final keyBlobVersionString = DB.instance.get( + boxName: DB.boxNameDesktopData, + key: _kKeyBlobVersionKey, + ); + await box.close(); + return int.tryParse(keyBlobVersionString ?? "1") ?? 1; + } + + Future _updateStoredKeyBlobVersion(int version) async { + await DB.instance.put( + boxName: DB.boxNameDesktopData, + key: _kKeyBlobVersionKey, + value: version.toString(), + ); + } } diff --git a/pubspec.lock b/pubspec.lock index 8721ccc48..b5b417fd2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1408,8 +1408,8 @@ packages: dependency: "direct main" description: path: "." - ref: "6ada1204a4e0cf84d932b568e6150550478db69b" - resolved-ref: "6ada1204a4e0cf84d932b568e6150550478db69b" + ref: "93e2687bcc10fc7258c7dab038c363fc9ff8ba5d" + resolved-ref: "93e2687bcc10fc7258c7dab038c363fc9ff8ba5d" url: "https://github.com/cypherstack/stack_wallet_backup.git" source: git version: "0.0.1" diff --git a/pubspec.yaml b/pubspec.yaml index 759fc51f5..e1d2cba49 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,7 +54,7 @@ dependencies: stack_wallet_backup: git: url: https://github.com/cypherstack/stack_wallet_backup.git - ref: 6ada1204a4e0cf84d932b568e6150550478db69b + ref: 93e2687bcc10fc7258c7dab038c363fc9ff8ba5d bip47: git: From 188a9bc0d0e454f5fe4069eec10ba321b90b906b Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 10:05:49 -0600 Subject: [PATCH 28/55] update swb ref --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index e1d2cba49..32ab70261 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,7 +54,7 @@ dependencies: stack_wallet_backup: git: url: https://github.com/cypherstack/stack_wallet_backup.git - ref: 93e2687bcc10fc7258c7dab038c363fc9ff8ba5d + ref: e4b08d2b8965a5ae49bd57f598fa9011dd0c25e9 bip47: git: From 26c57b5456238b75a87ca06ab683d405316a38f6 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 10:59:15 -0600 Subject: [PATCH 29/55] typecast to generic PaynymWalletInterface --- .../paynym/dialogs/paynym_details_popup.dart | 23 ++++++++-------- lib/pages/paynym/paynym_claim_view.dart | 14 +++++----- .../subwidgets/desktop_paynym_details.dart | 26 +++++++++---------- .../send_view/confirm_transaction_view.dart | 5 ++-- .../wallet_view/desktop_wallet_view.dart | 13 +++++----- .../paynym_follow_toggle_button.dart | 24 ++++++++--------- pubspec.lock | 4 +-- 7 files changed, 54 insertions(+), 55 deletions(-) diff --git a/lib/pages/paynym/dialogs/paynym_details_popup.dart b/lib/pages/paynym/dialogs/paynym_details_popup.dart index 295eff134..840e0e1fc 100644 --- a/lib/pages/paynym/dialogs/paynym_details_popup.dart +++ b/lib/pages/paynym/dialogs/paynym_details_popup.dart @@ -14,8 +14,7 @@ import 'package:stackwallet/pages/paynym/subwidgets/paynym_bot.dart'; import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/route_generator.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; -import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; @@ -62,10 +61,10 @@ class _PaynymDetailsPopupState extends ConsumerState { ), ); - final wallet = ref - .read(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .wallet as DogecoinWallet; + final manager = + ref.read(walletsChangeNotifierProvider).getManager(widget.walletId); + + final wallet = manager.wallet as PaynymWalletInterface; if (await wallet.hasConnected(widget.accountLite.code)) { canPop = true; @@ -74,7 +73,7 @@ class _PaynymDetailsPopupState extends ConsumerState { return; } - final rates = await wallet.fees; + final rates = await manager.fees; Map preparedTx; @@ -116,7 +115,7 @@ class _PaynymDetailsPopupState extends ConsumerState { Navigator.of(context).push( RouteGenerator.getRoute( builder: (_) => ConfirmTransactionView( - walletId: wallet.walletId, + walletId: manager.walletId, routeOnSuccessName: PaynymHomeView.routeName, isPaynymNotificationTransaction: true, transactionInfo: { @@ -132,7 +131,7 @@ class _PaynymDetailsPopupState extends ConsumerState { ); }, amount: (preparedTx["amount"] as int) + (preparedTx["fee"] as int), - coin: wallet.coin, + coin: manager.coin, ), ); } @@ -140,8 +139,10 @@ class _PaynymDetailsPopupState extends ConsumerState { @override Widget build(BuildContext context) { - final wallet = ref.watch(walletsChangeNotifierProvider.select( - (value) => value.getManager(widget.walletId).wallet as DogecoinWallet)); + final manager = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManager(widget.walletId))); + + final wallet = manager.wallet as PaynymWalletInterface; return DesktopDialog( maxWidth: MediaQuery.of(context).size.width - 32, diff --git a/lib/pages/paynym/paynym_claim_view.dart b/lib/pages/paynym/paynym_claim_view.dart index f141e04a4..23f9d868e 100644 --- a/lib/pages/paynym/paynym_claim_view.dart +++ b/lib/pages/paynym/paynym_claim_view.dart @@ -9,8 +9,7 @@ import 'package:stackwallet/pages/wallet_view/wallet_view.dart'; import 'package:stackwallet/providers/global/paynym_api_provider.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; -import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; @@ -160,17 +159,18 @@ class _PaynymClaimViewState extends ConsumerState { ).then((value) => shouldCancel = value == true), ); - // get wallet to access paynym calls - final wallet = ref + final manager = ref .read(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .wallet as DogecoinWallet; + .getManager(widget.walletId); + + // get wallet to access paynym calls + final wallet = manager.wallet as PaynymWalletInterface; if (shouldCancel) return; // get payment code final pCode = await wallet.getPaymentCode( - DerivePathTypeExt.primaryFor(wallet.coin)); + DerivePathTypeExt.primaryFor(manager.coin)); if (shouldCancel) return; diff --git a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart index ac33ce475..61db83d7b 100644 --- a/lib/pages/paynym/subwidgets/desktop_paynym_details.dart +++ b/lib/pages/paynym/subwidgets/desktop_paynym_details.dart @@ -12,8 +12,7 @@ import 'package:stackwallet/pages/paynym/dialogs/confirm_paynym_connect_dialog.d import 'package:stackwallet/pages/paynym/subwidgets/paynym_bot.dart'; import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; -import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; @@ -58,10 +57,10 @@ class _PaynymDetailsPopupState extends ConsumerState { ), ); - final wallet = ref - .read(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .wallet as DogecoinWallet; + final manager = + ref.read(walletsChangeNotifierProvider).getManager(widget.walletId); + + final wallet = manager.wallet as PaynymWalletInterface; if (await wallet.hasConnected(widget.accountLite.code)) { canPop = true; @@ -70,7 +69,7 @@ class _PaynymDetailsPopupState extends ConsumerState { return; } - final rates = await wallet.fees; + final rates = await manager.fees; Map preparedTx; @@ -113,7 +112,7 @@ class _PaynymDetailsPopupState extends ConsumerState { maxHeight: double.infinity, maxWidth: 580, child: ConfirmTransactionView( - walletId: wallet.walletId, + walletId: manager.walletId, isPaynymNotificationTransaction: true, transactionInfo: { "hex": preparedTx["hex"], @@ -142,7 +141,7 @@ class _PaynymDetailsPopupState extends ConsumerState { ); }, amount: (preparedTx["amount"] as int) + (preparedTx["fee"] as int), - coin: wallet.coin, + coin: manager.coin, ), ); } @@ -154,10 +153,11 @@ class _PaynymDetailsPopupState extends ConsumerState { @override Widget build(BuildContext context) { - final wallet = ref - .watch(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .wallet as DogecoinWallet; + final manager = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManager(widget.walletId))); + + final wallet = manager.wallet as PaynymWalletInterface; + return RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: Column( diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 8f36ce596..adc7a2e9c 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -12,10 +12,9 @@ import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart'; import 'package:stackwallet/route_generator.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; -import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart'; import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; @@ -92,7 +91,7 @@ class _ConfirmTransactionViewState try { String txid; if (widget.isPaynymNotificationTransaction) { - txid = await (manager.wallet as DogecoinWallet) + txid = await (manager.wallet as PaynymWalletInterface) .broadcastNotificationTx(preparedTx: transactionInfo); } else if (widget.isPaynymTransaction) { // diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart index c94b61550..8b8a65b58 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -19,10 +19,10 @@ import 'package:stackwallet/providers/global/paynym_api_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/ui/transaction_filter_provider.dart'; import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; -import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/services/coins/firo/firo_wallet.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/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; @@ -209,14 +209,13 @@ class _DesktopWalletViewState extends ConsumerState { ), ); - // todo make generic and not doge specific - final wallet = (ref - .read(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .wallet as DogecoinWallet); + final manager = + ref.read(walletsChangeNotifierProvider).getManager(widget.walletId); + + final wallet = manager.wallet as PaynymWalletInterface; final code = - await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(wallet.coin)); + await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(manager.coin)); final account = await ref.read(paynymAPIProvider).nym(code.toString()); diff --git a/lib/widgets/custom_buttons/paynym_follow_toggle_button.dart b/lib/widgets/custom_buttons/paynym_follow_toggle_button.dart index a93a4510c..5591a5ff3 100644 --- a/lib/widgets/custom_buttons/paynym_follow_toggle_button.dart +++ b/lib/widgets/custom_buttons/paynym_follow_toggle_button.dart @@ -9,8 +9,7 @@ import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/providers/global/paynym_api_provider.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; -import 'package:stackwallet/services/coins/coin_paynym_extension.dart'; -import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; @@ -59,17 +58,18 @@ class _PaynymFollowToggleButtonState ), ); - final wallet = ref - .read(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .wallet as DogecoinWallet; + final manager = + ref.read(walletsChangeNotifierProvider).getManager(widget.walletId); + + // get wallet to access paynym calls + final wallet = manager.wallet as PaynymWalletInterface; final followedAccount = await ref .read(paynymAPIProvider) .nym(widget.paymentCodeStringToFollow, true); final myPCode = - await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(wallet.coin)); + await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(manager.coin)); PaynymResponse token = await ref.read(paynymAPIProvider).token(myPCode.toString()); @@ -160,17 +160,17 @@ class _PaynymFollowToggleButtonState ), ); - final wallet = ref - .read(walletsChangeNotifierProvider) - .getManager(widget.walletId) - .wallet as DogecoinWallet; + final manager = + ref.read(walletsChangeNotifierProvider).getManager(widget.walletId); + + final wallet = manager.wallet as PaynymWalletInterface; final followedAccount = await ref .read(paynymAPIProvider) .nym(widget.paymentCodeStringToFollow, true); final myPCode = - await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(wallet.coin)); + await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(manager.coin)); PaynymResponse token = await ref.read(paynymAPIProvider).token(myPCode.toString()); diff --git a/pubspec.lock b/pubspec.lock index b5b417fd2..073ef8a47 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1408,8 +1408,8 @@ packages: dependency: "direct main" description: path: "." - ref: "93e2687bcc10fc7258c7dab038c363fc9ff8ba5d" - resolved-ref: "93e2687bcc10fc7258c7dab038c363fc9ff8ba5d" + ref: e4b08d2b8965a5ae49bd57f598fa9011dd0c25e9 + resolved-ref: e4b08d2b8965a5ae49bd57f598fa9011dd0c25e9 url: "https://github.com/cypherstack/stack_wallet_backup.git" source: git version: "0.0.1" From 4f2690f88085d69bfa996ce5061cbceb71b0b8c7 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 11:28:58 -0600 Subject: [PATCH 30/55] show available balance label and linter fixes --- lib/pages/send_view/send_view.dart | 78 +++++++++++++----------------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index f687ab9a6..0109a5b53 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -266,9 +266,9 @@ class _SendViewState extends ConsumerState { Decimal? balance; if (ref.read(publicPrivateBalanceStateProvider.state).state == "Private") { - balance = await wallet.availablePrivateBalance(); + balance = wallet.availablePrivateBalance(); } else { - balance = await wallet.availablePublicBalance(); + balance = wallet.availablePublicBalance(); } return Format.localizedStringAsFixed( @@ -442,48 +442,38 @@ class _SendViewState extends ConsumerState { const SizedBox( width: 6, ), - if (coin != Coin.firo && - coin != Coin.firoTestNet) - Expanded( - child: Text( + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( ref.watch(provider.select( (value) => value.walletName)), - style: STextStyles.titleBold12(context), + style: STextStyles.titleBold12(context) + .copyWith(fontSize: 14), overflow: TextOverflow.ellipsis, maxLines: 1, ), - ), - if (coin == Coin.firo || - coin == Coin.firoTestNet) - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - ref.watch(provider.select( - (value) => value.walletName)), - style: - STextStyles.titleBold12(context) - .copyWith(fontSize: 14), - ), - // const SizedBox( - // height: 2, - // ), + // const SizedBox( + // height: 2, + // ), + if (coin == Coin.firo || + coin == Coin.firoTestNet) Text( "${ref.watch(publicPrivateBalanceStateProvider.state).state} balance", style: STextStyles.label(context) .copyWith(fontSize: 10), ), - ], - ), - if (coin != Coin.firo && - coin != Coin.firoTestNet) - const SizedBox( - width: 10, - ), - if (coin == Coin.firo || - coin == Coin.firoTestNet) - const Spacer(), + if (coin != Coin.firo && + coin != Coin.firoTestNet) + Text( + "Available balance", + style: STextStyles.label(context) + .copyWith(fontSize: 10), + ), + ], + ), + const Spacer(), FutureBuilder( // TODO redo this widget now that its not actually a future future: (coin != Coin.firo && @@ -1072,17 +1062,17 @@ class _SendViewState extends ConsumerState { .state) .state == "Private") { - cryptoAmountController.text = - (await firoWallet - .availablePrivateBalance()) - .toStringAsFixed(Constants - .decimalPlacesForCoin(coin)); + cryptoAmountController.text = firoWallet + .availablePrivateBalance() + .toStringAsFixed( + Constants.decimalPlacesForCoin( + coin)); } else { - cryptoAmountController.text = - (await firoWallet - .availablePublicBalance()) - .toStringAsFixed(Constants - .decimalPlacesForCoin(coin)); + cryptoAmountController.text = firoWallet + .availablePublicBalance() + .toStringAsFixed( + Constants.decimalPlacesForCoin( + coin)); } } else { cryptoAmountController.text = (ref From a41c903a96f9bb0b432603fd842b96411304a183 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 11:46:16 -0600 Subject: [PATCH 31/55] mobile paynym send view --- .../paynym/dialogs/paynym_details_popup.dart | 13 +- lib/pages/send_view/send_view.dart | 494 +++++++++--------- lib/route_generator.dart | 13 + 3 files changed, 286 insertions(+), 234 deletions(-) diff --git a/lib/pages/paynym/dialogs/paynym_details_popup.dart b/lib/pages/paynym/dialogs/paynym_details_popup.dart index 840e0e1fc..a2aea2a14 100644 --- a/lib/pages/paynym/dialogs/paynym_details_popup.dart +++ b/lib/pages/paynym/dialogs/paynym_details_popup.dart @@ -12,6 +12,7 @@ import 'package:stackwallet/pages/paynym/dialogs/confirm_paynym_connect_dialog.d import 'package:stackwallet/pages/paynym/paynym_home_view.dart'; import 'package:stackwallet/pages/paynym/subwidgets/paynym_bot.dart'; import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart'; +import 'package:stackwallet/pages/send_view/send_view.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; @@ -25,6 +26,7 @@ import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/loading_indicator.dart'; import 'package:stackwallet/widgets/rounded_container.dart'; +import 'package:tuple/tuple.dart'; class PaynymDetailsPopup extends ConsumerStatefulWidget { const PaynymDetailsPopup({ @@ -44,7 +46,16 @@ class _PaynymDetailsPopupState extends ConsumerState { bool _showInsufficientFundsInfo = false; Future _onSend() async { - // todo send + final manager = + ref.read(walletsChangeNotifierProvider).getManager(widget.walletId); + await Navigator.of(context).pushNamed( + SendView.routeName, + arguments: Tuple3( + manager.walletId, + manager.coin, + widget.accountLite, + ), + ); } Future _onConnectPressed() async { diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 0109a5b53..81cfa9569 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -6,6 +6,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/models/paynym/paynym_account_lite.dart'; import 'package:stackwallet/models/send_view_auto_fill_data.dart'; import 'package:stackwallet/pages/address_book_views/address_book_view.dart'; import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart'; @@ -52,6 +53,7 @@ class SendView extends ConsumerStatefulWidget { this.autoFillData, this.clipboard = const ClipboardWrapper(), this.barcodeScanner = const BarcodeScannerWrapper(), + this.accountLite, }) : super(key: key); static const String routeName = "/sendView"; @@ -61,6 +63,7 @@ class SendView extends ConsumerStatefulWidget { final SendViewAutoFillData? autoFillData; final ClipboardInterface clipboard; final BarcodeScannerInterface barcodeScanner; + final PaynymAccountLite? accountLite; @override ConsumerState createState() => _SendViewState(); @@ -278,6 +281,8 @@ class _SendViewState extends ConsumerState { return null; } + bool get isPaynymSend => widget.accountLite != null; + @override void initState() { ref.refresh(feeSheetSessionCacheProvider); @@ -307,6 +312,11 @@ class _SendViewState extends ConsumerState { _addressToggleFlag = true; } + if (isPaynymSend) { + sendToController.text = widget.accountLite!.nymName; + noteController.text = "PayNym send"; + } + if (coin != Coin.epicCash) { _cryptoFocus.addListener(() { if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) { @@ -599,102 +609,253 @@ class _SendViewState extends ConsumerState { height: 16, ), Text( - "Send to", + isPaynymSend ? "Send to PayNym address" : "Send to", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), const SizedBox( height: 8, ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("sendViewAddressFieldKey"), + if (isPaynymSend) + TextField( + key: const Key("sendViewPaynymAddressFieldKey"), controller: sendToController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - // inputFormatters: [ - // FilteringTextInputFormatter.allow( - // RegExp("[a-zA-Z0-9]{34}")), - // ], - toolbarOptions: const ToolbarOptions( - copy: false, - cut: false, - paste: true, - selectAll: false, + enabled: false, + readOnly: true, + style: STextStyles.fieldLabel(context), + ), + if (!isPaynymSend) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - onChanged: (newValue) { - _address = newValue; - _updatePreviewButtonState( - _address, _amountToSend); - - setState(() { - _addressToggleFlag = newValue.isNotEmpty; - }); - }, - focusNode: _addressFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter ${coin.ticker} address", - _addressFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, + child: TextField( + key: const Key("sendViewAddressFieldKey"), + controller: sendToController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + // inputFormatters: [ + // FilteringTextInputFormatter.allow( + // RegExp("[a-zA-Z0-9]{34}")), + // ], + toolbarOptions: const ToolbarOptions( + copy: false, + cut: false, + paste: true, + selectAll: false, ), - suffixIcon: Padding( - padding: sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - _addressToggleFlag - ? TextFieldIconButton( - key: const Key( - "sendViewClearAddressFieldButtonKey"), - onTap: () { - sendToController.text = ""; - _address = ""; - _updatePreviewButtonState( - _address, _amountToSend); - setState(() { - _addressToggleFlag = false; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - key: const Key( - "sendViewPasteAddressFieldButtonKey"), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - String content = - data.text!.trim(); - if (content - .contains("\n")) { - content = - content.substring( - 0, - content.indexOf( - "\n")); + onChanged: (newValue) { + _address = newValue; + _updatePreviewButtonState( + _address, _amountToSend); + + setState(() { + _addressToggleFlag = newValue.isNotEmpty; + }); + }, + focusNode: _addressFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter ${coin.ticker} address", + _addressFocusNode, + context, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + _addressToggleFlag + ? TextFieldIconButton( + key: const Key( + "sendViewClearAddressFieldButtonKey"), + onTap: () { + sendToController.text = ""; + _address = ""; + _updatePreviewButtonState( + _address, + _amountToSend); + setState(() { + _addressToggleFlag = + false; + }); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + key: const Key( + "sendViewPasteAddressFieldButtonKey"), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard + .kTextPlain); + if (data?.text != null && + data! + .text!.isNotEmpty) { + String content = + data.text!.trim(); + if (content + .contains("\n")) { + content = + content.substring( + 0, + content.indexOf( + "\n")); + } + + sendToController.text = + content; + _address = content; + + _updatePreviewButtonState( + _address, + _amountToSend); + setState(() { + _addressToggleFlag = + sendToController + .text + .isNotEmpty; + }); + } + }, + child: sendToController + .text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewAddressBookButtonKey"), + onTap: () { + Navigator.of(context).pushNamed( + AddressBookView.routeName, + arguments: widget.coin, + ); + }, + child: const AddressBookIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewScanQrButtonKey"), + onTap: () async { + try { + // ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = false; + if (FocusScope.of(context) + .hasFocus) { + FocusScope.of(context) + .unfocus(); + await Future.delayed( + const Duration( + milliseconds: 75)); + } + + final qrResult = + await scanner.scan(); + + // Future.delayed( + // const Duration(seconds: 2), + // () => ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = true, + // ); + + Logging.instance.log( + "qrResult content: ${qrResult.rawContent}", + level: LogLevel.Info); + + final results = + AddressUtils.parseUri( + qrResult.rawContent); + + Logging.instance.log( + "qrResult parsed: $results", + level: LogLevel.Info); + + if (results.isNotEmpty && + results["scheme"] == + coin.uriScheme) { + // auto fill address + _address = + results["address"] ?? + ""; + sendToController.text = + _address!; + + // autofill notes field + if (results["message"] != + null) { + noteController.text = + results["message"]!; + } else if (results[ + "label"] != + null) { + noteController.text = + results["label"]!; } + // autofill amount field + if (results["amount"] != + null) { + final amount = + Decimal.parse(results[ + "amount"]!); + cryptoAmountController + .text = + Format + .localizedStringAsFixed( + value: amount, + locale: ref + .read( + localeServiceChangeNotifierProvider) + .locale, + decimalPlaces: Constants + .decimalPlacesForCoin( + coin), + ); + amount.toString(); + _amountToSend = amount; + } + + _updatePreviewButtonState( + _address, + _amountToSend); + setState(() { + _addressToggleFlag = + sendToController + .text.isNotEmpty; + }); + + // now check for non standard encoded basic address + } else if (ref + .read( + walletsChangeNotifierProvider) + .getManager(walletId) + .validateAddress(qrResult + .rawContent)) { + _address = + qrResult.rawContent; sendToController.text = - content; - _address = content; + _address ?? ""; _updatePreviewButtonState( _address, @@ -705,161 +866,28 @@ class _SendViewState extends ConsumerState { .text.isNotEmpty; }); } - }, - child: sendToController - .text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewAddressBookButtonKey"), - onTap: () { - Navigator.of(context).pushNamed( - AddressBookView.routeName, - arguments: widget.coin, - ); - }, - child: const AddressBookIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewScanQrButtonKey"), - onTap: () async { - try { - // ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = false; - if (FocusScope.of(context) - .hasFocus) { - FocusScope.of(context) - .unfocus(); - await Future.delayed( - const Duration( - milliseconds: 75)); + } on PlatformException catch (e, s) { + // ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = true; + // here we ignore the exception caused by not giving permission + // to use the camera to scan a qr code + Logging.instance.log( + "Failed to get camera permissions while trying to scan qr code in SendView: $e\n$s", + level: LogLevel.Warning); } - - final qrResult = - await scanner.scan(); - - // Future.delayed( - // const Duration(seconds: 2), - // () => ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = true, - // ); - - Logging.instance.log( - "qrResult content: ${qrResult.rawContent}", - level: LogLevel.Info); - - final results = - AddressUtils.parseUri( - qrResult.rawContent); - - Logging.instance.log( - "qrResult parsed: $results", - level: LogLevel.Info); - - if (results.isNotEmpty && - results["scheme"] == - coin.uriScheme) { - // auto fill address - _address = - results["address"] ?? ""; - sendToController.text = - _address!; - - // autofill notes field - if (results["message"] != - null) { - noteController.text = - results["message"]!; - } else if (results["label"] != - null) { - noteController.text = - results["label"]!; - } - - // autofill amount field - if (results["amount"] != - null) { - final amount = - Decimal.parse( - results["amount"]!); - cryptoAmountController - .text = - Format - .localizedStringAsFixed( - value: amount, - locale: ref - .read( - localeServiceChangeNotifierProvider) - .locale, - decimalPlaces: Constants - .decimalPlacesForCoin( - coin), - ); - amount.toString(); - _amountToSend = amount; - } - - _updatePreviewButtonState( - _address, _amountToSend); - setState(() { - _addressToggleFlag = - sendToController - .text.isNotEmpty; - }); - - // now check for non standard encoded basic address - } else if (ref - .read( - walletsChangeNotifierProvider) - .getManager(walletId) - .validateAddress( - qrResult.rawContent)) { - _address = - qrResult.rawContent; - sendToController.text = - _address ?? ""; - - _updatePreviewButtonState( - _address, _amountToSend); - setState(() { - _addressToggleFlag = - sendToController - .text.isNotEmpty; - }); - } - } on PlatformException catch (e, s) { - // ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = true; - // here we ignore the exception caused by not giving permission - // to use the camera to scan a qr code - Logging.instance.log( - "Failed to get camera permissions while trying to scan qr code in SendView: $e\n$s", - level: LogLevel.Warning); - } - }, - child: const QrCodeIcon(), - ) - ], + }, + child: const QrCodeIcon(), + ) + ], + ), ), ), ), ), ), - ), Builder( builder: (_) { final error = _updateInvalidAddressText( diff --git a/lib/route_generator.dart b/lib/route_generator.dart index af88499ba..e83863312 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -6,6 +6,7 @@ import 'package:stackwallet/models/buy/response_objects/quote.dart'; import 'package:stackwallet/models/contact_address_entry.dart'; import 'package:stackwallet/models/exchange/incomplete_exchange.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart'; +import 'package:stackwallet/models/paynym/paynym_account_lite.dart'; import 'package:stackwallet/models/send_view_auto_fill_data.dart'; 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'; @@ -841,6 +842,18 @@ class RouteGenerator { name: settings.name, ), ); + } else if (args is Tuple3) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => SendView( + walletId: args.item1, + coin: args.item2, + accountLite: args.item3, + ), + settings: RouteSettings( + name: settings.name, + ), + ); } return _routeError("${settings.name} invalid args: ${args.toString()}"); From 828c301af7e5cb9fbdbe35f8976b9d9c063f5f4c Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 12:16:38 -0600 Subject: [PATCH 32/55] mobile paynym send flow implemented --- .../send_view/confirm_transaction_view.dart | 14 +- lib/pages/send_view/send_view.dart | 487 +++++++++--------- .../mixins/paynym_wallet_interface.dart | 10 +- 3 files changed, 252 insertions(+), 259 deletions(-) diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index adc7a2e9c..f56911a63 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -4,6 +4,7 @@ import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/models/paynym/paynym_account_lite.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart'; import 'package:stackwallet/pages/send_view/sub_widgets/sending_transaction_dialog.dart'; @@ -94,8 +95,7 @@ class _ConfirmTransactionViewState txid = await (manager.wallet as PaynymWalletInterface) .broadcastNotificationTx(preparedTx: transactionInfo); } else if (widget.isPaynymTransaction) { - // - throw UnimplementedError("paynym send not implemented yet"); + txid = await manager.confirmSend(txData: transactionInfo); } else { final coin = manager.coin; if ((coin == Coin.firo || coin == Coin.firoTestNet) && @@ -333,14 +333,20 @@ class _ConfirmTransactionViewState crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( - "Recipient", + widget.isPaynymTransaction + ? "PayNym recipient" + : "Recipient", style: STextStyles.smallMed12(context), ), const SizedBox( height: 4, ), Text( - "${transactionInfo["address"] ?? "ERROR"}", + widget.isPaynymTransaction + ? (transactionInfo["paynymAccountLite"] + as PaynymAccountLite) + .nymName + : "${transactionInfo["address"] ?? "ERROR"}", style: STextStyles.itemSubtitle12(context), ), ], diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 81cfa9569..c9216bf0e 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:bip47/bip47.dart'; import 'package:cw_core/monero_transaction_priority.dart'; import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; @@ -20,6 +21,7 @@ import 'package:stackwallet/providers/wallet/public_private_balance_state_provid import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; import 'package:stackwallet/services/coins/manager.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/address_utils.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/barcode_scanner_interface.dart'; @@ -162,12 +164,17 @@ class _SendViewState extends ConsumerState { } void _updatePreviewButtonState(String? address, Decimal? amount) { - final isValidAddress = ref - .read(walletsChangeNotifierProvider) - .getManager(walletId) - .validateAddress(address ?? ""); - ref.read(previewTxButtonStateProvider.state).state = - (isValidAddress && amount != null && amount > Decimal.zero); + if (isPaynymSend) { + ref.read(previewTxButtonStateProvider.state).state = + (amount != null && amount > Decimal.zero); + } else { + final isValidAddress = ref + .read(walletsChangeNotifierProvider) + .getManager(walletId) + .validateAddress(address ?? ""); + ref.read(previewTxButtonStateProvider.state).state = + (isValidAddress && amount != null && amount > Decimal.zero); + } } late Future _calculateFeesFuture; @@ -281,6 +288,226 @@ class _SendViewState extends ConsumerState { return null; } + Future _previewTransaction() async { + // wait for keyboard to disappear + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 100), + ); + final manager = + ref.read(walletsChangeNotifierProvider).getManager(walletId); + + // // TODO: remove the need for this!! + // final bool isOwnAddress = + // await manager.isOwnAddress(_address!); + // if (isOwnAddress && coin != Coin.dogecoinTestNet) { + // await showDialog( + // context: context, + // useSafeArea: false, + // barrierDismissible: true, + // builder: (context) { + // return StackDialog( + // title: "Transaction failed", + // message: + // "Sending to self is currently disabled", + // rightButton: TextButton( + // style: Theme.of(context) + // .extension()! + // .getSecondaryEnabledButtonColor( + // context), + // child: Text( + // "Ok", + // style: STextStyles.button( + // context) + // .copyWith( + // color: Theme.of(context) + // .extension< + // StackColors>()! + // .accentColorDark), + // ), + // onPressed: () { + // Navigator.of(context).pop(); + // }, + // ), + // ); + // }, + // ); + // return; + // } + + final amount = Format.decimalAmountToSatoshis(_amountToSend!, coin); + int availableBalance; + if ((coin == Coin.firo || coin == Coin.firoTestNet)) { + if (ref.read(publicPrivateBalanceStateProvider.state).state == + "Private") { + availableBalance = Format.decimalAmountToSatoshis( + (manager.wallet as FiroWallet).availablePrivateBalance(), coin); + } else { + availableBalance = Format.decimalAmountToSatoshis( + (manager.wallet as FiroWallet).availablePublicBalance(), coin); + } + } else { + availableBalance = + Format.decimalAmountToSatoshis(manager.balance.getSpendable(), coin); + } + + // confirm send all + if (amount == availableBalance) { + final bool? shouldSendAll = await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return StackDialog( + title: "Confirm send all", + message: + "You are about to send your entire balance. Would you like to continue?", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Yes", + style: STextStyles.button(context), + ), + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ); + }, + ); + + if (shouldSendAll == null || shouldSendAll == false) { + // cancel preview + return; + } + } + + try { + bool wasCancelled = false; + + unawaited( + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: false, + builder: (context) { + return BuildingTransactionDialog( + onCancel: () { + wasCancelled = true; + + Navigator.of(context).pop(); + }, + ); + }, + ), + ); + + Map txData; + + if (isPaynymSend) { + final wallet = manager.wallet as PaynymWalletInterface; + final paymentCode = PaymentCode.fromPaymentCode( + widget.accountLite!.code, + wallet.networkType, + ); + final feeRate = ref.read(feeRateTypeStateProvider); + txData = await wallet.preparePaymentCodeSend( + paymentCode: paymentCode, + satoshiAmount: amount, + args: {"feeRate": feeRate}, + ); + } else if ((coin == Coin.firo || coin == Coin.firoTestNet) && + ref.read(publicPrivateBalanceStateProvider.state).state != + "Private") { + txData = await (manager.wallet as FiroWallet).prepareSendPublic( + address: _address!, + satoshiAmount: amount, + args: {"feeRate": ref.read(feeRateTypeStateProvider)}, + ); + } else { + txData = await manager.prepareSend( + address: _address!, + satoshiAmount: amount, + args: {"feeRate": ref.read(feeRateTypeStateProvider)}, + ); + } + + if (!wasCancelled && mounted) { + // pop building dialog + Navigator.of(context).pop(); + txData["note"] = noteController.text; + if (isPaynymSend) { + txData["paynymAccountLite"] = widget.accountLite!; + } else { + txData["address"] = _address; + } + + unawaited(Navigator.of(context).push( + RouteGenerator.getRoute( + shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, + builder: (_) => ConfirmTransactionView( + transactionInfo: txData, + walletId: walletId, + isPaynymTransaction: isPaynymSend, + ), + settings: const RouteSettings( + name: ConfirmTransactionView.routeName, + ), + ), + )); + } + } catch (e) { + if (mounted) { + // pop building dialog + Navigator.of(context).pop(); + + unawaited(showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return StackDialog( + title: "Transaction failed", + message: e.toString(), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ); + }, + )); + } + } + } + bool get isPaynymSend => widget.accountLite != null; @override @@ -1532,253 +1759,7 @@ class _SendViewState extends ConsumerState { onPressed: ref .watch(previewTxButtonStateProvider.state) .state - ? () async { - // wait for keyboard to disappear - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); - final manager = ref - .read(walletsChangeNotifierProvider) - .getManager(walletId); - - // // TODO: remove the need for this!! - // final bool isOwnAddress = - // await manager.isOwnAddress(_address!); - // if (isOwnAddress && coin != Coin.dogecoinTestNet) { - // await showDialog( - // context: context, - // useSafeArea: false, - // barrierDismissible: true, - // builder: (context) { - // return StackDialog( - // title: "Transaction failed", - // message: - // "Sending to self is currently disabled", - // rightButton: TextButton( - // style: Theme.of(context) - // .extension()! - // .getSecondaryEnabledButtonColor( - // context), - // child: Text( - // "Ok", - // style: STextStyles.button( - // context) - // .copyWith( - // color: Theme.of(context) - // .extension< - // StackColors>()! - // .accentColorDark), - // ), - // onPressed: () { - // Navigator.of(context).pop(); - // }, - // ), - // ); - // }, - // ); - // return; - // } - - final amount = - Format.decimalAmountToSatoshis( - _amountToSend!, coin); - int availableBalance; - if ((coin == Coin.firo || - coin == Coin.firoTestNet)) { - if (ref - .read( - publicPrivateBalanceStateProvider - .state) - .state == - "Private") { - availableBalance = - Format.decimalAmountToSatoshis( - (manager.wallet as FiroWallet) - .availablePrivateBalance(), - coin); - } else { - availableBalance = - Format.decimalAmountToSatoshis( - (manager.wallet as FiroWallet) - .availablePublicBalance(), - coin); - } - } else { - availableBalance = - Format.decimalAmountToSatoshis( - manager.balance.getSpendable(), - coin); - } - - // confirm send all - if (amount == availableBalance) { - final bool? shouldSendAll = - await showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return StackDialog( - title: "Confirm send all", - message: - "You are about to send your entire balance. Would you like to continue?", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle( - context), - child: Text( - "Cancel", - style: STextStyles.button( - context) - .copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .accentColorDark), - ), - onPressed: () { - Navigator.of(context) - .pop(false); - }, - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle( - context), - child: Text( - "Yes", - style: - STextStyles.button(context), - ), - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - ); - }, - ); - - if (shouldSendAll == null || - shouldSendAll == false) { - // cancel preview - return; - } - } - - try { - bool wasCancelled = false; - - unawaited(showDialog( - context: context, - useSafeArea: false, - barrierDismissible: false, - builder: (context) { - return BuildingTransactionDialog( - onCancel: () { - wasCancelled = true; - - Navigator.of(context).pop(); - }, - ); - }, - )); - - Map txData; - - if ((coin == Coin.firo || - coin == Coin.firoTestNet) && - ref - .read( - publicPrivateBalanceStateProvider - .state) - .state != - "Private") { - txData = - await (manager.wallet as FiroWallet) - .prepareSendPublic( - address: _address!, - satoshiAmount: amount, - args: { - "feeRate": ref - .read(feeRateTypeStateProvider) - }, - ); - } else { - txData = await manager.prepareSend( - address: _address!, - satoshiAmount: amount, - args: { - "feeRate": ref - .read(feeRateTypeStateProvider) - }, - ); - } - - if (!wasCancelled && mounted) { - // pop building dialog - Navigator.of(context).pop(); - txData["note"] = noteController.text; - txData["address"] = _address; - - unawaited(Navigator.of(context).push( - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator - .useMaterialPageRoute, - builder: (_) => - ConfirmTransactionView( - transactionInfo: txData, - walletId: walletId, - ), - settings: const RouteSettings( - name: ConfirmTransactionView - .routeName, - ), - ), - )); - } - } catch (e) { - if (mounted) { - // pop building dialog - Navigator.of(context).pop(); - - unawaited(showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return StackDialog( - title: "Transaction failed", - message: e.toString(), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle( - context), - child: Text( - "Ok", - style: STextStyles.button( - context) - .copyWith( - color: Theme.of( - context) - .extension< - StackColors>()! - .accentColorDark), - ), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ); - }, - )); - } - } - } + ? _previewTransaction : null, style: ref .watch(previewTxButtonStateProvider.state) diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index 1073c3c40..45f33d3be 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -105,6 +105,9 @@ mixin PaynymWalletInterface { _checkChangeAddressForTransactions = checkChangeAddressForTransactions; } + // convenience getter + btc_dart.NetworkType get networkType => _network; + // generate bip32 payment code root Future getRootNode({ required List mnemonic, @@ -147,7 +150,7 @@ mixin PaynymWalletInterface { return Format.uint8listToString(bytes); } - Future>> preparePaymentCodeSend( + Future> preparePaymentCodeSend( {required PaymentCode paymentCode, required int satoshiAmount, Map? args}) async { @@ -163,7 +166,10 @@ mixin PaynymWalletInterface { ); return _prepareSend( - address: sendToAddress.value, satoshiAmount: satoshiAmount); + address: sendToAddress.value, + satoshiAmount: satoshiAmount, + args: args, + ); } } From 4170ca958f3e0ff861fc7d6d5a1c9408bcf62761 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 15:22:39 -0600 Subject: [PATCH 33/55] include paynym receiving addresses when checking for incoming transaction amounts --- lib/services/mixins/electrum_x_parsing.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart index 61bc03beb..23be3d80d 100644 --- a/lib/services/mixins/electrum_x_parsing.dart +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -19,6 +19,7 @@ mixin ElectrumXParsing { Set receivingAddresses = myAddresses .where((e) => e.subType == AddressSubType.receiving || + e.subType == AddressSubType.paynymReceive || e.subType == AddressSubType.paynymNotification) .map((e) => e.value) .toSet(); From 9cc0d74b16b182ddac0775e3f5c8d0945803b311 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 15:25:53 -0600 Subject: [PATCH 34/55] check paynym receiving addresses based on payment code notification tx history --- .../coins/dogecoin/dogecoin_wallet.dart | 2 + .../mixins/paynym_wallet_interface.dart | 64 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index f5a057500..f6b13f586 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -762,6 +762,8 @@ class DogecoinWallet extends CoinServiceAPI GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.3, walletId)); await _checkCurrentReceivingAddressesForTransactions(); + await checkAllCurrentReceivingPaynymAddressesForTransactions(); + final fetchFuture = _refreshTransactions(); final utxosRefreshFuture = _updateUTXOs(); GlobalEventBus.instance diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index 45f33d3be..1d194feb9 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -108,6 +108,70 @@ mixin PaynymWalletInterface { // convenience getter btc_dart.NetworkType get networkType => _network; + Future
currentReceivingPaynymAddress(PaymentCode sender) async { + final address = await _db + .getAddresses(_walletId) + .filter() + .group((q) => q + .subTypeEqualTo(AddressSubType.paynymReceive) + .and() + .otherDataEqualTo(sender.toString())) + .sortByDerivationIndexDesc() + .findFirst(); + + if (address == null) { + final generatedAddress = await _generatePaynymReceivingAddress(sender, 0); + await _db.putAddress(generatedAddress); + return currentReceivingPaynymAddress(sender); + } else { + return address; + } + } + + Future
_generatePaynymReceivingAddress( + PaymentCode sender, + int index, + ) async { + final myPrivateKey = + await deriveNotificationPrivateKey(mnemonic: await _getMnemonic()); + final paymentAddress = PaymentAddress.initWithPrivateKey( + myPrivateKey, + sender, + index, + ); + final pair = paymentAddress.getReceiveAddressKeyPair(); + final address = generatePaynymReceivingAddressFromKeyPair( + pair: pair, + derivationIndex: index, + derivePathType: DerivePathType.bip44, + fromPaymentCode: sender, + ); + return address; + } + + Future checkCurrentPaynymReceivingAddressForTransactions( + PaymentCode sender) async { + final address = await currentReceivingPaynymAddress(sender); + final txCount = await _getTxCount(address: address.value); + if (txCount > 0) { + // generate next address and add to db + final nextAddress = await _generatePaynymReceivingAddress( + sender, + address.derivationIndex + 1, + ); + await _db.putAddress(nextAddress); + } + } + + Future checkAllCurrentReceivingPaynymAddressesForTransactions() async { + final codes = await getAllPaymentCodesFromNotificationTransactions(); + final List> futures = []; + for (final code in codes) { + futures.add(checkCurrentPaynymReceivingAddressForTransactions(code)); + } + await Future.wait(futures); + } + // generate bip32 payment code root Future getRootNode({ required List mnemonic, From 9b74f52ce9258ed4db45e8f2fc56c6255ea171a7 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 26 Jan 2023 16:17:26 -0600 Subject: [PATCH 35/55] add receiving address derivation to secure storage --- .../coins/dogecoin/dogecoin_wallet.dart | 2 + .../mixins/paynym_wallet_interface.dart | 72 ++++++++++++++++--- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index f6b13f586..462f030ce 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -1118,6 +1118,8 @@ class DogecoinWallet extends CoinServiceAPI fetchBuildTxData: fetchBuildTxData, refresh: refresh, checkChangeAddressForTransactions: checkChangeAddressForTransactions, + addDerivation: addDerivation, + addDerivations: addDerivations, ); } diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index 1d194feb9..57a8e534e 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -54,6 +54,18 @@ mixin PaynymWalletInterface { ) _fetchBuildTxData; late final Future Function() _refresh; late final Future Function() _checkChangeAddressForTransactions; + late final Future Function({ + required int chain, + required String address, + required String pubKey, + required String wif, + required DerivePathType derivePathType, + }) _addDerivation; + late final Future Function({ + required int chain, + required DerivePathType derivePathType, + required Map derivationsToAdd, + }) _addDerivations; // initializer void initPaynymWalletInterface({ @@ -87,6 +99,20 @@ mixin PaynymWalletInterface { fetchBuildTxData, required Future Function() refresh, required Future Function() checkChangeAddressForTransactions, + required Future Function({ + required int chain, + required String address, + required String pubKey, + required String wif, + required DerivePathType derivePathType, + }) + addDerivation, + required Future Function({ + required int chain, + required DerivePathType derivePathType, + required Map derivationsToAdd, + }) + addDerivations, }) { _walletId = walletId; _walletName = walletName; @@ -103,6 +129,8 @@ mixin PaynymWalletInterface { _fetchBuildTxData = fetchBuildTxData; _refresh = refresh; _checkChangeAddressForTransactions = checkChangeAddressForTransactions; + _addDerivation = addDerivation; + _addDerivations = addDerivations; } // convenience getter @@ -140,7 +168,7 @@ mixin PaynymWalletInterface { index, ); final pair = paymentAddress.getReceiveAddressKeyPair(); - final address = generatePaynymReceivingAddressFromKeyPair( + final address = await generatePaynymReceivingAddressFromKeyPair( pair: pair, derivationIndex: index, derivePathType: DerivePathType.bip44, @@ -704,7 +732,7 @@ mixin PaynymWalletInterface { i, // index to use ); - if (receivingGapCounter < maxUnusedAddressGap) { + if (outgoingGapCounter < maxUnusedAddressGap) { final pair = paymentAddress.getSendAddressKeyPair(); final address = generatePaynymSendAddressFromKeyPair( pair: pair, @@ -717,15 +745,15 @@ mixin PaynymWalletInterface { final count = await _getTxCount(address: address.value); if (count > 0) { - receivingGapCounter++; + outgoingGapCounter++; } else { - receivingGapCounter = 0; + outgoingGapCounter = 0; } } - if (outgoingGapCounter < maxUnusedAddressGap) { + if (receivingGapCounter < maxUnusedAddressGap) { final pair = paymentAddress.getReceiveAddressKeyPair(); - final address = generatePaynymReceivingAddressFromKeyPair( + final address = await generatePaynymReceivingAddressFromKeyPair( pair: pair, derivationIndex: i, derivePathType: DerivePathType.bip44, @@ -736,9 +764,9 @@ mixin PaynymWalletInterface { final count = await _getTxCount(address: address.value); if (count > 0) { - outgoingGapCounter++; + receivingGapCounter++; } else { - outgoingGapCounter = 0; + receivingGapCounter = 0; } } } @@ -803,12 +831,12 @@ mixin PaynymWalletInterface { return address; } - Address generatePaynymReceivingAddressFromKeyPair({ + Future
generatePaynymReceivingAddressFromKeyPair({ required btc_dart.ECPair pair, required int derivationIndex, required DerivePathType derivePathType, required PaymentCode fromPaymentCode, - }) { + }) async { final data = btc_dart.PaymentData(pubkey: pair.publicKey); String addressString; @@ -867,6 +895,30 @@ mixin PaynymWalletInterface { otherData: fromPaymentCode.toString(), ); + final myCode = await getPaymentCode(DerivePathType.bip44); + + final bip32NetworkType = bip32.NetworkType( + wif: _network.wif, + bip32: bip32.Bip32Type( + public: _network.bip32.public, + private: _network.bip32.private, + ), + ); + + final bip32.BIP32 node = bip32.BIP32.fromPrivateKey( + pair.privateKey!, + myCode.getChain(), + bip32NetworkType, + ); + + await _addDerivation( + chain: 0, + address: address.value, + derivePathType: DerivePathType.bip44, + pubKey: Format.uint8listToString(node.publicKey), + wif: node.toWIF(), + ); + return address; } From b76c9e6c6b11b62238432c3e62d18cf60d3f2414 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 10:04:15 -0600 Subject: [PATCH 36/55] isar inspector active in debug mode and add single transaction fetch function --- lib/db/main_db.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/db/main_db.dart b/lib/db/main_db.dart index 413951e37..931fb6665 100644 --- a/lib/db/main_db.dart +++ b/lib/db/main_db.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; @@ -28,7 +29,7 @@ class MainDB { AddressSchema, ], directory: (await StackFileSystem.applicationIsarDirectory()).path, - inspector: false, + inspector: kDebugMode, name: "wallet_data", ); return true; @@ -73,6 +74,10 @@ class MainDB { await isar.transactions.putAll(transactions); }); + Future getTransaction(String walletId, String txid) async { + return isar.transactions.getByTxidWalletId(txid, walletId); + } + // utxos QueryBuilder getUTXOs(String walletId) => isar.utxos.where().walletIdEqualTo(walletId); From 6d7284d216cc497bc174cba9bcb4dcaa67e73d69 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 10:04:55 -0600 Subject: [PATCH 37/55] do not display incoming notification transaction in ui --- lib/services/coins/dogecoin/dogecoin_wallet.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 462f030ce..142817fbd 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -151,8 +151,16 @@ class DogecoinWallet extends CoinServiceAPI Future> get utxos => db.getUTXOs(walletId).findAll(); @override - Future> get transactions => - db.getTransactions(walletId).sortByTimestampDesc().findAll(); + Future> get transactions => db + .getTransactions(walletId) + .filter() + .not() + .group((q) => q + .subTypeEqualTo(isar_models.TransactionSubType.bip47Notification) + .and() + .typeEqualTo(isar_models.TransactionType.incoming)) + .sortByTimestampDesc() + .findAll(); @override Coin get coin => _coin; From 5159a612713e709e23e9620457ae038984acf3a0 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 10:20:26 -0600 Subject: [PATCH 38/55] block paynym notification utxos --- .../coins/dogecoin/dogecoin_wallet.dart | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 142817fbd..9da638e3d 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -1534,15 +1534,34 @@ class DogecoinWallet extends CoinServiceAPI coin: coin, ); - // todo check here if we should mark as blocked + // fetch stored tx to see if paynym notification tx and block utxo + final storedTx = await db.getTransaction( + walletId, + fetchedUtxoList[i][j]["tx_hash"] as String, + ); + + bool shouldBlock = false; + String? blockReason; + + if (storedTx?.subType == + isar_models.TransactionSubType.bip47Notification && + storedTx?.type == isar_models.TransactionType.incoming) { + // probably safe to assume this is an incoming tx as it is a utxo + // belonging to this wallet. The extra check may be redundant but + // just in case... + + shouldBlock = true; + blockReason = "Incoming paynym notification transaction."; + } + final utxo = isar_models.UTXO( walletId: walletId, txid: txn["txid"] as String, vout: fetchedUtxoList[i][j]["tx_pos"] as int, value: fetchedUtxoList[i][j]["value"] as int, name: "", - isBlocked: false, - blockedReason: null, + isBlocked: shouldBlock, + blockedReason: blockReason, isCoinbase: txn["is_coinbase"] as bool? ?? false, blockHash: txn["blockhash"] as String?, blockHeight: fetchedUtxoList[i][j]["height"] as int?, From 8b071e8774f8c076ff08ab25bbc846b8b57029f8 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 10:21:23 -0600 Subject: [PATCH 39/55] ensure paynym notification address is generated and added to database on restore --- lib/services/coins/dogecoin/dogecoin_wallet.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 9da638e3d..8d675dba9 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -538,6 +538,12 @@ class DogecoinWallet extends CoinServiceAPI ...p2pkhChangeAddressArray, ]); + // generate to ensure notification address is in db before refreshing transactions + await getMyNotificationAddress(DerivePathType.bip44); + + // refresh transactions to pick up any received notification transactions + await _refreshTransactions(); + await _updateUTXOs(); await Future.wait([ From 33660467b114255166de70e1870ba2f13551b894 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 10:22:55 -0600 Subject: [PATCH 40/55] add notification address derivation --- lib/services/mixins/paynym_wallet_interface.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index 57a8e534e..f2d89e04a 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -1014,6 +1014,14 @@ mixin PaynymWalletInterface { otherData: paymentCode.toString(), ); + await _addDerivation( + chain: 0, + address: address.value, + derivePathType: DerivePathType.bip44, + pubKey: Format.uint8listToString(node.publicKey), + wif: node.toWIF(), + ); + await _db.putAddress(address); return address; } From 0d775660c79f3fecae68284b3ca9709c5b6f0fbd Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 10:37:15 -0600 Subject: [PATCH 41/55] update featured paynyms --- lib/utilities/featured_paynyms.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/utilities/featured_paynyms.dart b/lib/utilities/featured_paynyms.dart index 5abff9f2a..2a99bc459 100644 --- a/lib/utilities/featured_paynyms.dart +++ b/lib/utilities/featured_paynyms.dart @@ -1,12 +1,12 @@ abstract class FeaturedPaynyms { - // TODO: replace with actual values - static const String samouraiWalletDevFund = - "PM8TJYkuSdYXJnwDBq8ChfinfXv3srxhQrx3eoEwbSw51wMjdo9JJ2DsycwT3gt3zHQ7cV1grvabMmmf1Btj6fY7tgkgSz9B8MZuR3kjYfgMLMURJCXN"; + // TODO: replace with actual value + // static const String samouraiWalletDevFund = + // "PM8TJYkuSdYXJnwDBq8ChfinfXv3srxhQrx3eoEwbSw51wMjdo9JJ2DsycwT3gt3zHQ7cV1grvabMmmf1Btj6fY7tgkgSz9B8MZuR3kjYfgMLMURJCXN"; static const String stackWallet = - "PM8TJYkuSdYXJnwDBq8ChfinfXv3srxhQrx3eoEwbSw51wMjdo9JJ2DsycwT3gt3zHQ7cV1grvabMmmf1Btj6fY7tgkgSz9B8MZuR3kjYfgMLMURJCXN"; + "PM8TJPdEeH3A77h4xJYQeXPWix2W5yAJrzVQ8ggET1n92utnc57FXCoH94Z2wUSJNfGwkX1kNDTCQLkHecVsjQHGkDE8MUyWE4xWJcc1EDDYCeSSBfLL"; static Map get featured => { "Stack Wallet": stackWallet, - "Samourai Wallet Dev Fund": samouraiWalletDevFund, + // "Samourai Wallet Dev Fund": samouraiWalletDevFund, }; } From 466e2dd2de85bab28f1b9a1db6c5c9f10966601f Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 10:46:38 -0600 Subject: [PATCH 42/55] raw tx electrumx fetch fix --- lib/electrumx_rpc/electrumx.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index c34b760e4..a06cc7365 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -544,6 +544,10 @@ class ElectrumX { verbose, ], ); + if (!verbose) { + return {"rawtx": response["result"] as String}; + } + return Map.from(response["result"] as Map); } catch (e) { rethrow; From ae7163a40f2d50c88b269e9146a2ae2e5e4dd9b0 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 11:19:44 -0600 Subject: [PATCH 43/55] add singel address getter by value --- lib/db/main_db.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/db/main_db.dart b/lib/db/main_db.dart index 931fb6665..53b6397ab 100644 --- a/lib/db/main_db.dart +++ b/lib/db/main_db.dart @@ -48,6 +48,10 @@ class MainDB { await isar.addresses.putAll(addresses); }); + Future getAddress(String walletId, String address) async { + return isar.addresses.getByValueWalletId(address, walletId); + } + Future updateAddress(Address oldAddress, Address newAddress) => isar.writeTxn(() async { newAddress.id = oldAddress.id; From 47acad29a5e3070b125157598db6ee62e7fa8c67 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 11:20:12 -0600 Subject: [PATCH 44/55] isar index violation error fix --- lib/services/mixins/paynym_wallet_interface.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index f2d89e04a..4da65408b 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -306,8 +306,13 @@ mixin PaynymWalletInterface { derivePathType: DerivePathType.bip44, toPaymentCode: pCode, ); - await _db.putAddress(address); + final storedAddress = await _db.getAddress(_walletId, address.value); + if (storedAddress == null) { + await _db.putAddress(address); + } else { + await _db.updateAddress(storedAddress, address); + } final count = await _getTxCount(address: address.value); // return address if unused, otherwise continue to next index if (count == 0) { From 2dd8a5b190ca772bff6592f57f789b9028b3b98a Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 12:22:30 -0600 Subject: [PATCH 45/55] no such transaction exception --- lib/electrumx_rpc/electrumx.dart | 11 ++++++++++- lib/exceptions/electrumx/no_such_transaction.dart | 5 +++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 lib/exceptions/electrumx/no_such_transaction.dart diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index a06cc7365..a2326345d 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -4,6 +4,7 @@ import 'dart:io'; 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/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:uuid/uuid.dart'; @@ -132,7 +133,15 @@ class ElectrumX { final response = await _rpcClient!.request(jsonRequestString); if (response["error"] != null) { - throw Exception("JSONRPC response error: $response"); + if (response["error"] + .toString() + .contains("No such mempool or blockchain transaction")) { + throw NoSuchTransactionException( + "No such mempool or blockchain transaction: ${args.first}"); + } + + throw Exception( + "JSONRPC response \ncommand: $command \nargs: $args \nerror: $response"); } currentFailoverIndex = -1; diff --git a/lib/exceptions/electrumx/no_such_transaction.dart b/lib/exceptions/electrumx/no_such_transaction.dart new file mode 100644 index 000000000..a2bea262b --- /dev/null +++ b/lib/exceptions/electrumx/no_such_transaction.dart @@ -0,0 +1,5 @@ +import 'package:stackwallet/exceptions/sw_exception.dart'; + +class NoSuchTransactionException extends SWException { + NoSuchTransactionException(super.message); +} From 451edbfc6741531912c2c9fad6c9b96884fa5b1a Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 12:49:25 -0600 Subject: [PATCH 46/55] handle dropped mempool/blockchain transactions --- lib/electrumx_rpc/electrumx.dart | 4 +++- .../electrumx/no_such_transaction.dart | 4 +++- .../coins/dogecoin/dogecoin_wallet.dart | 8 +++++++ lib/services/notifications_service.dart | 5 ++++- .../transaction_notification_tracker.dart | 21 +++++++++++++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/electrumx_rpc/electrumx.dart b/lib/electrumx_rpc/electrumx.dart index a2326345d..6667c3de5 100644 --- a/lib/electrumx_rpc/electrumx.dart +++ b/lib/electrumx_rpc/electrumx.dart @@ -137,7 +137,9 @@ class ElectrumX { .toString() .contains("No such mempool or blockchain transaction")) { throw NoSuchTransactionException( - "No such mempool or blockchain transaction: ${args.first}"); + "No such mempool or blockchain transaction", + args.first.toString(), + ); } throw Exception( diff --git a/lib/exceptions/electrumx/no_such_transaction.dart b/lib/exceptions/electrumx/no_such_transaction.dart index a2bea262b..0c7bedeae 100644 --- a/lib/exceptions/electrumx/no_such_transaction.dart +++ b/lib/exceptions/electrumx/no_such_transaction.dart @@ -1,5 +1,7 @@ import 'package:stackwallet/exceptions/sw_exception.dart'; class NoSuchTransactionException extends SWException { - NoSuchTransactionException(super.message); + final String txid; + + NoSuchTransactionException(super.message, this.txid); } diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 8d675dba9..073d050c9 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -14,6 +14,7 @@ import 'package:isar/isar.dart'; import 'package:stackwallet/db/main_db.dart'; import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart'; +import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models; import 'package:stackwallet/models/paymint/fee_object_model.dart'; @@ -611,6 +612,13 @@ class DogecoinWallet extends CoinServiceAPI } } return needsRefresh; + } on NoSuchTransactionException catch (e) { + // TODO: move direct transactions elsewhere + await db.isar.writeTxn(() async { + await db.isar.transactions.deleteByTxidWalletId(e.txid, walletId); + }); + await txTracker.deleteTransaction(e.txid); + return true; } catch (e, s) { Logging.instance.log( "Exception caught in refreshIfThereIsNewData: $e\n$s", diff --git a/lib/services/notifications_service.dart b/lib/services/notifications_service.dart index 2368adeab..2bfe0e12f 100644 --- a/lib/services/notifications_service.dart +++ b/lib/services/notifications_service.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart'; +import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; import 'package:stackwallet/hive/db.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart'; import 'package:stackwallet/models/notification_model.dart'; @@ -169,12 +170,14 @@ class NotificationsService extends ChangeNotifier { } // replaces the current notification with the updated one - add(updatedNotification, true); + await add(updatedNotification, true); } } else { // TODO: check non electrumx coins } } + } on NoSuchTransactionException catch (e, s) { + await _deleteWatchedTxNotification(notification); } catch (e, s) { Logging.instance.log("$e $s", level: LogLevel.Error); } diff --git a/lib/services/transaction_notification_tracker.dart b/lib/services/transaction_notification_tracker.dart index 696465e85..6a2cce2c7 100644 --- a/lib/services/transaction_notification_tracker.dart +++ b/lib/services/transaction_notification_tracker.dart @@ -54,4 +54,25 @@ class TransactionNotificationTracker { key: "notifiedConfirmedTransactions", value: notifiedConfirmedTransactions); } + + Future deleteTransaction(String txid) async { + final notifiedPendingTransactions = DB.instance.get( + boxName: walletId, key: "notifiedPendingTransactions") as Map? ?? + {}; + final notifiedConfirmedTransactions = DB.instance.get( + boxName: walletId, key: "notifiedConfirmedTransactions") as Map? ?? + {}; + + notifiedPendingTransactions.remove(txid); + notifiedConfirmedTransactions.remove(txid); + + await DB.instance.put( + boxName: walletId, + key: "notifiedConfirmedTransactions", + value: notifiedConfirmedTransactions); + await DB.instance.put( + boxName: walletId, + key: "notifiedPendingTransactions", + value: notifiedPendingTransactions); + } } From 04854582ae786c1f23de9372b3df356420db438d Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 13:09:58 -0600 Subject: [PATCH 47/55] desktop first start MainDB load fix --- lib/main.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8296d739a..2a8335110 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -254,6 +254,7 @@ class _MaterialAppWithThemeState extends ConsumerState _desktopHasPassword = await ref.read(storageCryptoHandlerProvider).hasPassword(); } + await MainDB.instance.initMainDB(); } Future load() async { @@ -267,8 +268,6 @@ class _MaterialAppWithThemeState extends ConsumerState await loadShared(); } - await MainDB.instance.initMainDB(); - _notificationsService = ref.read(notificationsProvider); _nodeService = ref.read(nodeServiceChangeNotifierProvider); _tradesService = ref.read(tradesServiceProvider); From c8783bb032fb0bf909c9422375a0b2e34132db58 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 13:10:35 -0600 Subject: [PATCH 48/55] ignore duplicate unblinded codes --- lib/services/mixins/paynym_wallet_interface.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index 4da65408b..a3b44951f 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -702,7 +702,10 @@ mixin PaynymWalletInterface { transaction: tx, myNotificationAddress: myAddress, ); - if (unBlinded != null) { + if (unBlinded != null && + unBlindedList + .where((e) => e.toString() == unBlinded.toString()) + .isEmpty) { unBlindedList.add(unBlinded); } } From 6094a767d743f28f35461f6f5ac6173aadee1568 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 14:10:23 -0600 Subject: [PATCH 49/55] desktop rescanning navigation fix --- .../sub_widgets/rescanning_dialog.dart | 67 ++++++++++++------- .../wallet_network_settings_view.dart | 12 ++-- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/rescanning_dialog.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/rescanning_dialog.dart index da39b1017..0435d023b 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/rescanning_dialog.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/rescanning_dialog.dart @@ -2,6 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/theme/stack_colors.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/stack_dialog.dart'; class RescanningDialog extends StatefulWidget { @@ -21,9 +24,12 @@ class _RescanningDialogState extends State late AnimationController? _spinController; late Animation _spinAnimation; + late final bool isDesktop; + // late final VoidCallback onCancel; @override void initState() { + isDesktop = Util.isDesktop; // onCancel = widget.onCancel; _spinController = AnimationController( @@ -53,33 +59,42 @@ class _RescanningDialogState extends State onWillPop: () async { return false; }, - child: StackDialog( - title: "Rescanning blockchain", - message: "This may take a while. Please do not exit this screen.", - icon: RotationTransition( - turns: _spinAnimation, - child: SvgPicture.asset( - Assets.svg.arrowRotate3, - width: 24, - height: 24, - color: Theme.of(context).extension()!.accentColorDark, - ), + child: ConditionalParent( + condition: isDesktop, + builder: (child) => DesktopDialog( + maxHeight: 200, + maxWidth: 500, + child: child, + ), + child: StackDialog( + title: "Rescanning blockchain", + message: "This may take a while. Please do not exit this screen.", + icon: RotationTransition( + turns: _spinAnimation, + child: SvgPicture.asset( + Assets.svg.arrowRotate3, + width: 24, + height: 24, + color: + Theme.of(context).extension()!.accentColorDark, + ), + ), + // rightButton: TextButton( + // style: Theme.of(context).textButtonTheme.style?.copyWith( + // backgroundColor: MaterialStateProperty.all( + // CFColors.buttonGray, + // ), + // ), + // child: Text( + // "Cancel", + // style: STextStyles.itemSubtitle12(context), + // ), + // onPressed: () { + // Navigator.of(context).pop(); + // onCancel.call(); + // }, + // ), ), - // rightButton: TextButton( - // style: Theme.of(context).textButtonTheme.style?.copyWith( - // backgroundColor: MaterialStateProperty.all( - // CFColors.buttonGray, - // ), - // ), - // child: Text( - // "Cancel", - // style: STextStyles.itemSubtitle12(context), - // ), - // onPressed: () { - // Navigator.of(context).pop(); - // onCancel.call(); - // }, - // ), ), ); } 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 cc552279c..21e0f2d49 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 @@ -76,6 +76,8 @@ class _WalletNetworkSettingsViewState StreamSubscription? _blocksRemainingSubscription; // late StreamSubscription _nodeStatusSubscription; + late final bool isDesktop; + late double _percent; late int _blocksRemaining; bool _advancedIsExpanded = false; @@ -114,7 +116,7 @@ class _WalletNetworkSettingsViewState if (mounted) { // pop rescanning dialog - Navigator.pop(context); + Navigator.of(context, rootNavigator: isDesktop).pop(); // show success await showDialog( @@ -132,7 +134,7 @@ class _WalletNetworkSettingsViewState style: STextStyles.itemSubtitle12(context), ), onPressed: () { - Navigator.of(context).pop(); + Navigator.of(context, rootNavigator: isDesktop).pop(); }, ), ), @@ -143,7 +145,7 @@ class _WalletNetworkSettingsViewState if (mounted) { // pop rescanning dialog - Navigator.pop(context); + Navigator.of(context, rootNavigator: isDesktop).pop(); // show error await showDialog( @@ -162,7 +164,7 @@ class _WalletNetworkSettingsViewState style: STextStyles.itemSubtitle12(context), ), onPressed: () { - Navigator.of(context).pop(); + Navigator.of(context, rootNavigator: isDesktop).pop(); }, ), ), @@ -183,6 +185,7 @@ class _WalletNetworkSettingsViewState @override void initState() { + isDesktop = Util.isDesktop; _currentSyncStatus = widget.initialSyncStatus; // _currentNodeStatus = widget.initialNodeStatus; if (_currentSyncStatus == WalletSyncStatus.synced) { @@ -270,7 +273,6 @@ class _WalletNetworkSettingsViewState @override Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; - final bool isDesktop = Util.isDesktop; final progressLength = isDesktop ? 430.0 From c7446f1946d3e056dcb101870dc2586bc3059594 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 14:43:00 -0600 Subject: [PATCH 50/55] receiving address fix --- .../mixins/paynym_wallet_interface.dart | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index a3b44951f..16d65c6cf 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -140,10 +140,9 @@ mixin PaynymWalletInterface { final address = await _db .getAddresses(_walletId) .filter() - .group((q) => q - .subTypeEqualTo(AddressSubType.paynymReceive) - .and() - .otherDataEqualTo(sender.toString())) + .subTypeEqualTo(AddressSubType.paynymReceive) + .and() + .otherDataEqualTo(sender.toString()) .sortByDerivationIndexDesc() .findFirst(); @@ -160,12 +159,15 @@ mixin PaynymWalletInterface { PaymentCode sender, int index, ) async { - final myPrivateKey = - await deriveNotificationPrivateKey(mnemonic: await _getMnemonic()); + final myPrivateKey = await deriveReceivingPrivateKey( + mnemonic: await _getMnemonic(), + index: index, + ); + final paymentAddress = PaymentAddress.initWithPrivateKey( myPrivateKey, sender, - index, + 0, ); final pair = paymentAddress.getReceiveAddressKeyPair(); final address = await generatePaynymReceivingAddressFromKeyPair( @@ -216,6 +218,15 @@ mixin PaynymWalletInterface { return node.privateKey!; } + Future deriveReceivingPrivateKey({ + required List mnemonic, + required int index, + }) async { + final root = await getRootNode(mnemonic: mnemonic); + final node = root.derivePath(kPaynymDerivePath).derive(index); + return node.privateKey!; + } + /// fetch or generate this wallet's bip47 payment code Future getPaymentCode( DerivePathType derivePathType, @@ -722,8 +733,12 @@ mixin PaynymWalletInterface { const maxCount = 2147483647; assert(maxNumberOfIndexesToCheck < maxCount); - final myPrivateKey = - await deriveNotificationPrivateKey(mnemonic: await _getMnemonic()); + final mnemonic = await _getMnemonic(); + + final mySendPrivateKey = + await deriveNotificationPrivateKey(mnemonic: mnemonic); + final receivingNode = + (await getRootNode(mnemonic: mnemonic)).derivePath(kPaynymDerivePath); List
addresses = []; int receivingGapCounter = 0; @@ -734,14 +749,13 @@ mixin PaynymWalletInterface { (receivingGapCounter < maxUnusedAddressGap || outgoingGapCounter < maxUnusedAddressGap); i++) { - final paymentAddress = PaymentAddress.initWithPrivateKey( - myPrivateKey, - other, - i, // index to use - ); - if (outgoingGapCounter < maxUnusedAddressGap) { - final pair = paymentAddress.getSendAddressKeyPair(); + final paymentAddressSending = PaymentAddress.initWithPrivateKey( + mySendPrivateKey, + other, + i, // index to use + ); + final pair = paymentAddressSending.getSendAddressKeyPair(); final address = generatePaynymSendAddressFromKeyPair( pair: pair, derivationIndex: i, @@ -753,14 +767,20 @@ mixin PaynymWalletInterface { final count = await _getTxCount(address: address.value); if (count > 0) { - outgoingGapCounter++; - } else { outgoingGapCounter = 0; + } else { + outgoingGapCounter++; } } if (receivingGapCounter < maxUnusedAddressGap) { - final pair = paymentAddress.getReceiveAddressKeyPair(); + final myReceivingPrivateKey = receivingNode.derive(i).privateKey!; + final paymentAddressReceiving = PaymentAddress.initWithPrivateKey( + myReceivingPrivateKey, + other, + 0, + ); + final pair = paymentAddressReceiving.getReceiveAddressKeyPair(); final address = await generatePaynymReceivingAddressFromKeyPair( pair: pair, derivationIndex: i, @@ -772,13 +792,13 @@ mixin PaynymWalletInterface { final count = await _getTxCount(address: address.value); if (count > 0) { - receivingGapCounter++; - } else { receivingGapCounter = 0; + } else { + receivingGapCounter++; } } } - await _db.putAddresses(addresses); + await _db.updateOrPutAddresses(addresses); } Address generatePaynymSendAddressFromKeyPair({ From b09b3d0e1f7aec3354a3f01fe922b2407386f54a Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 14:43:38 -0600 Subject: [PATCH 51/55] restore all paynym history function --- lib/services/coins/dogecoin/dogecoin_wallet.dart | 6 ++++++ lib/services/mixins/paynym_wallet_interface.dart | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 073d050c9..2db5ee516 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -545,6 +545,12 @@ class DogecoinWallet extends CoinServiceAPI // refresh transactions to pick up any received notification transactions await _refreshTransactions(); + // restore paynym transactions + await restoreAllHistory( + maxUnusedAddressGap: maxUnusedAddressGap, + maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, + ); + await _updateUTXOs(); await Future.wait([ diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index 16d65c6cf..ee86b3e79 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -724,6 +724,20 @@ mixin PaynymWalletInterface { return unBlindedList; } + Future restoreAllHistory({ + required int maxUnusedAddressGap, + required int maxNumberOfIndexesToCheck, + }) async { + final codes = await getAllPaymentCodesFromNotificationTransactions(); + final List> futures = []; + for (final code in codes) { + futures.add(restoreHistoryWith( + code, maxUnusedAddressGap, maxNumberOfIndexesToCheck)); + } + + await Future.wait(futures); + } + Future restoreHistoryWith( PaymentCode other, int maxUnusedAddressGap, From d59d25cb04fede317e143c4b377c74805fd94b31 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 14:44:00 -0600 Subject: [PATCH 52/55] add convenience function to add or update a list of addresses --- lib/db/main_db.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/db/main_db.dart b/lib/db/main_db.dart index 53b6397ab..90293171c 100644 --- a/lib/db/main_db.dart +++ b/lib/db/main_db.dart @@ -48,6 +48,27 @@ class MainDB { await isar.addresses.putAll(addresses); }); + Future updateOrPutAddresses(List
addresses) async { + await isar.writeTxn(() async { + for (final address in addresses) { + final storedAddress = await isar.addresses + .getByValueWalletId(address.value, address.walletId); + + if (storedAddress == null) { + await isar.addresses.put(address); + } else { + address.id = storedAddress.id; + await storedAddress.transactions.load(); + final txns = storedAddress.transactions.toList(); + await isar.addresses.delete(storedAddress.id); + await isar.addresses.put(address); + address.transactions.addAll(txns); + await address.transactions.save(); + } + } + }); + } + Future getAddress(String walletId, String address) async { return isar.addresses.getByValueWalletId(address, walletId); } From 6c678e577b04d9769b1150bf1f9f8a44f376de6b Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 14:44:53 -0600 Subject: [PATCH 53/55] disable whirlpool button --- .../sub_widgets/wallet_navigation_bar.dart | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart b/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart index c663b8ba0..6f8438770 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart @@ -62,41 +62,41 @@ class _WalletNavigationBarState extends ConsumerState { child: Column( mainAxisSize: MainAxisSize.min, children: [ - AnimatedOpacity( - opacity: scale, - duration: duration, - child: GestureDetector( - onTap: () {}, - child: Container( - padding: const EdgeInsets.all(16), - width: 146, - decoration: BoxDecoration( - color: - Theme.of(context).extension()!.popupBG, - boxShadow: [ - Theme.of(context) - .extension()! - .standardBoxShadow - ], - borderRadius: BorderRadius.circular( - widget.height / 2.0, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Whirlpool", - style: STextStyles.w600_12(context), - ), - ], - ), - ), - ), - ), - const SizedBox( - height: 8, - ), + // AnimatedOpacity( + // opacity: scale, + // duration: duration, + // child: GestureDetector( + // onTap: () {}, + // child: Container( + // padding: const EdgeInsets.all(16), + // width: 146, + // decoration: BoxDecoration( + // color: + // Theme.of(context).extension()!.popupBG, + // boxShadow: [ + // Theme.of(context) + // .extension()! + // .standardBoxShadow + // ], + // borderRadius: BorderRadius.circular( + // widget.height / 2.0, + // ), + // ), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Text( + // "Whirlpool", + // style: STextStyles.w600_12(context), + // ), + // ], + // ), + // ), + // ), + // ), + // const SizedBox( + // height: 8, + // ), AnimatedOpacity( opacity: scale, duration: duration, From 3105c21c3543791751ab4d9fa452673c1d5a1560 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 15:03:03 -0600 Subject: [PATCH 54/55] move paynym interface from doge to btc --- .../coins/bitcoin/bitcoin_wallet.dart | 136 ++++++++++-------- .../coins/dogecoin/dogecoin_wallet.dart | 69 ++++----- 2 files changed, 113 insertions(+), 92 deletions(-) diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart index 82e5f646d..eda84d027 100644 --- a/lib/services/coins/bitcoin/bitcoin_wallet.dart +++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart @@ -13,6 +13,7 @@ import 'package:isar/isar.dart'; import 'package:stackwallet/db/main_db.dart'; import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart'; +import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models; import 'package:stackwallet/models/paymint/fee_object_model.dart'; @@ -23,6 +24,7 @@ import 'package:stackwallet/services/event_bus/events/global/updated_in_backgrou 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/electrum_x_parsing.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; @@ -138,7 +140,7 @@ bip32.BIP32 getBip32RootWrapper(Tuple2 args) { } class BitcoinWallet extends CoinServiceAPI - with WalletCache, WalletDB, ElectrumXParsing { + with WalletCache, WalletDB, ElectrumXParsing, PaynymWalletInterface { static const integrationTestFlag = bool.fromEnvironment("IS_INTEGRATION_TEST"); @@ -178,8 +180,16 @@ class BitcoinWallet extends CoinServiceAPI Future> get utxos => db.getUTXOs(walletId).findAll(); @override - Future> get transactions => - db.getTransactions(walletId).sortByTimestampDesc().findAll(); + Future> get transactions => db + .getTransactions(walletId) + .filter() + .not() + .group((q) => q + .subTypeEqualTo(isar_models.TransactionSubType.bip47Notification) + .and() + .typeEqualTo(isar_models.TransactionType.incoming)) + .sortByTimestampDesc() + .findAll(); @override Future get currentReceivingAddress async => @@ -673,6 +683,18 @@ class BitcoinWallet extends CoinServiceAPI ...p2shChangeAddressArray, ]); + // generate to ensure notification address is in db before refreshing transactions + await getMyNotificationAddress(DerivePathType.bip44); + + // refresh transactions to pick up any received notification transactions + await _refreshTransactions(); + + // restore paynym transactions + await restoreAllHistory( + maxUnusedAddressGap: maxUnusedAddressGap, + maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, + ); + await _updateUTXOs(); await Future.wait([ @@ -737,6 +759,13 @@ class BitcoinWallet extends CoinServiceAPI } } return needsRefresh; + } on NoSuchTransactionException catch (e) { + // TODO: move direct transactions elsewhere + await db.isar.writeTxn(() async { + await db.isar.transactions.deleteByTxidWalletId(e.txid, walletId); + }); + await txTracker.deleteTransaction(e.txid); + return true; } catch (e, s) { Logging.instance.log( "Exception caught in refreshIfThereIsNewData: $e\n$s", @@ -906,6 +935,8 @@ class BitcoinWallet extends CoinServiceAPI GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.3, walletId)); await _checkCurrentReceivingAddressesForTransactions(); + await checkAllCurrentReceivingPaynymAddressesForTransactions(); + final fetchFuture = _refreshTransactions(); final utxosRefreshFuture = _updateUTXOs(); GlobalEventBus.instance @@ -1264,6 +1295,25 @@ class BitcoinWallet extends CoinServiceAPI _secureStore = secureStore; initCache(walletId, coin); initWalletDB(mockableOverride: mockableOverride); + initPaynymWalletInterface( + walletId: walletId, + walletName: walletName, + network: _network, + coin: coin, + db: db, + electrumXClient: electrumXClient, + getMnemonic: () => mnemonic, + getChainHeight: () => chainHeight, + getCurrentChangeAddress: () => currentChangeAddress, + estimateTxFee: estimateTxFee, + prepareSend: prepareSend, + getTxCount: getTxCount, + fetchBuildTxData: fetchBuildTxData, + refresh: refresh, + checkChangeAddressForTransactions: _checkChangeAddressForTransactions, + addDerivation: addDerivation, + addDerivations: addDerivations, + ); } @override @@ -1324,62 +1374,11 @@ class BitcoinWallet extends CoinServiceAPI .getAddresses(walletId) .filter() .not() - .typeEqualTo(isar_models.AddressType.unknown) - .and() - .not() .typeEqualTo(isar_models.AddressType.nonWallet) .and() - .group((q) => q - .subTypeEqualTo(isar_models.AddressSubType.receiving) - .or() - .subTypeEqualTo(isar_models.AddressSubType.change)) + .not() + .subTypeEqualTo(isar_models.AddressSubType.nonWallet) .findAll(); - // final List allAddresses = []; - // final receivingAddresses = DB.instance.get( - // boxName: walletId, key: 'receivingAddressesP2WPKH') as List; - // final changeAddresses = DB.instance.get( - // boxName: walletId, key: 'changeAddressesP2WPKH') as List; - // final receivingAddressesP2PKH = DB.instance.get( - // boxName: walletId, key: 'receivingAddressesP2PKH') as List; - // final changeAddressesP2PKH = - // DB.instance.get(boxName: walletId, key: 'changeAddressesP2PKH') - // as List; - // final receivingAddressesP2SH = DB.instance.get( - // boxName: walletId, key: 'receivingAddressesP2SH') as List; - // final changeAddressesP2SH = - // DB.instance.get(boxName: walletId, key: 'changeAddressesP2SH') - // as List; - // - // for (var i = 0; i < receivingAddresses.length; i++) { - // if (!allAddresses.contains(receivingAddresses[i])) { - // allAddresses.add(receivingAddresses[i] as String); - // } - // } - // for (var i = 0; i < changeAddresses.length; i++) { - // if (!allAddresses.contains(changeAddresses[i])) { - // allAddresses.add(changeAddresses[i] as String); - // } - // } - // for (var i = 0; i < receivingAddressesP2PKH.length; i++) { - // if (!allAddresses.contains(receivingAddressesP2PKH[i])) { - // allAddresses.add(receivingAddressesP2PKH[i] as String); - // } - // } - // for (var i = 0; i < changeAddressesP2PKH.length; i++) { - // if (!allAddresses.contains(changeAddressesP2PKH[i])) { - // allAddresses.add(changeAddressesP2PKH[i] as String); - // } - // } - // for (var i = 0; i < receivingAddressesP2SH.length; i++) { - // if (!allAddresses.contains(receivingAddressesP2SH[i])) { - // allAddresses.add(receivingAddressesP2SH[i] as String); - // } - // } - // for (var i = 0; i < changeAddressesP2SH.length; i++) { - // if (!allAddresses.contains(changeAddressesP2SH[i])) { - // allAddresses.add(changeAddressesP2SH[i] as String); - // } - // } return allAddresses; } @@ -1754,15 +1753,34 @@ class BitcoinWallet extends CoinServiceAPI coin: coin, ); - // todo check here if we should mark as blocked + // fetch stored tx to see if paynym notification tx and block utxo + final storedTx = await db.getTransaction( + walletId, + fetchedUtxoList[i][j]["tx_hash"] as String, + ); + + bool shouldBlock = false; + String? blockReason; + + if (storedTx?.subType == + isar_models.TransactionSubType.bip47Notification && + storedTx?.type == isar_models.TransactionType.incoming) { + // probably safe to assume this is an incoming tx as it is a utxo + // belonging to this wallet. The extra check may be redundant but + // just in case... + + shouldBlock = true; + blockReason = "Incoming paynym notification transaction."; + } + final utxo = isar_models.UTXO( walletId: walletId, txid: txn["txid"] as String, vout: fetchedUtxoList[i][j]["tx_pos"] as int, value: fetchedUtxoList[i][j]["value"] as int, name: "", - isBlocked: false, - blockedReason: null, + isBlocked: shouldBlock, + blockedReason: blockReason, isCoinbase: txn["is_coinbase"] as bool? ?? false, blockHash: txn["blockhash"] as String?, blockHeight: fetchedUtxoList[i][j]["height"] as int?, diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 2db5ee516..90d2764ac 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -25,7 +25,6 @@ import 'package:stackwallet/services/event_bus/events/global/updated_in_backgrou 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/electrum_x_parsing.dart'; -import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/services/mixins/wallet_cache.dart'; import 'package:stackwallet/services/mixins/wallet_db.dart'; import 'package:stackwallet/services/node_service.dart'; @@ -127,7 +126,7 @@ bip32.BIP32 getBip32RootWrapper(Tuple2 args) { } class DogecoinWallet extends CoinServiceAPI - with WalletCache, WalletDB, ElectrumXParsing, PaynymWalletInterface { + with WalletCache, WalletDB, ElectrumXParsing { static const integrationTestFlag = bool.fromEnvironment("IS_INTEGRATION_TEST"); final _prefs = Prefs.instance; @@ -539,17 +538,18 @@ class DogecoinWallet extends CoinServiceAPI ...p2pkhChangeAddressArray, ]); - // generate to ensure notification address is in db before refreshing transactions - await getMyNotificationAddress(DerivePathType.bip44); - - // refresh transactions to pick up any received notification transactions - await _refreshTransactions(); - - // restore paynym transactions - await restoreAllHistory( - maxUnusedAddressGap: maxUnusedAddressGap, - maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, - ); + // paynym stuff + // // generate to ensure notification address is in db before refreshing transactions + // await getMyNotificationAddress(DerivePathType.bip44); + // + // // refresh transactions to pick up any received notification transactions + // await _refreshTransactions(); + // + // // restore paynym transactions + // await restoreAllHistory( + // maxUnusedAddressGap: maxUnusedAddressGap, + // maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, + // ); await _updateUTXOs(); @@ -790,7 +790,8 @@ class DogecoinWallet extends CoinServiceAPI GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.3, walletId)); await _checkCurrentReceivingAddressesForTransactions(); - await checkAllCurrentReceivingPaynymAddressesForTransactions(); + // paynym stuff + // await checkAllCurrentReceivingPaynymAddressesForTransactions(); final fetchFuture = _refreshTransactions(); final utxosRefreshFuture = _updateUTXOs(); @@ -1130,25 +1131,27 @@ class DogecoinWallet extends CoinServiceAPI _secureStore = secureStore; initCache(walletId, coin); initWalletDB(mockableOverride: mockableOverride); - initPaynymWalletInterface( - walletId: walletId, - walletName: walletName, - network: network, - coin: coin, - db: db, - electrumXClient: electrumXClient, - getMnemonic: () => mnemonic, - getChainHeight: () => chainHeight, - getCurrentChangeAddress: () => currentChangeAddress, - estimateTxFee: estimateTxFee, - prepareSend: prepareSend, - getTxCount: getTxCount, - fetchBuildTxData: fetchBuildTxData, - refresh: refresh, - checkChangeAddressForTransactions: checkChangeAddressForTransactions, - addDerivation: addDerivation, - addDerivations: addDerivations, - ); + + // paynym stuff + // initPaynymWalletInterface( + // walletId: walletId, + // walletName: walletName, + // network: network, + // coin: coin, + // db: db, + // electrumXClient: electrumXClient, + // getMnemonic: () => mnemonic, + // getChainHeight: () => chainHeight, + // getCurrentChangeAddress: () => currentChangeAddress, + // estimateTxFee: estimateTxFee, + // prepareSend: prepareSend, + // getTxCount: getTxCount, + // fetchBuildTxData: fetchBuildTxData, + // refresh: refresh, + // checkChangeAddressForTransactions: checkChangeAddressForTransactions, + // addDerivation: addDerivation, + // addDerivations: addDerivations, + // ); } @override From 39856745258bca471e185a768b42531d293d8b0c Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 27 Jan 2023 18:18:58 -0600 Subject: [PATCH 55/55] dirty payment code obfuscation --- .../coins/bitcoin/bitcoin_wallet.dart | 1 + .../mixins/paynym_wallet_interface.dart | 74 ++++++++++++++++--- .../flutter_secure_storage_interface.dart | 18 +++++ 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart index eda84d027..83188746e 100644 --- a/lib/services/coins/bitcoin/bitcoin_wallet.dart +++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart @@ -1302,6 +1302,7 @@ class BitcoinWallet extends CoinServiceAPI coin: coin, db: db, electrumXClient: electrumXClient, + secureStorage: secureStore, getMnemonic: () => mnemonic, getChainHeight: () => chainHeight, getCurrentChangeAddress: () => currentChangeAddress, diff --git a/lib/services/mixins/paynym_wallet_interface.dart b/lib/services/mixins/paynym_wallet_interface.dart index ee86b3e79..3a9642cf0 100644 --- a/lib/services/mixins/paynym_wallet_interface.dart +++ b/lib/services/mixins/paynym_wallet_interface.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:math'; import 'dart:typed_data'; import 'package:bip32/bip32.dart' as bip32; @@ -18,6 +19,7 @@ import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'; import 'package:stackwallet/utilities/bip32_utils.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; +import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:tuple/tuple.dart'; @@ -32,6 +34,7 @@ mixin PaynymWalletInterface { late final Coin _coin; late final MainDB _db; late final ElectrumX _electrumXClient; + late final SecureStorageInterface _secureStorage; // passed in wallet functions late final Future> Function() _getMnemonic; @@ -75,6 +78,7 @@ mixin PaynymWalletInterface { required Coin coin, required MainDB db, required ElectrumX electrumXClient, + required SecureStorageInterface secureStorage, required Future> Function() getMnemonic, required Future Function() getChainHeight, required Future Function() getCurrentChangeAddress, @@ -120,6 +124,7 @@ mixin PaynymWalletInterface { _coin = coin; _db = db; _electrumXClient = electrumXClient; + _secureStorage = secureStorage; _getMnemonic = getMnemonic; _getChainHeight = getChainHeight; _getCurrentChangeAddress = getCurrentChangeAddress; @@ -137,12 +142,15 @@ mixin PaynymWalletInterface { btc_dart.NetworkType get networkType => _network; Future
currentReceivingPaynymAddress(PaymentCode sender) async { + final key = await lookupKey(sender.toString()); final address = await _db .getAddresses(_walletId) .filter() .subTypeEqualTo(AddressSubType.paynymReceive) .and() - .otherDataEqualTo(sender.toString()) + .otherDataEqualTo(key) + .and() + .otherDataIsNotNull() .sortByDerivationIndexDesc() .findFirst(); @@ -232,8 +240,9 @@ mixin PaynymWalletInterface { DerivePathType derivePathType, ) async { final address = await getMyNotificationAddress(derivePathType); + final pCodeString = await paymentCodeStringByKey(address.otherData!); final paymentCode = PaymentCode.fromPaymentCode( - address.otherData!, + pCodeString!, _network, ); return paymentCode; @@ -287,12 +296,15 @@ mixin PaynymWalletInterface { const maxCount = 2147483647; for (int i = startIndex; i < maxCount; i++) { + final key = await lookupKey(pCode.toString()); final address = await _db .getAddresses(_walletId) .filter() .subTypeEqualTo(AddressSubType.paynymSend) .and() - .otherDataEqualTo(pCode.toString()) + .otherDataEqualTo(key) + .and() + .otherDataIsNotNull() .and() .derivationIndexEqualTo(i) .findFirst(); @@ -311,7 +323,7 @@ mixin PaynymWalletInterface { ).getSendAddressKeyPair(); // add address to local db - final address = generatePaynymSendAddressFromKeyPair( + final address = await generatePaynymSendAddressFromKeyPair( pair: pair, derivationIndex: i, derivePathType: DerivePathType.bip44, @@ -770,7 +782,7 @@ mixin PaynymWalletInterface { i, // index to use ); final pair = paymentAddressSending.getSendAddressKeyPair(); - final address = generatePaynymSendAddressFromKeyPair( + final address = await generatePaynymSendAddressFromKeyPair( pair: pair, derivationIndex: i, derivePathType: DerivePathType.bip44, @@ -815,12 +827,12 @@ mixin PaynymWalletInterface { await _db.updateOrPutAddresses(addresses); } - Address generatePaynymSendAddressFromKeyPair({ + Future
generatePaynymSendAddressFromKeyPair({ required btc_dart.ECPair pair, required int derivationIndex, required DerivePathType derivePathType, required PaymentCode toPaymentCode, - }) { + }) async { final data = btc_dart.PaymentData(pubkey: pair.publicKey); String addressString; @@ -867,7 +879,7 @@ mixin PaynymWalletInterface { derivationIndex: derivationIndex, type: AddressType.nonWallet, subType: AddressSubType.paynymSend, - otherData: toPaymentCode.toString(), + otherData: await storeCode(toPaymentCode.toString()), ); return address; @@ -934,7 +946,7 @@ mixin PaynymWalletInterface { derivationIndex: derivationIndex, type: addrType, subType: AddressSubType.paynymReceive, - otherData: fromPaymentCode.toString(), + otherData: await storeCode(fromPaymentCode.toString()), ); final myCode = await getPaymentCode(DerivePathType.bip44); @@ -1053,7 +1065,7 @@ mixin PaynymWalletInterface { derivationIndex: 0, type: type, subType: AddressSubType.paynymNotification, - otherData: paymentCode.toString(), + otherData: await storeCode(paymentCode.toString()), ); await _addDerivation( @@ -1068,4 +1080,46 @@ mixin PaynymWalletInterface { return address; } } + + /// look up a key that corresponds to a payment code string + Future lookupKey(String paymentCodeString) async { + final keys = + (await _secureStorage.keys).where((e) => e.startsWith(kPCodeKeyPrefix)); + for (final key in keys) { + final value = await _secureStorage.read(key: key); + if (value == paymentCodeString) { + return key; + } + } + return null; + } + + /// fetch a payment code string + Future paymentCodeStringByKey(String key) async { + final value = await _secureStorage.read(key: key); + return value; + } + + /// store payment code string and return the generated key used + Future storeCode(String paymentCodeString) async { + final key = _generateKey(); + await _secureStorage.write(key: key, value: paymentCodeString); + return key; + } + + /// generate a new payment code string storage key + String _generateKey() { + final bytes = _randomBytes(24); + return "$kPCodeKeyPrefix${bytes.toHex}"; + } + + // https://github.com/AaronFeickert/stack_wallet_backup/blob/master/lib/secure_storage.dart#L307-L311 + /// Generate cryptographically-secure random bytes + Uint8List _randomBytes(int n) { + final Random rng = Random.secure(); + return Uint8List.fromList( + List.generate(n, (_) => rng.nextInt(0xFF + 1))); + } } + +const String kPCodeKeyPrefix = "pCode_key_"; diff --git a/lib/utilities/flutter_secure_storage_interface.dart b/lib/utilities/flutter_secure_storage_interface.dart index 539f17847..16fa98760 100644 --- a/lib/utilities/flutter_secure_storage_interface.dart +++ b/lib/utilities/flutter_secure_storage_interface.dart @@ -46,6 +46,8 @@ abstract class SecureStorageInterface { MacOsOptions? mOptions, WindowsOptions? wOptions, }); + + Future> get keys; } class DesktopSecureStore { @@ -110,6 +112,10 @@ class DesktopSecureStore { await isar.encryptedStringValues.deleteByKey(key); }); } + + Future> get keys async { + return await isar.encryptedStringValues.where().keyProperty().findAll(); + } } /// all *Options params ignored on desktop @@ -229,6 +235,15 @@ class SecureStorageWrapper implements SecureStorageInterface { ); } } + + @override + Future> get keys async { + if (_isDesktop) { + return (_store as DesktopSecureStore).keys; + } else { + return (await (_store as FlutterSecureStorage).readAll()).keys.toList(); + } + } } // Mock class for testing purposes @@ -305,4 +320,7 @@ class FakeSecureStorage implements SecureStorageInterface { @override dynamic get store => throw UnimplementedError(); + + @override + Future> get keys => Future(() => _store.keys.toList()); }