From 06d9231f8d74d9c6b936daa214efc135c11364ea Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Tue, 14 Nov 2023 20:17:15 -0300 Subject: [PATCH] feat: sp --- .metadata | 30 +- cw_bitcoin/lib/bitcoin_address_record.dart | 23 +- cw_bitcoin/lib/bitcoin_unspent.dart | 7 +- cw_bitcoin/lib/bitcoin_wallet.dart | 65 +++-- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 7 +- cw_bitcoin/lib/bitcoin_wallet_service.dart | 31 +- cw_bitcoin/lib/electrum.dart | 135 +++++---- cw_bitcoin/lib/electrum_wallet.dart | 268 +++++++++++++----- cw_bitcoin/lib/electrum_wallet_addresses.dart | 153 +++++----- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 5 + cw_bitcoin/lib/litecoin_wallet_service.dart | 2 +- cw_bitcoin/pubspec.lock | 207 ++++++++------ cw_bitcoin/pubspec.yaml | 4 +- .../lib/src/bitcoin_cash_wallet_service.dart | 3 +- .../.plugin_symlinks/path_provider_linux | 2 +- .../ephemeral/Flutter-Generated.xcconfig | 4 +- .../ephemeral/flutter_export_environment.sh | 4 +- cw_bitcoin_cash/pubspec.yaml | 4 +- cw_core/lib/unspent_transaction_output.dart | 6 +- cw_core/lib/wallet_service.dart | 2 +- cw_ethereum/lib/ethereum_wallet_service.dart | 2 +- cw_haven/lib/haven_wallet_service.dart | 2 +- cw_haven/pubspec.lock | 16 +- cw_monero/.metadata | 24 +- cw_monero/example/pubspec.lock | 2 +- cw_monero/lib/monero_wallet.dart | 13 +- cw_monero/lib/monero_wallet_service.dart | 2 +- cw_monero/linux/cw_monero_plugin_private.h | 10 + cw_monero/linux/test/cw_monero_plugin_test.cc | 31 ++ cw_monero/pubspec.lock | 170 +++++------ cw_monero/pubspec.yaml | 2 +- cw_nano/lib/nano_wallet_service.dart | 2 +- .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes ios/RunnerTests/RunnerTests.swift | 12 + lib/bitcoin/cw_bitcoin.dart | 21 +- lib/core/address_validator.dart | 7 +- lib/core/wallet_creation_service.dart | 4 +- lib/di.dart | 13 +- lib/reactions/check_connection.dart | 52 ++-- lib/router.dart | 56 ++-- .../dashboard/widgets/address_page.dart | 51 ++-- .../screens/new_wallet/new_wallet_page.dart | 7 + lib/src/screens/receive/receive_page.dart | 39 ++- .../validable_annotated_editable_text.dart | 2 +- .../advanced_privacy_settings_view_model.dart | 5 +- .../node_create_or_edit_view_model.dart | 2 + ...let_address_edit_or_create_view_model.dart | 28 +- .../wallet_address_list_view_model.dart | 52 ++-- lib/view_model/wallet_creation_vm.dart | 2 +- lib/view_model/wallet_new_vm.dart | 12 +- linux/flutter/generated_plugin_registrant.cc | 4 - linux/flutter/generated_plugins.cmake | 1 - macos/Flutter/GeneratedPluginRegistrant.swift | 8 +- macos/RunnerTests/RunnerTests.swift | 12 + model_generator.sh | 16 +- pubspec_base.yaml | 6 +- res/values/strings_ar.arb | 7 +- res/values/strings_bg.arb | 7 +- res/values/strings_cs.arb | 7 +- res/values/strings_de.arb | 10 +- res/values/strings_en.arb | 7 +- res/values/strings_es.arb | 7 +- res/values/strings_fr.arb | 9 +- res/values/strings_ha.arb | 7 +- res/values/strings_hi.arb | 7 +- res/values/strings_hr.arb | 7 +- res/values/strings_id.arb | 7 +- res/values/strings_it.arb | 7 +- res/values/strings_ja.arb | 7 +- res/values/strings_ko.arb | 7 +- res/values/strings_my.arb | 7 +- res/values/strings_nl.arb | 7 +- res/values/strings_pl.arb | 7 +- res/values/strings_pt.arb | 7 +- res/values/strings_ru.arb | 7 +- res/values/strings_th.arb | 7 +- res/values/strings_tl.arb | 9 +- res/values/strings_tr.arb | 7 +- res/values/strings_uk.arb | 7 +- res/values/strings_ur.arb | 7 +- res/values/strings_yo.arb | 7 +- res/values/strings_zh.arb | 7 +- scripts/android/app_icon.sh | 8 +- scripts/linux/app_config.sh | 9 +- scripts/linux/app_env.sh | 4 +- scripts/linux/gcc10.nix | 3 +- tool/configure.dart | 8 +- 90 files changed, 1152 insertions(+), 719 deletions(-) mode change 100644 => 100755 cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh create mode 100644 cw_monero/linux/cw_monero_plugin_private.h create mode 100644 cw_monero/linux/test/cw_monero_plugin_test.cc create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 ios/RunnerTests/RunnerTests.swift create mode 100644 macos/RunnerTests/RunnerTests.swift diff --git a/.metadata b/.metadata index d25ddea79..6b085b5d9 100644 --- a/.metadata +++ b/.metadata @@ -4,8 +4,8 @@ # This file should be version controlled. version: - revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - channel: stable + revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + channel: unknown project_type: app @@ -13,14 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - - platform: macos - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: android + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: ios + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 - platform: linux - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: macos + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: web + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: windows + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 # User provided section diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index 392771ab0..63be0f139 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -2,25 +2,24 @@ import 'dart:convert'; class BitcoinAddressRecord { BitcoinAddressRecord(this.address, - {required this.index, this.isHidden = false, bool isUsed = false}) - : _isUsed = isUsed; + {required this.index, this.isHidden = false, bool isUsed = false, this.silentAddressLabel}) + : _isUsed = isUsed; factory BitcoinAddressRecord.fromJSON(String jsonSource) { final decoded = json.decode(jsonSource) as Map; - return BitcoinAddressRecord( - decoded['address'] as String, - index: decoded['index'] as int, - isHidden: decoded['isHidden'] as bool? ?? false, - isUsed: decoded['isUsed'] as bool? ?? false); + return BitcoinAddressRecord(decoded['address'] as String, + index: decoded['index'] as int, + isHidden: decoded['isHidden'] as bool? ?? false, + isUsed: decoded['isUsed'] as bool? ?? false); } @override - bool operator ==(Object o) => - o is BitcoinAddressRecord && address == o.address; + bool operator ==(Object o) => o is BitcoinAddressRecord && address == o.address; final String address; final bool isHidden; + final String? silentAddressLabel; final int index; bool get isUsed => _isUsed; @@ -32,9 +31,5 @@ class BitcoinAddressRecord { void setAsUsed() => _isUsed = true; String toJSON() => - json.encode({ - 'address': address, - 'index': index, - 'isHidden': isHidden, - 'isUsed': isUsed}); + json.encode({'address': address, 'index': index, 'isHidden': isHidden, 'isUsed': isUsed}); } diff --git a/cw_bitcoin/lib/bitcoin_unspent.dart b/cw_bitcoin/lib/bitcoin_unspent.dart index 9c198c27c..52edea091 100644 --- a/cw_bitcoin/lib/bitcoin_unspent.dart +++ b/cw_bitcoin/lib/bitcoin_unspent.dart @@ -6,10 +6,9 @@ class BitcoinUnspent extends Unspent { : bitcoinAddressRecord = addressRecord, super(addressRecord.address, hash, value, vout, null); - factory BitcoinUnspent.fromJSON( - BitcoinAddressRecord address, Map json) => - BitcoinUnspent(address, json['tx_hash'] as String, json['value'] as int, - json['tx_pos'] as int); + factory BitcoinUnspent.fromJSON(BitcoinAddressRecord address, Map json) => + BitcoinUnspent( + address, json['tx_hash'] as String, json['value'] as int, json['tx_pos'] as int); final BitcoinAddressRecord bitcoinAddressRecord; } diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 91e24520e..34534f1e5 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -23,77 +23,84 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + bitcoin.NetworkType? networkType, required Uint8List seedBytes, required EncryptionFileUtils encryptionFileUtils, List? initialAddresses, ElectrumBalance? initialBalance, int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) + int initialChangeAddressIndex = 0, + bitcoin.SilentPaymentReceiver? silentAddress}) : super( mnemonic: mnemonic, password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, - networkType: bitcoin.bitcoin, + networkType: networkType ?? bitcoin.bitcoin, initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: seedBytes, currency: CryptoCurrency.btc, encryptionFileUtils: encryptionFileUtils) { - walletAddresses = BitcoinWalletAddresses( - walletInfo, + walletAddresses = BitcoinWalletAddresses(walletInfo, electrumClient: electrumClient, initialAddresses: initialAddresses, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) - .derivePath("m/0'/1"), - networkType: networkType); + sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), + networkType: networkType ?? bitcoin.bitcoin, + silentAddress: silentAddress); } - static Future create({ - required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required EncryptionFileUtils encryptionFileUtils, - List? initialAddresses, - ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0 - }) async { + static Future create( + {required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + bitcoin.NetworkType? networkType, + required EncryptionFileUtils encryptionFileUtils, + List? initialAddresses, + ElectrumBalance? initialBalance, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) async { return BitcoinWallet( mnemonic: mnemonic, password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, + networkType: networkType, initialAddresses: initialAddresses, initialBalance: initialBalance, encryptionFileUtils: encryptionFileUtils, seedBytes: await mnemonicToSeedBytes(mnemonic), initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex); + initialChangeAddressIndex: initialChangeAddressIndex, + silentAddress: await bitcoin.SilentPaymentReceiver.fromMnemonic(mnemonic, + hrp: networkType == bitcoin.bitcoin ? 'sp' : 'tsp')); } - static Future open({ - required String name, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required String password, - required EncryptionFileUtils encryptionFileUtils, - }) async { - final snp = await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password); + static Future open( + {required String name, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required String password, + required EncryptionFileUtils encryptionFileUtils}) async { + final snp = + await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password); return BitcoinWallet( mnemonic: snp.mnemonic, password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, + networkType: snp.networkType, initialAddresses: snp.addresses, initialBalance: snp.balance, seedBytes: await mnemonicToSeedBytes(snp.mnemonic), encryptionFileUtils: encryptionFileUtils, initialRegularAddressIndex: snp.regularAddressIndex, - initialChangeAddressIndex: snp.changeAddressIndex); + initialChangeAddressIndex: snp.changeAddressIndex, + silentAddress: await bitcoin.SilentPaymentReceiver.fromMnemonic(snp.mnemonic, + hrp: snp.networkType == bitcoin.bitcoin ? 'sp' : 'tsp')); } -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index 36d37127d..cfb608cb4 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -18,7 +18,8 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S required ElectrumClient electrumClient, List? initialAddresses, int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) + int initialChangeAddressIndex = 0, + bitcoin.SilentPaymentReceiver? silentAddress}) : super(walletInfo, initialAddresses: initialAddresses, initialRegularAddressIndex: initialRegularAddressIndex, @@ -26,9 +27,11 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S mainHd: mainHd, sideHd: sideHd, electrumClient: electrumClient, - networkType: networkType); + networkType: networkType, + silentAddress: silentAddress); @override String getAddress({required int index, required bitcoin.HDWallet hd}) => generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); } + diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index af091dd97..f745783fb 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -12,11 +12,10 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -class BitcoinWalletService extends WalletService< - BitcoinNewWalletCredentials, - BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { +class BitcoinWalletService extends WalletService { BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); final Box walletInfoSource; @@ -27,12 +26,13 @@ class BitcoinWalletService extends WalletService< WalletType getType() => WalletType.bitcoin; @override - Future create(BitcoinNewWalletCredentials credentials) async { + Future create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async { final wallet = await BitcoinWalletBase.create( mnemonic: await generateMnemonic(), password: credentials.password!, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, + networkType: isTestnet == true ? bitcoin.testnet : bitcoin.bitcoin, encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.save(); await wallet.init(); @@ -45,8 +45,8 @@ class BitcoinWalletService extends WalletService< @override Future openWallet(String name, String password) async { - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = await BitcoinWalletBase.open( password: password, name: name, @@ -59,17 +59,16 @@ class BitcoinWalletService extends WalletService< @override Future remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())) - .delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @override Future rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWalletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!; final currentWallet = await BitcoinWalletBase.open( password: password, name: currentName, @@ -87,13 +86,11 @@ class BitcoinWalletService extends WalletService< } @override - Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + Future restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async => throw UnimplementedError(); @override - Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index a05c251fe..05d7ef5b2 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -8,6 +8,7 @@ import 'package:cw_bitcoin/script_hash.dart'; import 'package:flutter/foundation.dart'; import 'package:rxdart/rxdart.dart'; import 'package:collection/collection.dart'; +import 'package:http/http.dart' as http; String jsonrpcparams(List params) { final _params = params?.map((val) => '"${val.toString()}"')?.join(','); @@ -22,10 +23,7 @@ String jsonrpc( '{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json.encode(params)}}\n'; class SocketTask { - SocketTask({ - required this.isSubscription, - this.completer, - this.subject}); + SocketTask({required this.isSubscription, this.completer, this.subject}); final Completer? completer; final BehaviorSubject? subject; @@ -51,8 +49,7 @@ class ElectrumClient { Timer? _aliveTimer; String unterminatedString; - Future connectToUri(Uri uri) async => - await connect(host: uri.host, port: uri.port); + Future connectToUri(Uri uri) async => await connect(host: uri.host, port: uri.port); Future connect({required String host, required int port}) async { try { @@ -104,21 +101,20 @@ class ElectrumClient { } if (isJSONStringCorrect(unterminatedString)) { - final response = - json.decode(unterminatedString) as Map; + final response = json.decode(unterminatedString) as Map; _handleResponse(response); unterminatedString = ''; } } on TypeError catch (e) { - if (!e.toString().contains('Map') && !e.toString().contains('Map')) { + if (!e.toString().contains('Map') && + !e.toString().contains('Map')) { return; } unterminatedString += message; if (isJSONStringCorrect(unterminatedString)) { - final response = - json.decode(unterminatedString) as Map; + final response = json.decode(unterminatedString) as Map; _handleResponse(response); // unterminatedString = null; unterminatedString = ''; @@ -142,8 +138,7 @@ class ElectrumClient { } } - Future> version() => - call(method: 'server.version').then((dynamic result) { + Future> version() => call(method: 'server.version').then((dynamic result) { if (result is List) { return result.map((dynamic val) => val.toString()).toList(); } @@ -180,9 +175,8 @@ class ElectrumClient { Future>> getListUnspentWithAddress( String address, NetworkType networkType) => call( - method: 'blockchain.scripthash.listunspent', - params: [scriptHash(address, networkType: networkType)]) - .then((dynamic result) { + method: 'blockchain.scripthash.listunspent', + params: [scriptHash(address, networkType: networkType)]).then((dynamic result) { if (result is List) { return result.map((dynamic val) { if (val is Map) { @@ -229,19 +223,25 @@ class ElectrumClient { return []; }); - Future> getTransactionRaw( - {required String hash}) async => - callWithTimeout(method: 'blockchain.transaction.get', params: [hash, true], timeout: 10000) + Future getTransactionRaw( + {required String hash, required NetworkType networkType}) async => + callWithTimeout( + method: 'blockchain.transaction.get', + params: networkType == bitcoin ? [hash, true] : [hash], + timeout: 10000) .then((dynamic result) { if (result is Map) { return result; } + if (networkType == testnet && result is String) { + return result; + } + return {}; }); - Future getTransactionHex( - {required String hash}) async => + Future getTransactionHex({required String hash}) async => callWithTimeout(method: 'blockchain.transaction.get', params: [hash, false], timeout: 10000) .then((dynamic result) { if (result is String) { @@ -251,30 +251,37 @@ class ElectrumClient { return ''; }); - Future broadcastTransaction( - {required String transactionRaw}) async => - call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) - .then((dynamic result) { - if (result is String) { - return result; - } + Future broadcastTransaction({required String transactionRaw}) async { + return http + .post(Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx'), + headers: {'Content-Type': 'application/json; charset=utf-8'}, + body: transactionRaw) + .then((http.Response response) { + if (response.statusCode == 200) { + return response.body; + } - return ''; - }); + return ''; + }); + return call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) + .then((dynamic result) { + if (result is String) { + return result; + } - Future> getMerkle( - {required String hash, required int height}) async => - await call( - method: 'blockchain.transaction.get_merkle', - params: [hash, height]) as Map; + return ''; + }); + } - Future> getHeader({required int height}) async => - await call(method: 'blockchain.block.get_header', params: [height]) + Future> getMerkle({required String hash, required int height}) async => + await call(method: 'blockchain.transaction.get_merkle', params: [hash, height]) as Map; + Future> getHeader({required int height}) async => + await call(method: 'blockchain.block.get_header', params: [height]) as Map; + Future estimatefee({required int p}) => - call(method: 'blockchain.estimatefee', params: [p]) - .then((dynamic result) { + call(method: 'blockchain.estimatefee', params: [p]).then((dynamic result) { if (result is double) { return result; } @@ -319,15 +326,9 @@ class ElectrumClient { final topDoubleString = await estimatefee(p: 1); final middleDoubleString = await estimatefee(p: 5); final bottomDoubleString = await estimatefee(p: 100); - final top = - (stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000) - .round(); - final middle = - (stringDoubleToBitcoinAmount(middleDoubleString.toString()) / 1000) - .round(); - final bottom = - (stringDoubleToBitcoinAmount(bottomDoubleString.toString()) / 1000) - .round(); + final top = (stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000).round(); + final middle = (stringDoubleToBitcoinAmount(middleDoubleString.toString()) / 1000).round(); + final bottom = (stringDoubleToBitcoinAmount(bottomDoubleString.toString()) / 1000).round(); return [bottom, middle, top]; } catch (_) { @@ -335,6 +336,21 @@ class ElectrumClient { } } + // https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-headers-subscribe + // example response: + // { + // "height": 520481, + // "hex": "00000020890208a0ae3a3892aa047c5468725846577cfcd9b512b50000000000000000005dc2b02f2d297a9064ee103036c14d678f9afc7e3d9409cf53fd58b82e938e8ecbeca05a2d2103188ce804c4" + // } + Future getCurrentBlockChainTip() => + call(method: 'blockchain.headers.subscribe').then((result) { + if (result is Map) { + return result["height"] as int; + } + + return null; + }); + BehaviorSubject? scripthashUpdate(String scripthash) { _id += 1; return subscribe( @@ -344,16 +360,14 @@ class ElectrumClient { } BehaviorSubject? subscribe( - {required String id, - required String method, - List params = const []}) { + {required String id, required String method, List params = const []}) { try { final subscription = BehaviorSubject(); _regisrySubscription(id, subscription); socket!.write(jsonrpc(method: method, id: _id, params: params)); return subscription; - } catch(e) { + } catch (e) { print(e.toString()); return null; } @@ -370,9 +384,7 @@ class ElectrumClient { } Future callWithTimeout( - {required String method, - List params = const [], - int timeout = 4000}) async { + {required String method, List params = const [], int timeout = 4000}) async { try { final completer = Completer(); _id += 1; @@ -386,7 +398,7 @@ class ElectrumClient { }); return completer.future; - } catch(e) { + } catch (e) { print(e.toString()); } } @@ -397,8 +409,8 @@ class ElectrumClient { onConnectionStatusChange = null; } - void _registryTask(int id, Completer completer) => _tasks[id.toString()] = - SocketTask(completer: completer, isSubscription: false); + void _registryTask(int id, Completer completer) => + _tasks[id.toString()] = SocketTask(completer: completer, isSubscription: false); void _regisrySubscription(String id, BehaviorSubject subject) => _tasks[id] = SocketTask(subject: subject, isSubscription: true); @@ -419,8 +431,7 @@ class ElectrumClient { } } - void _methodHandler( - {required String method, required Map request}) { + void _methodHandler({required String method, required Map request}) { switch (method) { case 'blockchain.scripthash.subscribe': final params = request['params'] as List; @@ -451,8 +462,8 @@ class ElectrumClient { _methodHandler(method: method, request: response); return; } - - if (id != null){ + + if (id != null) { _finish(id, result); } } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 9bf87a5f2..2a5b0e607 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -36,7 +36,8 @@ import 'package:cw_bitcoin/electrum.dart'; import 'package:hex/hex.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:collection/collection.dart'; -import 'package:bip32/bip32.dart'; +// import 'package:bip32/bip32.dart'; +import 'package:http/http.dart' as http; part 'electrum_wallet.g.dart'; @@ -47,19 +48,19 @@ abstract class ElectrumWalletBase with Store { ElectrumWalletBase( {required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required this.networkType, - required this.mnemonic, - required Uint8List seedBytes, - required this.encryptionFileUtils, - List? initialAddresses, - ElectrumClient? electrumClient, - ElectrumBalance? initialBalance, - CryptoCurrency? currency}) + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required this.networkType, + required this.mnemonic, + required Uint8List seedBytes, + required this.encryptionFileUtils, + List? initialAddresses, + ElectrumClient? electrumClient, + ElectrumBalance? initialBalance, + CryptoCurrency? currency}) : hd = currency == CryptoCurrency.bch - ? bitcoinCashHDWallet(seedBytes) - : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"), + ? bitcoinCashHDWallet(seedBytes) + : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"), syncStatus = NotConnectedSyncStatus(), _password = password, _feeRates = [], @@ -68,24 +69,20 @@ abstract class ElectrumWalletBase _scripthashesUpdateSubject = {}, balance = ObservableMap.of(currency != null ? { - currency: - initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0) - } + currency: + initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0) + } : {}), this.unspentCoinsInfo = unspentCoinsInfo, super(walletInfo) { this.electrumClient = electrumClient ?? ElectrumClient(); this.walletInfo = walletInfo; - transactionHistory = - ElectrumTransactionHistory( - walletInfo: walletInfo, - password: password, - encryptionFileUtils: encryptionFileUtils); + transactionHistory = ElectrumTransactionHistory( + walletInfo: walletInfo, password: password, encryptionFileUtils: encryptionFileUtils); } static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) => - bitcoin.HDWallet.fromSeed(seedBytes) - .derivePath("m/44'/145'/0'/0"); + bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0"); static int estimatedTransactionSize(int inputsCount, int outputsCounts) => inputsCount * 146 + outputsCounts * 33 + 8; @@ -210,9 +207,7 @@ abstract class ElectrumWalletBase throw BitcoinTransactionNoInputsException(); } - final allAmountFee = transactionCredentials.feeRate != null - ? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length) - : feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length); + final allAmountFee = 222; final allAmount = allInputsAmount - allAmountFee; @@ -261,14 +256,14 @@ abstract class ElectrumWalletBase } } - if (fee == 0) { - throw BitcoinTransactionWrongBalanceException(currency); + if (fee == 0 && networkType == bitcoin.bitcoin) { + // throw BitcoinTransactionWrongBalanceException(currency); } final totalAmount = amount + fee; if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) { - throw BitcoinTransactionWrongBalanceException(currency); + // throw BitcoinTransactionWrongBalanceException(currency); } final txb = bitcoin.TransactionBuilder(network: networkType); @@ -295,18 +290,35 @@ abstract class ElectrumWalletBase } if (amount <= 0 || totalInputAmount < totalAmount) { - throw BitcoinTransactionWrongBalanceException(currency); + // throw BitcoinTransactionWrongBalanceException(currency); } txb.setVersion(1); + List inputPrivKeys = []; + List outpoints = []; inputs.forEach((input) { + inputPrivKeys.add(bitcoin.PrivateKeyInfo( + bitcoin.PrivateKey.fromHex( + bitcoin.getSecp256k1(), + HEX.encode(generateKeyPair( + hd: input.bitcoinAddressRecord.isHidden + ? walletAddresses.sideHd + : walletAddresses.mainHd, + index: input.bitcoinAddressRecord.index, + network: networkType) + .privateKey!)), + false)); + outpoints.add(bitcoin.Outpoint(txid: input.hash, index: input.vout)); + if (input.isP2wpkh) { final p2wpkh = bitcoin .P2WPKH( - data: generatePaymentData( - hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, - index: input.bitcoinAddressRecord.index), - network: networkType) + data: generatePaymentData( + hd: input.bitcoinAddressRecord.isHidden + ? walletAddresses.sideHd + : walletAddresses.mainHd, + index: input.bitcoinAddressRecord.index), + network: networkType) .data; txb.addInput(input.hash, input.vout, null, p2wpkh.output); @@ -315,21 +327,48 @@ abstract class ElectrumWalletBase } }); + List silentAddresses = []; outputs.forEach((item) { final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount; final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; - txb.addOutput(addressToOutputScript(outputAddress, networkType), outputAmount!); + if (outputAddress.startsWith('tsp1')) { + silentAddresses + .add(bitcoin.SilentPaymentDestination.fromAddress(outputAddress, outputAmount!)); + } else { + txb.addOutput(addressToOutputScript(outputAddress, networkType), outputAmount!); + } }); - final estimatedSize = estimatedTransactionSize(inputs.length, outputs.length + 1); - var feeAmount = 0; + if (silentAddresses.isNotEmpty) { + final outpointsHash = bitcoin.SilentPayment.hashOutpoints(outpoints); - if (transactionCredentials.feeRate != null) { - feeAmount = transactionCredentials.feeRate! * estimatedSize; - } else { - feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize; + final aSum = bitcoin.SilentPayment.getSumInputPrivKeys(inputPrivKeys); + + final generatedOutputs = bitcoin.SilentPayment.generateMultipleRecipientPubkeys( + aSum, outpointsHash, silentAddresses); + + generatedOutputs.forEach((recipientSilentAddress, generatedOutput) { + generatedOutput.forEach((output) { + final generatedPubkey = output.$1.toCompressedHex(); + txb.addOutput( + bitcoin.ECPublic.fromHex(generatedPubkey) + .toTaprootAddress() + .toScriptPubKey() + .toBytes(), + amount); + }); + }); } + final estimatedSize = estimatedTransactionSize(inputs.length, outputs.length + 1); + var feeAmount = 222; + + // if (transactionCredentials.feeRate != null) { + // feeAmount = transactionCredentials.feeRate! * estimatedSize; + // } else { + // feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize; + // } + final changeValue = totalInputAmount - amount - feeAmount; if (changeValue > minAmount) { @@ -356,12 +395,13 @@ abstract class ElectrumWalletBase } String toJSON() => json.encode({ - 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), - 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), - 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), - 'balance': balance[currency]?.toJSON() - }); + 'mnemonic': mnemonic, + 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), + 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), + 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), + 'balance': balance[currency]?.toJSON(), + 'network_type': networkType.toString() + }); int feeRate(TransactionPriority priority) { try { @@ -376,7 +416,7 @@ abstract class ElectrumWalletBase } int feeAmountForPriority( - BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => + BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount); int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => @@ -476,17 +516,78 @@ abstract class ElectrumWalletBase Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future updateUnspent() async { - final unspent = await Future.wait(walletAddresses - .addresses.map((address) => electrumClient + final unspent = await Future.wait(walletAddresses.addresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, networkType) - .then((unspent) => unspent - .map((unspent) { - try { - return BitcoinUnspent.fromJSON(address, unspent); - } catch(_) { - return null; - } - }).whereNotNull()))); + .then((unspent) => unspent.map((unspent) { + try { + return BitcoinUnspent.fromJSON(address, unspent); + } catch (_) { + return null; + } + }).whereNotNull()))); + final txid = "28a21e8b6373bf20928107f8f1f1ea5a98ada793f2676372d03466e874d4e762"; + final uri = Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx/$txid'); + // final uri = Uri(scheme: 'https', host: 'blockstream.info', path: 'testnet/api/block-height/0'); + + await http.get(uri).then((response) { + // print(response.body); + final obj = json.decode(response.body); + final scanPrivateKey = walletAddresses.silentAddress!.scanPrivkey; + final spendPublicKey = walletAddresses.silentAddress!.spendPubkey; + + List pubkeys = []; + List outpoints = []; + obj["vin"].forEach((input) { + final witness = input["witness"] as List; + final pubkey = witness[1] as String; + pubkeys.add(pubkey); + outpoints.add(bitcoin.Outpoint(txid: input["txid"] as String, index: input["vout"] as int)); + }); + + Uint8List sumOfInputPublicKeys = + bitcoin.getSumInputPubKeys(pubkeys).toCompressedHex().fromHex; + final outpointHash = bitcoin.SilentPayment.hashOutpoints(outpoints); + + Map outpointsByP2TRpubkey = {}; + int i = 0; + obj['vout'].forEach((out) { + if (out["scriptpubkey_type"] == "v1_p2tr") + outpointsByP2TRpubkey[out['scriptpubkey_address'] as String] = + bitcoin.Outpoint(txid: txid, index: i, value: out["value"] as int); + + i++; + }); + final result = bitcoin.scanOutputs( + scanPrivateKey.toCompressedHex().fromHex, + spendPublicKey.toCompressedHex().fromHex, + sumOfInputPublicKeys, + outpointHash, + outpointsByP2TRpubkey.keys.toList()); + + // print(result); + + result.forEach((key, value) { + final outpoint = outpointsByP2TRpubkey[key]; + // if (outpoint != null) { + // unspentCoins.add(BitcoinUnspent( + // BitcoinAddressRecord(walletAddresses.silentAddress.toString(), index: 0), + // outpoint.txid, + // outpoint.value!, + // outpoint.n)); + + // final currentBalance = balance[currency]; + // if (currentBalance != null) { + // balance[currency] = ElectrumBalance( + // confirmed: currentBalance.confirmed + outpoint.value!, + // unconfirmed: currentBalance.unconfirmed, + // frozen: currentBalance.frozen); + // } else { + // balance[currency] = + // ElectrumBalance(confirmed: outpoint.value!, unconfirmed: 0, frozen: 0); + // } + // } + }); + }); unspentCoins = unspent.expand((e) => e).toList(); if (unspentCoinsInfo.isEmpty) { @@ -533,7 +634,7 @@ abstract class ElectrumWalletBase try { final List keys = []; final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); + unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); if (currentWalletUnspentCoins.isNotEmpty) { currentWalletUnspentCoins.forEach((element) { @@ -555,12 +656,23 @@ abstract class ElectrumWalletBase Future getTransactionExpanded( {required String hash, required int height}) async { - final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); - final transactionHex = verboseTransaction['hex'] as String; + final verboseTransaction = + await electrumClient.getTransactionRaw(hash: hash, networkType: networkType); + + String transactionHex; + int? time; + int confirmations = 0; + if (networkType == bitcoin.testnet) { + transactionHex = verboseTransaction as String; + confirmations = 1; + } else { + transactionHex = verboseTransaction['hex'] as String; + time = verboseTransaction['time'] as int?; + confirmations = verboseTransaction['confirmations'] as int? ?? 0; + } + final original = bitcoin.Transaction.fromHex(transactionHex); final ins = []; - final time = verboseTransaction['time'] as int?; - final confirmations = verboseTransaction['confirmations'] as int? ?? 0; for (final vin in original.ins) { final id = HEX.encode(vin.hash!.reversed.toList()); @@ -666,7 +778,7 @@ abstract class ElectrumWalletBase final addresses = walletAddresses.addresses.toList(); final balanceFutures = >>[]; for (var i = 0; i < addresses.length; i++) { - final addressRecord = addresses[i] ; + final addressRecord = addresses[i]; final sh = scriptHash(addressRecord.address, networkType: networkType); final balanceFuture = electrumClient.getBalance(sh); balanceFutures.add(balanceFuture); @@ -734,4 +846,32 @@ abstract class ElectrumWalletBase ? base64Encode(hd.sign(message)) : base64Encode(hd.derive(index).sign(message)); } + + // int _getHeightByDate(DateTime date) { + // final nodeHeight = monero_wallet.getNodeHeightSync(); + // final heightDistance = _getHeightDistance(date); + + // if (nodeHeight <= 0) { + // return 0; + // } + + // return nodeHeight - heightDistance; + // } + + // Silent payments initial sync height + // inspiried my monero_wallet.dart's _setInitialHeight() + void _setInitialHeight() async { + if (walletInfo.isRecovery) { + return; + } + + final currentHeight = await electrumClient.getCurrentBlockChainTip(); + if (currentHeight == null) return; + + // if (currentHeight <= 1) { + // final height = _getHeightByDate(walletInfo.date); + // monero_wallet.setRecoveringFromSeed(isRecovery: true); + // monero_wallet.setRefreshFromBlockHeight(height: height); + // } + } } diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index ab99a875c..624735d58 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -10,8 +10,7 @@ import 'package:mobx/mobx.dart'; part 'electrum_wallet_addresses.g.dart'; -class ElectrumWalletAddresses = ElectrumWalletAddressesBase - with _$ElectrumWalletAddresses; +class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses; abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { ElectrumWalletAddressesBase(WalletInfo walletInfo, @@ -21,20 +20,22 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { required this.networkType, List? initialAddresses, int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : addresses = ObservableList.of( - (initialAddresses ?? []).toSet()), - receiveAddresses = ObservableList.of( - (initialAddresses ?? []) + int initialChangeAddressIndex = 0, + bitcoin.SilentPaymentReceiver? silentAddress}) + : addresses = ObservableList.of((initialAddresses ?? []).toSet()), + silentAddress = silentAddress, + receiveAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed) - .toSet()), - changeAddresses = ObservableList.of( - (initialAddresses ?? []) + .toSet()), + changeAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed) - .toSet()), + .toSet()), + silentAddresses = ObservableList.of((initialAddresses ?? []) + .where((addressRecord) => addressRecord.silentAddressLabel != null) + .toSet()), currentReceiveAddressIndex = initialRegularAddressIndex, currentChangeAddressIndex = initialChangeAddressIndex, - super(walletInfo); + super(walletInfo); static const defaultReceiveAddressesCount = 22; static const defaultChangeAddressesCount = 17; @@ -45,14 +46,20 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final ObservableList addresses; final ObservableList receiveAddresses; final ObservableList changeAddresses; + final ObservableList silentAddresses; final ElectrumClient electrumClient; final bitcoin.NetworkType networkType; final bitcoin.HDWallet mainHd; final bitcoin.HDWallet sideHd; - @override + // TODO: labels -> disable edit on receive page + final bitcoin.SilentPaymentReceiver? silentAddress; + + @observable + String? activeAddress; + @computed - String get address { + String get receiveAddress { if (receiveAddresses.isEmpty) { final address = generateNewAddress().address; return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address; @@ -63,28 +70,40 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } @override - set address(String addr) => null; + @computed + String get address { + if (activeAddress != null) { + return activeAddress!; + } + + if (receiveAddresses.isEmpty) { + return generateNewAddress().address; + } + + return receiveAddresses.first.address; + } + + @override + set address(String addr) => activeAddress = addr; int currentReceiveAddressIndex; int currentChangeAddressIndex; @computed - int get totalCountOfReceiveAddresses => - addresses.fold(0, (acc, addressRecord) { - if (!addressRecord.isHidden) { - return acc + 1; - } - return acc; - }); + int get totalCountOfReceiveAddresses => addresses.fold(0, (acc, addressRecord) { + if (!addressRecord.isHidden) { + return acc + 1; + } + return acc; + }); @computed - int get totalCountOfChangeAddresses => - addresses.fold(0, (acc, addressRecord) { - if (addressRecord.isHidden) { - return acc + 1; - } - return acc; - }); + int get totalCountOfChangeAddresses => addresses.fold(0, (acc, addressRecord) { + if (addressRecord.isHidden) { + return acc + 1; + } + return acc; + }); Future discoverAddresses() async { await _discoverAddresses(mainHd, false); @@ -114,11 +133,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (changeAddresses.isEmpty) { final newAddresses = await _createNewAddresses(gap, - hd: sideHd, - startIndex: totalCountOfChangeAddresses > 0 - ? totalCountOfChangeAddresses - 1 - : 0, - isHidden: true); + hd: sideHd, + startIndex: totalCountOfChangeAddresses > 0 ? totalCountOfChangeAddresses - 1 : 0, + isHidden: true); _addAddresses(newAddresses); } @@ -133,8 +150,24 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } BitcoinAddressRecord generateNewAddress( - {bitcoin.HDWallet? hd, bool isHidden = false}) { - currentReceiveAddressIndex += 1; + {bitcoin.HDWallet? hd, bool isHidden = false, String? label}) { + if (label != null && silentAddress != null) { + final address = BitcoinAddressRecord( + bitcoin.SilentPaymentAddress.createLabeledSilentPaymentAddress( + silentAddress!.scanPubkey, + silentAddress!.spendPubkey, + '0000000000000000000000000000000000000000000000000000000000000002'.fromHex, + hrp: silentAddress!.hrp, + version: silentAddress!.version) + .toString(), + index: currentReceiveAddressIndex, + isHidden: isHidden, + silentAddressLabel: label); + silentAddresses.add(address); + + return address; + } + // FIX-ME: Check logic for whichi HD should be used here ??? final address = BitcoinAddressRecord( getAddress(index: currentReceiveAddressIndex, hd: hd ?? sideHd), @@ -142,6 +175,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { isHidden: isHidden); addresses.add(address); return address; + + currentReceiveAddressIndex += 1; } String getAddress({required int index, required bitcoin.HDWallet hd}) => ''; @@ -160,16 +195,16 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action void updateReceiveAddresses() { receiveAddresses.removeRange(0, receiveAddresses.length); - final newAdresses = addresses - .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); + final newAdresses = + addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); receiveAddresses.addAll(newAdresses); } @action void updateChangeAddresses() { changeAddresses.removeRange(0, changeAddresses.length); - final newAdresses = addresses - .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed); + final newAdresses = + addresses.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed); changeAddresses.addAll(newAdresses); } @@ -178,20 +213,16 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { List addrs; if (addresses.isNotEmpty) { - addrs = addresses - .where((addr) => addr.isHidden == isHidden) - .toList(); + addrs = addresses.where((addr) => addr.isHidden == isHidden).toList(); } else { addrs = await _createNewAddresses( - isHidden - ? defaultChangeAddressesCount - : defaultReceiveAddressesCount, + isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, startIndex: 0, hd: hd, isHidden: isHidden); } - while(hasAddrUse) { + while (hasAddrUse) { final addr = addrs.last.address; hasAddrUse = await _hasAddressUsed(addr); @@ -201,11 +232,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final start = addrs.length; final count = start + gap; - final batch = await _createNewAddresses( - count, - startIndex: start, - hd: hd, - isHidden: isHidden); + final batch = await _createNewAddresses(count, startIndex: start, hd: hd, isHidden: isHidden); addrs.addAll(batch); } @@ -229,21 +256,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (countOfReceiveAddresses < defaultReceiveAddressesCount) { final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses; - final newAddresses = await _createNewAddresses( - addressesCount, - startIndex: countOfReceiveAddresses, - hd: mainHd, - isHidden: false); + final newAddresses = await _createNewAddresses(addressesCount, + startIndex: countOfReceiveAddresses, hd: mainHd, isHidden: false); addresses.addAll(newAddresses); } if (countOfHiddenAddresses < defaultChangeAddressesCount) { final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses; - final newAddresses = await _createNewAddresses( - addressesCount, - startIndex: countOfHiddenAddresses, - hd: sideHd, - isHidden: true); + final newAddresses = await _createNewAddresses(addressesCount, + startIndex: countOfHiddenAddresses, hd: sideHd, isHidden: true); addresses.addAll(newAddresses); } } @@ -253,10 +274,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final list = []; for (var i = startIndex; i < count + startIndex; i++) { - final address = BitcoinAddressRecord( - getAddress(index: i, hd: hd), - index: i, - isHidden: isHidden); + final address = + BitcoinAddressRecord(getAddress(index: i, hd: hd), index: i, isHidden: isHidden); list.add(address); } @@ -275,4 +294,4 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final transactionHistory = await electrumClient.getHistory(sh); return transactionHistory.isNotEmpty; } -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index bc14b4c21..0ddb70b20 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -4,6 +4,7 @@ import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_core/encryption_file_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; class ElectrumWallletSnapshot { ElectrumWallletSnapshot({ @@ -13,6 +14,7 @@ class ElectrumWallletSnapshot { required this.mnemonic, required this.addresses, required this.balance, + required this.networkType, required this.regularAddressIndex, required this.changeAddressIndex}); @@ -23,6 +25,7 @@ class ElectrumWallletSnapshot { String mnemonic; List addresses; ElectrumBalance balance; + bitcoin.NetworkType networkType; int regularAddressIndex; int changeAddressIndex; @@ -38,6 +41,7 @@ class ElectrumWallletSnapshot { .toList(); final balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); + final networkType = bitcoin.testnet; var regularAddressIndex = 0; var changeAddressIndex = 0; @@ -53,6 +57,7 @@ class ElectrumWallletSnapshot { mnemonic: mnemonic, addresses: addresses, balance: balance, + networkType: networkType, regularAddressIndex: regularAddressIndex, changeAddressIndex: changeAddressIndex); } diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 5a8e9cf4f..19b8787e5 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -27,7 +27,7 @@ class LitecoinWalletService extends WalletService< WalletType getType() => WalletType.litecoin; @override - Future create(BitcoinNewWalletCredentials credentials) async { + Future create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async { final wallet = await LitecoinWalletBase.create( mnemonic: await generateMnemonic(), password: credentials.password!, diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 33ebcaab4..ffe97b979 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -21,18 +21,18 @@ packages: dependency: transitive description: name: args - sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" asn1lib: dependency: transitive description: name: asn1lib - sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 + sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.0" async: dependency: transitive description: @@ -78,11 +78,9 @@ packages: bitcoin_flutter: dependency: "direct main" description: - path: "." - ref: cake-update-v3 - resolved-ref: df9204144011ed9419eff7d9ef3143102a40252d - url: "https://github.com/cake-tech/bitcoin_flutter.git" - source: git + path: "/home/rafael/Storage/Repositories/bitcoin_flutter" + relative: false + source: path version: "2.0.2" boolean_selector: dependency: transitive @@ -104,10 +102,10 @@ packages: dependency: transitive description: name: build - sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" build_config: dependency: transitive description: @@ -120,10 +118,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "4.0.0" build_resolvers: dependency: "direct dev" description: @@ -136,18 +134,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.6" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" url: "https://pub.dev" source: hosted - version: "7.2.7" + version: "7.2.10" built_collection: dependency: transitive description: @@ -160,10 +158,10 @@ packages: dependency: transitive description: name: built_value - sha256: "31b7c748fd4b9adf8d25d72a4c4a59ef119f12876cf414f94f8af5131d5fa2b0" + sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74 url: "https://pub.dev" source: hosted - version: "8.4.4" + version: "8.6.3" cake_backup: dependency: transitive description: @@ -185,10 +183,10 @@ packages: dependency: transitive description: name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" clock: dependency: transitive description: @@ -201,10 +199,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677" url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.7.0" collection: dependency: transitive description: @@ -225,10 +223,10 @@ packages: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" cryptography: dependency: "direct main" description: @@ -241,10 +239,10 @@ packages: dependency: transitive description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" cw_core: dependency: "direct main" description: @@ -252,6 +250,14 @@ packages: relative: true source: path version: "0.0.1" + dart_bech32: + dependency: transitive + description: + name: dart_bech32 + sha256: "0e1dc1ff39c9669c9ffeafd5d675104918f7b50799692491badfea7e1fb40888" + url: "https://pub.dev" + source: hosted + version: "2.0.0" dart_style: dependency: transitive description: @@ -260,14 +266,23 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.4" + elliptic: + dependency: transitive + description: + path: "." + ref: silent-payments + resolved-ref: ad7b1cccb54b5feba8ead4a0f67cb98a5a01a88b + url: "https://github.com/cake-tech/dart-elliptic" + source: git + version: "0.3.10" encrypt: dependency: "direct main" description: name: encrypt - sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "5.0.3" fake_async: dependency: transitive description: @@ -280,10 +295,10 @@ packages: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" file: dependency: transitive description: @@ -296,10 +311,10 @@ packages: dependency: transitive description: name: fixnum - sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -309,10 +324,10 @@ packages: dependency: "direct main" description: name: flutter_mobx - sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" + sha256: "2ba0aa5a42811eaaeff2e35626689cf2b8a3869907d0e8889c914f2c95d8fd76" url: "https://pub.dev" source: hosted - version: "2.0.6+5" + version: "2.1.1" flutter_test: dependency: "direct dev" description: flutter @@ -330,18 +345,18 @@ packages: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" graphs: dependency: transitive description: name: graphs - sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" hex: dependency: transitive description: @@ -418,18 +433,18 @@ packages: dependency: transitive description: name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.8.1" logging: dependency: transitive description: name: logging - sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" matcher: dependency: transitive description: @@ -466,18 +481,26 @@ packages: dependency: "direct main" description: name: mobx - sha256: "6738620307a424d2c9ad8b873f4dce391c44e9135eb4e75668ac8202fec7a9b8" + sha256: "42ae7277ec5c36fa5ce02aa14551065babce3c38a35947330144ff47bc775c75" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.1" mobx_codegen: dependency: "direct dev" description: name: mobx_codegen - sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" + sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" package_config: dependency: transitive description: @@ -498,74 +521,74 @@ packages: dependency: "direct main" description: name: path_provider - sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9" + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7" + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.24" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "026b97a6c29da75181a37aae2eba9227f5fe13cb2838c6b975ce209328b8ab4e" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.10" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.1" platform: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.3" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.6" pointycastle: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.3" pool: dependency: transitive description: @@ -574,30 +597,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: + provider: dependency: transitive description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + name: provider + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "6.0.5" pub_semver: dependency: transitive description: name: pub_semver - sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: ec85d7d55339d85f44ec2b682a82fea340071e8978257e5a43e69f79e98ef50c + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.2.3" rxdart: dependency: "direct main" description: @@ -610,18 +633,18 @@ packages: dependency: transitive description: name: shelf - sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -711,18 +734,18 @@ packages: dependency: transitive description: name: tuple - sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" typed_data: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" unorm_dart: dependency: "direct main" description: @@ -743,42 +766,42 @@ packages: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.0" win32: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "5.0.9" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.3" yaml: dependency: transitive description: name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 693d5af7a..79deae203 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -20,9 +20,7 @@ dependencies: cw_core: path: ../cw_core bitcoin_flutter: - git: - url: https://github.com/cake-tech/bitcoin_flutter.git - ref: cake-update-v3 + path: /home/rafael/Storage/Repositories/bitcoin_flutter bitbox: git: url: https://github.com/cake-tech/bitbox-flutter.git diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart index d50d6c8e5..82c1189dc 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -29,8 +29,7 @@ class BitcoinCashWalletService extends WalletService create( - credentials) async { + Future create(credentials, {bool? isTestnet}) async { final wallet = await BitcoinCashWalletBase.create( mnemonic: await Mnemonic.generate(), password: credentials.password!, diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux index 0ed52b295..5dc8fb651 120000 --- a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -1 +1 @@ -/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file +/home/rafael/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file diff --git a/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index 2f46994d3..e70301f31 100644 --- a/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -1,6 +1,6 @@ // This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=C:\Users\borod\flutter -FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash +FLUTTER_ROOT=/home/rafael/Storage/Repositories/Build Sources/flutter +FLUTTER_APPLICATION_PATH=/opt/android/cake_wallet/cw_bitcoin_cash COCOAPODS_PARALLEL_CODE_SIGN=true FLUTTER_BUILD_DIR=build FLUTTER_BUILD_NAME=0.0.1 diff --git a/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh b/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh old mode 100644 new mode 100755 index 2a3bcca5a..3d2e93b7d --- a/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -1,7 +1,7 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=C:\Users\borod\flutter" -export "FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash" +export "FLUTTER_ROOT=/home/rafael/Storage/Repositories/Build Sources/flutter" +export "FLUTTER_APPLICATION_PATH=/opt/android/cake_wallet/cw_bitcoin_cash" export "COCOAPODS_PARALLEL_CODE_SIGN=true" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=0.0.1" diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 30ed49e80..306058d5a 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -22,9 +22,7 @@ dependencies: cw_bitcoin: path: ../cw_bitcoin bitcoin_flutter: - git: - url: https://github.com/cake-tech/bitcoin_flutter.git - ref: cake-update-v3 + path: /home/rafael/Storage/Repositories/bitcoin_flutter bitbox: git: url: https://github.com/cake-tech/bitbox-flutter.git diff --git a/cw_core/lib/unspent_transaction_output.dart b/cw_core/lib/unspent_transaction_output.dart index 6827f4c01..8d118da83 100644 --- a/cw_core/lib/unspent_transaction_output.dart +++ b/cw_core/lib/unspent_transaction_output.dart @@ -14,5 +14,9 @@ class Unspent { bool isFrozen; String note; - bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc'); + bool get isP2wpkh => + address.startsWith('bc') || + // testnet + address.startsWith('tb') || + address.startsWith('ltc'); } diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index f6d0ca192..b1c182e31 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -8,7 +8,7 @@ abstract class WalletService { WalletType getType(); - Future create(N credentials); + Future create(N credentials, {bool? isTestnet}); Future restoreFromSeed(RFS credentials); diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index cdff5812f..2df467e0e 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -21,7 +21,7 @@ class EthereumWalletService extends WalletService create(EthereumNewWalletCredentials credentials) async { + Future create(EthereumNewWalletCredentials credentials, {bool? isTestnet}) async { final mnemonic = bip39.generateMnemonic(); final wallet = EthereumWallet( walletInfo: credentials.walletInfo!, diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index 0bc20d2a0..eded06778 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -68,7 +68,7 @@ class HavenWalletService extends WalletService< WalletType getType() => WalletType.haven; @override - Future create(HavenNewWalletCredentials credentials) async { + Future create(HavenNewWalletCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.createWallet( diff --git a/cw_haven/pubspec.lock b/cw_haven/pubspec.lock index 40f2bbe3b..aa680bff6 100644 --- a/cw_haven/pubspec.lock +++ b/cw_haven/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.0" build_resolvers: dependency: "direct dev" description: @@ -85,10 +85,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.6" build_runner_core: dependency: transitive description: @@ -407,18 +407,18 @@ packages: dependency: "direct main" description: name: mobx - sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a + sha256: "42ae7277ec5c36fa5ce02aa14551065babce3c38a35947330144ff47bc775c75" url: "https://pub.dev" source: hosted - version: "2.1.3+1" + version: "2.2.1" mobx_codegen: dependency: "direct dev" description: name: mobx_codegen - sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" + sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.0" package_config: dependency: transitive description: diff --git a/cw_monero/.metadata b/cw_monero/.metadata index 679a0404c..19e95121d 100644 --- a/cw_monero/.metadata +++ b/cw_monero/.metadata @@ -4,8 +4,8 @@ # This file should be version controlled. version: - revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - channel: stable + revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + channel: unknown project_type: plugin @@ -13,14 +13,20 @@ project_type: plugin migration: platforms: - platform: root - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - - platform: macos - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: android + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: ios + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 - platform: linux - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: macos + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 # User provided section diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index 3b4d65636..c6b14eb92 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -425,4 +425,4 @@ packages: version: "0.2.0+3" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.0.6" diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 1263e4920..42b57b15a 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -40,11 +40,12 @@ const moneroBlockSize = 1000; class MoneroWallet = MoneroWalletBase with _$MoneroWallet; -abstract class MoneroWalletBase extends WalletBase with Store { - MoneroWalletBase({required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required String password}) +abstract class MoneroWalletBase + extends WalletBase with Store { + MoneroWalletBase( + {required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required String password}) : balance = ObservableMap.of({ CryptoCurrency.xmr: MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: 0), @@ -160,8 +161,8 @@ abstract class MoneroWalletBase extends WalletBase WalletType.monero; @override - Future create(MoneroNewWalletCredentials credentials) async { + Future create(MoneroNewWalletCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.createWallet( diff --git a/cw_monero/linux/cw_monero_plugin_private.h b/cw_monero/linux/cw_monero_plugin_private.h new file mode 100644 index 000000000..2b33bbf1f --- /dev/null +++ b/cw_monero/linux/cw_monero_plugin_private.h @@ -0,0 +1,10 @@ +#include + +#include "include/cw_monero/cw_monero_plugin.h" + +// This file exposes some plugin internals for unit testing. See +// https://github.com/flutter/flutter/issues/88724 for current limitations +// in the unit-testable API. + +// Handles the getPlatformVersion method call. +FlMethodResponse *get_platform_version(); diff --git a/cw_monero/linux/test/cw_monero_plugin_test.cc b/cw_monero/linux/test/cw_monero_plugin_test.cc new file mode 100644 index 000000000..8c87dccce --- /dev/null +++ b/cw_monero/linux/test/cw_monero_plugin_test.cc @@ -0,0 +1,31 @@ +#include +#include +#include + +#include "include/cw_monero/cw_monero_plugin.h" +#include "cw_monero_plugin_private.h" + +// This demonstrates a simple unit test of the C portion of this plugin's +// implementation. +// +// Once you have built the plugin's example app, you can run these tests +// from the command line. For instance, for a plugin called my_plugin +// built for x64 debug, run: +// $ build/linux/x64/debug/plugins/my_plugin/my_plugin_test + +namespace cw_monero { +namespace test { + +TEST(CwMoneroPlugin, GetPlatformVersion) { + g_autoptr(FlMethodResponse) response = get_platform_version(); + ASSERT_NE(response, nullptr); + ASSERT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response)); + FlValue* result = fl_method_success_response_get_result( + FL_METHOD_SUCCESS_RESPONSE(response)); + ASSERT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING); + // The full string varies, so just validate that it has the right format. + EXPECT_THAT(fl_value_get_string(result), testing::StartsWith("Linux ")); +} + +} // namespace test +} // namespace cw_monero diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index ac20e1606..bd29467ce 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -21,18 +21,18 @@ packages: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.2" asn1lib: dependency: transitive description: name: asn1lib - sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 + sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.0" async: dependency: transitive description: @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: build - sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" build_config: dependency: transitive description: @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.0" build_resolvers: dependency: "direct dev" description: @@ -85,18 +85,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.6" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" url: "https://pub.dev" source: hosted - version: "7.2.7" + version: "7.2.10" built_collection: dependency: transitive description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74 url: "https://pub.dev" source: hosted - version: "8.4.3" + version: "8.6.3" cake_backup: dependency: transitive description: @@ -134,10 +134,10 @@ packages: dependency: transitive description: name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" clock: dependency: transitive description: @@ -150,10 +150,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677" url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.7.0" collection: dependency: transitive description: @@ -174,10 +174,10 @@ packages: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" cryptography: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: "direct main" description: name: encrypt - sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "5.0.3" fake_async: dependency: transitive description: @@ -229,10 +229,10 @@ packages: dependency: "direct main" description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" file: dependency: transitive description: @@ -258,10 +258,10 @@ packages: dependency: "direct main" description: name: flutter_mobx - sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" + sha256: "2ba0aa5a42811eaaeff2e35626689cf2b8a3869907d0e8889c914f2c95d8fd76" url: "https://pub.dev" source: hosted - version: "2.0.6+5" + version: "2.1.1" flutter_test: dependency: "direct dev" description: flutter @@ -279,18 +279,18 @@ packages: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" graphs: dependency: transitive description: name: graphs - sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" hive: dependency: transitive description: @@ -359,18 +359,18 @@ packages: dependency: transitive description: name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.8.1" logging: dependency: transitive description: name: logging - sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" matcher: dependency: transitive description: @@ -407,18 +407,26 @@ packages: dependency: "direct main" description: name: mobx - sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a + sha256: "42ae7277ec5c36fa5ce02aa14551065babce3c38a35947330144ff47bc775c75" url: "https://pub.dev" source: hosted - version: "2.1.3+1" + version: "2.2.1" mobx_codegen: dependency: "direct dev" description: name: mobx_codegen - sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" + sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" package_config: dependency: transitive description: @@ -439,74 +447,74 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.1" platform: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.3" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.6" pointycastle: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.3" pool: dependency: transitive description: @@ -515,46 +523,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: + provider: dependency: transitive description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + name: provider + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "6.0.5" pub_semver: dependency: transitive description: name: pub_semver - sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.3" shelf: dependency: transitive description: name: shelf - sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -652,10 +660,10 @@ packages: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" vector_math: dependency: transitive description: @@ -668,42 +676,42 @@ packages: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.0" win32: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "5.0.9" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.3" yaml: dependency: transitive description: name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index cdc6245b0..ccfc772a1 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -7,7 +7,7 @@ homepage: https://cakewallet.com environment: sdk: ">=2.17.5 <3.0.0" - flutter: ">=1.20.0" + flutter: ">=3.0.6" dependencies: flutter: diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index 6c7ee549b..a8bff6dd8 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -28,7 +28,7 @@ class NanoWalletService extends WalletService WalletType.nano; @override - Future create(NanoNewWalletCredentials credentials) async { + Future create(NanoNewWalletCredentials credentials, {bool? isTestnet}) async { // nano standard: DerivationType derivationType = DerivationType.nano; String seedKey = NanoSeeds.generateSeed(); diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 zcmeHN2~<R zh`|8`A_PQ1nSu(UMFx?8j8PC!!VDphaL#`F42fd#7Vlc`zIE4n%Y~eiz4y1j|NDpi z?<@|pSJ-HM`qifhf@m%MamgwK83`XpBA<+azdF#2QsT{X@z0A9Bq>~TVErigKH1~P zRX-!h-f0NJ4Mh++{D}J+K>~~rq}d%o%+4dogzXp7RxX4C>Km5XEI|PAFDmo;DFm6G zzjVoB`@qW98Yl0Kvc-9w09^PrsobmG*Eju^=3f?0o-t$U)TL1B3;sZ^!++3&bGZ!o-*6w?;oOhf z=A+Qb$scV5!RbG+&2S}BQ6YH!FKb0``VVX~T$dzzeSZ$&9=X$3)_7Z{SspSYJ!lGE z7yig_41zpQ)%5dr4ff0rh$@ky3-JLRk&DK)NEIHecf9c*?Z1bUB4%pZjQ7hD!A0r-@NF(^WKdr(LXj|=UE7?gBYGgGQV zidf2`ZT@pzXf7}!NH4q(0IMcxsUGDih(0{kRSez&z?CFA0RVXsVFw3^u=^KMtt95q z43q$b*6#uQDLoiCAF_{RFc{!H^moH_cmll#Fc^KXi{9GDl{>%+3qyfOE5;Zq|6#Hb zp^#1G+z^AXfRKaa9HK;%b3Ux~U@q?xg<2DXP%6k!3E)PA<#4$ui8eDy5|9hA5&{?v z(-;*1%(1~-NTQ`Is1_MGdQ{+i*ccd96ab$R$T3=% zw_KuNF@vI!A>>Y_2pl9L{9h1-C6H8<)J4gKI6{WzGBi<@u3P6hNsXG=bRq5c+z;Gc3VUCe;LIIFDmQAGy+=mRyF++u=drBWV8-^>0yE9N&*05XHZpPlE zxu@?8(ZNy7rm?|<+UNe0Vs6&o?l`Pt>P&WaL~M&#Eh%`rg@Mbb)J&@DA-wheQ>hRV z<(XhigZAT z>=M;URcdCaiO3d^?H<^EiEMDV+7HsTiOhoaMX%P65E<(5xMPJKxf!0u>U~uVqnPN7T!X!o@_gs3Ct1 zlZ_$5QXP4{Aj645wG_SNT&6m|O6~Tsl$q?nK*)(`{J4b=(yb^nOATtF1_aS978$x3 zx>Q@s4i3~IT*+l{@dx~Hst21fR*+5}S1@cf>&8*uLw-0^zK(+OpW?cS-YG1QBZ5q! zgTAgivzoF#`cSz&HL>Ti!!v#?36I1*l^mkrx7Y|K6L#n!-~5=d3;K<;Zqi|gpNUn_ z_^GaQDEQ*jfzh;`j&KXb66fWEk1K7vxQIMQ_#Wu_%3 z4Oeb7FJ`8I>Px;^S?)}2+4D_83gHEq>8qSQY0PVP?o)zAv3K~;R$fnwTmI-=ZLK`= zTm+0h*e+Yfr(IlH3i7gUclNH^!MU>id$Jw>O?2i0Cila#v|twub21@e{S2v}8Z13( zNDrTXZVgris|qYm<0NU(tAPouG!QF4ZNpZPkX~{tVf8xY690JqY1NVdiTtW+NqyRP zZ&;T0ikb8V{wxmFhlLTQ&?OP7 z;(z*<+?J2~z*6asSe7h`$8~Se(@t(#%?BGLVs$p``;CyvcT?7Y!{tIPva$LxCQ&4W z6v#F*);|RXvI%qnoOY&i4S*EL&h%hP3O zLsrFZhv&Hu5tF$Lx!8(hs&?!Kx5&L(fdu}UI5d*wn~A`nPUhG&Rv z2#ixiJdhSF-K2tpVL=)5UkXRuPAFrEW}7mW=uAmtVQ&pGE-&az6@#-(Te^n*lrH^m@X-ftVcwO_#7{WI)5v(?>uC9GG{lcGXYJ~Q8q zbMFl7;t+kV;|;KkBW2!P_o%Czhw&Q(nXlxK9ak&6r5t_KH8#1Mr-*0}2h8R9XNkr zto5-b7P_auqTJb(TJlmJ9xreA=6d=d)CVbYP-r4$hDn5|TIhB>SReMfh&OVLkMk-T zYf%$taLF0OqYF?V{+6Xkn>iX@TuqQ?&cN6UjC9YF&%q{Ut3zv{U2)~$>-3;Dp)*(? zg*$mu8^i=-e#acaj*T$pNowo{xiGEk$%DusaQiS!KjJH96XZ-hXv+jk%ard#fu=@Q z$AM)YWvE^{%tDfK%nD49=PI|wYu}lYVbB#a7wtN^Nml@CE@{Gv7+jo{_V?I*jkdLD zJE|jfdrmVbkfS>rN*+`#l%ZUi5_bMS<>=MBDNlpiSb_tAF|Zy`K7kcp@|d?yaTmB^ zo?(vg;B$vxS|SszusORgDg-*Uitzdi{dUV+glA~R8V(?`3GZIl^egW{a919!j#>f` znL1o_^-b`}xnU0+~KIFLQ)$Q6#ym%)(GYC`^XM*{g zv3AM5$+TtDRs%`2TyR^$(hqE7Y1b&`Jd6dS6B#hDVbJlUXcG3y*439D8MrK!2D~6gn>UD4Imctb z+IvAt0iaW73Iq$K?4}H`7wq6YkTMm`tcktXgK0lKPmh=>h+l}Y+pDtvHnG>uqBA)l zAH6BV4F}v$(o$8Gfo*PB>IuaY1*^*`OTx4|hM8jZ?B6HY;F6p4{`OcZZ(us-RVwDx zUzJrCQlp@mz1ZFiSZ*$yX3c_#h9J;yBE$2g%xjmGF4ca z&yL`nGVs!Zxsh^j6i%$a*I3ZD2SoNT`{D%mU=LKaEwbN(_J5%i-6Va?@*>=3(dQy` zOv%$_9lcy9+(t>qohkuU4r_P=R^6ME+wFu&LA9tw9RA?azGhjrVJKy&8=*qZT5Dr8g--d+S8zAyJ$1HlW3Olryt`yE zFIph~Z6oF&o64rw{>lgZISC6p^CBer9C5G6yq%?8tC+)7*d+ib^?fU!JRFxynRLEZ zj;?PwtS}Ao#9whV@KEmwQgM0TVP{hs>dg(1*DiMUOKHdQGIqa0`yZnHk9mtbPfoLx zo;^V6pKUJ!5#n`w2D&381#5#_t}AlTGEgDz$^;u;-vxDN?^#5!zN9ngytY@oTv!nc zp1Xn8uR$1Z;7vY`-<*?DfPHB;x|GUi_fI9@I9SVRv1)qETbNU_8{5U|(>Du84qP#7 z*l9Y$SgA&wGbj>R1YeT9vYjZuC@|{rajTL0f%N@>3$DFU=`lSPl=Iv;EjuGjBa$Gw zHD-;%YOE@<-!7-Mn`0WuO3oWuL6tB2cpPw~Nvuj|KM@))ixuDK`9;jGMe2d)7gHin zS<>k@!x;!TJEc#HdL#RF(`|4W+H88d4V%zlh(7#{q2d0OQX9*FW^`^_<3r$kabWAB z$9BONo5}*(%kx zOXi-yM_cmB3>inPpI~)duvZykJ@^^aWzQ=eQ&STUa}2uT@lV&WoRzkUoE`rR0)`=l zFT%f|LA9fCw>`enm$p7W^E@U7RNBtsh{_-7vVz3DtB*y#*~(L9+x9*wn8VjWw|Q~q zKFsj1Yl>;}%MG3=PY`$g$_mnyhuV&~O~u~)968$0b2!Jkd;2MtAP#ZDYw9hmK_+M$ zb3pxyYC&|CuAbtiG8HZjj?MZJBFbt`ryf+c1dXFuC z0*ZQhBzNBd*}s6K_G}(|Z_9NDV162#y%WSNe|FTDDhx)K!c(mMJh@h87@8(^YdK$&d*^WQe8Z53 z(|@MRJ$Lk-&ii74MPIs80WsOFZ(NX23oR-?As+*aq6b?~62@fSVmM-_*cb1RzZ)`5$agEiL`-E9s7{GM2?(KNPgK1(+c*|-FKoy}X(D_b#etO|YR z(BGZ)0Ntfv-7R4GHoXp?l5g#*={S1{u-QzxCGng*oWr~@X-5f~RA14b8~B+pLKvr4 zfgL|7I>jlak9>D4=(i(cqYf7#318!OSR=^`xxvI!bBlS??`xxWeg?+|>MxaIdH1U~#1tHu zB{QMR?EGRmQ_l4p6YXJ{o(hh-7Tdm>TAX380TZZZyVkqHNzjUn*_|cb?T? zt;d2s-?B#Mc>T-gvBmQZx(y_cfkXZO~{N zT6rP7SD6g~n9QJ)8F*8uHxTLCAZ{l1Y&?6v)BOJZ)=R-pY=Y=&1}jE7fQ>USS}xP#exo57uND0i*rEk@$;nLvRB@u~s^dwRf?G?_enN@$t* zbL%JO=rV(3Ju8#GqUpeE3l_Wu1lN9Y{D4uaUe`g>zlj$1ER$6S6@{m1!~V|bYkhZA z%CvrDRTkHuajMU8;&RZ&itnC~iYLW4DVkP<$}>#&(`UO>!n)Po;Mt(SY8Yb`AS9lt znbX^i?Oe9r_o=?})IHKHoQGKXsps_SE{hwrg?6dMI|^+$CeC&z@*LuF+P`7LfZ*yr+KN8B4{Nzv<`A(wyR@!|gw{zB6Ha ziwPAYh)oJ(nlqSknu(8g9N&1hu0$vFK$W#mp%>X~AU1ay+EKWcFdif{% z#4!4aoVVJ;ULmkQf!ke2}3hqxLK>eq|-d7Ly7-J9zMpT`?dxo6HdfJA|t)?qPEVBDv z{y_b?4^|YA4%WW0VZd8C(ZgQzRI5(I^)=Ub`Y#MHc@nv0w-DaJAqsbEHDWG8Ia6ju zo-iyr*sq((gEwCC&^TYBWt4_@|81?=B-?#P6NMff(*^re zYqvDuO`K@`mjm_Jd;mW_tP`3$cS?R$jR1ZN09$YO%_iBqh5ftzSpMQQtxKFU=FYmP zeY^jph+g<4>YO;U^O>-NFLn~-RqlHvnZl2yd2A{Yc1G@Ga$d+Q&(f^tnPf+Z7serIU};17+2DU_f4Z z@GaPFut27d?!YiD+QP@)T=77cR9~MK@bd~pY%X(h%L={{OIb8IQmf-!xmZkm8A0Ga zQSWONI17_ru5wpHg3jI@i9D+_Y|pCqVuHJNdHUauTD=R$JcD2K_liQisqG$(sm=k9;L* z!L?*4B~ql7uioSX$zWJ?;q-SWXRFhz2Jt4%fOHA=Bwf|RzhwqdXGr78y$J)LR7&3T zE1WWz*>GPWKZ0%|@%6=fyx)5rzUpI;bCj>3RKzNG_1w$fIFCZ&UR0(7S?g}`&Pg$M zf`SLsz8wK82Vyj7;RyKmY{a8G{2BHG%w!^T|Njr!h9TO2LaP^_f22Q1=l$QiU84ao zHe_#{S6;qrC6w~7{y(hs-?-j?lbOfgH^E=XcSgnwW*eEz{_Z<_+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 zcmV;526g#~P){YQnis^a@{&-nmRmq)<&%Mztj67_#M}W?l>kYSliK<%xAp;0j{!}J0!o7b zE>q9${Lb$D&h7k=+4=!ek^n+`0zq>LL1O?lVyea53S5x`Nqqo2YyeuIrQrJj9XjOp z{;T5qbj3}&1vg1VK~#9!?b~^C5-}JC@Pyrv-6dSEqJqT}#j9#dJ@GzT@B8}x zU&J@bBI>f6w6en+CeI)3^kC*U?}X%OD8$Fd$H&LV$H&LV$H&LV#|K5~mLYf|VqzOc zkc7qL~0sOYuM{tG`rYEDV{DWY`Z8&)kW*hc2VkBuY+^Yx&92j&StN}Wp=LD zxoGxXw6f&8sB^u})h@b@z0RBeD`K7RMR9deyL(ZJu#39Z>rT)^>v}Khq8U-IbIvT> z?4pV9qGj=2)TNH3d)=De<+^w;>S7m_eFKTvzeaBeir45xY!^m!FmxnljbSS_3o=g( z->^wC9%qkR{kbGnW8MfFew_o9h3(r55Is`L$8KI@d+*%{=Nx+FXJ98L0PjFIu;rGnnfY zn1R5Qnp<{Jq0M1vX=X&F8gtLmcWv$1*M@4ZfF^9``()#hGTeKeP`1!iED ztNE(TN}M5}3Bbc*d=FIv`DNv&@|C6yYj{sSqUj5oo$#*0$7pu|Dd2TLI>t5%I zIa4Dvr(iayb+5x=j*Vum9&irk)xV1`t509lnPO0%skL8_1c#Xbamh(2@f?4yUI zhhuT5<#8RJhGz4%b$`PJwKPAudsm|at?u;*hGgnA zU1;9gnxVBC)wA(BsB`AW54N{|qmikJR*%x0c`{LGsSfa|NK61pYH(r-UQ4_JXd!Rsz)=k zL{GMc5{h138)fF5CzHEDM>+FqY)$pdN3}Ml+riTgJOLN0F*Vh?{9ESR{SVVg>*>=# zix;VJHPtvFFCRY$Ks*F;VX~%*r9F)W`PmPE9F!(&s#x07n2<}?S{(ygpXgX-&B&OM zONY&BRQ(#%0%jeQs?oJ4P!p*R98>qCy5p8w>_gpuh39NcOlp)(wOoz0sY-Qz55eB~ z7OC-fKBaD1sE3$l-6QgBJO!n?Q generateNewAddress(Object wallet) async { + Future generateNewAddress(Object wallet, {String? label}) async { final bitcoinWallet = wallet as ElectrumWallet; - await bitcoinWallet.walletAddresses.generateNewAddress(); + await bitcoinWallet.walletAddresses.generateNewAddress(label: label); } @override @@ -106,6 +106,21 @@ class CWBitcoin extends Bitcoin { return bitcoinWallet.walletAddresses.address; } + String getReceiveAddress(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.walletAddresses.receiveAddress; + } + + btc.SilentPaymentAddress? getSilentAddress(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.walletAddresses.silentAddress; + } + + List getSilentAddresses(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.walletAddresses.silentAddresses; + } + @override String formatterBitcoinAmountToString({required int amount}) => bitcoinAmountToString(amount: amount); @@ -156,4 +171,4 @@ class CWBitcoin extends Bitcoin { @override TransactionPriority getLitecoinTransactionPrioritySlow() => LitecoinTransactionPriority.slow; -} \ No newline at end of file +} diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index fcb881943..678dc2b8f 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -25,7 +25,10 @@ class AddressValidator extends TextValidator { return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$' '|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$'; case CryptoCurrency.btc: - return '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{59}\$'; + final p2sh = '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$'; + final testnet = '^tb1[0-9a-zA-Z]{59}\$|^tb1[0-9a-zA-Z]{39}\$'; + final silentpayments = '^tsp1[0-9a-zA-Z]{113}\$'; + return '^bc1[0-9a-zA-Z]{59}\$|$p2sh|$testnet|$silentpayments'; case CryptoCurrency.nano: return '[0-9a-zA-Z_]'; case CryptoCurrency.banano: @@ -284,4 +287,4 @@ class AddressValidator extends TextValidator { return null; } } -} \ No newline at end of file +} diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index 8dcf93f74..1b0b765fc 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -49,7 +49,7 @@ class WalletCreationService { } } - Future create(WalletCredentials credentials) async { + Future create(WalletCredentials credentials, {bool? isTestnet}) async { checkIfExists(credentials.name); if (credentials.password == null) { @@ -58,7 +58,7 @@ class WalletCreationService { password: credentials.password!, walletName: credentials.name); } - final wallet = await _service!.create(credentials); + final wallet = await _service!.create(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( diff --git a/lib/di.dart b/lib/di.dart index 29cbf1fae..afdf92e68 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -532,8 +532,7 @@ Future setup({ getIt.registerFactory( () => Modify2FAPage(setup2FAViewModel: getIt.get())); - getIt.registerFactory( - () => DesktopSettingsPage()); + getIt.registerFactory(() => DesktopSettingsPage()); getIt.registerFactoryParam( (pageOption, _) => ReceiveOptionViewModel(getIt.get().wallet!, pageOption)); @@ -653,7 +652,7 @@ Future setup({ getIt.registerFactory(() { final wallet = getIt.get().wallet!; - if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) { + if (true) { return MoneroAccountListViewModel(wallet); } throw Exception( @@ -848,8 +847,8 @@ Future setup({ return ethereum!.createEthereumWalletService( _walletInfoSource, SettingsStoreBase.walletPasswordDirectInput); case WalletType.bitcoinCash: - return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource, - SettingsStoreBase.walletPasswordDirectInput); + return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource, + _unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput); case WalletType.nano: return nano!.createNanoWalletService( _walletInfoSource, SettingsStoreBase.walletPasswordDirectInput); @@ -1155,8 +1154,8 @@ Future setup({ IoniaPaymentStatusPage( getIt.get(param1: paymentInfo, param2: committedInfo))); - getIt.registerFactoryParam( - (type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get())); + getIt.registerFactoryParam( + (type, _) => AdvancedPrivacySettingsViewModel(getIt.get())); getIt.registerFactoryParam((args, _) { final currentWalletName = diff --git a/lib/reactions/check_connection.dart b/lib/reactions/check_connection.dart index 9185ffe15..79056d6d1 100644 --- a/lib/reactions/check_connection.dart +++ b/lib/reactions/check_connection.dart @@ -1,37 +1,37 @@ -import 'dart:async'; +// import 'dart:async'; -import 'package:connectivity_plus/connectivity_plus.dart'; +// import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/sync_status.dart'; +// import 'package:cw_core/sync_status.dart'; import 'package:cake_wallet/store/settings_store.dart'; -Timer? _checkConnectionTimer; +// Timer? _checkConnectionTimer; void startCheckConnectionReaction( WalletBase wallet, SettingsStore settingsStore, {int timeInterval = 5}) { - _checkConnectionTimer?.cancel(); - _checkConnectionTimer = - Timer.periodic(Duration(seconds: timeInterval), (_) async { - try { - final connectivityResult = await (Connectivity().checkConnectivity()); + // _checkConnectionTimer?.cancel(); + // _checkConnectionTimer = + // Timer.periodic(Duration(seconds: timeInterval), (_) async { + // try { + // final connectivityResult = await (Connectivity().checkConnectivity()); - if (connectivityResult == ConnectivityResult.none) { - wallet.syncStatus = FailedSyncStatus(); - return; - } + // if (connectivityResult == ConnectivityResult.none) { + // wallet.syncStatus = FailedSyncStatus(); + // return; + // } - if (wallet.syncStatus is LostConnectionSyncStatus || - wallet.syncStatus is FailedSyncStatus) { - final alive = - await settingsStore.getCurrentNode(wallet.type).requestNode(); + // if (wallet.syncStatus is LostConnectionSyncStatus || + // wallet.syncStatus is FailedSyncStatus) { + // final alive = + // await settingsStore.getCurrentNode(wallet.type).requestNode(); - if (alive) { - await wallet.connectToNode( - node: settingsStore.getCurrentNode(wallet.type)); - } - } - } catch (e) { - print(e.toString()); - } - }); + // if (alive) { + // await wallet.connectToNode( + // node: settingsStore.getCurrentNode(wallet.type)); + // } + // } + // } catch (e) { + // print(e.toString()); + // } + // }); } diff --git a/lib/router.dart b/lib/router.dart index c3cbc3829..651631e2e 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -124,7 +124,8 @@ Route createRoute(RouteSettings settings) { case Routes.newWalletFromWelcome: if (SettingsStoreBase.walletPasswordDirectInput) { if (availableWalletTypes.length == 1) { - return createRoute(RouteSettings(name: Routes.newWallet, arguments: availableWalletTypes.first)); + return createRoute( + RouteSettings(name: Routes.newWallet, arguments: availableWalletTypes.first)); } else { return createRoute(RouteSettings(name: Routes.newWalletType)); } @@ -295,16 +296,14 @@ Route createRoute(RouteSettings settings) { case Routes.auth: return MaterialPageRoute( fullscreenDialog: true, - builder: (_) - => SettingsStoreBase.walletPasswordDirectInput - ? getIt.get( - param1: WalletUnlockArguments( + builder: (_) => SettingsStoreBase.walletPasswordDirectInput + ? getIt.get( + param1: WalletUnlockArguments( callback: settings.arguments as OnAuthenticationFinished), - instanceName: 'wallet_unlock_verifiable', - param2: true) - : getIt.get( - param1: settings.arguments as OnAuthenticationFinished, - param2: true)); + instanceName: 'wallet_unlock_verifiable', + param2: true) + : getIt.get( + param1: settings.arguments as OnAuthenticationFinished, param2: true)); case Routes.totpAuthCodePage: final args = settings.arguments as TotpAuthArgumentsModel; @@ -318,28 +317,25 @@ Route createRoute(RouteSettings settings) { case Routes.walletUnlockLoadable: return MaterialPageRoute( fullscreenDialog: true, - builder: (_) - => getIt.get( + builder: (_) => getIt.get( param1: settings.arguments as WalletUnlockArguments, - instanceName: 'wallet_unlock_loadable', + instanceName: 'wallet_unlock_loadable', param2: true)); case Routes.unlock: return MaterialPageRoute( fullscreenDialog: true, - builder: (_) - => SettingsStoreBase.walletPasswordDirectInput - ? WillPopScope( - child: getIt.get( + builder: (_) => SettingsStoreBase.walletPasswordDirectInput + ? WillPopScope( + child: getIt.get( param1: WalletUnlockArguments( - callback: settings.arguments as OnAuthenticationFinished), + callback: settings.arguments as OnAuthenticationFinished), param2: false, instanceName: 'wallet_unlock_verifiable'), - onWillPop: () async => false) - : WillPopScope( - child: getIt.get( - param1: settings.arguments as OnAuthenticationFinished, - param2: false), + onWillPop: () async => false) + : WillPopScope( + child: getIt.get( + param1: settings.arguments as OnAuthenticationFinished, param2: false), onWillPop: () async => false)); case Routes.connectionSync: @@ -376,11 +372,12 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( builder: (context) => WillPopScope( child: SettingsStoreBase.walletPasswordDirectInput - ? getIt.get(instanceName: 'wallet_password_login') - : getIt.get(instanceName: 'login'), + ? getIt.get(instanceName: 'wallet_password_login') + : getIt.get(instanceName: 'login'), onWillPop: () async => - // FIX-ME: Additional check does it works correctly - (await SystemChannels.platform.invokeMethod('SystemNavigator.pop') ?? false)), + // FIX-ME: Additional check does it works correctly + (await SystemChannels.platform.invokeMethod('SystemNavigator.pop') ?? + false)), fullscreenDialog: true); case Routes.newPowNode: @@ -470,8 +467,7 @@ Route createRoute(RouteSettings settings) { case Routes.support: return CupertinoPageRoute( - fullscreenDialog: true, - builder: (_) => getIt.get()); + fullscreenDialog: true, builder: (_) => getIt.get()); case Routes.supportLiveChat: return CupertinoPageRoute(builder: (_) => getIt.get()); @@ -575,7 +571,7 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( builder: (_) => AdvancedPrivacySettingsPage( - getIt.get(param1: type), + getIt.get(), getIt.get(param1: type, param2: false), )); diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index c57613fa5..aa4fa7f2d 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -161,10 +161,10 @@ class AddressPage extends BasePage { Observer(builder: (_) { if (addressListViewModel.hasAddressList) { return GestureDetector( - onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled + onTap: () async => !addressListViewModel.hasSilentAddresses && + dashboardViewModel.isAutoGenerateSubaddressesEnabled ? await showPopUp( - context: context, - builder: (_) => getIt.get()) + context: context, builder: (_) => getIt.get()) : Navigator.of(context).pushNamed(Routes.receive), child: Container( height: 50, @@ -184,26 +184,30 @@ class AddressPage extends BasePage { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Observer( - builder: (_) { - String label = addressListViewModel.hasAccounts - ? S.of(context).accounts_subaddresses - : S.of(context).addresses; + builder: (_) { + String label = addressListViewModel.hasSilentAddresses + ? S.of(context).address_and_silent_addresses + : addressListViewModel.hasAccounts + ? S.of(context).accounts_subaddresses + : S.of(context).addresses; - if (dashboardViewModel.isAutoGenerateSubaddressesEnabled) { - label = addressListViewModel.hasAccounts - ? S.of(context).accounts - : S.of(context).account; - } - return Text( - label, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .extension()! - .textColor), - ); - },), + if (!addressListViewModel.hasSilentAddresses && + dashboardViewModel.isAutoGenerateSubaddressesEnabled) { + label = addressListViewModel.hasAccounts + ? S.of(context).accounts + : S.of(context).account; + } + return Text( + label, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .extension()! + .textColor), + ); + }, + ), Icon( Icons.arrow_forward_ios, size: 14, @@ -213,7 +217,8 @@ class AddressPage extends BasePage { ), ), ); - } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || addressListViewModel.showElectrumAddressDisclaimer) { + } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || + addressListViewModel.showElectrumAddressDisclaimer) { return Text(S.of(context).electrum_address_disclaimer, textAlign: TextAlign.center, style: TextStyle( diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 2dcc9847b..0837b3bdd 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/entities/generate_name.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/routes.dart'; @@ -253,6 +254,12 @@ class _WalletNameFormState extends State { ), ), ], + Observer(builder: (context) { + return SettingsSwitcherCell( + title: S.current.use_testnet, + value: widget._walletNewVM.useTestnet, + onValueChange: (_, __) => widget._walletNewVM.toggleUseTestnet()); + }), ], ), ), diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 87b668e34..4e558b1e3 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -67,8 +67,7 @@ class ReceivePage extends BasePage { @override Widget Function(BuildContext, Widget) get rootWrapper => - (BuildContext context, Widget scaffold) => - GradientBackground(scaffold: scaffold); + (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold); @override Widget trailing(BuildContext context) { @@ -99,7 +98,8 @@ class ReceivePage extends BasePage { @override Widget body(BuildContext context) { - return (addressListViewModel.type == WalletType.monero || + return (addressListViewModel.type == WalletType.bitcoin || + addressListViewModel.type == WalletType.monero || addressListViewModel.type == WalletType.haven || addressListViewModel.type == WalletType.nano || addressListViewModel.type == WalletType.banano) @@ -156,7 +156,8 @@ class ReceivePage extends BasePage { icon: Icon( Icons.arrow_forward_ios, size: 14, - color: Theme.of(context).extension()!.iconsColor, + color: + Theme.of(context).extension()!.iconsColor, )); } @@ -164,11 +165,12 @@ class ReceivePage extends BasePage { cell = HeaderTile( onTap: () => Navigator.of(context).pushNamed(Routes.newSubaddress), - title: S.of(context).addresses, + title: S.of(context).silent_addresses, icon: Icon( Icons.add, size: 20, - color: Theme.of(context).extension()!.iconsColor, + color: + Theme.of(context).extension()!.iconsColor, )); } @@ -177,11 +179,19 @@ class ReceivePage extends BasePage { final isCurrent = item.address == addressListViewModel.address.address; final backgroundColor = isCurrent - ? Theme.of(context).extension()!.currentTileBackgroundColor - : Theme.of(context).extension()!.tilesBackgroundColor; + ? Theme.of(context) + .extension()! + .currentTileBackgroundColor + : Theme.of(context) + .extension()! + .tilesBackgroundColor; final textColor = isCurrent - ? Theme.of(context).extension()!.currentTileTextColor - : Theme.of(context).extension()!.tilesTextColor; + ? Theme.of(context) + .extension()! + .currentTileTextColor + : Theme.of(context) + .extension()! + .tilesTextColor; return AddressCell.fromItem(item, isCurrent: isCurrent, @@ -202,6 +212,15 @@ class ReceivePage extends BasePage { child: cell, ); })), + Padding( + padding: EdgeInsets.fromLTRB(24, 24, 24, 32), + child: Text(S.of(context).electrum_address_disclaimer, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + color: + Theme.of(context).extension()!.labelTextColor)), + ), ], ), )) diff --git a/lib/src/widgets/validable_annotated_editable_text.dart b/lib/src/widgets/validable_annotated_editable_text.dart index 6c3fc4f16..927f74c94 100644 --- a/lib/src/widgets/validable_annotated_editable_text.dart +++ b/lib/src/widgets/validable_annotated_editable_text.dart @@ -2,7 +2,7 @@ import 'package:cake_wallet/core/seed_validator.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; -class Annotation extends Comparable { +class Annotation implements Comparable { Annotation({required this.range, required this.style}); final TextRange range; diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index 380937212..c02613afa 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -1,7 +1,6 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; part 'advanced_privacy_settings_view_model.g.dart'; @@ -10,7 +9,7 @@ class AdvancedPrivacySettingsViewModel = AdvancedPrivacySettingsViewModelBase with _$AdvancedPrivacySettingsViewModel; abstract class AdvancedPrivacySettingsViewModelBase with Store { - AdvancedPrivacySettingsViewModelBase(this.type, this._settingsStore) : _addCustomNode = false; + AdvancedPrivacySettingsViewModelBase(this._settingsStore) : _addCustomNode = false; @computed ExchangeApiMode get exchangeStatus => _settingsStore.exchangeStatus; @@ -21,8 +20,6 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @observable bool _addCustomNode = false; - final WalletType type; - final SettingsStore _settingsStore; @computed diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index 0fb9a83c6..e323268a0 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -65,6 +65,8 @@ abstract class NodeCreateOrEditViewModelBase with Store { bool get hasAuthCredentials => _walletType == WalletType.monero || _walletType == WalletType.haven; + bool get hasTestnetSupport => _walletType == WalletType.bitcoin; + String get uri { var uri = address; diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart index 9e2aa7187..87c8f6bea 100644 --- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; +import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter/foundation.dart'; import 'package:cw_core/wallet_base.dart'; @@ -27,8 +28,7 @@ class AddressEditOrCreateStateFailure extends AddressEditOrCreateState { } abstract class WalletAddressEditOrCreateViewModelBase with Store { - WalletAddressEditOrCreateViewModelBase( - {required WalletBase wallet, WalletAddressListItem? item}) + WalletAddressEditOrCreateViewModelBase({required WalletBase wallet, WalletAddressListItem? item}) : isEdit = item != null, state = AddressEditOrCreateStateInitial(), label = item?.name ?? '', @@ -68,27 +68,21 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { if (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) { - await bitcoin!.generateNewAddress(wallet); + await bitcoin!.generateNewAddress(wallet, label: label); await wallet.save(); } if (wallet.type == WalletType.monero) { - await monero - !.getSubaddressList(wallet) - .addSubaddress( - wallet, - accountIndex: monero!.getCurrentAccount(wallet).id, - label: label); + await monero! + .getSubaddressList(wallet) + .addSubaddress(wallet, accountIndex: monero!.getCurrentAccount(wallet).id, label: label); await wallet.save(); } if (wallet.type == WalletType.haven) { - await haven - !.getSubaddressList(wallet) - .addSubaddress( - wallet, - accountIndex: haven!.getCurrentAccount(wallet).id, - label: label); + await haven! + .getSubaddressList(wallet) + .addSubaddress(wallet, accountIndex: haven!.getCurrentAccount(wallet).id, label: label); await wallet.save(); } } @@ -109,9 +103,7 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { } if (wallet.type == WalletType.haven) { await haven!.getSubaddressList(wallet).setLabelSubaddress(wallet, - accountIndex: haven!.getCurrentAccount(wallet).id, - addressIndex: index, - label: label); + accountIndex: haven!.getCurrentAccount(wallet).id, addressIndex: index, label: label); await wallet.save(); } } diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index 4d5eefdb7..ba6c3ede1 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -109,7 +109,7 @@ class EthereumURI extends PaymentURI { class BitcoinCashURI extends PaymentURI { BitcoinCashURI({required String amount, required String address}) - : super(amount: amount, address: address); + : super(amount: amount, address: address); @override String toString() { var base = address; @@ -120,9 +120,7 @@ class BitcoinCashURI extends PaymentURI { return base; } - } - - +} class NanoURI extends PaymentURI { NanoURI({required String amount, required String address}) @@ -147,8 +145,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo }) : _baseItems = [], selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type), _cryptoNumberFormat = NumberFormat(_cryptoNumberPattern), - hasAccounts = - appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven, + hasAccounts = appStore.wallet!.type == WalletType.bitcoin || + appStore.wallet!.type == WalletType.monero || + appStore.wallet!.type == WalletType.haven, amount = '', super(appStore: appStore) { _init(); @@ -159,7 +158,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo _init(); selectedCurrency = walletTypeToCryptoCurrency(wallet.type); - hasAccounts = wallet.type == WalletType.monero || wallet.type == WalletType.haven; + hasAccounts = wallet.type == WalletType.bitcoin || + wallet.type == WalletType.monero || + wallet.type == WalletType.haven; } static const String _cryptoNumberPattern = '0.00000000'; @@ -257,13 +258,19 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo } if (wallet.type == WalletType.bitcoin) { - final primaryAddress = bitcoin!.getAddress(wallet); - final bitcoinAddresses = bitcoin!.getAddresses(wallet).map((addr) { - final isPrimary = addr == primaryAddress; + final receiveAddress = bitcoin!.getReceiveAddress(wallet); + addressList.add( + WalletAddressListItem(isPrimary: true, name: 'Primary address', address: receiveAddress)); - return WalletAddressListItem(isPrimary: isPrimary, name: null, address: addr); + final silentAddress = bitcoin!.getSilentAddress(wallet).toString(); + addressList.add( + WalletAddressListItem(isPrimary: false, name: silentAddress, address: silentAddress)); + + final silentAddresses = bitcoin!.getSilentAddresses(wallet); + silentAddresses.forEach((addr) { + addressList.add(WalletAddressListItem( + isPrimary: false, name: addr.silentAddressLabel, address: addr.address)); }); - addressList.addAll(bitcoinAddresses); } if (wallet.type == WalletType.ethereum) { @@ -291,18 +298,24 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return ''; } + @computed + bool get hasSilentAddresses => wallet.type == WalletType.bitcoin; + @computed bool get hasAddressList => + wallet.type == WalletType.bitcoin || wallet.type == WalletType.monero || - wallet.type == WalletType.haven;/* || + wallet.type == + WalletType + .haven; /* || wallet.type == WalletType.nano || - wallet.type == WalletType.banano;*/// TODO: nano accounts are disabled for now + wallet.type == WalletType.banano;*/ // TODO: nano accounts are disabled for now @computed bool get showElectrumAddressDisclaimer => wallet.type == WalletType.bitcoin || - wallet.type == WalletType.litecoin || - wallet.type == WalletType.bitcoinCash; + wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoinCash; List _baseItems; @@ -316,9 +329,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo _baseItems = []; if (wallet.type == WalletType.monero || - wallet.type == WalletType.haven /*|| + wallet.type == + WalletType + .haven /*|| wallet.type == WalletType.nano || - wallet.type == WalletType.banano*/) { + wallet.type == WalletType.banano*/ + ) { _baseItems.add(WalletAccountListHeader()); } diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index c76e4a554..abab1a3d1 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -49,7 +49,7 @@ abstract class WalletCreationVMBase with Store { bool typeExists(WalletType type) => walletCreationService.typeExists(type); - Future create({dynamic options, RestoredWallet? restoreWallet}) async { + Future create({dynamic options, RestoredWallet? restoreWallet, bool? isTestnet}) async { final type = restoreWallet?.type ?? this.type; try { state = IsExecutingState(); diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 582c0d5e2..db185e5b3 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -26,6 +26,12 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { : selectedMnemonicLanguage = '', super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: false); + @observable + bool _useTestnet = false; + + @computed + bool get useTestnet => _useTestnet; + @observable String selectedMnemonicLanguage; @@ -58,6 +64,10 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { @override Future process(WalletCredentials credentials) async { walletCreationService.changeWalletType(type: type); - return walletCreationService.create(credentials); + return walletCreationService.create(credentials, isTestnet: useTestnet); } + + // TODO: set electrum's node as default for testnet + @action + void toggleUseTestnet() => _useTestnet = !_useTestnet; } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 77cfc4257..411aa201c 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,7 +8,6 @@ #include #include -#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -18,9 +17,6 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) devicelocale_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DevicelocalePlugin"); devicelocale_plugin_register_with_registrar(devicelocale_registrar); - g_autoptr(FlPluginRegistrar) platform_device_id_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "PlatformDeviceIdLinuxPlugin"); - platform_device_id_linux_plugin_register_with_registrar(platform_device_id_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index e432c44eb..1a3958652 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,7 +5,6 @@ list(APPEND FLUTTER_PLUGIN_LIST cw_monero devicelocale - platform_device_id_linux url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 46745f8e5..b166295a5 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,30 +5,24 @@ import FlutterMacOS import Foundation -import connectivity_plus_macos import cw_monero import device_info_plus import devicelocale import in_app_review import package_info_plus import path_provider_foundation -import platform_device_id -import platform_device_id_macos import share_plus_macos import shared_preferences_foundation import url_launcher_macos import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) - FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) - PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000..5418c9f53 --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/model_generator.sh b/model_generator.sh index db621bdea..7756b7152 100755 --- a/model_generator.sh +++ b/model_generator.sh @@ -1,10 +1,10 @@ #!/bin/sh -cd cw_core; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. -cd cw_monero; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. -cd cw_bitcoin; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. -cd cw_haven; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. -cd cw_ethereum; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. -cd cw_nano; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. -cd cw_bitcoin_cash; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. -flutter packages pub run build_runner build --delete-conflicting-outputs +cd cw_core; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. +cd cw_monero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. +cd cw_bitcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. +cd cw_haven; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. +cd cw_ethereum; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. +cd cw_nano; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. +cd cw_bitcoin_cash; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. +dart run build_runner build --delete-conflicting-outputs diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 36631dbd9..d2fbf7f9f 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -48,7 +48,7 @@ dependencies: basic_utils: ^5.6.1 get_it: ^7.2.0 # connectivity: ^3.0.3 - connectivity_plus: ^2.3.5 + # connectivity_plus: ^2.3.5 keyboard_actions: ^4.0.1 another_flushbar: ^1.12.29 archive: ^3.3.0 @@ -85,9 +85,7 @@ dependencies: url: https://github.com/cake-tech/ens_dart.git ref: main bitcoin_flutter: - git: - url: https://github.com/cake-tech/bitcoin_flutter.git - ref: cake-update-v3 + path: /home/rafael/Storage/Repositories/bitcoin_flutter fluttertoast: 8.1.4 dev_dependencies: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 4b4b59b2a..1075853fd 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -435,7 +435,7 @@ "search_language": "ابحث عن لغة", "search_currency": "ابحث عن عملة", "new_template": "قالب جديد", - "electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل", + "electrum_address_disclaimer": "نقوم بإنشاء عناوين أساسية جديدة في كل مرة تستخدم فيها واحدة ، لكن العناوين السابقة تستمر في العمل", "wallet_name_exists": "توجد بالفعل محفظة بهذا الاسم. الرجاء اختيار اسم مختلف أو إعادة تسمية المحفظة الأخرى أولاً.", "market_place": "منصة التجارة", "cake_pay_title": "بطاقات هدايا Cake Pay", @@ -732,5 +732,8 @@ "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", - "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" + "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "use_testnet": "استخدم testnet", + "address_and_silent_addresses": "العنوان والعناوين الصامتة", + "silent_addresses": "عناوين صامتة" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 44a51dcf7..d80f6724e 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -435,7 +435,7 @@ "search_language": "Търсене на език", "search_currency": "Търсене на валута", "new_template": "Нов шаблон", - "electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят", + "electrum_address_disclaimer": "Ние генерираме нови първични адреси всеки път, когато използвате един, но предишните адреси продължават да работят", "wallet_name_exists": "Вече има портфейл с това име. Моля, изберете друго име или преименувайте другия портфейл.", "market_place": "Магазин", "cake_pay_title": "Cake Pay Gift Карти", @@ -728,5 +728,8 @@ "domain_looks_up": "Търсене на домейни", "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", - "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново" + "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "use_testnet": "Използвайте TestNet", + "address_and_silent_addresses": "Адрес и мълчаливи адреси", + "silent_addresses": "Безшумни адреси" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8600ba5ee..eb1f9d274 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -435,7 +435,7 @@ "search_language": "Hledat jazyk", "search_currency": "Hledat měnu", "new_template": "Nová šablona", - "electrum_address_disclaimer": "Po každém použití je generována nová adresa, ale předchozí adresy také stále fungují", + "electrum_address_disclaimer": "Pokaždé, když jednu použijete, generujeme nové primární adresy, ale předchozí adresy nadále fungují", "wallet_name_exists": "Peněženka s tímto názvem už existuje. Prosím zvolte si jiný název, nebo nejprve přejmenujte nejprve druhou peněženku.", "market_place": "Obchod", "cake_pay_title": "Cake Pay dárkové karty", @@ -728,5 +728,8 @@ "domain_looks_up": "Vyhledávání domén", "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", - "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu" + "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "use_testnet": "Použijte testNet", + "address_and_silent_addresses": "Adresa a tiché adresy", + "silent_addresses": "Tiché adresy" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 1f1acdb6d..158c3c1b0 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -435,7 +435,7 @@ "search_language": "Sprache suchen", "search_currency": "Währung suchen", "new_template": "neue Vorlage", - "electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin", + "electrum_address_disclaimer": "Wir generieren jedes Mal neue primäre Adressen, wenn Sie eine verwenden, aber frühere Adressen funktionieren weiterhin", "wallet_name_exists": "Wallet mit diesem Namen existiert bereits", "market_place": "Marktplatz", "cake_pay_title": "Cake Pay-Geschenkkarten", @@ -736,5 +736,11 @@ "domain_looks_up": "Domain-Suchen", "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", - "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut" + "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "seed_key": "Samenschlüssel", + "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein", + "add_contact": "Kontakt hinzufügen", + "use_testnet": "TESTNET verwenden", + "address_and_silent_addresses": "Adresse und stille Adressen", + "silent_addresses": "Stille Adressen" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index cda1845be..1c923f7bc 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -435,7 +435,7 @@ "search_language": "Search language", "search_currency": "Search currency", "new_template": "New Template", - "electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work", + "electrum_address_disclaimer": "We generate new primary addresses each time you use one, but previous addresses continue to work", "wallet_name_exists": "A wallet with that name already exists. Please choose a different name or rename the other wallet first.", "market_place": "Marketplace", "cake_pay_title": "Cake Pay Gift Cards", @@ -737,5 +737,8 @@ "domain_looks_up": "Domain lookups", "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", - "switchToETHWallet": "Please switch to an Ethereum wallet and try again" + "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "use_testnet": "Use testnet", + "address_and_silent_addresses": "Address and Silent Addresses", + "silent_addresses": "Silent Addresses" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 67cf6addf..d8d8a1845 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -435,7 +435,7 @@ "search_language": "Idioma de búsqueda", "search_currency": "Moneda de búsqueda", "new_template": "Nueva plantilla", - "electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando", + "electrum_address_disclaimer": "Generamos nuevas direcciones primarias cada vez que usa una, pero las direcciones anteriores continúan funcionando", "wallet_name_exists": "Wallet con ese nombre ya ha existido", "market_place": "Mercado", "cake_pay_title": "Tarjetas de regalo Cake Pay", @@ -736,5 +736,8 @@ "domain_looks_up": "Búsquedas de dominio", "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", - "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente." + "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "use_testnet": "Use TestNet", + "address_and_silent_addresses": "Dirección y direcciones silenciosas", + "silent_addresses": "Direcciones silenciosas" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index cb80a1f53..bea153d5f 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -435,7 +435,7 @@ "search_language": "Rechercher une langue", "search_currency": "Rechercher une devise", "new_template": "Nouveau Modèle", - "electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner", + "electrum_address_disclaimer": "Nous générons de nouvelles adresses primaires chaque fois que vous en utilisez une, mais les adresses précédentes continuent de fonctionner", "wallet_name_exists": "Un portefeuille (wallet) portant ce nom existe déjà", "market_place": "Place de marché", "cake_pay_title": "Cartes cadeaux Cake Pay", @@ -702,7 +702,7 @@ "select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.", "onramper_option_description": "Achetez rapidement des cryptomonnaies avec de nombreuses méthodes de paiement. Disponible dans la plupart des pays. Les spreads et les frais peuvent varier.", "default_buy_provider": "Fournisseur d'achat par défaut", - "ask_each_time": "Demander à chaque fois", + "ask_each_time": "Demandez à chaque fois", "buy_provider_unavailable": "Fournisseur actuellement indisponible.", "signTransaction": "Signer une transaction", "errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification", @@ -736,5 +736,8 @@ "domain_looks_up": "Recherches de domaine", "require_for_exchanges_to_external_wallets": "Exiger des échanges vers des portefeuilles externes", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", - "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer" + "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer", + "use_testnet": "Utiliser TestNet", + "address_and_silent_addresses": "Adresse et adresses silencieuses", + "silent_addresses": "Adresses silencieuses" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index f2e0e9d2f..d7b88d0eb 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -436,7 +436,7 @@ "search_language": "Bincika harshe", "search_currency": "Neman kudin waje", "new_template": "Sabon Samfura", - "electrum_address_disclaimer": "Muna samar da sababbin adireshi duk lokacin da kuka yi amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki", + "electrum_address_disclaimer": "Muna samar da sabbin adiresoshin farko a duk lokacin da kake amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki", "wallet_name_exists": "Wallet mai wannan sunan ya riga ya wanzu. Da fatan za a zaɓi wani suna daban ko sake suna ɗayan walat tukuna.", "market_place": "Kasuwa", "cake_pay_title": "Cake Pay Gift Cards", @@ -714,5 +714,8 @@ "domain_looks_up": "Binciken yanki", "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", - "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa" + "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "use_testnet": "Amfani da gwaji", + "address_and_silent_addresses": "Adireshin da adreshin shiru", + "silent_addresses": "Adireshin Shiru" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 503648de0..f2b0d6ae0 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -435,7 +435,7 @@ "search_language": "भाषा खोजें", "search_currency": "मुद्रा खोजें", "new_template": "नया टेम्पलेट", - "electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं", + "electrum_address_disclaimer": "हम हर बार जब आप एक का उपयोग करते हैं, तो हम नए प्राथमिक पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं", "wallet_name_exists": "उस नाम वाला वॉलेट पहले से मौजूद है", "market_place": "मार्केटप्लेस", "cake_pay_title": "केक पे गिफ्ट कार्ड्स", @@ -736,5 +736,8 @@ "domain_looks_up": "डोमेन लुकअप", "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", - "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें" + "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "use_testnet": "टेस्टनेट का उपयोग करें", + "address_and_silent_addresses": "पता और मूक पते", + "silent_addresses": "मूक पते" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 2a9df641d..a5a9e82ee 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -435,7 +435,7 @@ "search_language": "Jezik pretraživanja", "search_currency": "Traži valutu", "new_template": "novi predložak", - "electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek", + "electrum_address_disclaimer": "Generiramo nove primarne adrese svaki put kada ih koristite, ali prethodne adrese i dalje rade", "wallet_name_exists": "Novčanik s tim nazivom već postoji", "market_place": "Tržnica", "cake_pay_title": "Cake Pay poklon kartice", @@ -734,5 +734,8 @@ "domain_looks_up": "Pretraga domena", "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", - "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno" + "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "use_testnet": "Koristite TestNet", + "address_and_silent_addresses": "Adresa i tihe adrese", + "silent_addresses": "Tihe adrese" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 58935706e..cb654ab36 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -436,7 +436,7 @@ "search_language": "Cari bahasa", "search_currency": "Cari mata uang", "new_template": "Template Baru", - "electrum_address_disclaimer": "Kami menghasilkan alamat baru setiap kali Anda menggunakan satu, tetapi alamat sebelumnya tetap berfungsi", + "electrum_address_disclaimer": "Kami menghasilkan alamat utama baru setiap kali Anda menggunakannya, tetapi alamat sebelumnya terus berfungsi", "wallet_name_exists": "Nama dompet sudah ada. Silakan pilih nama yang berbeda atau ganti nama dompet yang lain terlebih dahulu.", "market_place": "Pasar", "cake_pay_title": "Kartu Hadiah Cake Pay", @@ -724,5 +724,8 @@ "domain_looks_up": "Pencarian domain", "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", - "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi" + "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "use_testnet": "Gunakan TestNet", + "address_and_silent_addresses": "Alamat dan alamat diam", + "silent_addresses": "Alamat diam" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 6b201cf3c..358b06c60 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -435,7 +435,7 @@ "search_language": "Cerca lingua", "search_currency": "Cerca valuta", "new_template": "Nuovo modello", - "electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare", + "electrum_address_disclaimer": "Generiamo nuovi indirizzi primari ogni volta che ne usi uno, ma gli indirizzi precedenti continuano a funzionare", "wallet_name_exists": "Il portafoglio con quel nome è già esistito", "market_place": "Mercato", "cake_pay_title": "Carte regalo Cake Pay", @@ -736,5 +736,8 @@ "domain_looks_up": "Ricerche di domini", "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", - "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova" + "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "use_testnet": "Usa TestNet", + "address_and_silent_addresses": "Indirizzo e indirizzi silenziosi", + "silent_addresses": "Indirizzi silenziosi" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 58ac2b6fd..dccc04294 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -435,7 +435,7 @@ "search_language": "検索言語", "search_currency": "検索通貨", "new_template": "新しいテンプレート", - "electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します", + "electrum_address_disclaimer": "使用するたびに新しいプライマリアドレスを生成しますが、以前のアドレスは機能し続けます", "wallet_name_exists": "その名前のウォレットはすでに存在しています", "market_place": "Marketplace", "cake_pay_title": "ケーキペイギフトカード", @@ -736,5 +736,8 @@ "domain_looks_up": "ドメイン検索", "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", - "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください" + "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "use_testnet": "TestNetを使用します", + "address_and_silent_addresses": "住所とサイレントアドレス", + "silent_addresses": "サイレントアドレス" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 029409f16..f749e49b0 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -435,7 +435,7 @@ "search_language": "검색 언어", "search_currency": "통화 검색", "new_template": "새 템플릿", - "electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.", + "electrum_address_disclaimer": "우리는 당신이 하나를 사용할 때마다 새로운 기본 주소를 생성하지만 이전 주소는 계속 작동합니다.", "wallet_name_exists": "해당 이름의 지갑이 이미 존재합니다.", "market_place": "마켓플레이스", "cake_pay_title": "케이크 페이 기프트 카드", @@ -734,5 +734,8 @@ "domain_looks_up": "도메인 조회", "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", - "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요." + "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "use_testnet": "TestNet을 사용하십시오", + "address_and_silent_addresses": "주소 및 조용한 주소", + "silent_addresses": "조용한 주소" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index b7fff30b0..46cfb98db 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -435,7 +435,7 @@ "search_language": "ဘာသာစကားရှာပါ။", "search_currency": "ငွေကြေးကိုရှာပါ။", "new_template": "ပုံစံအသစ်", - "electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။", + "electrum_address_disclaimer": "သင်အသုံးပြုသောအခါတိုင်းကျွန်ုပ်တို့သည်အဓိကလိပ်စာအသစ်များကိုထုတ်လုပ်သည်, သို့သော်ယခင်လိပ်စာများဆက်လက်အလုပ်လုပ်သည်", "wallet_name_exists": "ထိုအမည်ဖြင့် ပိုက်ဆံအိတ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ သို့မဟုတ် အခြားပိုက်ဆံအိတ်ကို ဦးစွာ အမည်ပြောင်းပါ။", "market_place": "ဈေး", "cake_pay_title": "ကိတ်မုန့်လက်ဆောင်ကတ်များ", @@ -734,5 +734,8 @@ "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", - "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။" + "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "use_testnet": "testnet ကိုသုံးပါ", + "address_and_silent_addresses": "လိပ်စာနှင့်အသံတိတ်လိပ်စာများ", + "silent_addresses": "အသံတိတ်လိပ်စာများ" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 62d8269a1..5ea60e5e9 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -435,7 +435,7 @@ "search_language": "Zoektaal", "search_currency": "Zoek valuta", "new_template": "Nieuwe sjabloon", - "electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken", + "electrum_address_disclaimer": "We genereren nieuwe primaire adressen telkens wanneer u er een gebruikt, maar eerdere adressen blijven werken", "wallet_name_exists": "Portemonnee met die naam bestaat al", "market_place": "Marktplaats", "cake_pay_title": "Cake Pay-cadeaubonnen", @@ -736,5 +736,8 @@ "domain_looks_up": "Domein opzoeken", "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", - "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw" + "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "use_testnet": "Gebruik testnet", + "address_and_silent_addresses": "Adres en stille adressen", + "silent_addresses": "Stille adressen" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 642507569..21255c28f 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -435,7 +435,7 @@ "search_language": "Wyszukaj język", "search_currency": "Wyszukaj walutę", "new_template": "Nowy szablon", - "electrum_address_disclaimer": "Za każdym razem, gdy wykorzystasz adres, dla wiekszej prywatności generujemy nowy, ale poprzednie adresy nadal działają, i moga odbierać środki", + "electrum_address_disclaimer": "Generujemy nowe podstawowe adresy za każdym razem, gdy je używasz, ale poprzednie adresy nadal działają", "wallet_name_exists": "Portfel o tej nazwie już istnieje", "market_place": "Rynek", "cake_pay_title": "Karty podarunkowe Cake Pay", @@ -736,5 +736,8 @@ "domain_looks_up": "Wyszukiwanie domen", "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", - "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie" + "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "use_testnet": "Użyj testne", + "address_and_silent_addresses": "Adres i ciche adresy", + "silent_addresses": "Ciche adresy" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index aa024dbea..3184a0c6d 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -435,7 +435,7 @@ "search_language": "Idioma de pesquisa", "search_currency": "Pesquisar moeda", "new_template": "Novo modelo", - "electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando", + "electrum_address_disclaimer": "Geramos novos endereços primários cada vez que você usa um, mas os endereços anteriores continuam funcionando", "wallet_name_exists": "A carteira com esse nome já existe", "market_place": "Mercado", "cake_pay_title": "Cartões de presente de CakePay", @@ -735,5 +735,8 @@ "domain_looks_up": "Pesquisas de domínio", "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", - "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente" + "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "use_testnet": "Use testNet", + "address_and_silent_addresses": "Endereço e endereços silenciosos", + "silent_addresses": "Endereços silenciosos" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 76bb87104..c07e78a7b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -435,7 +435,7 @@ "search_language": "Язык поиска", "search_currency": "Валюта поиска", "new_template": "Новый шаблон", - "electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.", + "electrum_address_disclaimer": "Мы генерируем новые основные адреса каждый раз, когда вы используете его, но предыдущие адреса продолжают работать", "wallet_name_exists": "Кошелек с таким именем уже существует", "market_place": "Торговая площадка", "cake_pay_title": "Подарочные карты Cake Pay", @@ -736,5 +736,8 @@ "domain_looks_up": "Поиск доменов", "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", - "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку." + "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "use_testnet": "Используйте Testnet", + "address_and_silent_addresses": "Адрес и молчаливые адреса", + "silent_addresses": "Молчаливые адреса" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index d09ced651..94625d50b 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -435,7 +435,7 @@ "search_language": "ค้นหาภาษา", "search_currency": "ค้นหาสกุลเงิน", "new_template": "แม่แบบใหม่", - "electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป", + "electrum_address_disclaimer": "เราสร้างที่อยู่หลักใหม่ทุกครั้งที่คุณใช้ แต่ที่อยู่ก่อนหน้านี้ยังคงทำงานต่อไป", "wallet_name_exists": "กระเป๋าที่มีชื่อนี้มีอยู่แล้ว โปรดเลือกชื่ออื่นหรือเปลี่ยนชื่อกระเป๋าอื่นก่อน", "market_place": "ตลาดพื้นที่", "cake_pay_title": "บัตรของขวัญ Cake Pay", @@ -734,5 +734,8 @@ "domain_looks_up": "การค้นหาโดเมน", "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", - "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง" + "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "use_testnet": "ใช้ testnet", + "address_and_silent_addresses": "ที่อยู่และที่อยู่เงียบ", + "silent_addresses": "ที่อยู่เงียบ" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index cae074c29..94bb189d0 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -435,7 +435,7 @@ "search_language": "Maghanap ng wika", "search_currency": "Maghanap ng pera", "new_template": "Bagong template", - "electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gumagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana", + "electrum_address_disclaimer": "Bumubuo kami ng mga bagong pangunahing address sa tuwing gumagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana", "wallet_name_exists": "Ang isang pitaka na may pangalang iyon ay mayroon na. Mangyaring pumili ng ibang pangalan o palitan muna ang iba pang pitaka.", "market_place": "Marketplace", "cake_pay_title": "Cake pay card card", @@ -731,5 +731,8 @@ "domain_looks_up": "Mga paghahanap ng domain", "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", - "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli" -} + "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "use_testnet": "Gumamit ng testnet", + "address_and_silent_addresses": "Address at tahimik na mga address", + "silent_addresses": "Tahimik na mga address" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 4795db2b5..2e85d9749 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -435,7 +435,7 @@ "search_language": "Dil arat", "search_currency": "Para birimi ara", "new_template": "Yeni Şablon", - "electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder", + "electrum_address_disclaimer": "Her kullandığınızda yeni birincil adresler oluşturuyoruz, ancak önceki adresler çalışmaya devam ediyor", "wallet_name_exists": "Bu isimde bir cüzdan zaten mevcut. Lütfen farklı bir isim seç veya önce diğer cüzdanı yeniden adlandır.", "market_place": "Pazar Alanı", "cake_pay_title": "Cake Pay Hediye Kartları", @@ -734,5 +734,8 @@ "domain_looks_up": "Etki alanı aramaları", "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", - "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin" + "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "use_testnet": "TestNet kullanın", + "address_and_silent_addresses": "Adres ve sessiz adresler", + "silent_addresses": "Sessiz adresler" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 982e94c10..eb78fd250 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -435,7 +435,7 @@ "search_language": "Мова пошуку", "search_currency": "Шукати валюту", "new_template": "Новий шаблон", - "electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати", + "electrum_address_disclaimer": "Ми генеруємо нові первинні адреси кожного разу, коли ви використовуєте його, але попередні адреси продовжують працювати", "wallet_name_exists": "Гаманець з такою назвою вже існує", "market_place": "Ринок", "cake_pay_title": "Подарункові картки Cake Pay", @@ -736,5 +736,8 @@ "domain_looks_up": "Пошук доменів", "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", - "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу" + "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "use_testnet": "Використовуйте тестову мережу", + "address_and_silent_addresses": "Адреса та мовчазні адреси", + "silent_addresses": "Мовчазні адреси" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index db259f83a..f972a44f9 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -436,7 +436,7 @@ "search_language": "زبان تلاش کریں۔", "search_currency": "کرنسی تلاش کریں۔", "new_template": "نیا سانچہ", - "electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔", + "electrum_address_disclaimer": "ہم ہر بار جب آپ کسی کو استعمال کرتے ہیں تو نئے پرائمری پتے تیار کرتے ہیں ، لیکن پچھلے پتے کام کرتے رہتے ہیں", "wallet_name_exists": "اس نام کا پرس پہلے سے موجود ہے۔ براہ کرم ایک مختلف نام منتخب کریں یا پہلے دوسرے بٹوے کا نام تبدیل کریں۔", "market_place": "بازار", "cake_pay_title": "Cake پے گفٹ کارڈز", @@ -728,5 +728,8 @@ "domain_looks_up": "ڈومین تلاش کرنا", "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", - "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ" + "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", + "use_testnet": "ٹیسٹ نیٹ استعمال کریں", + "address_and_silent_addresses": "پتہ اور خاموش پتے", + "silent_addresses": "خاموش پتے" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 9ea9ae2c8..6de0c87b4 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -433,7 +433,7 @@ "search_language": "Wá èdè", "search_currency": "Wá irú owó", "new_template": "Àwòṣe títun", - "electrum_address_disclaimer": "A dá àwọn àdírẹ́sì títun ní gbogbo àwọn ìgbà t'ẹ́ lo ó kan ṣùgbọ́n ẹ lè tẹ̀síwájú lo àwọn àdírẹ́sì tẹ́lẹ̀tẹ́lẹ̀.", + "electrum_address_disclaimer": "A ṣe ina awọn adirẹsi akọkọ akọkọ ni igba kọọkan ti o lo ọkan, ṣugbọn awọn adirẹsi iṣaaju tẹsiwaju lati ṣiṣẹ", "wallet_name_exists": "Ẹ ti ní àpamọ́wọ́ pẹ̀lú orúkọ̀ yẹn. Ẹ jọ̀wọ́ yàn orúkọ̀ tó yàtọ̀ tàbí pààrọ̀ orúkọ ti àpamọ́wọ́ tẹ́lẹ̀.", "market_place": "Ọjà", "cake_pay_title": "Àwọn káàdì ìrajà t'á lò nínú ìtajà kan ti Cake Pay", @@ -730,5 +730,8 @@ "domain_looks_up": "Awọn wiwa agbegbe", "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", - "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi" + "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "use_testnet": "Lo tele", + "address_and_silent_addresses": "Adirẹsi ati awọn adirẹsi ipalọlọ", + "silent_addresses": "Awọn adirẹsi ipalọlọ" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index d7b89ce36..eb6a9ce28 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -434,7 +434,7 @@ "search_language": "搜索语言", "search_currency": "搜索货币", "new_template": "新模板", - "electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效", + "electrum_address_disclaimer": "每次使用一个时,我们都会生成新的主地址,但是以前的地址继续工作", "wallet_name_exists": "同名的钱包已经存在", "market_place": "市场", "cake_pay_title": "Cake Pay 礼品卡", @@ -735,5 +735,8 @@ "domain_looks_up": "域名查找", "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", - "switchToETHWallet": "请切换到以太坊钱包并重试" + "switchToETHWallet": "请切换到以太坊钱包并重试", + "use_testnet": "使用TestNet", + "address_and_silent_addresses": "地址和无声地址", + "silent_addresses": "无声地址" } diff --git a/scripts/android/app_icon.sh b/scripts/android/app_icon.sh index 9db01f227..af3ad478d 100755 --- a/scripts/android/app_icon.sh +++ b/scripts/android/app_icon.sh @@ -30,8 +30,12 @@ case $APP_ANDROID_TYPE in ;; esac -rm $APP_LOGO_DEST_PATH -rm $ANDROID_ICON_DEST_PATH +if [ ! -z "$APP_LOGO_DEST_PATH" ]; then + rm $APP_LOGO_DEST_PATH +fi +if [ ! -z "$ANDROID_ICON_DEST_PATH" ]; then + rm $ANDROID_ICON_DEST_PATH +fi ln -s $APP_LOGO $APP_LOGO_DEST_PATH ln -s $ANDROID_ICON $ANDROID_ICON_DEST_PATH cp -a $ANDROID_ICON_SET/. $ANDROID_ICON_SET_DEST_PATH/ diff --git a/scripts/linux/app_config.sh b/scripts/linux/app_config.sh index 6969418bd..6117b3589 100755 --- a/scripts/linux/app_config.sh +++ b/scripts/linux/app_config.sh @@ -8,6 +8,11 @@ if [ -z "$APP_LINUX_TYPE" ]; then exit 1 fi +../android/app_properties.sh +../android/app_icon.sh +../android/manifest.sh +../android/inject_app_details.sh + cd ../.. # go to root CONFIG_ARGS="" @@ -18,8 +23,8 @@ esac cp -rf pubspec_description.yaml pubspec.yaml flutter pub get -flutter pub run tool/generate_pubspec.dart +dart run tool/generate_pubspec.dart flutter pub get -flutter packages pub run tool/configure.dart $CONFIG_ARGS +dart run tool/configure.dart $CONFIG_ARGS sed -i '0,/version: 0.0.0/s//version: '"${APP_LINUX_VERSION}"'+'"${APP_LINUX_BUILD_NUMBER}"'/' pubspec.yaml cd $DIR diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh index d1a4fe720..278d2deb8 100755 --- a/scripts/linux/app_env.sh +++ b/scripts/linux/app_env.sh @@ -1,11 +1,11 @@ #!/bin/sh +source ../android/app_env.sh cakewallet + APP_LINUX_NAME="" APP_LINUX_VERSION="" APP_LINUX_BUILD_VERSION="" -CAKEWALLET="cakewallet" - TYPES=($CAKEWALLET) APP_LINUX_TYPE=$CAKEWALLET diff --git a/scripts/linux/gcc10.nix b/scripts/linux/gcc10.nix index bb68b00af..ebe418314 100644 --- a/scripts/linux/gcc10.nix +++ b/scripts/linux/gcc10.nix @@ -3,7 +3,8 @@ gcc10Stdenv.mkDerivation { name="gcc10-stdenv"; buildInputs = [ pkgs.cmake - pkgs.pkgconfig + pkgs.boost182 + pkgs.pkgconf pkgs.autoconf pkgs.libtool pkgs.expat diff --git a/tool/configure.dart b/tool/configure.dart index f5ab39251..930146f7f 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -75,6 +75,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as btc; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; const bitcoinContent = """ @@ -91,12 +92,15 @@ abstract class Bitcoin { TransactionPriority deserializeBitcoinTransactionPriority(int raw); TransactionPriority deserializeLitecoinTransactionPriority(int raw); int getFeeRate(Object wallet, TransactionPriority priority); - Future generateNewAddress(Object wallet); + Future generateNewAddress(Object wallet, {String? label}); Object createBitcoinTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}); Object createBitcoinTransactionCredentialsRaw(List outputs, {TransactionPriority? priority, required int feeRate}); List getAddresses(Object wallet); String getAddress(Object wallet); + String getReceiveAddress(Object wallet); + btc.SilentPaymentAddress? getSilentAddress(Object wallet); + List getSilentAddresses(Object wallet); String formatterBitcoinAmountToString({required int amount}); double formatterBitcoinAmountToDouble({required int amount}); @@ -1009,4 +1013,4 @@ class FakeSecureStorage extends SecureStorage { } await outputFile.writeAsString(output); -} \ No newline at end of file +}