WIP token tx parsing

This commit is contained in:
julian 2023-03-24 10:11:18 -06:00
parent 361d3a8095
commit e53683ac68
2 changed files with 97 additions and 59 deletions

View file

@ -21,26 +21,33 @@ class EthTokenTxDto {
required this.transactionIndex,
});
EthTokenTxDto.fromMap(Map json)
: address = json['address'] as String,
blockNumber = json['blockNumber'] as int,
logIndex = json['logIndex'] as int,
topics = List<String>.from(json['topics'] as List),
data = json['data'] as String,
articulatedLog = ArticulatedLog.fromJson(json['articulatedLog']),
compressedLog = json['compressedLog'] as String,
transactionHash = json['transactionHash'] as String,
transactionIndex = json['transactionIndex'] as int;
EthTokenTxDto.fromMap(Map<String, dynamic> map)
: address = map['address'] as String,
blockNumber = map['blockNumber'] as int,
logIndex = map['logIndex'] as int,
topics = List<String>.from(map['topics'] as List),
data = map['data'] as String,
articulatedLog = map['articulatedLog'] == null
? null
: ArticulatedLog.fromMap(
Map<String, dynamic>.from(
map['articulatedLog'] as Map,
),
),
compressedLog = map['compressedLog'] as String,
transactionHash = map['transactionHash'] as String,
transactionIndex = map['transactionIndex'] as int;
final String address;
final int blockNumber;
final int logIndex;
final List<String> topics;
final String data;
final ArticulatedLog articulatedLog;
final ArticulatedLog? articulatedLog;
final String compressedLog;
final String transactionHash;
final int transactionIndex;
EthTokenTxDto copyWith({
String? address,
int? blockNumber,
@ -63,19 +70,25 @@ class EthTokenTxDto {
transactionHash: transactionHash ?? this.transactionHash,
transactionIndex: transactionIndex ?? this.transactionIndex,
);
Map<String, dynamic> toJson() {
Map<String, dynamic> toMap() {
final map = <String, dynamic>{};
map['address'] = address;
map['blockNumber'] = blockNumber;
map['logIndex'] = logIndex;
map['topics'] = topics;
map['data'] = data;
map['articulatedLog'] = articulatedLog.toJson();
map['articulatedLog'] = articulatedLog?.toMap();
map['compressedLog'] = compressedLog;
map['transactionHash'] = transactionHash;
map['transactionIndex'] = transactionIndex;
return map;
}
@override
String toString() {
return toMap().toString();
}
}
/// name : "Transfer"
@ -87,9 +100,13 @@ class ArticulatedLog {
required this.inputs,
});
ArticulatedLog.fromJson(dynamic json)
: name = json['name'] as String,
inputs = Inputs.fromJson(json['inputs']);
ArticulatedLog.fromMap(Map<String, dynamic> map)
: name = map['name'] as String,
inputs = Inputs.fromMap(
Map<String, dynamic>.from(
map['inputs'] as Map,
),
);
final String name;
final Inputs inputs;
@ -103,10 +120,10 @@ class ArticulatedLog {
inputs: inputs ?? this.inputs,
);
Map<String, dynamic> toJson() {
Map<String, dynamic> toMap() {
final map = <String, dynamic>{};
map['name'] = name;
map['inputs'] = inputs.toJson();
map['inputs'] = inputs.toMap();
return map;
}
}
@ -122,10 +139,10 @@ class Inputs {
required this.to,
});
Inputs.fromJson(dynamic json)
: amount = json['_amount'] as String,
from = json['_from'] as String,
to = json['_to'] as String;
Inputs.fromMap(Map<String, dynamic> map)
: amount = map['_amount'] as String,
from = map['_from'] as String,
to = map['_to'] as String;
final String amount;
final String from;
@ -142,7 +159,7 @@ class Inputs {
to: to ?? this.to,
);
Map<String, dynamic> toJson() {
Map<String, dynamic> toMap() {
final map = <String, dynamic>{};
map['_amount'] = amount;
map['_from'] = from;

View file

@ -25,6 +25,7 @@ import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/eth_commons.dart';
import 'package:stackwallet/utilities/extensions/extensions.dart';
import 'package:stackwallet/utilities/extensions/impl/contract_abi.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
@ -340,6 +341,9 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
.sortByTimestampDesc()
.findAll();
String _addressFromTopic(String topic) =>
checksumEthereumAddress("0x${topic.substring(topic.length - 40)}");
Future<void> _refreshTransactions() async {
String addressString =
checksumEthereumAddress(await currentReceivingAddress);
@ -382,12 +386,47 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
final List<Tuple2<Transaction, Address?>> txnsData = [];
for (final tuple in data) {
bool isIncoming;
if (checksumEthereumAddress(tuple.item1.articulatedLog.inputs.from) ==
addressString) {
isIncoming = false;
int amount;
String fromAddress, toAddress;
if (tuple.item1.articulatedLog == null) {
if (tuple.item1.topics.length != 3) {
throw Exception("Topics length != 3 for "
"${ethWallet.walletName} ${ethWallet.walletId}: "
"${tuple.item1.toString()}");
}
amount = tuple.item1.data.toBigIntFromHex.toInt();
fromAddress = _addressFromTopic(
tuple.item1.topics[1],
);
toAddress = _addressFromTopic(
tuple.item1.topics[2],
);
} else {
amount = int.parse(
tuple.item1.articulatedLog!.inputs.amount,
);
fromAddress = checksumEthereumAddress(
tuple.item1.articulatedLog!.inputs.from,
);
toAddress = checksumEthereumAddress(
tuple.item1.articulatedLog!.inputs.to,
);
}
bool isIncoming;
bool isSentToSelf = false;
if (fromAddress == addressString) {
isIncoming = false;
if (toAddress == addressString) {
isSentToSelf = true;
}
} else if (toAddress == addressString) {
isIncoming = true;
} else {
throw Exception("Unknown token transaction found for "
"${ethWallet.walletName} ${ethWallet.walletId}: "
"${tuple.item1.toString()}");
}
final txn = Transaction(
@ -396,7 +435,7 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
timestamp: tuple.item2.timestamp,
type: isIncoming ? TransactionType.incoming : TransactionType.outgoing,
subType: TransactionSubType.ethToken,
amount: int.parse(tuple.item1.articulatedLog.inputs.amount),
amount: amount,
fee: tuple.item2.gasUsed * tuple.item2.gasPrice.toInt(),
height: tuple.item1.blockNumber,
isCancelled: false,
@ -410,39 +449,21 @@ class EthTokenWallet extends ChangeNotifier with EthTokenCache {
Address? transactionAddress = await ethWallet.db
.getAddresses(ethWallet.walletId)
.filter()
.valueEqualTo(addressString)
.valueEqualTo(toAddress)
.findFirst();
if (transactionAddress == null) {
if (isIncoming) {
transactionAddress = Address(
walletId: ethWallet.walletId,
value: addressString,
publicKey: [],
derivationIndex: 0,
derivationPath: DerivationPath()..value = "$hdPathEthereum/0",
type: AddressType.ethereum,
subType: AddressSubType.receiving,
);
} else {
final myRcvAddr = await currentReceivingAddress;
final isSentToSelf = myRcvAddr == addressString;
transactionAddress = Address(
walletId: ethWallet.walletId,
value: addressString,
publicKey: [],
derivationIndex: isSentToSelf ? 0 : -1,
derivationPath: isSentToSelf
? (DerivationPath()..value = "$hdPathEthereum/0")
: null,
type: AddressType.ethereum,
subType: isSentToSelf
? AddressSubType.receiving
: AddressSubType.nonWallet,
);
}
}
transactionAddress ??= Address(
walletId: ethWallet.walletId,
value: toAddress,
publicKey: [],
derivationIndex: isSentToSelf ? 0 : -1,
derivationPath: isSentToSelf
? (DerivationPath()..value = "$hdPathEthereum/0")
: null,
type: AddressType.ethereum,
subType:
isSentToSelf ? AddressSubType.receiving : AddressSubType.nonWallet,
);
txnsData.add(Tuple2(txn, transactionAddress));
}