diff --git a/assets/zcash_node_list.yml b/assets/zcash_node_list.yml deleted file mode 100644 index 88db5c54c..000000000 --- a/assets/zcash_node_list.yml +++ /dev/null @@ -1,12 +0,0 @@ -- uri: zec.rocks:443 - is_default: false - useSSL: true - isEnabledForAutoSwitching: true -- uri: zec-node.cakewallet.com:443 - is_default: true - useSSL: true - isEnabledForAutoSwitching: true -- uri: 2c4whzg26j6hgjh22rxynj3oig4gm22ga7x74weclujywxye23v3u5id.onion:9067 - useSSL: false -- uri: bvp2l442g5ogma7rywzahm7eqyhpp3g26n3gvvxeioqn5csio2ir6myd.onion:9067 - useSSL: false diff --git a/cw_zcash/.gitignore b/cw_zcash/.gitignore deleted file mode 100644 index 3cceda557..000000000 --- a/cw_zcash/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# https://dart.dev/guides/libraries/private-files -# Created by `dart pub` -.dart_tool/ - -# Avoid committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock diff --git a/cw_zcash/CHANGELOG.md b/cw_zcash/CHANGELOG.md deleted file mode 100644 index effe43c82..000000000 --- a/cw_zcash/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -## 1.0.0 - -- Initial version. diff --git a/cw_zcash/README.md b/cw_zcash/README.md deleted file mode 100644 index b6754b047..000000000 --- a/cw_zcash/README.md +++ /dev/null @@ -1 +0,0 @@ -# cw_zcash diff --git a/cw_zcash/analysis_options.yaml b/cw_zcash/analysis_options.yaml deleted file mode 100644 index f43bd483d..000000000 --- a/cw_zcash/analysis_options.yaml +++ /dev/null @@ -1,31 +0,0 @@ -analyzer: - errors: - implementation_imports: ignore - must_be_immutable: ignore - overridden_fields: ignore - exclude: - - "**.g.dart" - - "external/**" - -linter: - rules: - unawaited_futures: true - avoid_print: false - parameter_assignments: true - prefer_const_declarations: true - prefer_final_fields: true - prefer_final_in_for_each: true - prefer_final_locals: true - prefer_final_parameters: true - avoid_void_async: true - require_trailing_commas: true - sort_child_properties_last: true - sort_constructors_first: true - sort_unnamed_constructors_first: true - unnecessary_async: true - unnecessary_await_in_return: true - unnecessary_string_interpolations: true - always_declare_return_types: true - -formatter: - page_width: 100 diff --git a/cw_zcash/lib/cw_zcash.dart b/cw_zcash/lib/cw_zcash.dart deleted file mode 100644 index c312ddb82..000000000 --- a/cw_zcash/lib/cw_zcash.dart +++ /dev/null @@ -1,15 +0,0 @@ -/// Support for doing something awesome. -/// -/// More dartdocs go here. -library; - -export 'src/zcash_balance.dart'; -export 'src/zcash_mnemonic_is_incorrect_exception.dart'; -export 'src/zcash_transaction_info.dart'; -export 'src/zcash_transactions.dart'; -export 'src/zcash_wallet.dart'; -export 'src/zcash_wallet_service.dart'; -export 'src/models.dart'; -export 'src/zcash_transaction_credentials.dart'; -export 'src/pending_zcash_transaction.dart'; -export 'src/zcash_receive_page_options.dart'; diff --git a/cw_zcash/lib/src/legacy/zkool_sweep.dart b/cw_zcash/lib/src/legacy/zkool_sweep.dart deleted file mode 100644 index 20f04daa3..000000000 --- a/cw_zcash/lib/src/legacy/zkool_sweep.dart +++ /dev/null @@ -1,196 +0,0 @@ -import 'dart:io'; - -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:path/path.dart' as p; -import 'package:zkool/src/rust/api/account.dart' as zkool_account; -import 'package:zkool/src/rust/api/coin.dart' as zkool_coin; -import 'package:zkool/src/rust/api/sync.dart' as zkool_sync; -import 'package:zkool/src/rust/api/pay.dart' as zkool_pay; -import 'package:zkool/src/rust/api/key.dart' as zkool_key; -import 'package:zkool/src/rust/api/network.dart' as zkool_network; -import 'package:zkool/src/rust/pay.dart' as zkool_paydart; -import 'package:zkool/src/rust/frb_generated.dart' as zkool_frb; - -class ZkoolSweep { - ZkoolSweep({ - required this.currentBalance, - required this.cacheDir, - required this.seed, - required this.passphrase, - required this.address, - required this.url, - required this.height, - }); - final int currentBalance; - final String seed; - final String cacheDir; - final String passphrase; - final String address; - final String url; - final int height; - static SweepUpdate msg = SweepUpdate(message: 'Idling', currentHeight: 0, networkHeight: 0); - Future start() async { - try { - await _init(); - if (!zkool_key.isValidAddress(address: address)) { - msg.message = "$address is not valid"; - return; - } - - msg = SweepUpdate(message: 'Starting import', currentHeight: 0, networkHeight: 0); - await _newAccount(); - msg.message = "Starting sync"; - await warpSync(); - msg.message = "Waiting"; - while (msg.blocksLeft != 0 && msg.networkHeight != 0) { - await Future.delayed(Duration(seconds: 1)); - } - await Future.delayed(Duration(seconds: 5)); - final balance = await getBalance(); - if (balance.toInt() == balance) { - msg.message = "No need to sweep, balance is the same"; - return; - } - msg.message = "Sweeping"; - await sweep(balance); - } catch (e) { - msg.message = e.toString(); - printV("zkool_sweep: $e"); - rethrow; - } - } - - Future getBalance() async { - final b = await zkool_sync.balance(c: c); - return b.field0.reduce((final a, final b) => a + b); - } - - Future sweep(final BigInt amount) async { - msg.message = "prepare"; - final tx = await zkool_pay.prepare( - recipients: [zkool_paydart.Recipient(address: address, amount: amount)], - options: zkool_pay.PaymentOptions( - srcPools: 7, - recipientPaysFee: true, - smartTransparent: false, - ), - c: c, - ); - msg.message = "getLatestHeight"; - final height = await getLatestHeight(); - msg.message = "signTransaction"; - final signTx = await zkool_pay.signTransaction(pczt: tx, c: c); - msg.message = "extractTransaction"; - final txBytes = await zkool_pay.extractTransaction(package: signTx); - msg.message = "broadcastTransaction"; - final result = await zkool_pay.broadcastTransaction(height: height, txBytes: txBytes, c: c); - msg.message = "result"; - if (result.isEmpty) { - msg.message = "Unknown error"; - throw Exception(result); - } - } - - static var c = zkool_coin.Coin(); - - static bool _isInit = false; - - File get dbFile => File(p.join(cacheDir, "zkool-tmp-mirror.db")); - - Future warpSync() async { - final currentHeight = await getLatestHeight(); - msg.networkHeight = currentHeight; - final sync = zkool_sync.synchronize( - accounts: [currentAccount], - currentHeight: currentHeight, - actionsPerSync: 10000, - transparentLimit: 100, - checkpointAge: 200, - c: c, - ); - bool success = false; - await sync.listen( - (final syncProgress) { - msg.currentHeight = syncProgress.height; - msg.message = "Sync ${syncProgress.height} / ${syncProgress.time}"; - }, - onError: (final e) { - msg.message = e.toString(); - }, - onDone: () { - msg.message = "Sync done!"; - success = true; - }, - ); - - if (msg.currentHeight != currentHeight && msg.currentHeight != 0) { - msg.message = "Canceling sync"; - await zkool_sync.cancelSync(); - await Future.delayed(Duration(seconds: 1)); - return warpSync(); - } - return 0; - } - - Future getLatestHeight() async { - try { - return await zkool_network.getCurrentHeight(c: c); - } catch (e) { - printV("getLatestHeight: $e"); - } - return 0; - } - - Future _newAccount() async { - final id = await zkool_account.newAccount( - na: zkool_account.NewAccount( - name: 'restoretmp' + DateTime.now().microsecondsSinceEpoch.toString(), - restore: true, - passphrase: "", - key: seed, - aindex: 0, - birth: height, - folder: '', - useInternal: true, - internal: false, - ledger: false, - ), - c: c, - ); - currentAccount = id; - c = await c.setAccount(account: id); - } - - int currentAccount = 0; - - Future _init() async { - if (_isInit) return; - _isInit = true; - printV(".init()"); - await zkool_frb.RustLib.init(); - await zkool_network.initDatadir(directory: dbFile.parent.path); - c = await c.openDatabase(dbFilepath: dbFile.path, password: 'cw_zcash_migration'); - c = c.setLwd(url: url, serverType: 0); - printV(".init(): Done"); - } -} - -class SweepUpdate { - SweepUpdate({required this.message, required this.currentHeight, required this.networkHeight}); - String message; - int currentHeight; - int networkHeight; - double get progress { - if (networkHeight == 0) return 0.01; - return currentHeight / networkHeight; - } - - int get blocksLeft => networkHeight - currentHeight; - - Map toJson() => { - "message": message, - "currentHeight": currentHeight, - "networkHeight": networkHeight, - "progress": progress, - }; -} diff --git a/cw_zcash/lib/src/models.dart b/cw_zcash/lib/src/models.dart deleted file mode 100644 index e6886b189..000000000 --- a/cw_zcash/lib/src/models.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:cw_core/wallet_credentials.dart'; - -class ZcashNewWalletCredentials extends WalletCredentials { - ZcashNewWalletCredentials({ - required final String name, - final String? password, - required final String? passphrase, - final String? mnemonic, - final int? seedPhraseLength, - }) : super( - name: name, - password: password, - passphrase: passphrase, - seedPhraseLength: seedPhraseLength, - ) { - this.mnemonic = mnemonic; - } - - String? mnemonic; -} - -class ZcashFromSeedWalletCredentials extends WalletCredentials { - ZcashFromSeedWalletCredentials({ - required final String name, - final String? password, - required final String? passphrase, - required this.seed, - required super.height, - }) : super(name: name, password: password, passphrase: passphrase); - final String? seed; -} - -class ZcashFromKeysWalletCredentials extends WalletCredentials { - ZcashFromKeysWalletCredentials({ - required final String name, - final String? password, - required final int? height, - required this.privateKey, - }) : super(name: name, password: password, height: height); - final String? privateKey; -} diff --git a/cw_zcash/lib/src/pending_zcash_transaction.dart b/cw_zcash/lib/src/pending_zcash_transaction.dart deleted file mode 100644 index 28be24652..000000000 --- a/cw_zcash/lib/src/pending_zcash_transaction.dart +++ /dev/null @@ -1,103 +0,0 @@ -import 'dart:convert'; -import 'dart:math'; - -import 'package:cw_core/output_info.dart'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_zcash/cw_zcash.dart'; -import 'package:cw_core/currency_for_wallet_type.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cw_zcash/src/zcash_taddress_rotation.dart'; -import 'package:warp_api/data_fb_generated.dart'; -import 'package:warp_api/warp_api.dart'; - -class PendingZcashTransaction with PendingTransaction { - PendingZcashTransaction({ - required this.zcashWallet, - required this.credentials, - required this.txPlan, - required this.fee, - required this.availableBalance, - }); - - final ZcashWallet zcashWallet; - final ZcashTransactionCredentials credentials; - final String txPlan; - String? _txId; - final int availableBalance; - - @override - String get id => _txId ?? ''; - - @override - String get hex => ''; - - @override - String get amountFormatted { - return walletTypeToCryptoCurrency(WalletType.zcash).formatAmount(BigInt.from(totalAmount)); - } - - int get totalAmount { - final isAll = credentials.outputs.fold(false, (final a, final b) => a || (b.sendAll)); - if (isAll) { - return availableBalance; - } - return credentials.outputs.fold( - 0, - (final a, final b) => a + (b.formattedCryptoAmount ?? 0), - ); - } - - @override - String get feeFormatted => - '$feeFormattedValue ${walletTypeToCryptoCurrency(WalletType.zcash).title}'; - - @override - late String feeFormattedValue = walletTypeToCryptoCurrency( - WalletType.zcash, - ).formatAmount(BigInt.from(fee)); - - int fee; - - @override - Future commit() async { - _txId = await ZcashWalletService.runInDbMutex( - () => WarpApi.signAndBroadcast(ZcashWalletBase.coin, zcashWallet.accountId, txPlan), - ); - ZcashWalletBase.temporarySentTx[zcashWallet.accountId] ??= []; - ZcashWalletBase.temporarySentTx[zcashWallet.accountId]?.add( - ShieldedTx( - base64.decode( - ZcashTaddressRotation.flatBuffersPack( - ShieldedTxT( - id: Random().nextInt(pow(2, 32).toInt()), - txId: _txId, - height: 0, - timestamp: DateTime.now().millisecondsSinceEpoch ~/ 1000, - value: -totalAmount, - ).pack, - ), - ), - ), - ); - await ZcashTransactionInfo.addCachedDestinationAddress( - _txId ?? '', - credentials.outputs.reduce((final o1, final o2) { - return OutputInfo( - address: o1.address + "," + o2.address, - sendAll: false, - isParsedAddress: false, - ); - }).address, - ); - await zcashWallet.updateTransactions(); - await zcashWallet.updateBalance(); - } - - @override - Future> commitUR() { - throw UnimplementedError('UR not supported for Zcash'); - } - - @override - bool shouldCommitUR() => false; -} diff --git a/cw_zcash/lib/src/util/crc32.dart b/cw_zcash/lib/src/util/crc32.dart deleted file mode 100644 index c5fc23995..000000000 --- a/cw_zcash/lib/src/util/crc32.dart +++ /dev/null @@ -1,296 +0,0 @@ -/// CRC32 -/// Copyright (C) 2012, Kai Sellgren -/// Licensed under the MIT License. -/// http://www.opensource.org/licenses/mit-license.php -/// source: https://raw.githubusercontent.com/kaisellgren/CRC32/refs/heads/master/lib/crc32.dart -// ignore_for_file: parameter_assignments - -import 'dart:convert'; - -/// Computes Cyclic Redundancy Check values. -class CRC32 { - /// Computes a CRC32 value for the given input. - /// - /// The return value is an unsigned integer. - /// - /// You may optionally specify the beginning CRC value. - static int compute(dynamic input, [int crc = 0]) { - if (input == null) throw new ArgumentError.notNull('input'); - if (input is String) input = utf8.encode(input); - - crc = crc ^ (0xffffffff); - - for (final byte in input) { - if (!(byte >= -128 && byte <= 255)) - throw new FormatException("Invalid value in input: $byte"); - - final x = CRC32._table[(crc ^ byte) & 0xff]; - crc = (crc & 0xffffffff) >> 8; // crc >>> 8 (32-bit unsigned integer) - crc ^= x; - } - - crc = crc ^ (0xffffffff); - - // Turns the signed integer into an unsigned integer. - return crc & 0xffffffff; - } - - static const _table = const [ - 0x00000000, - 0x77073096, - 0xEE0E612C, - 0x990951BA, - 0x076DC419, - 0x706AF48F, - 0xE963A535, - 0x9E6495A3, - 0x0EDB8832, - 0x79DCB8A4, - 0xE0D5E91E, - 0x97D2D988, - 0x09B64C2B, - 0x7EB17CBD, - 0xE7B82D07, - 0x90BF1D91, - 0x1DB71064, - 0x6AB020F2, - 0xF3B97148, - 0x84BE41DE, - 0x1ADAD47D, - 0x6DDDE4EB, - 0xF4D4B551, - 0x83D385C7, - 0x136C9856, - 0x646BA8C0, - 0xFD62F97A, - 0x8A65C9EC, - 0x14015C4F, - 0x63066CD9, - 0xFA0F3D63, - 0x8D080DF5, - 0x3B6E20C8, - 0x4C69105E, - 0xD56041E4, - 0xA2677172, - 0x3C03E4D1, - 0x4B04D447, - 0xD20D85FD, - 0xA50AB56B, - 0x35B5A8FA, - 0x42B2986C, - 0xDBBBC9D6, - 0xACBCF940, - 0x32D86CE3, - 0x45DF5C75, - 0xDCD60DCF, - 0xABD13D59, - 0x26D930AC, - 0x51DE003A, - 0xC8D75180, - 0xBFD06116, - 0x21B4F4B5, - 0x56B3C423, - 0xCFBA9599, - 0xB8BDA50F, - 0x2802B89E, - 0x5F058808, - 0xC60CD9B2, - 0xB10BE924, - 0x2F6F7C87, - 0x58684C11, - 0xC1611DAB, - 0xB6662D3D, - 0x76DC4190, - 0x01DB7106, - 0x98D220BC, - 0xEFD5102A, - 0x71B18589, - 0x06B6B51F, - 0x9FBFE4A5, - 0xE8B8D433, - 0x7807C9A2, - 0x0F00F934, - 0x9609A88E, - 0xE10E9818, - 0x7F6A0DBB, - 0x086D3D2D, - 0x91646C97, - 0xE6635C01, - 0x6B6B51F4, - 0x1C6C6162, - 0x856530D8, - 0xF262004E, - 0x6C0695ED, - 0x1B01A57B, - 0x8208F4C1, - 0xF50FC457, - 0x65B0D9C6, - 0x12B7E950, - 0x8BBEB8EA, - 0xFCB9887C, - 0x62DD1DDF, - 0x15DA2D49, - 0x8CD37CF3, - 0xFBD44C65, - 0x4DB26158, - 0x3AB551CE, - 0xA3BC0074, - 0xD4BB30E2, - 0x4ADFA541, - 0x3DD895D7, - 0xA4D1C46D, - 0xD3D6F4FB, - 0x4369E96A, - 0x346ED9FC, - 0xAD678846, - 0xDA60B8D0, - 0x44042D73, - 0x33031DE5, - 0xAA0A4C5F, - 0xDD0D7CC9, - 0x5005713C, - 0x270241AA, - 0xBE0B1010, - 0xC90C2086, - 0x5768B525, - 0x206F85B3, - 0xB966D409, - 0xCE61E49F, - 0x5EDEF90E, - 0x29D9C998, - 0xB0D09822, - 0xC7D7A8B4, - 0x59B33D17, - 0x2EB40D81, - 0xB7BD5C3B, - 0xC0BA6CAD, - 0xEDB88320, - 0x9ABFB3B6, - 0x03B6E20C, - 0x74B1D29A, - 0xEAD54739, - 0x9DD277AF, - 0x04DB2615, - 0x73DC1683, - 0xE3630B12, - 0x94643B84, - 0x0D6D6A3E, - 0x7A6A5AA8, - 0xE40ECF0B, - 0x9309FF9D, - 0x0A00AE27, - 0x7D079EB1, - 0xF00F9344, - 0x8708A3D2, - 0x1E01F268, - 0x6906C2FE, - 0xF762575D, - 0x806567CB, - 0x196C3671, - 0x6E6B06E7, - 0xFED41B76, - 0x89D32BE0, - 0x10DA7A5A, - 0x67DD4ACC, - 0xF9B9DF6F, - 0x8EBEEFF9, - 0x17B7BE43, - 0x60B08ED5, - 0xD6D6A3E8, - 0xA1D1937E, - 0x38D8C2C4, - 0x4FDFF252, - 0xD1BB67F1, - 0xA6BC5767, - 0x3FB506DD, - 0x48B2364B, - 0xD80D2BDA, - 0xAF0A1B4C, - 0x36034AF6, - 0x41047A60, - 0xDF60EFC3, - 0xA867DF55, - 0x316E8EEF, - 0x4669BE79, - 0xCB61B38C, - 0xBC66831A, - 0x256FD2A0, - 0x5268E236, - 0xCC0C7795, - 0xBB0B4703, - 0x220216B9, - 0x5505262F, - 0xC5BA3BBE, - 0xB2BD0B28, - 0x2BB45A92, - 0x5CB36A04, - 0xC2D7FFA7, - 0xB5D0CF31, - 0x2CD99E8B, - 0x5BDEAE1D, - 0x9B64C2B0, - 0xEC63F226, - 0x756AA39C, - 0x026D930A, - 0x9C0906A9, - 0xEB0E363F, - 0x72076785, - 0x05005713, - 0x95BF4A82, - 0xE2B87A14, - 0x7BB12BAE, - 0x0CB61B38, - 0x92D28E9B, - 0xE5D5BE0D, - 0x7CDCEFB7, - 0x0BDBDF21, - 0x86D3D2D4, - 0xF1D4E242, - 0x68DDB3F8, - 0x1FDA836E, - 0x81BE16CD, - 0xF6B9265B, - 0x6FB077E1, - 0x18B74777, - 0x88085AE6, - 0xFF0F6A70, - 0x66063BCA, - 0x11010B5C, - 0x8F659EFF, - 0xF862AE69, - 0x616BFFD3, - 0x166CCF45, - 0xA00AE278, - 0xD70DD2EE, - 0x4E048354, - 0x3903B3C2, - 0xA7672661, - 0xD06016F7, - 0x4969474D, - 0x3E6E77DB, - 0xAED16A4A, - 0xD9D65ADC, - 0x40DF0B66, - 0x37D83BF0, - 0xA9BCAE53, - 0xDEBB9EC5, - 0x47B2CF7F, - 0x30B5FFE9, - 0xBDBDF21C, - 0xCABAC28A, - 0x53B39330, - 0x24B4A3A6, - 0xBAD03605, - 0xCDD70693, - 0x54DE5729, - 0x23D967BF, - 0xB3667A2E, - 0xC4614AB8, - 0x5D681B02, - 0x2A6F2B94, - 0xB40BBE37, - 0xC30C8EA1, - 0x5A05DF1B, - 0x2D02EF8D, - ]; -} diff --git a/cw_zcash/lib/src/zcash_balance.dart b/cw_zcash/lib/src/zcash_balance.dart deleted file mode 100644 index ab5ec84d2..000000000 --- a/cw_zcash/lib/src/zcash_balance.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:cw_core/balance.dart'; -import 'package:cw_core/crypto_currency.dart'; - -class ZcashBalance extends Balance { - ZcashBalance({required this.confirmed, required this.unconfirmed, required final int frozen}) - : _frozen = frozen, - super.fromInt(confirmed, unconfirmed); - - factory ZcashBalance.zero() => ZcashBalance(confirmed: 0, unconfirmed: 0, frozen: 0); - - final int confirmed; - final int unconfirmed; - final int _frozen; - BigInt get frozen => BigInt.from(_frozen); - - @override - String get formattedAvailableBalance { - return CryptoCurrency.zec.formatAmount(BigInt.from(confirmed)); - } - - @override - String get formattedAdditionalBalance { - if (unconfirmed == 0) return '0.0'; - return CryptoCurrency.zec.formatAmount(BigInt.from(unconfirmed)); - } - - @override - String get formattedUnAvailableBalance { - if (frozen == 0) return ''; - return CryptoCurrency.zec.formatAmount(BigInt.from(_frozen)); - } -} diff --git a/cw_zcash/lib/src/zcash_mnemonic_is_incorrect_exception.dart b/cw_zcash/lib/src/zcash_mnemonic_is_incorrect_exception.dart deleted file mode 100644 index 4986837c5..000000000 --- a/cw_zcash/lib/src/zcash_mnemonic_is_incorrect_exception.dart +++ /dev/null @@ -1,5 +0,0 @@ -class ZcashMnemonicIsIncorrectException implements Exception { - @override - String toString() => - 'Zcash mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; -} diff --git a/cw_zcash/lib/src/zcash_receive_page_options.dart b/cw_zcash/lib/src/zcash_receive_page_options.dart deleted file mode 100644 index 8a9d05766..000000000 --- a/cw_zcash/lib/src/zcash_receive_page_options.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'package:cw_core/receive_page_option.dart'; -import 'package:cw_core/utils/print_verbose.dart'; - -enum ZcashAddressType { - transparent, - transparentRotated, - shieldedSapling, - shieldedOrchard, - unifiedType, -} - -class ZcashReceivePageOption implements ReceivePageOption { - factory ZcashReceivePageOption.fromType(final ZcashAddressType type) { - switch (type) { - case ZcashAddressType.transparent: - return transparent; - case ZcashAddressType.transparentRotated: - return transparentRotated; - case ZcashAddressType.shieldedSapling: - return shieldedSapling; - case ZcashAddressType.shieldedOrchard: - return shieldedOrchard; - case ZcashAddressType.unifiedType: - return unified; - } - } - const ZcashReceivePageOption._( - this.type, - this.value, { - this.iconPath, - this.description, - this.isCommon = false, - }); - - final String value; - final String? iconPath; - final String? description; - final bool isCommon; - final bool addAddressWord = false; - - static const transparent = ZcashReceivePageOption._( - ZcashAddressType.transparent, - "Public", - description: "Static & Transparent", - iconPath: "assets/new-ui/address-type-picker-icons/zec/public.svg", - ); - static const transparentRotated = ZcashReceivePageOption._( - ZcashAddressType.transparentRotated, - "Transparent", - description: "Disposable", - iconPath: "assets/new-ui/address-type-picker-icons/zec/transparent.svg", - isCommon: true, - ); - static const shieldedSapling = ZcashReceivePageOption._( - ZcashAddressType.shieldedSapling, - "Legacy Shielded", - description: "Sapling", - iconPath: "assets/new-ui/address-type-picker-icons/zec/sapling.svg", - ); - static const shieldedOrchard = ZcashReceivePageOption._( - ZcashAddressType.shieldedOrchard, - "Shielded", - description: "Default (Orchard)", - iconPath: "assets/new-ui/address-type-picker-icons/zec/shielded.svg", - isCommon: true, - ); - static const unified = ZcashReceivePageOption._( - ZcashAddressType.unifiedType, - "Unified", - description: "Compatible Shielded", - iconPath: "assets/new-ui/address-type-picker-icons/zec/unified.svg", - isCommon: true, - ); - - final ZcashAddressType type; - - String toString() { - return value; - } - - static const all = [ - ZcashReceivePageOption.shieldedOrchard, - ZcashReceivePageOption.shieldedSapling, - ZcashReceivePageOption.unified, - ZcashReceivePageOption.transparentRotated, - ZcashReceivePageOption.transparent, - ]; - - ZcashAddressType toType() { - return type; - } - - static ZcashAddressType typeFromString(final String str) { - for (int i = 0; i < ZcashAddressType.values.length; i++) { - if (str == ZcashAddressType.values[i].toString()) { - return ZcashAddressType.values[i]; - } - } - printV("Not found for: $str"); - return ZcashAddressType.shieldedOrchard; - } -} diff --git a/cw_zcash/lib/src/zcash_taddress_rotation.dart b/cw_zcash/lib/src/zcash_taddress_rotation.dart deleted file mode 100644 index 1c2ef1f20..000000000 --- a/cw_zcash/lib/src/zcash_taddress_rotation.dart +++ /dev/null @@ -1,445 +0,0 @@ -// create offset wallets for T address rotation. -// Each address is considered one time use, if it receives less than 15000 zatoshi balance will be essentially burned. -// -// This class takes address index as constructor, and will create 10 addresses by default, if any of the addresses gets used -// it will be moved out of the pool -// -// T addresses are generated by creating new wallets with an extra seed word (or appending to "passphrase") the following -// :tgen:${CRC32(seed)} -// It is highly unlikely for users to create a wallet with that specific last word and add index to it -// We could leverage other fields such as native account index alone, but users may want to set that in future -// This solution is rather simple and if standard would get estabilished for this purpose it can be easily -// turned off and replaced with proper solution. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cw_zcash/src/util/crc32.dart'; -import 'package:cw_zcash/src/zcash_wallet.dart'; -import 'package:cw_zcash/src/zcash_wallet_service.dart'; -import 'package:flutter/foundation.dart'; -import 'package:warp_api/data_fb_generated.dart'; -import 'package:warp_api/warp_api.dart'; -import 'package:flat_buffers/flat_buffers.dart' as fb; -import 'package:path/path.dart' as p; - -class ZcashTaddressRotation { - ZcashTaddressRotation(this.accountIndex); - final int accountIndex; - - static bool _isStarted = false; - - static const coin = ZcashWalletBase.coin; - static String seedForOffset(final String seed) { - final seedWords = seed.split(" "); - if ([12, 24].contains(seedWords.length)) { - seedWords.add(""); - } - final lastI = seedWords.length - 1; - final crc = CRC32.compute(seed); - seedWords[lastI] += ":tgen:${crc}"; - return seedWords.join(" "); - } - - static bool isSeedForWallet(final String? mainWallet, final String? subWallet) { - if (mainWallet == null || subWallet == null) return false; - return seedForOffset(mainWallet.trim()) == subWallet; - } - - static Map> rotationAccounts = {}; - static Map> rotationAccountsUsable = {}; - static Map> shieldedAccountsTx = {}; - static Future init() async { - printV("Deserializing previous state"); - if (_isStarted) { - return; - } - _isStarted = true; - final pfw = await pathForWalletTypeDir(type: WalletType.zcash); - try { - final f = File(p.join(pfw, "zec-taddr.json")); - if (!f.existsSync()) { - f.writeAsBytesSync(serialize()); - } - deserialize(f.readAsBytesSync()); - } catch (e) { - printV("Failed to deserialize T address DB for zcash, it doesn't really matter: $e"); - } - - unawaited( - (() async { - await Future.delayed(Duration(seconds: 5)); - return _jobRunner(); - })(), - ); - } - - static Future serializeToFile() async { - final pfw = await pathForWalletTypeDir(type: WalletType.zcash); - final f = File(p.join(pfw, "zec-taddr.json")); - f.writeAsBytesSync(serialize()); - } - - static Uint8List serialize() { - final data = { - "rotationAccounts": rotationAccounts.map( - (final k, final v) => MapEntry( - k.toRadixString(16), - v.map((final a) => flatBuffersPack(a.unpack().pack)).toList(), - ), - ), - if (kDebugMode) - "_rotationAccounts": rotationAccounts.map( - (final k, final v) => - MapEntry(k.toRadixString(16), v.map((final a) => a.toString()).toList()), - ), - "rotationAccountsUsable": rotationAccountsUsable.map( - (final k, final v) => MapEntry( - k.toRadixString(16), - v.map((final a) => flatBuffersPack(a.unpack().pack)).toList(), - ), - ), - if (kDebugMode) - "_rotationAccountsUsable": rotationAccountsUsable.map( - (final k, final v) => - MapEntry(k.toRadixString(16), v.map((final a) => a.toString()).toList()), - ), - "shieldedAccountsTx": shieldedAccountsTx.map( - (final k, final v) => MapEntry( - k.toRadixString(16), - v.map((final a) => flatBuffersPack(a.unpack().pack)).toList(), - ), - ), - if (kDebugMode) - "_shieldedAccountsTx": shieldedAccountsTx.map( - (final k, final v) => - MapEntry(k.toRadixString(16), v.map((final a) => a.toString()).toList()), - ), - }; - - if (kDebugMode) { - return utf8.encode(JsonEncoder.withIndent(" ").convert(data)); - } - return utf8.encode(jsonEncode(data)); - } - - static String flatBuffersPack(final int Function(fb.Builder fbBuilder) pack) { - final fbBuilder = fb.Builder(); - final offset = pack(fbBuilder); - fbBuilder.finish(offset); - return base64.encode(fbBuilder.buffer); - } - - static void deserialize(final Uint8List bytes) { - // todo: replace keys with sums and reverse in serialize - // final List seeds = []; - // for (int i = 0; i < accounts.length; i++) { - // final acc = accounts[i]; - // final backup = WarpApi.getBackup(coin, acc.id); - // await WarpApi.transparentSync(coin, acc.id, syncHeight); - // seeds.add(backup.seed!); - // } - try { - final Map data = jsonDecode(utf8.decode(bytes)); - rotationAccounts = (data["rotationAccounts"] as Map).map( - (final k, final v) => MapEntry( - int.parse(k, radix: 16), - (v as List).map((final a) => Account(atob(a))).toList(), - ), - ); - rotationAccountsUsable = (data["rotationAccountsUsable"] as Map).map( - (final k, final v) => MapEntry( - int.parse(k, radix: 16), - (v as List).map((final a) => Account(atob(a))).toList(), - ), - ); - shieldedAccountsTx = (data["shieldedAccountsTx"] as Map).map( - (final k, final v) => MapEntry( - int.parse(k, radix: 16), - (v as List).map((final a) => ShieldedTx(atob(a))).toList(), - ), - ); - } catch (e) { - rethrow; - } - } - - static Uint8List atob(final String value) => - Uint8List.fromList(List.from(base64.decode(value))); - - static Future createAndSweepTAddresses() async { - int chainHeight = 0; - try { - chainHeight = await WarpApi.getLatestHeight(coin); - } catch (e) { - printV("Error getting latest height: $e"); - } - final dbHeight = WarpApi.getDbHeight(coin); - final height = dbHeight.unpack(); - final syncHeight = height.height; - if (chainHeight != syncHeight) { - printV( - "Waiting for sync to finish: chainHeight(${chainHeight}) != syncHeight(${syncHeight})", - ); - return; - } - final Map> newShieldedAccountsTx = {}; - final accounts = WarpApi.getAccountList(coin); - if (accounts.isEmpty) return; - final Map seeds = {}; - for (int i = 0; i < accounts.length; i++) { - final acc = accounts[i]; - final backup = WarpApi.getBackup(coin, acc.id); - await WarpApi.transparentSync(coin, acc.id, syncHeight); - if (backup.seed == null) continue; - seeds[acc.id] = backup.seed!; - } - for (int i = 0; i < accounts.length; i++) { - final seed = seeds[accounts[i].id]!; - if ([12, 13, 24, 25].contains(seed.split(" ").length)) { - if (seed.split(" ").last.contains(":tgen:")) continue; - rotationAccounts[accounts[i].id] = []; - } - } - final raKeys = rotationAccounts.keys.toList(); - seeds.removeWhere((_, final val) => raKeys.contains(val)); - printV("raKeys: ${raKeys.length}"); - for (int i = 0; i < raKeys.length; i++) { - final accs = accounts.where((final a) { - final seed = WarpApi.getBackup(coin, a.id).seed; - return isSeedForWallet(seeds[raKeys[i]], seed); - }).toList(); - rotationAccounts[raKeys[i]]!.addAll(accs); - final acc = accountForSeed(seeds[raKeys[i]]!)!; - final txs = WarpApi.getTxsSync(coin, acc.id); - newShieldedAccountsTx[acc.id] ??= []; - newShieldedAccountsTx[acc.id]!.addAll(txs); - } - rotationAccountsUsable = rotationAccounts.map((final k, final v) => MapEntry(k, v.toList())); - printV("rotationAccounts: ${rotationAccounts.length}"); - - for (int i = 0; i < raKeys.length; i++) { - final acc = accountForSeed(seeds[raKeys[i]]!)!; - newShieldedAccountsTx[acc.id] = []; - for (int j = 0; j < (rotationAccounts[raKeys[i]]?.length ?? 0); j++) { - final txs = WarpApi.getTxsSync(coin, rotationAccounts[raKeys[i]]![j].id); - rotationAccounts[raKeys[i]]![j]; - newShieldedAccountsTx[acc.id]!.addAll(txs); - } - rotationAccountsUsable[raKeys[i]]!.removeWhere((final a) { - final txs = WarpApi.getTxsSync(coin, a.id); - return txs.isNotEmpty; - }); - - // remove hidden addresses - final wis = await WalletInfo.selectList('type = ?', [WalletType.zcash.index]); - - final List hiddenAddresses_ = []; - for (int k = 0; k < wis.length; k++) { - final addrs = await wis[k].getHiddenAddresses(); - final addr2 = await wis[k].getUsedAddresses(); - hiddenAddresses_.addAll(addrs); - hiddenAddresses_.addAll(addr2); - } - final Set hiddenAddresses = hiddenAddresses_.toSet(); - rotationAccountsUsable[raKeys[i]]!.removeWhere((final a) { - return hiddenAddresses.contains(WarpApi.getTAddr(coin, a.id)); - }); - } - printV("rotationAccountsUsable: ${rotationAccountsUsable.length}"); - - bool didAddNewAccount = false; - for (int i = 0; i < raKeys.length; i++) { - if (rotationAccountsUsable[raKeys[i]]!.length < 5) { - final seed = seedForOffset(seeds[raKeys[i]]!); - final name = CRC32.compute(raKeys[i].toString()).toString(); - final id = await ZcashWalletService.runInDbMutex( - () => WarpApi.newAccount(coin, name, seed, rotationAccounts[raKeys[i]]!.length), - ); - printV("new id: $id / $seed"); - printV("${rotationAccounts[raKeys[i]]}"); - printV(raKeys[i]); - rotationAccounts[raKeys[i]]!.forEach((final a) { - final b = WarpApi.getBackup(coin, a.id); - printV("${a.id}"); - }); - didAddNewAccount = true; - } - } - printV("didAddNewAccount: ${didAddNewAccount}"); - if (didAddNewAccount) { - return createAndSweepTAddresses(); - } - - for (var i = 0; i < raKeys.length; i++) { - final accs = rotationAccounts[raKeys[i]]!; - inner: - for (var j = 0; j < accs.length; j++) { - int bal = 0; - try { - bal += await WarpApi.getTBalance(coin, accs[j].id); - } catch (e) { - printV("getTBalance: $e"); - return; - } - if (bal < 30000) continue inner; - final to = accountForSeed(seeds[raKeys[i]]!)!; - // final toAddress = WarpApi.getTAddr(coin, to.id); - // final fromSeed = WarpApi.getBackup(coin, to.id); - // final txId = await ZcashWalletService.runInDbMutex( - // () => WarpApi.sweepTransparentSeed( - // to.coin, - // to.id, - // chainHeight, - // fromSeed.seed!, - // 7, - // toAddress, - // 0, - // 1, - // FeeT(fee: 10000, minFee: 0, maxFee: 0, scheme: 0), - // ), - // ); - final recipientBuilder = RecipientObjectBuilder( - address: WarpApi.getAddress(coin, to.id, 4), - pools: 4, - feeIncluded: true, - amount: bal, - ); - - final recipient = Recipient(recipientBuilder.toBytes()); - final fee = FeeT(fee: 10000, minFee: 0, maxFee: 0, scheme: 0); - await ZcashWalletBase.loadProver(); - final txPlan = await ZcashWalletService.runInDbMutex( - () => WarpApi.prepareTx( - coin, - accs[j].id, - [recipient], - 3, // pools: (Transparent + Sapling) - 1, - 0, // anchorOffset - fee, - ), - ); - final _txId = await ZcashWalletService.runInDbMutex( - () => WarpApi.signAndBroadcast(ZcashWalletBase.coin, accs[j].id, txPlan), - ); - await ZcashWalletService.addShieldedTx(_txId); - printV("shielded: $_txId"); - - await Future.delayed(Duration(seconds: 120)); // let it be - return createAndSweepTAddresses(); - } - } - final nsatKeys = newShieldedAccountsTx.keys.toList(); - for (int i = 0; i < nsatKeys.length; i++) { - inner: - for (int j = 0; j < newShieldedAccountsTx[nsatKeys[i]]!.length; j++) { - final tx = newShieldedAccountsTx[nsatKeys[i]]?[j]; - if (tx == null) { - continue inner; - } - final _txId = tx.txId; - if (_txId == null) { - continue inner; - } - if (tx.value < 0) { - await ZcashWalletService.addShieldedTx(_txId); - // continue inner; - } - if (ZcashWalletService.autoshieldTx.contains(_txId)) { - continue inner; - } - } - } - shieldedAccountsTx = newShieldedAccountsTx.map((final k, final v) => MapEntry(k, v.toList())); - await serializeToFile(); - return; - } - - static ShieldedTx reverseAmount(final ShieldedTx t) { - final tt = t.unpack(); - tt.value = -tt.value; - return ShieldedTx(base64.decode(flatBuffersPack(tt.pack))); - } - - static Account? accountForSeed(final String seed) { - final accounts = WarpApi.getAccountList(coin); - if (accounts.isEmpty) return null; - for (int i = 0; i < accounts.length; i++) { - final acc = accounts[i]; - final backup = WarpApi.getBackup(coin, acc.id); - if (backup.seed == seed) { - return acc; - } - } - return null; - } - - static Future _jobRunner() async { - for (;;) { - try { - await Future.delayed(Duration(seconds: 5)); - await createAndSweepTAddresses(); - } catch (e, s) { - printV(e); - s.toString().split("\n").forEach(printV); - rethrow; - } finally { - await Future.delayed(Duration(seconds: 30)); - } - } - } - - static String? addressForAccount(final int accountId, final Set? hiddenAddresses) { - final accs = rotationAccountsUsable[accountId] ?? []; - for (int i = 0; i < accs.length; i++) { - final addr = WarpApi.getTAddr(coin, accs[i].id); - if (hiddenAddresses?.contains(addr) == true) { - continue; - } - return addr; - } - return null; - } - - static List? allAddressesForAccount(final int accountId) { - final acc = rotationAccounts[accountId]; - if (acc == null) { - printV("Nothing found"); - return null; - } - for (int i = 0; i < acc.length; i++) { - final b = WarpApi.getBackup(coin, acc[i].id); - printV("$i. ${b.seed?.split(" ").last}, ${b.index}, ${WarpApi.getTAddr(coin, acc[i].id)}"); - } - return acc.map((final a) => WarpApi.getTAddr(coin, a.id)).toList(); - } - - static List? allUsedAddressesForAccount(final int accountId) { - final seed = WarpApi.getBackup(coin, accountId).seed; - if (seed == null) return []; - final acc = rotationAccounts[seed]?.toList(); - if (acc == null) { - printV("Nothing found"); - return null; - } - acc.removeWhere((final a1) { - for (int i = 0; i < (rotationAccountsUsable[seed]?.length ?? 0); i++) { - if (rotationAccountsUsable[seed]?[i].id == a1.id) { - return true; - } - } - return false; - }); - for (int i = 0; i < acc.length; i++) { - final b = WarpApi.getBackup(coin, acc[i].id); - printV("$i. ${b.seed?.split(" ").last}, ${b.index}, ${WarpApi.getTAddr(coin, acc[i].id)}"); - } - return acc.map((final a) => WarpApi.getTAddr(coin, a.id)).toList(); - } -} diff --git a/cw_zcash/lib/src/zcash_transaction_credentials.dart b/cw_zcash/lib/src/zcash_transaction_credentials.dart deleted file mode 100644 index 7ec3e5a81..000000000 --- a/cw_zcash/lib/src/zcash_transaction_credentials.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/monero_transaction_priority.dart'; -import 'package:cw_core/output_info.dart'; - -class ZcashTransactionCredentials { - ZcashTransactionCredentials({ - required this.outputs, - required this.priority, - required this.currency, - }); - - final List outputs; - final MoneroTransactionPriority priority; - final CryptoCurrency currency; -} diff --git a/cw_zcash/lib/src/zcash_transaction_info.dart b/cw_zcash/lib/src/zcash_transaction_info.dart deleted file mode 100644 index 617bd046b..000000000 --- a/cw_zcash/lib/src/zcash_transaction_info.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:cw_core/currency_for_wallet_type.dart'; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/format_amount.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cw_zcash/cw_zcash.dart'; -import 'package:path/path.dart' as p; - -class ZcashTransactionInfo extends TransactionInfo { - ZcashTransactionInfo({ - required final String id, - required final int amount, - required final int fee, - required final TransactionDirection direction, - required final bool isPending, - required final DateTime date, - required final int height, - required final int confirmations, - required final String to, - final String? memo, - }) { - this.id = id; - this.amount = amount; - this.fee = fee; - this.height = height; - this.direction = direction; - this.date = date; - this.isPending = isPending; - this.confirmations = confirmations; - this.to = getCachedDestinationAddress(id); - if (memo != null && memo.isNotEmpty) { - additionalInfo['memo'] = memo; - } - additionalInfo['autoShield'] = false; - // note: this won't work yet, fee is not in zcash_lib metadata, - // leaving here so it can start working automagically in future - if (amount == fee && to.startsWith("u")) { - additionalInfo['autoShield'] = true; - } - // remove below when above starts working - additionalInfo['autoShield'] = ZcashWalletService.autoshieldTx.contains(txHash); - // --- == === cut here === == --- - if (additionalInfo['autoShield'] == true) { - additionalInfo['memo'] ??= ''; - additionalInfo['memo'] += '\This is an auto-shielding transaction. Enjoy default privacy!'; - additionalInfo['memo'] = additionalInfo['memo'].trim(); - } - } - - String? _fiatAmount; - - @override - String amountFormatted() => - '${walletTypeToCryptoCurrency(WalletType.zcash).formatAmount(BigInt.from(amount))} ${walletTypeToCryptoCurrency(WalletType.zcash).title}'; - - @override - String? feeFormatted() { - if (fee == null || fee == 0) return null; - return '${walletTypeToCryptoCurrency(WalletType.zcash).formatAmount(BigInt.from(fee!))} ${walletTypeToCryptoCurrency(WalletType.zcash).title}'; - } - - @override - String fiatAmount() => _fiatAmount ?? ''; - - @override - void changeFiatAmount(final String amount) => _fiatAmount = formatAmount(amount); - - String? get memo => additionalInfo['memo'] as String?; - - static final Map _destinationAddressMap = {}; - - static String? getCachedDestinationAddress(final String txId) { - return _destinationAddressMap[txId] ?? - _destinationAddressMap['"$txId"'] ?? - _destinationAddressMap[txId.replaceAll('"', '')]; - } - - static Future addCachedDestinationAddress(final String txId, final String address) async { - _destinationAddressMap[txId] = address; - final pfwt = await pathForWalletTypeDir(type: WalletType.zcash); - final f = File(p.join(pfwt, "sent-tx-map.json")); - f.writeAsStringSync(json.encode(_destinationAddressMap)); - } - - static Future init() async { - try { - final pfwt = await pathForWalletTypeDir(type: WalletType.zcash); - final f = File(p.join(pfwt, "sent-tx-map.json")); - if (!f.existsSync()) { - f.writeAsStringSync('{}'); - } - final tmpMap = json.decode(f.readAsStringSync()); - tmpMap.forEach((final k, final v) { - _destinationAddressMap[k.toString()] = v.toString(); - }); - } catch (e, s) { - printV("failed to deserialize: $e, $s"); - } - } -} diff --git a/cw_zcash/lib/src/zcash_transactions.dart b/cw_zcash/lib/src/zcash_transactions.dart deleted file mode 100644 index afb074314..000000000 --- a/cw_zcash/lib/src/zcash_transactions.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:mobx/mobx.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/transaction_history.dart'; - -class ZcashTransactionHistory extends TransactionHistoryBase { - ZcashTransactionHistory() { - transactions = ObservableMap(); - } - - @override - void addMany(final Map txs) { - transactions.addAll(txs); - } - - @override - void addOne(final TransactionInfo txs) { - transactions[txs.txHash] = txs; - } - - @override - Future save() async { - // No need to save anything, backend is taking care of that - } -} diff --git a/cw_zcash/lib/src/zcash_wallet.dart b/cw_zcash/lib/src/zcash_wallet.dart deleted file mode 100644 index 0ade54d54..000000000 --- a/cw_zcash/lib/src/zcash_wallet.dart +++ /dev/null @@ -1,1193 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/monero_transaction_priority.dart'; -import 'package:cw_core/node.dart'; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/sync_status.dart'; -import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; -import 'package:cw_core/wallet_addresses.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_type.dart'; -import 'package:bip39/bip39.dart' as bip39; -import 'package:cw_zcash/cw_zcash.dart'; -import 'package:cw_zcash/src/legacy/zkool_sweep.dart'; -import 'package:cw_zcash/src/util/crc32.dart'; -import 'package:cw_zcash/src/zcash_taddress_rotation.dart'; -import 'package:cw_zcash/src/zcash_wallet_addresses.dart'; -import 'package:flutter/foundation.dart'; -import 'package:mobx/mobx.dart'; -import 'package:warp_api/warp_api.dart'; -import 'package:warp_api/data_fb_generated.dart'; -import 'package:flutter/services.dart'; -import 'package:mutex/mutex.dart'; -import 'package:path/path.dart' as p; -import 'package:path_provider/path_provider.dart'; - -part 'zcash_wallet.g.dart'; - -class ZcashWallet = ZcashWalletBase with _$ZcashWallet; - -abstract class ZcashWalletBase - extends WalletBase - with Store { - ZcashWalletBase(super.walletInfo, super.derivationInfo, {required this.accountId}) { - transactionHistory = ZcashTransactionHistory(); - } - - final int accountId; - static const int coin = 0; // Zcash mainnet coin ID in warp_api - @override - @observable - SyncStatus syncStatus = NotConnectedSyncStatus(); - - Timer? _syncStatusTimer; - Timer? _periodicSyncTimer; - int _initialSyncHeight = 0; - int _lastKnownBlockHeight = 0; - - @override - ObservableMap balance = ObservableMap.of({ - CryptoCurrency.zec: ZcashBalance(confirmed: 0, unconfirmed: 0, frozen: 0), - }); - - static int internalCalculateEstimatedFee(final TransactionPriority priority, final int? amount) { - const baseFee = 10000; - switch (priority) { - case MoneroTransactionPriority.slow: - case MoneroTransactionPriority.automatic: - return baseFee; - case MoneroTransactionPriority.medium: - return baseFee * 2; - case MoneroTransactionPriority.fast: - return baseFee * 4; - case MoneroTransactionPriority.fastest: - return baseFee * 10; - } - ; - return internalCalculateEstimatedFee(MoneroTransactionPriority.automatic, amount); - } - - @override - int calculateEstimatedFee(final TransactionPriority priority, final int? amount) { - return internalCalculateEstimatedFee(priority, amount); - } - - @override - Future changePassword(final String password) async { - // throw UnimplementedError(); - } - - static bool isNodeWorking = true; - - @override - Future checkNodeHealth() { - return Future.value(isNodeWorking); - } - - @override - Future close({final bool shouldCleanup = false}) async { - _stopSyncStatusUpdates(); - _stopPeriodicSync(); - await ZcashWalletService.runInDbMutex(() async => WarpApi.cancelSync()); - } - - Node? lastNode; - @override - @action - Future connectToNode({required final Node node}) async { - lastNode = node; - printV("connecting to node: ${node.uriRaw}"); - syncStatus = ConnectingSyncStatus(); - try { - String lwdUrl = node.uriRaw; - if (!lwdUrl.startsWith('http://') && !lwdUrl.startsWith('https://')) { - final protocol = node.useSSL == true ? 'https://' : 'http://'; - lwdUrl = '$protocol$lwdUrl'; - } - printV("Setting LWD URL to: $lwdUrl"); - WarpApi.updateLWD(coin, lwdUrl); - syncStatus = ConnectedSyncStatus(); - try { - await updateBalance(); - await updateTransactions(); - } catch (e) { - printV("Error updating balance/transactions after connect: $e"); - } - } catch (e) { - printV("Connection error: $e"); - syncStatus = FailedSyncStatus(error: e.toString()); - rethrow; - } - } - - @override - Future createTransaction(final Object credentials) async { - final creds = credentials as ZcashTransactionCredentials; - await updateBalance(); - - final zcashBalance = balance[CryptoCurrency.zec]; - final availableBalance = zcashBalance?.confirmed ?? 0; - - final recipients = []; - int totalAmount = 0; - - for (final output in creds.outputs) { - int amount; - if (output.sendAll) { - amount = availableBalance; - } else { - amount = output.formattedCryptoAmount ?? 0; - - if (amount == 0 && output.cryptoAmount != null && output.cryptoAmount!.isNotEmpty) { - try { - final parsedAmount = CryptoCurrency.zec.parseAmount( - output.cryptoAmount!.replaceAll(',', '.'), - ); - amount = parsedAmount.toInt(); - printV("Parsed amount from cryptoAmount '${output.cryptoAmount}': $amount"); - } catch (e) { - printV("Failed to parse cryptoAmount '${output.cryptoAmount}': $e"); - } - } - - if (amount <= 0) { - throw Exception( - 'Invalid amount for output. Amount: ${output.cryptoAmount}, Formatted: ${output.formattedCryptoAmount}', - ); - } - } - - totalAmount += amount; - - var address = (output.isParsedAddress ? output.extractedAddress! : output.address).trim(); - - if (address.isEmpty) { - throw Exception('Empty address for output'); - } - - final paymentUri = WarpApi.decodePaymentURI(coin, address); - String memo = output.memo ?? ''; - // String memo = ''; - if (paymentUri != null && paymentUri.address != null) { - address = paymentUri.address!; - if (memo.isEmpty && paymentUri.memo != null) { - memo = paymentUri.memo!; - } - } - - if (!WarpApi.validAddress(coin, address)) { - throw Exception('Invalid Zcash address: $address'); - } - - int recipientPools = 7; - - if (address.startsWith('t1') || address.startsWith('t3')) { - recipientPools = 1; // Transparent only - } else if (address.startsWith('zs')) { - recipientPools = 2; // Sapling only - } - // For unified addresses (u1...) and other types, use 7 (all pools) - - final builder = RecipientObjectBuilder( - address: address, - pools: recipientPools, - amount: amount, - feeIncluded: output.sendAll, - replyTo: false, - memo: memo.isNotEmpty ? memo : null, - ); - - recipients.add(Recipient(builder.toBytes())); - } - - if (totalAmount > availableBalance) { - throw Exception('Insufficient balance'); - } - - final fee = FeeT( - fee: internalCalculateEstimatedFee(creds.priority, null), - minFee: 0, - maxFee: 0, - scheme: 0, // Fixed fee scheme - ); - - // pools parameter: bitmask for which pools to use for sending - // 1=Transparent, 2=Sapling, 4=Orchard, 7=All pools - await ZcashWalletBase.loadProver(); - // Using 7 (all pools) allows spending from any pool type - final txPlan = await ZcashWalletService.runInDbMutex( - () => WarpApi.prepareTx( - coin, - accountId, - recipients, - 7, // pools: All pools (Transparent + Sapling + Orchard) - allows spending from any pool - 1, // senderUAType: 0 = unified address - 0, // anchorOffset - fee, - ), - ); - - return PendingZcashTransaction( - zcashWallet: this as ZcashWallet, - credentials: creds, - txPlan: txPlan, - fee: internalCalculateEstimatedFee(creds.priority, null), - availableBalance: availableBalance, - ); - } - - static const _dispPhrase = "Received to disposable address"; - Future> getShieldTxForUi() async { - final tx = (ZcashTaddressRotation.shieldedAccountsTx[accountId] ?? []) - .map((final v) { - final unpacked = v.unpack(); - unpacked.memo ??= ""; - unpacked.memo = "${unpacked.memo}\n$_dispPhrase".trim(); - final List buff = base64.decode( - ZcashTaddressRotation.flatBuffersPack(unpacked.pack), - ); - return ShieldedTx(buff); - }) - .where((final t) => t.value > 0); - - return tx.toList(); - } - - static Map> temporarySentTx = {}; - - static String txChecksumKey(final ShieldedTx tx) { - final direction = tx.value > 0 ? TransactionDirection.incoming : TransactionDirection.outgoing; - return 'tx${direction}_${tx.id}_${tx.timestamp}_${CRC32.compute(tx.toString())}'; - } - - @override - Future> fetchTransactions() async { - await ZcashWalletService.loadShieldTxs(); - final txs = (await ZcashWalletService.runInDbMutex( - () => WarpApi.getTxs(coin, accountId), - )).toList(); - // ShieldedTx{id: 26, txId: 4d1be06ce2c2debec8d98ce4e9434c8aac27c980488b459017d423fdcab37f93, height: 3195705, shortTxId: 4d1be06c, timestamp: 1767730944, name: null, value: 1000000, address: null, memo: , messages: MemoVec{memos: null}} - - final shieldTx = await getShieldTxForUi(); - - txs.addAll(shieldTx); - final txIds = txs.map((final tx) => tx.txId!.replaceAll('"', '')).toSet(); - temporarySentTx[accountId]?.removeWhere( - (final ttx) => txIds.contains(ttx.txId!.replaceAll('"', '')), - ); - txs.addAll(temporarySentTx[accountId] ?? []); - - txs.sort((final a, final b) => a.height.compareTo(b.height)); - final Map result = {}; - int currentHeight = 0; - try { - currentHeight = await WarpApi.getLatestHeight(coin); - } catch (e) { - printV("Error getting latest height: $e"); - } - - for (final tx in txs) { - final direction = tx.value > 0 - ? TransactionDirection.incoming - : TransactionDirection.outgoing; - - final confirmations = tx.height > 0 && currentHeight > 0 ? currentHeight - tx.height + 1 : 0; - - final txChecksum = txChecksumKey(tx); - final txId = tx.txId ?? tx.shortTxId ?? txChecksum; - - final txInfo = ZcashTransactionInfo( - id: txId.trim().replaceAll('"', ''), - amount: tx.value.abs(), - fee: 0, - direction: direction, - isPending: tx.height == 0, - date: DateTime.fromMillisecondsSinceEpoch(tx.timestamp * 1000), - height: tx.height, - confirmations: confirmations, - to: tx.address ?? '', - memo: tx.memo, - ); - // if (txInfo.additionalInfo['autoShield'] == true) { - // continue; - // } - result[txChecksum] = txInfo; - } - - return result; - } - - @override - Object get keys { - final backup = WarpApi.getBackup(coin, accountId); - return { - // "seed": backup.seed, - // "index": backup.index, - "privateSpendKey": backup.sk, - "privateViewKey": backup.fvk, - "uvk": backup.uvk, - "tsk": backup.tsk, - if (lastKnownRestoreHeight != null) "restoreHeight": lastKnownRestoreHeight.toString(), - }; - } - - @override - String get password => _password!; - - @override - Future renameWalletFiles(final String newWalletName) async { - final currentWalletPath = await pathForWallet(name: name, type: type); - final currentCacheFile = File(currentWalletPath); - final newWalletPath = await pathForWallet(name: newWalletName, type: type); - if (currentCacheFile.existsSync()) { - await currentCacheFile.copy(newWalletPath); - } - Directory(currentWalletPath).deleteSync(recursive: true); - } - - @override - bool get hasRescan => true; - - static Future storeZcashHeight(final int height) async { - lastKnownRestoreHeight = height; - final zcashDir = await pathForWalletTypeDir(type: WalletType.zcash); - final zcashInitialSync = File(p.join(zcashDir, ".initial-sync-marker")); - zcashInitialSync.writeAsBytesSync([0x00]); - zcashInitialSync.writeAsStringSync(height.toString(), mode: FileMode.writeOnlyAppend); - } - - static int? lastKnownRestoreHeight = null; - static Future loadZcashHeight() async { - final zcashDir = await pathForWalletTypeDir(type: WalletType.zcash); - final zcashInitialSync = File(p.join(zcashDir, ".initial-sync-marker")); - if (!await zcashInitialSync.exists()) { - return null; - } - final bytes = await zcashInitialSync.readAsBytes(); - if (bytes.isEmpty) { - return null; - } - final heightString = String.fromCharCodes(bytes.skip(1)); - lastKnownRestoreHeight = int.tryParse(heightString); - return lastKnownRestoreHeight; - } - - static int zashiAnnouncedBlockHeight = 2419420; - - @override - @action - Future rescan({required final int height}) async { - try { - syncStatus = StartingScanSyncStatus(height); - printV("rescanning from: $height"); - await storeZcashHeight(height); - await ZcashWalletService.runInDbMutex(() async => WarpApi.rescanFrom(coin, height)); - await startSync(); - } catch (e) { - printV("Rescan error: $e"); - syncStatus = FailedSyncStatus(error: e.toString()); - } - } - - bool _isTransactionUpdating = false; - - Future updateTransactions() async { - try { - if (_isTransactionUpdating) { - return; - } - - _isTransactionUpdating = true; - final transactions = await fetchTransactions(); - - final currentIds = transactionHistory.transactions.keys.toSet(); - final newIds = transactions.keys.toSet(); - - currentIds - .difference(newIds) - .forEach((final id) => transactionHistory.transactions.remove(id)); - - transactions.forEach((final key, final tx) { - transactionHistory.transactions[key] = tx; - }); - await transactionHistory.save(); - _isTransactionUpdating = false; - } catch (e, stackTrace) { - printV("Update transactions error: $e"); - printV("Stack trace: $stackTrace"); - _isTransactionUpdating = false; - } - } - - Future updateTransactionsHistory() => updateTransactions(); - - @override - Future save() async {} - - Future init() async { - try { - await walletAddresses.init(); - - await updateBalance(); - await updateTransactions(); - } catch (e) { - printV("Wallet init error: $e"); - } - } - - @override - String? get seed { - try { - final backup = WarpApi.getBackup(coin, accountId); - final seed = backup.seed?.split(" "); - if (seed == null) { - return null; - } - if ([13, 25].contains(seed.length)) { - seed.removeLast(); - } - return seed.join(" ").trim(); - } catch (e) { - return null; - } - } - - @override - String? get passphrase { - try { - final backup = WarpApi.getBackup(coin, accountId); - final seed = backup.seed?.split(" "); - if (seed == null) { - return null; - } - if ([13, 25].contains(seed.length)) { - final passphrase = seed.removeLast(); - return passphrase; - } - return null; - } catch (e) { - return null; - } - } - - @override - Future signMessage(final String message, {final String? address = null}) { - throw UnimplementedError(); - } - - @override - @action - Future startSync() async { - try { - syncStatus = AttemptingSyncStatus(); - - _initialSyncHeight = 0; - _lastKnownBlockHeight = 0; - - _startSyncStatusUpdates(); - - syncStatus = SyncronizingSyncStatus(); - - unawaited( - _runWarpSync().catchError((final e) { - isNodeWorking = false; - printV("WarpSync error in startSync: $e"); - syncStatus = FailedSyncStatus(error: e.toString()); - _stopSyncStatusUpdates(); - }), - ); - } catch (e) { - isNodeWorking = false; - printV("Sync error: $e"); - syncStatus = FailedSyncStatus(error: e.toString()); - _stopSyncStatusUpdates(); - rethrow; - } - } - - static Mutex warpSyncMutex = Mutex(); - - static Future initialSyncCheck() async { - final zcashDir = await pathForWalletTypeDir(type: WalletType.zcash); - final zcashInitialSync = File(p.join(zcashDir, ".initial-sync-marker")); - if (!zcashInitialSync.existsSync()) { - int chainHeight = 3000000; // fallback if node is offline - try { - chainHeight = await WarpApi.getLatestHeight(coin); - } catch (e) { - printV("Error getting latest height: $e"); - } - await ZcashWalletService.runInDbMutex( - () async => await WarpApi.rescanFrom(coin, chainHeight - 150000), - ); - await storeZcashHeight(chainHeight); - } - } - - @action - Future _runWarpSync() async { - Timer? _t; - try { - await warpSyncMutex.acquire(); - await initialSyncCheck(); - isNodeWorking = true; - printV("Starting warpSync for coin $coin, account $accountId"); - int? initialQueue = null; - void _cancelSyncIfShould(final Timer t) { - initialQueue ??= ZcashWalletService.dbMutexQueue + 2; - if (ZcashWalletService.dbMutexQueue <= initialQueue!) { - initialQueue = ZcashWalletService.dbMutexQueue; - return; - } - printV( - "Canceling sync! (ZcashWalletService.dbMutexQueue: ${ZcashWalletService.dbMutexQueue} > initialQueue: ${initialQueue})", - ); - WarpApi.cancelSync(); - t.cancel(); - _t = null; - } - - unawaited( - Future.delayed(Duration(seconds: 2)).then((_) { - _t = Timer.periodic(Duration(milliseconds: 100), _cancelSyncIfShould); - }), - ); - final result = await ZcashWalletService.runInDbMutex( - () => WarpApi.warpSync(coin, accountId, true, 0, 1000000, 0), - ); - printV("warpSync completed with result: $result"); - - await _updateSyncStatus(); - } catch (e) { - syncStatus = FailedSyncStatus(error: e.toString()); - unawaited(Future.delayed(Duration(seconds: 1)).then((_) => unawaited(_runWarpSync()))); - _stopSyncStatusUpdates(); - } finally { - isNodeWorking = false; - warpSyncMutex.release(); - _t?.cancel(); - } - } - - void _startSyncStatusUpdates() { - _stopSyncStatusUpdates(); - _updateSyncStatus(); - _syncStatusTimer = Timer.periodic(const Duration(milliseconds: 5000), (_) { - _updateSyncStatus().catchError((final e) { - printV("Error in sync status update timer: $e"); - }); - }); - } - - void _stopSyncStatusUpdates() { - _syncStatusTimer?.cancel(); - _syncStatusTimer = null; - } - - void _startPeriodicSync() { - printV("_startPeriodicSync"); - _stopPeriodicSync(); - _periodicSyncTimer = Timer.periodic(const Duration(seconds: 5), (_) async { - try { - final chainHeight = await WarpApi.getLatestHeight(coin); - final dbHeight = WarpApi.getDbHeight(coin); - final height = dbHeight.unpack(); - final syncHeight = height.height; - - if (syncHeight < chainHeight) { - printV("Periodic sync: chainHeight=$chainHeight, syncHeight=$syncHeight, starting sync"); - await _runWarpSync(); - } else { - await updateBalance(); - await updateTransactions(); - } - } catch (e) { - printV("Periodic sync error: $e"); - } - }); - } - - void _stopPeriodicSync() { - _periodicSyncTimer?.cancel(); - _periodicSyncTimer = null; - } - - @action - Future _updateSyncStatus() async { - try { - final dbHeight = WarpApi.getDbHeight(coin); - final height = dbHeight.unpack(); - final syncHeight = height.height; - - final chainHeight = await WarpApi.getLatestHeight(coin); - - if (_initialSyncHeight <= 0 && syncHeight > 0) { - _initialSyncHeight = syncHeight; - printV("Initialized sync height to: $_initialSyncHeight"); - if (syncHeight - 10 > dbHeight.height) {} - } - - if (chainHeight <= 0) { - if (syncStatus is! ConnectedSyncStatus && syncStatus is! ConnectingSyncStatus) { - syncStatus = ConnectedSyncStatus(); - } - try { - await updateBalance(); - await updateTransactions(); - } catch (e) { - printV("Error updating balance/transactions: $e"); - } - return; - } - - if (syncHeight <= 0) { - if (syncStatus is! ConnectedSyncStatus && - syncStatus is! ConnectingSyncStatus && - syncStatus is! AttemptingSyncStatus) { - syncStatus = ConnectedSyncStatus(); - } - try { - await updateBalance(); - await updateTransactions(); - } catch (e) { - printV("Error updating balance/transactions: $e"); - } - return; - } - - if (syncHeight >= chainHeight && syncHeight > 0) { - syncStatus = SyncedSyncStatus(); - _stopSyncStatusUpdates(); - await updateBalance(); - await updateTransactions(); - _startPeriodicSync(); - return; - } - - if (_lastKnownBlockHeight != syncHeight) { - _lastKnownBlockHeight = syncHeight; - } - - if (syncHeight < 0 || chainHeight < syncHeight) { - return; - } - - final blocksLeft = chainHeight - syncHeight; - if (blocksLeft <= 0) { - syncStatus = SyncedSyncStatus(); - _stopSyncStatusUpdates(); - await updateBalance(); - await updateTransactions(); - _startPeriodicSync(); - return; - } - - double ptc = 0.0; - if (_initialSyncHeight > 0) { - final track = chainHeight - _initialSyncHeight; - final diff = track > 0 ? track - (chainHeight - syncHeight) : 0; - ptc = track > 0 && diff >= 0 ? diff / track : 0.0; - } else { - ptc = syncHeight / chainHeight; - } - - syncStatus = SyncingSyncStatus(blocksLeft, ptc.clamp(0.0, 1.0)); - - await updateBalance(); - await updateTransactions(); - } catch (e) { - printV("Sync status update error: $e"); - } - } - - String getDiversifiedAddress(final int uaType, {final DateTime? time}) { - try { - final timestamp = (time ?? DateTime.now()).millisecondsSinceEpoch ~/ 1000; - return WarpApi.getDiversifiedAddress(coin, accountId, uaType, timestamp); - } catch (e) { - printV("Error getting diversified address: $e"); - return ""; - } - } - - static final autoShieldMutex = Mutex(); - Future _autoShield() async { - try { - await autoShieldMutex.acquire(); - await _$autoShield(); - } catch (e) { - printV("shielding failed: $e"); - await Future.delayed(Duration(seconds: 30)); - } finally { - autoShieldMutex.release(); - } - } - - Future _$autoShield() async { - final chainHeight = await WarpApi.getLatestHeight(coin); - final dbHeight = WarpApi.getDbHeight(coin); - final height = dbHeight.unpack(); - final syncHeight = height.height; - if (chainHeight != syncHeight) { - printV("Not autoshielding: chainHeight(${chainHeight}) != syncHeight(${syncHeight})"); - return; - } - final bpConfirmed = WarpApi.getPoolBalances(coin, accountId, 0, false); - if (bpConfirmed.transparent + bpConfirmed.sapling <= 20000) { - return; - } - - final recipientBuilder = RecipientObjectBuilder( - address: (walletAddresses as ZcashWalletAddresses).orchardAddress, - pools: 4, - feeIncluded: true, - amount: bpConfirmed.transparent + bpConfirmed.sapling, - ); - - final recipient = Recipient(recipientBuilder.toBytes()); - final fee = FeeT(fee: 10000, minFee: 0, maxFee: 0, scheme: 0); - await ZcashWalletBase.loadProver(); - final txPlan = await ZcashWalletService.runInDbMutex( - () => WarpApi.prepareTx( - coin, - accountId, - [recipient], - 3, // pools: (Transparent + Sapling) - 1, - 0, // anchorOffset - fee, - ), - ); - final _txId = await ZcashWalletService.runInDbMutex( - () => WarpApi.signAndBroadcast(ZcashWalletBase.coin, accountId, txPlan), - ); - await ZcashWalletService.addShieldedTx(_txId); - printV("shielded: $_txId"); - await updateTransactions(); - await updateBalance(); - await Future.delayed(Duration(seconds: 75 * 5)); // do not re-try doing that - } - - @override - @action - Future updateBalance() async { - try { - final poolBalances = WarpApi.getPoolBalances(coin, accountId, 0, true); - final balances = poolBalances.unpack(); - // final notes = WarpApi.getNotesSync(coin, accountId); - // int frozenBalance = 0; - // for (final note in notes) { - // if (note.excluded) { - // frozenBalance += note.value; - // } - // } - final total = balances.orchard + balances.sapling + balances.transparent; - final spendable = total - balances.transparent; - - final confirmedPoolBalances = WarpApi.getPoolBalances(coin, accountId, 3, true); - final confirmedBalances = confirmedPoolBalances.unpack(); - final confirmedTotal = - confirmedBalances.orchard + confirmedBalances.sapling + confirmedBalances.transparent; - - int knownOutPending = 0; - ZcashWalletBase.temporarySentTx[accountId]?.forEach((final sTx) { - knownOutPending += sTx.value; // it's negative - }); - final confirmedSpendable = confirmedTotal - balances.transparent + knownOutPending; - - unawaited(_autoShield()); - - balance[CryptoCurrency.zec] = ZcashBalance( - confirmed: confirmedSpendable, - unconfirmed: spendable - confirmedSpendable, - frozen: 0, - ); - } catch (e, stackTrace) { - printV("Balance update error: $e"); - printV("Stack trace: $stackTrace"); - } - } - - @override - Future verifyMessage( - final String message, - final String signature, { - final String? address = null, - }) { - throw UnimplementedError(); - } - - @observable - late WalletAddresses walletAddresses = ZcashWalletAddresses(accountId, walletInfo); - - static Future create(final WalletCredentials credentials) async { - await _init(); - final newWalletCredentials = credentials as ZcashNewWalletCredentials; - - String mnemonic; - if (newWalletCredentials.mnemonic?.isNotEmpty == true) { - mnemonic = newWalletCredentials.mnemonic!; - } else { - final strength = (newWalletCredentials.seedPhraseLength == 24) ? 256 : 128; - mnemonic = bip39.generateMnemonic(strength: strength); - } - - final accountId = await _restoreZcashWalletFromSeed( - name: credentials.name, - seed: mnemonic, - passphrase: newWalletCredentials.passphrase, - ); - await _saveAccountId(credentials.name, accountId); - final wallet = await open( - name: credentials.name, - password: credentials.password!, - walletInfo: credentials.walletInfo!, - ); - await wallet.walletAddresses.saveAddressesInBox(); - return wallet; - } - - static Future restore(final WalletCredentials credentials) async { - await _init(); - final fromSeedCredentials = credentials as ZcashFromSeedWalletCredentials; - final String? seed = fromSeedCredentials.seed; - if (seed == null || seed.isEmpty) { - throw Exception('Seed phrase is required for wallet restoration'); - } - - final accountId = await _restoreZcashWalletFromSeed( - name: credentials.name, - seed: seed, - passphrase: fromSeedCredentials.passphrase, - ); - await _saveAccountId(credentials.name, accountId); - final wallet = await open( - name: credentials.name, - password: credentials.password!, - walletInfo: credentials.walletInfo!, - ); - await wallet.walletAddresses.saveAddressesInBox(); - printV("height: ${credentials.height}"); - if (credentials.height != null) { - await storeZcashHeight(credentials.height!); - unawaited( - Future.delayed(Duration(seconds: 2)).then( - (_) => ZcashWalletService.runInDbMutex( - () async => await WarpApi.rescanFrom(coin, credentials.height ?? 0), - ), - ), - ); - } - return wallet; - } - - static Future restoreKeys(final WalletCredentials credentials) async { - await _init(); - final fromKeysCredentials = credentials as ZcashFromKeysWalletCredentials; - final String? keys = fromKeysCredentials.privateKey; - if (keys == null || keys.isEmpty) { - throw Exception('Key is required for wallet restoration'); - } - - final zcashSecretExtendedKeyRegex = RegExp(r'^secret-extended-key-main1[a-z0-9]+$'); - if (!zcashSecretExtendedKeyRegex.hasMatch(keys)) { - throw Exception('Key is not in secret-extended-key-main1 format'); - } - - final accountId = await _restoreZcashWalletFromSeed( - name: credentials.name, - seed: keys, - passphrase: fromKeysCredentials.passphrase, - ); - await _saveAccountId(credentials.name, accountId); - final wallet = await open( - name: credentials.name, - password: credentials.password!, - walletInfo: credentials.walletInfo!, - ); - await wallet.walletAddresses.saveAddressesInBox(); - printV("height: ${credentials.height}"); - if (credentials.height != null) { - await storeZcashHeight(credentials.height!); - unawaited( - Future.delayed(Duration(seconds: 2)).then( - (_) => ZcashWalletService.runInDbMutex( - () async => await WarpApi.rescanFrom(coin, credentials.height ?? 0), - ), - ), - ); - } - return wallet; - } - - static Future open({ - required final String name, - required final String password, - required final WalletInfo walletInfo, - }) async { - await _init(); - if (password.isNotEmpty) { - WarpApi.setDbPasswd(coin, password); - } - final accountId = await getZcashAccountIdForName(name); - if (accountId == null) { - throw Exception("Wallet account not found for name: $name"); - } - final wallet = ZcashWallet( - walletInfo, - await walletInfo.getDerivationInfo(), - accountId: accountId, - ); - await wallet.walletAddresses.init(); - return wallet; - } - - static Future _restoreZcashWalletFromSeed({ - required final String name, - required String seed, - required String? passphrase, - }) async { - if (passphrase?.isNotEmpty == true) { - passphrase = passphrase!.replaceAll(" ", "_"); - seed = "${seed} ${passphrase}"; - } - final accountId = await ZcashWalletService.runInDbMutex( - () => WarpApi.newAccount(coin, name, seed, 0), - ); - return accountId; - } - - static Future getZcashAccountIdForName(final String name) async { - final wPath = await pathForWallet(name: name, type: _type); - final f = File(wPath); - if (!f.existsSync()) { - final accounts = WarpApi.getAccountList(coin); - for (final account in accounts) { - if (account.name == name) { - return account.id; - } - } - return null; - } - final content = f.readAsStringSync(); - return int.tryParse(content.trim()); - } - - static Future _saveAccountId(final String name, final int accountId) async { - final wPath = await pathForWallet(name: name, type: _type); - final f = File(wPath); - f.writeAsStringSync(accountId.toString()); - } - - static WalletType get _type => WalletType.zcash; - - static Future getDbDataPath() async { - final pathForWalletType = await pathForWalletTypeDir(type: _type); - final dbDataPath = "${pathForWalletType}/zec.db"; - if (!Directory(pathForWalletType).existsSync()) { - Directory(pathForWalletType).createSync(recursive: true); - } - return dbDataPath; - } - - static Future getTorDir() async { - final pathForWalletType = await pathForWalletTypeDir(type: _type); - final torPath = "${pathForWalletType}/tor"; - if (!Directory(torPath).existsSync()) { - Directory(torPath).createSync(recursive: true); - } - return torPath; - } - - static Future getFsBlockCacheDir() async { - final pathForWalletType = await pathForWalletTypeDir(type: _type); - final fsBlockCacheDir = "${pathForWalletType}/blockCache"; - if (!Directory(pathForWalletType).existsSync()) { - Directory(pathForWalletType).createSync(recursive: true); - } - return fsBlockCacheDir; - } - - static String? dbDataPath; - static bool _initialized = false; - - static void unlockDatabase(final String password) { - _password = password; - } - - static String? _password; - static Future _init() async { - if (_initialized) return; - dbDataPath = await getDbDataPath(); - printV("WarpApi.initWallet"); - if (_password == null) { - throw Exception("Zcash wallet locked! Please contact support"); - } - if (!File(dbDataPath!).existsSync()) { - //TODO(mrcyjanek): copy-encrypt - } - // coin+1 = ycash - WarpApi.setDbPasswd(coin, ''); - WarpApi.setDbPasswd(coin + 1, ''); - WarpApi.initWallet(coin, dbDataPath!); - WarpApi.initWallet(coin + 1, dbDataPath!); - try { - WarpApi.migrateData(coin); - WarpApi.migrateData(coin + 1); - } catch (e) { - printV("zec init failed: $e"); - } // do not fail on network exception - await loadZcashHeight(); - - unawaited(loadProver()); - - await ZcashTaddressRotation.init(); - await ZcashTransactionInfo.init(); - _initialized = true; - } - - static bool isProverLoaded = false; - static Future loadProver() async { - Uint8List? spend; - Uint8List? output; - final cacheDir = await getApplicationCacheDirectory(); - try { - final spendBundle = await rootBundle.load('scripts/zcash_lib/assets/sapling-spend.params'); - final outputBundle = await rootBundle.load('scripts/zcash_lib/assets/sapling-output.params'); - spend = spendBundle.buffer.asUint8List(); - output = outputBundle.buffer.asUint8List(); - if (spend.length == 0 || output.length == 0) { - spend = await File(cacheDir.path + "/sapling-spend.params").readAsBytesSync(); - output = await File(cacheDir.path + "/sapling-output.params").readAsBytesSync(); - } - if (spend.length == 0 || output.length == 0) throw Exception("NUH UH"); - } catch (e) { - printV("$e. Fine, I'll download them."); - final spendResponse = await ProxyWrapper().get( - clearnetUri: Uri.parse("https://download.z.cash/downloads/sapling-spend.params"), - ); - final outputResponse = await ProxyWrapper().get( - clearnetUri: Uri.parse("https://download.z.cash/downloads/sapling-output.params"), - ); - spend = spendResponse.bodyBytes; - output = outputResponse.bodyBytes; - await File(cacheDir.path + "/sapling-spend.params").writeAsBytes(spend); - await File(cacheDir.path + "/sapling-output.params").writeAsBytes(output); - } - WarpApi.initProver(spend, output); - isProverLoaded = true; - } - - static Future getBlockHeightByTime(final DateTime time) async { - final genesisTime = DateTime.utc(2016, 10, 28); - const genesisHeight = 0; - - final firstHalvingTime = DateTime.utc(2020, 11, 18); - const firstHalvingHeight = 1046400; - - final secondHalvingTime = DateTime.utc(2024, 11, 23); - const secondHalvingHeight = 2726400; - - final t = time.toUtc().millisecondsSinceEpoch; - final t0 = genesisTime.millisecondsSinceEpoch; - final t1 = firstHalvingTime.millisecondsSinceEpoch; - final t2 = secondHalvingTime.millisecondsSinceEpoch; - - if (t <= t0) return genesisHeight; - - if (t < t1) { - return _interpolate(genesisHeight, firstHalvingHeight, t0, t1, t); - } - - if (t < t2) { - return _interpolate(firstHalvingHeight, secondHalvingHeight, t1, t2, t); - } - - final secondsSince2 = (t - t2) / 1000.0; - final blocksSince2 = (secondsSince2 / 76.0).floor(); - return secondHalvingHeight + blocksSince2; - } - - static int _interpolate( - final int hStart, - final int hEnd, - final int tStart, - final int tEnd, - final int t, - ) { - if (tEnd == tStart) return hStart; - final ratio = (t - tStart) / (tEnd - tStart); - return (hStart + (hEnd - hStart) * ratio).round(); - } - - static Future getHeightByDate(final DateTime date) async { - int height = await getBlockHeightByTime(date); - try { - final h2 = await WarpApi.getBlockHeightByTime(coin, date); - height = h2; - } catch (e) { - printV("getHeightByDate: $e"); - } - return height; - } - - bool couldBeZashiWallet() { - final backup = WarpApi.getBackup(coin, accountId); - final seed = backup.seed?.split(" "); - if (seed == null) return false; - if (zkoolSweep != null) return false; - if (!(syncStatus is SyncedSyncStatus)) return false; - return seed.length == 24; - } - - static ZkoolSweep? zkoolSweep; - - static bool _didRunRescanInternalChange = false; - Future rescanInternalChange() async { - if (_didRunRescanInternalChange) { - return; - } - _didRunRescanInternalChange = true; - final bal = - balance[CryptoCurrency.zec]!.confirmed + - balance[CryptoCurrency.zec]!.unconfirmed + - balance[CryptoCurrency.zec]!.frozen.toInt(); - final osCacheDir = await getApplicationCacheDirectory(); - final cacheDir = osCacheDir.createTempSync("zkool-import"); - zkoolSweep = ZkoolSweep( - currentBalance: bal, - cacheDir: cacheDir.path, - seed: seed ?? '', - passphrase: password, - address: (walletAddresses as ZcashWalletAddresses).orchardAddress, - url: (lastNode!.isSSL ? 'https://' : 'http://') + lastNode!.uriRaw, - height: (await loadZcashHeight()) ?? zashiAnnouncedBlockHeight, - ); - unawaited(zkoolSweep!.start()); - int count = 0; - Timer.periodic(Duration(milliseconds: 1000 ~/ 120), (final Timer t) { - final msg = ZkoolSweep.msg; - if (kDebugMode && (++count % (120 ~/ 10)) == 0) { - printV(msg.message); - } - if (msg.blocksLeft == 0 && msg.networkHeight != 0) { - zkoolSweep = null; - t.cancel(); - } - if (msg.blocksLeft == 0) { - syncStatus = ConnectedSyncStatus(); - return; - } - syncStatus = SyncingSyncStatus(msg.blocksLeft, msg.progress); - }); - } -} diff --git a/cw_zcash/lib/src/zcash_wallet_addresses.dart b/cw_zcash/lib/src/zcash_wallet_addresses.dart deleted file mode 100644 index a9fd207ae..000000000 --- a/cw_zcash/lib/src/zcash_wallet_addresses.dart +++ /dev/null @@ -1,247 +0,0 @@ -import 'package:cw_core/payment_uris.dart'; -import 'package:cw_core/receive_page_option.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/wallet_addresses.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_zcash/cw_zcash.dart'; -import 'package:cw_zcash/src/zcash_taddress_rotation.dart'; -import 'package:mobx/mobx.dart'; -import 'package:warp_api/warp_api.dart'; - -part 'zcash_wallet_addresses.g.dart'; - -class ZcashWalletAddresses = ZcashWalletAddressesBase with _$ZcashWalletAddresses; - -abstract class ZcashWalletAddressesBase extends WalletAddresses with Store { - ZcashWalletAddressesBase(this.accountId, final WalletInfo walletInfo) : super(walletInfo) { - addressPageType = ZcashReceivePageOption.typeFromString(walletInfo.addressPageType ?? ""); - } - - final int accountId; - - static const int transparentType = 0; - static const int shieldedSaplingType = 1; - static const int shieldedOrchardType = 2; - static const int unifiedType = 3; - - String? _transparentAddress; - String? _saplingAddress; - String? _orchardAddress; - String? _unifiedAddress; - - @override - @computed - String get latestAddress { - switch (addressPageType) { - case ZcashAddressType.transparent: - return transparentAddress; - case ZcashAddressType.transparentRotated: - // just to display something, after the wallet is synced the address - // will start rotating, and since we can't rotate address until the wallet syncs - // we can't know if some T address already got used, so we would still default to - // the same address. - // So.. we can - // 1) display placeholder text (looks ugly) - // 2) display static address - // 3) display first address from rotated pool which is also static until synced - // 2 seems like an obvious winner simply because it offers little to no benefit over 3 - // and is noticably less complex in implementation - return transparentAddressRotated ?? transparentAddress; - case ZcashAddressType.shieldedSapling: - return saplingAddress; - case ZcashAddressType.shieldedOrchard: - return orchardAddress; - case ZcashAddressType.unifiedType: - if (_unifiedAddress == null) { - _unifiedAddress = WarpApi.getAddress(ZcashWalletBase.coin, accountId, 6); - } - return _unifiedAddress ?? ""; - } - } - - @observable - ZcashAddressType? _addressPageType; - - @computed - ZcashAddressType get addressPageType => _addressPageType ?? ZcashAddressType.shieldedOrchard; - - @computed - set addressPageType(final ZcashAddressType newZat) { - _addressPageType = newZat; - init(); - address = latestAddress; - } - - @action - Future setAddressType(final ZcashAddressType type) async { - addressPageType = ZcashReceivePageOption.typeFromString(type.toString()); - walletInfo.addressPageType = type.toString(); - await walletInfo.save(); - } - - String get transparentAddress { - try { - if (_transparentAddress == null) { - _transparentAddress = WarpApi.getTAddr(ZcashWalletBase.coin, accountId); - } - return _transparentAddress ?? ""; - } catch (e) { - return ""; - } - } - - @computed - String? get transparentAddressRotated { - try { - return ZcashTaddressRotation.addressForAccount(accountId, hiddenAddresses); - } catch (e) { - return null; - } - } - - String get saplingAddress { - try { - if (_saplingAddress == null) { - _saplingAddress = WarpApi.getAddress(ZcashWalletBase.coin, accountId, 2); - } - return _saplingAddress ?? ""; - } catch (e) { - return ""; - } - } - - String get orchardAddress { - try { - if (_orchardAddress == null) { - _orchardAddress = WarpApi.getAddress(ZcashWalletBase.coin, accountId, 4); - } - return _orchardAddress ?? ""; - } catch (e) { - return ""; - } - } - - @override - @computed - String get addressForExchange => transparentAddressRotated ?? transparentAddress; - - @override - @computed - String get addressForBuy => transparentAddressRotated ?? transparentAddress; - - @override - bool containsAddress(final String address) { - return this.address == address || addressesMap.values.contains(address); - } - - static int get coin => ZcashWalletBase.coin; - - @override - @observable - Set hiddenAddresses = {}; - - Future _initAddresses() async { - addressesMap = await walletInfo.getAddresses(); - addressInfos = await walletInfo.getAddressInfos(); - usedAddresses = await walletInfo.getUsedAddresses(); - manualAddresses = await walletInfo.getManualAddresses(); - hiddenAddresses = await walletInfo.getHiddenAddresses(); - address = latestAddress; - } - - @override - Future init() async { - await _initAddresses(); - - await ZcashTaddressRotation.init(); - int accountIndex = 0; - addressInfos = { - 0: - ZcashTaddressRotation.allAddressesForAccount(accountId)?.map((final v) { - return WalletInfoAddressInfo( - walletInfoId: walletInfo.internalId, - mapKey: ++accountIndex, - accountIndex: 0, - address: v, - label: "", - ); - }).toList() ?? - [], - }; - hiddenAddresses.addAll( - ZcashTaddressRotation.allUsedAddressesForAccount(accountId)?.toSet() ?? {}, - ); - - // addressInfos[0]?.removeWhere((final test) => hiddenAddresses.contains(test.address)); - if (_addressPageType == ZcashAddressType.transparentRotated) { - final addr = ZcashTaddressRotation.addressForAccount(accountId, hiddenAddresses); - if (addr != null) { - address = addr; - } - } - await saveAddressesInBox(); - } - - @observable - late String _address = latestAddress; - - @computed - String get address { - return _address; - } - - void set address(final String _$address) => _address = _$address; - - @override - String get primaryAddress => address; - - @override - Future saveAddressesInBox() async { - try { - await walletInfo.setAddresses(addressesMap); - await walletInfo.setAddressInfos(addressInfos); - await walletInfo.setUsedAddresses(usedAddresses.toList()); - await walletInfo.setHiddenAddresses(hiddenAddresses.toList()); - await walletInfo.setManualAddresses(manualAddresses.toList()); - await _initAddresses(); - } catch (e) { - printV("Error saving addresses: $e"); - } - } - - @override - Future updateAddressesInBox() async { - _transparentAddress = null; - _saplingAddress = null; - _orchardAddress = null; - _unifiedAddress = null; - } - - @override - Map get usableAddressesMap => addressesMap; - - @override - Map get usableAllAddressesMap => allAddressesMap; - - List getAddressInfos() { - if (addressPageType != ZcashAddressType.transparentRotated) { - return []; - } - final List allInfos = []; - for (final entry in addressInfos.entries) { - allInfos.addAll(entry.value); - } - return allInfos; - } - - @override - List get receivePageOptions { - return [ - ...ZcashReceivePageOption.all, - ...ReceivePageOptions.where((final element) => element != ReceivePageOption.mainnet), - ]; - } - - @override - PaymentURI getPaymentUri(final String amount) => ZcashURI(amount: amount, address: address); -} diff --git a/cw_zcash/lib/src/zcash_wallet_service.dart b/cw_zcash/lib/src/zcash_wallet_service.dart deleted file mode 100644 index 0d79e7065..000000000 --- a/cw_zcash/lib/src/zcash_wallet_service.dart +++ /dev/null @@ -1,181 +0,0 @@ -import 'dart:io'; - -import 'package:bip39/bip39.dart' as bip39; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/utils/print_verbose.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:cw_core/wallet_type.dart'; -import 'package:cw_zcash/cw_zcash.dart'; -import 'package:mutex/mutex.dart'; -import 'package:path/path.dart' as p; - -class ZcashWalletService - extends - WalletService< - ZcashNewWalletCredentials, - ZcashFromSeedWalletCredentials, - ZcashFromKeysWalletCredentials, - ZcashNewWalletCredentials - > { - ZcashWalletService(); - - static Mutex dbMutex = Mutex(); - static int dbMutexQueue = 0; - static Future runInDbMutex(final Future Function() call) async { - try { - printV("dbMutexQueue: ${dbMutexQueue++}"); - await dbMutex.acquire(); - return await call(); - } finally { - dbMutex.release(); - dbMutexQueue--; - } - } - - static Set autoshieldTx = {}; - - static Future addShieldedTx(final String txId) async { - final pathForWalletType = await pathForWalletTypeDir(type: type); - final shieldedListFile = p.join(pathForWalletType, "autoshield_list.txt"); - autoshieldTx.add(txId.replaceAll(RegExp(r'[^a-zA-Z0-9 ]'), '')); - final shieldedList = File(shieldedListFile); - shieldedList.writeAsStringSync(autoshieldTx.join("\n")); - } - - static Future loadShieldTxs() async { - try { - final pathForWalletType = await pathForWalletTypeDir(type: type); - final shieldedListFile = p.join(pathForWalletType, "autoshield_list.txt"); - final shieldedList = File(shieldedListFile); - if (!shieldedList.existsSync()) { - return; - } - autoshieldTx = shieldedList.readAsLinesSync().toSet(); - } catch (e) { - printV("loadShieldTxs failed: $e"); - } - } - - static bool walletFilesExist(final String path) => - !File(path).existsSync() && !File('$path.keys').existsSync(); - - @override - WalletType getType() => type; - - static WalletType get type => WalletType.zcash; - - @override - Future create(final WalletCredentials credentials, {final bool? isTestnet}) { - return ZcashWalletBase.create(credentials); - } - - @override - Future isWalletExit(final String name) async { - final path = await pathForWallet(name: name, type: getType()); - return File(path).existsSync(); - } - - @override - Future openWallet(final String name, final String password) async { - await loadShieldTxs(); - final walletInfo = await WalletInfo.get(name, getType()); - if (walletInfo == null) { - throw Exception('Wallet not found'); - } - try { - final wallet = await ZcashWalletBase.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - await saveBackup(name); - return wallet; - } catch (e) { - await restoreWalletFilesFromBackup(name); - final wallet = await ZcashWalletBase.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - return wallet; - } - } - - @override - Future remove(final String wallet) async { - final path = await pathForWalletDir(name: wallet, type: getType()); - final file = Directory(path); - final isExist = file.existsSync(); - - if (isExist) { - await file.delete(recursive: true); - } - - final walletInfo = await WalletInfo.get(wallet, getType()); - if (walletInfo == null) { - throw Exception('Wallet not found'); - } - await WalletInfo.delete(walletInfo); - } - - @override - Future rename(final String currentName, final String password, final String newName) async { - final currentWalletInfo = await WalletInfo.get(currentName, getType()); - if (currentWalletInfo == null) { - throw Exception('Wallet not found'); - } - final accountId = await ZcashWalletBase.getZcashAccountIdForName(currentName); - if (accountId == null) { - throw Exception('Wallet account not found for name: $currentName'); - } - final currentWallet = ZcashWallet( - currentWalletInfo, - await currentWalletInfo.getDerivationInfo(), - accountId: accountId, - ); - - await currentWallet.renameWalletFiles(newName); - - final newWalletInfo = currentWalletInfo; - newWalletInfo.id = WalletBase.idFor(newName, getType()); - newWalletInfo.name = newName; - - await newWalletInfo.save(); - } - - @override - Future restoreFromKeys( - final ZcashFromKeysWalletCredentials credentials, { - final bool? isTestnet, - }) async { - return ZcashWalletBase.restoreKeys(credentials); - } - - @override - Future restoreFromSeed( - final ZcashFromSeedWalletCredentials credentials, { - final bool? isTestnet, - }) async { - if (credentials.seed == null || credentials.seed!.isEmpty) { - throw ZcashMnemonicIsIncorrectException(); - } - - if (!bip39.validateMnemonic(credentials.seed!)) { - throw ZcashMnemonicIsIncorrectException(); - } - - return ZcashWalletBase.restore(credentials); - } - - @override - Future restoreFromHardwareWallet(final ZcashNewWalletCredentials credentials) { - throw UnimplementedError( - "Restoring a Zcash wallet from a hardware wallet is not yet supported!", - ); - } -} diff --git a/cw_zcash/pubspec.yaml b/cw_zcash/pubspec.yaml deleted file mode 100644 index 835981eb2..000000000 --- a/cw_zcash/pubspec.yaml +++ /dev/null @@ -1,38 +0,0 @@ -name: cw_zcash -description: Zcash library for cake wallet -version: 1.0.0 -publish_to: none - -environment: - sdk: ^3.8.0 - -dependencies: - flutter: - sdk: flutter - warp_api: - path: ../scripts/zcash_lib/packages/warp_api_ffi - cw_core: - path: ../cw_core - mobx: ^2.5.0 - bip39: ^1.0.6 - mutex: ^3.1.0 - - path: any - flat_buffers: any - zkool: - git: - url: https://github.com/cake-tech/zkool2 - ref: b1642f260da4fa00dd2f8d4dd689073d0b56960a - - path_provider: any -dependency_overrides: - decimal: ^2.3.3 - -dev_dependencies: - flutter_test: - sdk: flutter - build_runner: ^2.4.15 - build_resolvers: ^2.4.4 - mobx_codegen: ^2.0.7 - hive_generator: ^2.0.1 - ffigen: ^16.1.0 diff --git a/hashwallet.bat b/hashwallet.bat index 0d88226b2..8033d2d77 100644 --- a/hashwallet.bat +++ b/hashwallet.bat @@ -24,7 +24,7 @@ IF NOT EXIST "%secrets_file_path%" ( ) ELSE (echo === Using previously/already generated secrets file: %secrets_file_path% ===) echo === Generating mobx models === -for /d %%i in (cw_core cw_monero cw_bitcoin cw_evm cw_nano cw_bitcoin_cash cw_solana cw_tron cw_zcash.) do ( +for /d %%i in (cw_core cw_monero cw_bitcoin cw_evm cw_nano cw_bitcoin_cash cw_wownero cw_dogecoin) do ( cd %%i call flutter pub get > nul call dart run build_runner build --delete-conflicting-outputs > nul diff --git a/pubspec_base.yaml b/pubspec_base.yaml index f6841b6a3..70a8c5660 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -271,13 +271,10 @@ flutter: - assets/dogecoin_electrum_server_list.yml - assets/base_node_list.yml - assets/arbitrum_node_list.yml - - assets/zcash_node_list.yml - assets/bsc_node_list.yml - assets/text/ - assets/faq/ - assets/animation/ - - scripts/zcash_lib/assets/sapling-spend.params - - scripts/zcash_lib/assets/sapling-output.params - assets/new-ui/ - assets/new-ui/icons/ - assets/new-ui/hero/ diff --git a/scripts/android/build_zcash.sh b/scripts/android/build_zcash.sh deleted file mode 100755 index eca46936a..000000000 --- a/scripts/android/build_zcash.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -x -e -cd "$(dirname "$0")" - -../prepare_zcash.sh - -pushd ../zcash_lib - ./build-scripts/build-android.sh -popd diff --git a/scripts/android/docker/Dockerfile.final b/scripts/android/docker/Dockerfile.final index 0f9a794a5..d9f130f90 100644 --- a/scripts/android/docker/Dockerfile.final +++ b/scripts/android/docker/Dockerfile.final @@ -5,7 +5,6 @@ ARG BITBOX_IMAGE ARG MONERO_IMAGE ARG DECRED_IMAGE ARG MWEBD_IMAGE -ARG ZCASH_IMAGE FROM ${TORCH_IMAGE} AS torch_src FROM ${REOWN_IMAGE} AS reown_src @@ -13,7 +12,6 @@ FROM ${BITBOX_IMAGE} AS bitbox_src FROM ${MONERO_IMAGE} AS monero_src FROM ${DECRED_IMAGE} AS decred_src FROM ${MWEBD_IMAGE} AS mwebd_src -FROM ${ZCASH_IMAGE} AS zcash_src FROM --platform=linux/amd64 alpine @@ -23,4 +21,3 @@ COPY --from=bitbox_src /w /w.top COPY --from=monero_src /w /w.top COPY --from=decred_src /w /w.top COPY --from=mwebd_src /w /w.top -COPY --from=zcash_src /w /w.top diff --git a/scripts/android/docker/Dockerfile.zcash b/scripts/android/docker/Dockerfile.zcash deleted file mode 100644 index 26bb1c82c..000000000 --- a/scripts/android/docker/Dockerfile.zcash +++ /dev/null @@ -1,11 +0,0 @@ -ARG BASE_IMAGE -FROM --platform=linux/amd64 ${BASE_IMAGE} AS build - -RUN mkdir -p /w/scripts/android -COPY scripts/prepare_zcash.sh /w/scripts/prepare_zcash.sh -COPY scripts/android/build_zcash.sh /w/scripts/android/build_zcash.sh -RUN /w/scripts/android/build_zcash.sh \ - && rm -rf /w/scripts/zcash_lib/target - -FROM --platform=linux/amd64 alpine -COPY --from=build /w /w diff --git a/scripts/android/docker/build.sh b/scripts/android/docker/build.sh index 3a3824379..e6cb1d372 100755 --- a/scripts/android/docker/build.sh +++ b/scripts/android/docker/build.sh @@ -56,9 +56,8 @@ reown_ver=$(tinysha $SCRIPT_DIR/Dockerfile.reown $REPO_ROOT/scripts/prepare_reow bitbox_ver=$(tinysha $SCRIPT_DIR/Dockerfile.bitbox $REPO_ROOT/scripts/build_bitbox_flutter.sh) monero_ver=$(tinysha $SCRIPT_DIR/Dockerfile.monero $REPO_ROOT/scripts/prepare_moneroc.sh $REPO_ROOT/scripts/android/build_monero_all.sh) mwebd_ver=$(tinysha $SCRIPT_DIR/Dockerfile.mwebd $(find $REPO_ROOT/cw_mweb/go -type f)) -zcash_ver=$(tinysha $SCRIPT_DIR/Dockerfile.zcash $REPO_ROOT/scripts/prepare_zcash.sh $REPO_ROOT/scripts/android/build_zcash.sh) decred_ver=$(tinysha $SCRIPT_DIR/Dockerfile.torch $SCRIPT_DIR/Dockerfile.decred $REPO_ROOT/scripts/android/build_decred.sh) -echo $base_ver $torch_ver $reown_ver $bitbox_ver $monero_ver $mwebd_ver $zcash_ver $decred_ver > /tmp/docker_build_versions +echo $base_ver $torch_ver $reown_ver $bitbox_ver $monero_ver $mwebd_ver $decred_ver > /tmp/docker_build_versions final_ver=$(tinysha /tmp/docker_build_versions) docker create --name temp_extract $(img final $final_ver) \ @@ -83,8 +82,6 @@ build reown "$reown_ver" --build-arg BASE_IMAGE="$(img base "$base_ver")" build monero "$monero_ver" --build-arg BASE_IMAGE="$(img base "$base_ver")" -build zcash "$zcash_ver" --build-arg BASE_IMAGE="$(img base "$base_ver")" - build torch "$torch_ver" \ --build-arg BASE_IMAGE="$(img base "$base_ver")" @@ -99,8 +96,7 @@ build final $final_ver \ --build-arg BITBOX_IMAGE="$(img bitbox $bitbox_ver)" \ --build-arg MONERO_IMAGE="$(img monero $monero_ver)" \ --build-arg DECRED_IMAGE="$(img decred $decred_ver)" \ - --build-arg MWEBD_IMAGE="$(img mwebd $mwebd_ver)" \ - --build-arg ZCASH_IMAGE="$(img zcash $zcash_ver)" + --build-arg MWEBD_IMAGE="$(img mwebd $mwebd_ver)" echo "done: $(img final $final_ver)" echo $(img final $final_ver) > /tmp/cakewallet_docker diff --git a/scripts/ios/build_zcash.sh b/scripts/ios/build_zcash.sh deleted file mode 100755 index 96a8e4992..000000000 --- a/scripts/ios/build_zcash.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -x -e -cd "$(dirname "$0")" - -../prepare_zcash.sh - -pushd ../zcash_lib - ./build-scripts/mac/build-mac.sh -popd diff --git a/scripts/linux/build_zcash.sh b/scripts/linux/build_zcash.sh deleted file mode 100755 index 07f85f018..000000000 --- a/scripts/linux/build_zcash.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -x -e -cd "$(dirname "$0")" - -../prepare_zcash.sh - -pushd ../zcash_lib - ./build-scripts/build-linux.sh -popd diff --git a/scripts/macos/build_zcash.sh b/scripts/macos/build_zcash.sh deleted file mode 100755 index 96a8e4992..000000000 --- a/scripts/macos/build_zcash.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -x -e -cd "$(dirname "$0")" - -../prepare_zcash.sh - -pushd ../zcash_lib - ./build-scripts/mac/build-mac.sh -popd diff --git a/scripts/prepare_zcash.sh b/scripts/prepare_zcash.sh deleted file mode 100755 index 5abc3212d..000000000 --- a/scripts/prepare_zcash.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -set -x -e -cd "$(dirname "$0")" - -HASH=647231e2e6d93c1d6c16d4019cd3a11a3aaa9504 - -if [[ ! -d "zcash_lib/.git" ]]; -then - rm -rf zcash_lib - git clone https://github.com/MrCyjaneK/zwallet.git zcash_lib - cd zcash_lib -else - cd zcash_lib - git fetch -a -fi - - -git reset --hard -git checkout $HASH -git reset --hard -git submodule update --init --force --recursive - -# in go I could nicely replace => the heck out of it -# sadly rust is not go -find . -name Cargo.toml -exec sed -i.bak -E ' -s|rusqlite[[:space:]]*=[[:space:]]*\{[^}]*\}|rusqlite = { version = "0.29.0", features = ["bundled", "modern_sqlite", "backup"] }|g -' {} + -# find . -name Cargo.toml -exec sed -i.bak -E 's|r2d2_sqlite[[:space:]]*=[[:space:]]*([^\n]*)|r2d2_sqlite = "0.32.0"|g' {} +