dev
dart 212 lines 5.52 KB
Raw
1 import 'package:blockchain_utils/hex/hex.dart';
2 import 'package:cw_core/crypto_currency.dart';
3 import 'package:on_chain/on_chain.dart';
4
5 class TronTRC20TransactionModel extends TronTransactionModel {
6 String? transactionId;
7
8 String? tokenSymbol;
9
10 int? decimals;
11
12 CryptoCurrency get currency => CryptoCurrency(
13 name: tokenSymbol ?? "TRX", title: tokenSymbol ?? "TRX", decimals: decimals ?? 6);
14
15 int? timestamp;
16
17 @override
18 String? from;
19
20 @override
21 String? to;
22
23 String? value;
24
25 @override
26 String get hash => transactionId!;
27
28 @override
29 DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp ?? 0);
30
31 @override
32 BigInt? get amount => BigInt.parse(value ?? '0');
33
34 @override
35 int? get fee => 0;
36
37 TronTRC20TransactionModel({
38 this.transactionId,
39 this.tokenSymbol,
40 this.timestamp,
41 this.from,
42 this.to,
43 this.value,
44 });
45
46 TronTRC20TransactionModel.fromJson(Map<String, dynamic> json) {
47 transactionId = json['transaction_id'];
48 tokenSymbol = json['token_info'] != null ? json['token_info']['symbol'] : null;
49 decimals = json['token_info'] != null ? json['token_info']['decimals'] : null;
50 timestamp = json['block_timestamp'];
51 from = json['from'];
52 to = json['to'];
53 value = json['value'];
54 }
55 }
56
57 class TronTransactionModel {
58 List<Ret>? ret;
59 String? txID;
60 int? blockTimestamp;
61 List<Contract>? contracts;
62
63 /// Getters to extract out the needed/useful information directly from the model params
64 /// Without having to go through extra steps in the methods that use this model.
65 bool get isError {
66 if (ret?.first.contractRet == null) return true;
67
68 return ret?.first.contractRet != "SUCCESS";
69 }
70
71 String get hash => txID!;
72
73 DateTime get date => DateTime.fromMillisecondsSinceEpoch(blockTimestamp ?? 0);
74
75 String? get from => contracts?.first.parameter?.value?.ownerAddress;
76
77 String? get to => contracts?.first.parameter?.value?.receiverAddress;
78
79 BigInt? get amount => contracts?.first.parameter?.value?.txAmount;
80
81 int? get fee => ret?.first.fee;
82
83 String? get contractAddress => contracts?.first.parameter?.value?.contractAddress;
84
85 TronTransactionModel({
86 this.ret,
87 this.txID,
88 this.blockTimestamp,
89 this.contracts,
90 });
91
92 TronTransactionModel.fromJson(Map<String, dynamic> json) {
93 if (json['ret'] != null) {
94 ret = <Ret>[];
95 json['ret'].forEach((v) {
96 ret!.add(Ret.fromJson(v));
97 });
98 }
99 txID = json['txID'];
100 blockTimestamp = json['block_timestamp'];
101 contracts = json['raw_data'] != null
102 ? (json['raw_data']['contract'] as List)
103 .map((e) => Contract.fromJson(e as Map<String, dynamic>))
104 .toList()
105 : null;
106 }
107 }
108
109 class Ret {
110 String? contractRet;
111 int? fee;
112
113 Ret({this.contractRet, this.fee});
114
115 Ret.fromJson(Map<String, dynamic> json) {
116 contractRet = json['contractRet'];
117 fee = json['fee'];
118 }
119 }
120
121 class Contract {
122 Parameter? parameter;
123 String? type;
124
125 Contract({this.parameter, this.type});
126
127 Contract.fromJson(Map<String, dynamic> json) {
128 parameter = json['parameter'] != null ? Parameter.fromJson(json['parameter']) : null;
129 type = json['type'];
130 }
131 }
132
133 class Parameter {
134 Value? value;
135 String? typeUrl;
136
137 Parameter({this.value, this.typeUrl});
138
139 Parameter.fromJson(Map<String, dynamic> json) {
140 value = json['value'] != null ? Value.fromJson(json['value']) : null;
141 typeUrl = json['type_url'];
142 }
143 }
144
145 class Value {
146 String? data;
147 String? ownerAddress;
148 String? contractAddress;
149 int? amount;
150 String? toAddress;
151 String? assetName;
152
153 //Getters to extract address for tron transactions
154 /// If the contract address is null, it returns the toAddress
155 /// If it's not null, it decodes the data field and gets the receiver address.
156 String? get receiverAddress {
157 if (contractAddress == null) return toAddress;
158
159 if (data == null) return null;
160
161 return _decodeAddressFromEncodedDataField(data!);
162 }
163
164 //Getters to extract amount for tron transactions
165 /// If the contract address is null, it returns the amount
166 /// If it's not null, it decodes the data field and gets the tx amount.
167 BigInt? get txAmount {
168 if (contractAddress == null) return BigInt.from(amount ?? 0);
169
170 if (data == null) return null;
171
172 return _decodeAmountInvolvedFromEncodedDataField(data!);
173 }
174
175 Value(
176 {this.data,
177 this.ownerAddress,
178 this.contractAddress,
179 this.amount,
180 this.toAddress,
181 this.assetName});
182
183 Value.fromJson(Map<String, dynamic> json) {
184 data = json['data'];
185 ownerAddress = json['owner_address'];
186 contractAddress = json['contract_address'];
187 amount = json['amount'];
188 toAddress = json['to_address'];
189 assetName = json['asset_name'];
190 }
191
192 /// To get the address from the encoded data field
193 String _decodeAddressFromEncodedDataField(String output) {
194 // To get the receiver address from the encoded params
195 output = output.replaceFirst('0x', '').substring(8);
196 final abiCoder = ABICoder.fromType('address');
197 final decoded = abiCoder.decode(AbiParameter.bytes, hex.decode(output));
198 final tronAddress = TronAddress.fromEthAddress((decoded.result as ETHAddress).toBytes());
199
200 return tronAddress.toString();
201 }
202
203 /// To get the amount from the encoded data field
204 BigInt _decodeAmountInvolvedFromEncodedDataField(String output) {
205 output = output.replaceFirst('0x', '').substring(72);
206 final amountAbiCoder = ABICoder.fromType('uint256');
207 final decodedA = amountAbiCoder.decode(AbiParameter.uint256, hex.decode(output));
208 final amount = decodedA.result as BigInt;
209
210 return amount;
211 }
212 }