use new transaction nonce property

This commit is contained in:
julian 2023-03-31 10:15:42 -06:00
parent f969179ea6
commit c8139007e3
20 changed files with 110 additions and 4 deletions

View file

@ -28,6 +28,7 @@ class Transaction {
required this.otherData,
required this.inputs,
required this.outputs,
required this.nonce,
});
Tuple2<Transaction, Address?> copyWith({
@ -46,6 +47,7 @@ class Transaction {
String? otherData,
List<Input>? inputs,
List<Output>? 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<String>.from(json["inputs"] as List)
.map((e) => Input.fromJsonString(e))
.toList(),

View file

@ -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<Output>(
offsets[9],
@ -287,7 +288,6 @@ Transaction _transactionDeserialize(
walletId: reader.readString(offsets[15]),
);
object.id = id;
object.nonce = reader.readLongOrNull(offsets[7]);
return object;
}

View file

@ -1346,6 +1346,7 @@ class BitcoinWallet extends CoinServiceAPI
isLelantus: false,
otherData: null,
slateId: null,
nonce: null,
inputs: [],
outputs: [],
);

View file

@ -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,
);

View file

@ -1128,6 +1128,7 @@ class DogecoinWallet extends CoinServiceAPI
isLelantus: false,
otherData: null,
slateId: null,
nonce: null,
inputs: [],
outputs: [],
);

View file

@ -1699,6 +1699,7 @@ class EpicCashWallet extends CoinServiceAPI
tx["tx_type"] == "TxReceivedCancelled",
isLelantus: false,
slateId: slateId,
nonce: null,
otherData: tx["id"].toString(),
inputs: [],
outputs: [],

View file

@ -868,12 +868,26 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
Future<void> _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<Tuple2<Transaction, Address?>> 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,
);
}

View file

@ -483,6 +483,7 @@ Future<Map<dynamic, dynamic>> 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: [],
);

View file

@ -1253,6 +1253,7 @@ class LitecoinWallet extends CoinServiceAPI
isLelantus: false,
otherData: null,
slateId: null,
nonce: null,
inputs: [],
outputs: [],
);

View file

@ -937,6 +937,7 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
isLelantus: false,
slateId: null,
otherData: null,
nonce: null,
inputs: [],
outputs: [],
);

View file

@ -1243,6 +1243,7 @@ class NamecoinWallet extends CoinServiceAPI
isLelantus: false,
otherData: null,
slateId: null,
nonce: null,
inputs: [],
outputs: [],
);

View file

@ -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,
);

View file

@ -1016,6 +1016,7 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
isLelantus: false,
slateId: null,
otherData: null,
nonce: null,
inputs: [],
outputs: [],
);

View file

@ -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<EthereumResponse<List<Tuple2<EthTxDTO, int?>>>>
getEthTransactionNonces(
List<EthTxDTO> 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<Map<String, dynamic>>.from(json["data"] as List);
final List<Tuple2<EthTxDTO, int?>> 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<EthereumResponse<List<EthTokenTxExtraDTO>>>
getEthTokenTransactionsByTxids(List<String> txids) async {
try {

View file

@ -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: [],

View file

@ -231,6 +231,7 @@ mixin ElectrumXParsing {
isLelantus: false,
slateId: null,
otherData: null,
nonce: null,
inputs: ins,
outputs: outs,
);

View file

@ -349,6 +349,7 @@ class DbVersionMigrator with WalletDB {
isLelantus: false,
slateId: tx.slateId,
otherData: tx.otherData,
nonce: null,
inputs: [],
outputs: [],
);

View file

@ -108,6 +108,7 @@ void main() {
isLelantus: null,
slateId: t.slateId,
otherData: t.otherData,
nonce: null,
inputs: [],
outputs: [],
),

View file

@ -115,6 +115,7 @@ void main() {
isLelantus: true,
slateId: null,
otherData: null,
nonce: null,
inputs: [],
outputs: [],
);

View file

@ -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(