import 'dart:io'; const bitcoinOutputPath = 'lib/bitcoin/bitcoin.dart'; const moneroOutputPath = 'lib/monero/monero.dart'; const havenOutputPath = 'lib/haven/haven.dart'; const ethereumOutputPath = 'lib/ethereum/ethereum.dart'; const bitcoinCashOutputPath = 'lib/bitcoin_cash/bitcoin_cash.dart'; const nanoOutputPath = 'lib/nano/nano.dart'; const polygonOutputPath = 'lib/polygon/polygon.dart'; const lightningOutputPath = 'lib/lightning/lightning.dart'; const walletTypesPath = 'lib/wallet_types.g.dart'; const pubspecDefaultPath = 'pubspec_default.yaml'; const pubspecOutputPath = 'pubspec.yaml'; Future main(List args) async { const prefix = '--'; final hasBitcoin = args.contains('${prefix}bitcoin'); final hasMonero = args.contains('${prefix}monero'); final hasHaven = args.contains('${prefix}haven'); final hasEthereum = args.contains('${prefix}ethereum'); final hasBitcoinCash = args.contains('${prefix}bitcoinCash'); final hasNano = args.contains('${prefix}nano'); final hasBanano = args.contains('${prefix}banano'); final hasPolygon = args.contains('${prefix}polygon'); final hasLightning = args.contains('${prefix}lightning'); await generateBitcoin(hasBitcoin); await generateMonero(hasMonero); await generateHaven(hasHaven); await generateEthereum(hasEthereum); await generateBitcoinCash(hasBitcoinCash); await generateNano(hasNano); await generatePolygon(hasPolygon); await generateLightning(hasLightning); // await generateBanano(hasEthereum); await generatePubspec( hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum, hasNano: hasNano, hasBanano: hasBanano, hasBitcoinCash: hasBitcoinCash, hasPolygon: hasPolygon, hasLightning: hasLightning, ); await generateWalletTypes( hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum, hasNano: hasNano, hasBanano: hasBanano, hasBitcoinCash: hasBitcoinCash, hasPolygon: hasPolygon, hasLightning: hasLightning, ); } Future generateBitcoin(bool hasImplementation) async { final outputFile = File(bitcoinOutputPath); const bitcoinCommonHeaders = """ import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart';"""; const bitcoinCWHeaders = """ import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_bitcoin/bitcoin_wallet_service.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; import 'package:mobx/mobx.dart'; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; const bitcoinContent = """ class ElectrumSubAddress { ElectrumSubAddress({ required this.id, required this.name, required this.address, required this.txCount, required this.balance, required this.isChange}); final int id; final String name; final String address; final int txCount; final int balance; final bool isChange; } abstract class Bitcoin { TransactionPriority getMediumTransactionPriority(); WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({required String name, required String password, required String wif, WalletInfo? walletInfo}); WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo}); List getWordList(); Map getWalletKeys(Object wallet); List getTransactionPriorities(); List getLitecoinTransactionPriorities(); TransactionPriority deserializeBitcoinTransactionPriority(int raw); TransactionPriority deserializeLitecoinTransactionPriority(int raw); int getFeeRate(Object wallet, TransactionPriority priority); Future generateNewAddress(Object wallet, String label); Future updateAddress(Object wallet,String address, String label); Object createBitcoinTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}); Object createBitcoinTransactionCredentialsRaw(List outputs, {TransactionPriority? priority, required int feeRate}); List getAddresses(Object wallet); String getAddress(Object wallet); List getSubAddresses(Object wallet); String formatterBitcoinAmountToString({required int amount}); double formatterBitcoinAmountToDouble({required int amount}); int formatterStringDoubleToBitcoinAmount(String amount); String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate); List getUnspents(Object wallet); Future updateUnspents(Object wallet); WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource); WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource); TransactionPriority getBitcoinTransactionPriorityMedium(); TransactionPriority getLitecoinTransactionPriorityMedium(); TransactionPriority getBitcoinTransactionPrioritySlow(); TransactionPriority getLitecoinTransactionPrioritySlow(); } """; const bitcoinEmptyDefinition = 'Bitcoin? bitcoin;\n'; const bitcoinCWDefinition = 'Bitcoin? bitcoin = CWBitcoin();\n'; final output = '$bitcoinCommonHeaders\n' + (hasImplementation ? '$bitcoinCWHeaders\n' : '\n') + (hasImplementation ? '$bitcoinCwPart\n\n' : '\n') + (hasImplementation ? bitcoinCWDefinition : bitcoinEmptyDefinition) + '\n' + bitcoinContent; if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(output); } Future generateMonero(bool hasImplementation) async { final outputFile = File(moneroOutputPath); const moneroCommonHeaders = """ import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_monero/monero_unspent.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/output_info.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; import 'package:polyseed/polyseed.dart';"""; const moneroCWHeaders = """ import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_core/monero_amount_format.dart'; import 'package:cw_core/monero_transaction_priority.dart'; import 'package:cw_monero/monero_wallet_service.dart'; import 'package:cw_monero/monero_wallet.dart'; import 'package:cw_monero/monero_transaction_info.dart'; import 'package:cw_monero/monero_transaction_creation_credentials.dart'; import 'package:cw_core/account.dart' as monero_account; import 'package:cw_monero/api/wallet.dart' as monero_wallet_api; import 'package:cw_monero/mnemonics/english.dart'; import 'package:cw_monero/mnemonics/chinese_simplified.dart'; import 'package:cw_monero/mnemonics/dutch.dart'; import 'package:cw_monero/mnemonics/german.dart'; import 'package:cw_monero/mnemonics/japanese.dart'; import 'package:cw_monero/mnemonics/russian.dart'; import 'package:cw_monero/mnemonics/spanish.dart'; import 'package:cw_monero/mnemonics/portuguese.dart'; import 'package:cw_monero/mnemonics/french.dart'; import 'package:cw_monero/mnemonics/italian.dart'; import 'package:cw_monero/pending_monero_transaction.dart'; """; const moneroCwPart = "part 'cw_monero.dart';"; const moneroContent = """ class Account { Account({required this.id, required this.label, this.balance}); final int id; final String label; final String? balance; } class Subaddress { Subaddress({ required this.id, required this.label, required this.address}); final int id; final String label; final String address; } class MoneroBalance extends Balance { MoneroBalance({required this.fullBalance, required this.unlockedBalance}) : formattedFullBalance = monero!.formatterMoneroAmountToString(amount: fullBalance), formattedUnlockedBalance = monero!.formatterMoneroAmountToString(amount: unlockedBalance), super(unlockedBalance, fullBalance); MoneroBalance.fromString( {required this.formattedFullBalance, required this.formattedUnlockedBalance}) : fullBalance = monero!.formatterMoneroParseAmount(amount: formattedFullBalance), unlockedBalance = monero!.formatterMoneroParseAmount(amount: formattedUnlockedBalance), super(monero!.formatterMoneroParseAmount(amount: formattedUnlockedBalance), monero!.formatterMoneroParseAmount(amount: formattedFullBalance)); final int fullBalance; final int unlockedBalance; final String formattedFullBalance; final String formattedUnlockedBalance; @override String get formattedAvailableBalance => formattedUnlockedBalance; @override String get formattedAdditionalBalance => formattedFullBalance; } abstract class MoneroWalletDetails { @observable late Account account; @observable late MoneroBalance balance; } abstract class Monero { MoneroAccountList getAccountList(Object wallet); MoneroSubaddressList getSubaddressList(Object wallet); TransactionHistoryBase getTransactionHistory(Object wallet); MoneroWalletDetails getMoneroWalletDetails(Object wallet); String getTransactionAddress(Object wallet, int accountIndex, int addressIndex); String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex); int getHeightByDate({required DateTime date}); TransactionPriority getDefaultTransactionPriority(); TransactionPriority getMoneroTransactionPrioritySlow(); TransactionPriority getMoneroTransactionPriorityAutomatic(); TransactionPriority deserializeMoneroTransactionPriority({required int raw}); List getTransactionPriorities(); List getMoneroWordList(String language); List getUnspents(Object wallet); Future updateUnspents(Object wallet); WalletCredentials createMoneroRestoreWalletFromKeysCredentials({ required String name, required String spendKey, required String viewKey, required String address, required String password, required String language, required int height}); WalletCredentials createMoneroRestoreWalletFromSeedCredentials({required String name, required String password, required int height, required String mnemonic}); WalletCredentials createMoneroNewWalletCredentials({required String name, required String language, required bool isPolyseed, String password}); Map getKeys(Object wallet); Object createMoneroTransactionCreationCredentials({required List outputs, required TransactionPriority priority}); Object createMoneroTransactionCreationCredentialsRaw({required List outputs, required TransactionPriority priority}); String formatterMoneroAmountToString({required int amount}); double formatterMoneroAmountToDouble({required int amount}); int formatterMoneroParseAmount({required String amount}); Account getCurrentAccount(Object wallet); void setCurrentAccount(Object wallet, int id, String label, String? balance); void onStartup(); int getTransactionInfoAccountId(TransactionInfo tx); WalletService createMoneroWalletService(Box walletInfoSource, Box unspentCoinSource); Map pendingTransactionInfo(Object transaction); } abstract class MoneroSubaddressList { ObservableList get subaddresses; void update(Object wallet, {required int accountIndex}); void refresh(Object wallet, {required int accountIndex}); List getAll(Object wallet); Future addSubaddress(Object wallet, {required int accountIndex, required String label}); Future setLabelSubaddress(Object wallet, {required int accountIndex, required int addressIndex, required String label}); } abstract class MoneroAccountList { ObservableList get accounts; void update(Object wallet); void refresh(Object wallet); List getAll(Object wallet); Future addAccount(Object wallet, {required String label}); Future setLabelAccount(Object wallet, {required int accountIndex, required String label}); } """; const moneroEmptyDefinition = 'Monero? monero;\n'; const moneroCWDefinition = 'Monero? monero = CWMonero();\n'; final output = '$moneroCommonHeaders\n' + (hasImplementation ? '$moneroCWHeaders\n' : '\n') + (hasImplementation ? '$moneroCwPart\n\n' : '\n') + (hasImplementation ? moneroCWDefinition : moneroEmptyDefinition) + '\n' + moneroContent; if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(output); } Future generateHaven(bool hasImplementation) async { final outputFile = File(havenOutputPath); const havenCommonHeaders = """ import 'package:mobx/mobx.dart'; import 'package:flutter/foundation.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/output_info.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; import 'package:cw_core/crypto_currency.dart';"""; const havenCWHeaders = """ import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_core/monero_amount_format.dart'; import 'package:cw_core/monero_transaction_priority.dart'; import 'package:cw_haven/haven_wallet_service.dart'; import 'package:cw_haven/haven_wallet.dart'; import 'package:cw_haven/haven_transaction_info.dart'; import 'package:cw_haven/haven_transaction_history.dart'; import 'package:cw_core/account.dart' as monero_account; import 'package:cw_haven/api/wallet.dart' as monero_wallet_api; import 'package:cw_haven/mnemonics/english.dart'; import 'package:cw_haven/mnemonics/chinese_simplified.dart'; import 'package:cw_haven/mnemonics/dutch.dart'; import 'package:cw_haven/mnemonics/german.dart'; import 'package:cw_haven/mnemonics/japanese.dart'; import 'package:cw_haven/mnemonics/russian.dart'; import 'package:cw_haven/mnemonics/spanish.dart'; import 'package:cw_haven/mnemonics/portuguese.dart'; import 'package:cw_haven/mnemonics/french.dart'; import 'package:cw_haven/mnemonics/italian.dart'; import 'package:cw_haven/haven_transaction_creation_credentials.dart'; import 'package:cw_haven/api/balance_list.dart'; """; const havenCwPart = "part 'cw_haven.dart';"; const havenContent = """ class Account { Account({required this.id, required this.label}); final int id; final String label; } class Subaddress { Subaddress({ required this.id, required this.label, required this.address}); final int id; final String label; final String address; } class HavenBalance extends Balance { HavenBalance({required this.fullBalance, required this.unlockedBalance}) : formattedFullBalance = haven!.formatterMoneroAmountToString(amount: fullBalance), formattedUnlockedBalance = haven!.formatterMoneroAmountToString(amount: unlockedBalance), super(unlockedBalance, fullBalance); HavenBalance.fromString( {required this.formattedFullBalance, required this.formattedUnlockedBalance}) : fullBalance = haven!.formatterMoneroParseAmount(amount: formattedFullBalance), unlockedBalance = haven!.formatterMoneroParseAmount(amount: formattedUnlockedBalance), super(haven!.formatterMoneroParseAmount(amount: formattedUnlockedBalance), haven!.formatterMoneroParseAmount(amount: formattedFullBalance)); final int fullBalance; final int unlockedBalance; final String formattedFullBalance; final String formattedUnlockedBalance; @override String get formattedAvailableBalance => formattedUnlockedBalance; @override String get formattedAdditionalBalance => formattedFullBalance; } class AssetRate { AssetRate(this.asset, this.rate); final String asset; final int rate; } abstract class HavenWalletDetails { // FIX-ME: it's abstract class @observable late Account account; // FIX-ME: it's abstract class @observable late HavenBalance balance; } abstract class Haven { HavenAccountList getAccountList(Object wallet); MoneroSubaddressList getSubaddressList(Object wallet); TransactionHistoryBase getTransactionHistory(Object wallet); HavenWalletDetails getMoneroWalletDetails(Object wallet); String getTransactionAddress(Object wallet, int accountIndex, int addressIndex); int getHeightByDate({required DateTime date}); Future getCurrentHeight(); TransactionPriority getDefaultTransactionPriority(); TransactionPriority deserializeMoneroTransactionPriority({required int raw}); List getTransactionPriorities(); List getMoneroWordList(String language); WalletCredentials createHavenRestoreWalletFromKeysCredentials({ required String name, required String spendKey, required String viewKey, required String address, required String password, required String language, required int height}); WalletCredentials createHavenRestoreWalletFromSeedCredentials({required String name, required String password, required int height, required String mnemonic}); WalletCredentials createHavenNewWalletCredentials({required String name, required String language, String password}); Map getKeys(Object wallet); Object createHavenTransactionCreationCredentials({required List outputs, required TransactionPriority priority, required String assetType}); String formatterMoneroAmountToString({required int amount}); double formatterMoneroAmountToDouble({required int amount}); int formatterMoneroParseAmount({required String amount}); Account getCurrentAccount(Object wallet); void setCurrentAccount(Object wallet, int id, String label); void onStartup(); int getTransactionInfoAccountId(TransactionInfo tx); WalletService createHavenWalletService(Box walletInfoSource); CryptoCurrency assetOfTransaction(TransactionInfo tx); List getAssetRate(); } abstract class MoneroSubaddressList { ObservableList get subaddresses; void update(Object wallet, {required int accountIndex}); void refresh(Object wallet, {required int accountIndex}); List getAll(Object wallet); Future addSubaddress(Object wallet, {required int accountIndex, required String label}); Future setLabelSubaddress(Object wallet, {required int accountIndex, required int addressIndex, required String label}); } abstract class HavenAccountList { ObservableList get accounts; void update(Object wallet); void refresh(Object wallet); List getAll(Object wallet); Future addAccount(Object wallet, {required String label}); Future setLabelAccount(Object wallet, {required int accountIndex, required String label}); } """; const havenEmptyDefinition = 'Haven? haven;\n'; const havenCWDefinition = 'Haven? haven = CWHaven();\n'; final output = '$havenCommonHeaders\n' + (hasImplementation ? '$havenCWHeaders\n' : '\n') + (hasImplementation ? '$havenCwPart\n\n' : '\n') + (hasImplementation ? havenCWDefinition : havenEmptyDefinition) + '\n' + havenContent; if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(output); } Future generateEthereum(bool hasImplementation) async { final outputFile = File(ethereumOutputPath); const ethereumCommonHeaders = """ import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; import 'package:web3dart/web3dart.dart'; """; const ethereumCWHeaders = """ import 'package:cw_evm/evm_chain_formatter.dart'; import 'package:cw_evm/evm_chain_mnemonics.dart'; import 'package:cw_evm/evm_chain_transaction_credentials.dart'; import 'package:cw_evm/evm_chain_transaction_info.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; import 'package:cw_ethereum/ethereum_client.dart'; import 'package:cw_ethereum/ethereum_wallet.dart'; import 'package:cw_ethereum/ethereum_wallet_service.dart'; import 'package:eth_sig_util/util/utils.dart'; """; const ethereumCwPart = "part 'cw_ethereum.dart';"; const ethereumContent = """ abstract class Ethereum { List getEthereumWordList(String language); WalletService createEthereumWalletService(Box walletInfoSource); WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo}); WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); WalletCredentials createEthereumRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); String getAddress(WalletBase wallet); String getPrivateKey(WalletBase wallet); String getPublicKey(WalletBase wallet); TransactionPriority getDefaultTransactionPriority(); TransactionPriority getEthereumTransactionPrioritySlow(); List getTransactionPriorities(); TransactionPriority deserializeEthereumTransactionPriority(int raw); Object createEthereumTransactionCredentials( List outputs, { required TransactionPriority priority, required CryptoCurrency currency, int? feeRate, }); Object createEthereumTransactionCredentialsRaw( List outputs, { TransactionPriority? priority, required CryptoCurrency currency, required int feeRate, }); int formatterEthereumParseAmount(String amount); double formatterEthereumAmountToDouble({TransactionInfo? transaction, BigInt? amount, int exponent = 18}); List getERC20Currencies(WalletBase wallet); Future addErc20Token(WalletBase wallet, Erc20Token token); Future deleteErc20Token(WalletBase wallet, Erc20Token token); Future getErc20Token(WalletBase wallet, String contractAddress); CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); void updateEtherscanUsageState(WalletBase wallet, bool isEnabled); Web3Client? getWeb3Client(WalletBase wallet); } """; const ethereumEmptyDefinition = 'Ethereum? ethereum;\n'; const ethereumCWDefinition = 'Ethereum? ethereum = CWEthereum();\n'; final output = '$ethereumCommonHeaders\n' + (hasImplementation ? '$ethereumCWHeaders\n' : '\n') + (hasImplementation ? '$ethereumCwPart\n\n' : '\n') + (hasImplementation ? ethereumCWDefinition : ethereumEmptyDefinition) + '\n' + ethereumContent; if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(output); } Future generatePolygon(bool hasImplementation) async { final outputFile = File(polygonOutputPath); const polygonCommonHeaders = """ import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; import 'package:web3dart/web3dart.dart'; """; const polygonCWHeaders = """ import 'package:cw_evm/evm_chain_formatter.dart'; import 'package:cw_evm/evm_chain_mnemonics.dart'; import 'package:cw_evm/evm_chain_transaction_info.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; import 'package:cw_evm/evm_chain_transaction_credentials.dart'; import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; import 'package:cw_polygon/polygon_client.dart'; import 'package:cw_polygon/polygon_wallet.dart'; import 'package:cw_polygon/polygon_wallet_service.dart'; import 'package:eth_sig_util/util/utils.dart'; """; const polygonCwPart = "part 'cw_polygon.dart';"; const polygonContent = """ abstract class Polygon { List getPolygonWordList(String language); WalletService createPolygonWalletService(Box walletInfoSource); WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo}); WalletCredentials createPolygonRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); WalletCredentials createPolygonRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); String getAddress(WalletBase wallet); String getPrivateKey(WalletBase wallet); String getPublicKey(WalletBase wallet); TransactionPriority getDefaultTransactionPriority(); TransactionPriority getPolygonTransactionPrioritySlow(); List getTransactionPriorities(); TransactionPriority deserializePolygonTransactionPriority(int raw); Object createPolygonTransactionCredentials( List outputs, { required TransactionPriority priority, required CryptoCurrency currency, int? feeRate, }); Object createPolygonTransactionCredentialsRaw( List outputs, { TransactionPriority? priority, required CryptoCurrency currency, required int feeRate, }); int formatterPolygonParseAmount(String amount); double formatterPolygonAmountToDouble({TransactionInfo? transaction, BigInt? amount, int exponent = 18}); List getERC20Currencies(WalletBase wallet); Future addErc20Token(WalletBase wallet, Erc20Token token); Future deleteErc20Token(WalletBase wallet, Erc20Token token); Future getErc20Token(WalletBase wallet, String contractAddress); CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled); Web3Client? getWeb3Client(WalletBase wallet); } """; const polygonEmptyDefinition = 'Polygon? polygon;\n'; const polygonCWDefinition = 'Polygon? polygon = CWPolygon();\n'; final output = '$polygonCommonHeaders\n' + (hasImplementation ? '$polygonCWHeaders\n' : '\n') + (hasImplementation ? '$polygonCwPart\n\n' : '\n') + (hasImplementation ? polygonCWDefinition : polygonEmptyDefinition) + '\n' + polygonContent; if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(output); } Future generateLightning(bool hasImplementation) async { final outputFile = File(lightningOutputPath); const lightningCommonHeaders = """ import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; """; const lightningCWHeaders = """ import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_bitcoin/bitcoin_wallet_service.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_lightning/lightning_wallet_service.dart'; """; const lightningCwPart = "part 'cw_lightning.dart';"; const lightningContent = """ abstract class Lightning { TransactionPriority getMediumTransactionPriority(); WalletCredentials createLightningRestoreWalletFromSeedCredentials( {required String name, required String mnemonic, required String password}); WalletCredentials createLightningRestoreWalletFromWIFCredentials( {required String name, required String password, required String wif, WalletInfo? walletInfo}); WalletCredentials createLightningNewWalletCredentials( {required String name, WalletInfo? walletInfo}); List getWordList(); Map getWalletKeys(Object wallet); List getTransactionPriorities(); List getLitecoinTransactionPriorities(); TransactionPriority deserializeLightningTransactionPriority(int raw); TransactionPriority deserializeLitecoinTransactionPriority(int raw); int getFeeRate(Object wallet, TransactionPriority priority); Future generateNewAddress(Object wallet, String label); Future updateAddress(Object wallet, String address, String label); Object createLightningTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}); Object createLightningTransactionCredentialsRaw(List outputs, {TransactionPriority? priority, required int feeRate}); List getAddresses(Object wallet); String getAddress(Object wallet); List getSubAddresses(Object wallet); String formatterLightningAmountToString({required int amount}); double formatterLightningAmountToDouble({required int amount}); int formatterStringDoubleToLightningAmount(String amount); String lightningTransactionPriorityWithLabel(TransactionPriority priority, int rate); List getUnspents(Object wallet); Future updateUnspents(Object wallet); WalletService createLightningWalletService( Box walletInfoSource, Box unspentCoinSource); TransactionPriority getLightningTransactionPriorityMedium(); TransactionPriority getLightningTransactionPrioritySlow(); } """; const lightningEmptyDefinition = 'Lightning? lightning;\n'; const lightningCWDefinition = 'Lightning? lightning = CWLightning();\n'; final output = '$lightningCommonHeaders\n' + (hasImplementation ? '$lightningCWHeaders\n' : '\n') + (hasImplementation ? '$lightningCwPart\n\n' : '\n') + (hasImplementation ? lightningCWDefinition : lightningEmptyDefinition) + '\n' + lightningContent; if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(output); } Future generateBitcoinCash(bool hasImplementation) async { final outputFile = File(bitcoinCashOutputPath); const bitcoinCashCommonHeaders = """ import 'dart:typed_data'; import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; """; const bitcoinCashCWHeaders = """ import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; """; const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';"; const bitcoinCashContent = """ abstract class BitcoinCash { String getMnemonic(int? strength); Uint8List getSeedFromMnemonic(String seed); String getCashAddrFormat(String address); WalletService createBitcoinCashWalletService( Box walletInfoSource, Box unspentCoinSource); WalletCredentials createBitcoinCashNewWalletCredentials( {required String name, WalletInfo? walletInfo}); WalletCredentials createBitcoinCashRestoreWalletFromSeedCredentials( {required String name, required String mnemonic, required String password}); TransactionPriority deserializeBitcoinCashTransactionPriority(int raw); TransactionPriority getDefaultTransactionPriority(); List getTransactionPriorities(); TransactionPriority getBitcoinCashTransactionPrioritySlow(); } """; const bitcoinCashEmptyDefinition = 'BitcoinCash? bitcoinCash;\n'; const bitcoinCashCWDefinition = 'BitcoinCash? bitcoinCash = CWBitcoinCash();\n'; final output = '$bitcoinCashCommonHeaders\n' + (hasImplementation ? '$bitcoinCashCWHeaders\n' : '\n') + (hasImplementation ? '$bitcoinCashCwPart\n\n' : '\n') + (hasImplementation ? bitcoinCashCWDefinition : bitcoinCashEmptyDefinition) + '\n' + bitcoinCashContent; if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(output); } Future generateNano(bool hasImplementation) async { final outputFile = File(nanoOutputPath); const nanoCommonHeaders = """ import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/nano_account.dart'; import 'package:cw_core/account.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/nano_account_info_response.dart'; import 'package:mobx/mobx.dart'; import 'package:hive/hive.dart'; import 'package:cake_wallet/view_model/send/output.dart'; """; const nanoCWHeaders = """ import 'package:cw_nano/nano_client.dart'; import 'package:cw_nano/nano_mnemonic.dart'; import 'package:cw_nano/nano_wallet.dart'; import 'package:cw_nano/nano_wallet_service.dart'; import 'package:cw_nano/nano_transaction_info.dart'; import 'package:cw_nano/nano_transaction_credentials.dart'; import 'package:cw_nano/nano_wallet_creation_credentials.dart'; // needed for nano_util: import 'dart:convert'; import 'dart:typed_data'; import 'package:convert/convert.dart'; import "package:ed25519_hd_key/ed25519_hd_key.dart"; import 'package:libcrypto/libcrypto.dart'; import 'package:nanodart/nanodart.dart' as ND; import 'package:nanoutil/nanoutil.dart'; """; const nanoCwPart = "part 'cw_nano.dart';"; const nanoContent = """ abstract class Nano { NanoAccountList getAccountList(Object wallet); Account getCurrentAccount(Object wallet); void setCurrentAccount(Object wallet, int id, String label, String? balance); WalletService createNanoWalletService(Box walletInfoSource); WalletCredentials createNanoNewWalletCredentials({ required String name, String password, }); WalletCredentials createNanoRestoreWalletFromSeedCredentials({ required String name, required String password, required String mnemonic, DerivationType? derivationType, }); WalletCredentials createNanoRestoreWalletFromKeysCredentials({ required String name, required String password, required String seedKey, DerivationType? derivationType, }); List getNanoWordList(String language); Map getKeys(Object wallet); Object createNanoTransactionCredentials(List outputs); Future changeRep(Object wallet, String address); Future updateTransactions(Object wallet); BigInt getTransactionAmountRaw(TransactionInfo transactionInfo); String getRepresentative(Object wallet); } abstract class NanoAccountList { ObservableList get accounts; void update(Object wallet); void refresh(Object wallet); Future> getAll(Object wallet); Future addAccount(Object wallet, {required String label}); Future setLabelAccount(Object wallet, {required int accountIndex, required String label}); } abstract class NanoUtil { bool isValidBip39Seed(String seed); static const int maxDecimalDigits = 6; // Max digits after decimal BigInt rawPerNano = BigInt.parse("1000000000000000000000000000000"); BigInt rawPerNyano = BigInt.parse("1000000000000000000000000"); BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000"); BigInt rawPerXMR = BigInt.parse("1000000000000"); BigInt convertXMRtoNano = BigInt.parse("1000000000000000000"); String getRawAsUsableString(String? raw, BigInt rawPerCur); String getRawAccuracy(String? raw, BigInt rawPerCur); String getAmountAsRaw(String amount, BigInt rawPerCur); // derivationInfo: Future getInfoFromSeedOrMnemonic( DerivationType derivationType, { String? seedKey, String? mnemonic, required Node node, }); Future> compareDerivationMethods({ String? mnemonic, String? privateKey, required Node node, }); } """; const nanoEmptyDefinition = 'Nano? nano;\nNanoUtil? nanoUtil;\n'; const nanoCWDefinition = 'Nano? nano = CWNano();\nNanoUtil? nanoUtil = CWNanoUtil();\n'; final output = '$nanoCommonHeaders\n' + (hasImplementation ? '$nanoCWHeaders\n' : '\n') + (hasImplementation ? '$nanoCwPart\n\n' : '\n') + (hasImplementation ? nanoCWDefinition : nanoEmptyDefinition) + '\n' + nanoContent; if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(output); } Future generatePubspec( {required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum, required bool hasNano, required bool hasBanano, required bool hasBitcoinCash, required bool hasPolygon, required bool hasLightning}) async { const cwCore = """ cw_core: path: ./cw_core """; const cwMonero = """ cw_monero: path: ./cw_monero """; const cwBitcoin = """ cw_bitcoin: path: ./cw_bitcoin """; const cwHaven = """ cw_haven: path: ./cw_haven """; const cwSharedExternal = """ cw_shared_external: path: ./cw_shared_external """; const cwEthereum = """ cw_ethereum: path: ./cw_ethereum """; const cwBitcoinCash = """ cw_bitcoin_cash: path: ./cw_bitcoin_cash """; const cwNano = """ cw_nano: path: ./cw_nano """; const cwBanano = """ cw_banano: path: ./cw_banano """; const cwPolygon = """ cw_polygon: path: ./cw_polygon """; const cwEVM = """ cw_evm: path: ./cw_evm """; const cwLightning = """ cw_lightning: path: ./cw_lightning """; final inputFile = File(pubspecOutputPath); final inputText = await inputFile.readAsString(); final inputLines = inputText.split('\n'); final dependenciesIndex = inputLines.indexWhere((line) => line.toLowerCase() == 'dependencies:'); var output = cwCore; if (hasMonero) { output += '\n$cwMonero\n$cwSharedExternal'; } if (hasBitcoin) { output += '\n$cwBitcoin'; } if (hasEthereum) { output += '\n$cwEthereum'; } if (hasNano) { output += '\n$cwNano'; } if (hasBanano) { output += '\n$cwBanano'; } if (hasBitcoinCash) { output += '\n$cwBitcoinCash'; } if (hasPolygon) { output += '\n$cwPolygon'; } if (hasHaven && !hasMonero) { output += '\n$cwSharedExternal\n$cwHaven'; } else if (hasHaven) { output += '\n$cwHaven'; } if (hasEthereum || hasPolygon) { output += '\n$cwEVM'; } if (hasLightning) { output += '\n$cwLightning'; } final outputLines = output.split('\n'); inputLines.insertAll(dependenciesIndex + 1, outputLines); final outputContent = inputLines.join('\n'); final outputFile = File(pubspecOutputPath); if (outputFile.existsSync()) { await outputFile.delete(); } await outputFile.writeAsString(outputContent); } Future generateWalletTypes( {required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum, required bool hasNano, required bool hasBanano, required bool hasBitcoinCash, required bool hasPolygon, required bool hasLightning}) async { final walletTypesFile = File(walletTypesPath); if (walletTypesFile.existsSync()) { await walletTypesFile.delete(); } const outputHeader = "import 'package:cw_core/wallet_type.dart';"; const outputDefinition = 'final availableWalletTypes = ['; var outputContent = outputHeader + '\n\n' + outputDefinition + '\n'; if (hasMonero) { outputContent += '\tWalletType.monero,\n'; } if (hasBitcoin) { outputContent += '\tWalletType.bitcoin,\n'; } if (hasLightning) { outputContent += '\tWalletType.lightning,\n'; } if (hasEthereum) { outputContent += '\tWalletType.ethereum,\n'; } if (hasBitcoin) { outputContent += '\tWalletType.litecoin,\n'; } if (hasBitcoinCash) { outputContent += '\tWalletType.bitcoinCash,\n'; } if (hasPolygon) { outputContent += '\tWalletType.polygon,\n'; } if (hasNano) { outputContent += '\tWalletType.nano,\n'; } if (hasBanano) { outputContent += '\tWalletType.banano,\n'; } if (hasHaven) { outputContent += '\tWalletType.haven,\n'; } outputContent += '];\n'; await walletTypesFile.writeAsString(outputContent); }