diff --git a/assets/images/tbtc.png b/assets/images/tbtc.png new file mode 100644 index 000000000..bd4323edf Binary files /dev/null and b/assets/images/tbtc.png differ diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 3be7a8b67..e0218eff5 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -33,19 +33,21 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { List? initialSilentAddresses, int initialSilentAddressIndex = 0, }) : super( - mnemonic: mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - networkType: networkParam == null - ? bitcoin.bitcoin - : networkParam == BitcoinNetwork.mainnet - ? bitcoin.bitcoin - : bitcoin.testnet, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: seedBytes, - currency: CryptoCurrency.btc) { + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + networkType: networkParam == null + ? bitcoin.bitcoin + : networkParam == BitcoinNetwork.mainnet + ? bitcoin.bitcoin + : bitcoin.testnet, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: seedBytes, + currency: + networkParam == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc, + ) { walletAddresses = BitcoinWalletAddresses( walletInfo, initialAddresses: initialAddresses, diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index bea6c4957..5f6363c75 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -50,18 +50,24 @@ class ElectrumClient { String unterminatedString; Uri? uri; + bool? useSSL; - Future connectToUri(Uri uri) async { + Future connectToUri(Uri uri, {bool? useSSL}) async { this.uri = uri; - await connect(host: uri.host, port: uri.port); + this.useSSL = useSSL; + await connect(host: uri.host, port: uri.port, useSSL: useSSL); } - Future connect({required String host, required int port}) async { + Future connect({required String host, required int port, bool? useSSL}) async { try { await socket?.close(); } catch (_) {} - socket = await SecureSocket.connect(host, port, timeout: connectionTimeout); + if (useSSL == true) { + socket = await SecureSocket.connect(host, port, timeout: connectionTimeout); + } else { + socket = await Socket.connect(host, port, timeout: connectionTimeout); + } _setIsConnected(true); socket!.listen((Uint8List event) { diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 5a1cbda2f..4cd2d9f22 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -44,8 +44,6 @@ import 'package:http/http.dart' as http; part 'electrum_wallet.g.dart'; -const SCANNING_BLOCK_COUNT = 50; - class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet; abstract class ElectrumWalletBase @@ -89,6 +87,10 @@ abstract class ElectrumWalletBase this.electrumClient = electrumClient ?? ElectrumClient(); this.walletInfo = walletInfo; transactionHistory = ElectrumTransactionHistory(walletInfo: walletInfo, password: password); + + reaction((_) => syncStatus, (SyncStatus syncStatus) { + silentPaymentsScanningActive = syncStatus is SyncingSyncStatus; + }); } static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) => @@ -146,10 +148,10 @@ abstract class ElectrumWalletBase bool silentPaymentsScanningActive = false; @action - void setSilentPaymentsScanning(bool value) { - hasSilentPaymentsScanning = value; + void setSilentPaymentsScanning(bool active) { + silentPaymentsScanningActive = active; - if (value) { + if (active) { _setInitialHeight().then((_) { if ((currentChainTip ?? 0) > walletInfo.restoreHeight) { _setListeners(walletInfo.restoreHeight, chainTip: currentChainTip); @@ -218,16 +220,11 @@ abstract class ElectrumWalletBase chainTip: currentChainTip, electrumClient: ElectrumClient(), transactionHistoryIds: transactionHistory.transactions.keys.toList(), - node: electrumClient.uri.toString(), + node: node!, labels: walletAddresses.labels, )); await for (var message in receivePort) { - if (message is bool && message == false) { - nodeSupportsSilentPayments = message; - syncStatus = TimedOutSyncStatus(); - } - if (message is Map) { for (final map in message.entries) { final txid = map.key; @@ -274,6 +271,10 @@ abstract class ElectrumWalletBase // check if is a SyncStatus type since "is SyncStatus" doesn't work here if (message is SyncResponse) { + if (message.syncStatus is UnsupportedSyncStatus) { + nodeSupportsSilentPayments = false; + } + syncStatus = message.syncStatus; walletInfo.restoreHeight = message.height; await walletInfo.save(); @@ -316,11 +317,15 @@ abstract class ElectrumWalletBase } } + Node? node; + @action Future _electrumConnect(Node node, {bool? attemptedReconnect}) async { + this.node = node; + try { syncStatus = ConnectingSyncStatus(); - await electrumClient.connectToUri(node.uri); + await electrumClient.connectToUri(node.uri, useSSL: node.useSSL); electrumClient.onConnectionStatusChange = (bool isConnected) async { if (!isConnected) { syncStatus = LostConnectionSyncStatus(); @@ -346,6 +351,52 @@ abstract class ElectrumWalletBase bool _isBelowDust(int amount) => amount <= _getDustAmount() && network != BitcoinNetwork.testnet; + void _createSilentPayments( + List outputs, + List inputPubKeys, + List vinOutpoints, + List inputPrivKeyInfos, + ) { + List silentPaymentDestinations = []; + + for (final out in outputs) { + final address = out.address; + final amount = out.value; + + if (address is SilentPaymentAddress) { + silentPaymentDestinations.add( + SilentPaymentDestination.fromAddress(address.toAddress(network), amount.toInt()), + ); + } + } + + if (silentPaymentDestinations.isNotEmpty) { + final spb = SilentPaymentBuilder(pubkeys: inputPubKeys, outpoints: vinOutpoints); + final sendingOutputs = spb.createOutputs(inputPrivKeyInfos, silentPaymentDestinations); + + final outputsAdded = []; + + for (var i = 0; i < outputs.length; i++) { + final out = outputs[i]; + + final silentOutputs = sendingOutputs[out.address.toAddress(network)]; + if (silentOutputs != null) { + final silentOutput = + silentOutputs.firstWhereOrNull((element) => !outputsAdded.contains(element)); + + if (silentOutput != null) { + outputs[i] = BitcoinOutput( + address: silentOutput.address, + value: BigInt.from(silentOutput.amount), + ); + + outputsAdded.add(silentOutput); + } + } + } + } + } + Future estimateSendAllTx( List outputs, int feeRate, { @@ -416,6 +467,10 @@ abstract class ElectrumWalletBase throw BitcoinTransactionNoInputsException(); } + if (hasSilentPayment == true) { + _createSilentPayments(outputs, inputPubKeys, vinOutpoints, inputPrivKeyInfos); + } + int estimatedSize; if (network is BitcoinCashNetwork) { estimatedSize = ForkedTransactionBuilder.estimateTransactionSize( @@ -433,45 +488,6 @@ abstract class ElectrumWalletBase ); } - if (hasSilentPayment == true) { - List silentPaymentDestinations = []; - - for (final out in outputs) { - final address = out.address; - final amount = out.value; - - if (address is SilentPaymentAddress) { - final silentPaymentDestination = - SilentPaymentDestination.fromAddress(address.toAddress(network), amount.toInt()); - silentPaymentDestinations.add(silentPaymentDestination); - } - } - - final spb = SilentPaymentBuilder(pubkeys: inputPubKeys, outpoints: vinOutpoints); - final sendingOutputs = spb.createOutputs(inputPrivKeyInfos, silentPaymentDestinations); - - var outputsAdded = []; - - for (var i = 0; i < outputs.length; i++) { - final out = outputs[i]; - - final silentOutputs = sendingOutputs[out.address.toAddress(network)]; - if (silentOutputs != null) { - final silentOutput = - silentOutputs.firstWhereOrNull((element) => !outputsAdded.contains(element)); - - if (silentOutput != null) { - outputs[i] = BitcoinOutput( - address: silentOutput.address, - value: BigInt.from(silentOutput.amount), - ); - - outputsAdded.add(silentOutput); - } - } - } - } - int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize); if (fee == 0) { @@ -518,7 +534,9 @@ abstract class ElectrumWalletBase bool hasSilentPayment = false, }) async { final utxos = []; + List vinOutpoints = []; List inputPrivKeyInfos = []; + List inputPubKeys = []; int allInputsAmount = 0; bool spendsSilentPayment = false; @@ -553,6 +571,10 @@ abstract class ElectrumWalletBase ); } + inputPrivKeyInfos.add(ECPrivateInfo(privkey, address.type == SegwitAddresType.p2tr)); + inputPubKeys.add(privkey.getPublic()); + vinOutpoints.add(Outpoint(txid: utx.hash, index: utx.vout)); + utxos.add( UtxoWithAddress( utxo: BitcoinUtxo( @@ -579,6 +601,10 @@ abstract class ElectrumWalletBase throw BitcoinTransactionNoInputsException(); } + if (hasSilentPayment == true) { + _createSilentPayments(outputs, inputPubKeys, vinOutpoints, inputPrivKeyInfos); + } + final spendingAllCoins = sendingCoins.length == utxos.length; // How much is being spent - how much is being sent @@ -952,8 +978,10 @@ abstract class ElectrumWalletBase await transactionHistory.changePassword(password); } + @action @override Future rescan({required int height, int? chainTip, ScanData? scanData}) async { + silentPaymentsScanningActive = true; _setListeners(height); } @@ -1388,7 +1416,7 @@ class ScanData { final SendPort sendPort; final SilentPaymentOwner silentAddress; final int height; - final String node; + final Node node; final BasedUtxoNetwork network; final int chainTip; final ElectrumClient electrumClient; @@ -1436,7 +1464,7 @@ Future startRefresh(ScanData scanData) async { final electrumClient = scanData.electrumClient; if (!electrumClient.isConnected) { final node = scanData.node; - await electrumClient.connectToUri(Uri.parse(node)); + await electrumClient.connectToUri(node.uri, useSSL: node.useSSL); } return electrumClient; } @@ -1489,21 +1517,31 @@ Future startRefresh(ScanData scanData) async { try { final electrumClient = await getElectrumConnection(); + final scanningBlockCount = scanData.network == BitcoinNetwork.testnet ? 50 : 10; + Map? tweaks; try { - tweaks = await electrumClient.getTweaks(height: syncHeight, count: SCANNING_BLOCK_COUNT); + tweaks = await electrumClient.getTweaks(height: syncHeight, count: scanningBlockCount); } catch (e) { if (e is RequestFailedTimeoutException) { - return scanData.sendPort.send(false); + return scanData.sendPort.send( + SyncResponse(syncHeight, TimedOutSyncStatus()), + ); } } if (tweaks == null) { - scanData.sendPort.send(SyncResponse(syncHeight, - SyncingSyncStatus.fromHeightValues(currentChainTip, initialSyncHeight, syncHeight))); + return scanData.sendPort.send( + SyncResponse(syncHeight, UnsupportedSyncStatus()), + ); } - final blockHeights = tweaks!.keys; + if (tweaks.isEmpty) { + syncHeight += scanningBlockCount; + continue; + } + + final blockHeights = tweaks.keys; for (var i = 0; i < blockHeights.length; i++) { try { final blockHeight = blockHeights.elementAt(i).toString(); @@ -1515,81 +1553,83 @@ Future startRefresh(ScanData scanData) async { final outputPubkeys = (details["output_pubkeys"] as Map); final tweak = details["tweak"].toString(); - final spb = SilentPaymentBuilder(receiverTweak: tweak); - final addToWallet = spb.scanOutputs( - scanData.silentAddress.b_scan, - scanData.silentAddress.B_spend, - outputPubkeys.values - .map((o) => getScriptFromOutput( - o["pubkey"].toString(), int.parse(o["amount"].toString()))) - .toList(), - precomputedLabels: scanData.labels, - ); - - if (addToWallet.isEmpty) { - // no results tx, continue to next tx - continue; - } - - addToWallet.forEach((key, value) async { - final t_k = value.tweak; - - final addressRecord = BitcoinSilentPaymentAddressRecord( - value.output.address.toAddress(scanData.network), - index: 0, - isHidden: false, - isUsed: true, - network: scanData.network, - silentPaymentTweak: t_k, - type: SegwitAddresType.p2tr, + try { + final spb = SilentPaymentBuilder(receiverTweak: tweak); + final addToWallet = spb.scanOutputs( + scanData.silentAddress.b_scan, + scanData.silentAddress.B_spend, + outputPubkeys.values + .map((o) => getScriptFromOutput( + o["pubkey"].toString(), int.parse(o["amount"].toString()))) + .toList(), + precomputedLabels: scanData.labels, ); - int? amount; - int? pos; - outputPubkeys.entries.firstWhere((k) { - final matches = k.value["pubkey"] == key; - if (matches) { - amount = int.parse(k.value["amount"].toString()); - pos = int.parse(k.key.toString()); - return true; - } - return false; + if (addToWallet.isEmpty) { + // no results tx, continue to next tx + continue; + } + + addToWallet.forEach((key, value) async { + final t_k = value.tweak; + + final addressRecord = BitcoinSilentPaymentAddressRecord( + value.output.address.toAddress(scanData.network), + index: 0, + isHidden: false, + isUsed: true, + network: scanData.network, + silentPaymentTweak: t_k, + type: SegwitAddresType.p2tr, + ); + + int? amount; + int? pos; + outputPubkeys.entries.firstWhere((k) { + final matches = k.value["pubkey"] == key; + if (matches) { + amount = int.parse(k.value["amount"].toString()); + pos = int.parse(k.key.toString()); + return true; + } + return false; + }); + + final json = { + 'address_record': addressRecord.toJSON(), + 'tx_hash': txid, + 'value': amount!, + 'tx_pos': pos!, + 'silent_payment_tweak': t_k, + }; + + final tx = BitcoinUnspent.fromJSON(addressRecord, json); + + final txInfo = ElectrumTransactionInfo( + WalletType.bitcoin, + id: tx.hash, + height: syncHeight, + amount: 0, // will be added later via unspent + fee: 0, + direction: TransactionDirection.incoming, + isPending: false, + date: DateTime.now(), + confirmations: currentChainTip - syncHeight - 1, + to: value.label != null + ? SilentPaymentAddress( + version: scanData.silentAddress.version, + B_scan: scanData.silentAddress.B_scan.tweakAdd( + BigintUtils.fromBytes(BytesUtils.fromHexString(value.tweak))), + B_spend: scanData.silentAddress.B_spend, + hrp: scanData.silentAddress.hrp, + ).toString() + : scanData.silentAddress.toString(), + unspents: [tx], + ); + + scanData.sendPort.send({txInfo.id: txInfo}); }); - - final json = { - 'address_record': addressRecord.toJSON(), - 'tx_hash': txid, - 'value': amount!, - 'tx_pos': pos!, - 'silent_payment_tweak': t_k, - }; - - final tx = BitcoinUnspent.fromJSON(addressRecord, json); - - final txInfo = ElectrumTransactionInfo( - WalletType.bitcoin, - id: tx.hash, - height: syncHeight, - amount: 0, // will be added later via unspent - fee: 0, - direction: TransactionDirection.incoming, - isPending: false, - date: DateTime.now(), - confirmations: currentChainTip - syncHeight - 1, - to: value.label != null - ? SilentPaymentAddress( - version: scanData.silentAddress.version, - B_scan: scanData.silentAddress.B_scan - .tweakAdd(BigintUtils.fromBytes(BytesUtils.fromHexString(value.tweak))), - B_spend: scanData.silentAddress.B_spend, - hrp: scanData.silentAddress.hrp, - ).toString() - : scanData.silentAddress.toString(), - unspents: [tx], - ); - - scanData.sendPort.send({txInfo.id: txInfo}); - }); + } catch (_) {} } } catch (e, s) { print([e, s]); diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 50e7d8569..8d9b6101b 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -53,7 +53,7 @@ class ElectrumWalletSnapshot { .map((addr) => BitcoinSilentPaymentAddressRecord.fromJSON(addr, network: network)) .toList(); - final balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? + final balance = ElectrumBalance.fromJSON(data['balance'] as String?) ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; var changeAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index f1c1cd8ae..94dbeb61a 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -29,6 +29,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.bch, CryptoCurrency.bnb, CryptoCurrency.btc, + CryptoCurrency.tbtc, CryptoCurrency.dai, CryptoCurrency.dash, CryptoCurrency.eos, @@ -127,6 +128,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/images/bch_icon.png', decimals: 8); static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'Binance Coin', raw: 3, name: 'bnb', iconPath: 'assets/images/bnb_icon.png', decimals: 8); static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/images/btc.png', decimals: 8); + static const tbtc = CryptoCurrency(title: 'tBTC', fullName: 'Testnet Bitcoin', raw: 4, name: 'tbtc', iconPath: 'assets/images/tbtc.png', decimals: 8); static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/images/dai_icon.png', decimals: 18); static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png', decimals: 8); static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png', decimals: 4); diff --git a/cw_core/lib/currency_for_wallet_type.dart b/cw_core/lib/currency_for_wallet_type.dart index 58ee37669..1baca7b02 100644 --- a/cw_core/lib/currency_for_wallet_type.dart +++ b/cw_core/lib/currency_for_wallet_type.dart @@ -1,9 +1,12 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_type.dart'; -CryptoCurrency currencyForWalletType(WalletType type) { +CryptoCurrency currencyForWalletType(WalletType type, {bool? isTestnet}) { switch (type) { case WalletType.bitcoin: + if (isTestnet == true) { + return CryptoCurrency.tbtc; + } return CryptoCurrency.btc; case WalletType.monero: return CryptoCurrency.xmr; @@ -24,6 +27,7 @@ CryptoCurrency currencyForWalletType(WalletType type) { case WalletType.solana: return CryptoCurrency.sol; default: - throw Exception('Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType'); + throw Exception( + 'Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType'); } } diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 49f1bdc94..21b877989 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -24,7 +24,7 @@ abstract class WalletBase walletInfo.type; - CryptoCurrency get currency => currencyForWalletType(type); + CryptoCurrency get currency => currencyForWalletType(type, isTestnet: isTestnet); String get id => walletInfo.id; diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index a63ddf37c..9c7f6e0f9 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -161,11 +161,14 @@ String walletTypeToDisplayName(WalletType type) { } } -CryptoCurrency walletTypeToCryptoCurrency(WalletType type) { +CryptoCurrency walletTypeToCryptoCurrency(WalletType type, {bool isTestnet = false}) { switch (type) { case WalletType.monero: return CryptoCurrency.xmr; case WalletType.bitcoin: + if (isTestnet) { + return CryptoCurrency.tbtc; + } return CryptoCurrency.btc; case WalletType.litecoin: return CryptoCurrency.ltc; diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 8341b76e2..e623957d6 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -264,6 +264,8 @@ class CWBitcoin extends Bitcoin { return (option as BitcoinReceivePageOption).toType(); } + @override + @computed bool getScanningActive(Object wallet) { final bitcoinWallet = wallet as ElectrumWallet; return bitcoinWallet.silentPaymentsScanningActive; @@ -273,4 +275,9 @@ class CWBitcoin extends Bitcoin { final bitcoinWallet = wallet as ElectrumWallet; bitcoinWallet.setSilentPaymentsScanning(active); } + + bool isTestnet(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.isTestnet ?? false; + } } diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index 8bda1834a..2c77ffcea 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -211,10 +211,12 @@ class CryptoBalanceWidget extends StatelessWidget { dashboardViewModel.balanceViewModel.hasAdditionalBalance, hasSilentPayments: dashboardViewModel.balanceViewModel.hasSilentPayments, silentPaymentsScanningActive: - dashboardViewModel.balanceViewModel.silentPaymentsScanningActive, - setSilentPaymentsScanning: () => dashboardViewModel.balanceViewModel - .setSilentPaymentsScanning( - !dashboardViewModel.balanceViewModel.silentPaymentsScanningActive), + dashboardViewModel.silentPaymentsScanningActive, + setSilentPaymentsScanning: () => + dashboardViewModel.setSilentPaymentsScanning( + !dashboardViewModel.silentPaymentsScanningActive, + ), + isTestnet: dashboardViewModel.isTestnet, ); }); }, @@ -243,6 +245,7 @@ class BalanceRowWidget extends StatelessWidget { required this.hasSilentPayments, required this.silentPaymentsScanningActive, required this.setSilentPaymentsScanning, + required this.isTestnet, super.key, }); @@ -258,6 +261,7 @@ class BalanceRowWidget extends StatelessWidget { final bool hasAdditionalBalance; final bool hasSilentPayments; final bool silentPaymentsScanningActive; + final bool isTestnet; final void Function() setSilentPaymentsScanning; // void _showBalanceDescription(BuildContext context) { @@ -333,14 +337,24 @@ class BalanceRowWidget extends StatelessWidget { maxLines: 1, textAlign: TextAlign.start), SizedBox(height: 6), - Text('${availableFiatBalance}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontFamily: 'Lato', - fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.textColor, - height: 1)), + if (isTestnet) + Text(S.current.testnet_coins_no_value, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1)), + if (!isTestnet) + Text('${availableFiatBalance}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.textColor, + height: 1)), ], ), ), @@ -432,17 +446,18 @@ class BalanceRowWidget extends StatelessWidget { textAlign: TextAlign.center, ), SizedBox(height: 4), - Text( - frozenFiatBalance, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1, + if (!isTestnet) + Text( + frozenFiatBalance, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1, + ), ), - ), ], ), ), @@ -476,17 +491,18 @@ class BalanceRowWidget extends StatelessWidget { textAlign: TextAlign.center, ), SizedBox(height: 4), - Text( - '${additionalFiatBalance}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1, + if (!isTestnet) + Text( + '${additionalFiatBalance}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1, + ), ), - ), ], ), if (hasSilentPayments) ...[ diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart index ab8dcafdf..e4f32b0d9 100644 --- a/lib/src/screens/nodes/widgets/node_form.dart +++ b/lib/src/screens/nodes/widgets/node_form.dart @@ -19,7 +19,7 @@ class NodeForm extends StatelessWidget { _portController = TextEditingController(text: editingNode?.uri.port.toString()), _loginController = TextEditingController(text: editingNode?.login), _passwordController = TextEditingController(text: editingNode?.password), - _socksAddressController = TextEditingController(text: editingNode?.socksProxyAddress){ + _socksAddressController = TextEditingController(text: editingNode?.socksProxyAddress) { if (editingNode != null) { nodeViewModel ..setAddress((editingNode!.uri.host.toString())) @@ -60,7 +60,8 @@ class NodeForm extends StatelessWidget { _portController.addListener(() => nodeViewModel.port = _portController.text); _loginController.addListener(() => nodeViewModel.login = _loginController.text); _passwordController.addListener(() => nodeViewModel.password = _passwordController.text); - _socksAddressController.addListener(() => nodeViewModel.socksProxyAddress = _socksAddressController.text); + _socksAddressController + .addListener(() => nodeViewModel.socksProxyAddress = _socksAddressController.text); } final NodeCreateOrEditViewModel nodeViewModel; @@ -103,6 +104,25 @@ class NodeForm extends StatelessWidget { ], ), SizedBox(height: 10.0), + Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Observer( + builder: (_) => StandardCheckbox( + value: nodeViewModel.useSSL, + gradientBackground: true, + borderColor: Theme.of(context).dividerColor, + iconColor: Colors.white, + onChanged: (value) => nodeViewModel.useSSL = value, + caption: S.of(context).use_ssl, + ), + ) + ], + ), + ), if (nodeViewModel.hasAuthCredentials) ...[ Row( children: [ @@ -123,25 +143,6 @@ class NodeForm extends StatelessWidget { )) ], ), - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Observer( - builder: (_) => StandardCheckbox( - value: nodeViewModel.useSSL, - gradientBackground: true, - borderColor: Theme.of(context).dividerColor, - iconColor: Colors.white, - onChanged: (value) => nodeViewModel.useSSL = value, - caption: S.of(context).use_ssl, - ), - ) - ], - ), - ), Padding( padding: EdgeInsets.only(top: 20), child: Row( @@ -163,44 +164,44 @@ class NodeForm extends StatelessWidget { ), Observer( builder: (_) => Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - StandardCheckbox( - value: nodeViewModel.useSocksProxy, - gradientBackground: true, - borderColor: Theme.of(context).dividerColor, - iconColor: Colors.white, - onChanged: (value) { - if (!value) { - _socksAddressController.text = ''; - } - nodeViewModel.useSocksProxy = value; - }, - caption: 'SOCKS Proxy', - ), - ], - ), - ), - if (nodeViewModel.useSocksProxy) ...[ - SizedBox(height: 10.0), - Row( - children: [ - Expanded( - child: BaseTextFormField( + children: [ + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + StandardCheckbox( + value: nodeViewModel.useSocksProxy, + gradientBackground: true, + borderColor: Theme.of(context).dividerColor, + iconColor: Colors.white, + onChanged: (value) { + if (!value) { + _socksAddressController.text = ''; + } + nodeViewModel.useSocksProxy = value; + }, + caption: 'SOCKS Proxy', + ), + ], + ), + ), + if (nodeViewModel.useSocksProxy) ...[ + SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( controller: _socksAddressController, hintText: '[:]', validator: SocksProxyNodeAddressValidator(), )) - ], - ), - ] - ], - )), + ], + ), + ] + ], + )), ] ], ), diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 3f3e546b3..e856d3200 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -102,7 +102,7 @@ class ReceivePage extends BasePage { return (addressListViewModel.type == WalletType.monero || addressListViewModel.type == WalletType.haven || addressListViewModel.type == WalletType.nano || - isElectrumWallet) + isElectrumWallet) ? KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, @@ -164,21 +164,21 @@ class ReceivePage extends BasePage { } if (item is WalletAddressListHeader) { - cell = HeaderTile( - title: S.of(context).addresses, - walletAddressListViewModel: addressListViewModel, - showTrailingButton: !addressListViewModel.isAutoGenerateSubaddressEnabled, - showSearchButton: true, - trailingButtonTap: () => - Navigator.of(context).pushNamed(Routes.newSubaddress), - trailingIcon: Icon( - Icons.add, - size: 20, - color: Theme.of(context) - .extension()! - .iconsColor, - )); - } + cell = HeaderTile( + title: S.of(context).addresses, + walletAddressListViewModel: addressListViewModel, + showTrailingButton: + !addressListViewModel.isAutoGenerateSubaddressEnabled, + showSearchButton: true, + trailingButtonTap: () => + Navigator.of(context).pushNamed(Routes.newSubaddress), + trailingIcon: Icon( + Icons.add, + size: 20, + color: + Theme.of(context).extension()!.iconsColor, + )); + } if (item is WalletAddressListItem) { cell = Observer(builder: (_) { @@ -219,7 +219,7 @@ class ReceivePage extends BasePage { child: cell, ); })), - if (!addressListViewModel.hasSilentAddresses) + if (!addressListViewModel.isSilentPayments) Padding( padding: EdgeInsets.fromLTRB(24, 24, 24, 32), child: Text(S.of(context).electrum_address_disclaimer, diff --git a/lib/src/screens/rescan/rescan_page.dart b/lib/src/screens/rescan/rescan_page.dart index 3a0ba2473..f4dc865f0 100644 --- a/lib/src/screens/rescan/rescan_page.dart +++ b/lib/src/screens/rescan/rescan_page.dart @@ -11,7 +11,8 @@ class RescanPage extends BasePage { : _blockchainHeightWidgetKey = GlobalKey(); @override - String get title => S.current.rescan; + String get title => + _rescanViewModel.isSilentPaymentsScan ? S.current.silent_payments_scanning : S.current.rescan; final GlobalKey _blockchainHeightWidgetKey; final RescanViewModel _rescanViewModel; @@ -19,20 +20,19 @@ class RescanPage extends BasePage { Widget body(BuildContext context) { return Padding( padding: EdgeInsets.only(left: 24, right: 24, bottom: 24), - child: - Column(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - BlockchainHeightWidget(key: _blockchainHeightWidgetKey, - onHeightOrDateEntered: (value) => - _rescanViewModel.isButtonEnabled = value), + child: Column(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + BlockchainHeightWidget( + key: _blockchainHeightWidgetKey, + onHeightOrDateEntered: (value) => _rescanViewModel.isButtonEnabled = value, + isSilentPaymentsScan: _rescanViewModel.isSilentPaymentsScan, + ), Observer( builder: (_) => LoadingPrimaryButton( - isLoading: - _rescanViewModel.state == RescanWalletState.rescaning, + isLoading: _rescanViewModel.state == RescanWalletState.rescaning, text: S.of(context).rescan, onPressed: () async { await _rescanViewModel.rescanCurrentWallet( - restoreHeight: - _blockchainHeightWidgetKey.currentState!.height); + restoreHeight: _blockchainHeightWidgetKey.currentState!.height); Navigator.of(context).pop(); }, color: Theme.of(context).primaryColor, diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 685310506..d36997814 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -2,7 +2,6 @@ import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -167,7 +166,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin Navigator.of(context).pushNamed(Routes.rescan), ), if (DeviceInfo.instance.isMobile && FeatureFlag.isBackgroundSyncEnabled) ...[ diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index b57473cba..2029b9f48 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -96,6 +96,7 @@ class WalletListBody extends StatefulWidget { class WalletListBodyState extends State { final moneroIcon = Image.asset('assets/images/monero_logo.png', height: 24, width: 24); final bitcoinIcon = Image.asset('assets/images/bitcoin.png', height: 24, width: 24); + final tBitcoinIcon = Image.asset('assets/images/tbtc.png', height: 24, width: 24); final litecoinIcon = Image.asset('assets/images/litecoin_icon.png', height: 24, width: 24); final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24); final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24); @@ -161,7 +162,10 @@ class WalletListBodyState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ wallet.isEnabled - ? _imageFor(type: wallet.type) + ? _imageFor( + type: wallet.type, + isTestnet: wallet.isTestnet, + ) : nonWalletTypeIcon, SizedBox(width: 10), Flexible( @@ -296,9 +300,12 @@ class WalletListBodyState extends State { ); } - Image _imageFor({required WalletType type}) { + Image _imageFor({required WalletType type, bool? isTestnet}) { switch (type) { case WalletType.bitcoin: + if (isTestnet == true) { + return tBitcoinIcon; + } return bitcoinIcon; case WalletType.monero: return moneroIcon; diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index f98e0439b..0467b18a2 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -1,6 +1,5 @@ import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/utils/device_info.dart'; -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/services.dart'; import 'package:flutter/material.dart'; @@ -134,7 +133,8 @@ class AddressTextField extends StatelessWidget { ), )), ], - if (this.options.contains(AddressTextFieldOption.qrCode)) ...[ + if (this.options.contains(AddressTextFieldOption.qrCode) && + DeviceInfo.instance.isMobile) ...[ Container( width: prefixIconWidth, height: prefixIconHeight, @@ -194,7 +194,7 @@ class AddressTextField extends StatelessWidget { Future _presentQRScanner(BuildContext context) async { bool isCameraPermissionGranted = - await PermissionHandler.checkPermission(Permission.camera, context); + await PermissionHandler.checkPermission(Permission.camera, context); if (!isCameraPermissionGranted) return; final code = await presentQRScanner(); if (code.isEmpty) { diff --git a/lib/src/widgets/blockchain_height_widget.dart b/lib/src/widgets/blockchain_height_widget.dart index 221f87446..fcfeedda3 100644 --- a/lib/src/widgets/blockchain_height_widget.dart +++ b/lib/src/widgets/blockchain_height_widget.dart @@ -12,13 +12,15 @@ class BlockchainHeightWidget extends StatefulWidget { this.onHeightChange, this.focusNode, this.onHeightOrDateEntered, - this.hasDatePicker = true}) - : super(key: key); + this.hasDatePicker = true, + this.isSilentPaymentsScan = false, + }) : super(key: key); final Function(int)? onHeightChange; final Function(bool)? onHeightOrDateEntered; final FocusNode? focusNode; final bool hasDatePicker; + final bool isSilentPaymentsScan; @override State createState() => BlockchainHeightState(); @@ -64,9 +66,10 @@ class BlockchainHeightState extends State { child: BaseTextFormField( focusNode: widget.focusNode, controller: restoreHeightController, - keyboardType: TextInputType.numberWithOptions( - signed: false, decimal: false), - hintText: S.of(context).widgets_restore_from_blockheight, + keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false), + hintText: widget.isSilentPaymentsScan + ? S.of(context).silent_payments_scan_from_height + : S.of(context).widgets_restore_from_blockheight, ))) ], ), @@ -78,8 +81,7 @@ class BlockchainHeightState extends State { style: TextStyle( fontSize: 16.0, fontWeight: FontWeight.w500, - color: - Theme.of(context).extension()!.titleColor), + color: Theme.of(context).extension()!.titleColor), ), ), Row( @@ -91,7 +93,9 @@ class BlockchainHeightState extends State { child: IgnorePointer( child: BaseTextFormField( controller: dateController, - hintText: S.of(context).widgets_restore_from_date, + hintText: widget.isSilentPaymentsScan + ? S.of(context).silent_payments_scan_from_date + : S.of(context).widgets_restore_from_date, )), ), )) @@ -100,13 +104,12 @@ class BlockchainHeightState extends State { Padding( padding: EdgeInsets.only(left: 40, right: 40, top: 24), child: Text( - S.of(context).restore_from_date_or_blockheight, + widget.isSilentPaymentsScan + ? S.of(context).silent_payments_scan_from_date_or_blockheight + : S.of(context).restore_from_date_or_blockheight, textAlign: TextAlign.center, style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.normal, - color: Theme.of(context).hintColor - ), + fontSize: 12, fontWeight: FontWeight.normal, color: Theme.of(context).hintColor), ), ) ] diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 08bdd8252..d72b33903 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -46,8 +46,6 @@ abstract class BalanceViewModelBase with Store { : isReversing = false, isShowCard = appStore.wallet!.walletInfo.isShowIntroCakePayCard, wallet = appStore.wallet! { - silentPaymentsScanningActive = hasSilentPayments && bitcoin!.getScanningActive(wallet); - reaction((_) => appStore.wallet, _onWalletChange); } @@ -66,17 +64,6 @@ abstract class BalanceViewModelBase with Store { @computed bool get hasSilentPayments => wallet.type == WalletType.bitcoin; - @observable - bool silentPaymentsScanningActive = false; - - @action - void setSilentPaymentsScanning(bool active) { - if (hasSilentPayments) { - bitcoin!.setScanningActive(wallet, active); - silentPaymentsScanningActive = active; - } - } - @computed double get price { final price = fiatConvertationStore.prices[appStore.wallet!.currency]; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index b08a0c3c7..b4cd026fe 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -201,6 +201,14 @@ abstract class DashboardViewModelBase with Store { return true; }); + + if (hasSilentPayments) { + silentPaymentsScanningActive = bitcoin!.getScanningActive(wallet); + + reaction((_) => wallet.syncStatus, (SyncStatus syncStatus) { + silentPaymentsScanningActive = bitcoin!.getScanningActive(wallet); + }); + } } @observable @@ -287,14 +295,33 @@ abstract class DashboardViewModelBase with Store { @observable WalletBase, TransactionInfo> wallet; + @computed + bool get isTestnet => wallet.type == WalletType.bitcoin && bitcoin!.isTestnet(wallet); + + @computed bool get hasRescan => - (wallet.type == WalletType.bitcoin && bitcoin!.hasSelectedSilentPayments(wallet)) || + wallet.type == WalletType.bitcoin || wallet.type == WalletType.monero || wallet.type == WalletType.haven; + @computed + bool get hasSilentPayments => hasRescan && wallet.type == WalletType.bitcoin; + final KeyService keyService; final SharedPreferences sharedPreferences; + @observable + bool silentPaymentsScanningActive = false; + + @action + void setSilentPaymentsScanning(bool active) { + silentPaymentsScanningActive = active; + + if (hasSilentPayments) { + bitcoin!.setScanningActive(wallet, active); + } + } + BalanceViewModel balanceViewModel; AppStore appStore; diff --git a/lib/view_model/rescan_view_model.dart b/lib/view_model/rescan_view_model.dart index e263f4a12..b10e29e69 100644 --- a/lib/view_model/rescan_view_model.dart +++ b/lib/view_model/rescan_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -21,6 +22,9 @@ abstract class RescanViewModelBase with Store { @observable bool isButtonEnabled; + @computed + bool get isSilentPaymentsScan => bitcoin!.hasSelectedSilentPayments(_wallet); + @action Future rescanCurrentWallet({required int restoreHeight}) async { state = RescanWalletState.rescaning; 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 5e843ad78..c1c275a87 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 @@ -183,6 +183,8 @@ 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, amount = '', _settingsStore = appStore.settingsStore, super(appStore: appStore) { @@ -194,8 +196,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo _init(); selectedCurrency = walletTypeToCryptoCurrency(wallet.type); - _hasAccounts = - hasSilentAddresses || wallet.type == WalletType.monero || wallet.type == WalletType.haven; + hasAccounts = wallet.type == WalletType.monero || wallet.type == WalletType.haven; } static const String _cryptoNumberPattern = '0.00000000'; @@ -364,10 +365,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo } @observable - bool _hasAccounts = false; - - @computed - bool get hasAccounts => _hasAccounts; + bool hasAccounts; @computed String get accountLabel { @@ -382,21 +380,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return ''; } - @observable - // ignore: prefer_final_fields - bool? _hasSilentAddresses = null; - - @computed - bool get hasSilentAddresses => _hasSilentAddresses ?? wallet.type == WalletType.bitcoin; - // @computed - // bool get hasSilentAddresses => - // _hasSilentAddresses ?? - // wallet.type == WalletType.bitcoin && - // wallet.walletAddresses.addressPageType == btc.AddressType.p2sp; - @computed bool get hasAddressList => - hasSilentAddresses || wallet.type == WalletType.monero || wallet.type == WalletType.haven || wallet.type == WalletType.bitcoinCash || @@ -409,9 +394,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash; + @computed + bool get isSilentPayments => bitcoin!.hasSelectedSilentPayments(wallet); + @computed bool get isAutoGenerateSubaddressEnabled => wallet.type == WalletType.bitcoin - ? !bitcoin!.hasSelectedSilentPayments(wallet) + ? !isSilentPayments : _settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled; List _baseItems; diff --git a/lib/view_model/wallet_list/wallet_list_item.dart b/lib/view_model/wallet_list/wallet_list_item.dart index a644c07b3..24b1a3bd0 100644 --- a/lib/view_model/wallet_list/wallet_list_item.dart +++ b/lib/view_model/wallet_list/wallet_list_item.dart @@ -7,6 +7,7 @@ class WalletListItem { required this.key, this.isCurrent = false, this.isEnabled = true, + this.isTestnet = false, }); final String name; @@ -14,4 +15,5 @@ class WalletListItem { final bool isCurrent; final dynamic key; final bool isEnabled; + final bool isTestnet; } diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart index b31133c7d..2ed6358f4 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -61,6 +61,7 @@ abstract class WalletListViewModelBase with Store { key: info.key, isCurrent: info.name == _appStore.wallet?.name && info.type == _appStore.wallet?.type, isEnabled: availableWalletTypes.contains(info.type), + isTestnet: info.network?.toLowerCase().contains('testnet') ?? false, ), ), ); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index a66f85da4..067a50ca8 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -610,6 +610,9 @@ "sign_up": "اشتراك", "signTransaction": " ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ", "signup_for_card_accept_terms": "قم بالتسجيل للحصول على البطاقة وقبول الشروط.", + "silent_payments_scan_from_date": "فحص من التاريخ", + "silent_payments_scan_from_date_or_blockheight": "يرجى إدخال ارتفاع الكتلة الذي تريد بدء المسح الضوئي للمدفوعات الصامتة الواردة ، أو استخدام التاريخ بدلاً من ذلك. يمكنك اختيار ما إذا كانت المحفظة تواصل مسح كل كتلة ، أو تتحقق فقط من الارتفاع المحدد.", + "silent_payments_scan_from_height": "فحص من ارتفاع الكتلة", "silent_payments_scanning": "المدفوعات الصامتة المسح الضوئي", "slidable": "قابل للانزلاق", "sort_by": "ترتيب حسب", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "محفظتك تتم مزامنتها", "template": "قالب", "template_name": "اسم القالب", + "testnet_coins_no_value": "عملات TestNet ليس لها قيمة", "third_intro_content": "يعيش Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة على وجه الأرض بـ Yat!", "third_intro_title": "يتماشي Yat بلطف مع الآخرين", "thorchain_taproot_address_not_supported": "لا يدعم مزود Thorchain عناوين Taproot. يرجى تغيير العنوان أو تحديد مزود مختلف.", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index cc48a56e9..626ed5ae8 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -610,6 +610,9 @@ "sign_up": "Регистрация", "signTransaction": "Подпишете транзакция", "signup_for_card_accept_terms": "Регистрайте се за картата и приемете условията.", + "silent_payments_scan_from_date": "Сканиране от дата", + "silent_payments_scan_from_date_or_blockheight": "Моля, въведете височината на блока, която искате да започнете да сканирате за входящи безшумни плащания, или вместо това използвайте датата. Можете да изберете дали портфейлът продължава да сканира всеки блок или проверява само определената височина.", + "silent_payments_scan_from_height": "Сканиране от височината на блока", "silent_payments_scanning": "Безшумни плащания за сканиране", "slidable": "Плъзгащ се", "sort_by": "Сортирай по", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Вашият портфейл се синхронизира", "template": "Шаблон", "template_name": "Име на шаблон", + "testnet_coins_no_value": "Тестовите монети нямат стойност", "third_intro_content": "Yats също живее извън Cake Wallet. Всеки адрес на портфейл може да бъде заменен с Yat!", "third_intro_title": "Yat добре се сработва с други", "thorchain_taproot_address_not_supported": "Доставчикът на Thorchain не поддържа адреси на TapRoot. Моля, променете адреса или изберете друг доставчик.", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index f3076cf6c..0e4253cca 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -610,6 +610,9 @@ "sign_up": "Registrovat se", "signTransaction": "Podepsat transakci", "signup_for_card_accept_terms": "Zaregistrujte se pro kartu a souhlaste s podmínkami.", + "silent_payments_scan_from_date": "Skenovat od data", + "silent_payments_scan_from_date_or_blockheight": "Zadejte výšku bloku, kterou chcete začít skenovat, zda jsou přicházející tiché platby, nebo místo toho použijte datum. Můžete si vybrat, zda peněženka pokračuje v skenování každého bloku nebo zkontroluje pouze zadanou výšku.", + "silent_payments_scan_from_height": "Skenování z výšky bloku", "silent_payments_scanning": "Skenování tichých plateb", "slidable": "Posuvné", "sort_by": "Seřazeno podle", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Vaše peněženka se synchronizuje", "template": "Šablona", "template_name": "Název šablony", + "testnet_coins_no_value": "Mince TestNet nemají žádnou hodnotu", "third_intro_content": "Yat existuje i mimo Cake Wallet. Jakákoliv adresa peněženky na světě může být nahrazena Yatem!", "third_intro_title": "Yat dobře spolupracuje s ostatními", "thorchain_taproot_address_not_supported": "Poskytovatel Thorchain nepodporuje adresy Taproot. Změňte adresu nebo vyberte jiného poskytovatele.", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index cf4cbb7fa..b6f9d475c 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -611,6 +611,9 @@ "sign_up": "Anmelden", "signTransaction": "Transaktion unterzeichnen", "signup_for_card_accept_terms": "Melden Sie sich für die Karte an und akzeptieren Sie die Bedingungen.", + "silent_payments_scan_from_date": "Scan ab Datum", + "silent_payments_scan_from_date_or_blockheight": "Bitte geben Sie die Blockhöhe ein, die Sie für eingehende stille Zahlungen scannen möchten, oder verwenden Sie stattdessen das Datum. Sie können wählen, ob die Brieftasche jeden Block scannt oder nur die angegebene Höhe überprüft.", + "silent_payments_scan_from_height": "Scan aus der Blockhöhe scannen", "silent_payments_scanning": "Stille Zahlungen scannen", "slidable": "Verschiebbar", "sort_by": "Sortiere nach", @@ -647,6 +650,7 @@ "syncing_wallet_alert_title": "Ihr Wallet wird synchronisiert", "template": "Vorlage", "template_name": "Vorlagenname", + "testnet_coins_no_value": "Testnet -Münzen haben keinen Wert", "third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!", "third_intro_title": "Yat spielt gut mit anderen", "thorchain_taproot_address_not_supported": "Der Thorchain -Anbieter unterstützt keine Taproot -Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index d31435b48..97546bf88 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -610,6 +610,9 @@ "sign_up": "Sign Up", "signTransaction": "Sign Transaction", "signup_for_card_accept_terms": "Sign up for the card and accept the terms.", + "silent_payments_scan_from_date": "Scan from date", + "silent_payments_scan_from_date_or_blockheight": "Please enter the block height you want to start scanning for incoming silent payments, or, use the date instead. You can choose if the wallet continues scanning every block, or checks only the specified height.", + "silent_payments_scan_from_height": "Scan from block height", "silent_payments_scanning": "Silent Payments Scanning", "slidable": "Slidable", "sort_by": "Sort by", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Your wallet is syncing", "template": "Template", "template_name": "Template Name", + "testnet_coins_no_value": "Testnet coins have no value", "third_intro_content": "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!", "third_intro_title": "Yat plays nicely with others", "thorchain_taproot_address_not_supported": "The ThorChain provider does not support Taproot addresses. Please change the address or select a different provider.", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 6aa1cfbd8..2791de8d6 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -611,6 +611,9 @@ "sign_up": "Registrarse", "signTransaction": "Firmar transacción", "signup_for_card_accept_terms": "Regístrese para obtener la tarjeta y acepte los términos.", + "silent_payments_scan_from_date": "Escanear desde la fecha", + "silent_payments_scan_from_date_or_blockheight": "Ingrese la altura del bloque que desea comenzar a escanear para pagos silenciosos entrantes, o use la fecha en su lugar. Puede elegir si la billetera continúa escaneando cada bloque, o verifica solo la altura especificada.", + "silent_payments_scan_from_height": "Escanear desde la altura del bloque", "silent_payments_scanning": "Escaneo de pagos silenciosos", "slidable": "deslizable", "sort_by": "Ordenar por", @@ -647,6 +650,7 @@ "syncing_wallet_alert_title": "Tu billetera se está sincronizando", "template": "Plantilla", "template_name": "Nombre de la plantilla", + "testnet_coins_no_value": "Las monedas de prueba no tienen valor", "third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!", "third_intro_title": "Yat juega muy bien con otras", "thorchain_taproot_address_not_supported": "El proveedor de Thorchain no admite las direcciones de Taproot. Cambie la dirección o seleccione un proveedor diferente.", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 7b7ce56df..50772e112 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -610,6 +610,9 @@ "sign_up": "S'inscrire", "signTransaction": "Signer une transaction", "signup_for_card_accept_terms": "Inscrivez-vous pour la carte et acceptez les conditions.", + "silent_payments_scan_from_date": "Analyser à partir de la date", + "silent_payments_scan_from_date_or_blockheight": "Veuillez saisir la hauteur du bloc que vous souhaitez commencer à scanner pour les paiements silencieux entrants, ou utilisez la date à la place. Vous pouvez choisir si le portefeuille continue de numériser chaque bloc ou ne vérifie que la hauteur spécifiée.", + "silent_payments_scan_from_height": "Scan à partir de la hauteur du bloc", "silent_payments_scanning": "Payments silencieux SCANNING", "slidable": "Glissable", "sort_by": "Trier par", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Votre portefeuille (wallet) est en cours de synchronisation", "template": "Modèle", "template_name": "Nom du modèle", + "testnet_coins_no_value": "Les pièces TestNet n'ont aucune valeur", "third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !", "third_intro_title": "Yat est universel", "thorchain_taproot_address_not_supported": "Le fournisseur de Thorchain ne prend pas en charge les adresses de tapoot. Veuillez modifier l'adresse ou sélectionner un autre fournisseur.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 6c3de1e03..6c8a9fabe 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -612,6 +612,9 @@ "sign_up": "Shiga", "signTransaction": "Sa hannu Ma'amala", "signup_for_card_accept_terms": "Yi rajista don katin kuma karɓi sharuɗɗan.", + "silent_payments_scan_from_date": "Scan daga kwanan wata", + "silent_payments_scan_from_date_or_blockheight": "Da fatan za a shigar da toshe wurin da kake son fara bincika don biyan silins mai shigowa, ko, yi amfani da kwanan wata. Zaka iya zabar idan walat ɗin ya ci gaba da bincika kowane toshe, ko duba tsinkaye da aka ƙayyade.", + "silent_payments_scan_from_height": "Scan daga tsayin daka", "silent_payments_scanning": "Silent biya scanning", "slidable": "Mai iya zamewa", "sort_by": "Kasa", @@ -648,6 +651,7 @@ "syncing_wallet_alert_title": "Walat ɗin ku yana aiki tare", "template": "Samfura", "template_name": "Sunan Samfura", + "testnet_coins_no_value": "TalkNet tsabar kudi ba su da darajar", "third_intro_content": "Yats suna zaune a wajen Kek Wallet, kuma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!", "third_intro_title": "Yat yana wasa da kyau tare da wasu", "thorchain_taproot_address_not_supported": "Mai ba da tallafi na ThorChain baya goyan bayan adreshin taproot. Da fatan za a canza adireshin ko zaɓi mai bayarwa daban.", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 82445dfa3..8fb2ea081 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -612,6 +612,9 @@ "sign_up": "साइन अप करें", "signTransaction": "लेन-देन पर हस्ताक्षर करें", "signup_for_card_accept_terms": "कार्ड के लिए साइन अप करें और शर्तें स्वीकार करें।", + "silent_payments_scan_from_date": "तिथि से स्कैन करना", + "silent_payments_scan_from_date_or_blockheight": "कृपया उस ब्लॉक ऊंचाई दर्ज करें जिसे आप आने वाले मूक भुगतान के लिए स्कैन करना शुरू करना चाहते हैं, या, इसके बजाय तारीख का उपयोग करें। आप चुन सकते हैं कि क्या वॉलेट हर ब्लॉक को स्कैन करना जारी रखता है, या केवल निर्दिष्ट ऊंचाई की जांच करता है।", + "silent_payments_scan_from_height": "ब्लॉक ऊंचाई से स्कैन करें", "silent_payments_scanning": "मूक भुगतान स्कैनिंग", "slidable": "फिसलने लायक", "sort_by": "इसके अनुसार क्रमबद्ध करें", @@ -648,6 +651,7 @@ "syncing_wallet_alert_title": "आपका वॉलेट सिंक हो रहा है", "template": "खाका", "template_name": "टेम्पलेट नाम", + "testnet_coins_no_value": "टेस्टनेट सिक्कों का कोई मूल्य नहीं है", "third_intro_content": "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!", "third_intro_title": "Yat दूसरों के साथ अच्छा खेलता है", "thorchain_taproot_address_not_supported": "थोरचेन प्रदाता टैपरोट पते का समर्थन नहीं करता है। कृपया पता बदलें या एक अलग प्रदाता का चयन करें।", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4c64a9a34..df1b1ce11 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -610,6 +610,9 @@ "sign_up": "Prijavite se", "signTransaction": "Potpišite transakciju", "signup_for_card_accept_terms": "Prijavite se za karticu i prihvatite uvjete.", + "silent_payments_scan_from_date": "Skeniranje iz datuma", + "silent_payments_scan_from_date_or_blockheight": "Unesite visinu bloka koju želite započeti skeniranje za dolazna tiha plaćanja ili umjesto toga upotrijebite datum. Možete odabrati da li novčanik nastavlja skenirati svaki blok ili provjerava samo navedenu visinu.", + "silent_payments_scan_from_height": "Skeniranje s visine bloka", "silent_payments_scanning": "Skeniranje tihih plaćanja", "slidable": "Klizna", "sort_by": "Poredaj po", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Vaš novčanik se sinkronizira", "template": "Predložak", "template_name": "Naziv predloška", + "testnet_coins_no_value": "TestNet kovanice nemaju vrijednost", "third_intro_content": "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!", "third_intro_title": "Yat se lijepo igra s drugima", "thorchain_taproot_address_not_supported": "Thorchain pružatelj ne podržava Taproot adrese. Promijenite adresu ili odaberite drugog davatelja usluga.", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 90a92a8f2..32d0a997a 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -613,6 +613,9 @@ "sign_up": "Daftar", "signTransaction": "Tandatangani Transaksi", "signup_for_card_accept_terms": "Daftar untuk kartu dan terima syarat dan ketentuan.", + "silent_payments_scan_from_date": "Pindai dari tanggal", + "silent_payments_scan_from_date_or_blockheight": "Harap masukkan ketinggian blok yang ingin Anda mulai pemindaian untuk pembayaran diam yang masuk, atau, gunakan tanggal sebagai gantinya. Anda dapat memilih jika dompet terus memindai setiap blok, atau memeriksa hanya ketinggian yang ditentukan.", + "silent_payments_scan_from_height": "Pindai dari Tinggi Blok", "silent_payments_scanning": "Pemindaian pembayaran diam", "slidable": "Dapat digeser", "sort_by": "Sortir dengan", @@ -649,6 +652,7 @@ "syncing_wallet_alert_title": "Dompet Anda sedang disinkronkan", "template": "Template", "template_name": "Nama Templat", + "testnet_coins_no_value": "Koin TestNet tidak memiliki nilai", "third_intro_content": "Yats hidup di luar Cake Wallet juga. Setiap alamat dompet di dunia dapat diganti dengan Yat!", "third_intro_title": "Yat bermain baik dengan yang lain", "thorchain_taproot_address_not_supported": "Penyedia Thorchain tidak mendukung alamat Taproot. Harap ubah alamatnya atau pilih penyedia yang berbeda.", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 979595048..b3ba636ba 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -612,6 +612,9 @@ "sign_up": "Registrati", "signTransaction": "Firma la transazione", "signup_for_card_accept_terms": "Registrati per la carta e accetta i termini.", + "silent_payments_scan_from_date": "Scansionare dalla data", + "silent_payments_scan_from_date_or_blockheight": "Inserisci l'altezza del blocco che si desidera iniziare la scansione per i pagamenti silenziosi in arrivo o, utilizza invece la data. Puoi scegliere se il portafoglio continua a scansionare ogni blocco o controlla solo l'altezza specificata.", + "silent_payments_scan_from_height": "Scansione dall'altezza del blocco", "silent_payments_scanning": "Scansione di pagamenti silenziosi", "slidable": "Scorrevole", "sort_by": "Ordina per", @@ -648,6 +651,7 @@ "syncing_wallet_alert_title": "Il tuo portafoglio si sta sincronizzando", "template": "Modello", "template_name": "Nome modello", + "testnet_coins_no_value": "Le monete TestNet non hanno valore", "third_intro_content": "Yat può funzionare anche fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con uno Yat!", "third_intro_title": "Yat gioca bene con gli altri", "thorchain_taproot_address_not_supported": "Il provider di Thorchain non supporta gli indirizzi di TapRoot. Si prega di modificare l'indirizzo o selezionare un fornitore diverso.", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index b3a3cefe0..7274f83ab 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -611,6 +611,9 @@ "sign_up": "サインアップ", "signTransaction": "トランザクションに署名する", "signup_for_card_accept_terms": "カードにサインアップして、利用規約に同意してください。", + "silent_payments_scan_from_date": "日付からスキャンします", + "silent_payments_scan_from_date_or_blockheight": "着信のサイレント決済のためにスキャンを開始するブロックの高さを入力するか、代わりに日付を使用してください。ウォレットがすべてのブロックをスキャンし続けるか、指定された高さのみをチェックするかどうかを選択できます。", + "silent_payments_scan_from_height": "ブロックの高さからスキャンします", "silent_payments_scanning": "サイレントペイメントスキャン", "slidable": "スライド可能", "sort_by": "並び替え", @@ -647,6 +650,7 @@ "syncing_wallet_alert_title": "ウォレットは同期中です", "template": "テンプレート", "template_name": "テンプレート名", + "testnet_coins_no_value": "テストネットコインには価値がありません", "third_intro_content": "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!", "third_intro_title": "Yatは他の人とうまく遊ぶ", "thorchain_taproot_address_not_supported": "Thorchainプロバイダーは、TapRootアドレスをサポートしていません。アドレスを変更するか、別のプロバイダーを選択してください。", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index b2908056f..b38a5f5cd 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -611,6 +611,9 @@ "sign_up": "가입", "signTransaction": "거래 서명", "signup_for_card_accept_terms": "카드에 가입하고 약관에 동의합니다.", + "silent_payments_scan_from_date": "날짜부터 스캔하십시오", + "silent_payments_scan_from_date_or_blockheight": "들어오는 사일런트 결제를 위해 스캔을 시작하려는 블록 높이를 입력하거나 대신 날짜를 사용하십시오. 지갑이 모든 블록을 계속 스캔하는지 여부를 선택하거나 지정된 높이 만 확인할 수 있습니다.", + "silent_payments_scan_from_height": "블록 높이에서 스캔하십시오", "silent_payments_scanning": "조용한 지불 스캔", "slidable": "슬라이딩 가능", "sort_by": "정렬 기준", @@ -647,6 +650,7 @@ "syncing_wallet_alert_title": "지갑 동기화 중", "template": "주형", "template_name": "템플릿 이름", + "testnet_coins_no_value": "Testnet 코인은 가치가 없습니다", "third_intro_content": "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!", "third_intro_title": "Yat는 다른 사람들과 잘 놉니다.", "thorchain_taproot_address_not_supported": "Thorchain 제공 업체는 Taproot 주소를 지원하지 않습니다. 주소를 변경하거나 다른 공급자를 선택하십시오.", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 1453da4cc..68fcaeb52 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -610,6 +610,9 @@ "sign_up": "ဆိုင်းအပ်", "signTransaction": "ငွေလွှဲဝင်ပါ။", "signup_for_card_accept_terms": "ကတ်အတွက် စာရင်းသွင်းပြီး စည်းကမ်းချက်များကို လက်ခံပါ။", + "silent_payments_scan_from_date": "ရက်စွဲမှစကင်ဖတ်ပါ", + "silent_payments_scan_from_date_or_blockheight": "ကျေးဇူးပြု. သင်ဝင်လာသောအသံတိတ်ငွေပေးချေမှုအတွက်သင်စကင်ဖတ်စစ်ဆေးလိုသည့်အမြင့်ကိုဖြည့်ပါ။ သို့မဟုတ်နေ့စွဲကိုသုံးပါ။ Wallet သည်လုပ်ကွက်တိုင်းကိုဆက်လက်စကင်ဖတ်စစ်ဆေးပါကသို့မဟုတ်သတ်မှတ်ထားသောအမြင့်ကိုသာစစ်ဆေးပါကသင်ရွေးချယ်နိုင်သည်။", + "silent_payments_scan_from_height": "ပိတ်ပင်တားဆီးမှုအမြင့်ကနေ scan", "silent_payments_scanning": "အသံတိတ်ငွေပေးချေမှု scanning", "slidable": "လျှောချနိုင်သည်။", "sort_by": "အလိုက်စဥ်သည်", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်နေပါသည်။", "template": "ပုံစံခွက်", "template_name": "နမူနာပုံစံ", + "testnet_coins_no_value": "Testnet ဒင်္ဂါးပြားတန်ဖိုးမရှိပါ", "third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင် နေထိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့်ပိုက်ဆံအိတ်လိပ်စာကို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။", "third_intro_title": "Yat သည် အခြားသူများနှင့် ကောင်းစွာကစားသည်။", "thorchain_taproot_address_not_supported": "Thorchain Provider သည် Taproot လိပ်စာများကိုမထောက်ခံပါ။ ကျေးဇူးပြု. လိပ်စာကိုပြောင်းပါသို့မဟုတ်အခြားပံ့ပိုးပေးသူကိုရွေးချယ်ပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index b82019e6b..ccd25e273 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -610,6 +610,9 @@ "sign_up": "Aanmelden", "signTransaction": "Transactie ondertekenen", "signup_for_card_accept_terms": "Meld je aan voor de kaart en accepteer de voorwaarden.", + "silent_payments_scan_from_date": "Scan vanaf datum", + "silent_payments_scan_from_date_or_blockheight": "Voer de blokhoogte in die u wilt beginnen met scannen op inkomende stille betalingen, of gebruik in plaats daarvan de datum. U kunt kiezen of de portemonnee elk blok blijft scannen of alleen de opgegeven hoogte controleert.", + "silent_payments_scan_from_height": "Scan van blokhoogte", "silent_payments_scanning": "Stille betalingen scannen", "slidable": "Verschuifbaar", "sort_by": "Sorteer op", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Uw portemonnee wordt gesynchroniseerd", "template": "Sjabloon", "template_name": "Sjabloonnaam", + "testnet_coins_no_value": "Testnet -munten hebben geen waarde", "third_intro_content": "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!", "third_intro_title": "Yat speelt leuk met anderen", "thorchain_taproot_address_not_supported": "De Thorchain -provider ondersteunt geen Taprooot -adressen. Wijzig het adres of selecteer een andere provider.", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index c1e677284..a464e78f2 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -610,6 +610,9 @@ "sign_up": "Zarejestruj się", "signTransaction": "Podpisz transakcję", "signup_for_card_accept_terms": "Zarejestruj się, aby otrzymać kartę i zaakceptuj warunki.", + "silent_payments_scan_from_date": "Skanuj z daty", + "silent_payments_scan_from_date_or_blockheight": "Wprowadź wysokość bloku, którą chcesz rozpocząć skanowanie w poszukiwaniu cichej płatności lub zamiast tego skorzystaj z daty. Możesz wybrać, czy portfel kontynuuje skanowanie każdego bloku, lub sprawdza tylko określoną wysokość.", + "silent_payments_scan_from_height": "Skanuj z wysokości bloku", "silent_payments_scanning": "Skanowanie cichych płatności", "slidable": "Przesuwne", "sort_by": "Sortuj według", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Twój portfel się synchronizuje", "template": "Szablon", "template_name": "Nazwa szablonu", + "testnet_coins_no_value": "Monety testowe nie mają wartości", "third_intro_content": "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!", "third_intro_title": "Yat ładnie bawi się z innymi", "thorchain_taproot_address_not_supported": "Dostawca Thorchain nie obsługuje adresów TAPROOT. Zmień adres lub wybierz innego dostawcę.", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 77e105b04..e1e50252f 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -612,7 +612,10 @@ "sign_up": "Inscrever-se", "signTransaction": "Assinar transação", "signup_for_card_accept_terms": "Cadastre-se no cartão e aceite os termos.", - "silent_payments_scanning": "Scanear Pagamentos Silenciosos", + "silent_payments_scan_from_date": "Escanear a partir da data", + "silent_payments_scan_from_date_or_blockheight": "Por favor, insira a altura do bloco que deseja iniciar o escaneamento para obter pagamentos silenciosos ou use a data. Você pode escolher se a carteira continua digitalizando cada bloco ou verifica apenas a altura especificada.", + "silent_payments_scan_from_height": "Escanear a partir da altura do bloco", + "silent_payments_scanning": "Escanear Pagamentos Silenciosos", "slidable": "Deslizável", "sort_by": "Ordenar por", "spend_key_private": "Chave de gastos (privada)", @@ -648,6 +651,7 @@ "syncing_wallet_alert_title": "Sua carteira está sincronizando", "template": "Modelo", "template_name": "Nome do modelo", + "testnet_coins_no_value": "As moedas de teste não têm valor", "third_intro_content": "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!", "third_intro_title": "Yat joga bem com os outros", "thorchain_taproot_address_not_supported": "O provedor de Thorchain não suporta endereços de raiz de Tap. Altere o endereço ou selecione um provedor diferente.", @@ -807,4 +811,4 @@ "you_will_get": "Converter para", "you_will_send": "Converter de", "yy": "aa" -} +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c793ef6b1..74699d479 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -611,6 +611,9 @@ "sign_up": "Зарегистрироваться", "signTransaction": "Подписать транзакцию", "signup_for_card_accept_terms": "Подпишитесь на карту и примите условия.", + "silent_payments_scan_from_date": "Сканирование с даты", + "silent_payments_scan_from_date_or_blockheight": "Пожалуйста, введите высоту блока, которую вы хотите начать сканирование для входящих молчаливых платежей, или вместо этого используйте дату. Вы можете выбрать, продолжает ли кошелек сканировать каждый блок или проверять только указанную высоту.", + "silent_payments_scan_from_height": "Сканирование с высоты блока", "silent_payments_scanning": "Сканирование безмолвных платежей", "slidable": "Скользящий", "sort_by": "Сортировать по", @@ -647,6 +650,7 @@ "syncing_wallet_alert_title": "Ваш кошелек синхронизируется", "template": "Шаблон", "template_name": "Имя Шаблона", + "testnet_coins_no_value": "Монеты теста не имеют значения", "third_intro_content": "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!", "third_intro_title": "Yat хорошо взаимодействует с другими", "thorchain_taproot_address_not_supported": "Поставщик Thorchain не поддерживает адреса taproot. Пожалуйста, измените адрес или выберите другого поставщика.", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 1839cc930..6c5ee98f4 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -610,6 +610,9 @@ "sign_up": "สมัครสมาชิก", "signTransaction": "ลงนามในการทำธุรกรรม", "signup_for_card_accept_terms": "ลงทะเบียนสำหรับบัตรและยอมรับเงื่อนไข", + "silent_payments_scan_from_date": "สแกนตั้งแต่วันที่", + "silent_payments_scan_from_date_or_blockheight": "โปรดป้อนความสูงของบล็อกที่คุณต้องการเริ่มการสแกนสำหรับการชำระเงินแบบเงียบ ๆ หรือใช้วันที่แทน คุณสามารถเลือกได้ว่ากระเป๋าเงินยังคงสแกนทุกบล็อกหรือตรวจสอบความสูงที่ระบุเท่านั้น", + "silent_payments_scan_from_height": "สแกนจากความสูงของบล็อก", "silent_payments_scanning": "การสแกนการชำระเงินแบบเงียบ", "slidable": "เลื่อนได้", "sort_by": "เรียงตาม", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "กระเป๋าสตางค์ของคุณกำลังซิงค์", "template": "แบบฟอร์ม", "template_name": "ชื่อแม่แบบ", + "testnet_coins_no_value": "Testnet Coins ไม่มีค่า", "third_intro_content": "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!", "third_intro_title": "Yat ปฏิบัติตนอย่างดีกับผู้อื่น", "thorchain_taproot_address_not_supported": "ผู้ให้บริการ Thorchain ไม่รองรับที่อยู่ taproot โปรดเปลี่ยนที่อยู่หรือเลือกผู้ให้บริการอื่น", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 4d3ef91c0..ca37f2f48 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -610,6 +610,9 @@ "sign_up": "Mag -sign up", "signTransaction": "Mag-sign Transaksyon", "signup_for_card_accept_terms": "Mag -sign up para sa card at tanggapin ang mga termino.", + "silent_payments_scan_from_date": "I -scan mula sa petsa", + "silent_payments_scan_from_date_or_blockheight": "Mangyaring ipasok ang taas ng block na nais mong simulan ang pag -scan para sa papasok na tahimik na pagbabayad, o, gamitin ang petsa sa halip. Maaari kang pumili kung ang pitaka ay patuloy na pag -scan sa bawat bloke, o suriin lamang ang tinukoy na taas.", + "silent_payments_scan_from_height": "I -scan mula sa taas ng block", "silent_payments_scanning": "Tahimik na pag -scan ng mga pagbabayad", "slidable": "Slidable", "sort_by": "Pag -uri -uriin sa pamamagitan ng", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Ang iyong pitaka ay nag -sync", "template": "Template", "template_name": "Pangalan ng Template", + "testnet_coins_no_value": "Ang mga barya ng testnet ay walang halaga", "third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!", "third_intro_title": "Si Yat ay mahusay na gumaganap sa iba", "thorchain_taproot_address_not_supported": "Ang Tagabigay ng Thorchain ay hindi sumusuporta sa mga address ng taproot. Mangyaring baguhin ang address o pumili ng ibang provider.", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 55fbf6036..e12853b92 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -610,6 +610,9 @@ "sign_up": "Kaydol", "signTransaction": "İşlem İmzala", "signup_for_card_accept_terms": "Kart için kaydol ve koşulları kabul et.", + "silent_payments_scan_from_date": "Tarihten tarama", + "silent_payments_scan_from_date_or_blockheight": "Lütfen gelen sessiz ödemeler için taramaya başlamak istediğiniz blok yüksekliğini girin veya bunun yerine tarihi kullanın. Cüzdanın her bloğu taramaya devam edip etmediğini veya yalnızca belirtilen yüksekliği kontrol edip etmediğini seçebilirsiniz.", + "silent_payments_scan_from_height": "Blok yüksekliğinden tarama", "silent_payments_scanning": "Sessiz Ödemeler Taraması", "slidable": "kaydırılabilir", "sort_by": "Göre sırala", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "Cüzdanınız senkronize ediliyor", "template": "Şablon", "template_name": "şablon adı", + "testnet_coins_no_value": "TestNet paralarının değeri yok", "third_intro_content": "Yat'lar Cake Wallet'ın dışında da çalışabilir. Dünya üzerindeki herhangi bir cüzdan adresi Yat ile değiştirilebilir!", "third_intro_title": "Yat diğerleriyle iyi çalışır", "thorchain_taproot_address_not_supported": "Thorchain sağlayıcısı Taproot adreslerini desteklemiyor. Lütfen adresi değiştirin veya farklı bir sağlayıcı seçin.", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index d48c5eb3d..63e4242b1 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -611,6 +611,9 @@ "sign_up": "Зареєструватися", "signTransaction": "Підписати транзакцію", "signup_for_card_accept_terms": "Зареєструйтеся на картку та прийміть умови.", + "silent_payments_scan_from_date": "Сканувати з дати", + "silent_payments_scan_from_date_or_blockheight": "Введіть висоту блоку, яку ви хочете почати сканувати для вхідних мовчазних платежів, або скористайтеся датою замість цього. Ви можете вибрати, якщо гаманець продовжує сканувати кожен блок, або перевіряє лише вказану висоту.", + "silent_payments_scan_from_height": "Сканування від висоти блоку", "silent_payments_scanning": "Мовчазні платежі сканування", "slidable": "Розсувний", "sort_by": "Сортувати за", @@ -647,6 +650,7 @@ "syncing_wallet_alert_title": "Ваш гаманець синхронізується", "template": "Шаблон", "template_name": "Назва шаблону", + "testnet_coins_no_value": "Монети TestNet не мають значення", "third_intro_content": "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!", "third_intro_title": "Yat добре взаємодіє з іншими", "thorchain_taproot_address_not_supported": "Постачальник Thorchain не підтримує адреси Taproot. Будь ласка, змініть адресу або виберіть іншого постачальника.", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index b5255bc15..171c2b0d2 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -612,6 +612,9 @@ "sign_up": "سائن اپ", "signTransaction": "۔ﮟﯾﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ", "signup_for_card_accept_terms": "کارڈ کے لیے سائن اپ کریں اور شرائط کو قبول کریں۔", + "silent_payments_scan_from_date": "تاریخ سے اسکین کریں", + "silent_payments_scan_from_date_or_blockheight": "براہ کرم بلاک اونچائی میں داخل ہوں جس سے آپ آنے والی خاموش ادائیگیوں کے لئے اسکیننگ شروع کرنا چاہتے ہیں ، یا اس کے بجائے تاریخ کا استعمال کریں۔ آپ یہ منتخب کرسکتے ہیں کہ اگر پرس ہر بلاک کو اسکیننگ جاری رکھے ہوئے ہے ، یا صرف مخصوص اونچائی کی جانچ پڑتال کرتا ہے۔", + "silent_payments_scan_from_height": "بلاک اونچائی سے اسکین کریں", "silent_payments_scanning": "خاموش ادائیگی اسکیننگ", "slidable": "سلائیڈ ایبل", "sort_by": "ترتیب دیں", @@ -648,6 +651,7 @@ "syncing_wallet_alert_title": "آپ کا بٹوہ مطابقت پذیر ہو رہا ہے۔", "template": "سانچے", "template_name": "ٹیمپلیٹ کا نام", + "testnet_coins_no_value": "ٹیسٹ نیٹ سکے کی کوئی قیمت نہیں ہے", "third_intro_content": "Yats بھی Cake والیٹ سے باہر رہتے ہیں۔ زمین پر کسی بھی بٹوے کے پتے کو Yat سے تبدیل کیا جا سکتا ہے!", "third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح کھیلتا ہے۔", "thorchain_taproot_address_not_supported": "تھورچین فراہم کنندہ ٹیپروٹ پتے کی حمایت نہیں کرتا ہے۔ براہ کرم پتہ تبدیل کریں یا ایک مختلف فراہم کنندہ کو منتخب کریں۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 3435f9ca1..463076ea0 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -611,6 +611,9 @@ "sign_up": "Forúkọ sílẹ̀", "signTransaction": "Wole Idunadura", "signup_for_card_accept_terms": "Ẹ f'orúkọ sílẹ̀ láti gba káàdì àti àjọrò.", + "silent_payments_scan_from_date": "Scan lati ọjọ", + "silent_payments_scan_from_date_or_blockheight": "Jọwọ tẹ giga idibo ti o fẹ bẹrẹ ọlọjẹ fun awọn sisanwo ipalọlọ, tabi, lo ọjọ dipo. O le yan ti apamọwọ naa tẹsiwaju nṣapẹẹrẹ gbogbo bulọọki, tabi ṣayẹwo nikan giga ti o sọ tẹlẹ.", + "silent_payments_scan_from_height": "Scan lati Iga Iga", "silent_payments_scanning": "Awọn sisanwo ipalọlọ", "slidable": "Slidable", "sort_by": "Sa pelu", @@ -647,6 +650,7 @@ "syncing_wallet_alert_title": "Apamọwọ rẹ n muṣiṣẹpọ", "template": "Àwòṣe", "template_name": "Orukọ Awoṣe", + "testnet_coins_no_value": "Awọn aṣọ irekọja ko ni iye", "third_intro_content": "A sì lè lo Yats níta Cake Wallet. A lè rọ́pò Àdírẹ́sì kankan àpamọ́wọ́ fún Yat!", "third_intro_title": "Àlàáfíà ni Yat àti àwọn ìmíìn jọ wà", "thorchain_taproot_address_not_supported": "Olupese Trockchain ko ṣe atilẹyin awọn adirẹsi Taproot. Jọwọ yi adirẹsi pada tabi yan olupese ti o yatọ.", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 22e74ce5b..14ece96dd 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -610,6 +610,9 @@ "sign_up": "注册", "signTransaction": "签署交易", "signup_for_card_accept_terms": "注册卡并接受条款。", + "silent_payments_scan_from_date": "从日期开始扫描", + "silent_payments_scan_from_date_or_blockheight": "请输入您要开始扫描输入静音付款的块高度,或者使用日期。您可以选择钱包是否继续扫描每个块,或仅检查指定的高度。", + "silent_payments_scan_from_height": "从块高度扫描", "silent_payments_scanning": "无声付款扫描", "slidable": "可滑动", "sort_by": "排序方式", @@ -646,6 +649,7 @@ "syncing_wallet_alert_title": "您的钱包正在同步", "template": "模板", "template_name": "模板名称", + "testnet_coins_no_value": "TestNet硬币没有价值", "third_intro_content": "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!", "third_intro_title": "Yat 和別人玩得很好", "thorchain_taproot_address_not_supported": "Thorchain提供商不支持Taproot地址。请更改地址或选择其他提供商。", diff --git a/tool/configure.dart b/tool/configure.dart index 96891247c..5b0ad99aa 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -128,7 +128,7 @@ abstract class Bitcoin { List getAddresses(Object wallet); String getAddress(Object wallet); - List getSilentAddresses(Object wallet); + List getSilentAddresses(Object wallet); Future estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority); List getSubAddresses(Object wallet); @@ -149,14 +149,15 @@ abstract class Bitcoin { Future setAddressType(Object wallet, dynamic option); BitcoinReceivePageOption getSelectedAddressType(Object wallet); + List getBitcoinReceivePageOptions(); BitcoinAddressType getBitcoinAddressType(ReceivePageOption option); bool hasSelectedSilentPayments(Object wallet); - List getBitcoinReceivePageOptions(); bool isBitcoinReceivePageOption(ReceivePageOption option); BitcoinAddressType getOptionToType(ReceivePageOption option); bool hasTaprootInput(PendingTransaction pendingTransaction); bool getScanningActive(Object wallet); void setScanningActive(Object wallet, bool active); + bool isTestnet(Object wallet); } """; @@ -1052,7 +1053,8 @@ Future generatePubspec( final inputFile = File(pubspecOutputPath); final inputText = await inputFile.readAsString(); final inputLines = inputText.split('\n'); - final dependenciesIndex = inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:')); + final dependenciesIndex = + inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:')); var output = cwCore; if (hasMonero) {