dev
dart 2,163 lines 78.7 KB
Raw
1 import 'dart:io';
2
3 const bitcoinOutputPath = 'lib/bitcoin/bitcoin.dart';
4 const moneroOutputPath = 'lib/monero/monero.dart';
5 const bitcoinCashOutputPath = 'lib/bitcoin_cash/bitcoin_cash.dart';
6 const nanoOutputPath = 'lib/nano/nano.dart';
7 const solanaOutputPath = 'lib/solana/solana.dart';
8 const tronOutputPath = 'lib/tron/tron.dart';
9 const wowneroOutputPath = 'lib/wownero/wownero.dart';
10 const zanoOutputPath = 'lib/zano/zano.dart';
11 const decredOutputPath = 'lib/decred/decred.dart';
12 const dogecoinOutputPath = 'lib/dogecoin/dogecoin.dart';
13 const evmOutputPath = 'lib/evm/evm.dart';
14 const zcashOutputPath = 'lib/zcash/zcash.dart';
15 const walletTypesPath = 'lib/wallet_types.g.dart';
16 const secureStoragePath = 'lib/core/secure_storage.dart';
17 const pubspecDefaultPath = 'pubspec_default.yaml';
18 const pubspecOutputPath = 'pubspec.yaml';
19
20 Future<void> main(List<String> args) async {
21 const prefix = '--';
22 final hasBitcoin = args.contains('${prefix}bitcoin');
23 final hasMonero = args.contains('${prefix}monero');
24 final hasEthereum = args.contains('${prefix}ethereum');
25 final hasBitcoinCash = args.contains('${prefix}bitcoinCash');
26 final hasNano = args.contains('${prefix}nano');
27 final hasBanano = args.contains('${prefix}banano');
28 final hasPolygon = args.contains('${prefix}polygon');
29 final hasSolana = args.contains('${prefix}solana');
30 final hasTron = args.contains('${prefix}tron');
31 final hasWownero = args.contains('${prefix}wownero');
32 final hasZano = args.contains('${prefix}zano');
33 final hasDecred = args.contains('${prefix}decred');
34 final hasDogecoin = args.contains('${prefix}dogecoin');
35 final hasBase = args.contains('${prefix}base');
36 final hasArbitrum = args.contains('${prefix}arbitrum');
37 final hasBsc = args.contains('${prefix}bsc');
38 final hasZcash = args.contains('${prefix}zcash');
39 final hasEVM = hasEthereum || hasPolygon || hasBase || hasArbitrum || hasBsc;
40 final excludeFlutterSecureStorage = args.contains('${prefix}excludeFlutterSecureStorage');
41
42 await generateBitcoin(hasBitcoin);
43 await generateMonero(hasMonero);
44 await generateBitcoinCash(hasBitcoinCash);
45 await generateNano(hasNano);
46 await generateSolana(hasSolana);
47 await generateTron(hasTron);
48 await generateWownero(hasWownero);
49 await generateZano(hasZano);
50 // await generateBanano(hasEthereum);
51 await generateDecred(hasDecred);
52 await generateDogecoin(hasDogecoin);
53 await generateEVM(hasEVM);
54 await generateZcash(hasZcash);
55
56 await generatePubspec(
57 hasMonero: hasMonero,
58 hasBitcoin: hasBitcoin,
59 hasEthereum: hasEthereum,
60 hasNano: hasNano,
61 hasBanano: hasBanano,
62 hasBitcoinCash: hasBitcoinCash,
63 hasFlutterSecureStorage: !excludeFlutterSecureStorage,
64 hasPolygon: hasPolygon,
65 hasSolana: hasSolana,
66 hasTron: hasTron,
67 hasWownero: hasWownero,
68 hasZano: hasZano,
69 hasDecred: hasDecred,
70 hasDogecoin: hasDogecoin,
71 hasBase: hasBase,
72 hasArbitrum: hasArbitrum,
73 hasBsc: hasBsc,
74 hasZcash: hasZcash,
75 );
76 await generateWalletTypes(
77 hasMonero: hasMonero,
78 hasBitcoin: hasBitcoin,
79 hasEthereum: hasEthereum,
80 hasNano: hasNano,
81 hasBanano: hasBanano,
82 hasBitcoinCash: hasBitcoinCash,
83 hasPolygon: hasPolygon,
84 hasSolana: hasSolana,
85 hasTron: hasTron,
86 hasWownero: hasWownero,
87 hasZano: hasZano,
88 hasDecred: hasDecred,
89 hasDogecoin: hasDogecoin,
90 hasBase: hasBase,
91 hasArbitrum: hasArbitrum,
92 hasBsc: hasBsc,
93 hasZcash: hasZcash,
94 );
95 await injectSecureStorage(!excludeFlutterSecureStorage);
96 }
97
98 Future<void> generateBitcoin(bool hasImplementation) async {
99 final outputFile = File(bitcoinOutputPath);
100 const bitcoinCommonHeaders = """
101 import 'dart:io' show Platform;
102 import 'dart:typed_data';
103 import 'package:bitcoin_base/bitcoin_base.dart';
104 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
105 import 'package:cake_wallet/view_model/send/output.dart';
106 import 'package:cw_core/amount/money.dart';
107 import 'package:cw_core/hardware/hardware_account_data.dart';
108 import 'package:cw_core/hardware/hardware_wallet_service.dart';
109 import 'package:cw_core/node.dart';
110 import 'package:cw_core/payjoin_session.dart';
111 import 'package:cw_core/output_info.dart';
112 import 'package:cw_core/pending_transaction.dart';
113 import 'package:cw_core/receive_page_option.dart';
114 import 'package:cw_core/transaction_info.dart';
115 import 'package:cw_core/transaction_priority.dart';
116 import 'package:cw_core/unspent_coin_type.dart';
117 import 'package:cw_core/unspent_coins_info.dart';
118 import 'package:cw_core/unspent_transaction_output.dart';
119 import 'package:cw_core/wallet_base.dart';
120 import 'package:cw_core/wallet_credentials.dart';
121 import 'package:cw_core/wallet_info.dart';
122 import 'package:cw_core/wallet_service.dart';
123 import 'package:cw_core/wallet_type.dart';
124 import 'package:cw_core/utils/print_verbose.dart';
125 import 'package:cw_core/get_height_by_date.dart';
126 import 'package:hive/hive.dart';
127 import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
128 import 'package:bitbox_flutter/bitbox_flutter.dart' as bitbox;
129 import 'package:trezor_connect/trezor_connect.dart' as trezor;
130 import 'package:blockchain_utils/blockchain_utils.dart';
131 import 'package:bip39/bip39.dart' as bip39;
132 import 'package:collection/collection.dart';
133 """;
134 const bitcoinCWHeaders = """
135 import 'package:cw_bitcoin/utils.dart';
136 import 'package:cw_bitcoin/electrum_derivations.dart';
137 import 'package:cw_bitcoin/electrum.dart';
138 import 'package:cw_bitcoin/electrum_transaction_info.dart';
139 import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
140 import 'package:cw_bitcoin/bitcoin_receive_page_option.dart';
141 import 'package:cw_bitcoin/electrum_wallet.dart';
142 import 'package:cw_bitcoin/bitcoin_unspent.dart';
143 import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
144 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
145 import 'package:cw_bitcoin/bitcoin_wallet.dart';
146 import 'package:cw_bitcoin/bitcoin_wallet_service.dart';
147 import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
148 import 'package:cw_bitcoin/bitcoin_amount_format.dart';
149 import 'package:cw_bitcoin/bitcoin_address_record.dart';
150 import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
151 import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
152 import 'package:cw_bitcoin/lightning/lightning_addres_type.dart';
153 import 'package:cw_bitcoin/lightning/pending_lightning_transaction.dart';
154 import 'package:cw_bitcoin/litecoin_wallet_service.dart';
155 import 'package:cw_bitcoin/litecoin_wallet.dart';
156 import 'package:cw_bitcoin/hardware/bitcoin_ledger_service.dart';
157 import 'package:cw_bitcoin/hardware/litecoin_ledger_service.dart';
158 import 'package:cw_bitcoin/hardware/bitbox_service.dart';
159 import 'package:cw_bitcoin/hardware/trezor_service.dart';
160 import 'package:mobx/mobx.dart';
161 import "package:breez_sdk_spark_flutter/src/rust/errors.dart";
162 """;
163 const bitcoinCwPart = "part 'cw_bitcoin.dart';";
164 const bitcoinContent = """
165
166 class ElectrumSubAddress {
167 ElectrumSubAddress({
168 required this.id,
169 required this.name,
170 required this.address,
171 required this.txCount,
172 required this.balance,
173 required this.isChange,
174 this.derivationPath,
175 this.isLegacyDerivation = false
176 });
177 final int id;
178 final String name;
179 final String address;
180 final int txCount;
181 final int balance;
182 final bool isChange;
183 final String? derivationPath;
184 final bool isLegacyDerivation;
185 }
186
187 abstract class Bitcoin {
188 TransactionPriority getMediumTransactionPriority();
189
190 WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({
191 required String name,
192 required String mnemonic,
193 required String password,
194 required DerivationType derivationType,
195 required String derivationPath,
196 String? passphrase,
197 });
198 WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({required String name, required String password, required String wif, WalletInfo? walletInfo});
199 WalletCredentials createBitcoinWalletFromKeys({required String name, required String password, required String xpub, HardwareWalletType? hardwareWalletType});
200 WalletCredentials createLitecoinWalletFromKeys({required String name, required String password, required String xpub, required String scanSecret, required String spendPubkey, HardwareWalletType? hardwareWalletType});
201 WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic});
202 WalletCredentials createBitcoinHardwareWalletCredentials({required String name, required HardwareAccountData accountData, WalletInfo? walletInfo});
203 List<String> getWordList();
204 Map<String, String> getWalletKeys(Object wallet);
205 List<TransactionPriority> getTransactionPriorities();
206 List<TransactionPriority> getLitecoinTransactionPriorities();
207 TransactionPriority deserializeBitcoinTransactionPriority(int raw);
208 TransactionPriority deserializeLitecoinTransactionPriority(int raw);
209 int getFeeRate(Object wallet, TransactionPriority priority);
210 Future<void> generateNewAddress(Object wallet, String label);
211 Future<void> updateAddress(Object wallet,String address, String label);
212 Object createBitcoinTransactionCredentials(List<Output> outputs, {required TransactionPriority priority, int? feeRate, UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any, String? payjoinUri});
213
214 String getAddress(Object wallet);
215 List<ElectrumSubAddress> getSilentPaymentAddresses(Object wallet);
216 List<ElectrumSubAddress> getSilentPaymentReceivedAddresses(Object wallet);
217
218 Future<Money> estimateFakeSendAllTxAmount(WalletBase wallet, TransactionPriority priority,
219 {UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any});
220 List<ElectrumSubAddress> getSubAddresses(Object wallet);
221
222 String formatterBitcoinAmountToString({required int amount});
223 int formatterStringDoubleToBitcoinAmount(String amount);
224 String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate, {int? customRate});
225
226 List<Unspent> getUnspents(Object wallet, {UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any});
227 Future<void> updateUnspents(Object wallet);
228 WalletService createBitcoinWalletService(
229 Box<UnspentCoinsInfo> unspentCoinSource, Box<PayjoinSession> payjoinSessionSource, bool isDirect);
230 WalletService createLitecoinWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect);
231 TransactionPriority getBitcoinTransactionPriorityMedium();
232 TransactionPriority getBitcoinTransactionPriorityCustom();
233 TransactionPriority getLitecoinTransactionPriorityMedium();
234 TransactionPriority getBitcoinTransactionPrioritySlow();
235 TransactionPriority getLitecoinTransactionPrioritySlow();
236 Future<List<DerivationType>> compareDerivationMethods(
237 {required String mnemonic, required Node node});
238 Future<List<DerivationInfo>> getDerivationsFromMnemonic(
239 {required String mnemonic, required Node node, String? passphrase});
240 Map<DerivationType, List<DerivationInfo>> getElectrumDerivations();
241 Future<void> setAddressType(Object wallet, dynamic option);
242 ReceivePageOption getSelectedAddressType(Object wallet);
243 BitcoinAddressType getBitcoinAddressType(ReceivePageOption option);
244 ReceivePageOption getBitcoinLightningReceivePageOption();
245 ReceivePageOption getBitcoinSegwitPageOption();
246 ReceivePageOption getLitecoinMwebReceivePageOption();
247 bool isPayjoinAvailable(Object wallet);
248 bool hasSelectedSilentPayments(Object wallet);
249 bool hasSelectedLightning(Object wallet);
250 bool isBitcoinReceivePageOption(ReceivePageOption option);
251 BitcoinAddressType getOptionToType(ReceivePageOption option);
252 bool hasTaprootInput(PendingTransaction pendingTransaction);
253 bool getScanningActive(Object wallet);
254 Future<void> setScanningActive(Object wallet, bool active);
255 Future<void> setIsAlwaysScanningSP(Object wallet, bool active);
256 bool getIsAlwaysScanningSP(Object wallet);
257 bool isTestnet(Object wallet);
258
259 Future<PendingTransaction> replaceByFee(Object wallet, String transactionHash, String fee);
260 Future<String?> canReplaceByFee(Object wallet, Object tx);
261 int getTransactionVSize(Object wallet, String txHex);
262 Future<bool> isChangeSufficientForFee(Object wallet, String txId, String newFee);
263 int getFeeAmountForPriority(Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, {int? size});
264 int getEstimatedFeeWithFeeRate(Object wallet, int feeRate, int? amount,
265 {int? outputsCount, int? size});
266 int feeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size});
267 Future<bool> checkIfMempoolAPIIsEnabled(Object wallet);
268 Future<int> getHeightByDate({required DateTime date, bool? bitcoinMempoolAPIEnabled});
269 int getLitecoinHeightByDate({required DateTime date});
270 Future<void> rescan(Object wallet, {required int height, bool? doSingleScan});
271 Future<bool> getNodeIsElectrsSPEnabled(Object wallet);
272 void deleteSilentPaymentAddress(Object wallet, String address);
273 Future<void> updateFeeRates(Object wallet);
274 int getMaxCustomFeeRate(Object wallet);
275 Future<void> setHardwareWalletService(WalletBase wallet, HardwareWalletService service);
276 HardwareWalletService getLedgerHardwareWalletService(ledger.LedgerConnection connection, bool isBitcoin);
277 HardwareWalletService getBitboxHardwareWalletService(bitbox.BitboxManager manager, bool isBitcoin);
278 HardwareWalletService getTrezorHardwareWalletService(trezor.TrezorConnect connect, bool isBitcoin);
279 List<Output> updateOutputs(PendingTransaction pendingTransaction, List<Output> outputs);
280 bool txIsReceivedSilentPayment(TransactionInfo txInfo);
281 bool txIsMweb(TransactionInfo txInfo);
282 Future<void> setMwebEnabled(Object wallet, bool enabled);
283 bool getMwebEnabled(Object wallet);
284 String? getUnusedMwebAddress(Object wallet);
285 String? getUnusedSegwitAddress(Object wallet);
286 Future<String?> getUnusedSpakDepositAddress(Object wallet);
287 Future<void> commitPsbtUR(Object wallet, List<String> urCodes);
288
289 void updatePayjoinState(Object wallet, bool state);
290 String getPayjoinEndpoint(Object wallet);
291 void resumePayjoinSessions(Object wallet);
292 void stopPayjoinSessions(Object wallet);
293 Map<String, String> getSilentPaymentKeys(Object wallet);
294 List<String>? getTransactionAddresses(Object wallet, TransactionInfo tx);
295 String getNetworkName(Object wallet);
296 bool useLightning(Object wallet);
297 void updateUseLightning(Object wallet, bool value);
298 Future<void> setLightningUsername(Object wallet, String username);
299 Future<String?> getLightningUsername(Object wallet);
300 Future<String?> getLightningInvoice(Object wallet, BigInt amount);
301 String? getBreezSdkError(Object exception);
302 }
303 """;
304
305 const bitcoinEmptyDefinition = 'Bitcoin? bitcoin;\n';
306 const bitcoinCWDefinition = 'Bitcoin? bitcoin = CWBitcoin();\n';
307
308 final output = '$bitcoinCommonHeaders\n' +
309 (hasImplementation ? '$bitcoinCWHeaders\n' : '\n') +
310 (hasImplementation ? '$bitcoinCwPart\n\n' : '\n') +
311 (hasImplementation ? bitcoinCWDefinition : bitcoinEmptyDefinition) +
312 '\n' +
313 bitcoinContent;
314
315 if (outputFile.existsSync()) {
316 await outputFile.delete();
317 }
318
319 await outputFile.writeAsString(output);
320 }
321
322 Future<void> generateMonero(bool hasImplementation) async {
323 final outputFile = File(moneroOutputPath);
324 const moneroCommonHeaders = """
325 import 'package:cw_core/amount/money.dart';
326 import 'package:cw_core/crypto_currency.dart';
327 import 'package:cw_core/unspent_transaction_output.dart';
328 import 'package:cw_core/unspent_coins_info.dart';
329 import 'package:mobx/mobx.dart';
330 import 'package:cw_core/wallet_credentials.dart';
331 import 'package:cw_core/wallet_info.dart';
332 import 'package:cw_core/transaction_priority.dart';
333 import 'package:cw_core/transaction_history.dart';
334 import 'package:cw_core/transaction_info.dart';
335 import 'package:cw_core/balance.dart';
336 import 'package:cw_core/output_info.dart';
337 import 'package:cake_wallet/view_model/send/output.dart';
338 import 'package:cw_core/wallet_service.dart';
339 import 'package:hive/hive.dart';
340 import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
341 import 'package:trezor_flutter/trezor_flutter.dart' as trezor;
342 import 'package:polyseed/polyseed.dart';""";
343 const moneroCWHeaders = """
344 import 'package:cw_core/hardware/hardware_wallet_service.dart';
345 import 'package:cw_core/account.dart' as monero_account;
346 import 'package:cw_core/get_height_by_date.dart';
347 import 'package:cw_core/monero_amount_format.dart';
348 import 'package:cw_core/monero_transaction_priority.dart';
349 import 'package:cw_monero/api/wallet_manager.dart';
350 import 'package:cw_monero/api/wallet.dart' as monero_wallet_api;
351 import 'package:cw_monero/ledger.dart';
352 import 'package:cw_monero/monero_unspent.dart';
353 import 'package:cw_monero/api/account_list.dart';
354 import 'package:cw_monero/trezor.dart';
355 import 'package:cw_monero/monero_wallet_service.dart';
356 import 'package:cw_monero/monero_wallet.dart';
357 import 'package:cw_monero/monero_transaction_info.dart';
358 import 'package:cw_monero/monero_transaction_creation_credentials.dart';
359 import 'package:cw_monero/mnemonics/english.dart';
360 import 'package:cw_monero/mnemonics/chinese_simplified.dart';
361 import 'package:cw_monero/mnemonics/dutch.dart';
362 import 'package:cw_monero/mnemonics/german.dart';
363 import 'package:cw_monero/mnemonics/japanese.dart';
364 import 'package:cw_monero/mnemonics/russian.dart';
365 import 'package:cw_monero/mnemonics/spanish.dart';
366 import 'package:cw_monero/mnemonics/portuguese.dart';
367 import 'package:cw_monero/mnemonics/french.dart';
368 import 'package:cw_monero/mnemonics/italian.dart';
369 import 'package:cw_monero/pending_monero_transaction.dart';
370 """;
371 const moneroCwPart = "part 'cw_monero.dart';";
372 const moneroContent = """
373 class Account {
374 Account({required this.id, required this.label, this.balance});
375 final int id;
376 final String label;
377 final String? balance;
378 }
379
380 class Subaddress {
381 Subaddress({
382 required this.id,
383 required this.label,
384 required this.address,
385 required this.received,
386 required this.txCount});
387 final int id;
388 final String label;
389 final String address;
390 final String? received;
391 final int txCount;
392 }
393
394 class MoneroBalance extends Balance {
395 MoneroBalance({
396 required this.fullBalance,
397 required Money unlockedBalance,
398 Money? frozen,
399 }) : super(
400 unlockedBalance,
401 fullBalance - unlockedBalance,
402 frozen: frozen ?? Money.zero(CryptoCurrency.xmr),
403 );
404
405 final Money fullBalance;
406 }
407
408 abstract class MoneroWalletDetails {
409 @observable
410 late Account account;
411
412 @observable
413 late MoneroBalance balance;
414 }
415
416 abstract class Monero {
417 MoneroAccountList getAccountList(Object wallet);
418
419 MoneroSubaddressList getSubaddressList(Object wallet);
420
421 TransactionHistoryBase getTransactionHistory(Object wallet);
422
423 MoneroWalletDetails getMoneroWalletDetails(Object wallet);
424
425 String getTransactionAddress(Object wallet, int accountIndex, int addressIndex);
426
427 String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex);
428
429 int getHeightByDate({required DateTime date});
430 TransactionPriority getDefaultTransactionPriority();
431 TransactionPriority getMoneroTransactionPrioritySlow();
432 TransactionPriority getMoneroTransactionPriorityAutomatic();
433 TransactionPriority deserializeMoneroTransactionPriority({required int raw});
434 List<TransactionPriority> getTransactionPriorities();
435 List<String> getMoneroWordList(String language);
436
437 List<Unspent> getUnspents(Object wallet);
438 Future<void> updateUnspents(Object wallet);
439
440 Future<int> getCurrentHeight();
441
442 Future<bool> commitTransactionUR(Object wallet, String ur);
443
444 Map<String, String> exportOutputsUR(Object wallet);
445
446 bool needExportOutputs(Object wallet, Money amount);
447
448 bool hasUnknownKeyImages(Object wallet);
449
450 bool importKeyImagesUR(Object wallet, String ur);
451
452 WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
453 required String name,
454 required String spendKey,
455 required String viewKey,
456 required String address,
457 required String password,
458 required String language,
459 HardwareWalletType? hardwareWalletType,
460 required int height});
461 WalletCredentials createMoneroRestoreWalletFromSeedCredentials({required String name, required String password, required String passphrase, required int height, required String mnemonic});
462 WalletCredentials createMoneroRestoreWalletFromHardwareCredentials({required String name, required String password, required int height, required HardwareWalletService hardwareWalletService, required String? passphrase});
463 WalletCredentials createMoneroNewWalletCredentials({required String name, required String language, required int seedType, required String? passphrase, String? password, String? mnemonic});
464 Map<String, String> getKeys(Object wallet);
465 int? getRestoreHeight(Object wallet);
466 Object createMoneroTransactionCreationCredentials({required List<Output> outputs, required TransactionPriority priority});
467 Object createMoneroTransactionCreationCredentialsRaw({required List<OutputInfo> outputs, required TransactionPriority priority});
468 String formatterMoneroAmountToString({required int amount});
469 double formatterMoneroAmountToDouble({required int amount});
470 int formatterMoneroParseAmount({required String amount});
471 Account getCurrentAccount(Object wallet);
472 void monerocCheck();
473 bool isViewOnly();
474 void setCurrentAccount(Object wallet, int id, String label, String? balance);
475 void onStartup();
476 int getTransactionInfoAccountId(TransactionInfo tx);
477 WalletService createMoneroWalletService(Box<UnspentCoinsInfo> unspentCoinSource);
478 Map<String, String> pendingTransactionInfo(Object transaction);
479 Future<void> setLedgerConnection(Object wallet, ledger.LedgerConnection connection);
480 void resetLedgerConnection();
481 void setGlobalLedgerConnection(ledger.LedgerConnection connection);
482 bool hasGlobalLedgerConnection();
483 String? getLastLedgerCommand();
484 void setHardwareWalletService(Object wallet, HardwareWalletService service);
485 HardwareWalletService getLedgerHardwareWalletService(ledger.LedgerConnection connection);
486 HardwareWalletService getTrezorHardwareWalletService(trezor.TrezorClient client);
487 Future<void> syncTrezor(Object wallet);
488 Map<String, List<int>> debugCallLength();
489 Map<String, dynamic> getWalletCacheDebug();
490 }
491
492 abstract class MoneroSubaddressList {
493 ObservableList<Subaddress> get subaddresses;
494 Future<void> update(Object wallet, {required int accountIndex});
495 void refresh(Object wallet, {required int accountIndex});
496 Future<List<Subaddress>> getAll(Object wallet);
497 Future<void> addSubaddress(Object wallet, {required int accountIndex, required String label});
498 Future<void> setLabelSubaddress(Object wallet,
499 {required int accountIndex, required int addressIndex, required String label});
500 }
501
502 abstract class MoneroAccountList {
503 ObservableList<Account> get accounts;
504 void update(Object wallet);
505 void refresh(Object wallet);
506 List<Account> getAll(Object wallet);
507 Future<void> addAccount(Object wallet, {required String label});
508 Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label});
509 }
510 """;
511
512 const moneroEmptyDefinition = 'Monero? monero;\n';
513 const moneroCWDefinition = 'Monero? monero = CWMonero();\n';
514
515 final output = '$moneroCommonHeaders\n' +
516 (hasImplementation ? '$moneroCWHeaders\n' : '\n') +
517 (hasImplementation ? '$moneroCwPart\n\n' : '\n') +
518 (hasImplementation ? moneroCWDefinition : moneroEmptyDefinition) +
519 '\n' +
520 moneroContent;
521
522 if (outputFile.existsSync()) {
523 await outputFile.delete();
524 }
525
526 await outputFile.writeAsString(output);
527 }
528
529 Future<void> generateWownero(bool hasImplementation) async {
530 final outputFile = File(wowneroOutputPath);
531 const wowneroCommonHeaders = """
532 import 'package:cw_core/amount/money.dart';
533 import 'package:cw_core/crypto_currency.dart';
534 import 'package:cw_core/unspent_transaction_output.dart';
535 import 'package:cw_core/unspent_coins_info.dart';
536 import 'package:mobx/mobx.dart';
537 import 'package:cw_core/wallet_credentials.dart';
538 import 'package:cw_core/wallet_info.dart';
539 import 'package:cw_core/transaction_priority.dart';
540 import 'package:cw_core/transaction_history.dart';
541 import 'package:cw_core/transaction_info.dart';
542 import 'package:cw_core/balance.dart';
543 import 'package:cw_core/output_info.dart';
544 import 'package:cake_wallet/view_model/send/output.dart';
545 import 'package:cw_core/crypto_currency.dart';
546 import 'package:cake_wallet/core/key_service.dart';
547 import 'package:cake_wallet/core/secure_storage.dart';
548 import 'package:cake_wallet/entities/haven_seed_store.dart';
549 import 'package:cw_core/cake_hive.dart';
550 import 'package:cw_core/wallet_info.dart';
551 import 'package:cw_core/wallet_type.dart';
552 import 'package:cw_core/wallet_service.dart';
553 import 'package:hive/hive.dart';
554 import 'package:polyseed/polyseed.dart';""";
555 const wowneroCWHeaders = """
556 import 'package:cw_core/get_height_by_date.dart';
557 import 'package:cw_core/wownero_amount_format.dart';
558 import 'package:cw_core/monero_transaction_priority.dart';
559 import 'package:cw_wownero/wownero_unspent.dart';
560 import 'package:cw_wownero/wownero_wallet_service.dart';
561 import 'package:cw_wownero/wownero_wallet.dart';
562 import 'package:cw_wownero/wownero_transaction_info.dart';
563 import 'package:cw_wownero/wownero_transaction_creation_credentials.dart';
564 import 'package:cw_core/account.dart' as wownero_account;
565 import 'package:cw_wownero/api/wallet.dart' as wownero_wallet_api;
566 import 'package:cw_wownero/api/wallet_manager.dart';
567 import 'package:cw_wownero/mnemonics/english.dart';
568 import 'package:cw_wownero/mnemonics/chinese_simplified.dart';
569 import 'package:cw_wownero/mnemonics/dutch.dart';
570 import 'package:cw_wownero/mnemonics/german.dart';
571 import 'package:cw_wownero/mnemonics/japanese.dart';
572 import 'package:cw_wownero/mnemonics/russian.dart';
573 import 'package:cw_wownero/mnemonics/spanish.dart';
574 import 'package:cw_wownero/mnemonics/portuguese.dart';
575 import 'package:cw_wownero/mnemonics/french.dart';
576 import 'package:cw_wownero/mnemonics/italian.dart';
577 import 'package:cw_wownero/pending_wownero_transaction.dart';
578 """;
579 const wowneroCwPart = "part 'cw_wownero.dart';";
580 const wowneroContent = """
581 class Account {
582 Account({required this.id, required this.label, this.balance});
583 final int id;
584 final String label;
585 final String? balance;
586 }
587
588 class Subaddress {
589 Subaddress({
590 required this.id,
591 required this.label,
592 required this.address});
593 final int id;
594 final String label;
595 final String address;
596 }
597
598 class WowneroBalance extends Balance {
599 WowneroBalance({
600 required this.fullBalance,
601 required Money unlockedBalance,
602 Money? frozen,
603 }) : super(
604 unlockedBalance,
605 fullBalance - unlockedBalance,
606 frozen: frozen ?? Money.zero(CryptoCurrency.wow),
607 );
608
609 final Money fullBalance;
610 }
611
612 abstract class WowneroWalletDetails {
613 @observable
614 late Account account;
615
616 @observable
617 late WowneroBalance balance;
618 }
619
620 abstract class Wownero {
621 WowneroAccountList getAccountList(Object wallet);
622
623 WowneroSubaddressList getSubaddressList(Object wallet);
624
625 TransactionHistoryBase getTransactionHistory(Object wallet);
626
627 WowneroWalletDetails getWowneroWalletDetails(Object wallet);
628
629 String getTransactionAddress(Object wallet, int accountIndex, int addressIndex);
630
631 String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex);
632
633 int getHeightByDate({required DateTime date});
634 TransactionPriority getDefaultTransactionPriority();
635 TransactionPriority getWowneroTransactionPrioritySlow();
636 TransactionPriority getWowneroTransactionPriorityAutomatic();
637 TransactionPriority deserializeWowneroTransactionPriority({required int raw});
638 List<TransactionPriority> getTransactionPriorities();
639 List<String> getWowneroWordList(String language);
640
641 List<Unspent> getUnspents(Object wallet);
642 Future<void> updateUnspents(Object wallet);
643
644 Future<int> getCurrentHeight();
645 void wownerocCheck();
646
647 WalletCredentials createWowneroRestoreWalletFromKeysCredentials({
648 required String name,
649 required String spendKey,
650 required String viewKey,
651 required String address,
652 required String password,
653 required String language,
654 required int height});
655 WalletCredentials createWowneroRestoreWalletFromSeedCredentials({required String name, required String password, required String passphrase, required int height, required String mnemonic});
656 WalletCredentials createWowneroNewWalletCredentials({required String name, required String language, required bool isPolyseed, String? password, String? passphrase});
657 int? getRestoreHeight(Object wallet);
658 Map<String, String> getKeys(Object wallet);
659 Object createWowneroTransactionCreationCredentials({required List<Output> outputs, required TransactionPriority priority});
660 Object createWowneroTransactionCreationCredentialsRaw({required List<OutputInfo> outputs, required TransactionPriority priority});
661 String formatterWowneroAmountToString({required int amount});
662 double formatterWowneroAmountToDouble({required int amount});
663 int formatterWowneroParseAmount({required String amount});
664 Account getCurrentAccount(Object wallet);
665 void setCurrentAccount(Object wallet, int id, String label, String? balance);
666 void onStartup();
667 int getTransactionInfoAccountId(TransactionInfo tx);
668 WalletService createWowneroWalletService(Box<UnspentCoinsInfo> unspentCoinSource);
669 Map<String, String> pendingTransactionInfo(Object transaction);
670 String getLegacySeed(Object wallet, String langName);
671 Map<String, List<int>> debugCallLength();
672 Future<void> backupSeeds(Box<HavenSeedStore> havenSeedStore);
673 }
674
675 abstract class WowneroSubaddressList {
676 ObservableList<Subaddress> get subaddresses;
677 void update(Object wallet, {required int accountIndex});
678 void refresh(Object wallet, {required int accountIndex});
679 List<Subaddress> getAll(Object wallet);
680 Future<void> addSubaddress(Object wallet, {required int accountIndex, required String label});
681 Future<void> setLabelSubaddress(Object wallet,
682 {required int accountIndex, required int addressIndex, required String label});
683 }
684
685 abstract class WowneroAccountList {
686 ObservableList<Account> get accounts;
687 void update(Object wallet);
688 void refresh(Object wallet);
689 List<Account> getAll(Object wallet);
690 Future<void> addAccount(Object wallet, {required String label});
691 Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label});
692 }
693 """;
694
695 const wowneroEmptyDefinition = 'Wownero? wownero;\n';
696 const wowneroCWDefinition = 'Wownero? wownero = CWWownero();\n';
697
698 final output = '$wowneroCommonHeaders\n' +
699 (hasImplementation ? '$wowneroCWHeaders\n' : '\n') +
700 (hasImplementation ? '$wowneroCwPart\n\n' : '\n') +
701 (hasImplementation ? wowneroCWDefinition : wowneroEmptyDefinition) +
702 '\n' +
703 wowneroContent;
704
705 if (outputFile.existsSync()) {
706 await outputFile.delete();
707 }
708
709 await outputFile.writeAsString(output);
710 }
711
712 Future<void> generateBitcoinCash(bool hasImplementation) async {
713 final outputFile = File(bitcoinCashOutputPath);
714 const bitcoinCashCommonHeaders = """
715 import 'dart:typed_data';
716
717 import 'package:cw_core/unspent_transaction_output.dart';
718 import 'package:cw_core/transaction_priority.dart';
719 import 'package:cw_core/unspent_coins_info.dart';
720 import 'package:cw_core/wallet_credentials.dart';
721 import 'package:cw_core/wallet_info.dart';
722 import 'package:cw_core/wallet_service.dart';
723 import 'package:hive/hive.dart';
724 """;
725 const bitcoinCashCWHeaders = """
726 import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart';
727 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
728 """;
729 const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';";
730 const bitcoinCashContent = """
731 abstract class BitcoinCash {
732 String getCashAddrFormat(String address);
733
734 WalletService createBitcoinCashWalletService(
735 Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect);
736
737 WalletCredentials createBitcoinCashNewWalletCredentials(
738 {required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic});
739
740 WalletCredentials createBitcoinCashRestoreWalletFromSeedCredentials(
741 {required String name, required String mnemonic, required String password, String? passphrase});
742
743 TransactionPriority deserializeBitcoinCashTransactionPriority(int raw);
744
745 TransactionPriority getDefaultTransactionPriority();
746
747 List<TransactionPriority> getTransactionPriorities();
748
749 TransactionPriority getBitcoinCashTransactionPrioritySlow();
750 }
751 """;
752
753 const bitcoinCashEmptyDefinition = 'BitcoinCash? bitcoinCash;\n';
754 const bitcoinCashCWDefinition = 'BitcoinCash? bitcoinCash = CWBitcoinCash();\n';
755
756 final output = '$bitcoinCashCommonHeaders\n' +
757 (hasImplementation ? '$bitcoinCashCWHeaders\n' : '\n') +
758 (hasImplementation ? '$bitcoinCashCwPart\n\n' : '\n') +
759 (hasImplementation ? bitcoinCashCWDefinition : bitcoinCashEmptyDefinition) +
760 '\n' +
761 bitcoinCashContent;
762
763 if (outputFile.existsSync()) {
764 await outputFile.delete();
765 }
766
767 await outputFile.writeAsString(output);
768 }
769
770 Future<void> generateNano(bool hasImplementation) async {
771 final outputFile = File(nanoOutputPath);
772 const nanoCommonHeaders = """
773 import 'package:cw_core/cake_hive.dart';
774 import 'package:cw_core/nano_account.dart';
775 import 'package:cw_core/account.dart';
776 import 'package:cw_core/node.dart';
777 import 'package:cw_core/wallet_credentials.dart';
778 import 'package:cw_core/wallet_info.dart';
779 import 'package:cw_core/transaction_info.dart';
780 import 'package:cw_core/transaction_history.dart';
781 import 'package:cw_core/wallet_service.dart';
782 import 'package:cw_core/output_info.dart';
783 import 'package:cw_core/nano_account_info_response.dart';
784 import 'package:cw_core/n2_node.dart';
785 import 'package:cw_core/utils/print_verbose.dart';
786 import 'package:mobx/mobx.dart';
787 import 'package:hive/hive.dart';
788 import 'package:cake_wallet/view_model/send/output.dart';
789 """;
790 const nanoCWHeaders = """
791 import 'package:cw_nano/nano_client.dart';
792 import 'package:cw_nano/nano_mnemonic.dart';
793 import 'package:cw_nano/nano_wallet.dart';
794 import 'package:cw_nano/nano_wallet_service.dart';
795 import 'package:cw_nano/nano_transaction_info.dart';
796 import 'package:cw_nano/nano_transaction_credentials.dart';
797 import 'package:cw_nano/nano_wallet_creation_credentials.dart';
798 // needed for nano_util:
799 import 'dart:convert';
800 import 'dart:typed_data';
801 import 'package:convert/convert.dart';
802 import "package:ed25519_hd_key/ed25519_hd_key.dart";
803 import 'package:libcrypto/libcrypto.dart';
804 import 'package:nanodart/nanodart.dart' as ND;
805 import 'package:nanoutil/nanoutil.dart';
806 """;
807 const nanoCwPart = "part 'cw_nano.dart';";
808 const nanoContent = """
809 abstract class Nano {
810 NanoAccountList getAccountList(Object wallet);
811
812 Account getCurrentAccount(Object wallet);
813
814 void setCurrentAccount(Object wallet, int id, String label, String? balance);
815
816 WalletService createNanoWalletService(bool isDirect);
817
818 WalletCredentials createNanoNewWalletCredentials({
819 required String name,
820 String? password,
821 String? mnemonic,
822 WalletInfo? walletInfo,
823 String? passphrase,
824 });
825
826 WalletCredentials createNanoRestoreWalletFromSeedCredentials({
827 required String name,
828 required String password,
829 required String mnemonic,
830 required DerivationType derivationType,
831 String? passphrase,
832 });
833
834 WalletCredentials createNanoRestoreWalletFromKeysCredentials({
835 required String name,
836 required String password,
837 required String seedKey,
838 required DerivationType derivationType,
839 });
840
841 List<String> getNanoWordList(String language);
842 Map<String, String> getKeys(Object wallet);
843 Object createNanoTransactionCredentials(List<Output> outputs);
844 Future<void> changeRep(Object wallet, String address);
845 Future<bool> updateTransactions(Object wallet);
846 String getRepresentative(Object wallet);
847 Future<List<N2Node>> getN2Reps(Object wallet);
848 bool isRepOk(Object wallet);
849 }
850
851 abstract class NanoAccountList {
852 ObservableList<NanoAccount> get accounts;
853 void update(Object wallet);
854 void refresh(Object wallet);
855 Future<List<NanoAccount>> getAll(Object wallet);
856 Future<void> addAccount(Object wallet, {required String label});
857 Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label});
858 }
859
860 abstract class NanoUtil {
861 bool isValidBip39Seed(String seed);
862 static const int maxDecimalDigits = 6; // Max digits after decimal
863 BigInt rawPerNano = BigInt.parse("1000000000000000000000000000000");
864 BigInt rawPerNyano = BigInt.parse("1000000000000000000000000");
865 BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000");
866 BigInt rawPerXMR = BigInt.parse("1000000000000");
867 BigInt convertXMRtoNano = BigInt.parse("1000000000000000000");
868 String getRawAsUsableString(String? raw, BigInt rawPerCur);
869 String getRawAccuracy(String? raw, BigInt rawPerCur);
870 String getAmountAsRaw(String amount, BigInt rawPerCur);
871
872 // derivationInfo:
873 Future<AccountInfoResponse?> getInfoFromSeedOrMnemonic(
874 DerivationType derivationType, {
875 String? seedKey,
876 String? mnemonic,
877 required Node node,
878 });
879 Future<List<DerivationType>> compareDerivationMethods({
880 String? mnemonic,
881 String? privateKey,
882 required Node node,
883 });
884 Future<List<DerivationInfo>> getDerivationsFromMnemonic({
885 String? mnemonic,
886 String? seedKey,
887 required Node node,
888 });
889 }
890 """;
891
892 const nanoEmptyDefinition = 'Nano? nano;\nNanoUtil? nanoUtil;\n';
893 const nanoCWDefinition = 'Nano? nano = CWNano();\nNanoUtil? nanoUtil = CWNanoUtil();\n';
894
895 final output = '$nanoCommonHeaders\n' +
896 (hasImplementation ? '$nanoCWHeaders\n' : '\n') +
897 (hasImplementation ? '$nanoCwPart\n\n' : '\n') +
898 (hasImplementation ? nanoCWDefinition : nanoEmptyDefinition) +
899 '\n' +
900 nanoContent;
901
902 if (outputFile.existsSync()) {
903 await outputFile.delete();
904 }
905
906 await outputFile.writeAsString(output);
907 }
908
909 Future<void> generateSolana(bool hasImplementation) async {
910 final outputFile = File(solanaOutputPath);
911 const solanaCommonHeaders = """
912 import 'package:cake_wallet/view_model/send/output.dart';
913 import 'package:cake_wallet/exchange/provider/jupiter_exchange_provider.dart';
914 import 'package:cw_core/amount/money.dart';
915 import 'package:cw_core/crypto_currency.dart';
916 import 'package:cw_core/output_info.dart';
917 import 'package:cw_core/pending_transaction.dart';
918 import 'package:cw_core/transaction_info.dart';
919 import 'package:cw_core/wallet_base.dart';
920 import 'package:cw_core/wallet_credentials.dart';
921 import 'package:cw_core/wallet_info.dart';
922 import 'package:cw_core/wallet_service.dart';
923 import 'package:cw_core/spl_token.dart';
924 import 'package:cw_core/transaction_direction.dart';
925 import 'package:cw_core/utils/print_verbose.dart';
926
927 """;
928 const solanaCWHeaders = """
929 import 'package:cw_solana/solana_wallet.dart';
930 import 'package:cw_solana/solana_mnemonics.dart';
931 import 'package:cw_solana/solana_wallet_service.dart';
932 import 'package:cw_solana/solana_transaction_info.dart';
933 import 'package:cw_solana/pending_solana_transaction.dart';
934 import 'package:cw_solana/solana_transaction_credentials.dart';
935 import 'package:cw_solana/solana_wallet_creation_credentials.dart';
936 import 'package:cw_solana/default_spl_tokens.dart';
937 import 'package:cake_wallet/core/fiat_conversion_service.dart';
938 import 'package:cake_wallet/di.dart';
939 import 'package:cake_wallet/entities/fiat_api_mode.dart';
940 import 'package:cake_wallet/entities/fiat_currency.dart';
941 import 'package:cake_wallet/store/settings_store.dart';
942
943 import 'dart:convert';
944 import 'dart:typed_data';
945 import 'package:on_chain/solana/solana.dart' hide Store;
946 """;
947 const solanaCwPart = "part 'cw_solana.dart';";
948 const solanaContent = """
949 abstract class Solana {
950 List<String> getSolanaWordList(String language);
951 WalletService createSolanaWalletService(bool isDirect);
952 WalletCredentials createSolanaNewWalletCredentials(
953 {required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? passphrase});
954 WalletCredentials createSolanaRestoreWalletFromSeedCredentials(
955 {required String name, required String mnemonic, required String password, String? passphrase});
956 WalletCredentials createSolanaRestoreWalletFromPrivateKey(
957 {required String name, required String privateKey, required String password});
958
959 String getAddress(WalletBase wallet);
960 String getPrivateKey(WalletBase wallet);
961 String getPublicKey(WalletBase wallet);
962
963 Object createSolanaTransactionCredentials(
964 List<Output> outputs, {
965 required CryptoCurrency currency,
966 });
967
968 Object createSolanaTransactionCredentialsRaw(
969 List<OutputInfo> outputs, {
970 required CryptoCurrency currency,
971 });
972 List<CryptoCurrency> getSPLTokenCurrencies(WalletBase wallet);
973 Future<void> addSPLToken(
974 WalletBase wallet,
975 CryptoCurrency token,
976 String contractAddress,
977 );
978 Future<void> deleteSPLToken(WalletBase wallet, CryptoCurrency token);
979 Future<CryptoCurrency?> getSPLToken(WalletBase wallet, String contractAddress);
980
981 CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
982 String getTokenAddress(CryptoCurrency asset);
983 List<int>? getValidationLength(CryptoCurrency type);
984 Money? getEstimateFees(WalletBase wallet);
985 List<SPLToken> getDefaultSPLTokens();
986 List<String> getDefaultTokenContractAddresses();
987 List<String> getDefaultTokenSymbols();
988 bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);
989 Future<bool?> isTokenVerifiedOnJupiter(WalletBase wallet, String mintAddress);
990
991 // Jupiter swap transaction handling
992 // Signs and prepares a base64-encoded unsigned transaction for sending
993 Future<PendingTransaction> signAndPrepareJupiterSwapTransaction(
994 WalletBase wallet,
995 String base64Transaction,
996 String requestId,
997 String destinationAddress,
998 Money amount,
999 Money fee,
1000 );
1001
1002 // Fast transaction update after sending
1003 // Polls for a specific transaction by signature with exponential backoff
1004 // Falls back to full refresh if transaction is not found after max retries
1005 Future<void> pollForTransaction(
1006 WalletBase wallet,
1007 String signature, {
1008 Duration initialDelay = const Duration(seconds: 1),
1009 int maxRetries = 5,
1010 });
1011
1012 // Updates balances for specific tokens by mint addresses
1013 // Also updates native SOL balance
1014 // If tokenMints is null or empty, updates all tokens (full refresh)
1015 Future<void> updateTokenBalances(
1016 WalletBase wallet, {
1017 List<String>? tokenMints,
1018 });
1019
1020 Future<void> discoverAndAddWalletTokens(WalletBase wallet);
1021
1022 TransactionInfo getTransactionInfo({
1023 required String id,
1024 required DateTime blockTime,
1025 required String to,
1026 required String from,
1027 required TransactionDirection direction,
1028 required Money amount,
1029 required bool isPending,
1030 required Money fee,
1031 });
1032 }
1033
1034 class JupiterSwapFailedException implements Exception {
1035 final String message;
1036 final String signature;
1037 final num? errorCode;
1038 final String? errorMessage;
1039
1040 JupiterSwapFailedException({
1041 required this.message,
1042 required this.signature,
1043 this.errorCode,
1044 this.errorMessage,
1045 });
1046
1047 @override
1048 String toString() => message;
1049 }
1050
1051 """;
1052
1053 const solanaEmptyDefinition = 'Solana? solana;\n';
1054 const solanaCWDefinition = 'Solana? solana = CWSolana();\n';
1055
1056 final output = '$solanaCommonHeaders\n' +
1057 (hasImplementation ? '$solanaCWHeaders\n' : '\n') +
1058 (hasImplementation ? '$solanaCwPart\n\n' : '\n') +
1059 (hasImplementation ? solanaCWDefinition : solanaEmptyDefinition) +
1060 '\n' +
1061 solanaContent;
1062
1063 if (outputFile.existsSync()) {
1064 await outputFile.delete();
1065 }
1066
1067 await outputFile.writeAsString(output);
1068 }
1069
1070 Future<void> generateTron(bool hasImplementation) async {
1071 final outputFile = File(tronOutputPath);
1072 const tronCommonHeaders = """
1073 import 'package:cake_wallet/view_model/send/output.dart';
1074 import 'package:cw_core/amount/money.dart';
1075 import 'package:cw_core/crypto_currency.dart';
1076 import 'package:cw_core/pending_transaction.dart';
1077 import 'package:cw_core/output_info.dart';
1078 import 'package:cw_core/transaction_info.dart';
1079 import 'package:cw_core/wallet_base.dart';
1080 import 'package:cw_core/wallet_credentials.dart';
1081 import 'package:cw_core/wallet_info.dart';
1082 import 'package:cw_core/wallet_service.dart';
1083 import 'package:cw_core/tron_token.dart';
1084 import 'package:cw_core/transaction_direction.dart';
1085
1086 """;
1087 const tronCWHeaders = """
1088 import 'package:cw_evm/evm_chain_mnemonics.dart';
1089 import 'package:cw_tron/tron_transaction_credentials.dart';
1090 import 'package:cw_tron/tron_transaction_info.dart';
1091 import 'package:cw_tron/tron_wallet_creation_credentials.dart';
1092
1093 import 'package:cw_tron/tron_client.dart';
1094 import 'package:cw_tron/tron_wallet.dart';
1095 import 'package:cw_tron/tron_wallet_service.dart';
1096 import 'package:cw_tron/default_tron_tokens.dart';
1097
1098 """;
1099 const tronCwPart = "part 'cw_tron.dart';";
1100 const tronContent = """
1101 abstract class Tron {
1102 List<String> getTronWordList(String language);
1103 WalletService createTronWalletService(bool isDirect);
1104 WalletCredentials createTronNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? passphrase});
1105 WalletCredentials createTronRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
1106 WalletCredentials createTronRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
1107 String getAddress(WalletBase wallet);
1108
1109 Object createTronTransactionCredentials(
1110 List<Output> outputs, {
1111 required CryptoCurrency currency,
1112 });
1113
1114 List<CryptoCurrency> getTronTokenCurrencies(WalletBase wallet);
1115 Future<void> addTronToken(WalletBase wallet, CryptoCurrency token, String contractAddress);
1116 Future<void> deleteTronToken(WalletBase wallet, CryptoCurrency token);
1117 Future<CryptoCurrency?> getTronToken(WalletBase wallet, String contractAddress);
1118
1119 CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
1120 String getTokenAddress(CryptoCurrency asset);
1121 String getTronBase58Address(String hexAddress, WalletBase wallet);
1122
1123 Money? getTronNativeEstimatedFee(WalletBase wallet);
1124 Money? getTronTRC20EstimatedFee(WalletBase wallet);
1125
1126 void updateTronGridUsageState(WalletBase wallet, bool isEnabled);
1127 List<TronToken> getDefaultTronTokens();
1128 List<String> getDefaultTokenContractAddresses();
1129 List<String> getDefaultTokenSymbols();
1130 bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);
1131 TransactionInfo getTransactionInfo({
1132 required String id,
1133 required Money amount,
1134 Money? fee,
1135 required TransactionDirection direction,
1136 required DateTime blockTime,
1137 String? to,
1138 String? from,
1139 required bool isPending,
1140 });
1141 }
1142 """;
1143
1144 const tronEmptyDefinition = 'Tron? tron;\n';
1145 const tronCWDefinition = 'Tron? tron = CWTron();\n';
1146
1147 final output = '$tronCommonHeaders\n' +
1148 (hasImplementation ? '$tronCWHeaders\n' : '\n') +
1149 (hasImplementation ? '$tronCwPart\n\n' : '\n') +
1150 (hasImplementation ? tronCWDefinition : tronEmptyDefinition) +
1151 '\n' +
1152 tronContent;
1153
1154 if (outputFile.existsSync()) {
1155 await outputFile.delete();
1156 }
1157
1158 await outputFile.writeAsString(output);
1159 }
1160
1161 Future<void> generateZano(bool hasImplementation) async {
1162 final outputFile = File(zanoOutputPath);
1163 const zanoCommonHeaders = """
1164 import 'package:cake_wallet/utils/language_list.dart';
1165 import 'package:cake_wallet/view_model/send/output.dart';
1166 import 'package:collection/collection.dart';
1167 import 'package:cw_core/crypto_currency.dart';
1168 import 'package:cw_core/monero_transaction_priority.dart';
1169 import 'package:cw_core/output_info.dart';
1170 import 'package:cw_core/transaction_history.dart';
1171 import 'package:cw_core/transaction_info.dart';
1172 import 'package:cw_core/transaction_priority.dart';
1173 import 'package:cw_core/wallet_base.dart';
1174 import 'package:cw_core/wallet_credentials.dart';
1175 import 'package:cw_core/wallet_info.dart';
1176 import 'package:cw_core/wallet_service.dart';
1177 import 'package:cw_core/zano_asset.dart';
1178 import 'package:hive/hive.dart';
1179 """;
1180 const zanoCWHeaders = """
1181 import 'package:cw_zano/mnemonics/english.dart';
1182 import 'package:cw_zano/model/zano_transaction_credentials.dart';
1183 import 'package:cw_zano/model/zano_transaction_info.dart';
1184 import 'package:cw_zano/zano_formatter.dart';
1185 import 'package:cw_zano/zano_wallet.dart';
1186 import 'package:cw_zano/zano_wallet_service.dart';
1187 import 'package:cw_zano/zano_wallet_api.dart' as api;
1188 import 'package:cw_zano/zano_utils.dart';
1189 """;
1190 const zanoCwPart = "part 'cw_zano.dart';";
1191 const zanoContent = """
1192 abstract class Zano {
1193 TransactionPriority getDefaultTransactionPriority();
1194 TransactionPriority deserializeMoneroTransactionPriority({required int raw});
1195 List<TransactionPriority> getTransactionPriorities();
1196 List<String> getWordList(String language);
1197
1198 WalletCredentials createZanoRestoreWalletFromSeedCredentials({required String name, required String password, required String passphrase, required int height, required String mnemonic});
1199 WalletCredentials createZanoNewWalletCredentials({required String name, required String? password, required String? passphrase});
1200 Map<String, String> getKeys(Object wallet);
1201 Object createZanoTransactionCredentials({required List<Output> outputs, required TransactionPriority priority, required CryptoCurrency currency});
1202 double formatterIntAmountToDouble({required int amount, required CryptoCurrency currency, required bool forFee});
1203 int formatterParseAmount({required String amount, required CryptoCurrency currency});
1204 WalletService createZanoWalletService();
1205 CryptoCurrency? assetOfTransaction(WalletBase wallet, TransactionInfo tx);
1206 List<ZanoAsset> getZanoAssets(WalletBase wallet);
1207 String getZanoAssetAddress(CryptoCurrency asset);
1208 Future<void> changeZanoAssetAvailability(WalletBase wallet, CryptoCurrency token);
1209 Future<CryptoCurrency> addZanoAssetById(WalletBase wallet, String assetId);
1210 Future<void> deleteZanoAsset(WalletBase wallet, CryptoCurrency token);
1211 Future<CryptoCurrency?> getZanoAsset(WalletBase wallet, String contractAddress);
1212 String getAddress(WalletBase wallet);
1213 bool validateAddress(String address);
1214 Map<String, List<int>> debugCallLength();
1215 bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);
1216 }
1217 """;
1218 const zanoEmptyDefinition = 'Zano? zano;\n';
1219 const zanoCWDefinition = 'Zano? zano = CWZano();\n';
1220
1221 final output = '$zanoCommonHeaders\n' +
1222 (hasImplementation ? '$zanoCWHeaders\n' : '\n') +
1223 (hasImplementation ? '$zanoCwPart\n\n' : '\n') +
1224 (hasImplementation ? zanoCWDefinition : zanoEmptyDefinition) +
1225 '\n' +
1226 zanoContent;
1227
1228 if (outputFile.existsSync()) {
1229 await outputFile.delete();
1230 }
1231
1232 await outputFile.writeAsString(output);
1233 }
1234
1235 Future<void> generateDecred(bool hasImplementation) async {
1236 final outputFile = File(decredOutputPath);
1237 const decredCommonHeaders = """
1238 import 'package:cw_core/wallet_credentials.dart';
1239 import 'package:cw_core/address_info.dart';
1240 import 'package:cw_core/wallet_info.dart';
1241 import 'package:cw_core/transaction_priority.dart';
1242 import 'package:cw_core/output_info.dart';
1243 import 'package:cw_core/wallet_service.dart';
1244 import 'package:cw_core/unspent_transaction_output.dart';
1245 import 'package:cw_core/unspent_coins_info.dart';
1246 import 'package:cake_wallet/view_model/send/output.dart';
1247 import 'package:hive/hive.dart';
1248 """;
1249 const decredCWHeaders = """
1250 import 'package:cw_decred/transaction_priority.dart';
1251 import 'package:cw_decred/wallet.dart';
1252 import 'package:cw_decred/wallet_service.dart';
1253 import 'package:cw_decred/wallet_creation_credentials.dart';
1254 import 'package:cw_decred/transaction_credentials.dart';
1255 import 'package:cw_decred/mnemonic.dart';
1256 """;
1257 const decredCwPart = "part 'cw_decred.dart';";
1258 const decredContent = """
1259
1260 abstract class Decred {
1261 WalletCredentials createDecredNewWalletCredentials(
1262 {required String name, String? password, String? passphrase, String? mnemonic, WalletInfo? walletInfo});
1263 WalletCredentials createDecredRestoreWalletFromSeedCredentials(
1264 {required String name, required String mnemonic, required String password, String? passphrase});
1265 WalletCredentials createDecredRestoreWalletFromPubkeyCredentials(
1266 {required String name, required String pubkey, required String password});
1267 WalletService createDecredWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect);
1268
1269 List<TransactionPriority> getTransactionPriorities();
1270 TransactionPriority getDecredTransactionPriorityMedium();
1271 TransactionPriority getDecredTransactionPrioritySlow();
1272 TransactionPriority deserializeDecredTransactionPriority(int raw);
1273
1274 Object createDecredTransactionCredentials(List<Output> outputs, TransactionPriority priority);
1275
1276 List<WalletInfoAddressInfo> getAddressInfos(Object wallet);
1277 Future<void> updateAddress(Object wallet, String address, String label);
1278 Future<void> generateNewAddress(Object wallet, String label);
1279
1280 List<Unspent> getUnspents(Object wallet);
1281 void updateUnspents(Object wallet);
1282
1283 int heightByDate(DateTime date);
1284
1285 List<String> getDecredWordList();
1286
1287 String pubkey(Object wallet);
1288 }
1289 """;
1290
1291 const decredEmptyDefinition = 'Decred? decred;\n';
1292 const decredCWDefinition = 'Decred? decred = CWDecred();\n';
1293
1294 final output = '$decredCommonHeaders\n' +
1295 (hasImplementation ? '$decredCWHeaders\n' : '\n') +
1296 (hasImplementation ? '$decredCwPart\n\n' : '\n') +
1297 (hasImplementation ? decredCWDefinition : decredEmptyDefinition) +
1298 '\n' +
1299 decredContent;
1300
1301 if (outputFile.existsSync()) {
1302 await outputFile.delete();
1303 }
1304
1305 await outputFile.writeAsString(output);
1306 }
1307
1308 Future<void> generateDogecoin(bool hasImplementation) async {
1309 final outputFile = File(dogecoinOutputPath);
1310 const dogecoinCommonHeaders = """
1311 import 'package:cw_core/transaction_priority.dart';
1312 import 'package:cw_core/unspent_coins_info.dart';
1313 import 'package:cw_core/wallet_credentials.dart';
1314 import 'package:cw_core/wallet_info.dart';
1315 import 'package:cw_core/wallet_service.dart';
1316 import 'package:hive/hive.dart';
1317 """;
1318 const dogecoinCWHeaders = """
1319 import 'package:cw_dogecoin/cw_dogecoin.dart';
1320 """;
1321 const dogecoinCwPart = "part 'cw_dogecoin.dart';";
1322 const dogecoinContent = """
1323 abstract class DogeCoin {
1324
1325 WalletService createDogeCoinWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect);
1326
1327 WalletCredentials createDogeCoinNewWalletCredentials(
1328 {required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic});
1329
1330 WalletCredentials createDogeCoinRestoreWalletFromSeedCredentials(
1331 {required String name, required String mnemonic, required String password, String? passphrase});
1332
1333 TransactionPriority deserializeDogeCoinTransactionPriority(int raw);
1334
1335 TransactionPriority getDefaultTransactionPriority();
1336
1337 List<TransactionPriority> getTransactionPriorities();
1338
1339 TransactionPriority getDogeCoinTransactionPrioritySlow();
1340 }
1341 """;
1342
1343 const dogecoinEmptyDefinition = 'DogeCoin? dogecoin;\n';
1344 const dogecoinCWDefinition = 'DogeCoin? dogecoin = CWDogeCoin();\n';
1345
1346 final output = '$dogecoinCommonHeaders\n' +
1347 (hasImplementation ? '$dogecoinCWHeaders\n' : '\n') +
1348 (hasImplementation ? '$dogecoinCwPart\n\n' : '\n') +
1349 (hasImplementation ? dogecoinCWDefinition : dogecoinEmptyDefinition) +
1350 '\n' +
1351 dogecoinContent;
1352
1353 if (outputFile.existsSync()) {
1354 await outputFile.delete();
1355 }
1356
1357 await outputFile.writeAsString(output);
1358 }
1359
1360 Future<void> generateEVM(bool hasImplementation) async {
1361 final outputFile = File(evmOutputPath);
1362 const evmCommonHeaders = """
1363 import 'dart:math' as math;
1364 import 'package:cake_wallet/core/utilities.dart';
1365 import 'package:cake_wallet/view_model/send/output.dart';
1366 import 'package:cw_core/amount/money.dart';
1367 import 'package:cw_core/pending_transaction.dart';
1368 import 'package:cw_core/crypto_currency.dart';
1369 import 'package:cw_core/erc20_token.dart';
1370 import 'package:cw_core/hardware/hardware_account_data.dart';
1371 import 'package:cw_core/hardware/hardware_wallet_service.dart';
1372 import 'package:cw_core/output_info.dart';
1373 import 'package:cw_core/pending_transaction.dart';
1374 import 'package:cw_core/transaction_info.dart';
1375 import 'package:cw_core/transaction_priority.dart';
1376 import 'package:cw_core/wallet_base.dart';
1377 import 'package:cw_core/wallet_credentials.dart';
1378 import 'package:cw_core/wallet_info.dart';
1379 import 'package:cw_core/wallet_service.dart';
1380 import 'package:cw_core/wallet_type.dart';
1381 import 'package:cw_core/node.dart';
1382 import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
1383 import 'package:bitbox_flutter/bitbox_flutter.dart' as bitbox;
1384 import 'package:trezor_connect/trezor_connect.dart' as trezor;
1385 import 'package:web3dart/web3dart.dart';
1386 import 'package:cw_core/transaction_direction.dart';
1387
1388 """;
1389 const evmCWHeaders = """
1390 import 'package:cake_wallet/core/fiat_conversion_service.dart';
1391 import 'package:cake_wallet/di.dart';
1392 import 'package:cake_wallet/entities/fiat_api_mode.dart';
1393 import 'package:cake_wallet/entities/fiat_currency.dart';
1394 import 'package:cake_wallet/store/settings_store.dart';
1395 import 'package:cw_evm/utils/evm_chain_formatter.dart';
1396 import 'package:cw_evm/evm_chain_mnemonics.dart';
1397 import 'package:cw_evm/pending_evm_chain_transaction.dart';
1398 import 'package:cw_evm/evm_chain_registry.dart';
1399 import 'package:cw_evm/evm_erc20_balance.dart';
1400 import 'package:cw_evm/evm_chain_transaction_credentials.dart';
1401 import 'package:cw_evm/evm_chain_transaction_info.dart';
1402 import 'package:cw_evm/evm_chain_transaction_priority.dart';
1403 import 'package:cw_evm/hardware/evm_chain_bitbox_credentials.dart';
1404 import 'package:cw_evm/hardware/evm_chain_ledger_credentials.dart';
1405 import 'package:cw_evm/hardware/evm_chain_trezor_credentials.dart';
1406 import 'package:cw_evm/evm_chain_wallet.dart';
1407 import 'package:cw_evm/hardware/evm_chain_bitbox_service.dart';
1408 import 'package:cw_evm/hardware/evm_chain_ledger_service.dart';
1409 import 'package:cw_evm/hardware/evm_chain_trezor_service.dart';
1410 import 'package:cw_evm/evm_chain_wallet_service.dart';
1411 import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart';
1412 import 'package:cw_evm/utils/evm_chain_utils.dart';
1413 import 'package:cw_evm/evm_chain_default_tokens.dart';
1414 import 'package:cw_evm/deuro/deuro_savings.dart';
1415 import 'package:cw_evm/usdt0/usdt0_config.dart';
1416 import 'package:cw_evm/usdt0/usdt0_quote.dart';
1417 import 'package:cw_evm/usdt0/usdt0_service.dart';
1418 import 'package:eth_sig_util/util/utils.dart';
1419 export 'package:cw_evm/evm_chain_transaction_priority.dart';
1420 export 'package:cw_evm/evm_erc20_balance.dart';
1421 export 'package:cw_evm/usdt0/usdt0_quote.dart';
1422
1423 """;
1424 const evmCwPart = "part 'cw_evm.dart';";
1425 const evmContent = """
1426 /// Unified abstract class for all EVM chains
1427 ///
1428 /// This replaces separate proxy classes (Ethereum, Polygon, Base, Arbitrum)
1429 /// with a single unified interface that works for all EVM chains.
1430 /// Methods take WalletType parameter to determine chain-specific behavior.
1431 abstract class EVM {
1432 List<String> getEVMWordList(String language);
1433
1434 /// Create unified wallet service for any EVM chain
1435 WalletService createEVMWalletService(WalletType walletType, bool isDirect);
1436
1437 /// Generic credential creation - uses WalletType
1438 WalletCredentials createEVMNewWalletCredentials({
1439 required String name,
1440 WalletInfo? walletInfo,
1441 String? password,
1442 String? mnemonic,
1443 String? passphrase,
1444 });
1445
1446 WalletCredentials createEVMRestoreWalletFromSeedCredentials({
1447 required String name,
1448 required String mnemonic,
1449 required String password,
1450 String? passphrase,
1451 });
1452
1453 WalletCredentials createEVMRestoreWalletFromPrivateKey({
1454 required String name,
1455 required String privateKey,
1456 required String password,
1457 });
1458
1459 WalletCredentials createEVMHardwareWalletCredentials({
1460 required String name,
1461 required HardwareAccountData hwAccountData,
1462 WalletInfo? walletInfo,
1463 });
1464
1465 // Generic methods that work for all EVM chains
1466 String getAddress(WalletBase wallet);
1467 String getPrivateKey(WalletBase wallet);
1468 String getPublicKey(WalletBase wallet);
1469 TransactionPriority getDefaultTransactionPriority();
1470 TransactionPriority getEVMTransactionPrioritySlow();
1471 List<TransactionPriority> getTransactionPriorities();
1472 TransactionPriority deserializeEVMTransactionPriority(int raw);
1473
1474 Object createEVMTransactionCredentials(
1475 List<Output> outputs, {
1476 required TransactionPriority? priority,
1477 required CryptoCurrency currency,
1478 int? feeRate,
1479 bool useBlinkProtection = true,
1480 });
1481
1482 Object createEVMTransactionCredentialsRaw(
1483 List<OutputInfo> outputs, {
1484 TransactionPriority? priority,
1485 required CryptoCurrency currency,
1486 required int feeRate,
1487 bool useBlinkProtection = true,
1488 });
1489
1490 int formatterEVMParseAmount(String amount);
1491
1492 List<Erc20Token> getERC20Currencies(WalletBase wallet);
1493 Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token);
1494 Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token);
1495 Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token);
1496 Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress);
1497
1498 CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
1499 void updateScanProviderUsageState(WalletBase wallet, bool isEnabled);
1500 Web3Client? getWeb3Client(WalletBase wallet);
1501 String getTokenAddress(CryptoCurrency asset);
1502
1503 Future<bool> isApprovalRequired(
1504 WalletBase wallet,
1505 String tokenContract,
1506 String spender,
1507 BigInt requiredAmount,
1508 );
1509
1510 Future<BigInt?> getAllowance(
1511 WalletBase wallet,
1512 String tokenContract,
1513 String spender);
1514
1515 Future<PendingTransaction> createTokenApproval(
1516 WalletBase wallet,
1517 Money amount,
1518 String spender,
1519 TransactionPriority? priority,
1520 {bool useBlinkProtection = true}
1521 );
1522
1523 Future<PendingTransaction> createRawCallDataTransaction(
1524 WalletBase wallet,
1525 String to,
1526 String dataHex,
1527 Money valueWei,
1528 TransactionPriority? priority,
1529 {bool useBlinkProtection = true,
1530 String? sourceTokenAddress,
1531 BigInt? sourceTokenAmount}
1532 );
1533
1534 // Hardware wallet methods
1535 Future<void> setHardwareWalletService(WalletBase wallet, HardwareWalletService service);
1536 HardwareWalletService getLedgerHardwareWalletService(ledger.LedgerConnection connection);
1537 HardwareWalletService getBitboxHardwareWalletService(bitbox.BitboxManager manager);
1538 HardwareWalletService getTrezorHardwareWalletService(trezor.TrezorConnect connect);
1539
1540 // Utility methods
1541 List<Erc20Token> getDefaultTokensByChainId(int chainId);
1542 List<String> getDefaultTokenContractAddresses(WalletBase wallet);
1543 List<String> getDefaultTokenSymbols(WalletBase wallet);
1544 bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);
1545 String? getEVMNativeEstimatedFee(WalletBase wallet);
1546 String? getEVMERC20EstimatedFee(WalletBase wallet);
1547
1548 // Chain-specific integrations (optional, can be null for non-Ethereum chains)
1549 Future<Money>? getDEuroSavingsBalance(WalletBase wallet) => null;
1550 Future<Money>? getDEuroSavingsV1Balance(WalletBase wallet) => null;
1551 Future<Money>? getDEuroAccruedInterest(WalletBase wallet) => null;
1552 Future<BigInt>? getDEuroInterestRate(WalletBase wallet) => null;
1553 Future<BigInt>? getDEuroSavingsApproved(WalletBase wallet) => null;
1554 Future<PendingTransaction>? withdrawDEuroSavingV1(WalletBase wallet, TransactionPriority priority) => null;
1555 Future<PendingTransaction>? addDEuroSaving(WalletBase wallet, BigInt amount, TransactionPriority priority) => null;
1556 Future<PendingTransaction>? removeDEuroSaving(WalletBase wallet, BigInt amount, TransactionPriority priority) => null;
1557 Future<PendingTransaction>? reinvestDEuroInterest(WalletBase wallet, TransactionPriority priority) => null;
1558 Future<PendingTransaction>? enableDEuroSaving(WalletBase wallet, TransactionPriority priority) => null;
1559
1560 // Registry helper methods (for backward compatibility helpers)
1561 int getChainIdByWalletType(WalletType walletType);
1562 String getChainNameByWalletType(WalletType walletType);
1563 String getTokenNameByWalletType(WalletType walletType);
1564 String getCaip2ByChainId(int chainId);
1565 int? getChainIdByTag(String tag);
1566 int? getChainIdByTitle(String title);
1567 WalletType? getWalletTypeByChainId(int chainId);
1568 String getChainNameByChainId(int chainId);
1569 String getTokenNameByChainId(int chainId);
1570 // Chain selection methods
1571 List<ChainInfo> getAllChains();
1572 ChainInfo? getCurrentChain(WalletBase wallet);
1573 ChainInfo? getChainInfoByChainId(int chainId);
1574
1575
1576 int? getSelectedChainId(WalletBase wallet);
1577 Future<void> selectChain(WalletBase wallet, int chainId, {required Node node});
1578
1579 String? getExplorerUrlForChainId(int chainId, {bool showProtocol = true});
1580
1581 Future<bool?> getTransactionReceipt(WalletBase wallet, String txHash);
1582
1583 bool hasPriorityFee(int chainId);
1584
1585 bool isUSDT0Token(WalletBase wallet, CryptoCurrency token);
1586 List<ChainInfo> getUSDT0DestinationChains(WalletBase wallet);
1587
1588 Future<BridgeQuote> quoteUSDT0Transfer({
1589 required WalletBase wallet,
1590 required int sourceChainId,
1591 required int destinationChainId,
1592 required BigInt amount,
1593 required String recipientAddress,
1594 });
1595
1596 Future<PendingTransaction> executeUSDT0Transfer({
1597 required WalletBase wallet,
1598 required CryptoCurrency token,
1599 required int sourceChainId,
1600 required int destinationChainId,
1601 required BigInt amount,
1602 required String recipientAddress,
1603 required BridgeQuote quote,
1604 required TransactionPriority priority,
1605 bool useBlinkProtection = true,
1606 });
1607
1608 Future<EvmWalletConnectFeeQuote?> getWCBufferedFeeQuote(
1609 WalletBase wallet,
1610 TransactionPriority priority,
1611 );
1612
1613 TransactionInfo getTransactionInfo({
1614 required String id,
1615 required int height,
1616 required Money amount,
1617 required Money fee,
1618 required String tokenSymbol,
1619 int exponent = 18,
1620 required TransactionDirection direction,
1621 required bool isPending,
1622 required DateTime date,
1623 required int confirmations,
1624 String? to,
1625 String? from,
1626 String? evmSignatureName,
1627 String? contractAddress,
1628 required int chainId,
1629 });
1630
1631 Future<void> discoverAndAddWalletTokens(WalletBase wallet);
1632 }
1633
1634 class ChainInfo {
1635 const ChainInfo({
1636 required this.chainId,
1637 required this.name,
1638 required this.shortCode,
1639 required this.currency,
1640 });
1641
1642 final int chainId;
1643 final String name;
1644 final String shortCode;
1645 final CryptoCurrency currency;
1646
1647 @override
1648 bool operator ==(Object other) =>
1649 identical(this, other) ||
1650 other is ChainInfo && runtimeType == other.runtimeType && chainId == other.chainId;
1651
1652 @override
1653 int get hashCode => chainId.hashCode;
1654 }
1655
1656 class EvmWalletConnectFeeQuote {
1657 const EvmWalletConnectFeeQuote({
1658 required this.maxFeePerGasWei,
1659 required this.maxPriorityFeePerGasWei,
1660 this.latestBaseFeeWei,
1661 });
1662
1663 final int maxFeePerGasWei;
1664 final int maxPriorityFeePerGasWei;
1665 final int? latestBaseFeeWei;
1666 }
1667
1668 class BridgeQuote {
1669 const BridgeQuote({
1670 required this.nativeFee,
1671 required this.lzTokenFee,
1672 });
1673
1674 final BigInt nativeFee;
1675 final BigInt lzTokenFee;
1676 }
1677 """;
1678
1679 const evmEmptyDefinition = 'EVM? evm;\n';
1680 const evmCWDefinition = 'EVM? evm = CWEVM();\n';
1681
1682 final output = '$evmCommonHeaders\n' +
1683 (hasImplementation ? '$evmCWHeaders\n' : '\n') +
1684 (hasImplementation ? '$evmCwPart\n\n' : '\n') +
1685 (hasImplementation ? evmCWDefinition : evmEmptyDefinition) +
1686 '\n' +
1687 evmContent;
1688
1689 if (outputFile.existsSync()) {
1690 await outputFile.delete();
1691 }
1692
1693 await outputFile.writeAsString(output);
1694 }
1695
1696 Future<void> generateZcash(bool hasImplementation) async {
1697 final outputFile = File(zcashOutputPath);
1698 const zcashCommonHeaders = """
1699 import 'package:cake_wallet/view_model/send/output.dart';
1700 import 'package:cw_core/balance.dart';
1701 import 'package:cw_core/crypto_amount_format.dart';
1702 import 'package:cw_core/crypto_currency.dart';
1703 import 'package:cw_core/output_info.dart';
1704 import 'package:cw_core/transaction_history.dart';
1705 import 'package:cw_core/transaction_info.dart';
1706 import 'package:cw_core/transaction_priority.dart';
1707 import 'package:cw_core/monero_transaction_priority.dart';
1708 import 'package:cw_core/wallet_base.dart';
1709 import 'package:cw_core/wallet_credentials.dart';
1710 import 'package:cw_core/wallet_info.dart';
1711 import 'package:cw_core/wallet_service.dart';
1712 import 'package:cw_core/receive_page_option.dart';
1713 import 'package:cw_core/wallet_addresses.dart';
1714
1715 """;
1716 const zcashCWHeaders = """
1717 import 'package:cw_zcash/cw_zcash.dart';
1718 import 'package:cw_zcash/src/zcash_wallet_addresses.dart';
1719
1720 """;
1721 const zcashCwPart = "part 'cw_zcash.dart';";
1722 const zcashContent = """
1723 abstract class Zcash {
1724 List<String> getZcashWordList(String language);
1725 WalletService createZcashWalletService(bool isDirect);
1726 WalletCredentials createZcashNewWalletCredentials(
1727 {required String name,
1728 WalletInfo? walletInfo,
1729 String? password,
1730 String? mnemonic,
1731 required String? passphrase,
1732 int network = 0});
1733 WalletCredentials createZcashRestoreWalletFromSeedCredentials(
1734 {required String name,
1735 required String mnemonic,
1736 required String password,
1737 String? passphrase,
1738 required int? height,
1739 int network = 0});
1740 WalletCredentials createZcashRestoreWalletFromPrivateKey(
1741 {required String name, required String privateKey, required String password, required int height});
1742 String getAddress(WalletBase wallet);
1743 String getPrivateKey(WalletBase wallet);
1744 String getPublicKey(WalletBase wallet);
1745 Map<String, String> getKeys(Object wallet);
1746
1747 Object createZcashTransactionCredentials(
1748 List<Output> outputs, {
1749 required CryptoCurrency currency,
1750 int? feeRate,
1751 });
1752
1753 Object createZcashTransactionCredentialsRaw(
1754 List<OutputInfo> outputs, {
1755 required CryptoCurrency currency,
1756 required int feeRate,
1757 });
1758
1759 int formatterZcashParseAmount(String amount);
1760 double formatterZcashAmountToDouble({TransactionInfo? transaction, BigInt? amount});
1761 String formatterZcashAmountToString({required int amount});
1762
1763 List<WalletInfoAddressInfo> getAddressInfos(Object wallet);
1764
1765 TransactionPriority getDefaultTransactionPriority();
1766 TransactionPriority getZcashTransactionPriorityAutomatic();
1767 TransactionPriority deserializeZcashTransactionPriority({required int raw});
1768 List<TransactionPriority> getTransactionPriorities();
1769 ReceivePageOption getSelectedAddressType(Object wallet);
1770 dynamic getZcashAddressType(ReceivePageOption option);
1771 bool hasSelectedTransparentAddress(Object wallet);
1772 bool isRotatingAddressOption(ReceivePageOption option);
1773 Future<void> setAddressType(Object wallet, dynamic option);
1774 dynamic getOptionToType(ReceivePageOption option);
1775 void unlockDatabase(String password);
1776 Future<int> getHeightByDate(DateTime date);
1777 bool showMissingFundsCard(WalletBase wallet);
1778 Future<void> rescanInternalChange(WalletBase wallet);
1779 bool ironwoodActive(WalletAddresses walletAddresses);
1780 Future<bool> hasOrchardMigratableBalance(WalletBase wallet);
1781 }
1782 """;
1783
1784 const zcashEmptyDefinition = 'Zcash? zcash;\n';
1785 const zcashCWDefinition = 'Zcash? zcash = CWZcash();\n';
1786
1787 final output = '$zcashCommonHeaders\n' +
1788 (hasImplementation ? '$zcashCWHeaders\n' : '\n') +
1789 (hasImplementation ? '$zcashCwPart\n\n' : '\n') +
1790 (hasImplementation ? zcashCWDefinition : zcashEmptyDefinition) +
1791 '\n' +
1792 zcashContent;
1793
1794 if (outputFile.existsSync()) {
1795 await outputFile.delete();
1796 }
1797
1798 await outputFile.writeAsString(output);
1799 }
1800
1801 Future<void> generatePubspec({
1802 required bool hasMonero,
1803 required bool hasBitcoin,
1804 required bool hasEthereum,
1805 required bool hasNano,
1806 required bool hasBanano,
1807 required bool hasBitcoinCash,
1808 required bool hasFlutterSecureStorage,
1809 required bool hasPolygon,
1810 required bool hasSolana,
1811 required bool hasTron,
1812 required bool hasWownero,
1813 required bool hasZano,
1814 required bool hasDecred,
1815 required bool hasDogecoin,
1816 required bool hasBase,
1817 required bool hasArbitrum,
1818 required bool hasBsc,
1819 required bool hasZcash,
1820 }) async {
1821 const cwCore = """
1822 cw_core:
1823 path: ./cw_core
1824 """;
1825 const cwMonero = """
1826 cw_monero:
1827 path: ./cw_monero
1828 """;
1829 const cwBitcoin = """
1830 cw_bitcoin:
1831 path: ./cw_bitcoin
1832 """;
1833 const flutterSecureStorage = """
1834 flutter_secure_storage:
1835 git:
1836 url: https://github.com/cake-tech/flutter_secure_storage.git
1837 path: flutter_secure_storage
1838 ref: ca897a08677edb443b366352dd7412735e098e7b
1839 """;
1840 const cwBitcoinCash = """
1841 cw_bitcoin_cash:
1842 path: ./cw_bitcoin_cash
1843 """;
1844 const cwNano = """
1845 cw_nano:
1846 path: ./cw_nano
1847 """;
1848 const cwBanano = """
1849 cw_banano:
1850 path: ./cw_banano
1851 """;
1852 const cwSolana = """
1853 cw_solana:
1854 path: ./cw_solana
1855 """;
1856 const cwEVM = """
1857 cw_evm:
1858 path: ./cw_evm
1859 """;
1860 const cwTron = """
1861 cw_tron:
1862 path: ./cw_tron
1863 """;
1864 const cwWownero = """
1865 cw_wownero:
1866 path: ./cw_wownero
1867 """;
1868 const cwZano = """
1869 cw_zano:
1870 path: ./cw_zano
1871 """;
1872 const cwDecred = """
1873 cw_decred:
1874 path: ./cw_decred
1875 """;
1876 const cwDogecoin = """
1877 cw_dogecoin:
1878 path: ./cw_dogecoin
1879 """;
1880 const cwZcash = """
1881 cw_zcash:
1882 path: ./cw_zcash
1883 """;
1884
1885 final inputFile = File(pubspecOutputPath);
1886 final inputText = await inputFile.readAsString();
1887 final inputLines = inputText.split('\n');
1888 final dependenciesIndex = inputLines.indexWhere((line) => Platform.isWindows
1889 // On Windows it could contains `\r` (Carriage Return). It could be fixed in newer dart versions.
1890 ? line.toLowerCase() == 'dependencies:\r' || line.toLowerCase() == 'dependencies:'
1891 : line.toLowerCase() == 'dependencies:');
1892 var output = cwCore;
1893
1894 if (hasMonero) {
1895 output += '\n$cwMonero';
1896 }
1897
1898 if (hasBitcoin) {
1899 output += '\n$cwBitcoin';
1900 }
1901
1902 if (hasNano) {
1903 output += '\n$cwNano';
1904 }
1905
1906 if (hasBanano) {
1907 output += '\n$cwBanano';
1908 }
1909
1910 if (hasBitcoinCash) {
1911 output += '\n$cwBitcoinCash';
1912 }
1913
1914 if (hasSolana) {
1915 output += '\n$cwSolana';
1916 }
1917
1918 if (hasTron) {
1919 output += '\n$cwTron';
1920 }
1921
1922 if (hasDecred) {
1923 output += '\n$cwDecred';
1924 }
1925
1926 if (hasFlutterSecureStorage) {
1927 output += '\n$flutterSecureStorage\n';
1928 }
1929
1930 if (hasEthereum || hasPolygon || hasBase || hasArbitrum || hasBsc) {
1931 output += '\n$cwEVM';
1932 }
1933
1934 if (hasWownero) {
1935 output += '\n$cwWownero';
1936 }
1937
1938 if (hasZano) {
1939 output += '\n$cwZano';
1940 }
1941
1942 if (hasDogecoin) {
1943 output += '\n$cwDogecoin';
1944 }
1945
1946 if (hasZcash) {
1947 output += '\n$cwZcash';
1948 }
1949
1950 final outputLines = output.split('\n');
1951 inputLines.insertAll(dependenciesIndex + 1, outputLines);
1952 final outputContent = inputLines.join('\n');
1953 final outputFile = File(pubspecOutputPath);
1954
1955 if (outputFile.existsSync()) {
1956 await outputFile.delete();
1957 }
1958
1959 await outputFile.writeAsString(outputContent);
1960 }
1961
1962 Future<void> generateWalletTypes({
1963 required bool hasMonero,
1964 required bool hasBitcoin,
1965 required bool hasEthereum,
1966 required bool hasNano,
1967 required bool hasBanano,
1968 required bool hasBitcoinCash,
1969 required bool hasPolygon,
1970 required bool hasSolana,
1971 required bool hasTron,
1972 required bool hasWownero,
1973 required bool hasZano,
1974 required bool hasDecred,
1975 required bool hasDogecoin,
1976 required bool hasBase,
1977 required bool hasArbitrum,
1978 required bool hasBsc,
1979 required bool hasZcash,
1980 }) async {
1981 final walletTypesFile = File(walletTypesPath);
1982
1983 if (walletTypesFile.existsSync()) {
1984 await walletTypesFile.delete();
1985 }
1986
1987 const outputHeader = "import 'package:cw_core/wallet_type.dart';";
1988 const outputDefinition = 'final availableWalletTypes = <WalletType>[';
1989 var outputContent = outputHeader + '\n\n' + outputDefinition + '\n';
1990
1991 if (hasMonero) {
1992 outputContent += '\tWalletType.monero,\n';
1993 }
1994
1995 if (hasBitcoin) {
1996 outputContent += '\tWalletType.bitcoin,\n';
1997 }
1998
1999 if (hasEthereum) {
2000 outputContent += '\tWalletType.ethereum,\n';
2001 }
2002
2003 if (hasBsc) {
2004 outputContent += '\tWalletType.bsc,\n';
2005 }
2006
2007 if (hasSolana) {
2008 outputContent += '\tWalletType.solana,\n';
2009 }
2010
2011 if (hasZcash) {
2012 outputContent += '\tWalletType.zcash,\n';
2013 }
2014
2015 if (hasTron) {
2016 outputContent += '\tWalletType.tron,\n';
2017 }
2018
2019 if (hasDogecoin) {
2020 outputContent += '\tWalletType.dogecoin,\n';
2021 }
2022
2023 if (hasBitcoinCash) {
2024 outputContent += '\tWalletType.bitcoinCash,\n';
2025 }
2026
2027 if (hasBitcoin) {
2028 outputContent += '\tWalletType.litecoin,\n';
2029 }
2030
2031 if (hasBase) {
2032 outputContent += '\tWalletType.base,\n';
2033 }
2034
2035 if (hasArbitrum) {
2036 outputContent += '\tWalletType.arbitrum,\n';
2037 }
2038
2039 if (hasPolygon) {
2040 outputContent += '\tWalletType.polygon,\n';
2041 }
2042
2043 if (hasNano) {
2044 outputContent += '\tWalletType.nano,\n';
2045 }
2046
2047 if (hasDecred) {
2048 outputContent += '\tWalletType.decred,\n';
2049 }
2050
2051 if (hasZano) {
2052 outputContent += '\tWalletType.zano,\n';
2053 }
2054
2055 if (hasBanano) {
2056 outputContent += '\tWalletType.banano,\n';
2057 }
2058
2059 // if (hasWownero) {
2060 // outputContent += '\tWalletType.wownero,\n';
2061 // }
2062
2063 outputContent += '];\n';
2064 await walletTypesFile.writeAsString(outputContent);
2065 }
2066
2067 Future<void> injectSecureStorage(bool hasFlutterSecureStorage) async {
2068 const flutterSecureStorageHeader = """
2069 import 'dart:async';
2070 import 'dart:io';
2071 import 'package:flutter_secure_storage/flutter_secure_storage.dart';
2072 """;
2073 const abstractSecureStorage = """
2074 abstract class SecureStorage {
2075 Future<String?> read({required String key});
2076 Future<void> write({required String key, required String? value});
2077 Future<void> delete({required String key});
2078 Future<void> deleteAll();
2079 // Legacy
2080 Future<String?> readNoIOptions({required String key});
2081 Future<Map<String, String>> readAll();
2082 }""";
2083 const defaultSecureStorage = """
2084 class DefaultSecureStorage extends SecureStorage {
2085 DefaultSecureStorage._(this._secureStorage);
2086
2087 factory DefaultSecureStorage() => _instance;
2088
2089 static final _instance = DefaultSecureStorage._(FlutterSecureStorage(
2090 iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
2091 aOptions: AndroidOptions(encryptedSharedPreferences: true),
2092 ));
2093
2094 final FlutterSecureStorage _secureStorage;
2095
2096 @override
2097 Future<String?> read({required String key}) async => await _readInternal(key, false);
2098
2099 @override
2100 Future<void> write({required String key, required String? value}) async {
2101 // delete the value before writing on macOS because of a weird bug
2102 // https://github.com/mogol/flutter_secure_storage/issues/581
2103 if (Platform.isMacOS) {
2104 await _secureStorage.delete(key: key);
2105 }
2106 await _secureStorage.write(key: key, value: value);
2107 }
2108
2109 @override
2110 Future<void> delete({required String key}) async => _secureStorage.delete(key: key);
2111
2112 @override
2113 Future<void> deleteAll() async => _secureStorage.deleteAll();
2114
2115 @override
2116 Future<String?> readNoIOptions({required String key}) async => await _readInternal(key, true);
2117
2118 Future<String?> _readInternal(String key, bool useNoIOptions) async {
2119 return await _secureStorage.read(
2120 key: key,
2121 iOptions: useNoIOptions ? IOSOptions() : null,
2122 );
2123 }
2124
2125 @override
2126 Future<Map<String, String>> readAll() async {
2127 return await _secureStorage.readAll();
2128 }
2129 }""";
2130 const fakeSecureStorage = """
2131 class FakeSecureStorage extends SecureStorage {
2132 @override
2133 Future<String?> read({required String key}) async => null;
2134 @override
2135 Future<void> write({required String key, required String? value}) async {}
2136 @override
2137 Future<void> delete({required String key}) async {}
2138 @override
2139 Future<void> deleteAll() async {}
2140 @override
2141 Future<String?> readNoIOptions({required String key}) async => null;
2142 @override
2143 Future<Map<String, String>> readAll() async => {};
2144 }""";
2145 final outputFile = File(secureStoragePath);
2146 final header = hasFlutterSecureStorage
2147 ? '${flutterSecureStorageHeader}\n\nfinal SecureStorage secureStorageShared = DefaultSecureStorage();\n'
2148 : 'final SecureStorage secureStorageShared = FakeSecureStorage();\n';
2149 var output = '';
2150 if (outputFile.existsSync()) {
2151 await outputFile.delete();
2152 }
2153
2154 output += '${header}\n${abstractSecureStorage}\n\n';
2155
2156 if (hasFlutterSecureStorage) {
2157 output += '${defaultSecureStorage}\n';
2158 } else {
2159 output += '${fakeSecureStorage}\n';
2160 }
2161
2162 await outputFile.writeAsString(output);
2163 }