Line data Source code
1 : library generic_transaction;
2 :
3 : import 'dart:convert';
4 : import 'dart:typed_data';
5 : import 'package:convert/convert.dart';
6 : import 'package:walletkit_dart/src/common/http_repository.dart';
7 : import 'package:walletkit_dart/src/crypto/utxo/entities/payments/p2h.dart';
8 : import 'package:walletkit_dart/src/crypto/utxo/utils/pubkey_to_address.dart';
9 : import 'package:walletkit_dart/walletkit_dart.dart';
10 :
11 : part '../../crypto/evm/entities/transactions/evm_transaction.dart';
12 : part '../../crypto/utxo/entities/transactions/utxo_transaction.dart';
13 : part '../../crypto/tron/entities/tron_transaction.dart';
14 :
15 : sealed class GenericTransaction implements Comparable<GenericTransaction> {
16 : final String hash;
17 : final int block;
18 : final int confirmations;
19 : final int timeMilli;
20 : final CoinEntity token;
21 : final Amount amount;
22 : final Amount? fee;
23 : final String sender;
24 : final String recipient;
25 : final TransactionTransferMethod transferMethod;
26 : final ConfirmationStatus status;
27 :
28 11 : const GenericTransaction({
29 : required this.hash,
30 : required this.block,
31 : required this.confirmations,
32 : required this.timeMilli,
33 : required this.amount,
34 : required this.fee,
35 : required this.sender,
36 : required this.recipient,
37 : required this.transferMethod,
38 : required this.token,
39 : required this.status,
40 : });
41 :
42 0 : EVMTransaction? get evmTx => this is EVMTransaction ? this as EVMTransaction : null;
43 :
44 12 : BigInt get value => amount.value;
45 :
46 0 : BigInt get totalValue => value + (fee?.value ?? BigInt.zero);
47 :
48 2 : @override
49 4 : String toString() => "Transaction: $hash";
50 :
51 24 : bool get isPending => status == ConfirmationStatus.pending;
52 :
53 0 : bool get isConfirmed => status == ConfirmationStatus.confirmed;
54 :
55 0 : bool get isFailed => status == ConfirmationStatus.failed;
56 :
57 0 : DateTime get dateTime => DateTime.fromMillisecondsSinceEpoch(timeMilli);
58 :
59 7 : @override
60 : int compareTo(GenericTransaction other) {
61 7 : if (isPending) {
62 0 : if (other.isPending) return 0;
63 0 : return -1;
64 : }
65 7 : if (other.isPending) return 1;
66 28 : return -timeMilli.compareTo(other.timeMilli);
67 : }
68 :
69 8 : @override
70 64 : int get hashCode => hash.hashCode ^ token.hashCode ^ block.hashCode;
71 :
72 0 : @override
73 : bool operator ==(Object other) {
74 : if (identical(this, other)) return true;
75 :
76 0 : return other is GenericTransaction &&
77 0 : other.hash == hash &&
78 0 : other.token == token &&
79 0 : other.block == block;
80 : }
81 :
82 : Map<String, dynamic> toJson();
83 :
84 0 : factory GenericTransaction.fromJson(Map json) {
85 : return switch (json) {
86 : {
87 0 : 'hash': String _,
88 0 : 'block': int _,
89 0 : 'confirmations': int _,
90 0 : 'timeMilli': int _,
91 0 : 'amount': Map _,
92 0 : 'fee': Map? _,
93 0 : 'sender': String _,
94 0 : 'recipient': String _,
95 0 : 'transferMethod': int _,
96 0 : 'status': int _,
97 0 : 'token': Map _,
98 0 : 'input': String _,
99 0 : 'decodedInput': Map? _,
100 : } =>
101 0 : EVMTransaction.fromJson(json),
102 : {
103 0 : 'hash': String _,
104 0 : 'block': int _,
105 0 : 'confirmations': int _,
106 0 : 'timeMilli': int _,
107 0 : 'amount': Map _,
108 0 : 'fee': Map? _,
109 0 : 'sender': String _,
110 0 : 'recipient': String _,
111 0 : 'transferMethod': int _,
112 0 : 'status': int _,
113 0 : 'token': Map _,
114 0 : 'id': String _,
115 0 : 'version': int _,
116 0 : 'inputs': JsonList _,
117 0 : 'outputs': JsonList _,
118 : } =>
119 0 : UTXOTransaction.fromJson(json),
120 0 : _ => throw UnimplementedError("Unknown json: $json"),
121 : };
122 : }
123 : }
124 :
125 : enum ConfirmationStatus {
126 : notSubmitted("not_submitted"),
127 :
128 : /// Transaction is not confirmed yet
129 : pending("pending"),
130 :
131 : /// Transaction is confirmed
132 : confirmed("confirmed"),
133 :
134 : /// Transaction is failed
135 : failed("failed");
136 :
137 : /// TODO: When is a transaction failed?
138 9 : static ConfirmationStatus fromConfirmations(int? confirmations) {
139 : if (confirmations == null) return ConfirmationStatus.pending;
140 9 : if (confirmations <= 0) return ConfirmationStatus.pending;
141 :
142 : return ConfirmationStatus.confirmed;
143 : }
144 :
145 1 : static ConfirmationStatus fromReceiptStatus(int status) {
146 1 : if (status == 0) return ConfirmationStatus.failed;
147 1 : if (status == 1) return ConfirmationStatus.confirmed;
148 :
149 : return ConfirmationStatus.pending;
150 : }
151 :
152 0 : static ConfirmationStatus fromBool(bool? valid) {
153 : if (valid == null) return ConfirmationStatus.pending;
154 : if (valid) return ConfirmationStatus.confirmed;
155 : return ConfirmationStatus.failed;
156 : }
157 :
158 2 : static ConfirmationStatus fromJson(int status) => values[status];
159 :
160 : final String displayName;
161 :
162 : const ConfirmationStatus(this.displayName);
163 : }
164 :
165 : enum TransactionTransferMethod {
166 : receive("receive"),
167 :
168 : send("send"),
169 :
170 : own("own"),
171 :
172 : unknown("unknown");
173 :
174 1 : static TransactionTransferMethod fromAddress(
175 : String address,
176 : String recipient,
177 : String sender,
178 : ) {
179 3 : if (address.toLowerCase() == sender.toLowerCase() &&
180 3 : address.toLowerCase() == recipient.toLowerCase()) return TransactionTransferMethod.own;
181 1 : if (address == recipient) return TransactionTransferMethod.receive;
182 : return TransactionTransferMethod.send;
183 : }
184 :
185 : final String displayName;
186 :
187 : const TransactionTransferMethod(this.displayName);
188 :
189 2 : static TransactionTransferMethod fromJson(int index) => values[index];
190 : }
|