Line data Source code
1 : import 'dart:typed_data';
2 : import 'package:walletkit_dart/src/common/logger.dart';
3 : import 'package:walletkit_dart/walletkit_dart.dart';
4 :
5 : base class EtherscanTransaction extends EVMTransaction {
6 1 : const EtherscanTransaction({
7 : required super.hash,
8 : required super.block,
9 : required super.confirmations,
10 : required super.timeMilli,
11 : required super.amount,
12 : required super.fee,
13 : required super.sender,
14 : required super.recipient,
15 : required super.transferMethod,
16 : required super.token,
17 : required super.status,
18 : required super.input,
19 : required super.gasPrice,
20 : super.decodedInput,
21 : required super.gas,
22 : required super.gasUsed,
23 : });
24 :
25 1 : factory EtherscanTransaction.fromJson(
26 : Json json, {
27 : required CoinEntity token,
28 : required String address,
29 : }) {
30 : /// Etherscan V2
31 : if (json
32 : case {
33 2 : 'blockNumber': String block_s,
34 2 : 'timeStamp': String timeStamp_s,
35 2 : 'hash': String hash,
36 2 : 'from': String from,
37 2 : 'to': String to,
38 2 : 'value': String value_s,
39 2 : 'gas': String gas_s,
40 2 : 'gasUsed': String gasUsed_s,
41 2 : 'gasPrice': String gasPrice_s,
42 2 : 'txreceipt_status': String txreceipt_status_s,
43 2 : 'isError': String _,
44 2 : 'input': String input_s,
45 2 : 'functionName': String functionName, // V2 only
46 : }) {
47 1 : final block = block_s.toIntOrNull ?? -1;
48 1 : final confirmations = block_s.toIntOrNull ?? -1;
49 :
50 1 : final timeMilli = timeStamp_s.toIntOrNull ?? -1;
51 1 : final amount = Amount(
52 1 : value: BigInt.tryParse(value_s) ?? BigInt.from(-1),
53 1 : decimals: token.decimals,
54 : );
55 :
56 1 : final fee = Amount(
57 3 : value: gasPrice_s.toBigInt * gasUsed_s.toBigInt,
58 1 : decimals: token.decimals,
59 : );
60 :
61 1 : final gasPrice = Amount(
62 1 : value: gasPrice_s.toBigInt,
63 1 : decimals: token.decimals,
64 : );
65 :
66 : final transferMethod =
67 1 : TransactionTransferMethod.fromAddress(address, to, from);
68 :
69 1 : final input = input_s.hexToBytesWithPrefixOrNull ?? Uint8List(0);
70 :
71 : final contractFunction = switch (functionName) {
72 1 : "" => null,
73 1 : _ => ContractFunction.fromTextSignature(textSignature: functionName)
74 : };
75 :
76 : ContractFunctionWithValues? decodedInput;
77 : if (contractFunction != null) {
78 : try {
79 1 : decodedInput = ContractFunction.decode(
80 : data: input,
81 : function: contractFunction,
82 : );
83 : } catch (e, s) {
84 0 : Logger.logError(e, s: s, hint: "Failed to decode contract function");
85 : }
86 : }
87 :
88 1 : return EtherscanTransaction(
89 : hash: hash,
90 : block: block,
91 : confirmations: confirmations,
92 1 : timeMilli: timeMilli * 1000,
93 : amount: amount,
94 : fee: fee,
95 : gasPrice: gasPrice,
96 1 : gasUsed: gasUsed_s.toInt,
97 : sender: from,
98 1 : gas: gas_s.toInt,
99 : recipient: to,
100 : transferMethod: transferMethod,
101 : token: token,
102 1 : status: ConfirmationStatus.fromReceiptStatus(
103 1 : txreceipt_status_s.toIntOrNull ?? -1,
104 : ),
105 : input: input,
106 : decodedInput: decodedInput,
107 : );
108 : }
109 :
110 : /// Etherscan V1
111 : if (json
112 : case {
113 2 : 'blockNumber': String block_s,
114 2 : 'timeStamp': String timeStamp_s,
115 2 : 'hash': String hash,
116 2 : 'from': String from,
117 2 : 'to': String to,
118 2 : 'value': String value_s,
119 2 : 'gas': String gas_s,
120 2 : 'gasUsed': String gasUsed_s,
121 2 : 'gasPrice': String gasPrice_s,
122 2 : 'txreceipt_status': String txreceipt_status_s,
123 2 : 'isError': String _,
124 2 : 'input': String input_s,
125 : }) {
126 1 : final block = block_s.toIntOrNull ?? -1;
127 1 : final confirmations = block_s.toIntOrNull ?? -1;
128 :
129 1 : final timeMilli = timeStamp_s.toIntOrNull ?? -1;
130 1 : final amount = Amount(
131 1 : value: BigInt.tryParse(value_s) ?? BigInt.from(-1),
132 1 : decimals: token.decimals,
133 : );
134 :
135 1 : final fee = Amount(
136 3 : value: gasPrice_s.toBigInt * gasUsed_s.toBigInt,
137 1 : decimals: token.decimals,
138 : );
139 :
140 1 : final gasPrice = Amount(
141 1 : value: gasPrice_s.toBigInt,
142 1 : decimals: token.decimals,
143 : );
144 :
145 : final transferMethod =
146 1 : TransactionTransferMethod.fromAddress(address, to, from);
147 :
148 1 : final input = input_s.hexToBytesWithPrefixOrNull ?? Uint8List(0);
149 :
150 1 : return EtherscanTransaction(
151 : hash: hash,
152 : block: block,
153 : confirmations: confirmations,
154 1 : timeMilli: timeMilli * 1000,
155 : amount: amount,
156 : fee: fee,
157 : gasPrice: gasPrice,
158 1 : gasUsed: gasUsed_s.toInt,
159 : sender: from,
160 1 : gas: gas_s.toInt,
161 : recipient: to,
162 : transferMethod: transferMethod,
163 : token: token,
164 1 : status: ConfirmationStatus.fromReceiptStatus(
165 1 : txreceipt_status_s.toIntOrNull ?? -1,
166 : ),
167 : input: input,
168 : );
169 : }
170 :
171 0 : throw UnsupportedError("Invalid JSON for EtherscanTransaction");
172 : }
173 :
174 1 : factory EtherscanTransaction.fromJsonErc1155(
175 : Json json, {
176 : required EvmCoinEntity currency,
177 : required String address,
178 : }) {
179 1 : EtherscanTransaction _createTransaction({
180 : required String block_s,
181 : required String timeStamp_s,
182 : required String hash,
183 : required String from,
184 : required String to,
185 : required String gas_s,
186 : required String gasUsed_s,
187 : required String gasPrice_s,
188 : required String contractAddress,
189 : required String? symbol,
190 : required String? name,
191 : required String tokenID_s,
192 : required String input,
193 : String? tokenValue,
194 : }) {
195 1 : final block = block_s.toIntOrNull ?? -1;
196 1 : final confirmations = block_s.toIntOrNull ?? -1;
197 1 : final timeMilli = timeStamp_s.toIntOrNull ?? -1;
198 1 : final token = ERC1155Entity(
199 : name: name ?? "N.Av",
200 : symbol: symbol ?? "N.Av",
201 : contractAddress: contractAddress,
202 1 : chainID: currency.chainID,
203 1 : tokenId: BigInt.tryParse(tokenID_s) ?? BigInt.from(-1),
204 : );
205 1 : final amount = Amount(
206 : value: tokenValue != null
207 0 : ? (BigInt.tryParse(tokenValue) ?? BigInt.from(0))
208 1 : : BigInt.from(0),
209 : decimals: 0,
210 : );
211 1 : final fee = Amount(
212 3 : value: gasPrice_s.toBigInt * gasUsed_s.toBigInt,
213 1 : decimals: currency.decimals,
214 : );
215 1 : final gasPrice = Amount(
216 1 : value: gasPrice_s.toBigInt,
217 1 : decimals: currency.decimals,
218 : );
219 : final transferMethod =
220 1 : TransactionTransferMethod.fromAddress(address, to, from);
221 :
222 1 : return EtherscanTransaction(
223 : hash: hash,
224 : block: block,
225 : confirmations: confirmations,
226 1 : timeMilli: timeMilli * 1000,
227 : amount: amount,
228 : fee: fee,
229 1 : gasUsed: gasUsed_s.toInt,
230 : sender: from,
231 : recipient: to,
232 1 : gas: gas_s.toInt,
233 : gasPrice: gasPrice,
234 : transferMethod: transferMethod,
235 : token: token,
236 1 : status: ConfirmationStatus.fromConfirmations(confirmations),
237 1 : input: input.hexToBytesWithPrefixOrNull ?? Uint8List(0),
238 : );
239 : }
240 :
241 : if (json
242 : case {
243 2 : 'blockNumber': String block_s,
244 2 : 'timeStamp': String timeStamp_s,
245 2 : 'hash': String hash,
246 2 : 'from': String from,
247 2 : 'to': String to,
248 1 : 'tokenValue': String value_s,
249 0 : 'gas': String gas_s,
250 0 : 'gasUsed': String gasUsed_s,
251 0 : 'gasPrice': String gasPrice_s,
252 0 : 'contractAddress': String contractAddress,
253 0 : 'tokenSymbol': String? symbol,
254 0 : 'tokenName': String? name,
255 0 : 'tokenID': String tokenID_s,
256 0 : 'input': String? input,
257 : }) {
258 0 : return _createTransaction(
259 : block_s: block_s,
260 : timeStamp_s: timeStamp_s,
261 : hash: hash,
262 : from: from,
263 : to: to,
264 : gas_s: gas_s,
265 : gasUsed_s: gasUsed_s,
266 : gasPrice_s: gasPrice_s,
267 : contractAddress: contractAddress,
268 : symbol: symbol,
269 : name: name,
270 : tokenID_s: tokenID_s,
271 : input: input ?? "",
272 : tokenValue: value_s,
273 : );
274 : }
275 : if (json
276 : case {
277 2 : 'blockNumber': String block_s,
278 2 : 'timeStamp': String timeStamp_s,
279 2 : 'hash': String hash,
280 2 : 'from': String from,
281 2 : 'to': String to,
282 2 : 'gas': String gas_s,
283 2 : 'gasUsed': String gasUsed_s,
284 2 : 'gasPrice': String gasPrice_s,
285 2 : 'contractAddress': String contractAddress,
286 2 : 'tokenSymbol': String? symbol,
287 2 : 'tokenName': String? name,
288 2 : 'tokenID': String tokenID_s,
289 2 : 'input': String input,
290 : }) {
291 1 : return _createTransaction(
292 : block_s: block_s,
293 : timeStamp_s: timeStamp_s,
294 : hash: hash,
295 : from: from,
296 : to: to,
297 : gas_s: gas_s,
298 : gasUsed_s: gasUsed_s,
299 : gasPrice_s: gasPrice_s,
300 : contractAddress: contractAddress,
301 : symbol: symbol,
302 : name: name,
303 : tokenID_s: tokenID_s,
304 : input: input,
305 : );
306 : }
307 0 : throw UnsupportedError("Invalid JSON for EtherscanTransaction");
308 : }
309 :
310 1 : factory EtherscanTransaction.fromJsonErc20(
311 : Json json, {
312 : required EvmCoinEntity currency,
313 : required String address,
314 : }) {
315 : if (json
316 : case {
317 2 : 'blockNumber': String block_s,
318 2 : 'timeStamp': String timeStamp_s,
319 2 : 'hash': String hash,
320 2 : 'from': String from,
321 2 : 'to': String to,
322 2 : 'value': String value_s,
323 2 : 'gas': String gas_s,
324 2 : 'gasUsed': String gasUsed_s,
325 2 : 'gasPrice': String gasPrice_s,
326 2 : 'input': String input,
327 2 : 'contractAddress': String contractAddress,
328 2 : 'tokenDecimal': String decimals_s,
329 2 : 'tokenSymbol': String symbol,
330 2 : 'tokenName': String name,
331 : }) {
332 1 : final block = block_s.toIntOrNull ?? -1;
333 1 : final confirmations = block_s.toIntOrNull ?? -1;
334 :
335 1 : final timeMilli = timeStamp_s.toIntOrNull ?? -1;
336 :
337 1 : final token = ERC20Entity(
338 : name: name,
339 : symbol: symbol,
340 1 : decimals: decimals_s.toIntOrNull ?? 18,
341 : contractAddress: contractAddress,
342 1 : chainID: currency.chainID,
343 : );
344 :
345 1 : final amount = Amount(
346 1 : value: BigInt.tryParse(value_s) ?? BigInt.from(-1),
347 1 : decimals: token.decimals,
348 : );
349 :
350 1 : final fee = Amount(
351 3 : value: gasPrice_s.toBigInt * gasUsed_s.toBigInt,
352 1 : decimals: currency.decimals,
353 : );
354 :
355 1 : final gasPrice = Amount(
356 1 : value: gasPrice_s.toBigInt,
357 1 : decimals: currency.decimals,
358 : );
359 :
360 : final transferMethod =
361 1 : TransactionTransferMethod.fromAddress(address, to, from);
362 :
363 1 : return EtherscanTransaction(
364 : hash: hash,
365 : block: block,
366 : confirmations: confirmations,
367 1 : timeMilli: timeMilli * 1000,
368 : amount: amount,
369 : fee: fee,
370 1 : gasUsed: gasUsed_s.toInt,
371 : sender: from,
372 : recipient: to,
373 1 : gas: gas_s.toInt,
374 : gasPrice: gasPrice,
375 : transferMethod: transferMethod,
376 : token: token,
377 1 : status: ConfirmationStatus.fromConfirmations(confirmations),
378 2 : input: input.hexToBytesWithPrefixOrNull ?? Uint8List(0),
379 : );
380 : }
381 0 : throw UnsupportedError("Invalid JSON for EtherscanTransaction");
382 : }
383 :
384 1 : factory EtherscanTransaction.fromJsonErc721(
385 : Json json, {
386 : required EvmCoinEntity currency,
387 : required String address,
388 : }) {
389 : if (json
390 : case {
391 2 : 'blockNumber': String block_s,
392 2 : 'timeStamp': String timeStamp_s,
393 2 : 'hash': String hash,
394 2 : 'from': String from,
395 2 : 'to': String to,
396 2 : 'gas': String gas_s,
397 2 : 'gasUsed': String gasUsed_s,
398 2 : 'gasPrice': String gasPrice_s,
399 2 : 'contractAddress': String contractAddress,
400 2 : 'tokenID': String tokenID_s,
401 2 : 'tokenName': String name,
402 2 : 'tokenSymbol': String symbol,
403 2 : 'tokenDecimal': String _,
404 : }) {
405 1 : final block = block_s.toIntOrNull ?? -1;
406 1 : final confirmations = block_s.toIntOrNull ?? -1;
407 :
408 1 : final timeMilli = timeStamp_s.toIntOrNull ?? -1;
409 :
410 1 : final tokenId = BigInt.tryParse(tokenID_s) ?? BigInt.from(-1);
411 1 : final token = ERC721Entity(
412 : name: name,
413 : symbol: symbol,
414 : contractAddress: contractAddress,
415 1 : chainID: currency.chainID,
416 : tokenId: tokenId,
417 : );
418 :
419 1 : final amount = Amount(
420 1 : value: BigInt.zero,
421 : decimals: 0,
422 : );
423 :
424 1 : final fee = Amount(
425 3 : value: gasPrice_s.toBigInt * gasUsed_s.toBigInt,
426 1 : decimals: currency.decimals,
427 : );
428 :
429 1 : final gasPrice = Amount(
430 1 : value: gasPrice_s.toBigInt,
431 1 : decimals: currency.decimals,
432 : );
433 :
434 : final transferMethod =
435 1 : TransactionTransferMethod.fromAddress(address, to, from);
436 :
437 1 : return EtherscanTransaction(
438 : hash: hash,
439 : block: block,
440 : confirmations: confirmations,
441 1 : timeMilli: timeMilli * 1000,
442 : amount: amount,
443 : fee: fee,
444 : sender: from,
445 : gasPrice: gasPrice,
446 1 : gas: gas_s.toInt,
447 1 : gasUsed: gasUsed_s.toInt,
448 : recipient: to,
449 : transferMethod: transferMethod,
450 : token: token,
451 1 : status: ConfirmationStatus.fromConfirmations(confirmations),
452 1 : input: Uint8List(0),
453 : );
454 : }
455 0 : throw UnsupportedError("Invalid JSON for EtherscanTransaction");
456 : }
457 : }
|