mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-15 16:12:16 +00:00
WIP token tx parsing
This commit is contained in:
parent
361d3a8095
commit
e53683ac68
2 changed files with 97 additions and 59 deletions
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue