From c8139007e379c6ccc103f4d3f3095373de75cdbd Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 31 Mar 2023 10:15:42 -0600 Subject: [PATCH] use new transaction nonce property --- .../models/blockchain_data/transaction.dart | 6 ++ .../models/blockchain_data/transaction.g.dart | 2 +- .../coins/bitcoin/bitcoin_wallet.dart | 1 + .../coins/bitcoincash/bitcoincash_wallet.dart | 2 + .../coins/dogecoin/dogecoin_wallet.dart | 1 + .../coins/epiccash/epiccash_wallet.dart | 1 + .../coins/ethereum/ethereum_wallet.dart | 22 ++++++- lib/services/coins/firo/firo_wallet.dart | 5 ++ .../coins/litecoin/litecoin_wallet.dart | 1 + lib/services/coins/monero/monero_wallet.dart | 1 + .../coins/namecoin/namecoin_wallet.dart | 1 + .../coins/particl/particl_wallet.dart | 2 + .../coins/wownero/wownero_wallet.dart | 1 + lib/services/ethereum/ethereum_api.dart | 59 +++++++++++++++++++ .../ethereum/ethereum_token_service.dart | 1 + lib/services/mixins/electrum_x_parsing.dart | 1 + lib/utilities/db_version_migration.dart | 1 + .../services/coins/firo/firo_wallet_test.dart | 1 + test/services/coins/manager_test.dart | 1 + test/widget_tests/transaction_card_test.dart | 4 ++ 20 files changed, 110 insertions(+), 4 deletions(-) diff --git a/lib/models/isar/models/blockchain_data/transaction.dart b/lib/models/isar/models/blockchain_data/transaction.dart index 8fd1b9840..b1dacefba 100644 --- a/lib/models/isar/models/blockchain_data/transaction.dart +++ b/lib/models/isar/models/blockchain_data/transaction.dart @@ -28,6 +28,7 @@ class Transaction { required this.otherData, required this.inputs, required this.outputs, + required this.nonce, }); Tuple2 copyWith({ @@ -46,6 +47,7 @@ class Transaction { String? otherData, List? inputs, List? outputs, + int? nonce, Id? id, Address? address, }) { @@ -64,6 +66,7 @@ class Transaction { isLelantus: isLelantus ?? this.isLelantus, slateId: slateId ?? this.slateId, otherData: otherData ?? this.otherData, + nonce: nonce ?? this.nonce, inputs: inputs ?? this.inputs, outputs: outputs ?? this.outputs) ..id = id ?? this.id, @@ -147,6 +150,7 @@ class Transaction { "isLelantus: $isLelantus, " "slateId: $slateId, " "otherData: $otherData, " + "nonce: $nonce, " "address: ${address.value}, " "inputsLength: ${inputs.length}, " "outputsLength: ${outputs.length}, " @@ -167,6 +171,7 @@ class Transaction { "isLelantus": isLelantus, "slateId": slateId, "otherData": otherData, + "nonce": nonce, "address": address.value?.toJsonString(), "inputs": inputs.map((e) => e.toJsonString()).toList(), "outputs": outputs.map((e) => e.toJsonString()).toList(), @@ -193,6 +198,7 @@ class Transaction { isLelantus: json["isLelantus"] as bool?, slateId: json["slateId"] as String?, otherData: json["otherData"] as String?, + nonce: json["nonce"] as int?, inputs: List.from(json["inputs"] as List) .map((e) => Input.fromJsonString(e)) .toList(), diff --git a/lib/models/isar/models/blockchain_data/transaction.g.dart b/lib/models/isar/models/blockchain_data/transaction.g.dart index 850b503bc..74a5a1652 100644 --- a/lib/models/isar/models/blockchain_data/transaction.g.dart +++ b/lib/models/isar/models/blockchain_data/transaction.g.dart @@ -268,6 +268,7 @@ Transaction _transactionDeserialize( [], isCancelled: reader.readBool(offsets[5]), isLelantus: reader.readBoolOrNull(offsets[6]), + nonce: reader.readLongOrNull(offsets[7]), otherData: reader.readStringOrNull(offsets[8]), outputs: reader.readObjectList( offsets[9], @@ -287,7 +288,6 @@ Transaction _transactionDeserialize( walletId: reader.readString(offsets[15]), ); object.id = id; - object.nonce = reader.readLongOrNull(offsets[7]); return object; } diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart index c622479fb..ce5a76a7b 100644 --- a/lib/services/coins/bitcoin/bitcoin_wallet.dart +++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart @@ -1346,6 +1346,7 @@ class BitcoinWallet extends CoinServiceAPI isLelantus: false, otherData: null, slateId: null, + nonce: null, inputs: [], outputs: [], ); diff --git a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart index 73d44b91e..d07dbc8f0 100644 --- a/lib/services/coins/bitcoincash/bitcoincash_wallet.dart +++ b/lib/services/coins/bitcoincash/bitcoincash_wallet.dart @@ -1261,6 +1261,7 @@ class BitcoinCashWallet extends CoinServiceAPI isLelantus: false, otherData: null, slateId: null, + nonce: null, inputs: [], outputs: [], ); @@ -2326,6 +2327,7 @@ class BitcoinCashWallet extends CoinServiceAPI isLelantus: false, slateId: null, otherData: null, + nonce: null, inputs: inputs, outputs: outputs, ); diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart index 232b47889..3c12aada5 100644 --- a/lib/services/coins/dogecoin/dogecoin_wallet.dart +++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart @@ -1128,6 +1128,7 @@ class DogecoinWallet extends CoinServiceAPI isLelantus: false, otherData: null, slateId: null, + nonce: null, inputs: [], outputs: [], ); diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index a2f8a8713..5808e9fa9 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -1699,6 +1699,7 @@ class EpicCashWallet extends CoinServiceAPI tx["tx_type"] == "TxReceivedCancelled", isLelantus: false, slateId: slateId, + nonce: null, otherData: tx["id"].toString(), inputs: [], outputs: [], diff --git a/lib/services/coins/ethereum/ethereum_wallet.dart b/lib/services/coins/ethereum/ethereum_wallet.dart index 265e39ec2..0afd30bf8 100644 --- a/lib/services/coins/ethereum/ethereum_wallet.dart +++ b/lib/services/coins/ethereum/ethereum_wallet.dart @@ -868,12 +868,26 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB { Future _refreshTransactions() async { String thisAddress = await currentReceivingAddress; - final txsResponse = await EthereumAPI.getEthTransactions(thisAddress); + final response = await EthereumAPI.getEthTransactions(thisAddress); + + if (response.value == null) { + Logging.instance.log( + "Failed to refresh transactions for ${coin.prettyName} $walletName " + "$walletId: ${response.exception}", + level: LogLevel.Warning, + ); + return; + } + + final txsResponse = + await EthereumAPI.getEthTransactionNonces(response.value!); if (txsResponse.value != null) { final allTxs = txsResponse.value!; final List> txnsData = []; - for (final element in allTxs) { + for (final tuple in allTxs) { + final element = tuple.item1; + Amount transactionAmount = element.value; bool isIncoming; @@ -909,6 +923,7 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB { isLelantus: false, slateId: null, otherData: null, + nonce: tuple.item2, inputs: [], outputs: [], ); @@ -966,7 +981,8 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB { } } else { Logging.instance.log( - "Failed to refresh transactions for ${coin.prettyName} $walletName $walletId", + "Failed to refresh transactions with nonces for ${coin.prettyName} " + "$walletName $walletId: ${txsResponse.exception}", level: LogLevel.Warning, ); } diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart index c89ba8114..e973f3092 100644 --- a/lib/services/coins/firo/firo_wallet.dart +++ b/lib/services/coins/firo/firo_wallet.dart @@ -483,6 +483,7 @@ Future> staticProcessRestore( isLelantus: true, slateId: null, otherData: txid, + nonce: null, inputs: element.inputs, outputs: element.outputs, )..address.value = element.address.value; @@ -914,6 +915,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { isLelantus: false, otherData: null, slateId: null, + nonce: null, inputs: [], outputs: [], ); @@ -3070,6 +3072,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { isCancelled: false, isLelantus: true, slateId: null, + nonce: null, otherData: transactionInfo["otherData"] as String?, inputs: [], outputs: [], @@ -3631,6 +3634,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { isLelantus: false, slateId: null, otherData: null, + nonce: null, inputs: ins, outputs: outs, ); @@ -4971,6 +4975,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive { isLelantus: true, slateId: null, otherData: null, + nonce: null, inputs: [], outputs: [], ); diff --git a/lib/services/coins/litecoin/litecoin_wallet.dart b/lib/services/coins/litecoin/litecoin_wallet.dart index e5207b562..7feead18f 100644 --- a/lib/services/coins/litecoin/litecoin_wallet.dart +++ b/lib/services/coins/litecoin/litecoin_wallet.dart @@ -1253,6 +1253,7 @@ class LitecoinWallet extends CoinServiceAPI isLelantus: false, otherData: null, slateId: null, + nonce: null, inputs: [], outputs: [], ); diff --git a/lib/services/coins/monero/monero_wallet.dart b/lib/services/coins/monero/monero_wallet.dart index c8362426c..c0543a36a 100644 --- a/lib/services/coins/monero/monero_wallet.dart +++ b/lib/services/coins/monero/monero_wallet.dart @@ -937,6 +937,7 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB { isLelantus: false, slateId: null, otherData: null, + nonce: null, inputs: [], outputs: [], ); diff --git a/lib/services/coins/namecoin/namecoin_wallet.dart b/lib/services/coins/namecoin/namecoin_wallet.dart index 17007da2c..55076ad66 100644 --- a/lib/services/coins/namecoin/namecoin_wallet.dart +++ b/lib/services/coins/namecoin/namecoin_wallet.dart @@ -1243,6 +1243,7 @@ class NamecoinWallet extends CoinServiceAPI isLelantus: false, otherData: null, slateId: null, + nonce: null, inputs: [], outputs: [], ); diff --git a/lib/services/coins/particl/particl_wallet.dart b/lib/services/coins/particl/particl_wallet.dart index 4a467d119..5550c63d3 100644 --- a/lib/services/coins/particl/particl_wallet.dart +++ b/lib/services/coins/particl/particl_wallet.dart @@ -1172,6 +1172,7 @@ class ParticlWallet extends CoinServiceAPI isLelantus: false, otherData: null, slateId: null, + nonce: null, inputs: [], outputs: [], ); @@ -2367,6 +2368,7 @@ class ParticlWallet extends CoinServiceAPI outputs: outputs, isCancelled: false, isLelantus: false, + nonce: null, slateId: null, otherData: null, ); diff --git a/lib/services/coins/wownero/wownero_wallet.dart b/lib/services/coins/wownero/wownero_wallet.dart index 7eb5ee8b1..6a23276b3 100644 --- a/lib/services/coins/wownero/wownero_wallet.dart +++ b/lib/services/coins/wownero/wownero_wallet.dart @@ -1016,6 +1016,7 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB { isLelantus: false, slateId: null, otherData: null, + nonce: null, inputs: [], outputs: [], ); diff --git a/lib/services/ethereum/ethereum_api.dart b/lib/services/ethereum/ethereum_api.dart index 9c65057f1..dc474340a 100644 --- a/lib/services/ethereum/ethereum_api.dart +++ b/lib/services/ethereum/ethereum_api.dart @@ -11,6 +11,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/utilities/default_nodes.dart'; import 'package:stackwallet/utilities/eth_commons.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:tuple/tuple.dart'; class EthApiException with Exception { EthApiException(this.message); @@ -89,6 +90,64 @@ abstract class EthereumAPI { } } + static Future>>> + getEthTransactionNonces( + List txns, + ) async { + try { + final response = await get( + Uri.parse( + "$stackBaseServer/transactions?transactions=${txns.map((e) => e.hash).join(" ")}", + ), + ); + + if (response.statusCode == 200) { + if (response.body.isNotEmpty) { + final json = jsonDecode(response.body) as Map; + final list = List>.from(json["data"] as List); + + final List> result = []; + + for (final dto in txns) { + final data = + list.firstWhere((e) => e["hash"] == dto.hash, orElse: () => {}); + + final nonce = data["nonce"] as int?; + result.add(Tuple2(dto, nonce)); + } + return EthereumResponse( + result, + null, + ); + } else { + throw EthApiException( + "getEthTransactionNonces($txns) response is empty but status code is " + "${response.statusCode}", + ); + } + } else { + throw EthApiException( + "getEthTransactionNonces($txns) failed with status code: " + "${response.statusCode}", + ); + } + } on EthApiException catch (e) { + return EthereumResponse( + null, + e, + ); + } catch (e, s) { + Logging.instance.log( + "getEthTransactionNonces($txns): $e\n$s", + level: LogLevel.Error, + ); + return EthereumResponse( + null, + EthApiException(e.toString()), + ); + } + } + static Future>> getEthTokenTransactionsByTxids(List txids) async { try { diff --git a/lib/services/ethereum/ethereum_token_service.dart b/lib/services/ethereum/ethereum_token_service.dart index 636f4335a..4cbe18d72 100644 --- a/lib/services/ethereum/ethereum_token_service.dart +++ b/lib/services/ethereum/ethereum_token_service.dart @@ -447,6 +447,7 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache { isCancelled: false, isLelantus: false, slateId: null, + nonce: tuple.item2.nonce, otherData: tuple.item1.address, inputs: [], outputs: [], diff --git a/lib/services/mixins/electrum_x_parsing.dart b/lib/services/mixins/electrum_x_parsing.dart index 5432ea496..76734bf08 100644 --- a/lib/services/mixins/electrum_x_parsing.dart +++ b/lib/services/mixins/electrum_x_parsing.dart @@ -231,6 +231,7 @@ mixin ElectrumXParsing { isLelantus: false, slateId: null, otherData: null, + nonce: null, inputs: ins, outputs: outs, ); diff --git a/lib/utilities/db_version_migration.dart b/lib/utilities/db_version_migration.dart index ab893b5f9..ff740a87f 100644 --- a/lib/utilities/db_version_migration.dart +++ b/lib/utilities/db_version_migration.dart @@ -349,6 +349,7 @@ class DbVersionMigrator with WalletDB { isLelantus: false, slateId: tx.slateId, otherData: tx.otherData, + nonce: null, inputs: [], outputs: [], ); diff --git a/test/services/coins/firo/firo_wallet_test.dart b/test/services/coins/firo/firo_wallet_test.dart index 2c25bd711..ea5e4521d 100644 --- a/test/services/coins/firo/firo_wallet_test.dart +++ b/test/services/coins/firo/firo_wallet_test.dart @@ -108,6 +108,7 @@ void main() { isLelantus: null, slateId: t.slateId, otherData: t.otherData, + nonce: null, inputs: [], outputs: [], ), diff --git a/test/services/coins/manager_test.dart b/test/services/coins/manager_test.dart index 265f9f2cd..55ed98753 100644 --- a/test/services/coins/manager_test.dart +++ b/test/services/coins/manager_test.dart @@ -115,6 +115,7 @@ void main() { isLelantus: true, slateId: null, otherData: null, + nonce: null, inputs: [], outputs: [], ); diff --git a/test/widget_tests/transaction_card_test.dart b/test/widget_tests/transaction_card_test.dart index 984ed2baf..959c4e993 100644 --- a/test/widget_tests/transaction_card_test.dart +++ b/test/widget_tests/transaction_card_test.dart @@ -64,6 +64,7 @@ void main() { isLelantus: null, slateId: '', otherData: '', + nonce: null, inputs: [], outputs: [], )..address.value = Address( @@ -169,6 +170,7 @@ void main() { isLelantus: null, slateId: '', otherData: '', + nonce: null, inputs: [], outputs: [], )..address.value = Address( @@ -271,6 +273,7 @@ void main() { isLelantus: null, slateId: '', otherData: '', + nonce: null, inputs: [], outputs: [], )..address.value = Address( @@ -367,6 +370,7 @@ void main() { isLelantus: null, slateId: '', otherData: '', + nonce: null, inputs: [], outputs: [], )..address.value = Address(