dev
dart 274 lines 9.08 KB
Raw
1 import 'package:cake_wallet/entities/balance_display_mode.dart';
2 import 'package:cake_wallet/entities/fiat_currency.dart';
3 import 'package:cake_wallet/evm/evm.dart';
4 import 'package:cake_wallet/generated/i18n.dart';
5 import 'package:cake_wallet/reactions/wallet_connect.dart';
6 import 'package:cake_wallet/solana/solana.dart';
7 import 'package:cake_wallet/store/app_store.dart';
8 import 'package:cake_wallet/tron/tron.dart';
9 import 'package:cake_wallet/zano/zano.dart';
10 import 'package:cw_core/crypto_amount_format.dart';
11 import 'package:cw_core/crypto_currency.dart';
12 import 'package:cw_core/transaction_direction.dart';
13 import 'package:cw_core/transaction_info.dart';
14 import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
15 import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart';
16 import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
17 import 'package:cw_core/keyable.dart';
18 import 'package:cw_core/wallet_type.dart';
19
20 class TransactionListItem extends ActionListItem with Keyable {
21 TransactionListItem({
22 required this.transaction,
23 required this.balanceViewModel,
24 required AppStore appStore,
25 required super.key,
26 }) : _appStore = appStore;
27
28 final TransactionInfo transaction;
29 final BalanceViewModel balanceViewModel;
30 final AppStore _appStore;
31
32 double get price => balanceViewModel.price;
33
34 FiatCurrency get fiatCurrency => _appStore.settingsStore.fiatCurrency;
35
36 BalanceDisplayMode get displayMode => balanceViewModel.displayMode;
37
38 @override
39 dynamic get keyIndex => transaction.id;
40
41 bool get hasTokens =>
42 isEVMCompatibleChain(balanceViewModel.wallet.type) ||
43 balanceViewModel.wallet.type == WalletType.solana ||
44 balanceViewModel.wallet.type == WalletType.tron;
45
46 String get formattedCryptoAmount {
47 if (displayMode == BalanceDisplayMode.hiddenBalance) return '---';
48 if (balanceViewModel.wallet.type == WalletType.bitcoin) {
49 return _appStore.amountParsingProxy
50 .asDisplayStringWithSymbol(transaction.amount)
51 .withLocalSeperator(_appStore.settingsStore.languageCode);
52 }
53
54 return transaction.amount.toStringWithSymbol(fractionalDigits: 8);
55 }
56
57 String get formattedTitle {
58 if (balanceViewModel.wallet.type == WalletType.bitcoin &&
59 transaction.additionalInfo['hasMissingInputTx'] == true) {
60 return 'Transaction has missing data';
61 }
62
63 if (transaction.additionalInfo['isIronwoodMigration'] == true) {
64 return 'Migration';
65 }
66 if (transaction.additionalInfo['isAutoShield'] == true) {
67 if (transaction.isPending) {
68 final status = formattedStatus;
69 final baseString = S.current.shielding;
70 return status.isNotEmpty ? "$baseString $status" : "$baseString...";
71 }
72 return S.current.shielding;
73 }
74 if (transaction.isPending) {
75 final status = formattedStatus;
76 final baseString = transaction.direction == TransactionDirection.incoming
77 ? S.current.receiving
78 : S.current.sending;
79 return status.isNotEmpty ? "$baseString $status" : "$baseString...";
80 }
81
82 if (transaction.direction == TransactionDirection.incoming) {
83 return S.current.received;
84 }
85
86 return S.current.sent;
87 }
88
89 int get neededConfirmations {
90 switch (balanceViewModel.wallet.type) {
91 case WalletType.monero:
92 case WalletType.haven:
93 case WalletType.zano:
94 return 10;
95 case WalletType.wownero:
96 return 3;
97 case WalletType.litecoin:
98 bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false;
99 bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false;
100 if (isPegOut || fromPegOut) return 6;
101 default:
102 return 0;
103 }
104 return 0;
105 }
106
107 String get formattedPendingStatus {
108 switch (balanceViewModel.wallet.type) {
109 case WalletType.monero:
110 case WalletType.haven:
111 case WalletType.zano:
112 if (transaction.confirmations >= 0 && transaction.confirmations < 10) {
113 return ' (${transaction.confirmations}/10)';
114 }
115 break;
116 case WalletType.wownero:
117 if (transaction.confirmations >= 0 && transaction.confirmations < 3) {
118 return ' (${transaction.confirmations}/3)';
119 }
120 break;
121 case WalletType.litecoin:
122 bool isPegIn = (transaction.additionalInfo["isPegIn"] as bool?) ?? false;
123 bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false;
124 bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false;
125 String str = '';
126 if (transaction.confirmations <= 0) {
127 str = S.current.pending;
128 }
129 if ((isPegOut || fromPegOut) &&
130 transaction.confirmations >= 0 &&
131 transaction.confirmations < 6) {
132 str = " (${transaction.confirmations}/6)";
133 }
134 if (isPegIn) {
135 str += " (Mask)";
136 }
137 if (isPegOut) {
138 str += " (Unmask)";
139 }
140 return str;
141 default:
142 return '';
143 }
144
145 return '';
146 }
147
148 String get formattedStatus {
149 if ([
150 WalletType.monero,
151 WalletType.haven,
152 WalletType.wownero,
153 WalletType.litecoin,
154 WalletType.zano,
155 ].contains(balanceViewModel.wallet.type)) {
156 return formattedPendingStatus;
157 }
158
159 return "";
160 }
161
162 String get formattedType {
163 if (transaction.evmSignatureName == 'approval') {
164 return ' (${transaction.evmSignatureName})';
165 }
166 return '';
167 }
168
169 CryptoCurrency? get assetOfTransaction {
170 try {
171 if (isEVMCompatibleChain(balanceViewModel.wallet.type)) {
172 final asset = evm!.assetOfTransaction(balanceViewModel.wallet, transaction);
173 return asset;
174 }
175
176 if (balanceViewModel.wallet.type == WalletType.solana) {
177 final asset = solana!.assetOfTransaction(balanceViewModel.wallet, transaction);
178 return asset;
179 }
180
181 if (balanceViewModel.wallet.type == WalletType.tron) {
182 final asset = tron!.assetOfTransaction(balanceViewModel.wallet, transaction);
183 return asset;
184 }
185 } catch (e) {
186 return null;
187 }
188
189 return null;
190 }
191
192 String get formattedFiatAmount {
193 var amount = '';
194
195 switch (balanceViewModel.wallet.type) {
196 case WalletType.monero:
197 case WalletType.wownero:
198 case WalletType.bitcoin:
199 case WalletType.litecoin:
200 case WalletType.bitcoinCash:
201 case WalletType.dogecoin:
202 case WalletType.nano:
203 case WalletType.decred:
204 case WalletType.zcash:
205 amount = calculateFiatAmountRaw(
206 cryptoAmount: double.parse(transaction.amount.toString()),
207 price: price,
208 ).withLocalSeperator(_appStore.settingsStore.languageCode);
209 case WalletType.ethereum:
210 case WalletType.polygon:
211 case WalletType.base:
212 case WalletType.arbitrum:
213 case WalletType.bsc:
214 final asset = assetOfTransaction;
215 final price = balanceViewModel.fiatConversionStore.prices[asset];
216 amount = calculateFiatAmountRaw(
217 cryptoAmount: double.parse(transaction.amount.toString()),
218 price: price,
219 ).withLocalSeperator(_appStore.settingsStore.languageCode);
220 break;
221 case WalletType.solana:
222 final asset = solana!.assetOfTransaction(balanceViewModel.wallet, transaction);
223 final price = balanceViewModel.fiatConversionStore.prices[asset];
224 amount = calculateFiatAmountRaw(
225 cryptoAmount: double.parse(transaction.amount.toString()),
226 price: price,
227 ).withLocalSeperator(_appStore.settingsStore.languageCode);
228 break;
229 case WalletType.tron:
230 final asset = tron!.assetOfTransaction(balanceViewModel.wallet, transaction);
231 final price = balanceViewModel.fiatConversionStore.prices[asset];
232 amount = calculateFiatAmountRaw(
233 cryptoAmount: double.parse(transaction.amount.toString()),
234 price: price,
235 ).withLocalSeperator(_appStore.settingsStore.languageCode);
236 break;
237 case WalletType.zano:
238 final asset = zano!.assetOfTransaction(balanceViewModel.wallet, transaction);
239 if (asset == null) {
240 amount = "0.00";
241 break;
242 }
243 final price = balanceViewModel.fiatConversionStore.prices[asset];
244 amount = calculateFiatAmountRaw(
245 cryptoAmount: double.parse(transaction.amount.toString()),
246 price: price,
247 ).withLocalSeperator(_appStore.settingsStore.languageCode);
248 break;
249 case WalletType.none:
250 case WalletType.banano:
251 case WalletType.haven:
252 break;
253 }
254
255 transaction.changeFiatAmount(amount);
256 return displayMode == BalanceDisplayMode.hiddenBalance
257 ? '---'
258 : fiatCurrency.title + ' ' + transaction.fiatAmount();
259 }
260
261 @override
262 DateTime get date => transaction.date;
263
264 @override
265 bool operator ==(Object other) {
266 if (other is TransactionListItem) {
267 return other.transaction.txHash == transaction.txHash &&
268 other.transaction.confirmations == transaction.confirmations &&
269 other.transaction.isPending == transaction.isPending &&
270 other.transaction.direction == transaction.direction;
271 }
272 return false;
273 }
274 }