From a9a26ac62b4e71ee3345e733d90787d96c320404 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Wed, 10 Jan 2024 17:20:38 -0300 Subject: [PATCH 01/59] inital migration changes --- cw_bitcoin/lib/address_from_output.dart | 23 +-- cw_bitcoin/lib/address_to_output_script.dart | 23 +-- cw_bitcoin/lib/bitcoin_address_record.dart | 31 +-- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 43 ++-- cw_bitcoin/lib/electrum_wallet_addresses.dart | 189 ++++++++++-------- cw_bitcoin/lib/litecoin_wallet_addresses.dart | 5 +- cw_bitcoin/lib/script_hash.dart | 21 +- cw_bitcoin/lib/utils.dart | 54 ++--- cw_bitcoin/pubspec.yaml | 4 + cw_bitcoin_cash/pubspec.yaml | 5 +- cw_core/lib/unspent_transaction_output.dart | 4 +- cw_core/pubspec.yaml | 4 + lib/core/address_validator.dart | 20 +- lib/entities/receive_page_option.dart | 7 +- 14 files changed, 220 insertions(+), 213 deletions(-) diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index d06ffe402..d870e6747 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -1,23 +1,16 @@ import 'dart:typed_data'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; +import 'package:bitcoin_base/bitcoin_base.dart'; -String addressFromOutput(Uint8List script, bitcoin.NetworkType networkType) { +String addressFromOutput(Uint8List script, BasedUtxoNetwork network) { try { - return bitcoin.P2PKH( - data: PaymentData(output: script), - network: networkType) - .data - .address!; + return P2pkhAddress.fromScriptPubkey(script: Script.fromRaw(byteData: script)) + .toAddress(network); } catch (_) {} try { - return bitcoin.P2WPKH( - data: PaymentData(output: script), - network: networkType) - .data - .address!; - } catch(_) {} + return P2wpkhAddress.fromScriptPubkey(script: Script.fromRaw(byteData: script)) + .toAddress(network); + } catch (_) {} return ''; -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/address_to_output_script.dart b/cw_bitcoin/lib/address_to_output_script.dart index 01c7b67a5..d0ad0c30f 100644 --- a/cw_bitcoin/lib/address_to_output_script.dart +++ b/cw_bitcoin/lib/address_to_output_script.dart @@ -1,27 +1,18 @@ import 'dart:typed_data'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:bs58check/bs58check.dart' as bs58check; -import 'package:bitcoin_flutter/src/utils/constants/op.dart'; -import 'package:bitcoin_flutter/src/utils/script.dart' as bscript; -import 'package:bitcoin_flutter/src/address.dart'; +import 'package:bitcoin_base/bitcoin_base.dart'; -Uint8List p2shAddressToOutputScript(String address) { - final decodeBase58 = bs58check.decode(address); - final hash = decodeBase58.sublist(1); - return bscript.compile([OPS['OP_HASH160'], hash, OPS['OP_EQUAL']]); -} - -Uint8List addressToOutputScript( - String address, bitcoin.NetworkType networkType) { +List addressToOutputScript(String address, BasedUtxoNetwork network) { try { // FIXME: improve validation for p2sh addresses // 3 for bitcoin // m for litecoin - if (address.startsWith('3') || address.toLowerCase().startsWith('m')) { - return p2shAddressToOutputScript(address); + // (note: m is also for bitcoin's testnet. check networkType to make sure) + if (address.startsWith('3') || + (address.toLowerCase().startsWith('m') && network != BitcoinNetwork.testnet)) { + return P2shAddress.fromAddress(address: address, network: network).toScriptPubKey().toBytes(); } - return Address.addressToOutputScript(address, networkType); + return addressToOutputScript(address, network); } catch (err) { print(err); return Uint8List(0); diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index 392771ab0..74aa9ccd1 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -1,23 +1,27 @@ import 'dart:convert'; +import 'package:bitcoin_base/bitcoin_base.dart'; + 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.type}) + : _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, + type: decoded['type'] != null && decoded['type'] != '' + ? BitcoinAddressType.values + .firstWhere((type) => type.toString() == decoded['type'] as String) + : null); } @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; @@ -31,10 +35,13 @@ class BitcoinAddressRecord { void setAsUsed() => _isUsed = true; - String toJSON() => - json.encode({ + BitcoinAddressType? type; + + String toJSON() => json.encode({ 'address': address, 'index': index, 'isHidden': isHidden, - 'isUsed': isUsed}); + 'isUsed': isUsed, + 'type': type?.toString() ?? '', + }); } diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index 36d37127d..06d9d1efc 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -1,6 +1,5 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/electrum.dart'; +import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/utils.dart'; import 'package:cw_core/wallet_info.dart'; @@ -11,24 +10,26 @@ part 'bitcoin_wallet_addresses.g.dart'; class BitcoinWalletAddresses = BitcoinWalletAddressesBase with _$BitcoinWalletAddresses; abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with Store { - BitcoinWalletAddressesBase(WalletInfo walletInfo, - {required bitcoin.HDWallet mainHd, - required bitcoin.HDWallet sideHd, - required bitcoin.NetworkType networkType, - required ElectrumClient electrumClient, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super(walletInfo, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: mainHd, - sideHd: sideHd, - electrumClient: electrumClient, - networkType: networkType); + BitcoinWalletAddressesBase( + WalletInfo walletInfo, { + required super.mainHd, + required super.sideHd, + required super.network, + required super.electrumClient, + super.initialAddresses, + super.initialRegularAddressIndex = 0, + super.initialChangeAddressIndex = 0, + }) : super(walletInfo); @override - String getAddress({required int index, required bitcoin.HDWallet hd}) => - generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); + String getAddress({required int index, required HDWallet hd, BitcoinAddressType? addressType}) { + generateP2WPKHAddress(hd: hd, index: index, network: network); + if (addressType == BitcoinAddressType.p2pkh) + return generateP2PKHAddress(hd: hd, index: index, network: network); + + if (addressType == BitcoinAddressType.p2tr) + return generateP2TRAddress(hd: hd, index: index, network: network); + + return generateP2WPKHAddress(hd: hd, index: index, network: network); + } } diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index ab99a875c..aba0e246f 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -1,3 +1,4 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitbox/bitbox.dart' as bitbox; import 'package:cw_bitcoin/bitcoin_address_record.dart'; @@ -10,31 +11,28 @@ 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, - {required this.mainHd, - required this.sideHd, - required this.electrumClient, - required this.networkType, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : addresses = ObservableList.of( - (initialAddresses ?? []).toSet()), - receiveAddresses = ObservableList.of( - (initialAddresses ?? []) + ElectrumWalletAddressesBase( + WalletInfo walletInfo, { + required this.mainHd, + required this.sideHd, + required this.electrumClient, + required this.network, + List? initialAddresses, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0, + }) : addresses = ObservableList.of((initialAddresses ?? []).toSet()), + 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()), currentReceiveAddressIndex = initialRegularAddressIndex, currentChangeAddressIndex = initialChangeAddressIndex, - super(walletInfo); + super(walletInfo); static const defaultReceiveAddressesCount = 22; static const defaultChangeAddressesCount = 17; @@ -46,13 +44,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final ObservableList receiveAddresses; final ObservableList changeAddresses; final ElectrumClient electrumClient; - final bitcoin.NetworkType networkType; + final BasedUtxoNetwork network; final bitcoin.HDWallet mainHd; final bitcoin.HDWallet sideHd; - @override + @observable + BitcoinAddressType _addressPageType = BitcoinAddressType.p2wpkh; @computed - String get address { + BitcoinAddressType get addressPageType => _addressPageType; + + @computed + String get receiveAddress { if (receiveAddresses.isEmpty) { final address = generateNewAddress().address; return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address; @@ -63,28 +65,41 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } @override - set address(String addr) => null; + @computed + String get address { + if (receiveAddresses.isEmpty) { + return generateNewAddress().address; + } + + try { + return receiveAddresses + .firstWhere((address) => addressPageType == BitcoinAddressType.p2wpkh + ? address.type == null || address.type == addressPageType + : address.type == addressPageType) + .address; + } catch (_) {} + + return receiveAddresses.first.address; + } 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,12 +129,10 @@ 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); - _addAddresses(newAddresses); + hd: sideHd, + startIndex: totalCountOfChangeAddresses > 0 ? totalCountOfChangeAddresses - 1 : 0, + isHidden: true); + addAddresses(newAddresses); } if (currentChangeAddressIndex >= changeAddresses.length) { @@ -132,19 +145,24 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return address; } + @action BitcoinAddressRecord generateNewAddress( - {bitcoin.HDWallet? hd, bool isHidden = false}) { - currentReceiveAddressIndex += 1; + {bitcoin.HDWallet? hd, bool isHidden = false, String? label}) { // FIX-ME: Check logic for whichi HD should be used here ??? final address = BitcoinAddressRecord( - getAddress(index: currentReceiveAddressIndex, hd: hd ?? sideHd), + getAddress( + index: currentReceiveAddressIndex, hd: hd ?? sideHd, addressType: addressPageType), index: currentReceiveAddressIndex, isHidden: isHidden); addresses.add(address); return address; + + currentReceiveAddressIndex += 1; } - String getAddress({required int index, required bitcoin.HDWallet hd}) => ''; + String getAddress( + {required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) => + ''; @override Future updateAddressesInBox() async { @@ -160,38 +178,37 @@ 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); } - Future _discoverAddresses(bitcoin.HDWallet hd, bool isHidden) async { + @action + Future _discoverAddresses(bitcoin.HDWallet hd, bool isHidden, + {BitcoinAddressType? addressType}) async { var hasAddrUse = true; List addrs; - if (addresses.isNotEmpty) { - addrs = addresses - .where((addr) => addr.isHidden == isHidden) - .toList(); + if (addresses.where((addr) => addr.type == addressPageType).isNotEmpty) { + addrs = addresses.where((addr) => addr.isHidden == isHidden).toList(); } else { addrs = await _createNewAddresses( - isHidden - ? defaultChangeAddressesCount - : defaultReceiveAddressesCount, + isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, startIndex: 0, hd: hd, - isHidden: isHidden); + isHidden: isHidden, + addressType: addressType); } - while(hasAddrUse) { + while (hasAddrUse) { final addr = addrs.last.address; hasAddrUse = await _hasAddressUsed(addr); @@ -201,16 +218,13 @@ 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, addressType: addressType); addrs.addAll(batch); } if (addresses.length < addrs.length) { - _addAddresses(addrs); + addAddresses(addrs); } } @@ -229,41 +243,37 @@ 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); } } Future> _createNewAddresses(int count, - {required bitcoin.HDWallet hd, int startIndex = 0, bool isHidden = false}) async { + {required bitcoin.HDWallet hd, + int startIndex = 0, + bool isHidden = false, + BitcoinAddressType? addressType}) async { 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, addressType: addressType), + index: i, isHidden: isHidden, type: addressType); list.add(address); } return list; } - void _addAddresses(Iterable addresses) { + @action + void addAddresses(Iterable addresses) { final addressesSet = this.addresses.toSet(); addressesSet.addAll(addresses); this.addresses.removeRange(0, this.addresses.length); @@ -271,8 +281,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } Future _hasAddressUsed(String address) async { - final sh = scriptHash(address, networkType: networkType); + final sh = scriptHash(address, networkType: network); final transactionHistory = await electrumClient.getHistory(sh); return transactionHistory.isNotEmpty; } -} \ No newline at end of file + + @override + @action + Future setAddressType(dynamic type) async { + _addressPageType = type as BitcoinAddressType; + + await _discoverAddresses(mainHd, false, addressType: addressPageType); + updateReceiveAddresses(); + } +} diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart index a317fa9f2..4930ef5f3 100644 --- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart @@ -4,7 +4,6 @@ import 'package:cw_bitcoin/utils.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; -import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; part 'litecoin_wallet_addresses.g.dart'; @@ -35,5 +34,5 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses @override String getAddress({required int index, required bitcoin.HDWallet hd}) => - generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); -} \ No newline at end of file + generateP2WPKHAddress(hd: hd, index: index, network: network); +} diff --git a/cw_bitcoin/lib/script_hash.dart b/cw_bitcoin/lib/script_hash.dart index 76a1bfcf0..cdc38361b 100644 --- a/cw_bitcoin/lib/script_hash.dart +++ b/cw_bitcoin/lib/script_hash.dart @@ -2,8 +2,25 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:crypto/crypto.dart'; String scriptHash(String address, {required bitcoin.NetworkType networkType}) { - final outputScript = - bitcoin.Address.addressToOutputScript(address, networkType); + try { + final outputScript = bitcoin.Address.addressToOutputScript(address, networkType); + final parts = sha256.convert(outputScript).toString().split(''); + var res = ''; + + for (var i = parts.length - 1; i >= 0; i--) { + final char = parts[i]; + i--; + final nextChar = parts[i]; + res += nextChar; + res += char; + } + + return res; + } catch (e) {} + return ''; +} + +String scriptHashFromScript(List outputScript, {required bitcoin.NetworkType networkType}) { final parts = sha256.convert(outputScript).toString().split(''); var res = ''; diff --git a/cw_bitcoin/lib/utils.dart b/cw_bitcoin/lib/utils.dart index 0d5a413b3..ab2ae28b0 100644 --- a/cw_bitcoin/lib/utils.dart +++ b/cw_bitcoin/lib/utils.dart @@ -1,55 +1,25 @@ import 'dart:typed_data'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:flutter/foundation.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:hex/hex.dart'; -bitcoin.PaymentData generatePaymentData( - {required bitcoin.HDWallet hd, required int index}) => - PaymentData( - pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))); +bitcoin.PaymentData generatePaymentData({required bitcoin.HDWallet hd, required int index}) => + PaymentData(pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))); bitcoin.ECPair generateKeyPair( - {required bitcoin.HDWallet hd, - required int index, - required bitcoin.NetworkType network}) => + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => bitcoin.ECPair.fromWIF(hd.derive(index).wif!, network: network); String generateP2WPKHAddress( - {required bitcoin.HDWallet hd, - required int index, - required bitcoin.NetworkType networkType}) => - bitcoin - .P2WPKH( - data: PaymentData( - pubkey: - Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))), - network: networkType) - .data - .address!; - -String generateP2WPKHAddressByPath( - {required bitcoin.HDWallet hd, - required String path, - required bitcoin.NetworkType networkType}) => - bitcoin - .P2WPKH( - data: PaymentData( - pubkey: - Uint8List.fromList(HEX.decode(hd.derivePath(path).pubKey!))), - network: networkType) - .data - .address!; + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + P2wpkhAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); String generateP2PKHAddress( - {required bitcoin.HDWallet hd, - required int index, - required bitcoin.NetworkType networkType}) => - bitcoin - .P2PKH( - data: PaymentData( - pubkey: - Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))), - network: networkType) - .data - .address!; + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + P2pkhAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); + +String generateP2TRAddress( + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + P2trAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index a50ff68ad..d3b165c74 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -30,6 +30,10 @@ dependencies: rxdart: ^0.27.5 unorm_dart: ^0.2.0 cryptography: ^2.0.5 + bitcoin_base: + git: + url: https://github.com/cake-tech/bitcoin_base.git + ref: cake-update-v1 dev_dependencies: flutter_test: diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 49a5efb15..9c098c0ff 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -29,7 +29,10 @@ dependencies: git: url: https://github.com/cake-tech/bitbox-flutter.git ref: master - bitcoin_base: ^3.0.1 + bitcoin_base: + git: + url: https://github.com/cake-tech/bitcoin_base.git + ref: cake-update-v1 diff --git a/cw_core/lib/unspent_transaction_output.dart b/cw_core/lib/unspent_transaction_output.dart index b52daf43c..528236185 100644 --- a/cw_core/lib/unspent_transaction_output.dart +++ b/cw_core/lib/unspent_transaction_output.dart @@ -1,3 +1,5 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; + class Unspent { Unspent(this.address, this.hash, this.value, this.vout, this.keyImage) : isSending = true, @@ -16,5 +18,5 @@ class Unspent { bool isFrozen; String note; - bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc'); + bool get isP2wpkh => P2wpkhAddress.REGEX.hasMatch(address) || address.startsWith('ltc'); } diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 04a840d4e..105158bfe 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -20,6 +20,10 @@ dependencies: intl: ^0.18.0 encrypt: ^5.0.1 socks5_proxy: ^1.0.4 + bitcoin_base: + git: + url: https://github.com/cake-tech/bitcoin_base.git + ref: cake-update-v1 # tor: # git: # url: https://github.com/cake-tech/tor.git diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 2ae9e3297..1b5bc74a4 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -1,4 +1,4 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/validator.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -9,7 +9,7 @@ class AddressValidator extends TextValidator { : super( errorMessage: S.current.error_text_address, useAdditionalValidation: type == CryptoCurrency.btc - ? bitcoin.Address.validateAddress + ? (String txt) => validateAddress(address: txt, network: BitcoinNetwork.mainnet) : null, pattern: getPattern(type), length: getLength(type)); @@ -25,7 +25,7 @@ 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}\$'; + return '^${P2pkhAddress.REGEX.pattern}\$|^${P2shAddress.REGEX.pattern}\$|^${P2wpkhAddress.REGEX.pattern}\$|${P2trAddress.REGEX.pattern}\$'; case CryptoCurrency.nano: return '[0-9a-zA-Z_]'; case CryptoCurrency.banano: @@ -90,7 +90,7 @@ class AddressValidator extends TextValidator { case CryptoCurrency.dai: case CryptoCurrency.dash: case CryptoCurrency.eos: - return '[0-9a-zA-Z]'; + return '[0-9a-zA-Z]'; case CryptoCurrency.bch: return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{42}\$|^bitcoincash:q|p[0-9a-zA-Z]{41}\$|^bitcoincash:q|p[0-9a-zA-Z]{42}\$'; case CryptoCurrency.bnb: @@ -263,12 +263,10 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)8[0-9a-zA-Z]{94}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[0-9a-zA-Z]{106}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.btc: - return '([^0-9a-zA-Z]|^)1[0-9a-zA-Z]{32}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)1[0-9a-zA-Z]{33}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)3[0-9a-zA-Z]{32}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)3[0-9a-zA-Z]{33}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)bc1[0-9a-zA-Z]{39}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)bc1[0-9a-zA-Z]{59}([^0-9a-zA-Z]|\$)'; + return '([^0-9a-zA-Z]|^)${P2pkAddress.REGEX.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2shAddress.REGEX.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2wpkhAddress.REGEX.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2trAddress.REGEX.pattern}|\$)'; case CryptoCurrency.ltc: return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)' @@ -290,4 +288,4 @@ class AddressValidator extends TextValidator { return null; } } -} \ No newline at end of file +} diff --git a/lib/entities/receive_page_option.dart b/lib/entities/receive_page_option.dart index 3ee9abe96..cb04c9da0 100644 --- a/lib/entities/receive_page_option.dart +++ b/lib/entities/receive_page_option.dart @@ -1,4 +1,3 @@ - enum ReceivePageOption { mainnet, anonPayInvoice, @@ -9,13 +8,13 @@ enum ReceivePageOption { String label = ''; switch (this) { case ReceivePageOption.mainnet: - label = 'Mainnet'; + label = S.current.mainnet; break; case ReceivePageOption.anonPayInvoice: - label = 'Trocador AnonPay Invoice'; + label = S.current.trocador_anonpay_invoice; break; case ReceivePageOption.anonPayDonationLink: - label = 'Trocador AnonPay Donation Link'; + label = S.current.trocador_anonpay_donation_link; break; } return label; From 2596d6663dc0108298ebba2b8431ec3b841877b8 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 11 Jan 2024 15:43:50 -0300 Subject: [PATCH 02/59] feat: rest of changes --- cw_bitcoin/lib/bitcoin_wallet.dart | 30 ++- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 4 +- cw_bitcoin/lib/electrum.dart | 90 +++----- cw_bitcoin/lib/electrum_transaction_info.dart | 47 ++--- cw_bitcoin/lib/electrum_wallet.dart | 32 +-- cw_bitcoin/lib/electrum_wallet_addresses.dart | 30 +-- cw_bitcoin/lib/litecoin_wallet.dart | 40 ++-- cw_bitcoin/lib/litecoin_wallet_addresses.dart | 38 ++-- cw_bitcoin/lib/script_hash.dart | 24 +-- cw_bitcoin/lib/utils.dart | 12 +- cw_bitcoin/pubspec.lock | 179 +++++++++------- cw_bitcoin/pubspec.yaml | 1 + .../lib/src/bitcoin_cash_wallet.dart | 13 +- .../src/bitcoin_cash_wallet_addresses.dart | 34 ++- cw_core/lib/receive_page_options.dart | 52 +++++ cw_core/pubspec.lock | 199 ++++++++++-------- cw_haven/pubspec.lock | 17 ++ cw_monero/example/pubspec.lock | 17 ++ cw_monero/pubspec.lock | 17 ++ cw_nano/pubspec.lock | 26 ++- lib/entities/receive_page_option.dart | 68 ++++-- .../screens/dashboard/pages/address_page.dart | 16 +- .../dashboard/receive_option_view_model.dart | 17 +- .../wallet_address_list_view_model.dart | 31 ++- lib/view_model/wallet_creation_vm.dart | 3 +- res/values/strings_ar.arb | 7 +- res/values/strings_bg.arb | 7 +- res/values/strings_cs.arb | 7 +- res/values/strings_de.arb | 7 +- res/values/strings_en.arb | 7 +- res/values/strings_es.arb | 7 +- res/values/strings_fr.arb | 7 +- 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 | 7 +- 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 +- 51 files changed, 742 insertions(+), 477 deletions(-) create mode 100644 cw_core/lib/receive_page_options.dart diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 2c66d02fe..3334eb464 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -37,28 +37,25 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialBalance: initialBalance, seedBytes: seedBytes, currency: CryptoCurrency.btc) { - 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"), + network: network); } - static Future create({ - required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - 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, + List? initialAddresses, + ElectrumBalance? initialBalance, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) async { return BitcoinWallet( mnemonic: mnemonic, password: password, @@ -89,4 +86,5 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex); } -} \ 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 06d9d1efc..c857bc438 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -23,13 +23,15 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S @override String getAddress({required int index, required HDWallet hd, BitcoinAddressType? addressType}) { - generateP2WPKHAddress(hd: hd, index: index, network: network); if (addressType == BitcoinAddressType.p2pkh) return generateP2PKHAddress(hd: hd, index: index, network: network); if (addressType == BitcoinAddressType.p2tr) return generateP2TRAddress(hd: hd, index: index, network: network); + if (addressType == BitcoinAddressType.p2wsh) + return generateP2WSHAddress(hd: hd, index: index, network: network); + return generateP2WPKHAddress(hd: hd, index: index, network: network); } } diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index a05c251fe..2f73c24b6 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -2,12 +2,11 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:flutter/foundation.dart'; import 'package:rxdart/rxdart.dart'; -import 'package:collection/collection.dart'; String jsonrpcparams(List params) { final _params = params?.map((val) => '"${val.toString()}"')?.join(','); @@ -22,10 +21,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 +47,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 +99,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 +136,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(); } @@ -178,11 +171,10 @@ class ElectrumClient { }); Future>> getListUnspentWithAddress( - String address, NetworkType networkType) => + String address, BasedUtxoNetwork network) => call( - method: 'blockchain.scripthash.listunspent', - params: [scriptHash(address, networkType: networkType)]) - .then((dynamic result) { + method: 'blockchain.scripthash.listunspent', + params: [scriptHash(address, network: network)]).then((dynamic result) { if (result is List) { return result.map((dynamic val) { if (val is Map) { @@ -229,8 +221,7 @@ class ElectrumClient { return []; }); - Future> getTransactionRaw( - {required String hash}) async => + Future> getTransactionRaw({required String hash}) async => callWithTimeout(method: 'blockchain.transaction.get', params: [hash, true], timeout: 10000) .then((dynamic result) { if (result is Map) { @@ -240,8 +231,7 @@ class ElectrumClient { 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,8 +241,7 @@ class ElectrumClient { return ''; }); - Future broadcastTransaction( - {required String transactionRaw}) async => + Future broadcastTransaction({required String transactionRaw}) async => call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) .then((dynamic result) { if (result is String) { @@ -262,19 +251,15 @@ class ElectrumClient { return ''; }); - 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]) + 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 +304,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 (_) { @@ -344,16 +323,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 +347,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 +361,7 @@ class ElectrumClient { }); return completer.future; - } catch(e) { + } catch (e) { print(e.toString()); } } @@ -397,8 +372,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 +394,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 +425,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_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index bf5ec2c4f..c6a7b212e 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -1,3 +1,4 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:cw_bitcoin/address_from_output.dart'; @@ -10,9 +11,7 @@ import 'package:cw_core/wallet_type.dart'; class ElectrumTransactionBundle { ElectrumTransactionBundle(this.originalTransaction, - {required this.ins, - required this.confirmations, - this.time}); + {required this.ins, required this.confirmations, this.time}); final bitcoin.Transaction originalTransaction; final List ins; final int? time; @@ -39,8 +38,7 @@ class ElectrumTransactionInfo extends TransactionInfo { this.confirmations = confirmations; } - factory ElectrumTransactionInfo.fromElectrumVerbose( - Map obj, WalletType type, + factory ElectrumTransactionInfo.fromElectrumVerbose(Map obj, WalletType type, {required List addresses, required int height}) { final addressesSet = addresses.map((addr) => addr.address).toSet(); final id = obj['txid'] as String; @@ -58,10 +56,8 @@ class ElectrumTransactionInfo extends TransactionInfo { for (dynamic vin in vins) { final vout = vin['vout'] as int; final out = vin['tx']['vout'][vout] as Map; - final outAddresses = - (out['scriptPubKey']['addresses'] as List?)?.toSet(); - inputsAmount += - stringDoubleToBitcoinAmount((out['value'] as double? ?? 0).toString()); + final outAddresses = (out['scriptPubKey']['addresses'] as List?)?.toSet(); + inputsAmount += stringDoubleToBitcoinAmount((out['value'] as double? ?? 0).toString()); if (outAddresses?.intersection(addressesSet).isNotEmpty ?? false) { direction = TransactionDirection.outgoing; @@ -69,11 +65,9 @@ class ElectrumTransactionInfo extends TransactionInfo { } for (dynamic out in vout) { - final outAddresses = - out['scriptPubKey']['addresses'] as List? ?? []; + final outAddresses = out['scriptPubKey']['addresses'] as List? ?? []; final ntrs = outAddresses.toSet().intersection(addressesSet); - final value = stringDoubleToBitcoinAmount( - (out['value'] as double? ?? 0.0).toString()); + final value = stringDoubleToBitcoinAmount((out['value'] as double? ?? 0.0).toString()); totalOutAmount += value; if ((direction == TransactionDirection.incoming && ntrs.isNotEmpty) || @@ -96,14 +90,11 @@ class ElectrumTransactionInfo extends TransactionInfo { } factory ElectrumTransactionInfo.fromElectrumBundle( - ElectrumTransactionBundle bundle, - WalletType type, - bitcoin.NetworkType networkType, - {required Set addresses, - required int height}) { + ElectrumTransactionBundle bundle, WalletType type, BasedUtxoNetwork network, + {required Set addresses, required int height}) { final date = bundle.time != null - ? DateTime.fromMillisecondsSinceEpoch(bundle.time! * 1000) - : DateTime.now(); + ? DateTime.fromMillisecondsSinceEpoch(bundle.time! * 1000) + : DateTime.now(); var direction = TransactionDirection.incoming; var amount = 0; var inputAmount = 0; @@ -114,7 +105,7 @@ class ElectrumTransactionInfo extends TransactionInfo { final inputTransaction = bundle.ins[i]; final vout = input.index; final outTransaction = inputTransaction.outs[vout!]; - final address = addressFromOutput(outTransaction.script!, networkType); + final address = addressFromOutput(outTransaction.script!, network); inputAmount += outTransaction.value!; if (addresses.contains(address)) { direction = TransactionDirection.outgoing; @@ -123,7 +114,7 @@ class ElectrumTransactionInfo extends TransactionInfo { for (final out in bundle.originalTransaction.outs) { totalOutAmount += out.value!; - final address = addressFromOutput(out.script!, networkType); + final address = addressFromOutput(out.script!, network); final addressExists = addresses.contains(address); if ((direction == TransactionDirection.incoming && addressExists) || (direction == TransactionDirection.outgoing && !addressExists)) { @@ -152,8 +143,8 @@ class ElectrumTransactionInfo extends TransactionInfo { if (addresses != null) { tx.outs.forEach((out) { try { - final p2pkh = bitcoin.P2PKH( - data: PaymentData(output: out.script), network: bitcoin.bitcoin); + final p2pkh = + bitcoin.P2PKH(data: PaymentData(output: out.script), network: bitcoin.bitcoin); exist = addresses.contains(p2pkh.data.address); if (exist) { @@ -163,9 +154,8 @@ class ElectrumTransactionInfo extends TransactionInfo { }); } - final date = timestamp != null - ? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000) - : DateTime.now(); + final date = + timestamp != null ? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000) : DateTime.now(); return ElectrumTransactionInfo(type, id: tx.getId(), @@ -178,8 +168,7 @@ class ElectrumTransactionInfo extends TransactionInfo { confirmations: confirmations); } - factory ElectrumTransactionInfo.fromJson( - Map data, WalletType type) { + factory ElectrumTransactionInfo.fromJson(Map data, WalletType type) { return ElectrumTransactionInfo(type, id: data['id'] as String, height: data['height'] as int, diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 4c5ecc7f2..f9188cc22 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -3,9 +3,10 @@ import 'dart:convert'; import 'dart:io'; import 'dart:math'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:collection/collection.dart'; -import 'package:cw_bitcoin/address_to_output_script.dart'; +import 'package:cw_bitcoin/address_to_output_script.dart' as address_to_output_script; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; @@ -18,6 +19,7 @@ import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; +import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; @@ -72,6 +74,11 @@ abstract class ElectrumWalletBase } : {}), this.unspentCoinsInfo = unspentCoinsInfo, + this.network = networkType == bitcoin.bitcoin + ? BitcoinNetwork.mainnet + : networkType == litecoinNetwork + ? LitecoinNetwork.mainnet + : BitcoinNetwork.testnet, super(walletInfo) { this.electrumClient = electrumClient ?? ElectrumClient(); this.walletInfo = walletInfo; @@ -101,13 +108,12 @@ abstract class ElectrumWalletBase @observable SyncStatus syncStatus; - List get scriptHashes => walletAddresses.addresses - .map((addr) => scriptHash(addr.address, networkType: networkType)) - .toList(); + List get scriptHashes => + walletAddresses.addresses.map((addr) => scriptHash(addr.address, network: network)).toList(); List get publicScriptHashes => walletAddresses.addresses .where((addr) => !addr.isHidden) - .map((addr) => scriptHash(addr.address, networkType: networkType)) + .map((addr) => scriptHash(addr.address, network: network)) .toList(); String get xpub => hd.base58!; @@ -116,6 +122,7 @@ abstract class ElectrumWalletBase String get seed => mnemonic; bitcoin.NetworkType networkType; + BasedUtxoNetwork network; @override BitcoinWalletKeys get keys => @@ -310,7 +317,8 @@ abstract class ElectrumWalletBase outputs.forEach((item) { final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount; final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; - txb.addOutput(addressToOutputScript(outputAddress, networkType), outputAmount!); + txb.addOutput( + address_to_output_script.addressToOutputScript(outputAddress, network), outputAmount!); }); final estimatedSize = estimatedTransactionSize(inputs.length, outputs.length + 1); @@ -333,7 +341,7 @@ abstract class ElectrumWalletBase final keyPair = generateKeyPair( hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, index: input.bitcoinAddressRecord.index, - network: networkType); + network: network); final witnessValue = input.isP2wpkh ? input.value : null; txb.sign(vin: i, keyPair: keyPair, witnessValue: witnessValue); @@ -453,7 +461,7 @@ abstract class ElectrumWalletBase } bitcoin.ECPair keyPairFor({required int index}) => - generateKeyPair(hd: hd, index: index, network: networkType); + generateKeyPair(hd: hd, index: index, network: network); @override Future rescan({required int height}) async => throw UnimplementedError(); @@ -469,7 +477,7 @@ abstract class ElectrumWalletBase Future updateUnspent() async { final unspent = await Future.wait(walletAddresses.addresses.map((address) => electrumClient - .getListUnspentWithAddress(address.address, networkType) + .getListUnspentWithAddress(address.address, network) .then((unspent) => unspent.map((unspent) { try { return BitcoinUnspent.fromJSON(address, unspent); @@ -572,7 +580,7 @@ abstract class ElectrumWalletBase try { final tx = await getTransactionExpanded(hash: hash, height: height); final addresses = walletAddresses.addresses.map((addr) => addr.address).toSet(); - return ElectrumTransactionInfo.fromElectrumBundle(tx, walletInfo.type, networkType, + return ElectrumTransactionInfo.fromElectrumBundle(tx, walletInfo.type, network, addresses: addresses, height: height); } catch (_) { return null; @@ -584,7 +592,7 @@ abstract class ElectrumWalletBase final addressHashes = {}; final normalizedHistories = >[]; walletAddresses.addresses.forEach((addressRecord) { - final sh = scriptHash(addressRecord.address, networkType: networkType); + final sh = scriptHash(addressRecord.address, network: network); addressHashes[sh] = addressRecord; }); final histories = addressHashes.keys.map((scriptHash) => @@ -662,7 +670,7 @@ abstract class ElectrumWalletBase final balanceFutures = >>[]; for (var i = 0; i < addresses.length; i++) { final addressRecord = addresses[i]; - final sh = scriptHash(addressRecord.address, networkType: networkType); + final sh = scriptHash(addressRecord.address, network: network); final balanceFuture = electrumClient.getBalance(sh); balanceFutures.add(balanceFuture); } diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index aba0e246f..ee6001f3a 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -64,6 +64,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; } + @override + set address(String addr) => null; + @override @computed String get address { @@ -72,11 +75,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } try { - return receiveAddresses - .firstWhere((address) => addressPageType == BitcoinAddressType.p2wpkh - ? address.type == null || address.type == addressPageType - : address.type == addressPageType) - .address; + return receiveAddresses.firstWhere((address) { + print([1, address.address, address.type]); + return addressPageType == BitcoinAddressType.p2wpkh + ? address.type == null || address.type == addressPageType + : address.type == addressPageType; + }).address; } catch (_) {} return receiveAddresses.first.address; @@ -156,8 +160,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { isHidden: isHidden); addresses.add(address); return address; - - currentReceiveAddressIndex += 1; } String getAddress( @@ -177,10 +179,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action void updateReceiveAddresses() { + print(addresses.length); receiveAddresses.removeRange(0, receiveAddresses.length); final newAdresses = addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); - receiveAddresses.addAll(newAdresses); + receiveAddresses.addAll(addresses); + print(receiveAddresses.length); } @action @@ -223,9 +227,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { addrs.addAll(batch); } - if (addresses.length < addrs.length) { - addAddresses(addrs); - } + addAddresses(addrs); } Future _generateInitialAddresses() async { @@ -281,15 +283,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } Future _hasAddressUsed(String address) async { - final sh = scriptHash(address, networkType: network); + final sh = scriptHash(address, network: network); final transactionHistory = await electrumClient.getHistory(sh); return transactionHistory.isNotEmpty; } @override @action - Future setAddressType(dynamic type) async { - _addressPageType = type as BitcoinAddressType; + Future setAddressType(BitcoinAddressType type) async { + _addressPageType = type; await _discoverAddresses(mainHd, false, addressType: addressPageType); updateReceiveAddresses(); diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 6bf1c5735..54e30c7df 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -41,28 +41,26 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { seedBytes: seedBytes, currency: CryptoCurrency.ltc) { walletAddresses = LitecoinWalletAddresses( - walletInfo, - electrumClient: electrumClient, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd, - sideHd: bitcoin.HDWallet - .fromSeed(seedBytes, network: networkType) - .derivePath("m/0'/1"), - networkType: networkType,); + walletInfo, + electrumClient: electrumClient, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), + network: network, + ); } - static Future create({ - required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - 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, + List? initialAddresses, + ElectrumBalance? initialBalance, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) async { return LitecoinWallet( mnemonic: mnemonic, password: password, @@ -81,7 +79,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWallletSnapshot.load (name, walletInfo.type, password); + final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); return LitecoinWallet( mnemonic: snp.mnemonic, password: password, diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart index 4930ef5f3..ca631f617 100644 --- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart @@ -1,38 +1,28 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/utils.dart'; -import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:mobx/mobx.dart'; part 'litecoin_wallet_addresses.g.dart'; -class LitecoinWalletAddresses = LitecoinWalletAddressesBase - with _$LitecoinWalletAddresses; +class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses; -abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses - with Store { +abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store { LitecoinWalletAddressesBase( - WalletInfo walletInfo, - {required bitcoin.HDWallet mainHd, - required bitcoin.HDWallet sideHd, - required bitcoin.NetworkType networkType, - required ElectrumClient electrumClient, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super( - walletInfo, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: mainHd, - sideHd: sideHd, - electrumClient: electrumClient, - networkType: networkType); + WalletInfo walletInfo, { + required super.mainHd, + required super.sideHd, + required super.network, + required super.electrumClient, + super.initialAddresses, + super.initialRegularAddressIndex = 0, + super.initialChangeAddressIndex = 0, + }) : super(walletInfo); @override - String getAddress({required int index, required bitcoin.HDWallet hd}) => + String getAddress( + {required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) => generateP2WPKHAddress(hd: hd, index: index, network: network); } diff --git a/cw_bitcoin/lib/script_hash.dart b/cw_bitcoin/lib/script_hash.dart index cdc38361b..620d3d28a 100644 --- a/cw_bitcoin/lib/script_hash.dart +++ b/cw_bitcoin/lib/script_hash.dart @@ -1,26 +1,8 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:crypto/crypto.dart'; -String scriptHash(String address, {required bitcoin.NetworkType networkType}) { - try { - final outputScript = bitcoin.Address.addressToOutputScript(address, networkType); - final parts = sha256.convert(outputScript).toString().split(''); - var res = ''; - - for (var i = parts.length - 1; i >= 0; i--) { - final char = parts[i]; - i--; - final nextChar = parts[i]; - res += nextChar; - res += char; - } - - return res; - } catch (e) {} - return ''; -} - -String scriptHashFromScript(List outputScript, {required bitcoin.NetworkType networkType}) { +String scriptHash(String address, {required BasedUtxoNetwork network}) { + final outputScript = addressToOutputScript(address: address, network: network); final parts = sha256.convert(outputScript).toString().split(''); var res = ''; diff --git a/cw_bitcoin/lib/utils.dart b/cw_bitcoin/lib/utils.dart index ab2ae28b0..a63a43104 100644 --- a/cw_bitcoin/lib/utils.dart +++ b/cw_bitcoin/lib/utils.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:flutter/foundation.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; @@ -10,12 +11,21 @@ bitcoin.PaymentData generatePaymentData({required bitcoin.HDWallet hd, required bitcoin.ECPair generateKeyPair( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - bitcoin.ECPair.fromWIF(hd.derive(index).wif!, network: network); + bitcoin.ECPair.fromWIF(hd.derive(index).wif!, + network: network == BitcoinNetwork.mainnet + ? bitcoin.bitcoin + : network == LitecoinNetwork.mainnet + ? litecoinNetwork + : bitcoin.bitcoin); String generateP2WPKHAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => P2wpkhAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); +String generateP2WSHAddress( + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + P2wshAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); + String generateP2PKHAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => P2pkhAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 3344cb807..1ca78d86d 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/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: @@ -75,6 +75,15 @@ packages: url: "https://github.com/cake-tech/bitbox-flutter.git" source: git version: "1.0.1" + bitcoin_base: + dependency: "direct main" + description: + path: "." + ref: cake-update-v1 + resolved-ref: b5f0af48836250aa0f757a2a05b3e73e074f3c22 + url: "https://github.com/cake-tech/bitcoin_base.git" + source: git + version: "3.0.1" bitcoin_flutter: dependency: "direct main" description: @@ -84,6 +93,14 @@ packages: url: "https://github.com/cake-tech/bitcoin_flutter.git" source: git version: "2.1.0" + blockchain_utils: + dependency: "direct main" + description: + name: blockchain_utils + sha256: "9701dfaa74caad4daae1785f1ec4445cf7fb94e45620bc3a4aca1b9b281dc6c9" + url: "https://pub.dev" + source: hosted + version: "1.6.0" boolean_selector: dependency: transitive description: @@ -104,10 +121,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 +137,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.1" build_resolvers: dependency: "direct dev" description: @@ -136,18 +153,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.7" 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 +177,10 @@ packages: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + sha256: c9aabae0718ec394e5bc3c7272e6bb0dc0b32201a08fe185ec1d8401d3e39309 url: "https://pub.dev" source: hosted - version: "8.4.3" + version: "8.8.1" characters: dependency: transitive description: @@ -176,10 +193,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: @@ -192,10 +209,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.10.0" collection: dependency: transitive description: @@ -216,18 +233,18 @@ 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: name: cryptography - sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 + sha256: df156c5109286340817d21fa7b62f9140f17915077127dd70f8bd7a2a0997a35 url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.5.0" cw_core: dependency: "direct main" description: @@ -247,10 +264,10 @@ packages: dependency: transitive 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: @@ -263,10 +280,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: @@ -292,10 +309,10 @@ packages: dependency: "direct main" description: name: flutter_mobx - sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" + sha256: "4a5d062ff85ed3759f4aac6410ff0ffae32e324b2e71ca722ae1b37b32e865f4" url: "https://pub.dev" source: hosted - version: "2.0.6+5" + version: "2.2.0+2" flutter_test: dependency: "direct dev" description: flutter @@ -313,18 +330,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: @@ -401,18 +418,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: @@ -449,18 +466,26 @@ packages: dependency: "direct main" description: name: mobx - sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a + sha256: "74ee54012dc7c1b3276eaa960a600a7418ef5f9997565deb8fca1fd88fb36b78" url: "https://pub.dev" source: hosted - version: "2.1.3+1" + version: "2.3.0+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: @@ -481,18 +506,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_foundation: dependency: transitive description: @@ -513,10 +538,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -529,26 +554,26 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.8" 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: @@ -557,30 +582,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: + provider: dependency: transitive description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "6.1.1" 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" rxdart: dependency: "direct main" description: @@ -593,18 +618,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 @@ -702,10 +727,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" unorm_dart: dependency: "direct main" description: @@ -726,42 +751,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: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.4" 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.7.0" + flutter: ">=3.10.0" diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index d3b165c74..847b77773 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -34,6 +34,7 @@ dependencies: git: url: https://github.com/cake-tech/bitcoin_base.git ref: cake-update-v1 + blockchain_utils: ^1.6.0 dev_dependencies: flutter_test: diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index c23220423..dc4468a85 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -54,12 +54,10 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes) - .derivePath("m/44'/145'/0'/1"), - networkType: networkType); + sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"), + network: network); } - static Future create( {required String mnemonic, required String password, @@ -267,9 +265,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { electrumClient: electrumClient, amount: amount, fee: fee); } - bitbox.ECPair generateKeyPair( - {required bitcoin.HDWallet hd, - required int index}) => + bitbox.ECPair generateKeyPair({required bitcoin.HDWallet hd, required int index}) => bitbox.ECPair.fromWIF(hd.derive(index).wif!); @override @@ -322,7 +318,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { final index = address != null ? walletAddresses.addresses .firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address)) - .index : null; + .index + : null; final HD = index == null ? hd : hd.derive(index); return base64Encode(HD.signMessage(message)); } diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart index 1709c4d8f..508c6b34d 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -1,6 +1,5 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/utils.dart'; import 'package:cw_core/wallet_info.dart'; @@ -11,24 +10,19 @@ part 'bitcoin_cash_wallet_addresses.g.dart'; class BitcoinCashWalletAddresses = BitcoinCashWalletAddressesBase with _$BitcoinCashWalletAddresses; abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses with Store { - BitcoinCashWalletAddressesBase(WalletInfo walletInfo, - {required bitcoin.HDWallet mainHd, - required bitcoin.HDWallet sideHd, - required bitcoin.NetworkType networkType, - required ElectrumClient electrumClient, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super(walletInfo, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: mainHd, - sideHd: sideHd, - electrumClient: electrumClient, - networkType: networkType); + BitcoinCashWalletAddressesBase( + WalletInfo walletInfo, { + required super.mainHd, + required super.sideHd, + required super.network, + required super.electrumClient, + super.initialAddresses, + super.initialRegularAddressIndex = 0, + super.initialChangeAddressIndex = 0, + }) : super(walletInfo); @override - String getAddress({required int index, required bitcoin.HDWallet hd}) => - generateP2PKHAddress(hd: hd, index: index, networkType: networkType); + String getAddress( + {required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) => + generateP2PKHAddress(hd: hd, index: index, network: network); } diff --git a/cw_core/lib/receive_page_options.dart b/cw_core/lib/receive_page_options.dart new file mode 100644 index 000000000..46fb1a49a --- /dev/null +++ b/cw_core/lib/receive_page_options.dart @@ -0,0 +1,52 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; + +class CoreReceivePageOption { + static const mainnet = CoreReceivePageOption._('mainnet'); + static const anonPayInvoice = CoreReceivePageOption._('anonPayInvoice'); + static const anonPayDonationLink = CoreReceivePageOption._('anonPayDonationLink'); + + const CoreReceivePageOption._(this._value); + + final String _value; +} + +const ReceivePageOptions = [ + CoreReceivePageOption.mainnet, + CoreReceivePageOption.anonPayInvoice, + CoreReceivePageOption.anonPayDonationLink +]; + +class BitcoinReceivePageOption extends CoreReceivePageOption { + static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH)'); + static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)'); + static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)'); + static const p2pkh = BitcoinReceivePageOption._('Legacy (P2PKH)'); + + const BitcoinReceivePageOption._(String value) : super._(value); + + factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) { + switch (type) { + case BitcoinAddressType.p2tr: + return BitcoinReceivePageOption.p2tr; + case BitcoinAddressType.p2wsh: + return BitcoinReceivePageOption.p2wsh; + case BitcoinAddressType.p2pkh: + return BitcoinReceivePageOption.p2pkh; + case BitcoinAddressType.p2wpkh: + default: + return BitcoinReceivePageOption.p2wpkh; + } + } + + @override + String toString() { + return _value; + } +} + +const BitcoinReceivePageOptions = [ + BitcoinReceivePageOption.p2wpkh, + BitcoinReceivePageOption.p2tr, + BitcoinReceivePageOption.p2wsh, + BitcoinReceivePageOption.p2pkh +]; diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index aacbd9ddd..8ca9fb3c9 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -5,34 +5,34 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 url: "https://pub.dev" source: hosted - version: "47.0.0" + version: "64.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "6.2.0" args: 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: @@ -41,6 +41,23 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + bitcoin_base: + dependency: "direct main" + description: + path: "." + ref: cake-update-v1 + resolved-ref: b5f0af48836250aa0f757a2a05b3e73e074f3c22 + url: "https://github.com/cake-tech/bitcoin_base.git" + source: git + version: "3.0.1" + blockchain_utils: + dependency: transitive + description: + name: blockchain_utils + sha256: "9701dfaa74caad4daae1785f1ec4445cf7fb94e45620bc3a4aca1b9b281dc6c9" + url: "https://pub.dev" + source: hosted + version: "1.6.0" boolean_selector: dependency: transitive description: @@ -53,10 +70,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,34 +86,34 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.1" build_resolvers: dependency: "direct dev" description: name: build_resolvers - sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.0.10" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.7" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 url: "https://pub.dev" source: hosted - version: "7.2.7" + version: "7.2.11" built_collection: dependency: transitive description: @@ -109,10 +126,10 @@ packages: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + sha256: c9aabae0718ec394e5bc3c7272e6bb0dc0b32201a08fe185ec1d8401d3e39309 url: "https://pub.dev" source: hosted - version: "8.4.3" + version: "8.8.1" characters: dependency: transitive description: @@ -125,10 +142,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: @@ -141,10 +158,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.10.0" collection: dependency: transitive description: @@ -165,26 +182,26 @@ packages: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" dart_style: dependency: transitive description: name: dart_style - sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.3.4" 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: @@ -197,10 +214,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: "direct main" description: @@ -226,10 +243,10 @@ packages: dependency: "direct main" description: name: flutter_mobx - sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" + sha256: "4a5d062ff85ed3759f4aac6410ff0ffae32e324b2e71ca722ae1b37b32e865f4" url: "https://pub.dev" source: hosted - version: "2.0.6+5" + version: "2.2.0+2" flutter_test: dependency: "direct dev" description: flutter @@ -247,18 +264,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: @@ -327,18 +344,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: @@ -375,18 +392,26 @@ packages: dependency: "direct main" description: name: mobx - sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a + sha256: "74ee54012dc7c1b3276eaa960a600a7418ef5f9997565deb8fca1fd88fb36b78" url: "https://pub.dev" source: hosted - version: "2.1.3+1" + version: "2.3.0+1" mobx_codegen: dependency: "direct dev" description: name: mobx_codegen - sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" + sha256: b26c7f9c20b38f0ea572c1ed3f29d8e027cb265538bbd1aed3ec198642cfca42 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.6.0+1" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" package_config: dependency: transitive description: @@ -407,18 +432,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_foundation: dependency: transitive description: @@ -439,10 +464,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -455,26 +480,26 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.8" 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: @@ -483,46 +508,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: + provider: dependency: transitive description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "6.1.1" 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 @@ -540,18 +565,18 @@ packages: dependency: transitive description: name: source_gen - sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.2.6" + version: "1.5.0" source_helper: dependency: transitive description: name: source_helper - sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" url: "https://pub.dev" source: hosted - version: "1.3.3" + version: "1.3.4" source_span: dependency: transitive description: @@ -620,10 +645,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: @@ -636,42 +661,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: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.4" 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.7.0" + flutter: ">=3.10.0" diff --git a/cw_haven/pubspec.lock b/cw_haven/pubspec.lock index b0a350cc7..2a7bdaa44 100644 --- a/cw_haven/pubspec.lock +++ b/cw_haven/pubspec.lock @@ -41,6 +41,23 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + bitcoin_base: + dependency: transitive + description: + path: "." + ref: cake-update-v1 + resolved-ref: cf04ecee73316431230083a236392d1a87697b43 + url: "https://github.com/cake-tech/bitcoin_base.git" + source: git + version: "3.0.1" + blockchain_utils: + dependency: transitive + description: + name: blockchain_utils + sha256: "345706b5cbfd7e2daea5d210504a4d6ec589e40bf40b5b4946e1fdd9bf59320d" + url: "https://pub.dev" + source: hosted + version: "1.5.0" boolean_selector: dependency: transitive description: diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index c9ca8d92b..e3e0db311 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -25,6 +25,23 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + bitcoin_base: + dependency: transitive + description: + path: "." + ref: cake-update-v1 + resolved-ref: cf04ecee73316431230083a236392d1a87697b43 + url: "https://github.com/cake-tech/bitcoin_base.git" + source: git + version: "3.0.1" + blockchain_utils: + dependency: transitive + description: + name: blockchain_utils + sha256: "345706b5cbfd7e2daea5d210504a4d6ec589e40bf40b5b4946e1fdd9bf59320d" + url: "https://pub.dev" + source: hosted + version: "1.5.0" boolean_selector: dependency: transitive description: diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 0f8f2c90e..beba80932 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -41,6 +41,23 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + bitcoin_base: + dependency: transitive + description: + path: "." + ref: cake-update-v1 + resolved-ref: cf04ecee73316431230083a236392d1a87697b43 + url: "https://github.com/cake-tech/bitcoin_base.git" + source: git + version: "3.0.1" + blockchain_utils: + dependency: transitive + description: + name: blockchain_utils + sha256: "345706b5cbfd7e2daea5d210504a4d6ec589e40bf40b5b4946e1fdd9bf59320d" + url: "https://pub.dev" + source: hosted + version: "1.5.0" boolean_selector: dependency: transitive description: diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index 4a5496fa6..38ea6d241 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -57,6 +57,23 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + bitcoin_base: + dependency: transitive + description: + path: "." + ref: cake-update-v1 + resolved-ref: cf04ecee73316431230083a236392d1a87697b43 + url: "https://github.com/cake-tech/bitcoin_base.git" + source: git + version: "3.0.1" + blockchain_utils: + dependency: transitive + description: + name: blockchain_utils + sha256: "345706b5cbfd7e2daea5d210504a4d6ec589e40bf40b5b4946e1fdd9bf59320d" + url: "https://pub.dev" + source: hosted + version: "1.5.0" boolean_selector: dependency: transitive description: @@ -764,15 +781,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - tor: - dependency: transitive - description: - path: "." - ref: main - resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" - url: "https://github.com/cake-tech/tor.git" - source: git - version: "0.0.1" typed_data: dependency: transitive description: diff --git a/lib/entities/receive_page_option.dart b/lib/entities/receive_page_option.dart index cb04c9da0..8127b0d73 100644 --- a/lib/entities/receive_page_option.dart +++ b/lib/entities/receive_page_option.dart @@ -1,22 +1,66 @@ -enum ReceivePageOption { - mainnet, - anonPayInvoice, - anonPayDonationLink; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:bitcoin_base/bitcoin_base.dart'; + +class ReceivePageOption { + static const mainnet = ReceivePageOption._('mainnet'); + static const anonPayInvoice = ReceivePageOption._('anonPayInvoice'); + static const anonPayDonationLink = ReceivePageOption._('anonPayDonationLink'); + + const ReceivePageOption._(this._value); + + final String _value; @override String toString() { - String label = ''; switch (this) { case ReceivePageOption.mainnet: - label = S.current.mainnet; - break; + return S.current.mainnet; case ReceivePageOption.anonPayInvoice: - label = S.current.trocador_anonpay_invoice; - break; + return S.current.trocador_anonpay_invoice; case ReceivePageOption.anonPayDonationLink: - label = S.current.trocador_anonpay_donation_link; - break; + return S.current.trocador_anonpay_donation_link; } - return label; + return ""; } } + +const ReceivePageOptions = [ + ReceivePageOption.mainnet, + ReceivePageOption.anonPayInvoice, + ReceivePageOption.anonPayDonationLink +]; + +class BitcoinReceivePageOption extends ReceivePageOption { + static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH)'); + static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)'); + static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)'); + static const p2pkh = BitcoinReceivePageOption._('Legacy (P2PKH)'); + + const BitcoinReceivePageOption._(String value) : super._(value); + + factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) { + switch (type) { + case BitcoinAddressType.p2tr: + return BitcoinReceivePageOption.p2tr; + case BitcoinAddressType.p2wsh: + return BitcoinReceivePageOption.p2wsh; + case BitcoinAddressType.p2pkh: + return BitcoinReceivePageOption.p2pkh; + case BitcoinAddressType.p2wpkh: + default: + return BitcoinReceivePageOption.p2wpkh; + } + } + + @override + String toString() { + return _value; + } +} + +const BitcoinReceivePageOptions = [ + BitcoinReceivePageOption.p2wpkh, + BitcoinReceivePageOption.p2tr, + BitcoinReceivePageOption.p2wsh, + BitcoinReceivePageOption.p2pkh +]; diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index ff21d4aad..a943e1be7 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -25,6 +25,8 @@ import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart'; class AddressPage extends BasePage { AddressPage({ @@ -67,7 +69,7 @@ class AddressPage extends BasePage { size: 16, ); final _closeButton = - currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; + currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI; @@ -263,6 +265,18 @@ class AddressPage extends BasePage { ); } break; + case BitcoinReceivePageOption.p2pkh: + addressListViewModel.setAddressType(BitcoinAddressType.p2pkh); + break; + case BitcoinReceivePageOption.p2wpkh: + addressListViewModel.setAddressType(BitcoinAddressType.p2wpkh); + break; + case BitcoinReceivePageOption.p2tr: + addressListViewModel.setAddressType(BitcoinAddressType.p2tr); + break; + case BitcoinReceivePageOption.p2wsh: + addressListViewModel.setAddressType(BitcoinAddressType.p2wsh); + break; default: } }); diff --git a/lib/view_model/dashboard/receive_option_view_model.dart b/lib/view_model/dashboard/receive_option_view_model.dart index 0eaa2a5f0..20e5c424d 100644 --- a/lib/view_model/dashboard/receive_option_view_model.dart +++ b/lib/view_model/dashboard/receive_option_view_model.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -9,11 +10,21 @@ class ReceiveOptionViewModel = ReceiveOptionViewModelBase with _$ReceiveOptionVi abstract class ReceiveOptionViewModelBase with Store { ReceiveOptionViewModelBase(this._wallet, this.initialPageOption) - : selectedReceiveOption = initialPageOption ?? ReceivePageOption.mainnet, + : selectedReceiveOption = initialPageOption ?? + (_wallet.type == WalletType.bitcoin + ? BitcoinReceivePageOption.fromType( + (_wallet.walletAddresses as ElectrumWalletAddresses).addressPageType) + : ReceivePageOption.mainnet), _options = [] { final walletType = _wallet.type; - _options = - walletType == WalletType.haven ? [ReceivePageOption.mainnet] : ReceivePageOption.values; + _options = walletType == WalletType.haven + ? [ReceivePageOption.mainnet] + : walletType == WalletType.bitcoin + ? [ + ...BitcoinReceivePageOptions, + ...ReceivePageOptions.where((element) => element != ReceivePageOption.mainnet) + ] + : ReceivePageOptions; } final WalletBase _wallet; 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 ade279124..195c69702 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 @@ -4,6 +4,7 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; +import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_core/currency.dart'; import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; @@ -110,7 +111,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; @@ -121,9 +122,7 @@ class BitcoinCashURI extends PaymentURI { return base; } - } - - +} class NanoURI extends PaymentURI { NanoURI({required String amount, required String address}) @@ -321,15 +320,17 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo @computed bool get hasAddressList => 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; @@ -339,13 +340,23 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo void setAddress(WalletAddressListItem address) => wallet.walletAddresses.address = address.address; + @action + Future setAddressType(dynamic option) async { + if (wallet.type == WalletType.bitcoin) { + await (wallet.walletAddresses as ElectrumWalletAddresses).setAddressType(option); + } + } + void _init() { _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 45306905c..31e484864 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -78,7 +78,8 @@ abstract class WalletCreationVMBase with Store { getIt.get().registerSyncTask(); _appStore.authenticationStore.allowed(); state = ExecutedSuccessfullyState(); - } catch (e) { + } catch (e, s) { + print([e, s]); state = FailureState(e.toString()); } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 95871b904..97a6d1465 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -759,5 +759,8 @@ "default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ", "custom_drag": "مخصص (عقد وسحب)", - "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" -} + "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "mainnet": "mainnet", + "trocador_anonpay_donation_link": "رابط التبرع Trocador Anonpay", + "trocador_anonpay_invoice": "فاتورة Trocador Anonpay" +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 197dbe552..24804806f 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -755,5 +755,8 @@ "default_sell_provider": "Доставчик за продажба по подразбиране", "select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.", "custom_drag": "Персонализиране (задръжте и плъзнете)", - "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Трокадорна връзка за дарение на Anonpay", + "trocador_anonpay_invoice": "Трокадорна фактура Anonpay" +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index bed4e3193..01536cb54 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -755,5 +755,8 @@ "default_sell_provider": "Výchozí poskytovatel prodeje", "select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Trocador anonpay dar odkaz", + "trocador_anonpay_invoice": "Faktura Trocador AnonPay" +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 1d63bffc6..f52df1fbd 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Standard-Verkaufsanbieter", "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)", + "mainnet": "Hauptnetz", + "trocador_anonpay_donation_link": "Trocador Anonpay Spendenlink", + "trocador_anonpay_invoice": "Trocador Anonpay In Rechnung" +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index e6c95270e..71bb8e5cd 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -764,5 +764,8 @@ "default_sell_provider": "Default Sell Provider", "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Trocador AnonPay Donation Link", + "trocador_anonpay_invoice": "Trocador AnonPay Invoice" +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 6ee0f509c..86bf04238 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Proveedor de venta predeterminado", "select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.", "custom_drag": "Custom (mantenía y arrastre)", - "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)", + "mainnet": "Red", + "trocador_anonpay_donation_link": "Trocador Anonpay Donation Link", + "trocador_anonpay_invoice": "Trocador Anonpay Factura" +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 862f9ae7d..d7fbc008f 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Fournisseur de vente par défaut", "select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.", "custom_drag": "Custom (maintenir et traîner)", - "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)", + "mainnet": "MainNet", + "trocador_anonpay_donation_link": "Lien de don du Trocador anonpay", + "trocador_anonpay_invoice": "Facture anonpay du Trocador" +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 9456085dc..0bdac2939 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -745,5 +745,8 @@ "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", "select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.", "custom_drag": "Al'ada (riƙe da ja)", - "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", + "mainnet": "Otnet", + "trocador_anonpay_donation_link": "Hanyar bayar da gudummawa na Trorojador", + "trocador_anonpay_invoice": "Atroador Antonpay" +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f6a7701ee..9b3fc3173 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -763,5 +763,8 @@ "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", "select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", "custom_drag": "कस्टम (पकड़ और खींचें)", - "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)" -} + "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)", + "mainnet": "मेननेट", + "trocador_anonpay_donation_link": "Trocador anonpay दान लिंक", + "trocador_anonpay_invoice": "Trocador anonpay चालान" +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 3565c89a0..d7b7b4ff4 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -761,5 +761,8 @@ "default_sell_provider": "Zadani dobavljač prodaje", "select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.", "custom_drag": "Prilagođeni (držite i povucite)", - "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Link za donaciju trokadora", + "trocador_anonpay_invoice": "Trokador anonpay faktura" +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 6744f0a38..26b70df06 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -751,5 +751,8 @@ "default_sell_provider": "Penyedia Penjualan Default", "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.", "custom_drag": "Khusus (tahan dan seret)", - "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Tautan donasi trocador anonpay", + "trocador_anonpay_invoice": "Faktur Trocador Anonpay" +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index bb909a7e0..a99abeb08 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Fornitore di vendita predefinito", "select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Link di donazione di Trocador Anonpay", + "trocador_anonpay_invoice": "Trocador Anonpay fattura" +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 2152a3dcc..e4906c29f 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -763,5 +763,8 @@ "default_sell_provider": "デフォルトの販売プロバイダー", "select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。", "custom_drag": "カスタム(ホールドとドラッグ)", - "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)" -} + "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)", + "mainnet": "メインネット", + "trocador_anonpay_donation_link": "Trocador Anonpay寄付リンク", + "trocador_anonpay_invoice": "Trocador Anonpay Invoice" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 5ad5482ed..4a5501b5e 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -761,5 +761,8 @@ "default_sell_provider": "기본 판매 공급자", "select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.", "custom_drag": "사용자 정의 (홀드 앤 드래그)", - "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)" -} + "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)", + "mainnet": "메인 넷", + "trocador_anonpay_donation_link": "Trocador Anonpay 기부 링크", + "trocador_anonpay_invoice": "Trocador Anonpay 송장" +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 73f4e5dcd..945b0dd1d 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -761,5 +761,8 @@ "default_sell_provider": "ပုံသေရောင်းချပေးသူ", "select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။", "custom_drag": "စိတ်ကြိုက် (Drag)", - "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)" -} + "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)", + "mainnet": "မမက်မ", + "trocador_anonpay_donation_link": "Trocador Anonpay အလှူငွေလင့်ခ်", + "trocador_anonpay_invoice": "Trocador Anonpay ငွေတောင်းခံလွှာ" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 6cf41e0b9..ca81591cf 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Standaard verkoopaanbieder", "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.", "custom_drag": "Custom (vasthouden en slepen)", - "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)", + "mainnet": "Heuvel", + "trocador_anonpay_donation_link": "Trocador anonpay donatielink", + "trocador_anonpay_invoice": "Trocador anonpay factuur" +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 9d3fb3f93..f00336448 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Domyślny dostawca sprzedaży", "select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.", "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", - "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Link darowizny Trocador Anonpay", + "trocador_anonpay_invoice": "Trocador anonpay faktura" +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 5cf1fd370..1cc5c3acc 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -762,5 +762,8 @@ "default_sell_provider": "Provedor de venda padrão", "select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.", "custom_drag": "Personalizado (segure e arraste)", - "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Link de doação de Trocador Anonpay", + "trocador_anonpay_invoice": "Trocador ANONPAY Fatura" +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c81c0bd82..8267729e8 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Поставщик продаж по умолчанию", "select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.", "custom_drag": "Пользователь (удерживайте и перетаскивайте)", - "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)." -} + "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon).", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Ссылка пожертвования Trocador Anonpay", + "trocador_anonpay_invoice": "Трокадор Анонпай" +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 0965d3979..cbd5296d9 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -761,5 +761,8 @@ "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", "select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป", "custom_drag": "กำหนดเอง (ค้างและลาก)", - "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", + "mainnet": "หลัก", + "trocador_anonpay_donation_link": "ลิงค์บริจาค Trocador Anonpay", + "trocador_anonpay_invoice": "ใบแจ้งหนี้ Trocador Anonpay" +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index f9bbb5dea..5874692ac 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -757,5 +757,8 @@ "default_sell_provider": "Default na Sell Provider", "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", "custom_drag": "Pasadyang (hawakan at i -drag)", - "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)", + "mainnet": "Mainnet", + "trocador_anonpay_donation_link": "Trocador Anonpay Donation Link", + "trocador_anonpay_invoice": "Trocador Anonpay Invoice" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 6fdb8bb99..420aeb6d6 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -761,5 +761,8 @@ "default_sell_provider": "Varsayılan Satış Sağlayıcısı", "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", "custom_drag": "Özel (Bekle ve Sürükle)", - "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", + "mainnet": "Ana ağ", + "trocador_anonpay_donation_link": "Trocador anonpay bağış bağlantısı", + "trocador_anonpay_invoice": "Trocador anonpay faturası" +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 721a3970d..cdb51f7fb 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Постачальник продажу за замовчуванням", "select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.", "custom_drag": "На замовлення (утримуйте та перетягується)", - "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)", + "mainnet": "Мейннет", + "trocador_anonpay_donation_link": "Посилання на пожертву Trocador Anonpay", + "trocador_anonpay_invoice": "Рахунок -фактура Trocador Anonpay" +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e4a9f4590..d10d4a183 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -755,5 +755,8 @@ "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", "select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ", "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", - "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ " -} + "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ", + "mainnet": "مینیٹ", + "trocador_anonpay_donation_link": "ٹروکاڈور انونپے چندہ کا لنک", + "trocador_anonpay_invoice": "ٹروکاڈور انون پے انوائس" +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 964307e6b..106abdd6c 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -757,5 +757,8 @@ "default_sell_provider": "Aiyipada Olupese Tita", "select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.", "custom_drag": "Aṣa (mu ati fa)", - "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)", + "mainnet": "Akọkọ", + "trocador_anonpay_donation_link": "Ọna asopọ Ẹbun Anontay Anontay", + "trocador_anonpay_invoice": "Tragbar anonpaya risiti" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 43e8c6ce1..8a83f2675 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -762,5 +762,8 @@ "default_sell_provider": "默认销售提供商", "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。", "custom_drag": "定制(保持和拖动)", - "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)" -} + "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)", + "mainnet": "主网", + "trocador_anonpay_donation_link": "trocador anonpay捐赠链接", + "trocador_anonpay_invoice": "Trocador Anonpay发票" +} \ No newline at end of file From 1556cf8238a4cb17bfeb28b27b235cfb07b3cba6 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 12 Jan 2024 00:05:56 +0200 Subject: [PATCH 03/59] minor fix [skip ci] --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 5 +---- lib/bitcoin/cw_bitcoin.dart | 6 ++++++ .../wallet_address_list_view_model.dart | 20 ++++--------------- tool/configure.dart | 3 +++ 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index ee6001f3a..1466701ee 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -179,12 +179,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action void updateReceiveAddresses() { - print(addresses.length); receiveAddresses.removeRange(0, receiveAddresses.length); final newAdresses = addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); - receiveAddresses.addAll(addresses); - print(receiveAddresses.length); + receiveAddresses.addAll(newAdresses); } @action @@ -288,7 +286,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return transactionHistory.isNotEmpty; } - @override @action Future setAddressType(BitcoinAddressType type) async { _addressPageType = type; diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index dd713fd15..f26b39c68 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -155,4 +155,10 @@ class CWBitcoin extends Bitcoin { @override TransactionPriority getLitecoinTransactionPrioritySlow() => LitecoinTransactionPriority.slow; + + @override + Future setAddressType(Object wallet, dynamic option) async { + final bitcoinWallet = wallet as ElectrumWallet; + await bitcoinWallet.walletAddresses.setAddressType(option as BitcoinAddressType); + } } \ No newline at end of file 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 195c69702..3d131dc23 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 @@ -4,7 +4,6 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; -import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_core/currency.dart'; import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; @@ -112,6 +111,7 @@ class EthereumURI extends PaymentURI { class BitcoinCashURI extends PaymentURI { BitcoinCashURI({required String amount, required String address}) : super(amount: amount, address: address); + @override String toString() { var base = address; @@ -318,13 +318,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo } @computed - bool get hasAddressList => - wallet.type == WalletType.monero || - wallet.type == - WalletType - .haven; /* || - wallet.type == WalletType.nano || - wallet.type == WalletType.banano;*/ // TODO: nano accounts are disabled for now + bool get hasAddressList => wallet.type == WalletType.monero || wallet.type == WalletType.haven; @computed bool get showElectrumAddressDisclaimer => @@ -343,20 +337,14 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo @action Future setAddressType(dynamic option) async { if (wallet.type == WalletType.bitcoin) { - await (wallet.walletAddresses as ElectrumWalletAddresses).setAddressType(option); + await bitcoin!.setAddressType(wallet, option); } } void _init() { _baseItems = []; - if (wallet.type == WalletType.monero || - wallet.type == - WalletType - .haven /*|| - wallet.type == WalletType.nano || - wallet.type == WalletType.banano*/ - ) { + if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) { _baseItems.add(WalletAccountListHeader()); } diff --git a/tool/configure.dart b/tool/configure.dart index 67732faa9..5fc7d3d47 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -76,6 +76,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_base/bitcoin_base.dart'; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; const bitcoinContent = """ @@ -112,6 +113,8 @@ abstract class Bitcoin { TransactionPriority getLitecoinTransactionPriorityMedium(); TransactionPriority getBitcoinTransactionPrioritySlow(); TransactionPriority getLitecoinTransactionPrioritySlow(); + + Future setAddressType(Object wallet, dynamic option); } """; From b700f846f67d89ffb17b9e8bc8406f5ae27ab423 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 12 Jan 2024 10:58:28 -0300 Subject: [PATCH 04/59] fix: P2wshAddress & wallet address index --- cw_bitcoin/lib/bitcoin_wallet.dart | 9 ++-- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 4 +- cw_bitcoin/lib/electrum_wallet.dart | 5 +- cw_bitcoin/lib/electrum_wallet_addresses.dart | 26 ++++++---- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 47 +++++++++---------- cw_bitcoin/lib/litecoin_wallet.dart | 8 ++-- cw_bitcoin/lib/litecoin_wallet_addresses.dart | 4 +- cw_bitcoin/pubspec.lock | 10 ++-- .../lib/src/bitcoin_cash_wallet.dart | 8 ++-- .../src/bitcoin_cash_wallet_addresses.dart | 4 +- cw_core/pubspec.lock | 10 ++-- 11 files changed, 70 insertions(+), 65 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 3334eb464..04e988142 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -25,8 +25,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required Uint8List seedBytes, List? initialAddresses, ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}}) : super( mnemonic: mnemonic, password: password, @@ -54,8 +54,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, List? initialAddresses, ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) async { + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}}) async { return BitcoinWallet( mnemonic: mnemonic, password: password, @@ -87,4 +87,3 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialChangeAddressIndex: snp.changeAddressIndex); } } - diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index c857bc438..cbc086839 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -17,8 +17,8 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S required super.network, required super.electrumClient, super.initialAddresses, - super.initialRegularAddressIndex = 0, - super.initialChangeAddressIndex = 0, + super.initialRegularAddressIndex = const {}, + super.initialChangeAddressIndex = const {}, }) : super(walletInfo); @override diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index f9188cc22..160646e97 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -357,9 +357,10 @@ abstract class ElectrumWalletBase String toJSON() => json.encode({ 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), - 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), + 'account_index': walletAddresses.currentChangeAddressIndexByType.toString(), + 'change_address_index': walletAddresses.currentChangeAddressIndexByType.toString(), 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), + 'address_page_type': walletAddresses.addressPageType, 'balance': balance[currency]?.toJSON() }); diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 1466701ee..fe3b0dd55 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -21,8 +21,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { required this.electrumClient, required this.network, List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0, + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}, }) : addresses = ObservableList.of((initialAddresses ?? []).toSet()), receiveAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed) @@ -30,8 +30,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { changeAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed) .toSet()), - currentReceiveAddressIndex = initialRegularAddressIndex, - currentChangeAddressIndex = initialChangeAddressIndex, + currentReceiveAddressIndexByType = initialRegularAddressIndex, + currentChangeAddressIndexByType = initialChangeAddressIndex, super(walletInfo); static const defaultReceiveAddressesCount = 22; @@ -71,12 +71,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @computed String get address { if (receiveAddresses.isEmpty) { - return generateNewAddress().address; + final address = generateNewAddress().address; + return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address; } try { return receiveAddresses.firstWhere((address) { - print([1, address.address, address.type]); return addressPageType == BitcoinAddressType.p2wpkh ? address.type == null || address.type == addressPageType : address.type == addressPageType; @@ -86,8 +86,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return receiveAddresses.first.address; } - int currentReceiveAddressIndex; - int currentChangeAddressIndex; + Map currentReceiveAddressIndexByType = {}; + int get currentReceiveAddressIndex => + currentReceiveAddressIndexByType[_addressPageType.toString()] ?? 0; + void set currentReceiveAddressIndex(int index) => + currentReceiveAddressIndexByType[_addressPageType.toString()] = index; + + Map currentChangeAddressIndexByType = {}; + int get currentChangeAddressIndex => + currentChangeAddressIndexByType[_addressPageType.toString()] ?? 0; + void set currentChangeAddressIndex(int index) => + currentChangeAddressIndexByType[_addressPageType.toString()] = index; @computed int get totalCountOfReceiveAddresses => addresses.fold(0, (acc, addressRecord) { @@ -152,6 +161,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action BitcoinAddressRecord generateNewAddress( {bitcoin.HDWallet? hd, bool isHidden = false, String? label}) { + currentReceiveAddressIndex += 1; // FIX-ME: Check logic for whichi HD should be used here ??? final address = BitcoinAddressRecord( getAddress( diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 86d3e2fed..01deb4e90 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -6,15 +6,15 @@ import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_type.dart'; class ElectrumWallletSnapshot { - ElectrumWallletSnapshot({ - required this.name, - required this.type, - required this.password, - required this.mnemonic, - required this.addresses, - required this.balance, - required this.regularAddressIndex, - required this.changeAddressIndex}); + ElectrumWallletSnapshot( + {required this.name, + required this.type, + required this.password, + required this.mnemonic, + required this.addresses, + required this.balance, + required this.regularAddressIndex, + required this.changeAddressIndex}); final String name; final String password; @@ -23,8 +23,8 @@ class ElectrumWallletSnapshot { String mnemonic; List addresses; ElectrumBalance balance; - int regularAddressIndex; - int changeAddressIndex; + Map regularAddressIndex; + Map changeAddressIndex; static Future load(String name, WalletType type, String password) async { final path = await pathForWallet(name: name, type: type); @@ -38,22 +38,17 @@ class ElectrumWallletSnapshot { .toList(); final balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); - var regularAddressIndex = 0; - var changeAddressIndex = 0; - - try { - regularAddressIndex = int.parse(data['account_index'] as String? ?? '0'); - changeAddressIndex = int.parse(data['change_address_index'] as String? ?? '0'); - } catch (_) {} + final regularAddressIndexByType = data["account_index"] as Map? ?? {}; + final changeAddressIndexByType = data["change_address_index"] as Map? ?? {}; return ElectrumWallletSnapshot( - name: name, - type: type, - password: password, - mnemonic: mnemonic, - addresses: addresses, - balance: balance, - regularAddressIndex: regularAddressIndex, - changeAddressIndex: changeAddressIndex); + name: name, + type: type, + password: password, + mnemonic: mnemonic, + addresses: addresses, + balance: balance, + regularAddressIndex: regularAddressIndexByType, + changeAddressIndex: changeAddressIndexByType); } } diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 54e30c7df..7b96157ce 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -28,8 +28,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required Uint8List seedBytes, List? initialAddresses, ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}}) : super( mnemonic: mnemonic, password: password, @@ -59,8 +59,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, List? initialAddresses, ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) async { + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}}) async { return LitecoinWallet( mnemonic: mnemonic, password: password, diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart index ca631f617..f7d49b64d 100644 --- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart @@ -17,8 +17,8 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with required super.network, required super.electrumClient, super.initialAddresses, - super.initialRegularAddressIndex = 0, - super.initialChangeAddressIndex = 0, + super.initialRegularAddressIndex = const {}, + super.initialChangeAddressIndex = const {}, }) : super(walletInfo); @override diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 1ca78d86d..3af7b8505 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: b5f0af48836250aa0f757a2a05b3e73e074f3c22 + resolved-ref: ae3030bc30039e8e58241a6e9e5e007079d5aea6 url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "3.0.1" @@ -153,10 +153,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b" + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" url: "https://pub.dev" source: hosted - version: "2.4.7" + version: "2.4.8" build_runner_core: dependency: transitive description: @@ -522,10 +522,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" path_provider_linux: dependency: transitive description: diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index dc4468a85..23b67fd74 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -36,8 +36,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { required Uint8List seedBytes, List? initialAddresses, ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}}) : super( mnemonic: mnemonic, password: password, @@ -65,8 +65,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, List? initialAddresses, ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) async { + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}}) async { return BitcoinCashWallet( mnemonic: mnemonic, password: password, diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart index 508c6b34d..b0741ed34 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -17,8 +17,8 @@ abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses wi required super.network, required super.electrumClient, super.initialAddresses, - super.initialRegularAddressIndex = 0, - super.initialChangeAddressIndex = 0, + super.initialRegularAddressIndex = const {}, + super.initialChangeAddressIndex = const {}, }) : super(walletInfo); @override diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index 8ca9fb3c9..028bb5bb3 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -46,7 +46,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: b5f0af48836250aa0f757a2a05b3e73e074f3c22 + resolved-ref: ae3030bc30039e8e58241a6e9e5e007079d5aea6 url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "3.0.1" @@ -102,10 +102,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b" + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" url: "https://pub.dev" source: hosted - version: "2.4.7" + version: "2.4.8" build_runner_core: dependency: transitive description: @@ -448,10 +448,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" path_provider_linux: dependency: transitive description: From 99afde98bca5b7006d52e8769e776a8a4625cc1f Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 12 Jan 2024 11:07:28 -0300 Subject: [PATCH 05/59] fix: address review comments --- cw_bitcoin/lib/address_from_output.dart | 10 ++++++++++ cw_bitcoin/lib/address_to_output_script.dart | 12 +++++++----- lib/core/address_validator.dart | 3 ++- lib/entities/receive_page_option.dart | 16 +--------------- res/values/strings_ar.arb | 7 ++----- res/values/strings_bg.arb | 7 ++----- res/values/strings_cs.arb | 7 ++----- res/values/strings_de.arb | 7 ++----- res/values/strings_en.arb | 7 ++----- res/values/strings_es.arb | 7 ++----- res/values/strings_fr.arb | 7 ++----- 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 | 7 ++----- 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 ++----- 30 files changed, 72 insertions(+), 151 deletions(-) diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index d870e6747..b6c8a0afb 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -12,5 +12,15 @@ String addressFromOutput(Uint8List script, BasedUtxoNetwork network) { .toAddress(network); } catch (_) {} + try { + return P2wshAddress.fromScriptPubkey(script: Script.fromRaw(byteData: script)) + .toAddress(network); + } catch (_) {} + + try { + return P2trAddress.fromScriptPubkey(script: Script.fromRaw(byteData: script)) + .toAddress(network); + } catch (_) {} + return ''; } diff --git a/cw_bitcoin/lib/address_to_output_script.dart b/cw_bitcoin/lib/address_to_output_script.dart index d0ad0c30f..f1e5a30a1 100644 --- a/cw_bitcoin/lib/address_to_output_script.dart +++ b/cw_bitcoin/lib/address_to_output_script.dart @@ -1,18 +1,20 @@ import 'dart:typed_data'; -import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin; -List addressToOutputScript(String address, BasedUtxoNetwork network) { +List addressToOutputScript(String address, bitcoin.BasedUtxoNetwork network) { try { // FIXME: improve validation for p2sh addresses // 3 for bitcoin // m for litecoin // (note: m is also for bitcoin's testnet. check networkType to make sure) if (address.startsWith('3') || - (address.toLowerCase().startsWith('m') && network != BitcoinNetwork.testnet)) { - return P2shAddress.fromAddress(address: address, network: network).toScriptPubKey().toBytes(); + (address.toLowerCase().startsWith('m') && network != bitcoin.BitcoinNetwork.testnet)) { + return bitcoin.P2shAddress.fromAddress(address: address, network: network) + .toScriptPubKey() + .toBytes(); } - return addressToOutputScript(address, network); + return bitcoin.addressToOutputScript(address: address, network: network); } catch (err) { print(err); return Uint8List(0); diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 1b5bc74a4..7545d74e1 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -25,7 +25,7 @@ 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 '^${P2pkhAddress.REGEX.pattern}\$|^${P2shAddress.REGEX.pattern}\$|^${P2wpkhAddress.REGEX.pattern}\$|${P2trAddress.REGEX.pattern}\$'; + return '^${P2pkhAddress.REGEX.pattern}\$|^${P2shAddress.REGEX.pattern}\$|^${P2wpkhAddress.REGEX.pattern}\$|${P2trAddress.REGEX.pattern}\$|^${P2wshAddress.REGEX.pattern}\$'; case CryptoCurrency.nano: return '[0-9a-zA-Z_]'; case CryptoCurrency.banano: @@ -266,6 +266,7 @@ class AddressValidator extends TextValidator { return '([^0-9a-zA-Z]|^)${P2pkAddress.REGEX.pattern}|\$)' '([^0-9a-zA-Z]|^)${P2shAddress.REGEX.pattern}|\$)' '([^0-9a-zA-Z]|^)${P2wpkhAddress.REGEX.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2wshAddress.REGEX.pattern}|\$)' '([^0-9a-zA-Z]|^)${P2trAddress.REGEX.pattern}|\$)'; case CryptoCurrency.ltc: return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)' diff --git a/lib/entities/receive_page_option.dart b/lib/entities/receive_page_option.dart index 8127b0d73..a0664e5f2 100644 --- a/lib/entities/receive_page_option.dart +++ b/lib/entities/receive_page_option.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/generated/i18n.dart'; import 'package:bitcoin_base/bitcoin_base.dart'; class ReceivePageOption { @@ -12,15 +11,7 @@ class ReceivePageOption { @override String toString() { - switch (this) { - case ReceivePageOption.mainnet: - return S.current.mainnet; - case ReceivePageOption.anonPayInvoice: - return S.current.trocador_anonpay_invoice; - case ReceivePageOption.anonPayDonationLink: - return S.current.trocador_anonpay_donation_link; - } - return ""; + return _value; } } @@ -51,11 +42,6 @@ class BitcoinReceivePageOption extends ReceivePageOption { return BitcoinReceivePageOption.p2wpkh; } } - - @override - String toString() { - return _value; - } } const BitcoinReceivePageOptions = [ diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 97a6d1465..95871b904 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -759,8 +759,5 @@ "default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ", "custom_drag": "مخصص (عقد وسحب)", - "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", - "mainnet": "mainnet", - "trocador_anonpay_donation_link": "رابط التبرع Trocador Anonpay", - "trocador_anonpay_invoice": "فاتورة Trocador Anonpay" -} \ No newline at end of file + "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 24804806f..197dbe552 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -755,8 +755,5 @@ "default_sell_provider": "Доставчик за продажба по подразбиране", "select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.", "custom_drag": "Персонализиране (задръжте и плъзнете)", - "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Трокадорна връзка за дарение на Anonpay", - "trocador_anonpay_invoice": "Трокадорна фактура Anonpay" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)" +} diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 01536cb54..bed4e3193 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -755,8 +755,5 @@ "default_sell_provider": "Výchozí poskytovatel prodeje", "select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Trocador anonpay dar odkaz", - "trocador_anonpay_invoice": "Faktura Trocador AnonPay" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)" +} diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index f52df1fbd..1d63bffc6 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -763,8 +763,5 @@ "default_sell_provider": "Standard-Verkaufsanbieter", "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)", - "mainnet": "Hauptnetz", - "trocador_anonpay_donation_link": "Trocador Anonpay Spendenlink", - "trocador_anonpay_invoice": "Trocador Anonpay In Rechnung" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)" +} diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 71bb8e5cd..e6c95270e 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -764,8 +764,5 @@ "default_sell_provider": "Default Sell Provider", "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Trocador AnonPay Donation Link", - "trocador_anonpay_invoice": "Trocador AnonPay Invoice" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)" +} diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 86bf04238..6ee0f509c 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -763,8 +763,5 @@ "default_sell_provider": "Proveedor de venta predeterminado", "select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.", "custom_drag": "Custom (mantenía y arrastre)", - "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)", - "mainnet": "Red", - "trocador_anonpay_donation_link": "Trocador Anonpay Donation Link", - "trocador_anonpay_invoice": "Trocador Anonpay Factura" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)" +} diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d7fbc008f..862f9ae7d 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -763,8 +763,5 @@ "default_sell_provider": "Fournisseur de vente par défaut", "select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.", "custom_drag": "Custom (maintenir et traîner)", - "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)", - "mainnet": "MainNet", - "trocador_anonpay_donation_link": "Lien de don du Trocador anonpay", - "trocador_anonpay_invoice": "Facture anonpay du Trocador" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)" +} diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 0bdac2939..9456085dc 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -745,8 +745,5 @@ "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", "select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.", "custom_drag": "Al'ada (riƙe da ja)", - "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", - "mainnet": "Otnet", - "trocador_anonpay_donation_link": "Hanyar bayar da gudummawa na Trorojador", - "trocador_anonpay_invoice": "Atroador Antonpay" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)" +} diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 9b3fc3173..f6a7701ee 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -763,8 +763,5 @@ "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", "select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", "custom_drag": "कस्टम (पकड़ और खींचें)", - "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)", - "mainnet": "मेननेट", - "trocador_anonpay_donation_link": "Trocador anonpay दान लिंक", - "trocador_anonpay_invoice": "Trocador anonpay चालान" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)" +} diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index d7b7b4ff4..3565c89a0 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -761,8 +761,5 @@ "default_sell_provider": "Zadani dobavljač prodaje", "select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.", "custom_drag": "Prilagođeni (držite i povucite)", - "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Link za donaciju trokadora", - "trocador_anonpay_invoice": "Trokador anonpay faktura" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)" +} diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 26b70df06..6744f0a38 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -751,8 +751,5 @@ "default_sell_provider": "Penyedia Penjualan Default", "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.", "custom_drag": "Khusus (tahan dan seret)", - "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Tautan donasi trocador anonpay", - "trocador_anonpay_invoice": "Faktur Trocador Anonpay" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)" +} diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index a99abeb08..bb909a7e0 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -763,8 +763,5 @@ "default_sell_provider": "Fornitore di vendita predefinito", "select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Link di donazione di Trocador Anonpay", - "trocador_anonpay_invoice": "Trocador Anonpay fattura" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)" +} diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index e4906c29f..2152a3dcc 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -763,8 +763,5 @@ "default_sell_provider": "デフォルトの販売プロバイダー", "select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。", "custom_drag": "カスタム(ホールドとドラッグ)", - "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)", - "mainnet": "メインネット", - "trocador_anonpay_donation_link": "Trocador Anonpay寄付リンク", - "trocador_anonpay_invoice": "Trocador Anonpay Invoice" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)" +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 4a5501b5e..5ad5482ed 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -761,8 +761,5 @@ "default_sell_provider": "기본 판매 공급자", "select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.", "custom_drag": "사용자 정의 (홀드 앤 드래그)", - "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)", - "mainnet": "메인 넷", - "trocador_anonpay_donation_link": "Trocador Anonpay 기부 링크", - "trocador_anonpay_invoice": "Trocador Anonpay 송장" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)" +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 945b0dd1d..73f4e5dcd 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -761,8 +761,5 @@ "default_sell_provider": "ပုံသေရောင်းချပေးသူ", "select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။", "custom_drag": "စိတ်ကြိုက် (Drag)", - "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)", - "mainnet": "မမက်မ", - "trocador_anonpay_donation_link": "Trocador Anonpay အလှူငွေလင့်ခ်", - "trocador_anonpay_invoice": "Trocador Anonpay ငွေတောင်းခံလွှာ" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)" +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index ca81591cf..6cf41e0b9 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -763,8 +763,5 @@ "default_sell_provider": "Standaard verkoopaanbieder", "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.", "custom_drag": "Custom (vasthouden en slepen)", - "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)", - "mainnet": "Heuvel", - "trocador_anonpay_donation_link": "Trocador anonpay donatielink", - "trocador_anonpay_invoice": "Trocador anonpay factuur" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)" +} diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index f00336448..9d3fb3f93 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -763,8 +763,5 @@ "default_sell_provider": "Domyślny dostawca sprzedaży", "select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.", "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", - "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Link darowizny Trocador Anonpay", - "trocador_anonpay_invoice": "Trocador anonpay faktura" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)" +} diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 1cc5c3acc..5cf1fd370 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -762,8 +762,5 @@ "default_sell_provider": "Provedor de venda padrão", "select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.", "custom_drag": "Personalizado (segure e arraste)", - "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Link de doação de Trocador Anonpay", - "trocador_anonpay_invoice": "Trocador ANONPAY Fatura" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)" +} diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 8267729e8..c81c0bd82 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -763,8 +763,5 @@ "default_sell_provider": "Поставщик продаж по умолчанию", "select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.", "custom_drag": "Пользователь (удерживайте и перетаскивайте)", - "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon).", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Ссылка пожертвования Trocador Anonpay", - "trocador_anonpay_invoice": "Трокадор Анонпай" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)." +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index cbd5296d9..0965d3979 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -761,8 +761,5 @@ "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", "select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป", "custom_drag": "กำหนดเอง (ค้างและลาก)", - "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", - "mainnet": "หลัก", - "trocador_anonpay_donation_link": "ลิงค์บริจาค Trocador Anonpay", - "trocador_anonpay_invoice": "ใบแจ้งหนี้ Trocador Anonpay" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)" +} diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 5874692ac..f9bbb5dea 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -757,8 +757,5 @@ "default_sell_provider": "Default na Sell Provider", "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", "custom_drag": "Pasadyang (hawakan at i -drag)", - "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)", - "mainnet": "Mainnet", - "trocador_anonpay_donation_link": "Trocador Anonpay Donation Link", - "trocador_anonpay_invoice": "Trocador Anonpay Invoice" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)" +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 420aeb6d6..6fdb8bb99 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -761,8 +761,5 @@ "default_sell_provider": "Varsayılan Satış Sağlayıcısı", "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", "custom_drag": "Özel (Bekle ve Sürükle)", - "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", - "mainnet": "Ana ağ", - "trocador_anonpay_donation_link": "Trocador anonpay bağış bağlantısı", - "trocador_anonpay_invoice": "Trocador anonpay faturası" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)" +} diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index cdb51f7fb..721a3970d 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -763,8 +763,5 @@ "default_sell_provider": "Постачальник продажу за замовчуванням", "select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.", "custom_drag": "На замовлення (утримуйте та перетягується)", - "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)", - "mainnet": "Мейннет", - "trocador_anonpay_donation_link": "Посилання на пожертву Trocador Anonpay", - "trocador_anonpay_invoice": "Рахунок -фактура Trocador Anonpay" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)" +} diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index d10d4a183..e4a9f4590 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -755,8 +755,5 @@ "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", "select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ", "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", - "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ", - "mainnet": "مینیٹ", - "trocador_anonpay_donation_link": "ٹروکاڈور انونپے چندہ کا لنک", - "trocador_anonpay_invoice": "ٹروکاڈور انون پے انوائس" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ " +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 106abdd6c..964307e6b 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -757,8 +757,5 @@ "default_sell_provider": "Aiyipada Olupese Tita", "select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.", "custom_drag": "Aṣa (mu ati fa)", - "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)", - "mainnet": "Akọkọ", - "trocador_anonpay_donation_link": "Ọna asopọ Ẹbun Anontay Anontay", - "trocador_anonpay_invoice": "Tragbar anonpaya risiti" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)" +} diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 8a83f2675..43e8c6ce1 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -762,8 +762,5 @@ "default_sell_provider": "默认销售提供商", "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。", "custom_drag": "定制(保持和拖动)", - "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)", - "mainnet": "主网", - "trocador_anonpay_donation_link": "trocador anonpay捐赠链接", - "trocador_anonpay_invoice": "Trocador Anonpay发票" -} \ No newline at end of file + "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)" +} From 45055a74143a93ff47e2c33f3485de5a8a537382 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 12 Jan 2024 13:03:41 -0300 Subject: [PATCH 06/59] fix: address type restore --- cw_bitcoin/lib/bitcoin_wallet.dart | 103 ++++++++++-------- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 1 + cw_bitcoin/lib/electrum_wallet.dart | 6 +- cw_bitcoin/lib/electrum_wallet_addresses.dart | 9 ++ cw_bitcoin/lib/electrum_wallet_snapshot.dart | 59 ++++++---- cw_bitcoin/lib/litecoin_wallet.dart | 65 ++++++----- cw_bitcoin/lib/litecoin_wallet_addresses.dart | 1 + .../lib/src/bitcoin_cash_wallet.dart | 83 +++++++------- .../src/bitcoin_cash_wallet_addresses.dart | 1 + cw_core/lib/receive_page_options.dart | 52 --------- cw_core/lib/wallet_addresses.dart | 4 + cw_core/lib/wallet_info.dart | 3 + 12 files changed, 201 insertions(+), 186 deletions(-) delete mode 100644 cw_core/lib/receive_page_options.dart diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 04e988142..d7b52c63a 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -17,17 +17,18 @@ part 'bitcoin_wallet.g.dart'; class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet; abstract class BitcoinWalletBase extends ElectrumWallet with Store { - BitcoinWalletBase( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}}) - : super( + BitcoinWalletBase({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + String? addressPageType, + List? initialAddresses, + ElectrumBalance? initialBalance, + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}, + }) : super( mnemonic: mnemonic, password: password, walletInfo: walletInfo, @@ -37,35 +38,42 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialBalance: initialBalance, seedBytes: seedBytes, currency: CryptoCurrency.btc) { - walletAddresses = BitcoinWalletAddresses(walletInfo, - electrumClient: electrumClient, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), - network: network); + walletAddresses = BitcoinWalletAddresses( + walletInfo, + electrumClient: electrumClient, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), + network: network, + initialAddressPageType: addressPageType, + ); } - static Future create( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - List? initialAddresses, - ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}}) async { + static Future create({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + String? addressPageType, + List? initialAddresses, + ElectrumBalance? initialBalance, + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}, + }) async { return BitcoinWallet( - mnemonic: mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: await mnemonicToSeedBytes(mnemonic), - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex); + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: await mnemonicToSeedBytes(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + addressPageType: addressPageType, + ); } static Future open({ @@ -75,15 +83,18 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required String password, }) async { final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + print([ "SNP", snp.addressPageType ]); return BitcoinWallet( - mnemonic: snp.mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp.addresses, - initialBalance: snp.balance, - seedBytes: await mnemonicToSeedBytes(snp.mnemonic), - initialRegularAddressIndex: snp.regularAddressIndex, - initialChangeAddressIndex: snp.changeAddressIndex); + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + initialBalance: snp.balance, + seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex, + addressPageType: snp.addressPageType, + ); } } diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index cbc086839..6ce713e4e 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -17,6 +17,7 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S required super.network, required super.electrumClient, super.initialAddresses, + super.initialAddressPageType, super.initialRegularAddressIndex = const {}, super.initialChangeAddressIndex = const {}, }) : super(walletInfo); diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 160646e97..adf8a197e 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -357,10 +357,10 @@ abstract class ElectrumWalletBase String toJSON() => json.encode({ 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentChangeAddressIndexByType.toString(), - 'change_address_index': walletAddresses.currentChangeAddressIndexByType.toString(), + 'account_index': walletAddresses.currentChangeAddressIndexByType, + 'change_address_index': walletAddresses.currentChangeAddressIndexByType, 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), - 'address_page_type': walletAddresses.addressPageType, + 'address_page_type': walletInfo.addressPageType.toString(), 'balance': balance[currency]?.toJSON() }); diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index fe3b0dd55..f0a962acf 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -20,6 +20,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { required this.sideHd, required this.electrumClient, required this.network, + String? initialAddressPageType, List? initialAddresses, Map initialRegularAddressIndex = const {}, Map initialChangeAddressIndex = const {}, @@ -32,6 +33,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { .toSet()), currentReceiveAddressIndexByType = initialRegularAddressIndex, currentChangeAddressIndexByType = initialChangeAddressIndex, + _addressPageType = walletInfo.addressPageType != null + ? BitcoinAddressType.fromValue( + walletInfo.addressPageType ?? BitcoinAddressType.p2wpkh.toString()) + : BitcoinAddressType.p2wpkh, super(walletInfo); static const defaultReceiveAddressesCount = 22; @@ -52,6 +57,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { BitcoinAddressType _addressPageType = BitcoinAddressType.p2wpkh; @computed BitcoinAddressType get addressPageType => _addressPageType; + @computed + @override + String get addressPageTypeStr => addressPageType.toString(); @computed String get receiveAddress { @@ -302,5 +310,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { await _discoverAddresses(mainHd, false, addressType: addressPageType); updateReceiveAddresses(); + await saveAddressesInBox(); } } diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 01deb4e90..8bc02d3b2 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_core/pathForWallet.dart'; @@ -6,19 +7,22 @@ import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_type.dart'; class ElectrumWallletSnapshot { - ElectrumWallletSnapshot( - {required this.name, - required this.type, - required this.password, - required this.mnemonic, - required this.addresses, - required this.balance, - required this.regularAddressIndex, - required this.changeAddressIndex}); + ElectrumWallletSnapshot({ + required this.name, + required this.type, + required this.password, + required this.mnemonic, + required this.addresses, + required this.balance, + required this.regularAddressIndex, + required this.changeAddressIndex, + required this.addressPageType, + }); final String name; final String password; final WalletType type; + final String addressPageType; String mnemonic; List addresses; @@ -38,17 +42,34 @@ class ElectrumWallletSnapshot { .toList(); final balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); - final regularAddressIndexByType = data["account_index"] as Map? ?? {}; - final changeAddressIndexByType = data["change_address_index"] as Map? ?? {}; + var regularAddressIndexByType = {BitcoinAddressType.p2wpkh.toString(): 0}; + var changeAddressIndexByType = {BitcoinAddressType.p2wpkh.toString(): 0}; + + try { + regularAddressIndexByType = { + BitcoinAddressType.p2wpkh.toString(): int.parse(data['account_index'] as String? ?? '0') + }; + changeAddressIndexByType = { + BitcoinAddressType.p2wpkh.toString(): + int.parse(data['change_address_index'] as String? ?? '0') + }; + } catch (_) { + try { + regularAddressIndexByType = data["account_index"] as Map? ?? {}; + changeAddressIndexByType = data["change_address_index"] as Map? ?? {}; + } catch (_) {} + } return ElectrumWallletSnapshot( - name: name, - type: type, - password: password, - mnemonic: mnemonic, - addresses: addresses, - balance: balance, - regularAddressIndex: regularAddressIndexByType, - changeAddressIndex: changeAddressIndexByType); + name: name, + type: type, + password: password, + mnemonic: mnemonic, + addresses: addresses, + balance: balance, + regularAddressIndex: regularAddressIndexByType, + changeAddressIndex: changeAddressIndexByType, + addressPageType: data['address_page_type'] as String? ?? BitcoinAddressType.p2wpkh.toString(), + ); } } diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 7b96157ce..38f2358c2 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -20,17 +20,18 @@ part 'litecoin_wallet.g.dart'; class LitecoinWallet = LitecoinWalletBase with _$LitecoinWallet; abstract class LitecoinWalletBase extends ElectrumWallet with Store { - LitecoinWalletBase( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}}) - : super( + LitecoinWalletBase({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + String? addressPageType, + List? initialAddresses, + ElectrumBalance? initialBalance, + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}, + }) : super( mnemonic: mnemonic, password: password, walletInfo: walletInfo, @@ -49,6 +50,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { mainHd: hd, sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), network: network, + initialAddressPageType: addressPageType, ); } @@ -57,20 +59,23 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + String? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, Map initialRegularAddressIndex = const {}, Map initialChangeAddressIndex = const {}}) async { return LitecoinWallet( - mnemonic: mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: await mnemonicToSeedBytes(mnemonic), - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex); + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: await mnemonicToSeedBytes(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + addressPageType: addressPageType, + ); } static Future open({ @@ -81,15 +86,17 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { }) async { final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); return LitecoinWallet( - mnemonic: snp.mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp.addresses, - initialBalance: snp.balance, - seedBytes: await mnemonicToSeedBytes(snp.mnemonic), - initialRegularAddressIndex: snp.regularAddressIndex, - initialChangeAddressIndex: snp.changeAddressIndex); + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + initialBalance: snp.balance, + seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex, + addressPageType: snp.addressPageType, + ); } @override diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart index f7d49b64d..65ea43cbb 100644 --- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart @@ -16,6 +16,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with required super.sideHd, required super.network, required super.electrumClient, + super.initialAddressPageType, super.initialAddresses, super.initialRegularAddressIndex = const {}, super.initialChangeAddressIndex = const {}, diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 23b67fd74..c46aa0561 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -28,17 +28,18 @@ part 'bitcoin_cash_wallet.g.dart'; class BitcoinCashWallet = BitcoinCashWalletBase with _$BitcoinCashWallet; abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { - BitcoinCashWalletBase( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}}) - : super( + BitcoinCashWalletBase({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + String? addressPageType, + List? initialAddresses, + ElectrumBalance? initialBalance, + Map initialRegularAddressIndex = const {}, + Map initialChangeAddressIndex = const {}, + }) : super( mnemonic: mnemonic, password: password, walletInfo: walletInfo, @@ -48,14 +49,17 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { initialBalance: initialBalance, seedBytes: seedBytes, currency: CryptoCurrency.bch) { - walletAddresses = BitcoinCashWalletAddresses(walletInfo, - electrumClient: electrumClient, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"), - network: network); + walletAddresses = BitcoinCashWalletAddresses( + walletInfo, + electrumClient: electrumClient, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"), + network: network, + initialAddressPageType: addressPageType, + ); } static Future create( @@ -63,20 +67,23 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + String? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, Map initialRegularAddressIndex = const {}, Map initialChangeAddressIndex = const {}}) async { return BitcoinCashWallet( - mnemonic: mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: await Mnemonic.toSeed(mnemonic), - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex); + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: await Mnemonic.toSeed(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + addressPageType: addressPageType, + ); } static Future open({ @@ -87,15 +94,17 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { }) async { final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); return BitcoinCashWallet( - mnemonic: snp.mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp.addresses, - initialBalance: snp.balance, - seedBytes: await Mnemonic.toSeed(snp.mnemonic), - initialRegularAddressIndex: snp.regularAddressIndex, - initialChangeAddressIndex: snp.changeAddressIndex); + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + initialBalance: snp.balance, + seedBytes: await Mnemonic.toSeed(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex, + addressPageType: snp.addressPageType, + ); } @override diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart index b0741ed34..deb50184b 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -16,6 +16,7 @@ abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses wi required super.sideHd, required super.network, required super.electrumClient, + super.initialAddressPageType, super.initialAddresses, super.initialRegularAddressIndex = const {}, super.initialChangeAddressIndex = const {}, diff --git a/cw_core/lib/receive_page_options.dart b/cw_core/lib/receive_page_options.dart deleted file mode 100644 index 46fb1a49a..000000000 --- a/cw_core/lib/receive_page_options.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:bitcoin_base/bitcoin_base.dart'; - -class CoreReceivePageOption { - static const mainnet = CoreReceivePageOption._('mainnet'); - static const anonPayInvoice = CoreReceivePageOption._('anonPayInvoice'); - static const anonPayDonationLink = CoreReceivePageOption._('anonPayDonationLink'); - - const CoreReceivePageOption._(this._value); - - final String _value; -} - -const ReceivePageOptions = [ - CoreReceivePageOption.mainnet, - CoreReceivePageOption.anonPayInvoice, - CoreReceivePageOption.anonPayDonationLink -]; - -class BitcoinReceivePageOption extends CoreReceivePageOption { - static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH)'); - static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)'); - static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)'); - static const p2pkh = BitcoinReceivePageOption._('Legacy (P2PKH)'); - - const BitcoinReceivePageOption._(String value) : super._(value); - - factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) { - switch (type) { - case BitcoinAddressType.p2tr: - return BitcoinReceivePageOption.p2tr; - case BitcoinAddressType.p2wsh: - return BitcoinReceivePageOption.p2wsh; - case BitcoinAddressType.p2pkh: - return BitcoinReceivePageOption.p2pkh; - case BitcoinAddressType.p2wpkh: - default: - return BitcoinReceivePageOption.p2wpkh; - } - } - - @override - String toString() { - return _value; - } -} - -const BitcoinReceivePageOptions = [ - BitcoinReceivePageOption.p2wpkh, - BitcoinReceivePageOption.p2tr, - BitcoinReceivePageOption.p2wsh, - BitcoinReceivePageOption.p2pkh -]; diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index 632eb1332..85b00a025 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -1,3 +1,4 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_core/address_info.dart'; import 'package:cw_core/wallet_info.dart'; @@ -18,6 +19,8 @@ abstract class WalletAddresses { Set usedAddresses = {}; + String addressPageTypeStr = BitcoinAddressType.p2wpkh.toString(); + Future init(); Future updateAddressesInBox(); @@ -28,6 +31,7 @@ abstract class WalletAddresses { walletInfo.addresses = addressesMap; walletInfo.addressInfos = addressInfos; walletInfo.usedAddresses = usedAddresses.toList(); + walletInfo.addressPageType = addressPageTypeStr; if (walletInfo.isInBox) { await walletInfo.save(); diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index c4ccea00a..3867157f0 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -148,6 +148,9 @@ class WalletInfo extends HiveObject { @HiveField(17) String? derivationPath; + @HiveField(18) + String? addressPageType; + String get yatLastUsedAddress => yatLastUsedAddressRaw ?? ''; set yatLastUsedAddress(String address) { From 56d7aa211e3e9bbd69dfda115f45b8ab4e1f6ac8 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 12 Jan 2024 14:21:19 -0300 Subject: [PATCH 07/59] feat: add testnet --- cw_bitcoin/lib/bitcoin_wallet.dart | 10 +++-- cw_bitcoin/lib/bitcoin_wallet_service.dart | 19 +++++---- cw_bitcoin/lib/electrum.dart | 28 ++++++++++--- cw_bitcoin/lib/electrum_wallet.dart | 7 +++- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 11 ++++-- cw_bitcoin/lib/litecoin_wallet.dart | 2 +- cw_bitcoin/lib/litecoin_wallet_service.dart | 6 +-- .../lib/src/bitcoin_cash_wallet.dart | 2 +- .../lib/src/bitcoin_cash_wallet_service.dart | 6 +-- cw_core/lib/wallet_base.dart | 2 + cw_core/lib/wallet_service.dart | 8 ++-- cw_ethereum/lib/ethereum_wallet_service.dart | 6 +-- cw_haven/lib/haven_wallet_service.dart | 6 +-- cw_monero/lib/monero_wallet_service.dart | 6 +-- cw_nano/lib/nano_wallet_service.dart | 6 +-- cw_polygon/lib/polygon_wallet_service.dart | 6 +-- lib/core/wallet_creation_service.dart | 12 +++--- lib/entities/default_settings_migration.dart | 21 +++++++++- lib/router.dart | 14 +++++-- .../advanced_privacy_settings_page.dart | 39 +++++++++++++++++-- .../screens/new_wallet/new_wallet_page.dart | 15 ++++--- .../node_create_or_edit_view_model.dart | 2 + .../node_list/node_list_view_model.dart | 6 ++- .../transaction_details_view_model.dart | 8 +++- lib/view_model/wallet_creation_vm.dart | 11 ++++++ lib/view_model/wallet_new_vm.dart | 2 +- lib/view_model/wallet_restore_view_model.dart | 4 +- res/values/strings_ar.arb | 5 ++- res/values/strings_bg.arb | 5 ++- res/values/strings_cs.arb | 5 ++- res/values/strings_de.arb | 5 ++- res/values/strings_en.arb | 5 ++- res/values/strings_es.arb | 5 ++- res/values/strings_fr.arb | 5 ++- res/values/strings_ha.arb | 5 ++- res/values/strings_hi.arb | 5 ++- res/values/strings_hr.arb | 5 ++- res/values/strings_id.arb | 5 ++- res/values/strings_it.arb | 5 ++- res/values/strings_ja.arb | 5 ++- res/values/strings_ko.arb | 5 ++- res/values/strings_my.arb | 5 ++- res/values/strings_nl.arb | 5 ++- res/values/strings_pl.arb | 5 ++- res/values/strings_pt.arb | 5 ++- res/values/strings_ru.arb | 5 ++- res/values/strings_th.arb | 5 ++- res/values/strings_tl.arb | 5 ++- res/values/strings_tr.arb | 5 ++- res/values/strings_uk.arb | 5 ++- res/values/strings_ur.arb | 5 ++- res/values/strings_yo.arb | 5 ++- res/values/strings_zh.arb | 5 ++- 53 files changed, 269 insertions(+), 126 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index d7b52c63a..d3fa223bc 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -1,3 +1,4 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/unspent_coins_info.dart'; @@ -24,6 +25,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required Uint8List seedBytes, String? addressPageType, + BasedUtxoNetwork? networkParam, List? initialAddresses, ElectrumBalance? initialBalance, Map initialRegularAddressIndex = const {}, @@ -46,7 +48,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialChangeAddressIndex: initialChangeAddressIndex, mainHd: hd, sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), - network: network, + network: networkParam ?? network, initialAddressPageType: addressPageType, ); } @@ -57,6 +59,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, String? addressPageType, + BasedUtxoNetwork? network, List? initialAddresses, ElectrumBalance? initialBalance, Map initialRegularAddressIndex = const {}, @@ -73,6 +76,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, addressPageType: addressPageType, + networkParam: network, ); } @@ -82,8 +86,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); - print([ "SNP", snp.addressPageType ]); + final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password); return BitcoinWallet( mnemonic: snp.mnemonic, password: password, @@ -95,6 +98,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex, addressPageType: snp.addressPageType, + networkParam: snp.network, ); } } diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 3a97e0682..5d7d71ebb 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; @@ -25,12 +26,14 @@ 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); + mnemonic: await generateMnemonic(), + password: credentials.password!, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource, + network: (isTestnet ?? false) ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet, + ); await wallet.save(); await wallet.init(); return wallet; @@ -81,12 +84,12 @@ class BitcoinWalletService extends WalletService< @override Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async => throw UnimplementedError(); @override Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } @@ -100,4 +103,4 @@ class BitcoinWalletService extends WalletService< await wallet.init(); return wallet; } -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 2f73c24b6..d76eb09cb 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -7,6 +7,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:flutter/foundation.dart'; import 'package:rxdart/rxdart.dart'; +import 'package:http/http.dart' as http; String jsonrpcparams(List params) { final _params = params?.map((val) => '"${val.toString()}"')?.join(','); @@ -241,15 +242,32 @@ 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, BasedUtxoNetwork? network}) async { + if (network != null && network == BitcoinNetwork.testnet) { + 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) { + print(response.body); + if (response.statusCode == 200) { + return response.body; } return ''; }); + } + + return call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) + .then((dynamic result) { + if (result is String) { + return result; + } + + return ''; + }); + } Future> getMerkle({required String hash, required int height}) async => await call(method: 'blockchain.transaction.get_merkle', params: [hash, height]) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index adf8a197e..589d822d7 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -79,6 +79,7 @@ abstract class ElectrumWalletBase : networkType == litecoinNetwork ? LitecoinNetwork.mainnet : BitcoinNetwork.testnet, + this.isTestnet = networkType == bitcoin.testnet, super(walletInfo) { this.electrumClient = electrumClient ?? ElectrumClient(); this.walletInfo = walletInfo; @@ -124,6 +125,9 @@ abstract class ElectrumWalletBase bitcoin.NetworkType networkType; BasedUtxoNetwork network; + @override + bool? isTestnet; + @override BitcoinWalletKeys get keys => BitcoinWalletKeys(wif: hd.wif!, privateKey: hd.privKey!, publicKey: hd.pubKey!); @@ -361,7 +365,8 @@ abstract class ElectrumWalletBase 'change_address_index': walletAddresses.currentChangeAddressIndexByType, 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), 'address_page_type': walletInfo.addressPageType.toString(), - 'balance': balance[currency]?.toJSON() + 'balance': balance[currency]?.toJSON(), + 'network_type': network == BitcoinNetwork.mainnet ? 'mainnet' : 'testnet', }); int feeRate(TransactionPriority priority) { diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 8bc02d3b2..1922d1353 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -6,8 +6,8 @@ import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_type.dart'; -class ElectrumWallletSnapshot { - ElectrumWallletSnapshot({ +class ElectrumWalletSnapshot { + ElectrumWalletSnapshot({ required this.name, required this.type, required this.password, @@ -17,12 +17,14 @@ class ElectrumWallletSnapshot { required this.regularAddressIndex, required this.changeAddressIndex, required this.addressPageType, + required this.network, }); final String name; final String password; final WalletType type; final String addressPageType; + final BasedUtxoNetwork network; String mnemonic; List addresses; @@ -30,7 +32,7 @@ class ElectrumWallletSnapshot { Map regularAddressIndex; Map changeAddressIndex; - static Future load(String name, WalletType type, String password) async { + static Future load(String name, WalletType type, String password) async { final path = await pathForWallet(name: name, type: type); final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map; @@ -60,7 +62,7 @@ class ElectrumWallletSnapshot { } catch (_) {} } - return ElectrumWallletSnapshot( + return ElectrumWalletSnapshot( name: name, type: type, password: password, @@ -70,6 +72,7 @@ class ElectrumWallletSnapshot { regularAddressIndex: regularAddressIndexByType, changeAddressIndex: changeAddressIndexByType, addressPageType: data['address_page_type'] as String? ?? BitcoinAddressType.p2wpkh.toString(), + network: data['network_type'] == 'testnet' ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet, ); } } diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 38f2358c2..90dd3ce2d 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -84,7 +84,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password); return LitecoinWallet( mnemonic: snp.mnemonic, password: password, diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index b13ac7a7f..d2f48ca55 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -25,7 +25,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!, @@ -82,12 +82,12 @@ class LitecoinWalletService extends WalletService< @override Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async => throw UnimplementedError(); @override Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index c46aa0561..74fee5b17 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -92,7 +92,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password); return BitcoinCashWallet( mnemonic: snp.mnemonic, password: password, 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 8cc469a3a..2a45afd5b 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -31,7 +31,7 @@ class BitcoinCashWalletService extends WalletService create( - credentials) async { + credentials, {bool? isTestnet}) async { final strength = (credentials.seedPhraseLength == 12) ? 128 : (credentials.seedPhraseLength == 24) @@ -88,14 +88,14 @@ class BitcoinCashWalletService extends WalletService - restoreFromKeys(credentials) { + restoreFromKeys(credentials, {bool? isTestnet}) { // TODO: implement restoreFromKeys throw UnimplementedError('restoreFromKeys() is not implemented'); } @override Future restoreFromSeed( - BitcoinCashRestoreWalletFromSeedCredentials credentials) async { + BitcoinCashRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinCashMnemonicIsIncorrectException(); } diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 09b423c14..49f1bdc94 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -88,4 +88,6 @@ abstract class WalletBase renameWalletFiles(String newWalletName); String signMessage(String message, {String? address = null}) => throw UnimplementedError(); + + bool? isTestnet; } diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index f6d0ca192..7427a1892 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -1,18 +1,16 @@ -import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; abstract class WalletService { WalletType getType(); - Future create(N credentials); + Future create(N credentials, {bool? isTestnet}); - Future restoreFromSeed(RFS credentials); + Future restoreFromSeed(RFS credentials, {bool? isTestnet}); - Future restoreFromKeys(RFK credentials); + Future restoreFromKeys(RFK credentials, {bool? isTestnet}); Future openWallet(String name, String password); diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 0acc90bac..0fd4266be 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -19,7 +19,7 @@ class EthereumWalletService extends WalletService walletInfoSource; @override - Future create(EthereumNewWalletCredentials credentials) async { + Future create(EthereumNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -68,7 +68,7 @@ class EthereumWalletService extends WalletService restoreFromKeys(EthereumRestoreWalletFromPrivateKey credentials) async { + Future restoreFromKeys(EthereumRestoreWalletFromPrivateKey credentials, {bool? isTestnet}) async { final wallet = EthereumWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -84,7 +84,7 @@ class EthereumWalletService extends WalletService restoreFromSeed( - EthereumRestoreWalletFromSeedCredentials credentials) async { + EthereumRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw EthereumMnemonicIsIncorrectException(); } diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index 0bc20d2a0..66c0b2078 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( @@ -173,7 +173,7 @@ class HavenWalletService extends WalletService< @override Future restoreFromKeys( - HavenRestoreWalletFromKeysCredentials credentials) async { + HavenRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.restoreFromKeys( @@ -197,7 +197,7 @@ class HavenWalletService extends WalletService< @override Future restoreFromSeed( - HavenRestoreWalletFromSeedCredentials credentials) async { + HavenRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.restoreFromSeed( diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 9b9e254d0..0cb77d4e1 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -68,7 +68,7 @@ class MoneroWalletService extends WalletService< WalletType getType() => 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()); @@ -203,7 +203,7 @@ class MoneroWalletService extends WalletService< @override Future restoreFromKeys( - MoneroRestoreWalletFromKeysCredentials credentials) async { + MoneroRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.restoreFromKeys( @@ -228,7 +228,7 @@ class MoneroWalletService extends WalletService< @override Future restoreFromSeed( - MoneroRestoreWalletFromSeedCredentials credentials) async { + MoneroRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { // Restore from Polyseed if (Polyseed.isValidSeed(credentials.mnemonic)) { diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index 2f183d1cc..f975d9536 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -26,7 +26,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(); @@ -78,7 +78,7 @@ class NanoWalletService extends WalletService restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials) async { + Future restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { if (credentials.seedKey.contains(' ')) { throw Exception("Invalid key!"); } else { @@ -112,7 +112,7 @@ class NanoWalletService extends WalletService restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (credentials.mnemonic.contains(' ')) { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw nm.NanoMnemonicIsIncorrectException(); diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 43c6269f6..37f4642b9 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -19,7 +19,7 @@ class PolygonWalletService extends WalletService walletInfoSource; @override - Future create(PolygonNewWalletCredentials credentials) async { + Future create(PolygonNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -68,7 +68,7 @@ class PolygonWalletService extends WalletService restoreFromKeys(PolygonRestoreWalletFromPrivateKey credentials) async { + Future restoreFromKeys(PolygonRestoreWalletFromPrivateKey credentials, {bool? isTestnet}) async { final wallet = PolygonWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -83,7 +83,7 @@ class PolygonWalletService extends WalletService restoreFromSeed(PolygonRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(PolygonRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw EthereumMnemonicIsIncorrectException(); } diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index 8548f079f..a97b3a9d0 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -55,7 +55,7 @@ class WalletCreationService { } } - Future create(WalletCredentials credentials) async { + Future create(WalletCredentials credentials, {bool? isTestnet}) async { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; @@ -63,7 +63,7 @@ class WalletCreationService { credentials.seedPhraseLength = settingsStore.seedPhraseLength.value; } await keyService.saveWalletPassword(password: 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( @@ -73,12 +73,12 @@ class WalletCreationService { return wallet; } - Future restoreFromKeys(WalletCredentials credentials) async { + Future restoreFromKeys(WalletCredentials credentials, {bool? isTestnet}) async { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; await keyService.saveWalletPassword(password: password, walletName: credentials.name); - final wallet = await _service!.restoreFromKeys(credentials); + final wallet = await _service!.restoreFromKeys(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( @@ -88,12 +88,12 @@ class WalletCreationService { return wallet; } - Future restoreFromSeed(WalletCredentials credentials) async { + Future restoreFromSeed(WalletCredentials credentials, {bool? isTestnet}) async { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; await keyService.saveWalletPassword(password: password, walletName: credentials.name); - final wallet = await _service!.restoreFromSeed(credentials); + final wallet = await _service!.restoreFromSeed(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 22868ae28..42b31efb5 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -23,6 +23,10 @@ import 'package:collection/collection.dart'; const newCakeWalletMoneroUri = 'xmr-node.cakewallet.com:18081'; const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002'; +const publicBitcoinTestnetElectrumAddress = 'electrum.blockstream.info'; +const publicBitcoinTestnetElectrumPort = '60002'; +const publicBitcoinTestnetElectrumUri = + '$publicBitcoinTestnetElectrumAddress:$publicBitcoinTestnetElectrumPort'; const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002'; const havenDefaultNodeUri = 'nodes.havenprotocol.org:443'; const ethereumDefaultNodeUri = 'ethereum.publicnode.com'; @@ -322,6 +326,12 @@ Node? getBitcoinDefaultElectrumServer({required Box nodes}) { nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin); } +Node? getBitcoinTestnetDefaultElectrumServer({required Box nodes}) { + return nodes.values + .firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ?? + nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin); +} + Node? getLitecoinDefaultElectrumServer({required Box nodes}) { return nodes.values .firstWhereOrNull((Node node) => node.uriRaw == cakeWalletLitecoinElectrumUri) ?? @@ -410,8 +420,15 @@ Future rewriteSecureStoragePin({required FlutterSecureStorage secureStorag } Future changeBitcoinCurrentElectrumServerToDefault( - {required SharedPreferences sharedPreferences, required Box nodes}) async { - final server = getBitcoinDefaultElectrumServer(nodes: nodes); + {required SharedPreferences sharedPreferences, + required Box nodes, + bool? isTestnet}) async { + Node? server; + if (isTestnet == true) { + server = getBitcoinTestnetDefaultElectrumServer(nodes: nodes); + } else { + server = getBitcoinDefaultElectrumServer(nodes: nodes); + } final serverId = server?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, serverId); diff --git a/lib/router.dart b/lib/router.dart index b7b7c9a8e..0cedd11b2 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -532,13 +532,19 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get(param1: title, param2: url)); case Routes.advancedPrivacySettings: - final type = settings.arguments as WalletType; + final args = settings.arguments as List; + final type = args.first as WalletType; + final useTestnet = args[1] as bool?; + final toggleTestnet = args[2] as Function(bool? val); return CupertinoPageRoute( builder: (_) => AdvancedPrivacySettingsPage( - getIt.get(param1: type), - getIt.get(param1: type, param2: false), - getIt.get())); + useTestnet, + toggleTestnet, + getIt.get(param1: type), + getIt.get(param1: type, param2: false), + getIt.get(), + )); case Routes.anonPayInvoicePage: final args = settings.arguments as List; diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index a4bd6c7b9..0e3a81d5f 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/default_settings_migration.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; @@ -11,6 +12,7 @@ import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model. import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -19,7 +21,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class AdvancedPrivacySettingsPage extends BasePage { - AdvancedPrivacySettingsPage( + AdvancedPrivacySettingsPage(this.useTestnet, this.toggleUseTestnet, this.advancedPrivacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel); final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; @@ -29,13 +31,16 @@ class AdvancedPrivacySettingsPage extends BasePage { @override String get title => S.current.privacy_settings; + final bool? useTestnet; + final Function(bool? val) toggleUseTestnet; + @override Widget body(BuildContext context) => AdvancedPrivacySettingsBody( - advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel); + useTestnet, toggleUseTestnet, advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel); } class AdvancedPrivacySettingsBody extends StatefulWidget { - const AdvancedPrivacySettingsBody( + const AdvancedPrivacySettingsBody(this.useTestnet, this.toggleUseTestnet, this.privacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel, {Key? key}) : super(key: key); @@ -44,6 +49,9 @@ class AdvancedPrivacySettingsBody extends StatefulWidget { final NodeCreateOrEditViewModel nodeViewModel; final SeedTypeViewModel seedTypeViewModel; + final bool? useTestnet; + final Function(bool? val) toggleUseTestnet; + @override _AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState(); } @@ -52,9 +60,14 @@ class _AdvancedPrivacySettingsBodyState extends State(); + bool? testnetValue; @override Widget build(BuildContext context) { + if (testnetValue == null && widget.useTestnet != null) { + testnetValue = widget.useTestnet; + } + return Container( padding: EdgeInsets.only(top: 24), child: ScrollableWithBottomSection( @@ -125,6 +138,19 @@ class _AdvancedPrivacySettingsBodyState extends State WalletNameForm( - _walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _seedTypeViewModel); + _walletNewVM, + currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, + _seedTypeViewModel); } class WalletNameForm extends StatefulWidget { @@ -187,7 +190,6 @@ class _WalletNameFormState extends State { ), ), ), - if (_walletNewVM.hasLanguageSelector) ...[ if (_walletNewVM.hasSeedType) ...[ Observer( @@ -222,7 +224,7 @@ class _WalletNameFormState extends State { ), ), ) - ] + ], ], ), ), @@ -245,8 +247,11 @@ class _WalletNameFormState extends State { const SizedBox(height: 25), GestureDetector( onTap: () { - Navigator.of(context) - .pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type); + Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, arguments: [ + _walletNewVM.type, + _walletNewVM.useTestnet, + _walletNewVM.toggleUseTestnet + ]); }, child: Text(S.of(context).advanced_settings), ), 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/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index 0cd4d7491..2e359213b 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -52,7 +52,11 @@ abstract class NodeListViewModelBase with Store { switch (_appStore.wallet!.type) { case WalletType.bitcoin: - node = getBitcoinDefaultElectrumServer(nodes: _nodeSource)!; + if (_appStore.wallet!.isTestnet == true) { + node = getBitcoinTestnetDefaultElectrumServer(nodes: _nodeSource)!; + } else { + node = getBitcoinDefaultElectrumServer(nodes: _nodeSource)!; + } break; case WalletType.monero: node = getMoneroDefaultNode(nodes: _nodeSource); diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 4e17866cb..7619fae6a 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_type.dart'; @@ -15,6 +16,7 @@ import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:cake_wallet/monero/monero.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; part 'transaction_details_view_model.g.dart'; @@ -116,7 +118,11 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.monero: return 'https://monero.com/tx/${txId}'; case WalletType.bitcoin: - return 'https://mempool.space/tx/${txId}'; + if (wallet is ElectrumWallet) { + final networkType = (wallet as ElectrumWallet).networkType; + return 'https://mempool.space/${networkType == bitcoin.testnet ? "testnet/" : ""}tx/${txId}'; + } + return 'https://blockchair.com/litecoin/transaction/${txId}'; case WalletType.litecoin: return 'https://blockchair.com/litecoin/transaction/${txId}'; case WalletType.bitcoinCash: diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 31e484864..b4c0242f1 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -23,6 +23,12 @@ abstract class WalletCreationVMBase with Store { : state = InitialExecutionState(), name = ''; + @observable + bool _useTestnet = false; + + @computed + bool get useTestnet => _useTestnet; + @observable String name; @@ -95,4 +101,9 @@ abstract class WalletCreationVMBase with Store { Future processFromRestoredWallet( WalletCredentials credentials, RestoredWallet restoreWallet) => throw UnimplementedError(); + + @action + void toggleUseTestnet(bool? value) { + _useTestnet = value ?? !_useTestnet; + } } diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index d4a0c4c00..ee141dd73 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -82,6 +82,6 @@ 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); } } diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 8d1e3b223..8deab925c 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -202,9 +202,9 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { @override Future process(WalletCredentials credentials) async { if (mode == WalletRestoreMode.keys) { - return walletCreationService.restoreFromKeys(credentials); + return walletCreationService.restoreFromKeys(credentials, isTestnet: useTestnet); } - return walletCreationService.restoreFromSeed(credentials); + return walletCreationService.restoreFromSeed(credentials, isTestnet: useTestnet); } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 95871b904..2637185aa 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -759,5 +759,6 @@ "default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ", "custom_drag": "مخصص (عقد وسحب)", - "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" -} + "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "use_testnet": "استخدم testnet" +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 197dbe552..23854fce8 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -755,5 +755,6 @@ "default_sell_provider": "Доставчик за продажба по подразбиране", "select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.", "custom_drag": "Персонализиране (задръжте и плъзнете)", - "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)", + "use_testnet": "Използвайте TestNet" +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index bed4e3193..57bf77468 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -755,5 +755,6 @@ "default_sell_provider": "Výchozí poskytovatel prodeje", "select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", + "use_testnet": "Použijte testNet" +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 1d63bffc6..b9c55d305 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -763,5 +763,6 @@ "default_sell_provider": "Standard-Verkaufsanbieter", "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)", + "use_testnet": "TESTNET verwenden" +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index e6c95270e..7ea8de5f1 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -764,5 +764,6 @@ "default_sell_provider": "Default Sell Provider", "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)", + "use_testnet": "Use Testnet" +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 6ee0f509c..47c3b2c8f 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -763,5 +763,6 @@ "default_sell_provider": "Proveedor de venta predeterminado", "select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.", "custom_drag": "Custom (mantenía y arrastre)", - "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)", + "use_testnet": "Use TestNet" +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 862f9ae7d..056eaa70e 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -763,5 +763,6 @@ "default_sell_provider": "Fournisseur de vente par défaut", "select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.", "custom_drag": "Custom (maintenir et traîner)", - "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)", + "use_testnet": "Utiliser TestNet" +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 9456085dc..5e331a77d 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -745,5 +745,6 @@ "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", "select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.", "custom_drag": "Al'ada (riƙe da ja)", - "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", + "use_testnet": "Amfani da gwaji" +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f6a7701ee..6adfb0640 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -763,5 +763,6 @@ "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", "select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", "custom_drag": "कस्टम (पकड़ और खींचें)", - "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)" -} + "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)", + "use_testnet": "टेस्टनेट का उपयोग करें" +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 3565c89a0..cd0ae75d5 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -761,5 +761,6 @@ "default_sell_provider": "Zadani dobavljač prodaje", "select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.", "custom_drag": "Prilagođeni (držite i povucite)", - "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)", + "use_testnet": "Koristite TestNet" +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 6744f0a38..eda82f728 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -751,5 +751,6 @@ "default_sell_provider": "Penyedia Penjualan Default", "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.", "custom_drag": "Khusus (tahan dan seret)", - "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", + "use_testnet": "Gunakan TestNet" +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index bb909a7e0..d3badfcbd 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -763,5 +763,6 @@ "default_sell_provider": "Fornitore di vendita predefinito", "select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)", + "use_testnet": "Usa TestNet" +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 2152a3dcc..d71adeefd 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -763,5 +763,6 @@ "default_sell_provider": "デフォルトの販売プロバイダー", "select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。", "custom_drag": "カスタム(ホールドとドラッグ)", - "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)" -} + "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)", + "use_testnet": "テストネットを使用します" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 5ad5482ed..cde991267 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -761,5 +761,6 @@ "default_sell_provider": "기본 판매 공급자", "select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.", "custom_drag": "사용자 정의 (홀드 앤 드래그)", - "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)" -} + "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)", + "use_testnet": "TestNet을 사용하십시오" +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 73f4e5dcd..2b1b7cbf3 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -761,5 +761,6 @@ "default_sell_provider": "ပုံသေရောင်းချပေးသူ", "select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။", "custom_drag": "စိတ်ကြိုက် (Drag)", - "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)" -} + "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)", + "use_testnet": "testnet ကိုသုံးပါ" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 6cf41e0b9..65640b98d 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -763,5 +763,6 @@ "default_sell_provider": "Standaard verkoopaanbieder", "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.", "custom_drag": "Custom (vasthouden en slepen)", - "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)", + "use_testnet": "Gebruik testnet" +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 9d3fb3f93..3f6687d32 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -763,5 +763,6 @@ "default_sell_provider": "Domyślny dostawca sprzedaży", "select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.", "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", - "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)", + "use_testnet": "Użyj testne" +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 5cf1fd370..67ee25c8a 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -762,5 +762,6 @@ "default_sell_provider": "Provedor de venda padrão", "select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.", "custom_drag": "Personalizado (segure e arraste)", - "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", + "use_testnet": "Use testNet" +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c81c0bd82..d420087d6 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -763,5 +763,6 @@ "default_sell_provider": "Поставщик продаж по умолчанию", "select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.", "custom_drag": "Пользователь (удерживайте и перетаскивайте)", - "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)." -} + "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon).", + "use_testnet": "Используйте Testnet" +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 0965d3979..87a6d8943 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -761,5 +761,6 @@ "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", "select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป", "custom_drag": "กำหนดเอง (ค้างและลาก)", - "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", + "use_testnet": "ใช้ testnet" +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index f9bbb5dea..2cfc66235 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -757,5 +757,6 @@ "default_sell_provider": "Default na Sell Provider", "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", "custom_drag": "Pasadyang (hawakan at i -drag)", - "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)", + "use_testnet": "Gumamit ng testnet" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 6fdb8bb99..99ad0e1bc 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -761,5 +761,6 @@ "default_sell_provider": "Varsayılan Satış Sağlayıcısı", "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", "custom_drag": "Özel (Bekle ve Sürükle)", - "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", + "use_testnet": "TestNet kullanın" +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 721a3970d..ebfd784a5 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -763,5 +763,6 @@ "default_sell_provider": "Постачальник продажу за замовчуванням", "select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.", "custom_drag": "На замовлення (утримуйте та перетягується)", - "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)", + "use_testnet": "Використовуйте тестову мережу" +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e4a9f4590..4de84285e 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -755,5 +755,6 @@ "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", "select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ", "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", - "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ " -} + "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ", + "use_testnet": "ٹیسٹ نیٹ استعمال کریں" +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 964307e6b..1d13967c9 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -757,5 +757,6 @@ "default_sell_provider": "Aiyipada Olupese Tita", "select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.", "custom_drag": "Aṣa (mu ati fa)", - "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)", + "use_testnet": "Lo tele" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 43e8c6ce1..20467d256 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -762,5 +762,6 @@ "default_sell_provider": "默认销售提供商", "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。", "custom_drag": "定制(保持和拖动)", - "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)" -} + "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)", + "use_testnet": "使用TestNet" +} \ No newline at end of file From fe19f5aeef979e83a338af48141bc1094cec8469 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 12 Jan 2024 21:22:21 +0200 Subject: [PATCH 08/59] Fix review comments Remove bitcoin_base from cw_core --- cw_bitcoin/lib/address_to_output_script.dart | 11 ----- cw_bitcoin/lib/electrum_wallet.dart | 2 +- cw_bitcoin/lib/electrum_wallet_addresses.dart | 45 ++++++++++--------- cw_core/lib/unspent_transaction_output.dart | 4 +- cw_core/lib/wallet_addresses.dart | 3 +- cw_core/pubspec.lock | 17 ------- cw_core/pubspec.yaml | 4 -- 7 files changed, 28 insertions(+), 58 deletions(-) diff --git a/cw_bitcoin/lib/address_to_output_script.dart b/cw_bitcoin/lib/address_to_output_script.dart index f1e5a30a1..6ae50132b 100644 --- a/cw_bitcoin/lib/address_to_output_script.dart +++ b/cw_bitcoin/lib/address_to_output_script.dart @@ -3,17 +3,6 @@ import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin; List addressToOutputScript(String address, bitcoin.BasedUtxoNetwork network) { try { - // FIXME: improve validation for p2sh addresses - // 3 for bitcoin - // m for litecoin - // (note: m is also for bitcoin's testnet. check networkType to make sure) - if (address.startsWith('3') || - (address.toLowerCase().startsWith('m') && network != bitcoin.BitcoinNetwork.testnet)) { - return bitcoin.P2shAddress.fromAddress(address: address, network: network) - .toScriptPubKey() - .toBytes(); - } - return bitcoin.addressToOutputScript(address: address, network: network); } catch (err) { print(err); diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 589d822d7..7ca0dae09 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -361,7 +361,7 @@ abstract class ElectrumWalletBase String toJSON() => json.encode({ 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentChangeAddressIndexByType, + 'account_index': walletAddresses.currentReceiveAddressIndexByType, 'change_address_index': walletAddresses.currentChangeAddressIndexByType, 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), 'address_page_type': walletInfo.addressPageType.toString(), diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 47ec1a0c5..99b7980ef 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -55,29 +55,14 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @observable BitcoinAddressType _addressPageType = BitcoinAddressType.p2wpkh; + @computed BitcoinAddressType get addressPageType => _addressPageType; + @computed @override String get addressPageTypeStr => addressPageType.toString(); - @computed - String get receiveAddress { - if (receiveAddresses.isEmpty) { - final address = generateNewAddress().address; - return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address; - } - final receiveAddress = receiveAddresses.first.address; - - return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; - } - - @override - String get primaryAddress => getAddress(index: 0, hd: mainHd); - - @override - set address(String addr) => null; - @override @computed String get address { @@ -87,25 +72,39 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } try { - return receiveAddresses.firstWhere((address) { + final receiveAddress = receiveAddresses.firstWhere((address) { return addressPageType == BitcoinAddressType.p2wpkh ? address.type == null || address.type == addressPageType : address.type == addressPageType; }).address; + + return walletInfo.type == WalletType.bitcoinCash + ? toCashAddr(receiveAddress) + : receiveAddress; } catch (_) {} return receiveAddresses.first.address; } + @override + String get primaryAddress => getAddress(index: 0, hd: mainHd); + + @override + set address(String addr) => null; + Map currentReceiveAddressIndexByType = {}; + int get currentReceiveAddressIndex => currentReceiveAddressIndexByType[_addressPageType.toString()] ?? 0; + void set currentReceiveAddressIndex(int index) => currentReceiveAddressIndexByType[_addressPageType.toString()] = index; Map currentChangeAddressIndexByType = {}; + int get currentChangeAddressIndex => currentChangeAddressIndexByType[_addressPageType.toString()] ?? 0; + void set currentChangeAddressIndex(int index) => currentChangeAddressIndexByType[_addressPageType.toString()] = index; @@ -265,14 +264,20 @@ 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); + startIndex: countOfReceiveAddresses, + hd: mainHd, + isHidden: false, + addressType: addressPageType); addresses.addAll(newAddresses); } if (countOfHiddenAddresses < defaultChangeAddressesCount) { final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses; final newAddresses = await _createNewAddresses(addressesCount, - startIndex: countOfHiddenAddresses, hd: sideHd, isHidden: true); + startIndex: countOfHiddenAddresses, + hd: sideHd, + isHidden: true, + addressType: addressPageType); addresses.addAll(newAddresses); } } diff --git a/cw_core/lib/unspent_transaction_output.dart b/cw_core/lib/unspent_transaction_output.dart index 528236185..b52daf43c 100644 --- a/cw_core/lib/unspent_transaction_output.dart +++ b/cw_core/lib/unspent_transaction_output.dart @@ -1,5 +1,3 @@ -import 'package:bitcoin_base/bitcoin_base.dart'; - class Unspent { Unspent(this.address, this.hash, this.value, this.vout, this.keyImage) : isSending = true, @@ -18,5 +16,5 @@ class Unspent { bool isFrozen; String note; - bool get isP2wpkh => P2wpkhAddress.REGEX.hasMatch(address) || address.startsWith('ltc'); + bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc'); } diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index bda89401f..9b82a6252 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -1,4 +1,3 @@ -import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_core/address_info.dart'; import 'package:cw_core/wallet_info.dart'; @@ -21,7 +20,7 @@ abstract class WalletAddresses { Set usedAddresses = {}; - String addressPageTypeStr = BitcoinAddressType.p2wpkh.toString(); + String? addressPageTypeStr; Future init(); diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index 028bb5bb3..d5f2056a1 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -41,23 +41,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" - bitcoin_base: - dependency: "direct main" - description: - path: "." - ref: cake-update-v1 - resolved-ref: ae3030bc30039e8e58241a6e9e5e007079d5aea6 - url: "https://github.com/cake-tech/bitcoin_base.git" - source: git - version: "3.0.1" - blockchain_utils: - dependency: transitive - description: - name: blockchain_utils - sha256: "9701dfaa74caad4daae1785f1ec4445cf7fb94e45620bc3a4aca1b9b281dc6c9" - url: "https://pub.dev" - source: hosted - version: "1.6.0" boolean_selector: dependency: transitive description: diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 105158bfe..04a840d4e 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -20,10 +20,6 @@ dependencies: intl: ^0.18.0 encrypt: ^5.0.1 socks5_proxy: ^1.0.4 - bitcoin_base: - git: - url: https://github.com/cake-tech/bitcoin_base.git - ref: cake-update-v1 # tor: # git: # url: https://github.com/cake-tech/tor.git From 5af18a6d2c41358772c8cbd15dd228dbcfdcd6eb Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Fri, 12 Jan 2024 21:51:14 +0200 Subject: [PATCH 09/59] Fix address not matching selected type on start --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 99b7980ef..64f66a564 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -66,13 +66,18 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @override @computed String get address { - if (receiveAddresses.isEmpty) { + final typeMatchingAddresses = receiveAddresses.where((address) { + return addressPageType == BitcoinAddressType.p2wpkh + ? address.type == null || address.type == addressPageType + : address.type == addressPageType; + }); + + if (typeMatchingAddresses.isEmpty) { final address = generateNewAddress().address; return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address; } - try { - final receiveAddress = receiveAddresses.firstWhere((address) { + final receiveAddress = receiveAddresses.firstWhere((address) { return addressPageType == BitcoinAddressType.p2wpkh ? address.type == null || address.type == addressPageType : address.type == addressPageType; @@ -81,9 +86,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; - } catch (_) {} - - return receiveAddresses.first.address; } @override From ba6cb8f4eb8426669c760e6cb7fbd99f8b4abcb9 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 13 Jan 2024 00:03:37 +0200 Subject: [PATCH 10/59] remove un-necessary parameter [skip ci] --- cw_bitcoin/lib/bitcoin_wallet.dart | 1 - cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 1 - cw_bitcoin/lib/electrum_wallet_addresses.dart | 1 - cw_bitcoin/lib/litecoin_wallet.dart | 1 - cw_bitcoin/lib/litecoin_wallet_addresses.dart | 1 - cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart | 1 - cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart | 1 - 7 files changed, 7 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index d3fa223bc..e4ea2872b 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -49,7 +49,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { mainHd: hd, sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), network: networkParam ?? network, - initialAddressPageType: addressPageType, ); } diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index 6ce713e4e..cbc086839 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -17,7 +17,6 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S required super.network, required super.electrumClient, super.initialAddresses, - super.initialAddressPageType, super.initialRegularAddressIndex = const {}, super.initialChangeAddressIndex = const {}, }) : super(walletInfo); diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 64f66a564..9c4c690e9 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -20,7 +20,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { required this.sideHd, required this.electrumClient, required this.network, - String? initialAddressPageType, List? initialAddresses, Map initialRegularAddressIndex = const {}, Map initialChangeAddressIndex = const {}, diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 90dd3ce2d..4a9c007ec 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -50,7 +50,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { mainHd: hd, sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), network: network, - initialAddressPageType: addressPageType, ); } diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart index 65ea43cbb..f7d49b64d 100644 --- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart @@ -16,7 +16,6 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with required super.sideHd, required super.network, required super.electrumClient, - super.initialAddressPageType, super.initialAddresses, super.initialRegularAddressIndex = const {}, super.initialChangeAddressIndex = const {}, diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 74fee5b17..d88586fff 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -58,7 +58,6 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { mainHd: hd, sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"), network: network, - initialAddressPageType: addressPageType, ); } diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart index deb50184b..b0741ed34 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -16,7 +16,6 @@ abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses wi required super.sideHd, required super.network, required super.electrumClient, - super.initialAddressPageType, super.initialAddresses, super.initialRegularAddressIndex = const {}, super.initialChangeAddressIndex = const {}, From a0936b9eb8efa5af6351998f4841f386626fd53e Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 13 Jan 2024 01:54:27 +0200 Subject: [PATCH 11/59] Remove bitcoin specific code from main lib Fix possible runtime exception from list wrong access --- lib/router.dart | 8 ++++---- .../advanced_privacy_settings_page.dart | 15 ++++++++------- lib/src/screens/new_wallet/new_wallet_page.dart | 11 +++++------ .../transaction_details_view_model.dart | 8 +------- 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/lib/router.dart b/lib/router.dart index 0cedd11b2..37a409f2c 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -532,10 +532,10 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get(param1: title, param2: url)); case Routes.advancedPrivacySettings: - final args = settings.arguments as List; - final type = args.first as WalletType; - final useTestnet = args[1] as bool?; - final toggleTestnet = args[2] as Function(bool? val); + final args = settings.arguments as Map; + final type = args['type'] as WalletType; + final useTestnet = args['useTestnet'] as bool?; + final toggleTestnet = args['toggleTestnet'] as Function(bool? val)?; return CupertinoPageRoute( builder: (_) => AdvancedPrivacySettingsPage( diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 0e3a81d5f..f2dbdbd93 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -32,11 +32,11 @@ class AdvancedPrivacySettingsPage extends BasePage { String get title => S.current.privacy_settings; final bool? useTestnet; - final Function(bool? val) toggleUseTestnet; + final Function(bool? val)? toggleUseTestnet; @override - Widget body(BuildContext context) => AdvancedPrivacySettingsBody( - useTestnet, toggleUseTestnet, advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel); + Widget body(BuildContext context) => AdvancedPrivacySettingsBody(useTestnet, toggleUseTestnet, + advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel); } class AdvancedPrivacySettingsBody extends StatefulWidget { @@ -50,7 +50,7 @@ class AdvancedPrivacySettingsBody extends StatefulWidget { final SeedTypeViewModel seedTypeViewModel; final bool? useTestnet; - final Function(bool? val) toggleUseTestnet; + final Function(bool? val)? toggleUseTestnet; @override _AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState(); @@ -138,7 +138,8 @@ class _AdvancedPrivacySettingsBodyState extends State { const SizedBox(height: 25), GestureDetector( onTap: () { - Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, arguments: [ - _walletNewVM.type, - _walletNewVM.useTestnet, - _walletNewVM.toggleUseTestnet - ]); + Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, arguments: { + "type": _walletNewVM.type, + "useTestnet": _walletNewVM.useTestnet, + "toggleUseTestnet": _walletNewVM.toggleUseTestnet + }); }, child: Text(S.of(context).advanced_settings), ), diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 30e82e143..cc3841201 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -1,4 +1,3 @@ -import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_type.dart'; @@ -16,7 +15,6 @@ import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:cake_wallet/monero/monero.dart'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; part 'transaction_details_view_model.g.dart'; @@ -118,11 +116,7 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.monero: return 'https://monero.com/tx/${txId}'; case WalletType.bitcoin: - if (wallet is ElectrumWallet) { - final networkType = (wallet as ElectrumWallet).networkType; - return 'https://mempool.space/${networkType == bitcoin.testnet ? "testnet/" : ""}tx/${txId}'; - } - return 'https://blockchair.com/litecoin/transaction/${txId}'; + return 'https://mempool.space/${wallet.isTestnet == true ? "testnet/" : ""}tx/${txId}'; case WalletType.litecoin: return 'https://blockchair.com/litecoin/transaction/${txId}'; case WalletType.bitcoinCash: From af839af435f0ff4b89e3bfa6305b18ec1681cc7f Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 13 Jan 2024 01:56:15 +0200 Subject: [PATCH 12/59] Minor fix --- lib/src/screens/restore/wallet_restore_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 899aacd19..a3f872f09 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -211,7 +211,7 @@ class WalletRestorePage extends BasePage { GestureDetector( onTap: () { Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, - arguments: walletRestoreViewModel.type); + arguments: {'type': walletRestoreViewModel.type}); }, child: Text(S.of(context).advanced_settings), ), From b903e4993e36724daca035943b059e6e1c27fff4 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Tue, 16 Jan 2024 15:41:35 -0300 Subject: [PATCH 13/59] fix: fixes for Testnet --- cw_bitcoin/lib/bitcoin_wallet.dart | 6 ++++- cw_haven/pubspec.lock | 17 ------------ cw_monero/example/pubspec.lock | 17 ------------ cw_monero/pubspec.lock | 17 ------------ cw_nano/pubspec.lock | 26 +++++++------------ lib/router.dart | 4 +-- .../advanced_privacy_settings_page.dart | 11 ++++---- .../screens/new_wallet/new_wallet_page.dart | 2 +- .../screens/restore/wallet_restore_page.dart | 8 ++++-- 9 files changed, 28 insertions(+), 80 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index e4ea2872b..2168d1d1a 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -35,7 +35,11 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, - networkType: bitcoin.bitcoin, + networkType: networkParam == null + ? bitcoin.bitcoin + : networkParam == BitcoinNetwork.mainnet + ? bitcoin.bitcoin + : bitcoin.testnet, initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: seedBytes, diff --git a/cw_haven/pubspec.lock b/cw_haven/pubspec.lock index 2a7bdaa44..b0a350cc7 100644 --- a/cw_haven/pubspec.lock +++ b/cw_haven/pubspec.lock @@ -41,23 +41,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" - bitcoin_base: - dependency: transitive - description: - path: "." - ref: cake-update-v1 - resolved-ref: cf04ecee73316431230083a236392d1a87697b43 - url: "https://github.com/cake-tech/bitcoin_base.git" - source: git - version: "3.0.1" - blockchain_utils: - dependency: transitive - description: - name: blockchain_utils - sha256: "345706b5cbfd7e2daea5d210504a4d6ec589e40bf40b5b4946e1fdd9bf59320d" - url: "https://pub.dev" - source: hosted - version: "1.5.0" boolean_selector: dependency: transitive description: diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index e3e0db311..c9ca8d92b 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -25,23 +25,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" - bitcoin_base: - dependency: transitive - description: - path: "." - ref: cake-update-v1 - resolved-ref: cf04ecee73316431230083a236392d1a87697b43 - url: "https://github.com/cake-tech/bitcoin_base.git" - source: git - version: "3.0.1" - blockchain_utils: - dependency: transitive - description: - name: blockchain_utils - sha256: "345706b5cbfd7e2daea5d210504a4d6ec589e40bf40b5b4946e1fdd9bf59320d" - url: "https://pub.dev" - source: hosted - version: "1.5.0" boolean_selector: dependency: transitive description: diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index beba80932..0f8f2c90e 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -41,23 +41,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" - bitcoin_base: - dependency: transitive - description: - path: "." - ref: cake-update-v1 - resolved-ref: cf04ecee73316431230083a236392d1a87697b43 - url: "https://github.com/cake-tech/bitcoin_base.git" - source: git - version: "3.0.1" - blockchain_utils: - dependency: transitive - description: - name: blockchain_utils - sha256: "345706b5cbfd7e2daea5d210504a4d6ec589e40bf40b5b4946e1fdd9bf59320d" - url: "https://pub.dev" - source: hosted - version: "1.5.0" boolean_selector: dependency: transitive description: diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index 38ea6d241..a42bb9ab4 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -57,23 +57,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" - bitcoin_base: - dependency: transitive - description: - path: "." - ref: cake-update-v1 - resolved-ref: cf04ecee73316431230083a236392d1a87697b43 - url: "https://github.com/cake-tech/bitcoin_base.git" - source: git - version: "3.0.1" - blockchain_utils: - dependency: transitive - description: - name: blockchain_utils - sha256: "345706b5cbfd7e2daea5d210504a4d6ec589e40bf40b5b4946e1fdd9bf59320d" - url: "https://pub.dev" - source: hosted - version: "1.5.0" boolean_selector: dependency: transitive description: @@ -488,6 +471,15 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + nanoutil: + dependency: "direct main" + description: + path: "." + ref: c37e72817cf0a28162f43124f79661d6c8e0098f + resolved-ref: c37e72817cf0a28162f43124f79661d6c8e0098f + url: "https://github.com/perishllc/nanoutil.git" + source: git + version: "1.0.0" package_config: dependency: transitive description: diff --git a/lib/router.dart b/lib/router.dart index 37a409f2c..ef7b7f31e 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -534,8 +534,8 @@ Route createRoute(RouteSettings settings) { case Routes.advancedPrivacySettings: final args = settings.arguments as Map; final type = args['type'] as WalletType; - final useTestnet = args['useTestnet'] as bool?; - final toggleTestnet = args['toggleTestnet'] as Function(bool? val)?; + final useTestnet = args['useTestnet'] as bool; + final toggleTestnet = args['toggleTestnet'] as Function(bool? val); return CupertinoPageRoute( builder: (_) => AdvancedPrivacySettingsPage( diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index f2dbdbd93..26478345e 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -31,8 +31,8 @@ class AdvancedPrivacySettingsPage extends BasePage { @override String get title => S.current.privacy_settings; - final bool? useTestnet; - final Function(bool? val)? toggleUseTestnet; + final bool useTestnet; + final Function(bool? val) toggleUseTestnet; @override Widget body(BuildContext context) => AdvancedPrivacySettingsBody(useTestnet, toggleUseTestnet, @@ -49,8 +49,8 @@ class AdvancedPrivacySettingsBody extends StatefulWidget { final NodeCreateOrEditViewModel nodeViewModel; final SeedTypeViewModel seedTypeViewModel; - final bool? useTestnet; - final Function(bool? val)? toggleUseTestnet; + final bool useTestnet; + final Function(bool? val) toggleUseTestnet; @override _AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState(); @@ -138,8 +138,7 @@ class _AdvancedPrivacySettingsBodyState extends State { Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, arguments: { "type": _walletNewVM.type, "useTestnet": _walletNewVM.useTestnet, - "toggleUseTestnet": _walletNewVM.toggleUseTestnet + "toggleTestnet": _walletNewVM.toggleUseTestnet }); }, child: Text(S.of(context).advanced_settings), diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index a3f872f09..fe5ac8487 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -210,8 +210,12 @@ class WalletRestorePage extends BasePage { const SizedBox(height: 25), GestureDetector( onTap: () { - Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, - arguments: {'type': walletRestoreViewModel.type}); + Navigator.of(context) + .pushNamed(Routes.advancedPrivacySettings, arguments: { + 'type': walletRestoreViewModel.type, + 'useTestnet': walletRestoreViewModel.useTestnet, + 'toggleTestnet': walletRestoreViewModel.toggleUseTestnet + }); }, child: Text(S.of(context).advanced_settings), ), From 0a76faaeed9d6207724d3248ff35f16e152f6d26 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Tue, 16 Jan 2024 16:25:08 -0300 Subject: [PATCH 14/59] fix: bitcoin receive option dependency breaks monerocom --- .../lib/bitcoin_receive_page_option.dart | 32 ++++++------------- cw_core/lib/enumerate.dart | 13 ++++++++ cw_core/lib/receive_page_option.dart | 21 ++++++++++++ lib/di.dart | 2 +- .../screens/dashboard/pages/address_page.dart | 3 +- .../screens/receive/anonpay_invoice_page.dart | 2 +- .../screens/receive/anonpay_receive_page.dart | 2 +- .../anon_invoice_page_view_model.dart | 2 +- .../dashboard/receive_option_view_model.dart | 3 +- 9 files changed, 51 insertions(+), 29 deletions(-) rename lib/entities/receive_page_option.dart => cw_bitcoin/lib/bitcoin_receive_page_option.dart (62%) create mode 100644 cw_core/lib/enumerate.dart create mode 100644 cw_core/lib/receive_page_option.dart diff --git a/lib/entities/receive_page_option.dart b/cw_bitcoin/lib/bitcoin_receive_page_option.dart similarity index 62% rename from lib/entities/receive_page_option.dart rename to cw_bitcoin/lib/bitcoin_receive_page_option.dart index a0664e5f2..65daf8d5a 100644 --- a/lib/entities/receive_page_option.dart +++ b/cw_bitcoin/lib/bitcoin_receive_page_option.dart @@ -1,33 +1,19 @@ import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:cw_core/receive_page_option.dart'; -class ReceivePageOption { - static const mainnet = ReceivePageOption._('mainnet'); - static const anonPayInvoice = ReceivePageOption._('anonPayInvoice'); - static const anonPayDonationLink = ReceivePageOption._('anonPayDonationLink'); - - const ReceivePageOption._(this._value); - - final String _value; - - @override - String toString() { - return _value; - } -} - -const ReceivePageOptions = [ - ReceivePageOption.mainnet, - ReceivePageOption.anonPayInvoice, - ReceivePageOption.anonPayDonationLink -]; - -class BitcoinReceivePageOption extends ReceivePageOption { +class BitcoinReceivePageOption implements ReceivePageOption { static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH)'); static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)'); static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)'); static const p2pkh = BitcoinReceivePageOption._('Legacy (P2PKH)'); - const BitcoinReceivePageOption._(String value) : super._(value); + const BitcoinReceivePageOption._(this.value); + + final String value; + + String toString() { + return value; + } factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) { switch (type) { diff --git a/cw_core/lib/enumerate.dart b/cw_core/lib/enumerate.dart new file mode 100644 index 000000000..d92347e91 --- /dev/null +++ b/cw_core/lib/enumerate.dart @@ -0,0 +1,13 @@ +abstract class Enumerate { + String get value; + + @override + operator ==(other) { + if (identical(other, this)) return true; + if (other is! Enumerate) return false; + return other.runtimeType == runtimeType && value == other.value; + } + + @override + int get hashCode => value.hashCode; +} diff --git a/cw_core/lib/receive_page_option.dart b/cw_core/lib/receive_page_option.dart new file mode 100644 index 000000000..786d07bc5 --- /dev/null +++ b/cw_core/lib/receive_page_option.dart @@ -0,0 +1,21 @@ +import 'package:cw_core/enumerate.dart'; + +class ReceivePageOption implements Enumerate { + static const mainnet = ReceivePageOption._('mainnet'); + static const anonPayInvoice = ReceivePageOption._('anonPayInvoice'); + static const anonPayDonationLink = ReceivePageOption._('anonPayDonationLink'); + + const ReceivePageOption._(this.value); + + final String value; + + String toString() { + return value; + } +} + +const ReceivePageOptions = [ + ReceivePageOption.mainnet, + ReceivePageOption.anonPayInvoice, + ReceivePageOption.anonPayDonationLink +]; diff --git a/lib/di.dart b/lib/di.dart index 61a04bf1c..c449fbc02 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -13,7 +13,7 @@ import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/ionia/ionia_anypay.dart'; diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index a943e1be7..8604050cc 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -4,7 +4,8 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart'; import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; +import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; diff --git a/lib/src/screens/receive/anonpay_invoice_page.dart b/lib/src/screens/receive/anonpay_invoice_page.dart index fc835c72d..f33cdcc5b 100644 --- a/lib/src/screens/receive/anonpay_invoice_page.dart +++ b/lib/src/screens/receive/anonpay_invoice_page.dart @@ -4,7 +4,7 @@ import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/screens/receive/widgets/anonpay_input_form.dart'; diff --git a/lib/src/screens/receive/anonpay_receive_page.dart b/lib/src/screens/receive/anonpay_receive_page.dart index b602abde6..7d71e3a22 100644 --- a/lib/src/screens/receive/anonpay_receive_page.dart +++ b/lib/src/screens/receive/anonpay_receive_page.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; diff --git a/lib/view_model/anon_invoice_page_view_model.dart b/lib/view_model/anon_invoice_page_view_model.dart index 53e8473a0..187eea375 100644 --- a/lib/view_model/anon_invoice_page_view_model.dart +++ b/lib/view_model/anon_invoice_page_view_model.dart @@ -4,7 +4,7 @@ import 'package:cake_wallet/anonpay/anonpay_request.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/currency.dart'; diff --git a/lib/view_model/dashboard/receive_option_view_model.dart b/lib/view_model/dashboard/receive_option_view_model.dart index 20e5c424d..a8c802e98 100644 --- a/lib/view_model/dashboard/receive_option_view_model.dart +++ b/lib/view_model/dashboard/receive_option_view_model.dart @@ -1,5 +1,6 @@ -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; +import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; From a600040ec371bc17826d9ab45279ea7805138203 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 18 Jan 2024 01:18:44 +0200 Subject: [PATCH 15/59] Fix issues when building Monero.com --- cw_bitcoin/lib/bitcoin_receive_page_option.dart | 14 +++++++------- cw_bitcoin/lib/electrum_wallet_addresses.dart | 3 +-- lib/bitcoin/cw_bitcoin.dart | 9 +++++++++ lib/src/screens/dashboard/pages/address_page.dart | 1 - .../dashboard/receive_option_view_model.dart | 8 +++----- tool/configure.dart | 3 +++ 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_receive_page_option.dart b/cw_bitcoin/lib/bitcoin_receive_page_option.dart index 65daf8d5a..f04221ef1 100644 --- a/cw_bitcoin/lib/bitcoin_receive_page_option.dart +++ b/cw_bitcoin/lib/bitcoin_receive_page_option.dart @@ -15,6 +15,13 @@ class BitcoinReceivePageOption implements ReceivePageOption { return value; } + static const all = [ + BitcoinReceivePageOption.p2wpkh, + BitcoinReceivePageOption.p2tr, + BitcoinReceivePageOption.p2wsh, + BitcoinReceivePageOption.p2pkh + ]; + factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) { switch (type) { case BitcoinAddressType.p2tr: @@ -29,10 +36,3 @@ class BitcoinReceivePageOption implements ReceivePageOption { } } } - -const BitcoinReceivePageOptions = [ - BitcoinReceivePageOption.p2wpkh, - BitcoinReceivePageOption.p2tr, - BitcoinReceivePageOption.p2wsh, - BitcoinReceivePageOption.p2pkh -]; diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 9c4c690e9..08549e70c 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -33,8 +33,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { currentReceiveAddressIndexByType = initialRegularAddressIndex, currentChangeAddressIndexByType = initialChangeAddressIndex, _addressPageType = walletInfo.addressPageType != null - ? BitcoinAddressType.fromValue( - walletInfo.addressPageType ?? BitcoinAddressType.p2wpkh.toString()) + ? BitcoinAddressType.fromValue(walletInfo.addressPageType!) : BitcoinAddressType.p2wpkh, super(walletInfo); diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index f26b39c68..f8776e0a9 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -161,4 +161,13 @@ class CWBitcoin extends Bitcoin { final bitcoinWallet = wallet as ElectrumWallet; await bitcoinWallet.walletAddresses.setAddressType(option as BitcoinAddressType); } + + @override + BitcoinReceivePageOption getSelectedAddressType(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return BitcoinReceivePageOption.fromType(bitcoinWallet.walletAddresses.addressPageType); + } + + @override + List getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all; } \ No newline at end of file diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index 8604050cc..473a60959 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -26,7 +26,6 @@ import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_base/bitcoin_base.dart'; class AddressPage extends BasePage { diff --git a/lib/view_model/dashboard/receive_option_view_model.dart b/lib/view_model/dashboard/receive_option_view_model.dart index a8c802e98..1e4726eee 100644 --- a/lib/view_model/dashboard/receive_option_view_model.dart +++ b/lib/view_model/dashboard/receive_option_view_model.dart @@ -1,6 +1,5 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cw_core/receive_page_option.dart'; -import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; -import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -13,8 +12,7 @@ abstract class ReceiveOptionViewModelBase with Store { ReceiveOptionViewModelBase(this._wallet, this.initialPageOption) : selectedReceiveOption = initialPageOption ?? (_wallet.type == WalletType.bitcoin - ? BitcoinReceivePageOption.fromType( - (_wallet.walletAddresses as ElectrumWalletAddresses).addressPageType) + ? bitcoin!.getSelectedAddressType(_wallet) : ReceivePageOption.mainnet), _options = [] { final walletType = _wallet.type; @@ -22,7 +20,7 @@ abstract class ReceiveOptionViewModelBase with Store { ? [ReceivePageOption.mainnet] : walletType == WalletType.bitcoin ? [ - ...BitcoinReceivePageOptions, + ...bitcoin!.getBitcoinReceivePageOptions(), ...ReceivePageOptions.where((element) => element != ReceivePageOption.mainnet) ] : ReceivePageOptions; diff --git a/tool/configure.dart b/tool/configure.dart index d6f56e01d..02b1aa89d 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -66,6 +66,7 @@ import 'package:cw_core/wallet_service.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:hive/hive.dart';"""; const bitcoinCWHeaders = """ +import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; @@ -115,6 +116,8 @@ abstract class Bitcoin { TransactionPriority getLitecoinTransactionPrioritySlow(); Future setAddressType(Object wallet, dynamic option); + BitcoinReceivePageOption getSelectedAddressType(Object wallet); + List getBitcoinReceivePageOptions(); } """; From 3ebaf11de3c8974ca59af877b98e4c71d5860018 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 18 Jan 2024 19:27:57 -0300 Subject: [PATCH 16/59] feat: Transaction Builder changes --- cw_bitcoin/lib/address_from_output.dart | 35 +- cw_bitcoin/lib/electrum.dart | 2 +- cw_bitcoin/lib/electrum_transaction_info.dart | 28 +- cw_bitcoin/lib/electrum_wallet.dart | 380 ++++++++++-------- .../lib/pending_bitcoin_transaction.dart | 21 +- cw_bitcoin/lib/utils.dart | 10 +- cw_bitcoin/pubspec.lock | 6 +- .../lib/src/bitcoin_cash_wallet.dart | 8 +- cw_core/pubspec.lock | 4 +- lib/view_model/wallet_creation_vm.dart | 3 +- 10 files changed, 268 insertions(+), 229 deletions(-) diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index b6c8a0afb..7762fe94d 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -1,25 +1,22 @@ -import 'dart:typed_data'; import 'package:bitcoin_base/bitcoin_base.dart'; -String addressFromOutput(Uint8List script, BasedUtxoNetwork network) { +String addressFromOutputScript(Script script, BasedUtxoNetwork network) { try { - return P2pkhAddress.fromScriptPubkey(script: Script.fromRaw(byteData: script)) - .toAddress(network); - } catch (_) {} - - try { - return P2wpkhAddress.fromScriptPubkey(script: Script.fromRaw(byteData: script)) - .toAddress(network); - } catch (_) {} - - try { - return P2wshAddress.fromScriptPubkey(script: Script.fromRaw(byteData: script)) - .toAddress(network); - } catch (_) {} - - try { - return P2trAddress.fromScriptPubkey(script: Script.fromRaw(byteData: script)) - .toAddress(network); + switch (script.getType()) { + case ScriptType.P2PK: + return P2pkAddress.fromScriptPubkey(script: script).toAddress(network); + case ScriptType.P2PKH: + return P2pkhAddress.fromScriptPubkey(script: script).toAddress(network); + case ScriptType.P2SH: + return P2shAddress.fromScriptPubkey(script: script).toAddress(network); + case ScriptType.P2WPKH: + return P2wpkhAddress.fromScriptPubkey(script: script).toAddress(network); + case ScriptType.P2WSH: + return P2wshAddress.fromScriptPubkey(script: script).toAddress(network); + case ScriptType.P2TR: + return P2trAddress.fromScriptPubkey(script: script).toAddress(network); + default: + } } catch (_) {} return ''; diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index d76eb09cb..4748c2818 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -244,7 +244,7 @@ class ElectrumClient { Future broadcastTransaction( {required String transactionRaw, BasedUtxoNetwork? network}) async { - if (network != null && network == BitcoinNetwork.testnet) { + if (network == BitcoinNetwork.testnet) { return http .post(Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx'), headers: {'Content-Type': 'application/json; charset=utf-8'}, diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index c6a7b212e..6cb64e6cb 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -1,5 +1,6 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:cw_bitcoin/address_from_output.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; @@ -12,8 +13,8 @@ import 'package:cw_core/wallet_type.dart'; class ElectrumTransactionBundle { ElectrumTransactionBundle(this.originalTransaction, {required this.ins, required this.confirmations, this.time}); - final bitcoin.Transaction originalTransaction; - final List ins; + final bitcoin_base.BtcTransaction originalTransaction; + final List ins; final int? time; final int confirmations; } @@ -100,31 +101,28 @@ class ElectrumTransactionInfo extends TransactionInfo { var inputAmount = 0; var totalOutAmount = 0; - for (var i = 0; i < bundle.originalTransaction.ins.length; i++) { - final input = bundle.originalTransaction.ins[i]; + for (var i = 0; i < bundle.originalTransaction.inputs.length; i++) { + final input = bundle.originalTransaction.inputs[i]; final inputTransaction = bundle.ins[i]; - final vout = input.index; - final outTransaction = inputTransaction.outs[vout!]; - final address = addressFromOutput(outTransaction.script!, network); - inputAmount += outTransaction.value!; - if (addresses.contains(address)) { + final outTransaction = inputTransaction.outputs[input.txIndex]; + inputAmount += outTransaction.amount.toInt(); + if (addresses.contains(addressFromOutputScript(outTransaction.scriptPubKey, network))) { direction = TransactionDirection.outgoing; } } - for (final out in bundle.originalTransaction.outs) { - totalOutAmount += out.value!; - final address = addressFromOutput(out.script!, network); - final addressExists = addresses.contains(address); + for (final out in bundle.originalTransaction.outputs) { + totalOutAmount += out.amount.toInt(); + final addressExists = addresses.contains(addressFromOutputScript(out.scriptPubKey, network)); if ((direction == TransactionDirection.incoming && addressExists) || (direction == TransactionDirection.outgoing && !addressExists)) { - amount += out.value!; + amount += out.amount.toInt(); } } final fee = inputAmount - totalOutAmount; return ElectrumTransactionInfo(type, - id: bundle.originalTransaction.getId(), + id: bundle.originalTransaction.txId(), height: height, isPending: bundle.confirmations == 0, fee: fee, diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 7ca0dae09..44ab8c272 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -5,8 +5,8 @@ import 'dart:math'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base; import 'package:collection/collection.dart'; -import 'package:cw_bitcoin/address_to_output_script.dart' as address_to_output_script; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; @@ -189,174 +189,223 @@ abstract class ElectrumWalletBase @override Future createTransaction(Object credentials) async { - const minAmount = 546; - final transactionCredentials = credentials as BitcoinTransactionCredentials; - final inputs = []; - final outputs = transactionCredentials.outputs; - final hasMultiDestination = outputs.length > 1; - var allInputsAmount = 0; + try { + final outputs = []; + final outputAddresses = []; + final transactionCredentials = credentials as BitcoinTransactionCredentials; + final hasMultiDestination = transactionCredentials.outputs.length > 1; + final sendAll = !hasMultiDestination && transactionCredentials.outputs.first.sendAll; - if (unspentCoins.isEmpty) { - await updateUnspent(); - } + var credentialsAmount = 0; + var minAmount = 0.0; - for (final utx in unspentCoins) { - if (utx.isSending) { - allInputsAmount += utx.value; - inputs.add(utx); - } - } + for (final out in transactionCredentials.outputs) { + final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address; + BitcoinAddress address; - if (inputs.isEmpty) { - throw BitcoinTransactionNoInputsException(); - } + if (P2pkhAddress.REGEX.hasMatch(outputAddress)) { + address = P2pkhAddress.fromAddress(address: outputAddress, network: network); + minAmount += P2pkhAddress.outputSizeVB; + } else if (P2shAddress.REGEX.hasMatch(outputAddress)) { + address = P2shAddress.fromAddress(address: outputAddress, network: network); + minAmount += P2shAddress.outputSizeVB; + } else if (P2wshAddress.REGEX.hasMatch(outputAddress)) { + address = P2wshAddress.fromAddress(address: outputAddress, network: network); + minAmount += P2wshAddress.outputSizeVB; + } else if (P2trAddress.REGEX.hasMatch(outputAddress)) { + address = P2trAddress.fromAddress(address: outputAddress, network: network); + minAmount += P2trAddress.outputSizeVB; + } else if (P2wpkhAddress.REGEX.hasMatch(outputAddress)) { + address = P2wpkhAddress.fromAddress(address: outputAddress, network: network); + minAmount += P2wpkhAddress.outputSizeVB; + } else { + // TODO: proper error here for output address not found + throw BitcoinTransactionWrongBalanceException(currency); + } - final allAmountFee = transactionCredentials.feeRate != null - ? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length) - : feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length); + outputAddresses.add(address); - final allAmount = allInputsAmount - allAmountFee; + if (hasMultiDestination) { + if (out.sendAll || out.formattedCryptoAmount! <= 0) { + throw BitcoinTransactionWrongBalanceException(currency); + } - var credentialsAmount = 0; - var amount = 0; - var fee = 0; + final outputAmount = out.formattedCryptoAmount!; + credentialsAmount += outputAmount; - if (hasMultiDestination) { - if (outputs.any((item) => item.sendAll || item.formattedCryptoAmount! <= 0)) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - credentialsAmount = outputs.fold(0, (acc, value) => acc + value.formattedCryptoAmount!); - - if (allAmount - credentialsAmount < minAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - amount = credentialsAmount; - - if (transactionCredentials.feeRate != null) { - fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount, - outputsCount: outputs.length + 1); - } else { - fee = calculateEstimatedFee(transactionCredentials.priority, amount, - outputsCount: outputs.length + 1); - } - } else { - final output = outputs.first; - credentialsAmount = !output.sendAll ? output.formattedCryptoAmount! : 0; - - if (credentialsAmount > allAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - amount = output.sendAll || allAmount - credentialsAmount < minAmount - ? allAmount - : credentialsAmount; - - if (output.sendAll || amount == allAmount) { - fee = allAmountFee; - } else if (transactionCredentials.feeRate != null) { - fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount); - } else { - fee = calculateEstimatedFee(transactionCredentials.priority, amount); - } - } - - if (fee == 0) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - final totalAmount = amount + fee; - - if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - final txb = bitcoin.TransactionBuilder(network: networkType); - final changeAddress = await walletAddresses.getChangeAddress(); - var leftAmount = totalAmount; - var totalInputAmount = 0; - - inputs.clear(); - - for (final utx in unspentCoins) { - if (utx.isSending) { - leftAmount = leftAmount - utx.value; - totalInputAmount += utx.value; - inputs.add(utx); - - if (leftAmount <= 0) { - break; + outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount))); + } else { + if (!sendAll) { + final outputAmount = out.formattedCryptoAmount!; + credentialsAmount += outputAmount; + outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount))); + } else { + // The value will be changed after estimating the Tx size and deducting the fee from the total + outputs.add(BitcoinOutput(address: address, value: BigInt.from(0))); + } } } - } - if (inputs.isEmpty) { - throw BitcoinTransactionNoInputsException(); - } + final utxos = []; + final List privateKeys = []; - if (amount <= 0 || totalInputAmount < totalAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } + var leftAmount = credentialsAmount; + var overheadSizeVB = 0.0; + var allInputsAmount = 0; - txb.setVersion(1); - inputs.forEach((input) { - if (input.isP2wpkh) { - final p2wpkh = bitcoin - .P2WPKH( - data: generatePaymentData( - hd: input.bitcoinAddressRecord.isHidden + for (final utx in unspentCoins) { + if (utx.isSending) { + allInputsAmount += utx.value; + leftAmount = leftAmount - utx.value; + + BitcoinAddress address; + BitcoinAddressType scriptType; + if (P2pkhAddress.REGEX.hasMatch(utx.address)) { + address = P2pkhAddress.fromAddress(address: utx.address, network: network); + minAmount += P2pkhAddress.inputSizeVB; + scriptType = BitcoinAddressType.p2pkh; + } else if (P2wshAddress.REGEX.hasMatch(utx.address)) { + address = P2wshAddress.fromAddress(address: utx.address, network: network); + minAmount += P2wshAddress.inputSizeVB; + scriptType = BitcoinAddressType.p2wsh; + } else if (P2trAddress.REGEX.hasMatch(utx.address)) { + address = P2trAddress.fromAddress(address: utx.address, network: network); + minAmount += P2trAddress.inputSizeVB; + scriptType = BitcoinAddressType.p2tr; + } else { + address = P2wpkhAddress.fromAddress(address: utx.address, network: network); + minAmount += P2wpkhAddress.inputSizeVB; + scriptType = BitcoinAddressType.p2wpkh; + } + + privateKeys.add(generateECPrivate( + hd: utx.bitcoinAddressRecord.isHidden + ? walletAddresses.sideHd + : walletAddresses.mainHd, + index: utx.bitcoinAddressRecord.index, + network: network)); + + if (utx.bitcoinAddressRecord.type == BitcoinAddressType.p2pkh) { + overheadSizeVB = P2pkhAddress.overheadSizeVB; + } else { + overheadSizeVB = P2wpkhAddress.overheadSizeVB; + } + + utxos.add( + UtxoWithAddress( + utxo: BitcoinUtxo( + txHash: utx.hash, + value: BigInt.from(utx.value), + vout: utx.vout, + scriptType: scriptType, + ), + ownerDetails: UtxoAddressDetails( + publicKey: (utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd - : walletAddresses.mainHd, - index: input.bitcoinAddressRecord.index), - network: networkType) - .data; + : walletAddresses.mainHd) + .derive(utx.bitcoinAddressRecord.index) + .pubKey!, + address: address, + ), + ), + ); - txb.addInput(input.hash, input.vout, null, p2wpkh.output); - } else { - txb.addInput(input.hash, input.vout); + if (!sendAll && leftAmount <= 0) { + break; + } + } } - }); - outputs.forEach((item) { - final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount; - final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; - txb.addOutput( - address_to_output_script.addressToOutputScript(outputAddress, network), outputAmount!); - }); + if (utxos.isEmpty) { + throw BitcoinTransactionNoInputsException(); + } - final estimatedSize = estimatedTransactionSize(inputs.length, outputs.length + 1); - var feeAmount = 0; + minAmount += overheadSizeVB; - if (transactionCredentials.feeRate != null) { - feeAmount = transactionCredentials.feeRate! * estimatedSize; - } else { - feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize; - } + if (!sendAll) { + final changeValue = allInputsAmount - credentialsAmount; - final changeValue = totalInputAmount - amount - feeAmount; + if (changeValue > 0) { + final changeAddress = await walletAddresses.getChangeAddress(); + BitcoinAddress address; + if (P2pkhAddress.REGEX.hasMatch(changeAddress)) { + address = P2pkhAddress.fromAddress(address: changeAddress, network: network); + } else if (P2wshAddress.REGEX.hasMatch(changeAddress)) { + address = P2wshAddress.fromAddress(address: changeAddress, network: network); + } else if (P2trAddress.REGEX.hasMatch(changeAddress)) { + address = P2trAddress.fromAddress(address: changeAddress, network: network); + } else { + address = P2wpkhAddress.fromAddress(address: changeAddress, network: network); + } - if (changeValue > minAmount) { - txb.addOutput(changeAddress, changeValue); - } + outputAddresses.add(address); + outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue))); + } + } - for (var i = 0; i < inputs.length; i++) { - final input = inputs[i]; - final keyPair = generateKeyPair( - hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, - index: input.bitcoinAddressRecord.index, - network: network); - final witnessValue = input.isP2wpkh ? input.value : null; + final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( + utxos: utxos, outputs: outputAddresses, network: network); - txb.sign(vin: i, keyPair: keyPair, witnessValue: witnessValue); - } + final fee = transactionCredentials.feeRate != null + ? feeAmountWithFeeRate(transactionCredentials.feeRate!, 0, 0, size: estimatedSize) + : feeAmountForPriority(transactionCredentials.priority!, 0, 0, size: estimatedSize); - return PendingBitcoinTransaction(txb.build(), type, - electrumClient: electrumClient, amount: amount, fee: fee) - ..addListener((transaction) async { - transactionHistory.addOne(transaction); - await updateBalance(); + if (fee == 0) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + var amount = credentialsAmount; + + final lastOutput = outputs.last; + if (!sendAll) { + // Here, lastOutput is change, deduct the fee from it + outputs[outputs.length - 1] = + BitcoinOutput(address: lastOutput.address, value: lastOutput.value - BigInt.from(fee)); + } else { + // Here, if sendAll, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount for change + amount = allInputsAmount - fee; + outputs[outputs.length - 1] = + BitcoinOutput(address: lastOutput.address, value: BigInt.from(amount)); + } + + outputs.forEach((element) => print(["ELEMENT", element.value])); + + final totalAmount = amount + fee; + + if (totalAmount > balance[currency]!.confirmed || + totalAmount > allInputsAmount || + amount < minAmount) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + final txb = BitcoinTransactionBuilder( + utxos: utxos, outputs: outputs, fee: BigInt.from(fee), network: network); + + final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { + final key = + privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); + + if (key == null) { + throw Exception("Cannot find private key"); + } + + if (utxo.utxo.isP2tr()) { + return key.signTapRoot(txDigest); + } else { + return key.signInput(txDigest, sigHash: sighash); + } }); + + return PendingBitcoinTransaction(transaction, type, + electrumClient: electrumClient, amount: amount, fee: fee, network: network) + ..addListener((transaction) async { + transactionHistory.addOne(transaction); + await updateBalance(); + }); + } catch (e, s) { + print(["ERROR", e, s]); + throw e; + } } String toJSON() => json.encode({ @@ -381,24 +430,29 @@ abstract class ElectrumWalletBase } } - int feeAmountForPriority( - BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => - feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount); + int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount, + {int? size}) => + feeRate(priority) * (size ?? estimatedTransactionSize(inputsCount, outputsCount)); - int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => - feeRate * estimatedTransactionSize(inputsCount, outputsCount); + int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) => + feeRate * (size ?? estimatedTransactionSize(inputsCount, outputsCount)); @override - int calculateEstimatedFee(TransactionPriority? priority, int? amount, {int? outputsCount}) { + int calculateEstimatedFee(TransactionPriority? priority, int? amount, + {int? outputsCount, int? size}) { if (priority is BitcoinTransactionPriority) { return calculateEstimatedFeeWithFeeRate(feeRate(priority), amount, - outputsCount: outputsCount); + outputsCount: outputsCount, size: size); } return 0; } - int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount}) { + int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount, int? size}) { + if (size != null) { + return feeAmountWithFeeRate(feeRate, 0, 0, size: size); + } + int inputsCount = 0; if (amount != null) { @@ -466,9 +520,6 @@ abstract class ElectrumWalletBase await transactionHistory.changePassword(password); } - bitcoin.ECPair keyPairFor({required int index}) => - generateKeyPair(hd: hd, index: index, network: network); - @override Future rescan({required int height}) async => throw UnimplementedError(); @@ -504,8 +555,10 @@ abstract class ElectrumWalletBase if (unspentCoins.isNotEmpty) { unspentCoins.forEach((coin) { - final coinInfoList = unspentCoinsInfo.values - .where((element) => element.walletId.contains(id) && element.hash.contains(coin.hash)); + final coinInfoList = unspentCoinsInfo.values.where((element) => + element.walletId.contains(id) && + element.hash.contains(coin.hash) && + element.vout == coin.vout); if (coinInfoList.isNotEmpty) { final coinInfo = coinInfoList.first; @@ -566,15 +619,15 @@ abstract class ElectrumWalletBase {required String hash, required int height}) async { final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); final transactionHex = verboseTransaction['hex'] as String; - final original = bitcoin.Transaction.fromHex(transactionHex); - final ins = []; + final original = bitcoin_base.BtcTransaction.fromRaw(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()); + for (final vin in original.inputs) { + final id = HEX.encode(HEX.decode(vin.txId).reversed.toList()); final txHex = await electrumClient.getTransactionHex(hash: id); - final tx = bitcoin.Transaction.fromHex(txHex); + final tx = bitcoin_base.BtcTransaction.fromRaw(txHex); ins.add(tx); } @@ -685,6 +738,7 @@ abstract class ElectrumWalletBase unspentCoinsInfo.values.forEach((info) { unspentCoins.forEach((element) { if (element.hash == info.hash && + element.vout == info.vout && info.isFrozen && element.bitcoinAddressRecord.address == info.address && element.value == info.value) { diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index e2dc10bfb..fa413febd 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -1,5 +1,5 @@ import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; @@ -9,22 +9,21 @@ import 'package:cw_core/wallet_type.dart'; class PendingBitcoinTransaction with PendingTransaction { PendingBitcoinTransaction(this._tx, this.type, - {required this.electrumClient, - required this.amount, - required this.fee}) + {required this.electrumClient, required this.amount, required this.fee, this.network}) : _listeners = []; final WalletType type; - final bitcoin.Transaction _tx; + final BtcTransaction _tx; final ElectrumClient electrumClient; final int amount; final int fee; + final BasedUtxoNetwork? network; @override - String get id => _tx.getId(); + String get id => _tx.txId(); @override - String get hex => _tx.toHex(); + String get hex => _tx.serialize(); @override String get amountFormatted => bitcoinAmountToString(amount: amount); @@ -36,18 +35,16 @@ class PendingBitcoinTransaction with PendingTransaction { @override Future commit() async { - final result = - await electrumClient.broadcastTransaction(transactionRaw: _tx.toHex()); + final result = await electrumClient.broadcastTransaction(transactionRaw: hex, network: network); if (result.isEmpty) { throw BitcoinCommitTransactionException(); } - _listeners?.forEach((listener) => listener(transactionInfo())); + _listeners.forEach((listener) => listener(transactionInfo())); } - void addListener( - void Function(ElectrumTransactionInfo transaction) listener) => + void addListener(void Function(ElectrumTransactionInfo transaction) listener) => _listeners.add(listener); ElectrumTransactionInfo transactionInfo() => ElectrumTransactionInfo(type, diff --git a/cw_bitcoin/lib/utils.dart b/cw_bitcoin/lib/utils.dart index a63a43104..ba75d5081 100644 --- a/cw_bitcoin/lib/utils.dart +++ b/cw_bitcoin/lib/utils.dart @@ -1,6 +1,5 @@ import 'dart:typed_data'; import 'package:bitcoin_base/bitcoin_base.dart'; -import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:flutter/foundation.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; @@ -9,14 +8,9 @@ import 'package:hex/hex.dart'; bitcoin.PaymentData generatePaymentData({required bitcoin.HDWallet hd, required int index}) => PaymentData(pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))); -bitcoin.ECPair generateKeyPair( +ECPrivate generateECPrivate( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - bitcoin.ECPair.fromWIF(hd.derive(index).wif!, - network: network == BitcoinNetwork.mainnet - ? bitcoin.bitcoin - : network == LitecoinNetwork.mainnet - ? litecoinNetwork - : bitcoin.bitcoin); + ECPrivate.fromWif(hd.derive(index).wif!, netVersion: network.wifNetVer); String generateP2WPKHAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 3af7b8505..e64e2c4ac 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: ae3030bc30039e8e58241a6e9e5e007079d5aea6 + resolved-ref: e24e98986ec260ecd90e9a64811d65511e0961f1 url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "3.0.1" @@ -570,10 +570,10 @@ packages: dependency: transitive description: name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.dev" source: hosted - version: "3.7.3" + version: "3.7.4" pool: dependency: transitive description: diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index d88586fff..7cdbf71cd 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -277,14 +277,14 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { bitbox.ECPair.fromWIF(hd.derive(index).wif!); @override - int feeAmountForPriority( - BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => + int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount, + {int? size}) => feeRate(priority) * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount); - int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => + int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) => feeRate * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount); - int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount}) { + int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount, int? size}) { int inputsCount = 0; int totalValue = 0; diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index d5f2056a1..678e57b54 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -479,10 +479,10 @@ packages: dependency: transitive description: name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.dev" source: hosted - version: "3.7.3" + version: "3.7.4" pool: dependency: transitive description: diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index b4c0242f1..4a1e054d6 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -84,8 +84,7 @@ abstract class WalletCreationVMBase with Store { getIt.get().registerSyncTask(); _appStore.authenticationStore.allowed(); state = ExecutedSuccessfullyState(); - } catch (e, s) { - print([e, s]); + } catch (e) { state = FailureState(e.toString()); } } From 41d89997974a47c1d905bbb2c12e8b3b0ede9aeb Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 19 Jan 2024 11:47:03 -0300 Subject: [PATCH 17/59] fix: discover addresses, testnet restoring, duplicate unspent coins, and taproot address vs schnorr sig tweak --- cw_bitcoin/lib/bitcoin_unspent.dart | 7 ++- cw_bitcoin/lib/bitcoin_wallet_service.dart | 43 ++++++++++--------- cw_bitcoin/lib/electrum_wallet.dart | 7 ++- cw_bitcoin/lib/electrum_wallet_addresses.dart | 23 +++++----- .../lib/pending_bitcoin_transaction.dart | 1 + cw_bitcoin/pubspec.lock | 2 +- 6 files changed, 42 insertions(+), 41 deletions(-) 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_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 5d7d71ebb..af8df2b77 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -13,10 +13,8 @@ import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; -class BitcoinWalletService extends WalletService< - BitcoinNewWalletCredentials, - BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { +class BitcoinWalletService extends WalletService { BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -45,10 +43,12 @@ 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, walletInfo: walletInfo, + password: password, + name: name, + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; @@ -56,17 +56,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, @@ -83,22 +82,24 @@ class BitcoinWalletService extends WalletService< } @override - Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async => + Future restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials, + {bool? isTestnet}) async => throw UnimplementedError(); @override - Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { + Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } final wallet = await BitcoinWalletBase.create( - password: credentials.password!, - mnemonic: credentials.mnemonic, - walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + password: credentials.password!, + mnemonic: credentials.mnemonic, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource, + network: (isTestnet ?? false) ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet, + ); await wallet.save(); await wallet.init(); return wallet; diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 44ab8c272..77dd4ae83 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -390,7 +390,7 @@ abstract class ElectrumWalletBase } if (utxo.utxo.isP2tr()) { - return key.signTapRoot(txDigest); + return key.signTapRoot(txDigest, sighash: sighash, tweak: false); } else { return key.signInput(txDigest, sigHash: sighash); } @@ -599,7 +599,8 @@ abstract class ElectrumWalletBase if (currentWalletUnspentCoins.isNotEmpty) { currentWalletUnspentCoins.forEach((element) { - final existUnspentCoins = unspentCoins.where((coin) => element.hash.contains(coin.hash)); + final existUnspentCoins = unspentCoins + .where((coin) => element.hash.contains(coin.hash) && element.vout == coin.vout); if (existUnspentCoins.isEmpty) { keys.add(element.key); @@ -797,3 +798,5 @@ abstract class ElectrumWalletBase return base64Encode(HD.signMessage(message)); } } +// TODO: contact addresses +// TODO: select change address diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 08549e70c..4ceaec39b 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -76,14 +76,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } final receiveAddress = receiveAddresses.firstWhere((address) { - return addressPageType == BitcoinAddressType.p2wpkh - ? address.type == null || address.type == addressPageType - : address.type == addressPageType; - }).address; + return addressPageType == BitcoinAddressType.p2wpkh + ? address.type == null || address.type == addressPageType + : address.type == addressPageType; + }).address; - return walletInfo.type == WalletType.bitcoinCash - ? toCashAddr(receiveAddress) - : receiveAddress; + return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; } @override @@ -214,8 +212,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } @action - Future _discoverAddresses(bitcoin.HDWallet hd, bool isHidden, - {BitcoinAddressType? addressType}) async { + Future _discoverAddresses(bitcoin.HDWallet hd, bool isHidden) async { var hasAddrUse = true; List addrs; @@ -227,7 +224,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { startIndex: 0, hd: hd, isHidden: isHidden, - addressType: addressType); + addressType: addressPageType); } while (hasAddrUse) { @@ -241,7 +238,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, addressType: addressType); + startIndex: start, hd: hd, isHidden: isHidden, addressType: addressPageType); addrs.addAll(batch); } @@ -302,7 +299,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { void addAddresses(Iterable addresses) { final addressesSet = this.addresses.toSet(); addressesSet.addAll(addresses); - this.addresses.removeRange(0, this.addresses.length); + this.addresses.clear(); this.addresses.addAll(addressesSet); } @@ -316,7 +313,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { Future setAddressType(BitcoinAddressType type) async { _addressPageType = type; - await _discoverAddresses(mainHd, false, addressType: addressPageType); + await _discoverAddresses(mainHd, false); updateReceiveAddresses(); await saveAddressesInBox(); } diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index fa413febd..7d4ec978e 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -35,6 +35,7 @@ class PendingBitcoinTransaction with PendingTransaction { @override Future commit() async { + print(["HEX", hex]); final result = await electrumClient.broadcastTransaction(transactionRaw: hex, network: network); if (result.isEmpty) { diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index e64e2c4ac..5b029cf8c 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: e24e98986ec260ecd90e9a64811d65511e0961f1 + resolved-ref: "59d6167a28d2eb2065ec5e90c23825fdfcfff505" url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "3.0.1" From 8912e81f2ff4ea612f5f4b7dc3086c6a7f659c32 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 19 Jan 2024 11:52:18 -0300 Subject: [PATCH 18/59] fix: remove print --- cw_bitcoin/lib/pending_bitcoin_transaction.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index 7d4ec978e..fa413febd 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -35,7 +35,6 @@ class PendingBitcoinTransaction with PendingTransaction { @override Future commit() async { - print(["HEX", hex]); final result = await electrumClient.broadcastTransaction(transactionRaw: hex, network: network); if (result.isEmpty) { From ac0444a145d596d7f446c7c5a63708de1d7fc59d Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Tue, 23 Jan 2024 12:41:11 -0300 Subject: [PATCH 19/59] feat: improve error when failed broadcast response --- cw_bitcoin/lib/electrum.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 4748c2818..814adf6ac 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -250,12 +250,11 @@ class ElectrumClient { headers: {'Content-Type': 'application/json; charset=utf-8'}, body: transactionRaw) .then((http.Response response) { - print(response.body); if (response.statusCode == 200) { return response.body; } - return ''; + throw Exception('Failed to broadcast transaction: ${response.body}'); }); } From 9e212f12fedbd3de40799c96fdba4cc6c3372a3a Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Wed, 24 Jan 2024 11:57:21 -0300 Subject: [PATCH 20/59] feat: create fish shell env script --- scripts/android/app_env.fish | 75 ++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 scripts/android/app_env.fish diff --git a/scripts/android/app_env.fish b/scripts/android/app_env.fish new file mode 100644 index 000000000..be82ab9e6 --- /dev/null +++ b/scripts/android/app_env.fish @@ -0,0 +1,75 @@ +#!/usr/bin/env fish + +set APP_ANDROID_NAME "" +set APP_ANDROID_VERSION "" +set APP_ANDROID_BUILD_VERSION "" +set APP_ANDROID_ID "" +set APP_ANDROID_PACKAGE "" +set APP_ANDROID_SCHEME "" + +set MONERO_COM "monero.com" +set CAKEWALLET "cakewallet" +set HAVEN "haven" + +set -l TYPES $MONERO_COM $CAKEWALLET $HAVEN +set APP_ANDROID_TYPE $argv[1] + +set MONERO_COM_NAME "Monero.com" +set MONERO_COM_VERSION "1.10.0" +set MONERO_COM_BUILD_NUMBER 72 +set MONERO_COM_BUNDLE_ID "com.monero.app" +set MONERO_COM_PACKAGE "com.monero.app" +set MONERO_COM_SCHEME "monero.com" + +set CAKEWALLET_NAME "Cake Wallet" +set CAKEWALLET_VERSION "4.13.0" +set CAKEWALLET_BUILD_NUMBER 189 +set CAKEWALLET_BUNDLE_ID "com.cakewallet.cake_wallet" +set CAKEWALLET_PACKAGE "com.cakewallet.cake_wallet" +set CAKEWALLET_SCHEME "cakewallet" + +set HAVEN_NAME "Haven" +set HAVEN_VERSION "1.0.0" +set HAVEN_BUILD_NUMBER 1 +set HAVEN_BUNDLE_ID "com.cakewallet.haven" +set HAVEN_PACKAGE "com.cakewallet.haven" + +if not contains $APP_ANDROID_TYPE $TYPES + echo "Wrong app type." + return 1 + exit 1 +end + +switch $APP_ANDROID_TYPE + case $MONERO_COM + set APP_ANDROID_NAME $MONERO_COM_NAME + set APP_ANDROID_VERSION $MONERO_COM_VERSION + set APP_ANDROID_BUILD_NUMBER $MONERO_COM_BUILD_NUMBER + set APP_ANDROID_BUNDLE_ID $MONERO_COM_BUNDLE_ID + set APP_ANDROID_PACKAGE $MONERO_COM_PACKAGE + set APP_ANDROID_SCHEME $MONERO_COM_SCHEME + ;; + case $CAKEWALLET + set APP_ANDROID_NAME $CAKEWALLET_NAME + set APP_ANDROID_VERSION $CAKEWALLET_VERSION + set APP_ANDROID_BUILD_NUMBER $CAKEWALLET_BUILD_NUMBER + set APP_ANDROID_BUNDLE_ID $CAKEWALLET_BUNDLE_ID + set APP_ANDROID_PACKAGE $CAKEWALLET_PACKAGE + set APP_ANDROID_SCHEME $CAKEWALLET_SCHEME + ;; + case $HAVEN + set APP_ANDROID_NAME $HAVEN_NAME + set APP_ANDROID_VERSION $HAVEN_VERSION + set APP_ANDROID_BUILD_NUMBER $HAVEN_BUILD_NUMBER + set APP_ANDROID_BUNDLE_ID $HAVEN_BUNDLE_ID + set APP_ANDROID_PACKAGE $HAVEN_PACKAGE + ;; +end + +export APP_ANDROID_TYPE +export APP_ANDROID_NAME +export APP_ANDROID_VERSION +export APP_ANDROID_BUILD_NUMBER +export APP_ANDROID_BUNDLE_ID +export APP_ANDROID_PACKAGE +export APP_ANDROID_SCHEME From 55b0fe486624c1dc537f413a9d6a4735f3e566d6 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Wed, 24 Jan 2024 13:56:30 -0300 Subject: [PATCH 21/59] fix: unmodifiable maps --- cw_bitcoin/lib/bitcoin_wallet.dart | 8 +- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 4 +- cw_bitcoin/lib/electrum_wallet_addresses.dart | 111 +++++++++--------- cw_bitcoin/lib/litecoin_wallet.dart | 8 +- cw_bitcoin/lib/litecoin_wallet_addresses.dart | 4 +- .../lib/src/bitcoin_cash_wallet.dart | 8 +- .../src/bitcoin_cash_wallet_addresses.dart | 4 +- 7 files changed, 74 insertions(+), 73 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index f6d1df3f3..38c774104 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -28,8 +28,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { BasedUtxoNetwork? networkParam, List? initialAddresses, ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, }) : super( mnemonic: mnemonic, password: password, @@ -68,8 +68,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { BasedUtxoNetwork? network, List? initialAddresses, ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, }) async { return BitcoinWallet( mnemonic: mnemonic, diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index cbc086839..976d91cf2 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -17,8 +17,8 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S required super.network, required super.electrumClient, super.initialAddresses, - super.initialRegularAddressIndex = const {}, - super.initialChangeAddressIndex = const {}, + super.initialRegularAddressIndex, + super.initialChangeAddressIndex, }) : super(walletInfo); @override diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 4f364ea06..7bd829add 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -21,17 +21,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { required this.electrumClient, required this.network, List? initialAddresses, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}, - }) : addresses = ObservableList.of((initialAddresses ?? []).toSet()), + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, + }) : _addresses = ObservableList.of((initialAddresses ?? []).toSet()), receiveAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed) .toSet()), changeAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed) .toSet()), - currentReceiveAddressIndexByType = initialRegularAddressIndex, - currentChangeAddressIndexByType = initialChangeAddressIndex, + currentReceiveAddressIndexByType = initialRegularAddressIndex ?? {}, + currentChangeAddressIndexByType = initialChangeAddressIndex ?? {}, _addressPageType = walletInfo.addressPageType != null ? BitcoinAddressType.fromValue(walletInfo.addressPageType!) : BitcoinAddressType.p2wpkh, @@ -45,7 +45,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { static String toLegacy(String address) => bitbox.Address.toLegacyAddress(address); - final ObservableList addresses; + @observable + final List _addresses; final ObservableList receiveAddresses; final ObservableList changeAddresses; final ElectrumClient electrumClient; @@ -63,6 +64,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @override String get addressPageTypeStr => addressPageType.toString(); + @computed + List get addresses => _addresses.where(_isAddressTypeMatch).toList(); + + @action + void set addresses(List addresses) { + _addresses.clear(); + _addresses.addAll(addresses); + } + @override @computed String get address { @@ -74,12 +84,13 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { typeMatchingReceiveAddresses.isEmpty) { receiveAddress = generateNewAddress().address; } else { - final typeMatchingAddresses = addresses.where(_isAddressTypeMatch); - receiveAddress = - (typeMatchingReceiveAddresses.first.address != typeMatchingAddresses.first.address && - previousAddressRecord != null) - ? previousAddressRecord!.address - : typeMatchingReceiveAddresses.first.address; + if (previousAddressRecord != null && previousAddressRecord!.type == addressPageType) { + receiveAddress = (typeMatchingReceiveAddresses.first.address != addresses.first.address) + ? previousAddressRecord!.address + : typeMatchingReceiveAddresses.first.address; + } else { + receiveAddress = typeMatchingReceiveAddresses.first.address; + } } return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; @@ -93,7 +104,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (addr.startsWith('bitcoincash:')) { addr = toLegacy(addr); } - final addressRecord = addresses.firstWhere((addressRecord) => addressRecord.address == addr); + final addressRecord = _addresses.firstWhere((addressRecord) => addressRecord.address == addr); previousAddressRecord = addressRecord; receiveAddresses.remove(addressRecord); @@ -101,9 +112,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } @override - String get primaryAddress => getAddress(index: 0, hd: mainHd); + String get primaryAddress => getAddress(index: 0, hd: mainHd, addressType: addressPageType); - Map currentReceiveAddressIndexByType = {}; + Map currentReceiveAddressIndexByType; int get currentReceiveAddressIndex => currentReceiveAddressIndexByType[_addressPageType.toString()] ?? 0; @@ -111,7 +122,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { void set currentReceiveAddressIndex(int index) => currentReceiveAddressIndexByType[_addressPageType.toString()] = index; - Map currentChangeAddressIndexByType = {}; + Map currentChangeAddressIndexByType; int get currentChangeAddressIndex => currentChangeAddressIndexByType[_addressPageType.toString()] ?? 0; @@ -185,9 +196,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { BitcoinAddressRecord generateNewAddress({bitcoin.HDWallet? hd, String label = ''}) { final isHidden = hd == sideHd; - final newAddressIndex = addresses - .where((addressRecord) => addressRecord == addressPageType) - .fold(0, (int acc, addressRecord) => isHidden == addressRecord.isHidden ? acc + 1 : acc); + final newAddressIndex = addresses.fold( + 0, (int acc, addressRecord) => isHidden == addressRecord.isHidden ? acc + 1 : acc); final address = BitcoinAddressRecord( getAddress(index: newAddressIndex, hd: hd ?? sideHd, addressType: addressPageType), @@ -195,7 +205,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { isHidden: isHidden, name: label, ); - addresses.add(address); + _addresses.add(address); return address; } @@ -219,11 +229,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (address.startsWith('bitcoincash:')) { address = toLegacy(address); } - final addressRecord = addresses.firstWhere((addressRecord) => addressRecord.address == address); + final addressRecord = + _addresses.firstWhere((addressRecord) => addressRecord.address == address); addressRecord.setNewName(label); - final index = addresses.indexOf(addressRecord); - addresses.remove(addressRecord); - addresses.insert(index, addressRecord); + final index = _addresses.indexOf(addressRecord); + _addresses.remove(addressRecord); + _addresses.insert(index, addressRecord); } @action @@ -247,15 +258,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { var hasAddrUse = true; List addrs; - if (addresses.isNotEmpty) { + if (addresses.where((addr) => addr.isHidden == isHidden).isNotEmpty) { addrs = addresses.where((addr) => addr.isHidden == isHidden).toList(); } else { addrs = await _createNewAddresses( - isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, - startIndex: 0, - hd: hd, - isHidden: isHidden, - addressType: addressPageType); + isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, + startIndex: 0, + hd: hd, + isHidden: isHidden, + ); } while (hasAddrUse) { @@ -268,8 +279,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, addressType: addressPageType); + final batch = await _createNewAddresses(count, startIndex: start, hd: hd, isHidden: isHidden); addrs.addAll(batch); } @@ -291,39 +301,30 @@ 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, - addressType: addressPageType, - ); + 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, - addressType: addressPageType, - ); + final newAddresses = await _createNewAddresses(addressesCount, + startIndex: countOfHiddenAddresses, hd: sideHd, isHidden: true); addresses.addAll(newAddresses); } } - Future> _createNewAddresses(int count, - {required bitcoin.HDWallet hd, - int startIndex = 0, - bool isHidden = false, - BitcoinAddressType? addressType}) async { + Future> _createNewAddresses( + int count, { + required bitcoin.HDWallet hd, + int startIndex = 0, + bool isHidden = false, + }) async { final list = []; for (var i = startIndex; i < count + startIndex; i++) { final address = BitcoinAddressRecord( - getAddress(index: i, hd: hd), + getAddress(index: i, hd: hd, addressType: addressPageType), index: i, isHidden: isHidden, type: addressPageType, @@ -336,10 +337,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action void addAddresses(Iterable addresses) { - final addressesSet = this.addresses.toSet(); + final addressesSet = this._addresses.toSet(); addressesSet.addAll(addresses); - this.addresses.clear(); - this.addresses.addAll(addressesSet); + this._addresses.clear(); + this._addresses.addAll(addressesSet); } Future _hasAddressUsed(String address) async { diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index a0563f09c..1ce9555ac 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -29,8 +29,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { String? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, }) : super( mnemonic: mnemonic, password: password, @@ -64,8 +64,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { String? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}}) async { + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex}) async { return LitecoinWallet( mnemonic: mnemonic, password: password, diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart index f7d49b64d..993d17933 100644 --- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart @@ -17,8 +17,8 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with required super.network, required super.electrumClient, super.initialAddresses, - super.initialRegularAddressIndex = const {}, - super.initialChangeAddressIndex = const {}, + super.initialRegularAddressIndex, + super.initialChangeAddressIndex, }) : super(walletInfo); @override diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 89fc89574..5cea061f5 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -37,8 +37,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { String? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, }) : super( mnemonic: mnemonic, password: password, @@ -72,8 +72,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { String? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, - Map initialRegularAddressIndex = const {}, - Map initialChangeAddressIndex = const {}}) async { + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex}) async { return BitcoinCashWallet( mnemonic: mnemonic, password: password, diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart index b0741ed34..8291ce2a5 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -17,8 +17,8 @@ abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses wi required super.network, required super.electrumClient, super.initialAddresses, - super.initialRegularAddressIndex = const {}, - super.initialChangeAddressIndex = const {}, + super.initialRegularAddressIndex, + super.initialChangeAddressIndex, }) : super(walletInfo); @override From a1867d74f6e20ff6c54d6064c466a1c759555bda Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Wed, 24 Jan 2024 14:51:25 -0300 Subject: [PATCH 22/59] fix: build --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 7bd829add..01c1a9cbf 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -47,6 +47,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @observable final List _addresses; + final ObservableList receiveAddresses; final ObservableList changeAddresses; final ElectrumClient electrumClient; @@ -67,7 +68,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @computed List get addresses => _addresses.where(_isAddressTypeMatch).toList(); - @action void set addresses(List addresses) { _addresses.clear(); _addresses.addAll(addresses); From d00728846882d891000cd609e62f9e4cb68514cc Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Wed, 24 Jan 2024 15:01:11 -0300 Subject: [PATCH 23/59] fix: build --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 01c1a9cbf..f42bb8613 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -46,7 +46,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { static String toLegacy(String address) => bitbox.Address.toLegacyAddress(address); @observable - final List _addresses; + List _addresses; final ObservableList receiveAddresses; final ObservableList changeAddresses; From 57f3964771c13a18e3915e2480baa49dc22004f2 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 25 Jan 2024 14:00:42 -0300 Subject: [PATCH 24/59] fix: computed observable side effect bug --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index f42bb8613..6d1fa4770 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -45,8 +45,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { static String toLegacy(String address) => bitbox.Address.toLegacyAddress(address); - @observable - List _addresses; + final ObservableList _addresses; final ObservableList receiveAddresses; final ObservableList changeAddresses; @@ -205,7 +204,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { isHidden: isHidden, name: label, ); - _addresses.add(address); + addresses.add(address); return address; } From fb3564649c48ab60b3fe225ee7b00cd82fad9a1e Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 25 Jan 2024 14:01:12 -0300 Subject: [PATCH 25/59] feat: add nix script for android build_all --- scripts/android/shell.nix | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 scripts/android/shell.nix diff --git a/scripts/android/shell.nix b/scripts/android/shell.nix new file mode 100644 index 000000000..b89da09c0 --- /dev/null +++ b/scripts/android/shell.nix @@ -0,0 +1,16 @@ +{ pkgs ? import {} }: + +pkgs.mkShell { + buildInputs = [ + pkgs.curl + pkgs.unzip + pkgs.automake + pkgs.file + pkgs.pkg-config + pkgs.git + pkgs.libtool + pkgs.ncurses5 + pkgs.openjdk8 + pkgs.clang + ]; +} From d06362e9271df938d31fa6694f7989ddb42162a9 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 25 Jan 2024 16:48:03 -0300 Subject: [PATCH 26/59] fix: wrong keypairs used for signing --- cw_bitcoin/lib/electrum_wallet.dart | 72 ++++++++++++------- cw_bitcoin/lib/electrum_wallet_addresses.dart | 3 + 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 2a9b021d9..f0d920249 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -117,7 +117,7 @@ abstract class ElectrumWalletBase List get scriptHashes => walletAddresses.addresses.map((addr) => scriptHash(addr.address, network: network)).toList(); - List get publicScriptHashes => walletAddresses.addresses + List get publicScriptHashes => walletAddresses.allAddresses .where((addr) => !addr.isHidden) .map((addr) => scriptHash(addr.address, network: network)) .toList(); @@ -265,30 +265,60 @@ abstract class ElectrumWalletBase BitcoinAddress address; BitcoinAddressType scriptType; + + ECPrivate privkey; + ECPrivate mainPrivkey = generateECPrivate( + hd: walletAddresses.mainHd, index: utx.bitcoinAddressRecord.index, network: network); + ECPrivate sidePrivkey = generateECPrivate( + hd: walletAddresses.sideHd, index: utx.bitcoinAddressRecord.index, network: network); + if (P2pkhAddress.REGEX.hasMatch(utx.address)) { address = P2pkhAddress.fromAddress(address: utx.address, network: network); minAmount += P2pkhAddress.inputSizeVB; scriptType = BitcoinAddressType.p2pkh; + if (P2pkhAddress.fromPubkey(pubkey: mainPrivkey.getPublic().toHex()) + .toAddress(network) == + utx.address) { + privkey = mainPrivkey; + } else { + privkey = sidePrivkey; + } } else if (P2wshAddress.REGEX.hasMatch(utx.address)) { address = P2wshAddress.fromAddress(address: utx.address, network: network); minAmount += P2wshAddress.inputSizeVB; scriptType = BitcoinAddressType.p2wsh; + if (P2wshAddress.fromPubkey(pubkey: mainPrivkey.getPublic().toHex()) + .toAddress(network) == + utx.address) { + privkey = mainPrivkey; + } else { + privkey = sidePrivkey; + } } else if (P2trAddress.REGEX.hasMatch(utx.address)) { address = P2trAddress.fromAddress(address: utx.address, network: network); minAmount += P2trAddress.inputSizeVB; scriptType = BitcoinAddressType.p2tr; + if (P2trAddress.fromPubkey(pubkey: mainPrivkey.getPublic().toHex()) + .toAddress(network) == + utx.address) { + privkey = mainPrivkey; + } else { + privkey = sidePrivkey; + } } else { address = P2wpkhAddress.fromAddress(address: utx.address, network: network); minAmount += P2wpkhAddress.inputSizeVB; scriptType = BitcoinAddressType.p2wpkh; + if (P2wpkhAddress.fromPubkey(pubkey: mainPrivkey.getPublic().toHex()) + .toAddress(network) == + utx.address) { + privkey = mainPrivkey; + } else { + privkey = sidePrivkey; + } } - privateKeys.add(generateECPrivate( - hd: utx.bitcoinAddressRecord.isHidden - ? walletAddresses.sideHd - : walletAddresses.mainHd, - index: utx.bitcoinAddressRecord.index, - network: network)); + privateKeys.add(privkey); if (utx.bitcoinAddressRecord.type == BitcoinAddressType.p2pkh) { overheadSizeVB = P2pkhAddress.overheadSizeVB; @@ -304,14 +334,8 @@ abstract class ElectrumWalletBase vout: utx.vout, scriptType: scriptType, ), - ownerDetails: UtxoAddressDetails( - publicKey: (utx.bitcoinAddressRecord.isHidden - ? walletAddresses.sideHd - : walletAddresses.mainHd) - .derive(utx.bitcoinAddressRecord.index) - .pubKey!, - address: address, - ), + ownerDetails: + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), ), ); @@ -373,8 +397,6 @@ abstract class ElectrumWalletBase BitcoinOutput(address: lastOutput.address, value: BigInt.from(amount)); } - outputs.forEach((element) => print(["ELEMENT", element.value])); - final totalAmount = amount + fee; if (totalAmount > balance[currency]!.confirmed || @@ -417,7 +439,7 @@ abstract class ElectrumWalletBase 'mnemonic': mnemonic, 'account_index': walletAddresses.currentReceiveAddressIndexByType, 'change_address_index': walletAddresses.currentChangeAddressIndexByType, - 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), + 'addresses': walletAddresses.allAddresses.map((addr) => addr.toJSON()).toList(), 'address_page_type': walletInfo.addressPageType.toString(), 'balance': balance[currency]?.toJSON(), 'network_type': network == BitcoinNetwork.mainnet ? 'mainnet' : 'testnet', @@ -538,7 +560,7 @@ 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.allAddresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, network) .then((unspent) => unspent.map((unspent) { try { @@ -644,7 +666,7 @@ abstract class ElectrumWalletBase {required String hash, required int height}) async { try { final tx = await getTransactionExpanded(hash: hash, height: height); - final addresses = walletAddresses.addresses.map((addr) => addr.address).toSet(); + final addresses = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); return ElectrumTransactionInfo.fromElectrumBundle(tx, walletInfo.type, network, addresses: addresses, height: height); } catch (_) { @@ -658,7 +680,7 @@ abstract class ElectrumWalletBase final normalizedHistories = >[]; final newTxCounts = {}; - walletAddresses.addresses.forEach((addressRecord) { + walletAddresses.allAddresses.forEach((addressRecord) { final sh = scriptHash(addressRecord.address, network: network); addressHashes[sh] = addressRecord; newTxCounts[sh] = 0; @@ -756,7 +778,7 @@ abstract class ElectrumWalletBase } Future _fetchBalances() async { - final addresses = walletAddresses.addresses.toList(); + final addresses = walletAddresses.allAddresses.toList(); final balanceFutures = >>[]; for (var i = 0; i < addresses.length; i++) { final addressRecord = addresses[i]; @@ -807,10 +829,10 @@ abstract class ElectrumWalletBase String getChangeAddress() { const minCountOfHiddenAddresses = 5; final random = Random(); - var addresses = walletAddresses.addresses.where((addr) => addr.isHidden).toList(); + var addresses = walletAddresses.allAddresses.where((addr) => addr.isHidden).toList(); if (addresses.length < minCountOfHiddenAddresses) { - addresses = walletAddresses.addresses.toList(); + addresses = walletAddresses.allAddresses.toList(); } return addresses[random.nextInt(addresses.length)].address; @@ -822,7 +844,7 @@ abstract class ElectrumWalletBase @override String signMessage(String message, {String? address = null}) { final index = address != null - ? walletAddresses.addresses.firstWhere((element) => element.address == address).index + ? walletAddresses.allAddresses.firstWhere((element) => element.address == address).index : null; final HD = index == null ? hd : hd.derive(index); return base64Encode(HD.signMessage(message)); diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 6d1fa4770..7e81b0cfc 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -67,6 +67,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @computed List get addresses => _addresses.where(_isAddressTypeMatch).toList(); + @computed + List get allAddresses => _addresses; + void set addresses(List addresses) { _addresses.clear(); _addresses.addAll(addresses); From 315b6717e2398c20a0c16c3cd389c40a2cb9a6e4 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 26 Jan 2024 12:32:01 -0300 Subject: [PATCH 27/59] fix: wrong addresses when using fromScriptPubKey scripts --- cw_bitcoin/lib/electrum.dart | 15 +++++++++++++++ cw_bitcoin/lib/electrum_wallet.dart | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 814adf6ac..dbe4b3e71 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -331,6 +331,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( diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index f0d920249..e11335edf 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -417,7 +417,7 @@ abstract class ElectrumWalletBase } if (utxo.utxo.isP2tr()) { - return key.signTapRoot(txDigest, sighash: sighash, tweak: false); + return key.signTapRoot(txDigest, sighash: sighash); } else { return key.signInput(txDigest, sigHash: sighash); } From caab5325ec3d9dea93e839153b9d2eaedf9ab283 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 26 Jan 2024 12:36:06 -0300 Subject: [PATCH 28/59] fix(actual commit): testnet tx expanded + wrong addresses when using fromScriptPubKey scripts (update bitcoin_base deps) --- cw_bitcoin/lib/electrum_wallet.dart | 40 +++++++++++++++++++++++------ cw_bitcoin/pubspec.lock | 6 ++--- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index e11335edf..f0faf1f96 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -39,6 +39,7 @@ import 'package:hex/hex.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; +import 'package:http/http.dart' as http; part 'electrum_wallet.g.dart'; @@ -645,18 +646,41 @@ 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; + String transactionHex; + int? time; + int confirmations = 0; + if (network == BitcoinNetwork.mainnet) { + final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); + + transactionHex = verboseTransaction as String; + time = verboseTransaction['time'] as int?; + confirmations = verboseTransaction['confirmations'] as int? ?? 0; + } else { + // Testnet public electrum server does not support verbose transaction fetching + transactionHex = await electrumClient.getTransactionHex(hash: hash); + + final status = json.decode( + (await http.get(Uri.parse("https://blockstream.info/testnet/api/tx/$hash/status"))).body); + + time = status["block_time"] as int?; + final tip = await electrumClient.getCurrentBlockChainTip() ?? 0; + confirmations = tip - (status["block_height"] as int? ?? 0); + } + final original = bitcoin_base.BtcTransaction.fromRaw(transactionHex); final ins = []; - final time = verboseTransaction['time'] as int?; - final confirmations = verboseTransaction['confirmations'] as int? ?? 0; for (final vin in original.inputs) { - final id = HEX.encode(HEX.decode(vin.txId).reversed.toList()); - final txHex = await electrumClient.getTransactionHex(hash: id); - final tx = bitcoin_base.BtcTransaction.fromRaw(txHex); - ins.add(tx); + try { + final id = HEX.encode(HEX.decode(vin.txId).reversed.toList()); + final txHex = await electrumClient.getTransactionHex(hash: id); + final tx = bitcoin_base.BtcTransaction.fromRaw(txHex); + ins.add(tx); + } catch (_) { + ins.add(bitcoin_base.BtcTransaction.fromRaw( + await electrumClient.getTransactionHex(hash: vin.txId), + )); + } } return ElectrumTransactionBundle(original, ins: ins, time: time, confirmations: confirmations); diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 5b029cf8c..0f4db9f99 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: "59d6167a28d2eb2065ec5e90c23825fdfcfff505" + resolved-ref: "72a098119a55e5ac708358797bc052abe35e80ef" url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "3.0.1" @@ -177,10 +177,10 @@ packages: dependency: transitive description: name: built_value - sha256: c9aabae0718ec394e5bc3c7272e6bb0dc0b32201a08fe185ec1d8401d3e39309 + sha256: a3ec2e0f967bc47f69f95009bb93db936288d61d5343b9436e378b28a2f830c6 url: "https://pub.dev" source: hosted - version: "8.8.1" + version: "8.9.0" characters: dependency: transitive description: From e7d11788accc55549ad0444f07e147a7cbc1dd2f Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 26 Jan 2024 12:44:38 -0300 Subject: [PATCH 29/59] fix: self-send [skip ci] --- cw_bitcoin/lib/electrum_transaction_info.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index 6cb64e6cb..83d3a8f39 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -114,7 +114,12 @@ class ElectrumTransactionInfo extends TransactionInfo { for (final out in bundle.originalTransaction.outputs) { totalOutAmount += out.amount.toInt(); final addressExists = addresses.contains(addressFromOutputScript(out.scriptPubKey, network)); - if ((direction == TransactionDirection.incoming && addressExists) || + + if (addressExists && direction == TransactionDirection.outgoing) { + // Self-send + direction = TransactionDirection.incoming; + amount += out.amount.toInt(); + } else if ((direction == TransactionDirection.incoming && addressExists) || (direction == TransactionDirection.outgoing && !addressExists)) { amount += out.amount.toInt(); } From bb0c05c517164ad8e3be6d1ea81dc8d260ed9aca Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 26 Jan 2024 16:04:18 -0300 Subject: [PATCH 30/59] fix: p2wsh --- cw_bitcoin/pubspec.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 0f4db9f99..040adf2b5 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: "72a098119a55e5ac708358797bc052abe35e80ef" + resolved-ref: "4b1a4bc9e406b9d0025e4f80dd039d4bc40996b7" url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "3.0.1" From c799e37689d70df0756fc6ee962759a531c546c2 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 26 Jan 2024 17:42:36 -0300 Subject: [PATCH 31/59] fix: testnet fees --- cw_bitcoin/lib/electrum.dart | 5 ++++- cw_bitcoin/lib/electrum_wallet.dart | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index dbe4b3e71..51a53e285 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -316,7 +316,10 @@ class ElectrumClient { return []; }); - Future> feeRates() async { + Future> feeRates({BasedUtxoNetwork? network}) async { + if (network == BitcoinNetwork.testnet) { + return [1, 1, 1]; + } try { final topDoubleString = await estimatefee(p: 1); final middleDoubleString = await estimatefee(p: 5); diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index f0faf1f96..98644f359 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -162,7 +162,7 @@ abstract class ElectrumWalletBase _subscribeForUpdates(); await updateUnspent(); await updateBalance(); - _feeRates = await electrumClient.feeRates(); + _feeRates = await electrumClient.feeRates(network: network); Timer.periodic( const Duration(minutes: 1), (timer) async => _feeRates = await electrumClient.feeRates()); From ce17209de45f5dd8cfcdb1181f9db144123ece1b Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 27 Jan 2024 05:12:11 +0200 Subject: [PATCH 32/59] New versions --- assets/text/Monerocom_Release_Notes.txt | 6 +++--- assets/text/Release_Notes.txt | 10 ++++------ scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- scripts/macos/app_env.sh | 8 ++++---- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 2715bdeee..2b783ee1e 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,3 +1,3 @@ -On-ramp flow fixes and enhancements -UI enhancements -Generic enhancements and bug fixes \ No newline at end of file +Security and Privacy enhancements +Usability enhancements +Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 90428c2ab..411ed609b 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,6 +1,4 @@ -Add new Off-ramp providers (DFX, OnRamper) -On-ramp flow fixes and enhancements -Ethereum and WalletConnect fixes and improvements -Nano enhancements -UI enhancements -Generic enhancements and bug fixes \ No newline at end of file +List previously used Bitcoin addresses +Security and Privacy enhancements +Usability enhancements +Bug fixes \ No newline at end of file diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 163f178f3..9301b4a89 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.0" -MONERO_COM_BUILD_NUMBER=72 +MONERO_COM_VERSION="1.10.1" +MONERO_COM_BUILD_NUMBER=73 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.0" -CAKEWALLET_BUILD_NUMBER=189 +CAKEWALLET_VERSION="4.13.1" +CAKEWALLET_BUILD_NUMBER=190 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 9920b1e54..4642fbc64 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.0" -MONERO_COM_BUILD_NUMBER=70 +MONERO_COM_VERSION="1.10.1" +MONERO_COM_BUILD_NUMBER=71 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.0" -CAKEWALLET_BUILD_NUMBER=208 +CAKEWALLET_VERSION="4.13.1" +CAKEWALLET_BUILD_NUMBER=209 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index fa040dfee..e80642af3 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.0.0" -MONERO_COM_BUILD_NUMBER=1 +MONERO_COM_VERSION="1.0.1" +MONERO_COM_BUILD_NUMBER=2 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.6.0" -CAKEWALLET_BUILD_NUMBER=50 +CAKEWALLET_VERSION="1.6.1" +CAKEWALLET_BUILD_NUMBER=51 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From 8557cf31fb91650f2a0afdb20485eb0df623ecf0 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Sat, 27 Jan 2024 17:55:06 +0200 Subject: [PATCH 33/59] Update macos build number Minor UI fix --- .../screens/receive/widgets/address_cell.dart | 16 +++++++++------- scripts/macos/app_env.sh | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/src/screens/receive/widgets/address_cell.dart b/lib/src/screens/receive/widgets/address_cell.dart index 92c870421..a07456284 100644 --- a/lib/src/screens/receive/widgets/address_cell.dart +++ b/lib/src/screens/receive/widgets/address_cell.dart @@ -113,13 +113,15 @@ class AddressCell extends StatelessWidget { color: textColor, ), ), - AutoSizeText( - formattedAddress, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: isChange ? 10 : 14, - color: textColor, + Flexible( + child: AutoSizeText( + formattedAddress, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: isChange ? 10 : 14, + color: textColor, + ), ), ), ], diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index e80642af3..4e9c7a09b 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -17,7 +17,7 @@ fi MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.0.1" -MONERO_COM_BUILD_NUMBER=2 +MONERO_COM_BUILD_NUMBER=3 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" From 2dcf4ca95bc4ebe7dcd37ea381afcfb93a1e3c63 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Mon, 29 Jan 2024 10:31:09 -0300 Subject: [PATCH 34/59] fix: use new bitcoin_base ref, fix tx list wrong hex value & refactor hidden vs hd use - if always use sideHd for isHidden, it is easier to simplify the functions instead of passing both which can be error prone - (ps: now this could probably be changed, for example from isHidden to isChange since with address list we now see "hidden" addresses) --- cw_bitcoin/lib/electrum_wallet.dart | 2 +- cw_bitcoin/lib/electrum_wallet_addresses.dart | 38 ++++++++----------- cw_bitcoin/pubspec.lock | 2 +- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 98644f359..e8c5d982c 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -652,7 +652,7 @@ abstract class ElectrumWalletBase if (network == BitcoinNetwork.mainnet) { final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); - transactionHex = verboseTransaction as String; + transactionHex = verboseTransaction['hex'] as String; time = verboseTransaction['time'] as int?; confirmations = verboseTransaction['confirmations'] as int? ?? 0; } else { diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 7e81b0cfc..7249fd773 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -152,8 +152,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { }); Future discoverAddresses() async { - await _discoverAddresses(mainHd, false); - await _discoverAddresses(sideHd, true); + await _discoverAddresses(false); + await _discoverAddresses(true); await updateAddressesInBox(); } @@ -179,7 +179,6 @@ 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); addAddresses(newAddresses); @@ -195,16 +194,14 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return address; } - BitcoinAddressRecord generateNewAddress({bitcoin.HDWallet? hd, String label = ''}) { - final isHidden = hd == sideHd; - + BitcoinAddressRecord generateNewAddress({String label = ''}) { final newAddressIndex = addresses.fold( - 0, (int acc, addressRecord) => isHidden == addressRecord.isHidden ? acc + 1 : acc); + 0, (int acc, addressRecord) => addressRecord.isHidden == false ? acc + 1 : acc); final address = BitcoinAddressRecord( - getAddress(index: newAddressIndex, hd: hd ?? sideHd, addressType: addressPageType), + getAddress(index: newAddressIndex, hd: mainHd, addressType: addressPageType), index: newAddressIndex, - isHidden: isHidden, + isHidden: false, name: label, ); addresses.add(address); @@ -256,7 +253,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } @action - Future _discoverAddresses(bitcoin.HDWallet hd, bool isHidden) async { + Future _discoverAddresses(bool isHidden) async { var hasAddrUse = true; List addrs; @@ -266,7 +263,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { addrs = await _createNewAddresses( isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, startIndex: 0, - hd: hd, isHidden: isHidden, ); } @@ -281,7 +277,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, isHidden: isHidden); addrs.addAll(batch); } @@ -304,29 +300,25 @@ 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); + startIndex: countOfReceiveAddresses, isHidden: false); addresses.addAll(newAddresses); } if (countOfHiddenAddresses < defaultChangeAddressesCount) { final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses; final newAddresses = await _createNewAddresses(addressesCount, - startIndex: countOfHiddenAddresses, hd: sideHd, isHidden: true); + startIndex: countOfHiddenAddresses, isHidden: true); addresses.addAll(newAddresses); } } - Future> _createNewAddresses( - int count, { - required bitcoin.HDWallet hd, - int startIndex = 0, - bool isHidden = false, - }) async { + Future> _createNewAddresses(int count, + {int startIndex = 0, bool isHidden = false}) async { final list = []; for (var i = startIndex; i < count + startIndex; i++) { final address = BitcoinAddressRecord( - getAddress(index: i, hd: hd, addressType: addressPageType), + getAddress(index: i, hd: _getHd(isHidden), addressType: addressPageType), index: i, isHidden: isHidden, type: addressPageType, @@ -355,7 +347,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { Future setAddressType(BitcoinAddressType type) async { _addressPageType = type; - await _discoverAddresses(mainHd, false); + await _discoverAddresses(false); updateReceiveAddresses(); await saveAddressesInBox(); } @@ -366,4 +358,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { ? addressRecord.type == null || addressRecord.type == addressPageType : addressRecord.type == addressPageType; } + + bitcoin.HDWallet _getHd(bool isHidden) => isHidden ? sideHd : mainHd; } diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 040adf2b5..279fbf815 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: "4b1a4bc9e406b9d0025e4f80dd039d4bc40996b7" + resolved-ref: fbd9f53f9eb29037e90df1c23c7fe02ece6230a2 url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "3.0.1" From e388e6fb4c9e7276143c25dd47655322ecfaa621 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 30 Jan 2024 01:36:43 +0200 Subject: [PATCH 35/59] Fix if condition to handle litecoin case --- cw_bitcoin/lib/electrum_wallet.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index e8c5d982c..c5e6f7680 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -443,7 +443,7 @@ abstract class ElectrumWalletBase 'addresses': walletAddresses.allAddresses.map((addr) => addr.toJSON()).toList(), 'address_page_type': walletInfo.addressPageType.toString(), 'balance': balance[currency]?.toJSON(), - 'network_type': network == BitcoinNetwork.mainnet ? 'mainnet' : 'testnet', + 'network_type': network == BitcoinNetwork.testnet ? 'testnet' : 'mainnet', }); int feeRate(TransactionPriority priority) { @@ -649,13 +649,7 @@ abstract class ElectrumWalletBase String transactionHex; int? time; int confirmations = 0; - if (network == BitcoinNetwork.mainnet) { - final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); - - transactionHex = verboseTransaction['hex'] as String; - time = verboseTransaction['time'] as int?; - confirmations = verboseTransaction['confirmations'] as int? ?? 0; - } else { + if (network == BitcoinNetwork.testnet) { // Testnet public electrum server does not support verbose transaction fetching transactionHex = await electrumClient.getTransactionHex(hash: hash); @@ -665,6 +659,12 @@ abstract class ElectrumWalletBase time = status["block_time"] as int?; final tip = await electrumClient.getCurrentBlockChainTip() ?? 0; confirmations = tip - (status["block_height"] as int? ?? 0); + } else { + final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); + + transactionHex = verboseTransaction['hex'] as String; + time = verboseTransaction['time'] as int?; + confirmations = verboseTransaction['confirmations'] as int? ?? 0; } final original = bitcoin_base.BtcTransaction.fromRaw(transactionHex); From fb3e44c486db23e61fedf929a4ac2bdd1e0ea5db Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Tue, 30 Jan 2024 12:23:24 -0300 Subject: [PATCH 36/59] fix: self-send, change address was always making direction incoming --- cw_bitcoin/lib/electrum_transaction_info.dart | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index 83d3a8f39..ebe3acf17 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -111,20 +111,27 @@ class ElectrumTransactionInfo extends TransactionInfo { } } + final receivedAmounts = []; for (final out in bundle.originalTransaction.outputs) { totalOutAmount += out.amount.toInt(); final addressExists = addresses.contains(addressFromOutputScript(out.scriptPubKey, network)); - if (addressExists && direction == TransactionDirection.outgoing) { - // Self-send - direction = TransactionDirection.incoming; - amount += out.amount.toInt(); - } else if ((direction == TransactionDirection.incoming && addressExists) || + if (addressExists) { + receivedAmounts.add(out.amount.toInt()); + } + + if ((direction == TransactionDirection.incoming && addressExists) || (direction == TransactionDirection.outgoing && !addressExists)) { amount += out.amount.toInt(); } } + if (receivedAmounts.length == bundle.originalTransaction.outputs.length) { + // Self-send + direction = TransactionDirection.incoming; + amount = receivedAmounts.reduce((a, b) => a + b); + } + final fee = inputAmount - totalOutAmount; return ElectrumTransactionInfo(type, id: bundle.originalTransaction.txId(), From 36d597ece8ae354f983ec4da00e2177a825b63e3 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Tue, 30 Jan 2024 12:28:32 -0300 Subject: [PATCH 37/59] refactor: improve estimation function, add more inputs if balance missing --- cw_bitcoin/lib/electrum_wallet.dart | 394 +++++++++++++++------------- cw_bitcoin/pubspec.lock | 2 +- 2 files changed, 213 insertions(+), 183 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index c5e6f7680..ac03a575c 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -193,6 +193,130 @@ abstract class ElectrumWalletBase } } + Future _estimateTxFeeAndInputsToUse( + int credentialsAmount, + double minAmount, + bool sendAll, + List outputAddresses, + List outputs, + BitcoinTransactionCredentials transactionCredentials, + {int? inputsCount}) async { + final utxos = []; + List privateKeys = []; + + var leftAmount = credentialsAmount; + var overheadSizeVB = 0.0; + var allInputsAmount = 0; + + for (int i = 0; i < unspentCoins.length; i++) { + final utx = unspentCoins[i]; + + if (utx.isSending) { + allInputsAmount += utx.value; + leftAmount = leftAmount - utx.value; + + final address = _addressTypeFromStr(utx.address, network); + minAmount += _getInputSizeVB(address); + final privkey = generateECPrivate( + hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, + index: utx.bitcoinAddressRecord.index, + network: network); + + privateKeys.add(privkey); + + if (utx.bitcoinAddressRecord.type is LegacyAddress) { + overheadSizeVB = LegacyAddress.overheadSizeVB; + } else { + overheadSizeVB = SegwitAddress.overheadSizeVB; + } + + utxos.add( + UtxoWithAddress( + utxo: BitcoinUtxo( + txHash: utx.hash, + value: BigInt.from(utx.value), + vout: utx.vout, + scriptType: _getScriptType(address), + ), + ownerDetails: + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), + ), + ); + + if (inputsCount != null ? i + 1 == inputsCount : !sendAll && leftAmount <= 0) { + break; + } + } + } + + if (utxos.isEmpty) { + throw BitcoinTransactionNoInputsException(); + } + + minAmount += overheadSizeVB; + + var changeValue = allInputsAmount - credentialsAmount; + + if (!sendAll) { + if (changeValue > 0) { + final changeAddress = await walletAddresses.getChangeAddress(); + final address = _addressTypeFromStr(changeAddress, network); + outputAddresses.add(address); + outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue))); + } + } + + final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( + utxos: utxos, outputs: outputAddresses, network: network); + + final fee = transactionCredentials.feeRate != null + ? feeAmountWithFeeRate(transactionCredentials.feeRate!, 0, 0, size: estimatedSize) + : feeAmountForPriority(transactionCredentials.priority!, 0, 0, size: estimatedSize); + + if (fee == 0) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + var amount = credentialsAmount; + + final lastOutput = outputs.last; + if (!sendAll) { + if (changeValue > fee) { + // Here, lastOutput is change, deduct the fee from it + outputs[outputs.length - 1] = + BitcoinOutput(address: lastOutput.address, value: lastOutput.value - BigInt.from(fee)); + } + } else { + // Here, if sendAll, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount for change + amount = allInputsAmount - fee; + outputs[outputs.length - 1] = + BitcoinOutput(address: lastOutput.address, value: BigInt.from(amount)); + } + + final totalAmount = amount + fee; + + if (totalAmount > balance[currency]!.confirmed || amount < minAmount) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + if (totalAmount > allInputsAmount) { + if (unspentCoins.where((utx) => utx.isSending).length == utxos.length) { + throw BitcoinTransactionWrongBalanceException(currency); + } else { + if (changeValue > fee) { + outputAddresses.removeLast(); + outputs.removeLast(); + } + + return _estimateTxFeeAndInputsToUse( + credentialsAmount, minAmount, sendAll, outputAddresses, outputs, transactionCredentials, + inputsCount: utxos.length + 1); + } + } + + return EstimatedTxResult(utxos: utxos, privateKeys: privateKeys, fee: fee, amount: amount); + } + @override Future createTransaction(Object credentials) async { try { @@ -207,27 +331,8 @@ abstract class ElectrumWalletBase for (final out in transactionCredentials.outputs) { final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address; - BitcoinAddress address; - - if (P2pkhAddress.REGEX.hasMatch(outputAddress)) { - address = P2pkhAddress.fromAddress(address: outputAddress, network: network); - minAmount += P2pkhAddress.outputSizeVB; - } else if (P2shAddress.REGEX.hasMatch(outputAddress)) { - address = P2shAddress.fromAddress(address: outputAddress, network: network); - minAmount += P2shAddress.outputSizeVB; - } else if (P2wshAddress.REGEX.hasMatch(outputAddress)) { - address = P2wshAddress.fromAddress(address: outputAddress, network: network); - minAmount += P2wshAddress.outputSizeVB; - } else if (P2trAddress.REGEX.hasMatch(outputAddress)) { - address = P2trAddress.fromAddress(address: outputAddress, network: network); - minAmount += P2trAddress.outputSizeVB; - } else if (P2wpkhAddress.REGEX.hasMatch(outputAddress)) { - address = P2wpkhAddress.fromAddress(address: outputAddress, network: network); - minAmount += P2wpkhAddress.outputSizeVB; - } else { - // TODO: proper error here for output address not found - throw BitcoinTransactionWrongBalanceException(currency); - } + final address = _addressTypeFromStr(outputAddress, network); + minAmount += _getOutputSizeVB(address); outputAddresses.add(address); @@ -252,166 +357,18 @@ abstract class ElectrumWalletBase } } - final utxos = []; - final List privateKeys = []; - - var leftAmount = credentialsAmount; - var overheadSizeVB = 0.0; - var allInputsAmount = 0; - - for (final utx in unspentCoins) { - if (utx.isSending) { - allInputsAmount += utx.value; - leftAmount = leftAmount - utx.value; - - BitcoinAddress address; - BitcoinAddressType scriptType; - - ECPrivate privkey; - ECPrivate mainPrivkey = generateECPrivate( - hd: walletAddresses.mainHd, index: utx.bitcoinAddressRecord.index, network: network); - ECPrivate sidePrivkey = generateECPrivate( - hd: walletAddresses.sideHd, index: utx.bitcoinAddressRecord.index, network: network); - - if (P2pkhAddress.REGEX.hasMatch(utx.address)) { - address = P2pkhAddress.fromAddress(address: utx.address, network: network); - minAmount += P2pkhAddress.inputSizeVB; - scriptType = BitcoinAddressType.p2pkh; - if (P2pkhAddress.fromPubkey(pubkey: mainPrivkey.getPublic().toHex()) - .toAddress(network) == - utx.address) { - privkey = mainPrivkey; - } else { - privkey = sidePrivkey; - } - } else if (P2wshAddress.REGEX.hasMatch(utx.address)) { - address = P2wshAddress.fromAddress(address: utx.address, network: network); - minAmount += P2wshAddress.inputSizeVB; - scriptType = BitcoinAddressType.p2wsh; - if (P2wshAddress.fromPubkey(pubkey: mainPrivkey.getPublic().toHex()) - .toAddress(network) == - utx.address) { - privkey = mainPrivkey; - } else { - privkey = sidePrivkey; - } - } else if (P2trAddress.REGEX.hasMatch(utx.address)) { - address = P2trAddress.fromAddress(address: utx.address, network: network); - minAmount += P2trAddress.inputSizeVB; - scriptType = BitcoinAddressType.p2tr; - if (P2trAddress.fromPubkey(pubkey: mainPrivkey.getPublic().toHex()) - .toAddress(network) == - utx.address) { - privkey = mainPrivkey; - } else { - privkey = sidePrivkey; - } - } else { - address = P2wpkhAddress.fromAddress(address: utx.address, network: network); - minAmount += P2wpkhAddress.inputSizeVB; - scriptType = BitcoinAddressType.p2wpkh; - if (P2wpkhAddress.fromPubkey(pubkey: mainPrivkey.getPublic().toHex()) - .toAddress(network) == - utx.address) { - privkey = mainPrivkey; - } else { - privkey = sidePrivkey; - } - } - - privateKeys.add(privkey); - - if (utx.bitcoinAddressRecord.type == BitcoinAddressType.p2pkh) { - overheadSizeVB = P2pkhAddress.overheadSizeVB; - } else { - overheadSizeVB = P2wpkhAddress.overheadSizeVB; - } - - utxos.add( - UtxoWithAddress( - utxo: BitcoinUtxo( - txHash: utx.hash, - value: BigInt.from(utx.value), - vout: utx.vout, - scriptType: scriptType, - ), - ownerDetails: - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), - ), - ); - - if (!sendAll && leftAmount <= 0) { - break; - } - } - } - - if (utxos.isEmpty) { - throw BitcoinTransactionNoInputsException(); - } - - minAmount += overheadSizeVB; - - if (!sendAll) { - final changeValue = allInputsAmount - credentialsAmount; - - if (changeValue > 0) { - final changeAddress = await walletAddresses.getChangeAddress(); - BitcoinAddress address; - if (P2pkhAddress.REGEX.hasMatch(changeAddress)) { - address = P2pkhAddress.fromAddress(address: changeAddress, network: network); - } else if (P2wshAddress.REGEX.hasMatch(changeAddress)) { - address = P2wshAddress.fromAddress(address: changeAddress, network: network); - } else if (P2trAddress.REGEX.hasMatch(changeAddress)) { - address = P2trAddress.fromAddress(address: changeAddress, network: network); - } else { - address = P2wpkhAddress.fromAddress(address: changeAddress, network: network); - } - - outputAddresses.add(address); - outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue))); - } - } - - final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( - utxos: utxos, outputs: outputAddresses, network: network); - - final fee = transactionCredentials.feeRate != null - ? feeAmountWithFeeRate(transactionCredentials.feeRate!, 0, 0, size: estimatedSize) - : feeAmountForPriority(transactionCredentials.priority!, 0, 0, size: estimatedSize); - - if (fee == 0) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - var amount = credentialsAmount; - - final lastOutput = outputs.last; - if (!sendAll) { - // Here, lastOutput is change, deduct the fee from it - outputs[outputs.length - 1] = - BitcoinOutput(address: lastOutput.address, value: lastOutput.value - BigInt.from(fee)); - } else { - // Here, if sendAll, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount for change - amount = allInputsAmount - fee; - outputs[outputs.length - 1] = - BitcoinOutput(address: lastOutput.address, value: BigInt.from(amount)); - } - - final totalAmount = amount + fee; - - if (totalAmount > balance[currency]!.confirmed || - totalAmount > allInputsAmount || - amount < minAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } + final estimatedTx = await _estimateTxFeeAndInputsToUse( + credentialsAmount, minAmount, sendAll, outputAddresses, outputs, transactionCredentials); final txb = BitcoinTransactionBuilder( - utxos: utxos, outputs: outputs, fee: BigInt.from(fee), network: network); + utxos: estimatedTx.utxos, + outputs: outputs, + fee: BigInt.from(estimatedTx.fee), + network: network); final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { - final key = - privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); + final key = estimatedTx.privateKeys + .firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); if (key == null) { throw Exception("Cannot find private key"); @@ -425,13 +382,15 @@ abstract class ElectrumWalletBase }); return PendingBitcoinTransaction(transaction, type, - electrumClient: electrumClient, amount: amount, fee: fee, network: network) + electrumClient: electrumClient, + amount: estimatedTx.amount, + fee: estimatedTx.fee, + network: network) ..addListener((transaction) async { transactionHistory.addOne(transaction); await updateBalance(); }); - } catch (e, s) { - print(["ERROR", e, s]); + } catch (e) { throw e; } } @@ -874,5 +833,76 @@ abstract class ElectrumWalletBase return base64Encode(HD.signMessage(message)); } } -// TODO: contact addresses -// TODO: select change address + +class EstimateTxParams { + EstimateTxParams( + {required this.amount, + required this.feeRate, + required this.priority, + required this.outputsCount, + required this.size}); + + final int amount; + final int feeRate; + final TransactionPriority priority; + final int outputsCount; + final int size; +} + +class EstimatedTxResult { + EstimatedTxResult( + {required this.utxos, required this.privateKeys, required this.fee, required this.amount}); + + final List utxos; + final List privateKeys; + final int fee; + final int amount; +} + +BitcoinAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) { + if (P2pkhAddress.REGEX.hasMatch(address)) { + return P2pkhAddress.fromAddress(address: address, network: network); + } else if (P2wshAddress.REGEX.hasMatch(address)) { + return P2wshAddress.fromAddress(address: address, network: network); + } else if (P2trAddress.REGEX.hasMatch(address)) { + return P2trAddress.fromAddress(address: address, network: network); + } else { + return P2wpkhAddress.fromAddress(address: address, network: network); + } +} + +int _getOutputSizeVB(BitcoinAddress type) { + if (type is P2pkhAddress) { + return P2pkhAddress.outputSizeVB; + } else if (type is P2wshAddress) { + return P2wshAddress.outputSizeVB; + } else if (type is P2trAddress) { + return P2trAddress.outputSizeVB; + } else { + return P2wpkhAddress.outputSizeVB; + } +} + +double _getInputSizeVB(BitcoinAddress type) { + if (type is P2pkhAddress) { + return P2pkhAddress.inputSizeVB + 0.0; + } else if (type is P2wshAddress) { + return P2wshAddress.inputSizeVB; + } else if (type is P2trAddress) { + return P2trAddress.inputSizeVB; + } else { + return P2wpkhAddress.inputSizeVB + 0.0; + } +} + +BitcoinAddressType _getScriptType(BitcoinAddress type) { + if (type is P2pkhAddress) { + return BitcoinAddressType.p2pkh; + } else if (type is P2wshAddress) { + return BitcoinAddressType.p2wsh; + } else if (type is P2trAddress) { + return BitcoinAddressType.p2tr; + } else { + return BitcoinAddressType.p2wpkh; + } +} diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 279fbf815..a61571dc2 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: fbd9f53f9eb29037e90df1c23c7fe02ece6230a2 + resolved-ref: a5cfb6da084abef3e6daa25a4a204e2bd8ca8644 url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "3.0.1" From 192a649902cf9cfa34a2bcc3a13c2e8514d43021 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Mon, 5 Feb 2024 12:05:13 -0300 Subject: [PATCH 38/59] fix: new bitcoin_base update, fixes script issues --- cw_bitcoin/lib/address_from_output.dart | 14 ++-- .../lib/bitcoin_receive_page_option.dart | 8 +-- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 6 +- cw_bitcoin/lib/electrum_transaction_info.dart | 5 +- cw_bitcoin/lib/electrum_wallet.dart | 67 +++++-------------- cw_bitcoin/lib/electrum_wallet_addresses.dart | 9 ++- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 10 +-- cw_bitcoin/lib/utils.dart | 8 +-- cw_bitcoin/pubspec.lock | 8 +-- lib/core/address_validator.dart | 12 ++-- .../screens/dashboard/pages/address_page.dart | 15 ++--- 11 files changed, 61 insertions(+), 101 deletions(-) diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index 7762fe94d..74606dca6 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -2,18 +2,18 @@ import 'package:bitcoin_base/bitcoin_base.dart'; String addressFromOutputScript(Script script, BasedUtxoNetwork network) { try { - switch (script.getType()) { - case ScriptType.P2PK: + switch (script.getAddressType()) { + case PubKeyAddressType.p2pk: return P2pkAddress.fromScriptPubkey(script: script).toAddress(network); - case ScriptType.P2PKH: + case P2pkhAddressType.p2pkh: return P2pkhAddress.fromScriptPubkey(script: script).toAddress(network); - case ScriptType.P2SH: + case P2shAddressType.p2pkInP2sh: return P2shAddress.fromScriptPubkey(script: script).toAddress(network); - case ScriptType.P2WPKH: + case SegwitAddresType.p2wpkh: return P2wpkhAddress.fromScriptPubkey(script: script).toAddress(network); - case ScriptType.P2WSH: + case SegwitAddresType.p2wsh: return P2wshAddress.fromScriptPubkey(script: script).toAddress(network); - case ScriptType.P2TR: + case SegwitAddresType.p2tr: return P2trAddress.fromScriptPubkey(script: script).toAddress(network); default: } diff --git a/cw_bitcoin/lib/bitcoin_receive_page_option.dart b/cw_bitcoin/lib/bitcoin_receive_page_option.dart index f04221ef1..7ce653c51 100644 --- a/cw_bitcoin/lib/bitcoin_receive_page_option.dart +++ b/cw_bitcoin/lib/bitcoin_receive_page_option.dart @@ -24,13 +24,13 @@ class BitcoinReceivePageOption implements ReceivePageOption { factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) { switch (type) { - case BitcoinAddressType.p2tr: + case SegwitAddresType.p2tr: return BitcoinReceivePageOption.p2tr; - case BitcoinAddressType.p2wsh: + case SegwitAddresType.p2wsh: return BitcoinReceivePageOption.p2wsh; - case BitcoinAddressType.p2pkh: + case P2pkhAddressType.p2pkh: return BitcoinReceivePageOption.p2pkh; - case BitcoinAddressType.p2wpkh: + case SegwitAddresType.p2wpkh: default: return BitcoinReceivePageOption.p2wpkh; } diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index 976d91cf2..6207f6e14 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -23,13 +23,13 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S @override String getAddress({required int index, required HDWallet hd, BitcoinAddressType? addressType}) { - if (addressType == BitcoinAddressType.p2pkh) + if (addressType == P2pkhAddressType.p2pkh) return generateP2PKHAddress(hd: hd, index: index, network: network); - if (addressType == BitcoinAddressType.p2tr) + if (addressType == SegwitAddresType.p2tr) return generateP2TRAddress(hd: hd, index: index, network: network); - if (addressType == BitcoinAddressType.p2wsh) + if (addressType == SegwitAddresType.p2wsh) return generateP2WSHAddress(hd: hd, index: index, network: network); return generateP2WPKHAddress(hd: hd, index: index, network: network); diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index ebe3acf17..89baf2f8e 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -1,6 +1,5 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:cw_bitcoin/address_from_output.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; @@ -13,8 +12,8 @@ import 'package:cw_core/wallet_type.dart'; class ElectrumTransactionBundle { ElectrumTransactionBundle(this.originalTransaction, {required this.ins, required this.confirmations, this.time}); - final bitcoin_base.BtcTransaction originalTransaction; - final List ins; + final BtcTransaction originalTransaction; + final List ins; final int? time; final int confirmations; } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index ac03a575c..783f39fa1 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -195,9 +195,8 @@ abstract class ElectrumWalletBase Future _estimateTxFeeAndInputsToUse( int credentialsAmount, - double minAmount, bool sendAll, - List outputAddresses, + List outputAddresses, List outputs, BitcoinTransactionCredentials transactionCredentials, {int? inputsCount}) async { @@ -205,7 +204,6 @@ abstract class ElectrumWalletBase List privateKeys = []; var leftAmount = credentialsAmount; - var overheadSizeVB = 0.0; var allInputsAmount = 0; for (int i = 0; i < unspentCoins.length; i++) { @@ -216,7 +214,6 @@ abstract class ElectrumWalletBase leftAmount = leftAmount - utx.value; final address = _addressTypeFromStr(utx.address, network); - minAmount += _getInputSizeVB(address); final privkey = generateECPrivate( hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, index: utx.bitcoinAddressRecord.index, @@ -224,12 +221,6 @@ abstract class ElectrumWalletBase privateKeys.add(privkey); - if (utx.bitcoinAddressRecord.type is LegacyAddress) { - overheadSizeVB = LegacyAddress.overheadSizeVB; - } else { - overheadSizeVB = SegwitAddress.overheadSizeVB; - } - utxos.add( UtxoWithAddress( utxo: BitcoinUtxo( @@ -253,8 +244,6 @@ abstract class ElectrumWalletBase throw BitcoinTransactionNoInputsException(); } - minAmount += overheadSizeVB; - var changeValue = allInputsAmount - credentialsAmount; if (!sendAll) { @@ -267,7 +256,7 @@ abstract class ElectrumWalletBase } final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( - utxos: utxos, outputs: outputAddresses, network: network); + utxos: utxos, outputs: outputs, network: network); final fee = transactionCredentials.feeRate != null ? feeAmountWithFeeRate(transactionCredentials.feeRate!, 0, 0, size: estimatedSize) @@ -295,7 +284,7 @@ abstract class ElectrumWalletBase final totalAmount = amount + fee; - if (totalAmount > balance[currency]!.confirmed || amount < minAmount) { + if (totalAmount > balance[currency]!.confirmed) { throw BitcoinTransactionWrongBalanceException(currency); } @@ -309,7 +298,7 @@ abstract class ElectrumWalletBase } return _estimateTxFeeAndInputsToUse( - credentialsAmount, minAmount, sendAll, outputAddresses, outputs, transactionCredentials, + credentialsAmount, sendAll, outputAddresses, outputs, transactionCredentials, inputsCount: utxos.length + 1); } } @@ -321,18 +310,16 @@ abstract class ElectrumWalletBase Future createTransaction(Object credentials) async { try { final outputs = []; - final outputAddresses = []; + final outputAddresses = []; final transactionCredentials = credentials as BitcoinTransactionCredentials; final hasMultiDestination = transactionCredentials.outputs.length > 1; final sendAll = !hasMultiDestination && transactionCredentials.outputs.first.sendAll; var credentialsAmount = 0; - var minAmount = 0.0; for (final out in transactionCredentials.outputs) { final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address; final address = _addressTypeFromStr(outputAddress, network); - minAmount += _getOutputSizeVB(address); outputAddresses.add(address); @@ -358,7 +345,7 @@ abstract class ElectrumWalletBase } final estimatedTx = await _estimateTxFeeAndInputsToUse( - credentialsAmount, minAmount, sendAll, outputAddresses, outputs, transactionCredentials); + credentialsAmount, sendAll, outputAddresses, outputs, transactionCredentials); final txb = BitcoinTransactionBuilder( utxos: estimatedTx.utxos, @@ -859,50 +846,26 @@ class EstimatedTxResult { final int amount; } -BitcoinAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) { - if (P2pkhAddress.REGEX.hasMatch(address)) { +BitcoinBaseAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) { + if (P2pkhAddress.regex.hasMatch(address)) { return P2pkhAddress.fromAddress(address: address, network: network); - } else if (P2wshAddress.REGEX.hasMatch(address)) { + } else if (P2wshAddress.regex.hasMatch(address)) { return P2wshAddress.fromAddress(address: address, network: network); - } else if (P2trAddress.REGEX.hasMatch(address)) { + } else if (P2trAddress.regex.hasMatch(address)) { return P2trAddress.fromAddress(address: address, network: network); } else { return P2wpkhAddress.fromAddress(address: address, network: network); } } -int _getOutputSizeVB(BitcoinAddress type) { +BitcoinAddressType _getScriptType(BitcoinBaseAddress type) { if (type is P2pkhAddress) { - return P2pkhAddress.outputSizeVB; + return P2pkhAddressType.p2pkh; } else if (type is P2wshAddress) { - return P2wshAddress.outputSizeVB; + return SegwitAddresType.p2wsh; } else if (type is P2trAddress) { - return P2trAddress.outputSizeVB; + return SegwitAddresType.p2tr; } else { - return P2wpkhAddress.outputSizeVB; - } -} - -double _getInputSizeVB(BitcoinAddress type) { - if (type is P2pkhAddress) { - return P2pkhAddress.inputSizeVB + 0.0; - } else if (type is P2wshAddress) { - return P2wshAddress.inputSizeVB; - } else if (type is P2trAddress) { - return P2trAddress.inputSizeVB; - } else { - return P2wpkhAddress.inputSizeVB + 0.0; - } -} - -BitcoinAddressType _getScriptType(BitcoinAddress type) { - if (type is P2pkhAddress) { - return BitcoinAddressType.p2pkh; - } else if (type is P2wshAddress) { - return BitcoinAddressType.p2wsh; - } else if (type is P2trAddress) { - return BitcoinAddressType.p2tr; - } else { - return BitcoinAddressType.p2wpkh; + return SegwitAddresType.p2wpkh; } } diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 7249fd773..b213b601d 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -34,7 +34,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { currentChangeAddressIndexByType = initialChangeAddressIndex ?? {}, _addressPageType = walletInfo.addressPageType != null ? BitcoinAddressType.fromValue(walletInfo.addressPageType!) - : BitcoinAddressType.p2wpkh, + : SegwitAddresType.p2wpkh, super(walletInfo); static const defaultReceiveAddressesCount = 22; @@ -55,7 +55,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final bitcoin.HDWallet sideHd; @observable - BitcoinAddressType _addressPageType = BitcoinAddressType.p2wpkh; + BitcoinAddressType _addressPageType = SegwitAddresType.p2wpkh; @computed BitcoinAddressType get addressPageType => _addressPageType; @@ -347,14 +347,13 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { Future setAddressType(BitcoinAddressType type) async { _addressPageType = type; - await _discoverAddresses(false); - updateReceiveAddresses(); + await discoverAddresses(); await saveAddressesInBox(); } bool _isAddressTypeMatch(BitcoinAddressRecord addressRecord) { // Old wallets before address types were introduced will have an empty address record type - return addressPageType == BitcoinAddressType.p2wpkh + return addressPageType == SegwitAddresType.p2wpkh ? addressRecord.type == null || addressRecord.type == addressPageType : addressRecord.type == addressPageType; } diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 1922d1353..96879cc18 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -44,15 +44,15 @@ class ElectrumWalletSnapshot { .toList(); final balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); - var regularAddressIndexByType = {BitcoinAddressType.p2wpkh.toString(): 0}; - var changeAddressIndexByType = {BitcoinAddressType.p2wpkh.toString(): 0}; + var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; + var changeAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; try { regularAddressIndexByType = { - BitcoinAddressType.p2wpkh.toString(): int.parse(data['account_index'] as String? ?? '0') + SegwitAddresType.p2wpkh.toString(): int.parse(data['account_index'] as String? ?? '0') }; changeAddressIndexByType = { - BitcoinAddressType.p2wpkh.toString(): + SegwitAddresType.p2wpkh.toString(): int.parse(data['change_address_index'] as String? ?? '0') }; } catch (_) { @@ -71,7 +71,7 @@ class ElectrumWalletSnapshot { balance: balance, regularAddressIndex: regularAddressIndexByType, changeAddressIndex: changeAddressIndexByType, - addressPageType: data['address_page_type'] as String? ?? BitcoinAddressType.p2wpkh.toString(), + addressPageType: data['address_page_type'] as String? ?? SegwitAddresType.p2wpkh.toString(), network: data['network_type'] == 'testnet' ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet, ); } diff --git a/cw_bitcoin/lib/utils.dart b/cw_bitcoin/lib/utils.dart index ba75d5081..1f4e5e7b6 100644 --- a/cw_bitcoin/lib/utils.dart +++ b/cw_bitcoin/lib/utils.dart @@ -14,16 +14,16 @@ ECPrivate generateECPrivate( String generateP2WPKHAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - P2wpkhAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); + ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhAddress().toAddress(network); String generateP2WSHAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - P2wshAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); + ECPublic.fromHex(hd.derive(index).pubKey!).toP2wshAddress().toAddress(network); String generateP2PKHAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - P2pkhAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); + ECPublic.fromHex(hd.derive(index).pubKey!).toP2pkhAddress().toAddress(network); String generateP2TRAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - P2trAddress.fromPubkey(pubkey: hd.derive(index).pubKey!).toAddress(network); + ECPublic.fromHex(hd.derive(index).pubKey!).toTaprootAddress().toAddress(network); diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index a61571dc2..07c97deb3 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: asn1lib - sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd" + sha256: c9c85fedbe2188b95133cbe960e16f5f448860f7133330e272edbbca5893ddc6 url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.5.2" async: dependency: transitive description: @@ -80,10 +80,10 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: a5cfb6da084abef3e6daa25a4a204e2bd8ca8644 + resolved-ref: "318986da9cb03e4c18da2e6c0daf3e62aef7eb72" url: "https://github.com/cake-tech/bitcoin_base.git" source: git - version: "3.0.1" + version: "4.0.0" bitcoin_flutter: dependency: "direct main" description: diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 7545d74e1..3505ef182 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -25,7 +25,7 @@ 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 '^${P2pkhAddress.REGEX.pattern}\$|^${P2shAddress.REGEX.pattern}\$|^${P2wpkhAddress.REGEX.pattern}\$|${P2trAddress.REGEX.pattern}\$|^${P2wshAddress.REGEX.pattern}\$'; + return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$'; case CryptoCurrency.nano: return '[0-9a-zA-Z_]'; case CryptoCurrency.banano: @@ -263,11 +263,11 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)8[0-9a-zA-Z]{94}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[0-9a-zA-Z]{106}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.btc: - return '([^0-9a-zA-Z]|^)${P2pkAddress.REGEX.pattern}|\$)' - '([^0-9a-zA-Z]|^)${P2shAddress.REGEX.pattern}|\$)' - '([^0-9a-zA-Z]|^)${P2wpkhAddress.REGEX.pattern}|\$)' - '([^0-9a-zA-Z]|^)${P2wshAddress.REGEX.pattern}|\$)' - '([^0-9a-zA-Z]|^)${P2trAddress.REGEX.pattern}|\$)'; + return '([^0-9a-zA-Z]|^)${P2pkAddress.regex.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2shAddress.regex.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2wpkhAddress.regex.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2wshAddress.regex.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2trAddress.regex.pattern}|\$)'; case CryptoCurrency.ltc: return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)' diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index 54389d58a..e38a8f16d 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -165,11 +165,10 @@ class AddressPage extends BasePage { return SelectButton( text: addressListViewModel.buttonTitle, onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled && - (WalletType.monero == addressListViewModel.wallet.type || - WalletType.haven == addressListViewModel.wallet.type) + (WalletType.monero == addressListViewModel.wallet.type || + WalletType.haven == addressListViewModel.wallet.type) ? await showPopUp( - context: context, - builder: (_) => getIt.get()) + context: context, builder: (_) => getIt.get()) : Navigator.of(context).pushNamed(Routes.receive), textColor: Theme.of(context).extension()!.textColor, color: Theme.of(context).extension()!.syncedBackgroundColor, @@ -232,16 +231,16 @@ class AddressPage extends BasePage { } break; case BitcoinReceivePageOption.p2pkh: - addressListViewModel.setAddressType(BitcoinAddressType.p2pkh); + addressListViewModel.setAddressType(P2pkhAddressType.p2pkh); break; case BitcoinReceivePageOption.p2wpkh: - addressListViewModel.setAddressType(BitcoinAddressType.p2wpkh); + addressListViewModel.setAddressType(SegwitAddresType.p2wpkh); break; case BitcoinReceivePageOption.p2tr: - addressListViewModel.setAddressType(BitcoinAddressType.p2tr); + addressListViewModel.setAddressType(SegwitAddresType.p2tr); break; case BitcoinReceivePageOption.p2wsh: - addressListViewModel.setAddressType(BitcoinAddressType.p2wsh); + addressListViewModel.setAddressType(SegwitAddresType.p2wsh); break; default: } From b9e5c525160bbdd2532fe5fcf64c09fa91382600 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 6 Feb 2024 05:26:56 +0200 Subject: [PATCH 39/59] Update evm chain wallet service arguments --- cw_evm/lib/evm_chain_wallet_service.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cw_evm/lib/evm_chain_wallet_service.dart b/cw_evm/lib/evm_chain_wallet_service.dart index 988a38684..d77a3a81a 100644 --- a/cw_evm/lib/evm_chain_wallet_service.dart +++ b/cw_evm/lib/evm_chain_wallet_service.dart @@ -22,7 +22,7 @@ abstract class EVMChainWalletService extends WalletSer WalletType getType(); @override - Future create(EVMChainNewWalletCredentials credentials); + Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}); @override Future openWallet(String name, String password); @@ -31,10 +31,10 @@ abstract class EVMChainWalletService extends WalletSer Future rename(String currentName, String password, String newName); @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials); + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, {bool? isTestnet}); @override - Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials); + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}); @override Future isWalletExit(String name) async => From d0f6f83024076dd08b204ad437efc9cf33847d11 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 6 Feb 2024 22:30:57 +0200 Subject: [PATCH 40/59] Fix translation [skip ci] --- res/values/strings_ar.arb | 275 +------------------------------------ res/values/strings_bg.arb | 271 +----------------------------------- res/values/strings_cs.arb | 271 +----------------------------------- res/values/strings_de.arb | 279 +------------------------------------ res/values/strings_en.arb | 280 +------------------------------------- res/values/strings_es.arb | 279 +------------------------------------ res/values/strings_fr.arb | 280 +------------------------------------- res/values/strings_ha.arb | 260 +---------------------------------- res/values/strings_hi.arb | 279 +------------------------------------ res/values/strings_hr.arb | 277 +------------------------------------ res/values/strings_id.arb | 266 +----------------------------------- res/values/strings_it.arb | 279 +------------------------------------ res/values/strings_ja.arb | 279 +------------------------------------ res/values/strings_ko.arb | 277 +------------------------------------ res/values/strings_my.arb | 277 +------------------------------------ res/values/strings_nl.arb | 279 +------------------------------------ res/values/strings_pl.arb | 279 +------------------------------------ res/values/strings_pt.arb | 279 +------------------------------------ res/values/strings_ru.arb | 279 +------------------------------------ res/values/strings_th.arb | 277 +------------------------------------ res/values/strings_tl.arb | 273 +------------------------------------ res/values/strings_tr.arb | 277 +------------------------------------ res/values/strings_uk.arb | 279 +------------------------------------ res/values/strings_ur.arb | 270 +----------------------------------- res/values/strings_yo.arb | 275 +------------------------------------ res/values/strings_zh.arb | 279 +------------------------------------ 26 files changed, 52 insertions(+), 7123 deletions(-) diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 3effd913e..d834bfd90 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -712,6 +712,7 @@ "use_card_info_two": "يتم تحويل الأموال إلى الدولار الأمريكي عند الاحتفاظ بها في الحساب المدفوع مسبقًا ، وليس بالعملات الرقمية.", "use_ssl": "استخدم SSL", "use_suggested": "استخدام المقترح", + "use_testnet": "استخدم testnet", "variable_pair_not_supported": "هذا الزوج المتغير غير مدعوم في التبادلات المحددة", "verification": "تَحَقّق", "verify_with_2fa": "تحقق مع Cake 2FA", @@ -770,277 +771,5 @@ "you_now_have_debit_card": "لديك الآن بطاقة ائتمان", "you_pay": "انت تدفع", "you_will_get": "حول الى", - "you_will_send": "تحويل من", - "yy": "YY", - "zzzz": "ززز" - "online": "متصل", - "offline": "غير متصل على الانترنت", - "gift_card_number": "رقم بطاقة الهدية", - "pin_number": "الرقم السري", - "total_saving": "إجمالي المدخرات", - "last_30_days": "آخر 30 يومًا", - "avg_savings": "متوسط مدخرات", - "view_all": "مشاهدة الكل", - "active_cards": "البطاقات النشطة", - "delete_account": "حذف الحساب", - "cards": "البطاقات", - "active": "نشيط", - "redeemed": "استردت", - "gift_card_balance_note": "ستظهر هنا بطاقات الهدايا ذات الرصيد المتبقي", - "gift_card_redeemed_note": "ستظهر هنا بطاقات الهدايا التي استردت قيمتها", - "logout": "تسجيل خروج", - "add_tip": "أضف بقشيش", - "percentageOf": "من ${amount}", - "is_percentage": "يكون", - "search_category": "فئة البحث", - "mark_as_redeemed": "وضع علامة كمسترد", - "more_options": "المزيد من الخيارات", - "awaiting_payment_confirmation": "في انتظار تأكيد الدفع", - "transaction_sent_notice": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من مستكشف البلوك والبريد الإلكتروني.", - "agree": "موافق", - "in_store": "في المتجر", - "generating_gift_card": "يتم توليد بطاقة هدية", - "payment_was_received": "تم استلام الدفع الخاص بك.", - "proceed_after_one_minute": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من بريدك الإلكتروني.", - "order_id": "رقم التعريف الخاص بالطلب", - "gift_card_is_generated": "تم إنشاء بطاقة الهدايا", - "open_gift_card": "افتح بطاقة الهدية", - "contact_support": "اتصل بالدعم", - "gift_cards_unavailable": "تتوفر بطاقات الهدايا للشراء فقط باستخدام Monero و Bitcoin و Litecoin في الوقت الحالي", - "introducing_cake_pay": "نقدم لكم Cake Pay!", - "cake_pay_learn_more": "شراء واسترداد بطاقات الهدايا على الفور في التطبيق!\nاسحب من اليسار إلى اليمين لمعرفة المزيد.", - "automatic": "تلقائي", - "fixed_pair_not_supported": "هذا الزوج الثابت غير مدعوم في التبادلات المحددة", - "variable_pair_not_supported": "هذا الزوج المتغير غير مدعوم في التبادلات المحددة", - "none_of_selected_providers_can_exchange": "لا يمكن لأي من مقدمي الخدمة المختارين إجراء هذا التبادل", - "choose_one": "اختر واحدة", - "choose_from_available_options": "اختر من بين الخيارات المتاحة:", - "custom_redeem_amount": "مبلغ الاسترداد مخصص", - "add_custom_redemption": "إضافة استرداد مخصص", - "remaining": "متبقي", - "delete_wallet": "حذف المحفظة", - "delete_wallet_confirm_message": "هل أنت متأكد أنك تريد حذف محفظة ${wallet_name}؟", - "low_fee": "رسوم منخفضة", - "low_fee_alert": "أنت تستخدم حاليًا أولوية منخفضة لرسوم الشبكة. قد يتسبب هذا في فترات انتظار طويلة ، أو أسعار مختلفة ، أو إلغاء صفقات. نوصي بتحديد رسوم أعلى لتجربة أفضل.", - "ignor": "تجاهل", - "use_suggested": "استخدام المقترح", - "do_not_share_warning_text": "لا تشارك هذه مع أي شخص آخر ، بما في ذلك الدعم.\n\nيمكن أن تتم سرقة أموالك!", - "help": "مساعده", - "all_transactions": "كل التحركات المالية", - "all_trades": "جميع عمليات التداول", - "connection_sync": "الاتصال والمزامنة", - "security_and_backup": "الأمان والنسخ الاحتياطي", - "create_backup": "انشئ نسخة احتياطية", - "privacy_settings": "إعدادات الخصوصية", - "privacy": "خصوصية", - "display_settings": "اعدادات العرض", - "other_settings": "اعدادات اخرى", - "require_pin_after": "طلب PIN بعد", - "always": "دائماً", - "minutes_to_pin_code": "${minutes} دقيقة", - "disable_exchange": "تعطيل التبادل", - "advanced_settings": "إعدادات متقدمة", - "settings_can_be_changed_later": "يمكن تغيير هذه الإعدادات لاحقًا في إعدادات التطبيق", - "add_custom_node": "إضافة عقدة مخصصة جديدة", - "disable_fiat": "تعطيل fiat", - "fiat_api": "Fiat API", - "disabled": "معطلة", - "enabled": "ممكنة", - "tor_only": "Tor فقط", - "unmatched_currencies": "عملة محفظتك الحالية لا تتطابق مع عملة QR الممسوحة ضوئيًا", - "orbot_running_alert": "يرجى التأكد من تشغيل Orbot قبل الاتصال بهذه العقدة.", - "bitcoin_payments_require_1_confirmation": "تتطلب مدفوعات Bitcoin تأكيدًا واحدًا ، والذي قد يستغرق 20 دقيقة أو أكثر. شكرا لصبرك! سيتم إرسال بريد إلكتروني إليك عند تأكيد الدفع.", - "send_to_this_address": "أرسل ${currency} ${tag}إلى هذا العنوان", - "arrive_in_this_address": "سيصل ${currency} ${tag}إلى هذا العنوان", - "do_not_send": "لا ترسل", - "error_dialog_content": "عفوًا ، لقد حصلنا على بعض الخطأ.\n\nيرجى إرسال تقرير التعطل إلى فريق الدعم لدينا لتحسين التطبيق.", - "scan_qr_code": "امسح رمز QR ضوئيًا", - "cold_or_recover_wallet": "أضف محفظة باردة أو استعد محفظة ورقية", - "please_wait": "انتظر من فضلك", - "sweeping_wallet": "كنس المحفظة", - "sweeping_wallet_alert": "لن يستغرق هذا وقتًا طويلاً. لا تترك هذه الشاشة وإلا فقد يتم فقد أموال سويبت", - "decimal_places_error": "عدد كبير جدًا من المنازل العشرية", - "edit_node": "تحرير العقدة", - "invoice_details": "تفاصيل الفاتورة", - "donation_link_details": "تفاصيل رابط التبرع", - "anonpay_description": "توليد ${type}. يمكن للمستلم ${method} بأي عملة مشفرة مدعومة ، وستتلقى أموالاً في هذه", - "create_invoice": "إنشاء فاتورة", - "create_donation_link": "إنشاء رابط التبرع", - "optional_email_hint": "البريد الإلكتروني إخطار المدفوع لأمره الاختياري", - "optional_description": "وصف اختياري", - "optional_name": "اسم المستلم الاختياري", - "clearnet_link": "رابط Clearnet", - "onion_link": "رابط البصل", - "settings": "إعدادات", - "sell_monero_com_alert_content": "بيع Monero غير مدعوم حتى الآن", - "error_text_input_below_minimum_limit": " المبلغ أقل من الحد الأدنى", - "error_text_input_above_maximum_limit": "المبلغ أكبر من الحد الأقصى", - "show_market_place": "إظهار السوق", - "prevent_screenshots": "منع لقطات الشاشة وتسجيل الشاشة", - "profile": "حساب تعريفي", - "close": "يغلق", - "modify_2fa": "تعديل 2 عامل المصادقة", - "disable_cake_2fa": "تعطيل 2 عامل المصادقة", - "question_to_disable_2fa": "هل أنت متأكد أنك تريد تعطيل Cake 2FA؟ لن تكون هناك حاجة إلى رمز 2FA للوصول إلى المحفظة ووظائف معينة.", - "disable": "إبطال", - "setup_2fa": "تعيين 2 عامل المصادقة", - "verify_with_2fa": "تحقق مع Cake 2FA", - "totp_code": "كود TOTP", - "please_fill_totp": "يرجى ملء الرمز المكون من 8 أرقام الموجود على جهازك الآخر", - "totp_2fa_success": "نجاح! تم تمكين Cake 2FA لهذه المحفظة. تذكر حفظ بذرة ذاكري في حالة فقد الوصول إلى المحفظة.", - "totp_verification_success": "تم التحقق بنجاح!", - "totp_2fa_failure": "شفرة خاطئة. يرجى تجربة رمز مختلف أو إنشاء مفتاح سري جديد. استخدم تطبيق 2FA متوافقًا يدعم الرموز المكونة من 8 أرقام و SHA512.", - "enter_totp_code": "الرجاء إدخال رمز TOTP.", - "add_secret_code": " ﺔﻗﺩﺎﺼﻤﻟﺍ ﻖﻴﺒﻄﺗ ﻰﻟﺇ ﻱﺮﺴﻟﺍ ﺰﻣﺮﻟﺍ ﺍﺬﻫ ﻒﺿﺃ ﻭﺃ", - "totp_secret_code": "كود TOTP السري", - "setup_2fa_text": " .ﻲﻧﺎﺜﻟﺍ ﺔﻗﺩﺎﺼﻤﻟﺍ ﻞﻣﺎﻌﻛ TOTP ﻡﺍﺪﺨﺘﺳﺎﺑ Cake 2FA ﻞﻤﻌﻳ", - "setup_totp_recommended": " TOTP ﺩﺍﺪﻋﺇ", - "disable_buy": "تعطيل إجراء الشراء", - "disable_sell": "قم بتعطيل إجراء البيع", - "cake_2fa_preset": " كعكة 2FA مسبقا", - "narrow": "ضيق", - "normal": "طبيعي", - "aggressive": "عنيف", - "require_for_assessing_wallet": "تتطلب الوصول إلى المحفظة", - "require_for_sends_to_non_contacts": "تتطلب لارسال لغير جهات الاتصال", - "require_for_sends_to_contacts": "تتطلب لارسال جهات الاتصال", - "require_for_sends_to_internal_wallets": "تتطلب عمليات الإرسال إلى المحافظ الداخلية", - "require_for_exchanges_to_internal_wallets": "تتطلب عمليات التبادل إلى المحافظ الداخلية", - "require_for_adding_contacts": "تتطلب إضافة جهات اتصال", - "require_for_creating_new_wallets": "تتطلب إنشاء محافظ جديدة", - "require_for_all_security_and_backup_settings": "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", - "available_balance_description": "الرصيد المتاح هو الرصيد الذي يمكنك إنفاقه أو تحويله إلى محفظة أخرى. يتم تجميد الرصيد المتاح للمعاملات الصادرة والمعاملات الواردة غير المؤكدة.", - "syncing_wallet_alert_title": "محفظتك تتم مزامنتها", - "syncing_wallet_alert_content": "قد لا يكتمل رصيدك وقائمة المعاملات الخاصة بك حتى تظهر عبارة “SYNCHRONIZED“ في الأعلى. انقر / اضغط لمعرفة المزيد.", - "home_screen_settings": "إعدادات الشاشة الرئيسية", - "sort_by": "ترتيب حسب", - "search_add_token": "بحث / إضافة رمز", - "edit_token": "تحرير الرمز المميز", - "warning": "تحذير", - "add_token_warning": "لا تقم بتحرير أو إضافة رموز وفقًا لتعليمات المحتالين.\nقم دائمًا بتأكيد عناوين الرموز مع مصادر حسنة السمعة!", - "add_token_disclaimer_check": "لقد قمت بتأكيد عنوان ومعلومات عقد الرمز المميز باستخدام مصدر حسن السمعة. يمكن أن تؤدي إضافة معلومات خبيثة أو غير صحيحة إلى خسارة الأموال.", - "token_contract_address": "عنوان عقد الرمز", - "token_name": "اسم الرمز ، على سبيل المثال: Tether", - "token_symbol": "رمز العملة ، على سبيل المثال: USDT", - "token_decimal": "رمز عشري", - "field_required": "هذه الخانة مطلوبه", - "pin_at_top": "تثبيت ${token} في الأعلى", - "invalid_input": "مدخل غير صالح", - "fiat_balance": "الرصيد فيات", - "gross_balance": "إجمالي الرصيد", - "alphabetical": "مرتب حسب الحروف الأبجدية", - "generate_name": "توليد الاسم", - "balance_page": "صفحة التوازن", - "share": "يشارك", - "slidable": "قابل للانزلاق", - "monero_dark_theme": "موضوع مونيرو الظلام", - "bitcoin_dark_theme": "موضوع البيتكوين الظلام", - "bitcoin_light_theme": "موضوع البيتكوين الخفيفة", - "high_contrast_theme": "موضوع عالي التباين", - "matrix_green_dark_theme": "موضوع ماتريكس الأخضر الداكن", - "monero_light_theme": " ضوء مونيرو", - "etherscan_history": "Etherscan تاريخ", - "template_name": "اسم القالب", - "change_rep": "ﺏﻭﺪﻨﻣ ﺮﻴﻴﻐﺗ", - "change_rep_message": "؟ﻦﻴﻠﺜﻤﻤﻟﺍ ﺮﻴﻴﻐﺗ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ", - "manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ", - "unsupported_asset": ".ﻡﻮﻋﺪﻣ ﻞﺻﺃ ﻉﻮﻧ ﻦﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .ﻞﺻﻷﺍ ﺍﺬﻬﻟ ءﺍﺮﺟﻹﺍ ﺍﺬﻫ ﻢﻋﺪﻧ ﻻ ﻦﺤﻧ", - "manage_pow_nodes": "PoW ﻁﺎﻘﻧ ﺓﺭﺍﺩﺇ", - "support_title_live_chat": "الدعم المباشر", - "support_description_live_chat": "حرة وسريعة! ممثلو الدعم المدربين متاحون للمساعدة", - "support_title_guides": "أدلة محفظة كعكة", - "support_description_guides": "توثيق ودعم القضايا المشتركة", - "support_title_other_links": "روابط دعم أخرى", - "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", - "choose_derivation": "اختر اشتقاق المحفظة", - "new_first_wallet_text": "حافظ بسهولة على أمان العملة المشفرة", - "select_destination": ".ﻲﻃﺎﻴﺘﺣﻻﺍ ﺦﺴﻨﻟﺍ ﻒﻠﻣ ﺔﻬﺟﻭ ﺪﻳﺪﺤﺗ ءﺎﺟﺮﻟﺍ", - "auto_generate_subaddresses": "تلقائي توليد subddresses", - "save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ", - "select_buy_provider_notice": "حدد مزود شراء أعلاه. يمكنك تخطي هذه الشاشة عن طريق تعيين مزود شراء الافتراضي في إعدادات التطبيق.", - "onramper_option_description": "شراء بسرعة التشفير مع العديد من طرق الدفع. متوفر في معظم البلدان. ينتشر وتختلف الرسوم.", - "default_buy_provider": "مزود شراء الافتراضي", - "ask_each_time": "اسأل في كل مرة", - "buy_provider_unavailable": "مزود حاليا غير متوفر.", - "signTransaction": " ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ", - "errorGettingCredentials": "ﺩﺎﻤﺘﻋﻻﺍ ﺕﺎﻧﺎﻴﺑ ﻰﻠﻋ ﻝﻮﺼﺤﻟﺍ ءﺎﻨﺛﺃ ﺄﻄﺧ ﺙﺪﺣ :ﻞﺸﻓ", - "errorSigningTransaction": "ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ ءﺎﻨﺛﺃ ﺄﻄﺧ ﺙﺪﺣ", - "pairingInvalidEvent": "ﺢﻟﺎﺻ ﺮﻴﻏ ﺙﺪﺣ ﻥﺍﺮﻗﺇ", - "chains": "ﻞﺳﻼﺴﻟﺍ", - "methods": " ﻕﺮﻃُ", - "events": "ﺙﺍﺪﺣﻷﺍ", - "reject": "ﺾﻓﺮﻳ", - "approve": "ﺪﻤﺘﻌﻳ", - "expiresOn": "ﻲﻓ ﻪﺘﻴﺣﻼﺻ ﻲﻬﺘﻨﺗ", - "walletConnect": "WalletConnect", - "nullURIError": "ﻍﺭﺎﻓ (URI) ﻢﻈﺘﻨﻤﻟﺍ ﺩﺭﺍﻮﻤﻟﺍ ﻑﺮﻌﻣ", - "connectWalletPrompt": "ﺕﻼﻣﺎﻌﻤﻟﺍ ءﺍﺮﺟﻹ WalletConnect ﻊﻣ ﻚﺘﻈﻔﺤﻣ ﻞﻴﺻﻮﺘﺑ ﻢﻗ", - "newConnection": "ﺪﻳﺪﺟ ﻝﺎﺼﺗﺍ", - "activeConnectionsPrompt": "ﺎﻨﻫ ﺔﻄﺸﻨﻟﺍ ﺕﻻﺎﺼﺗﻻﺍ ﺮﻬﻈﺘﺳ", - "deleteConnectionConfirmationPrompt": "ـﺑ ﻝﺎﺼﺗﻻﺍ ﻑﺬﺣ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ", - "event": "ﺙﺪﺣ", - "successful": "ﺢﺟﺎﻧ", - "wouoldLikeToConnect": "ﻝﺎﺼﺗﻻﺍ ﻲﻓ ﺐﻏﺮﺗ", - "message": "ﺔﻟﺎﺳﺭ", - "do_not_have_enough_gas_asset": "ليس لديك ما يكفي من ${currency} لإجراء معاملة وفقًا لشروط شبكة blockchain الحالية. أنت بحاجة إلى المزيد من ${currency} لدفع رسوم شبكة blockchain، حتى لو كنت ترسل أصلًا مختلفًا.", - "totp_auth_url": "TOTP ﺔﻗﺩﺎﺼﻤﻟ URL ﻥﺍﻮﻨﻋ", - "awaitDAppProcessing": ".ﺔﺠﻟﺎﻌﻤﻟﺍ ﻦﻣ dApp ﻲﻬﺘﻨﻳ ﻰﺘﺣ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", - "copyWalletConnectLink": "ﺎﻨﻫ ﻪﻘﺼﻟﺍﻭ dApp ﻦﻣ WalletConnect ﻂﺑﺍﺭ ﺦﺴﻧﺍ", - "enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ", - "seed_key": "مفتاح البذور", - "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", - "change_rep_successful": "تم تغيير ممثل بنجاح", - "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", - "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!", - "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", - "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", - "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", - "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", - "order_by": "ترتيب حسب", - "creation_date": "تاريخ الإنشاء", - "group_by_type": "مجموعة حسب النوع", - "importNFTs": "NFTs ﺩﺍﺮﻴﺘﺳﺍ", - "noNFTYet": "ﻥﻵﺍ ﻰﺘﺣ NFTs ﺪﺟﻮﻳ ﻻ", - "address": " ﻥﺍﻮﻨﻋ", - "enterTokenID": "ﺰﻴﻤﻤﻟﺍ ﺰﻣﺮﻟﺍ ﻑﺮﻌﻣ ﻞﺧﺩﺃ", - "tokenID": "ﻒﻳﺮﻌﺗ ﺔﻗﺎﻄﺑ", - "name": "ﻢﺳﺍ", - "symbol": "ﺰﻣﺭ", - "seed_phrase_length": "ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", - "unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", - "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", - "unspent_change": "يتغير", - "setup_warning_2fa_text": ".ﺩﺭﺎﺒﻟﺍ ﻦﻳﺰﺨﺘﻟﺍ ﻞﺜﻣ ﺔﻨﻣﺁ ﺖﺴﻴﻟ ﺎﻬﻧﺇ .ﺔﻈﻔﺤﻤﻟﺍ ﻲﻓ ﺔﻨﻴﻌﻣ ﺕﺍءﺍﺮﺟﻹ ﺔﻴﻧﺎﺛ ﺔﻗﺩﺎﺼﻣ ﺔﺑﺎﺜ", - "scan_qr_on_device": " ﺮﺧﺁ ﺯﺎﻬﺟ ﻰﻠﻋ ﺎﻴًﺋﻮﺿ ﺍﺬﻫ ﺔﻌﻳﺮﺴﻟﺍ ﺔﺑﺎﺠﺘﺳﻻﺍ ﺰﻣﺭ ﺢﺴﻤﺑ ﻢﻗ", - "how_to_use": " ﻞﻤﻌﺘﺴﺗ ﻒﻴﻛ", - "seed_hex_form": "بذور المحفظة (شكل عرافة)", - "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ", - "seedtype": "البذور", - "seedtype_legacy": "إرث (25 كلمة)", - "seedtype_polyseed": "بوليسيد (16 كلمة)", - "seed_language_czech": "التشيكية", - "seed_language_korean": "الكورية", - "seed_language_chinese_traditional": "تقاليد صينية)", - "ascending": "تصاعدي", - "descending": "النزول", - "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", - "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ", - "wallet_seed_legacy": "بذرة محفظة قديمة", - "default_sell_provider": "ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", - "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ", - "custom_drag": "مخصص (عقد وسحب)", - "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", - "use_testnet": "استخدم testnet", - "receivable_balance": "التوازن القادم", - "confirmed_tx": "مؤكد", - "transaction_details_source_address": "عنوان المصدر", - "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ", - "contractName": "ﺪﻘﻌﻟﺍ ﻢﺳﺍ", - "contractSymbol": "ﺪﻘﻌﻟﺍ ﺰﻣﺭ", - "description": "ﻒﺻﻭ", - "camera_consent": ".ﻞﻴﺻﺎﻔﺘﻟﺍ ﻰﻠﻋ ﻝﻮﺼﺤﻠﻟ ﻢﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺔﻴﺻﻮﺼﺨﻟﺍ ﺔﺳﺎﻴﺳ ﻦﻣ ﻖﻘﺤﺘﻟﺍ ﻰﺟﺮﻳ .${provider} ﻝﻮﻠ", - "no_relays": "ﺕﻼﺣﺮﻤﻟﺍ ﻻ", - "choose_relay": "ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ", - "no_relays_message": ".ﻪﺑ ﺹﺎﺨﻟﺍ Nostr ﻞﺠﺳ ﻰﻟﺇ ﺕﻼﺣﺮﻤﻟﺍ ﺔﻓﺎﺿﻹ ﻢﻠﺘﺴﻤﻟﺍ ﺩﺎﺷﺭﺇ ﻰﺟﺮﻳ .ﺕﻼﺣﺮﻣ ﻱﺃ ﻰﻠﻋ ﻱﻮﺘﺤﻳ ﻻ", - "no_relay_on_domain": ".ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ .ﺡﺎﺘﻣ ﺮﻴﻏ ﻞﻴﺣﺮﺘﻟﺍ ﻥﺃ ﻭﺃ ﻡﺪﺨﺘﺴﻤﻟﺍ ﻝﺎﺠﻤﻟ ﻞﻴﺣﺮﺗ ﺪ" + "you_will_send": "تحويل من" } \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index ad231b5f2..3f5f8ce93 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -708,6 +708,7 @@ "use_card_info_two": "Средствата се обръщат в USD, когато биват запазени в предплатената карта, а не в дигитална валута.", "use_ssl": "Използване на SSL", "use_suggested": "Използване на предложеното", + "use_testnet": "Използвайте TestNet", "variable_pair_not_supported": "Този variable pair не се поддържа от избраната борса", "verification": "Потвърждаване", "verify_with_2fa": "Проверете с Cake 2FA", @@ -766,273 +767,5 @@ "you_now_have_debit_card": "Вече имате дебитна карта", "you_pay": "Вие плащате", "you_will_get": "Обръщане в", - "you_will_send": "Обръщане от", - "yy": "гг", - "online": "Онлайн", - "offline": "Офлайн", - "gift_card_number": "Номер на Gift Card", - "pin_number": "PIN код", - "total_saving": "Общо спестявания", - "last_30_days": "Последните 30 дни", - "avg_savings": "Средни спестявания", - "view_all": "Виж всички", - "active_cards": "Активни карти", - "delete_account": "Изтриване на акаунт", - "cards": "Карти", - "active": "Активиране", - "redeemed": "Използвани", - "gift_card_balance_note": "Гифткарти с наличен баланс ще се покажат тук", - "gift_card_redeemed_note": "Използваните гифткарти ще се покажат тук", - "logout": "Logout", - "add_tip": "Add Tip", - "percentageOf": "от ${amount}", - "is_percentage": "е", - "search_category": "Търсене в категория", - "mark_as_redeemed": "Отбележи като използван", - "more_options": "Още настройки", - "awaiting_payment_confirmation": "Чака се потвърждение на плащането", - "transaction_sent_notice": "Ако процесът продължи повече от 1 минута, проверете някой block explorer и своя имейл.", - "agree": "Съгласен/а съм", - "in_store": "In Store", - "generating_gift_card": "Създаване на Gift Card", - "payment_was_received": "Плащането бе получено.", - "proceed_after_one_minute": "Ако процесът продължи повече от 1 минута, проверете своя имейл.", - "order_id": "ID на поръчка", - "gift_card_is_generated": "Gift Card бе създадена", - "open_gift_card": "Отвори Gift Card", - "contact_support": "Свържи се с отдел поддръжка", - "gift_cards_unavailable": "В момента гифткарти могат да бъдат закупени само с Monero, Bitcoin и Litecoin", - "introducing_cake_pay": "Запознайте се с Cake Pay!", - "cake_pay_learn_more": "Купете и използвайте гифткарти директно в приложението!\nПлъзнете отляво надясно, за да научите още.", - "automatic": "Автоматично", - "fixed_pair_not_supported": "Този fixed pair не се поддържа от избраната борса", - "variable_pair_not_supported": "Този variable pair не се поддържа от избраната борса", - "none_of_selected_providers_can_exchange": "Нито един от избраните provider-ъри не може да направи този превод", - "choose_one": "Изберете едно", - "choose_from_available_options": "Изберете от следните опции:", - "custom_redeem_amount": "Персонализирана сума за използване", - "add_custom_redemption": "Добавете персонализиран Redemption", - "remaining": "оставащи", - "delete_wallet": "Изтриване на портфейл", - "delete_wallet_confirm_message": "Сигурни ли сте, че искате да изтриете протфейла ${wallet_name}?", - "low_fee": "Ниска такса", - "low_fee_alert": "Използвате ниска приоритетност в мрежата. Това може да доведе до дълго чакане, различни обменни курсове или отказани сделки. Препоръчваме използването на по-висока такса.", - "ignor": "Игнориране", - "use_suggested": "Използване на предложеното", - "do_not_share_warning_text": "Не споделяйте това с никого, дори и отдел поддръжка.\n\nПарите Ви могат и ще бъдат откраднати!", - "help": "Помощ", - "all_transactions": "Всички транзакции", - "all_trades": "Всички сделкки", - "connection_sync": "Свързване и синхронизиране", - "security_and_backup": "Сигурност и резервни копия", - "create_backup": "Създаване на резервно копие", - "privacy_settings": "Настройки за поверителност", - "privacy": "Поверителност", - "display_settings": "Настройки на екрана", - "other_settings": "Други настройки", - "require_pin_after": "Въведете PIN след", - "always": "Винаги", - "minutes_to_pin_code": "${minute} минути", - "disable_exchange": "Деактивиране на борса", - "advanced_settings": "Разширени настройки", - "settings_can_be_changed_later": "Тези настройки могат да бъдат променени по-късно от приложението", - "add_custom_node": "Добавяне на нов персонализиран Node", - "disable_fiat": "Деактивиране на fiat", - "fiat_api": "Fiat API", - "disabled": "Деактивирано", - "enabled": "Активирано", - "tor_only": "Само чрез Tor", - "unmatched_currencies": "Валутата на този портфейл не съвпада с тази от сканирания QR код", - "orbot_running_alert": "Моля, включете Orbot преди да свържете към този node.", - "contact_list_contacts": "Контакти", - "contact_list_wallets": "Моите портфейли", - "bitcoin_payments_require_1_confirmation": "Плащанията с Bitcoin изискват потвърждение, което може да отнеме 20 минути или повече. Благодарим за търпението! Ще получите имейл, когато плащането е потвърдено.", - "send_to_this_address": "Send ${currency} ${tag}to this address", - "arrive_in_this_address": "${currency} ${tag}ще отидат на този адрес", - "do_not_send": "Не изпращай", - "error_dialog_content": "Получихме грешка.\n\nМоля, изпратете доклада до нашия отдел поддръжка, за да подобрим приложението.", - "decimal_places_error": "Твърде много знаци след десетичната запетая", - "edit_node": "Редактиране на възел", - "invoice_details": "IДанни за фактура", - "donation_link_details": "Подробности за връзката за дарение", - "anonpay_description": "Генерирайте ${type}. Получателят може да ${method} с всяка поддържана криптовалута и вие ще получите средства в този портфейл.", - "create_invoice": "Създайте фактура", - "create_donation_link": "Създайте връзка за дарение", - "optional_email_hint": "Незадължителен имейл за уведомяване на получателя", - "optional_description": "Описание по избор", - "optional_name": "Незадължително име на получател", - "clearnet_link": "Clearnet връзка", - "onion_link": "Лукова връзка", - "sell_monero_com_alert_content": "Продажбата на Monero все още не се поддържа", - "error_text_input_below_minimum_limit": "Сумата е по-малко от минималната", - "error_text_input_above_maximum_limit": "Сумата надвишава максималната", - "show_market_place": "Покажи пазар", - "prevent_screenshots": "Предотвратете екранни снимки и запис на екрана", - "profile": "Профил", - "close": "затвори", - "modify_2fa": "Модифициране на тортата 2FA", - "disable_cake_2fa": "Деактивирайте Cake 2FA", - "question_to_disable_2fa": "Сигурни ли сте, че искате да деактивирате Cake 2FA? Вече няма да е необходим 2FA код за достъп до портфейла и определени функции.", - "disable": "Деактивиране", - "setup_2fa": "Настройка на Cake 2FA", - "verify_with_2fa": "Проверете с Cake 2FA", - "totp_code": "TOTP код", - "please_fill_totp": "Моля, попълнете 8-цифрения код на другото ви устройство", - "totp_2fa_success": "Успех! Cake 2FA е активиран за този портфейл. Не забравяйте да запазите мнемоничното начало, в случай че загубите достъп до портфейла.", - "totp_verification_success": "Проверката е успешна!", - "totp_2fa_failure": "Грешен код. Моля, опитайте с различен код или генерирайте нов таен ключ. Използвайте съвместимо 2FA приложение, което поддържа 8-цифрени кодове и SHA512.", - "enter_totp_code": "Моля, въведете TOTP кода.", - "add_secret_code": "Или добавете този таен код към приложение за удостоверяване", - "totp_secret_code": "TOTP таен код", - "setup_2fa_text": "Cake 2FA работи с помощта на TOTP като втори фактор за удостоверяване.\n\nTOTP на Cake 2FA изисква SHA-512 и поддръжка на 8 цифри; това осигурява повишена сигурност. Повече информация и поддържани приложения можете да намерите в ръководството.", - "setup_totp_recommended": "Настройка на TOTP", - "disable_buy": "Деактивирайте действието за покупка", - "disable_sell": "Деактивирайте действието за продажба", - "auto_generate_subaddresses": "Автоматично генериране на подадреси", - "cake_2fa_preset": "Торта 2FA Preset", - "narrow": "Тесен", - "normal": "нормално", - "aggressive": "Прекалено усърден", - "require_for_assessing_wallet": "Изискване за достъп до портфейла", - "require_for_sends_to_non_contacts": "Изискване за изпращане до лица без контакт", - "require_for_sends_to_contacts": "Изискване за изпращане до контакти", - "require_for_sends_to_internal_wallets": "Изискване за изпращане до вътрешни портфейли", - "require_for_exchanges_to_internal_wallets": "Изискване за обмен към вътрешни портфейли", - "require_for_adding_contacts": "Изисква се за добавяне на контакти", - "require_for_creating_new_wallets": "Изискване за създаване на нови портфейли", - "require_for_all_security_and_backup_settings": "Изисква се за всички настройки за сигурност и архивиране", - "available_balance_description": "Това е балансът, който можете да използвате за покупка на криптовалути. Това не включва замразените средства.", - "syncing_wallet_alert_title": "Вашият портфейл се синхронизира", - "syncing_wallet_alert_content": "Списъкът ви с баланс и транзакции може да не е пълен, докато в горната част не пише „СИНХРОНИЗИРАН“. Кликнете/докоснете, за да научите повече.", - "home_screen_settings": "Настройки на началния екран", - "sort_by": "Сортирай по", - "search_add_token": "Търсене/Добавяне на токен", - "edit_token": "Редактиране на токена", - "warning": "Внимание", - "add_token_warning": "Не редактирайте и не добавяйте токени според инструкциите на измамниците.\nВинаги потвърждавайте адресите на токени с надеждни източници!", - "add_token_disclaimer_check": "Потвърдих адреса и информацията за токен договора, използвайки надежден източник. Добавянето на злонамерена или неправилна информация може да доведе до загуба на средства.", - "token_contract_address": "Адрес на токен договор", - "token_name": "Име на токена, напр.: Tether", - "token_symbol": "Символ на токена, напр.: USDT", - "token_decimal": "Токен десетичен", - "field_required": "Това поле е задължително", - "pin_at_top": "закачете ${token} отгоре", - "invalid_input": "Невалиден вход", - "fiat_balance": "Фиат Баланс", - "gross_balance": "Брутен баланс", - "alphabetical": "Азбучен ред", - "generate_name": "Генериране на име", - "balance_page": "Страница за баланс", - "share": "Дял", - "slidable": "Плъзгащ се", - "monero_dark_theme": "Тъмна тема Monero", - "bitcoin_dark_theme": "Тъмна тема за биткойн", - "bitcoin_light_theme": "Лека биткойн тема", - "high_contrast_theme": "Тема с висок контраст", - "matrix_green_dark_theme": "Зелена тъмна тема Matrix", - "monero_light_theme": "Лека тема Monero", - "etherscan_history": "История на Etherscan", - "template_name": "Име на шаблон", - "change_rep": "Смяна на представител", - "change_rep_message": "Сигурни ли сте, че искате да смените представителите?", - "manage_nodes": "Управление на възли", - "unsupported_asset": "Не поддържаме това действие за този актив. Моля, създайте или преминете към портфейл от поддържан тип актив.", - "manage_pow_nodes": "Управление на PoW възли", - "support_title_live_chat": "Подкрепа на живо", - "support_description_live_chat": "Безплатно и бързо! Обучени представители на подкрепата са на разположение за подпомагане", - "support_title_guides": "Ръководства за портфейл за торта", - "support_description_guides": "Документация и подкрепа за общи проблеми", - "support_title_other_links": "Други връзки за поддръжка", - "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи", - "choose_derivation": "Изберете производно на портфейла", - "new_first_wallet_text": "Лесно пазете криптовалутата си в безопасност", - "select_destination": "Моля, изберете дестинация за архивния файл.", - "save_to_downloads": "Запазване в Изтегляния", - "select_buy_provider_notice": "Изберете доставчик на покупка по -горе. Можете да пропуснете този екран, като зададете вашия доставчик по подразбиране по подразбиране в настройките на приложението.", - "onramper_option_description": "Бързо купувайте криптовалута с много методи за плащане. Предлага се в повечето страни. Разпространенията и таксите варират.", - "default_buy_provider": "Доставчик по подразбиране купува", - "ask_each_time": "Питайте всеки път", - "buy_provider_unavailable": "Понастоящем доставчик не е наличен.", - "signTransaction": "Подпишете транзакция", - "errorGettingCredentials": "Неуспешно: Грешка при получаване на идентификационни данни", - "errorSigningTransaction": "Възникна грешка при подписване на транзакция", - "pairingInvalidEvent": "Невалидно събитие при сдвояване", - "chains": "Вериги", - "methods": "Методи", - "events": "събития", - "reject": "Отхвърляне", - "approve": "Одобряване", - "expiresOn": "Изтича на", - "walletConnect": "WalletConnect", - "nullURIError": "URI е нула", - "connectWalletPrompt": "Свържете портфейла си с WalletConnect, за да извършвате транзакции", - "newConnection": "Нова връзка", - "activeConnectionsPrompt": "Тук ще се появят активни връзки", - "deleteConnectionConfirmationPrompt": "Сигурни ли сте, че искате да изтриете връзката към", - "event": "Събитие", - "successful": "Успешен", - "wouoldLikeToConnect": "иска да се свърже", - "message": "Съобщение", - "do_not_have_enough_gas_asset": "Нямате достатъчно ${currency}, за да извършите транзакция с текущите условия на блокчейн мрежата. Имате нужда от повече ${currency}, за да платите таксите за блокчейн мрежа, дори ако изпращате различен актив.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Моля, изчакайте dApp да завърши обработката.", - "copyWalletConnectLink": "Копирайте връзката WalletConnect от dApp и я поставете тук", - "enterWalletConnectURI": "Въведете URI на WalletConnect", - "seed_key": "Ключ за семена", - "enter_seed_phrase": "Въведете вашата фраза за семена", - "change_rep_successful": "Успешно промени представител", - "add_contact": "Добави контакт", - "exchange_provider_unsupported": "${providerName} вече не се поддържа!", - "domain_looks_up": "Търсене на домейни", - "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", - "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", - "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", - "order_by": "Подредени по", - "creation_date": "Дата на създаване", - "group_by_type": "Група по вид", - "importNFTs": "Импортирайте NFT", - "noNFTYet": "Все още няма NFT", - "address": "Адрес", - "enterTokenID": "Въведете идентификатора на токена", - "tokenID": "документ за самоличност", - "name": "Име", - "symbol": "Символ", - "seed_phrase_length": "Дължина на началната фраза", - "unavailable_balance": "Неналично салдо", - "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", - "unspent_change": "Промяна", - "tor_connection": "Tor връзка", - "setup_warning_2fa_text": "Cake 2FA е второ удостоверяване за определени действия в портфейла. НЕ е толкова сигурно, колкото хладилното съхранение.\n\nАко загубите достъп до вашето 2FA приложение или TOTP ключове, ЩЕ загубите достъп до този портфейл. Ще трябва да възстановите портфейла си от мнемоничното семе.\n\nПоддръжката на Cake няма да може да ви помогне, ако загубите достъп до вашите 2FA или мнемонични семена.\nПреди да използвате Cake 2FA, препоръчваме да прочетете ръководството.", - "scan_qr_on_device": "Сканирайте този QR код на друго устройство", - "how_to_use": "Как да използвам", - "seed_hex_form": "Семена от портфейл (шестнадесетична форма)", - "seedtype": "Семенна тип", - "seedtype_legacy": "Наследство (25 думи)", - "seedtype_polyseed": "Поли семе (16 думи)", - "seed_language_czech": "Чех", - "seed_language_korean": "Корейски", - "seed_language_chinese_traditional": "Традиционен китайски)", - "ascending": "Възходящ", - "descending": "Низходящ", - "dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа", - "polygonscan_history": "История на PolygonScan", - "wallet_seed_legacy": "Наследено портфейл семе", - "default_sell_provider": "Доставчик за продажба по подразбиране", - "select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.", - "custom_drag": "Персонализиране (задръжте и плъзнете)", - "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)", - "use_testnet": "Използвайте TestNet", - "receivable_balance": "Баланс за вземания", - "confirmed_tx": "Потвърдено", - "transaction_details_source_address": "Адрес на източника", - "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза.", - "contractName": "Име на договора", - "contractSymbol": "Договор Символ", - "description": "Описание", - "camera_consent": "Вашият фотоапарат ще бъде използван за заснемане на изображение с цел идентификация от ${provider}. Моля, проверете тяхната политика за поверителност за подробности.", - "no_relays": "Без релета", - "choose_relay": "Моля, изберете реле, което да използвате", - "no_relays_message": "Намерихме запис Nostr NIP-05 за този потребител, но той не съдържа релета. Моля, инструктирайте получателя да добави релета към своя Nostr запис.", - "no_relay_on_domain": "Няма реле за домейна на потребителя или релето не е налично. Моля, изберете реле, което да използвате." - "zzzz": "zzzz" + "you_will_send": "Обръщане от" } \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 6de1ab654..be36f3d28 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -708,6 +708,7 @@ "use_card_info_two": "Prostředky jsou převedeny na USD, když jsou drženy na předplaceném účtu, nikoliv na digitální měnu.", "use_ssl": "Použít SSL", "use_suggested": "Použít doporučený", + "use_testnet": "Použijte testNet", "variable_pair_not_supported": "Tento pár s tržním kurzem není ve zvolené směnárně podporován", "verification": "Ověření", "verify_with_2fa": "Ověřte pomocí Cake 2FA", @@ -766,273 +767,5 @@ "you_now_have_debit_card": "Nyní máte debetní kartu", "you_pay": "Zaplatíte", "you_will_get": "Směnit na", - "you_will_send": "Směnit z", - "yy": "YY", - "online": "Online", - "offline": "Offline", - "gift_card_number": "Číslo dárkové karty", - "pin_number": "Číslo PIN", - "total_saving": "Celkem ušetřeno", - "last_30_days": "Posledních 30 dnů", - "avg_savings": "Prům. ušetřeno", - "view_all": "Zobrazit vše", - "active_cards": "Aktivní karty", - "delete_account": "Smazat účet", - "cards": "Karty", - "active": "Aktivní", - "redeemed": "Uplatněné", - "gift_card_balance_note": "Dárkové karty se zbývající částkou se zobrazí zde", - "gift_card_redeemed_note": "Dárkové karty, které jste uplatnili, se zobrazí zde", - "logout": "Odhlásit", - "add_tip": "Přidat spropitné", - "percentageOf": "z ${amount}", - "is_percentage": "je", - "search_category": "Hledat kategorii", - "mark_as_redeemed": "Označit jako uplatněný", - "more_options": "Více možností", - "awaiting_payment_confirmation": "Čeká se na potvrzení platby", - "transaction_sent_notice": "Pokud proces nepokročí během 1 minuty, zkontrolujte block explorer a svůj e-mail.", - "agree": "Souhlasím", - "in_store": "V obchodě", - "generating_gift_card": "Generuji dárkovou kartu", - "payment_was_received": "Vaše platba byla přijata.", - "proceed_after_one_minute": "Pokud proces nepokročí během 1 minuty, zkontrolujte svůj e-mail.", - "order_id": "ID objednávky", - "gift_card_is_generated": "Generuje se dárková karta", - "open_gift_card": "Otevřít dárkovou kartu", - "contact_support": "Kontaktovat podporu", - "gift_cards_unavailable": "Dárkové karty jsou v tuto chvíli dostupné pro zakoupení pouze pomocí Monera, Bitcoinu a Litecoinu.", - "introducing_cake_pay": "Představujeme Cake Pay!", - "cake_pay_learn_more": "Okamžitý nákup a uplatnění dárkových karet v aplikaci!\nPřejeďte prstem zleva doprava pro další informace.", - "automatic": "Automatický", - "fixed_pair_not_supported": "Tento pár s pevným kurzem není ve zvolené směnárně podporován", - "variable_pair_not_supported": "Tento pár s tržním kurzem není ve zvolené směnárně podporován", - "none_of_selected_providers_can_exchange": "Žádný ze zvolených poskytovatelů nemůže provést tuto směnu", - "choose_one": "Zvolte si", - "choose_from_available_options": "Zvolte si z dostupných možností:", - "custom_redeem_amount": "Vlastní částka pro uplatnění", - "add_custom_redemption": "Přidat vlastní uplatnění", - "remaining": "zbývá", - "delete_wallet": "Smazat peněženku", - "delete_wallet_confirm_message": "Opravdu chcete smazat ${wallet_name} peněženku?", - "low_fee": "Nízký poplatek", - "low_fee_alert": "Momentálně máte nastavené nízké poplatky pro transakce. To může způsobovat dlouhé čekání, změnu směnného kurzu, nebo zrušení směny. Doporučujeme nastavit vyšší poplatek.", - "ignor": "Ignorovat", - "use_suggested": "Použít doporučený", - "do_not_share_warning_text": "Toto nesdílejte s nikým jiným, ani s podporou.\n\nJinak mohou být Vaše prostředky ukradeny!", - "help": "pomoc", - "all_transactions": "Všechny transakce", - "all_trades": "Všechny obchody", - "connection_sync": "Připojení a synch.", - "security_and_backup": "Bezpečnost a zálohy", - "create_backup": "Vytvořit zálohu", - "privacy_settings": "Nastavení soukromí", - "privacy": "Soukromí", - "display_settings": "Nastavení zobrazení", - "other_settings": "Další nastavení", - "require_pin_after": "Vyžadovat PIN po", - "always": "Vždy", - "minutes_to_pin_code": "${minute} minutách", - "disable_exchange": "Zakázat směnárny", - "advanced_settings": "Pokročilé nastavení", - "settings_can_be_changed_later": "Tato nastavení mohou být změněna později v nastavení v této aplikaci", - "add_custom_node": "Přidat vlastní uzel", - "disable_fiat": "Zakázat fiat", - "fiat_api": "Fiat API", - "disabled": "Zakázáno", - "enabled": "Povoleno", - "tor_only": "Pouze Tor", - "unmatched_currencies": "Měna vaší současné peněženky neodpovídá té v naskenovaném QR kódu", - "orbot_running_alert": "Prosím ujistěte se, že je Orbot spuštěný, před tím, než se připojíte k tomuto uzlu.", - "contact_list_contacts": "Kontakty", - "contact_list_wallets": "Moje peněženky", - "bitcoin_payments_require_1_confirmation": "U plateb Bitcoinem je vyžadováno alespoň 1 potvrzení, což může trvat 20 minut i déle. Děkujeme za vaši trpělivost! Až bude platba potvrzena, budete informováni e-mailem.", - "send_to_this_address": "Poslat ${currency} ${tag}na tuto adresu", - "arrive_in_this_address": "${currency} ${tag}přijde na tuto adresu", - "do_not_send": "Neodesílat", - "error_dialog_content": "Nastala chyba.\n\nProsím odešlete zprávu o chybě naší podpoře, aby mohli zajistit opravu.", - "decimal_places_error": "Příliš mnoho desetinných míst", - "edit_node": "Upravit uzel", - "invoice_details": "detaily faktury", - "donation_link_details": "Podrobnosti odkazu na darování", - "anonpay_description": "Vygenerujte ${type}. Příjemce může ${method} s jakoukoli podporovanou kryptoměnou a vy obdržíte prostředky v této peněžence.", - "create_invoice": "Vytvořit fakturu", - "create_donation_link": "Vytvořit odkaz na darování", - "optional_email_hint": "Volitelný e-mail s upozorněním na příjemce platby", - "optional_description": "Volitelný popis", - "optional_name": "Volitelné jméno příjemce", - "clearnet_link": "Odkaz na Clearnet", - "onion_link": "Cibulový odkaz", - "sell_monero_com_alert_content": "Prodej Monero zatím není podporován", - "error_text_input_below_minimum_limit": "Částka je menší než minimální hodnota", - "error_text_input_above_maximum_limit": "Částka je větší než maximální hodnota", - "show_market_place": "Zobrazit trh", - "prevent_screenshots": "Zabránit vytváření snímků obrazovky a nahrávání obrazovky", - "profile": "Profil", - "close": "zavřít", - "modify_2fa": "Upravte Cake 2FA", - "disable_cake_2fa": "Zakázat Cake 2FA", - "question_to_disable_2fa": "Opravdu chcete deaktivovat Cake 2FA? Pro přístup k peněžence a některým funkcím již nebude potřeba kód 2FA.", - "disable": "Zakázat", - "setup_2fa": "Nastavení Cake 2FA", - "verify_with_2fa": "Ověřte pomocí Cake 2FA", - "totp_code": "Kód TOTP", - "please_fill_totp": "Vyplňte prosím 8místný kód na vašem druhém zařízení", - "totp_2fa_success": "Úspěch! Pro tuto peněženku povolen Cake 2FA. Nezapomeňte si uložit mnemotechnický klíč pro případ, že ztratíte přístup k peněžence.", - "totp_verification_success": "Ověření proběhlo úspěšně!", - "totp_2fa_failure": "Nesprávný kód. Zkuste prosím jiný kód nebo vygenerujte nový tajný klíč. Použijte kompatibilní aplikaci 2FA, která podporuje 8místné kódy a SHA512.", - "enter_totp_code": "Zadejte kód TOTP.", - "add_secret_code": "Nebo přidejte tento tajný kód do ověřovací aplikace", - "totp_secret_code": "Tajný kód TOTP", - "setup_2fa_text": "Cake 2FA pracuje s použitím TOTP jako druhého autentizačního faktoru.\n\nTOTP Cake 2FA vyžaduje SHA-512 a podporu 8 číslic; to poskytuje zvýšenou bezpečnost. Další informace a podporované aplikace naleznete v průvodci.", - "setup_totp_recommended": "Nastavení TOTP", - "disable_buy": "Zakázat akci nákupu", - "disable_sell": "Zakázat akci prodeje", - "auto_generate_subaddresses": "Automaticky generovat podadresy", - "cake_2fa_preset": "Předvolba Cake 2FA", - "narrow": "Úzký", - "normal": "Normální", - "aggressive": "Agresivní", - "require_for_assessing_wallet": "Vyžadovat pro přístup k peněžence", - "require_for_sends_to_non_contacts": "Vyžadovat pro odesílání nekontaktním osobám", - "require_for_sends_to_contacts": "Vyžadovat pro odeslání kontaktům", - "require_for_sends_to_internal_wallets": "Vyžadovat pro odesílání do interních peněženek", - "require_for_exchanges_to_internal_wallets": "Vyžadovat pro výměny do interních peněženek", - "require_for_adding_contacts": "Vyžadovat pro přidání kontaktů", - "require_for_creating_new_wallets": "Vyžadovat pro vytváření nových peněženek", - "require_for_all_security_and_backup_settings": "Vyžadovat všechna nastavení zabezpečení a zálohování", - "available_balance_description": "Dostupná částka je částka, kterou můžete okamžitě utratit. Zmrazená částka je částka, která ještě není k dispozici, protože ještě nebyla potvrzena síťovým protokolem.", - "syncing_wallet_alert_title": "Vaše peněženka se synchronizuje", - "syncing_wallet_alert_content": "Váš seznam zůstatků a transakcí nemusí být úplný, dokud nebude nahoře uvedeno „SYNCHRONIZOVANÉ“. Kliknutím/klepnutím se dozvíte více.", - "home_screen_settings": "Nastavení domovské obrazovky", - "sort_by": "Seřazeno podle", - "search_add_token": "Hledat / Přidat token", - "edit_token": "Upravit token", - "warning": "Varování", - "add_token_warning": "Neupravujte ani nepřidávejte tokeny podle pokynů podvodníků.\nVždy potvrďte adresy tokenů s renomovanými zdroji!", - "add_token_disclaimer_check": "Potvrdil jsem adresu a informace smlouvy o tokenu pomocí důvěryhodného zdroje. Přidání škodlivých nebo nesprávných informací může vést ke ztrátě finančních prostředků.", - "token_contract_address": "Adresa tokenové smlouvy", - "token_name": "Název tokenu např.: Tether", - "token_symbol": "Symbol tokenu, např.: USDT", - "token_decimal": "Token v desítkové soustavě", - "field_required": "Toto pole je povinné", - "pin_at_top": "špendlík ${token} nahoře", - "invalid_input": "Neplatný vstup", - "fiat_balance": "Fiat Balance", - "gross_balance": "Hrubý zůstatek", - "alphabetical": "Abecední", - "generate_name": "Generovat jméno", - "balance_page": "Stránka zůstatku", - "share": "Podíl", - "slidable": "Posuvné", - "monero_dark_theme": "Tmavé téma Monero", - "bitcoin_dark_theme": "Tmavé téma bitcoinů", - "bitcoin_light_theme": "Světlé téma bitcoinů", - "high_contrast_theme": "Téma s vysokým kontrastem", - "matrix_green_dark_theme": "Tmavé téma Matrix Green", - "monero_light_theme": "Světlé téma Monero", - "manage_nodes": "Spravovat uzly", - "etherscan_history": "Historie Etherscanu", - "template_name": "Název šablony", - "change_rep": "Změna zástupce", - "change_rep_message": "Jste si jisti, že chcete změnit zástupce?", - "unsupported_asset": "Tuto akci u tohoto díla nepodporujeme. Vytvořte nebo přepněte na peněženku podporovaného typu aktiv.", - "manage_pow_nodes": "Správa uzlů PoW", - "support_title_live_chat": "Živá podpora", - "support_description_live_chat": "Zdarma a rychle! K dispozici jsou zástupci vyškolených podpůrných podpory", - "support_title_guides": "Průvodce peněženkami dortu", - "support_description_guides": "Dokumentace a podpora běžných otázek", - "support_title_other_links": "Další odkazy na podporu", - "support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody", - "choose_derivation": "Vyberte derivaci peněženky", - "new_first_wallet_text": "Snadno udržujte svou kryptoměnu v bezpečí", - "select_destination": "Vyberte cíl pro záložní soubor.", - "save_to_downloads": "Uložit do Stažených souborů", - "select_buy_provider_notice": "Vyberte výše uvedeného poskytovatele nákupu. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele nákupu v nastavení aplikace.", - "onramper_option_description": "Rychle si koupte krypto s mnoha metodami plateb. K dispozici ve většině zemí. Rozpětí a poplatky se liší.", - "default_buy_provider": "Výchozí poskytovatel nákupu", - "ask_each_time": "Zeptejte se pokaždé", - "buy_provider_unavailable": "Poskytovatel aktuálně nedostupný.", - "signTransaction": "Podepsat transakci", - "errorGettingCredentials": "Selhalo: Chyba při získávání přihlašovacích údajů", - "errorSigningTransaction": "Při podepisování transakce došlo k chybě", - "pairingInvalidEvent": "Neplatná událost párování", - "chains": "Řetězy", - "methods": "Metody", - "events": "Události", - "reject": "Odmítnout", - "approve": "Schvalovat", - "expiresOn": "Vyprší dne", - "walletConnect": "WalletConnect", - "nullURIError": "URI je nulové", - "connectWalletPrompt": "Propojte svou peněženku s WalletConnect a provádějte transakce", - "newConnection": "Nové připojení", - "activeConnectionsPrompt": "Zde se zobrazí aktivní připojení", - "deleteConnectionConfirmationPrompt": "Jste si jisti, že chcete smazat připojení k?", - "event": "událost", - "successful": "Úspěšný", - "wouoldLikeToConnect": "by se chtělo připojit", - "message": "Zpráva", - "do_not_have_enough_gas_asset": "Nemáte dostatek ${currency} k provedení transakce s aktuálními podmínkami blockchainové sítě. K placení poplatků za blockchainovou síť potřebujete více ${currency}, i když posíláte jiné aktivum.", - "totp_auth_url": "URL AUTH TOTP", - "awaitDAppProcessing": "Počkejte, až dApp dokončí zpracování.", - "copyWalletConnectLink": "Zkopírujte odkaz WalletConnect z dApp a vložte jej sem", - "enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect", - "seed_key": "Klíč semen", - "enter_seed_phrase": "Zadejte svou frázi semen", - "change_rep_successful": "Úspěšně změnil zástupce", - "add_contact": "Přidat kontakt", - "exchange_provider_unsupported": "${providerName} již není podporováno!", - "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", - "order_by": "Seřadit podle", - "creation_date": "Datum vzniku", - "group_by_type": "Skupina podle typu", - "importNFTs": "Importujte NFT", - "noNFTYet": "Zatím žádné NFT", - "address": "Adresa", - "enterTokenID": "Zadejte ID tokenu", - "tokenID": "ID", - "name": "název", - "symbol": "Symbol", - "seed_phrase_length": "Délka fráze semene", - "unavailable_balance": "Nedostupný zůstatek", - "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", - "unspent_change": "Změna", - "tor_connection": "Připojení Tor", - "setup_warning_2fa_text": "Budete muset obnovit svou peněženku z mnemotechnického semínka.\n\nPodpora dortů vám nebude schopna pomoci, pokud ztratíte přístup ke svým 2FA nebo mnemotechnickým semenům.\nCake 2FA je druhá autentizace pro určité akce v peněžence. Před použitím Cake 2FA doporučujeme přečíst si průvodce.NENÍ tak bezpečný jako skladování v chladu.\n\nPokud ztratíte přístup ke své aplikaci 2FA nebo klíčům TOTP, ztratíte přístup k této peněžence. ", - "scan_qr_on_device": "Naskenujte tento QR kód na jiném zařízení", - "how_to_use": "Jak používat", - "seed_hex_form": "Semeno peněženky (hex formulář)", - "seedtype": "SeedType", - "seedtype_legacy": "Legacy (25 slov)", - "seedtype_polyseed": "Polyseed (16 slov)", - "seed_language_czech": "čeština", - "seed_language_korean": "korejština", - "seed_language_chinese_traditional": "Číňan (tradiční)", - "ascending": "Vzestupné", - "descending": "Klesající", - "dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě", - "polygonscan_history": "Historie PolygonScan", - "wallet_seed_legacy": "Starší semeno peněženky", - "default_sell_provider": "Výchozí poskytovatel prodeje", - "select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.", - "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", - "use_testnet": "Použijte testNet", - "receivable_balance": "Zůstatek pohledávek", - "confirmed_tx": "Potvrzeno", - "transaction_details_source_address": "Zdrojová adresa", - "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena.", - "contractName": "Název smlouvy", - "contractSymbol": "Symbol smlouvy", - "description": "Popis", - "camera_consent": "Váš fotoaparát použije k pořízení snímku pro účely identifikace ${provider}. Podrobnosti najdete v jejich Zásadách ochrany osobních údajů.", - "no_relays": "Žádná relé", - "choose_relay": "Vyberte relé, které chcete použít", - "no_relays_message": "Pro tohoto uživatele jsme našli záznam Nostr NIP-05, který však neobsahuje žádná relé. Požádejte příjemce, aby přidal přenosy do svého záznamu Nostr.", - "no_relay_on_domain": "Pro doménu uživatele neexistuje přenos nebo je přenos nedostupný. Vyberte relé, které chcete použít." - "zzzz": "Zzzz" + "you_will_send": "Směnit z" } \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 5654be302..9c1102261 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -715,6 +715,7 @@ "use_card_info_two": "Guthaben werden auf dem Prepaid-Konto in USD umgerechnet, nicht in digitale Währung.", "use_ssl": "SSL verwenden", "use_suggested": "Vorgeschlagen verwenden", + "use_testnet": "TESTNET verwenden", "variable_pair_not_supported": "Dieses Variablenpaar wird von den ausgewählten Börsen nicht unterstützt", "verification": "Verifizierung", "verify_with_2fa": "Verifizieren Sie mit Cake 2FA", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "Sie haben jetzt eine Debitkarte", "you_pay": "Sie bezahlen", "you_will_get": "Konvertieren zu", - "you_will_send": "Konvertieren von", - "yy": "YY", - "online": "online", - "offline": "offline", - "gift_card_number": "Geschenkkartennummer", - "pin_number": "PIN-Nummer", - "total_saving": "Gesamteinsparungen", - "last_30_days": "Letzte 30 Tage", - "avg_savings": "Durchschn. Einsparungen", - "view_all": "Alle anzeigen", - "active_cards": "Aktive Karten", - "delete_account": "Konto löschen", - "cards": "Karten", - "active": "Aktiv", - "redeemed": "Versilbert", - "gift_card_balance_note": "Geschenkkarten mit Restguthaben erscheinen hier", - "gift_card_redeemed_note": "Gutscheine, die Sie eingelöst haben, werden hier angezeigt", - "logout": "Abmelden", - "add_tip": "Tipp hinzufügen", - "percentageOf": "von ${amount}", - "is_percentage": "ist", - "search_category": "Suchkategorie", - "mark_as_redeemed": "Als eingelöst markieren", - "more_options": "Weitere Optionen", - "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung", - "transaction_sent_notice": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie einen Block-Explorer und Ihre E-Mail.", - "agree": "stimme zu", - "in_store": "Im Geschäft", - "generating_gift_card": "Geschenkkarte wird erstellt", - "payment_was_received": "Ihre Zahlung ist eingegangen.", - "proceed_after_one_minute": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie bitte Ihre E-Mail.", - "order_id": "Bestell-ID", - "gift_card_is_generated": "Geschenkkarte wird generiert", - "open_gift_card": "Geschenkkarte öffnen", - "contact_support": "Support kontaktieren", - "gift_cards_unavailable": "Geschenkkarten können derzeit nur über Monero, Bitcoin und Litecoin erworben werden", - "background_sync_mode": "Hintergrundsynchronisierungsmodus", - "sync_all_wallets": "Alle Wallets synchronisieren", - "introducing_cake_pay": "Einführung von Cake Pay!", - "cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.", - "automatic": "Automatisch", - "fixed_pair_not_supported": "Dieses feste Paar wird von den ausgewählten Vermittlungsstellen nicht unterstützt", - "variable_pair_not_supported": "Dieses Variablenpaar wird von den ausgewählten Börsen nicht unterstützt", - "none_of_selected_providers_can_exchange": "Keiner der ausgewählten Anbieter kann diesen Austausch vornehmen", - "choose_one": "Wähle ein", - "choose_from_available_options": "Wähle aus verfügbaren Optionen:", - "custom_redeem_amount": "Benutzerdefinierter Einlösungsbetrag", - "add_custom_redemption": "Benutzerdefinierte Einlösung hinzufügen", - "remaining": "Rest", - "delete_wallet": "Wallet löschen", - "delete_wallet_confirm_message": "Sind Sie sicher, dass Sie das ${wallet_name} Wallet löschen möchten?", - "low_fee": "Niedrige Gebühr", - "low_fee_alert": "Sie verwenden derzeit eine niedrige Netzwerkgebührenpriorität. Dies kann zu langen Wartezeiten, unterschiedlichen Kursen oder stornierten Trades führen. Wir empfehlen, für ein besseres Erlebnis eine höhere Gebühr festzulegen.", - "ignor": "Ignorieren", - "use_suggested": "Vorgeschlagen verwenden", - "do_not_share_warning_text": "Teilen Sie diese nicht mit anderen, einschließlich Support.\n\nIhr Geld kann und wird gestohlen werden!", - "help": "hilfe", - "all_transactions": "Alle Transaktionen", - "all_trades": "Alle Trades", - "connection_sync": "Verbindung und Synchronisierung", - "security_and_backup": "Sicherheit und Datensicherung", - "create_backup": "Backup erstellen", - "privacy_settings": "Datenschutzeinstellungen", - "privacy": "Datenschutz", - "display_settings": "Anzeigeeinstellungen", - "other_settings": "Andere Einstellungen", - "require_pin_after": "PIN anfordern nach", - "always": "immer", - "minutes_to_pin_code": "${minute} Minuten", - "disable_exchange": "Exchange deaktivieren", - "advanced_settings": "Erweiterte Einstellungen", - "settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden", - "add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen", - "disable_fiat": "Fiat deaktivieren", - "fiat_api": "Fiat API", - "disabled": "Deaktiviert", - "enabled": "Ermöglicht", - "tor_only": "Nur Tor", - "unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein", - "orbot_running_alert": "Bitte stellen Sie sicher, dass Orbot läuft, bevor Sie sich mit diesem Knoten verbinden.", - "contact_list_contacts": "Kontakte", - "contact_list_wallets": "Meine Wallets", - "bitcoin_payments_require_1_confirmation": "Bitcoin-Zahlungen erfordern 1 Bestätigung, was 20 Minuten oder länger dauern kann. Danke für Ihre Geduld! Sie erhalten eine E-Mail, wenn die Zahlung bestätigt ist.", - "send_to_this_address": "Senden Sie ${currency} ${tag}an diese Adresse", - "arrive_in_this_address": "${currency} ${tag}wird an dieser Adresse ankommen", - "do_not_send": "Nicht senden", - "error_dialog_content": "Hoppla, wir haben einen Fehler.\n\nBitte senden Sie den Absturzbericht an unser Support-Team, um die Anwendung zu verbessern.", - "scan_qr_code": "QR-Code scannen", - "cold_or_recover_wallet": "Fügen Sie eine Cold Wallet hinzu oder stellen Sie eine Paper Wallet wieder her", - "please_wait": "Warten Sie mal", - "sweeping_wallet": "Wallet leeren", - "sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE GELDER VERLOREN GEHEN", - "decimal_places_error": "Zu viele Nachkommastellen", - "edit_node": "Knoten bearbeiten", - "invoice_details": "Rechnungs-Details", - "donation_link_details": "Details zum Spendenlink", - "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.", - "create_invoice": "Rechnung erstellen", - "create_donation_link": "Spendenlink erstellen", - "optional_email_hint": "Optionale Benachrichtigungs-E-Mail für den Zahlungsempfänger", - "optional_description": "Optionale Beschreibung", - "optional_name": "Optionaler Empfängername", - "clearnet_link": "Clearnet-Link", - "onion_link": "Zwiebel-Link", - "settings": "Einstellungen", - "sell_monero_com_alert_content": "Der Verkauf von Monero wird noch nicht unterstützt", - "error_text_input_below_minimum_limit": "Menge ist unter dem Minimum", - "error_text_input_above_maximum_limit": "Menge ist über dem Maximum", - "show_market_place": "Marktplatz anzeigen", - "prevent_screenshots": "Verhindern Sie Screenshots und Bildschirmaufzeichnungen", - "profile": "Profil", - "close": "Schließen", - "modify_2fa": "Cake 2FA ändern", - "disable_cake_2fa": "Cake 2FA deaktivieren", - "question_to_disable_2fa": "Sind Sie sicher, dass Sie Cake 2FA deaktivieren möchten? Für den Zugriff auf die Wallet und bestimmte Funktionen wird kein 2FA-Code mehr benötigt.", - "disable": "Deaktivieren", - "setup_2fa": "Setup-Cake 2FA", - "verify_with_2fa": "Verifizieren Sie mit Cake 2FA", - "totp_code": "TOTP-Code", - "please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät vorhanden ist", - "totp_2fa_success": "Erfolg! Cake 2FA für dieses Wallet aktiviert. Denken Sie daran, Ihren mnemonischen Seed zu speichern, falls Sie den Zugriff auf die Wallet verlieren.", - "totp_verification_success": "Verifizierung erfolgreich!", - "totp_2fa_failure": "Falscher Code. Bitte versuchen Sie es mit einem anderen Code oder generieren Sie einen neuen geheimen Schlüssel. Verwenden Sie eine kompatible 2FA-App, die 8-stellige Codes und SHA512 unterstützt.", - "enter_totp_code": "Bitte geben Sie den TOTP-Code ein.", - "add_secret_code": "Oder fügen Sie diesen Geheimcode einer Authentifizierungs-App hinzu", - "totp_secret_code": "TOTP-Geheimcode", - "setup_2fa_text": "Cake 2FA verwendet TOTP als zweiten Authentifizierungsfaktor.\n\nDas TOTP von Cake 2FA erfordert SHA-512 und 8-stellige Unterstützung; Dies sorgt für erhöhte Sicherheit. Weitere Informationen und unterstützte Apps finden Sie im Leitfaden.", - "setup_totp_recommended": "TOTP einrichten", - "disable_buy": "Kaufaktion deaktivieren", - "disable_sell": "Verkaufsaktion deaktivieren", - "cake_2fa_preset": "Kuchen 2FA-Voreinstellung", - "monero_dark_theme": "Dunkles Monero-Thema", - "bitcoin_dark_theme": "Dunkles Bitcoin-Thema", - "bitcoin_light_theme": "Bitcoin Light-Thema", - "high_contrast_theme": "Kontrastreiches Thema", - "matrix_green_dark_theme": "Matrix Green Dark Theme", - "monero_light_theme": "Monero Light-Thema", - "auto_generate_subaddresses": "Unteradressen automatisch generieren", - "narrow": "Eng", - "normal": "Normal", - "aggressive": "Übereifrig", - "require_for_assessing_wallet": "Für den Zugriff auf die Wallet erforderlich", - "require_for_sends_to_non_contacts": "Erforderlich für Versendungen an Nichtkontakte", - "require_for_sends_to_contacts": "Erforderlich für Versendungen an Kontakte", - "require_for_sends_to_internal_wallets": "Erforderlich für Sendungen an interne Wallets", - "require_for_exchanges_to_internal_wallets": "Erforderlich für den Umtausch in interne Wallets", - "require_for_adding_contacts": "Erforderlich zum Hinzufügen von Kontakten", - "require_for_creating_new_wallets": "Erforderlich zum Erstellen neuer Wallets", - "require_for_all_security_and_backup_settings": "Für alle Sicherheits- und Sicherungseinstellungen erforderlich", - "available_balance_description": "Verfügbarer Saldo ist der Betrag, den Sie sofort ausgeben können. Dieser Betrag kann sich ändern, wenn Sie eine Transaktion senden oder empfangen.", - "syncing_wallet_alert_title": "Ihr Wallet wird synchronisiert", - "syncing_wallet_alert_content": "Ihr Kontostand und Ihre Transaktionsliste sind möglicherweise erst vollständig, wenn oben „SYNCHRONISIERT“ steht. Klicken/tippen Sie, um mehr zu erfahren.", - "home_screen_settings": "Einstellungen für den Startbildschirm", - "sort_by": "Sortiere nach", - "search_add_token": "Token suchen / hinzufügen", - "edit_token": "Token bearbeiten", - "warning": "Warnung", - "add_token_warning": "Bearbeiten oder fügen Sie Token nicht gemäß den Anweisungen von Betrügern hinzu.\nBestätigen Sie Token-Adressen immer mit seriösen Quellen!", - "add_token_disclaimer_check": "Ich habe die Adresse und Informationen zum Token-Vertrag anhand einer seriösen Quelle bestätigt. Das Hinzufügen böswilliger oder falscher Informationen kann zu einem Verlust von Geldern führen.", - "token_contract_address": "Token-Vertragsadresse", - "token_name": "Token-Name, z. B.: Tether", - "token_symbol": "Token-Symbol, z. B.: USDT", - "token_decimal": "Token-Dezimalzahl", - "field_required": "Dieses Feld ist erforderlich", - "pin_at_top": "Stecken Sie ${token} oben fest", - "invalid_input": "Ungültige Eingabe", - "fiat_balance": "Fiat Balance", - "gross_balance": "Bruttosaldo", - "alphabetical": "Alphabetisch", - "generate_name": "Namen generieren", - "balance_page": "Balance-Seite", - "share": "Teilen", - "slidable": "Verschiebbar", - "manage_nodes": "Knoten verwalten", - "etherscan_history": "Etherscan-Geschichte", - "template_name": "Vorlagenname", - "change_rep": "Change-Beauftragter", - "change_rep_message": "Sind Sie sicher, dass Sie den Vertreter wechseln möchten?", - "unsupported_asset": "Wir unterstützen diese Aktion für dieses Asset nicht. Bitte erstellen Sie eine Wallet eines unterstützten Asset-Typs oder wechseln Sie zu einer Wallet.", - "manage_pow_nodes": "PoW-Knoten verwalten", - "support_title_live_chat": "Live Support", - "support_description_live_chat": "Kostenlos und schnell! Ausgebildete Mitarbeiter stehen zur Unterstützung bereit, um zu helfen", - "support_title_guides": "Cake Wallet Guides", - "support_description_guides": "Dokumentation und Hilfe für bekannte Probleme", - "support_title_other_links": "Andere Support-Links", - "support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden", - "choose_derivation": "Wählen Sie Brieftaschenableitung", - "new_first_wallet_text": "Bewahren Sie Ihre Kryptowährung einfach sicher auf", - "select_destination": "Bitte wählen Sie das Ziel für die Sicherungsdatei aus.", - "save_to_downloads": "Unter „Downloads“ speichern", - "select_buy_provider_notice": "Wählen Sie oben einen Anbieter kaufen. Sie können diese Seite überspringen, indem Sie Ihren Standard-Kaufanbieter in den App-Einstellungen festlegen.", - "onramper_option_description": "Kaufen Sie schnell Krypto mit vielen Zahlungsmethoden. In den meisten Ländern erhältlich. Spreads und Gebühren variieren.", - "default_buy_provider": "Standard-Kaufanbieter", - "ask_each_time": "Jedes Mal fragen", - "buy_provider_unavailable": "Anbieter derzeit nicht verfügbar.", - "signTransaction": "Transaktion unterzeichnen", - "errorGettingCredentials": "Fehlgeschlagen: Fehler beim Abrufen der Anmeldeinformationen", - "errorSigningTransaction": "Beim Signieren der Transaktion ist ein Fehler aufgetreten", - "pairingInvalidEvent": "Paarung ungültiges Ereignis", - "chains": "Ketten", - "methods": "Methoden", - "events": "Veranstaltungen", - "reject": "Ablehnen", - "approve": "Genehmigen", - "expiresOn": "Läuft aus am", - "walletConnect": "WalletConnect", - "nullURIError": "URI ist null", - "connectWalletPrompt": "Verbinden Sie Ihr Wallet mit WalletConnect, um Transaktionen durchzuführen", - "newConnection": "Neue Verbindung", - "activeConnectionsPrompt": "Hier werden aktive Verbindungen angezeigt", - "deleteConnectionConfirmationPrompt": "Sind Sie sicher, dass Sie die Verbindung zu löschen möchten?", - "event": "Ereignis", - "successful": "Erfolgreich", - "wouoldLikeToConnect": "möchte mich gerne vernetzen", - "message": "Nachricht", - "do_not_have_enough_gas_asset": "Sie verfügen nicht über genügend ${currency}, um eine Transaktion unter den aktuellen Bedingungen des Blockchain-Netzwerks durchzuführen. Sie benötigen mehr ${currency}, um die Gebühren für das Blockchain-Netzwerk zu bezahlen, auch wenn Sie einen anderen Vermögenswert senden.", - "totp_auth_url": "TOTP-Auth-URL", - "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", - "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", - "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", - "seed_key": "Seed-Schlüssel", - "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", - "change_rep_successful": "Vertreter erfolgreich gerändert", - "add_contact": "Kontakt hinzufügen", - "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", - "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", - "order_by": "Sortieren nach", - "creation_date": "Erstellungsdatum", - "group_by_type": "Gruppe nach Typ", - "importNFTs": "NFTs importieren", - "noNFTYet": "Noch keine NFTs", - "address": "Adresse", - "enterTokenID": "Geben Sie die Token-ID ein", - "tokenID": "AUSWEIS", - "name": "Name", - "symbol": "Symbol", - "seed_phrase_length": "Länge der Seed-Phrase", - "unavailable_balance": "Nicht verfügbares Guthaben", - "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", - "unspent_change": "Wechselgeld", - "tor_connection": "Tor-Verbindung", - "setup_warning_2fa_text": "Sie müssen Ihr Wallet aus dem mnemonischen Seed wiederherstellen.\n\nDer Cake-Support kann Ihnen nicht weiterhelfen, wenn Sie den Zugriff auf Ihre 2FA- oder Mnemonik-Seeds verlieren.\nCake 2FA ist eine zweite Authentifizierung für bestimmte Aktionen im Wallet. Bevor Sie Cake 2FA verwenden, empfehlen wir Ihnen, die Anleitung durchzulesen.Es ist NICHT so sicher wie eine Kühllagerung.\n\nWenn Sie den Zugriff auf Ihre 2FA-App oder Ihre TOTP-Schlüssel verlieren, verlieren Sie auch den Zugriff auf dieses Wallet. ", - "scan_qr_on_device": "Scannen Sie diesen QR-Code auf einem anderen Gerät", - "how_to_use": "Wie benutzt man", - "seed_hex_form": "Brieftaschensamen (Sechskantform)", - "seedtype": "Seedtyp", - "seedtype_legacy": "Veraltet (25 Wörter)", - "seedtype_polyseed": "Polyseed (16 Wörter)", - "seed_language_czech": "Tschechisch", - "seed_language_korean": "Koreanisch", - "seed_language_chinese_traditional": "Chinesisch (Traditionell)", - "ascending": "Aufsteigend", - "descending": "Absteigend", - "dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa", - "polygonscan_history": "PolygonScan-Verlauf", - "wallet_seed_legacy": "Legacy Wallet Seed", - "default_sell_provider": "Standard-Verkaufsanbieter", - "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.", - "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)", - "use_testnet": "TESTNET verwenden", - "receivable_balance": "Forderungsbilanz", - "confirmed_tx": "Bestätigt", - "transaction_details_source_address": "Quelladresse", - "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert.", - "contractName": "Vertragsname", - "contractSymbol": "Vertragssymbol", - "description": "Beschreibung", - "camera_consent": "Mit Ihrer Kamera wird bis zum ${provider} ein Bild zur Identifizierung aufgenommen. Weitere Informationen finden Sie in deren Datenschutzbestimmungen.", - "no_relays": "Keine Relais", - "choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus", - "no_relays_message": "Wir haben einen Nostr NIP-05-Eintrag für diesen Benutzer gefunden, der jedoch keine Relays enthält. Bitte weisen Sie den Empfänger an, Relays zu seinem Nostr-Datensatz hinzuzufügen.", - "no_relay_on_domain": "Es gibt kein Relay für die Domäne des Benutzers oder das Relay ist nicht verfügbar. Bitte wählen Sie ein zu verwendendes Relais aus." - "zzzz": "Zzzz" + "you_will_send": "Konvertieren von" } \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4a99eb724..1065876d3 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -717,6 +717,7 @@ "use_card_info_two": "Funds are converted to USD when they're held in the prepaid account, not in digital currencies.", "use_ssl": "Use SSL", "use_suggested": "Use Suggested", + "use_testnet": "Use Testnet", "variable_pair_not_supported": "This variable pair is not supported with the selected exchanges", "verification": "Verification", "verify_with_2fa": "Verify with Cake 2FA", @@ -775,282 +776,5 @@ "you_now_have_debit_card": "You now have a debit card", "you_pay": "You Pay", "you_will_get": "Convert to", - "you_will_send": "Convert from", - "yy": "YY", - "online": "Online", - "offline": "Offline", - "gift_card_number": "Gift card number", - "pin_number": "PIN number", - "total_saving": "Total Savings", - "last_30_days": "Last 30 days", - "avg_savings": "Avg. Savings", - "view_all": "View all", - "active_cards": "Active cards", - "delete_account": "Delete Account", - "cards": "Cards", - "active": "Active", - "redeemed": "Redeemed", - "gift_card_balance_note": "Gift cards with a balance remaining will appear here", - "gift_card_redeemed_note": "Gift cards you’ve redeemed will appear here", - "logout": "Logout", - "add_tip": "Add Tip", - "percentageOf": "of ${amount}", - "is_percentage": "is", - "search_category": "Search category", - "mark_as_redeemed": "Mark As Redeemed", - "more_options": "More Options", - "awaiting_payment_confirmation": "Awaiting Payment Confirmation", - "transaction_sent_notice": "If the screen doesn’t proceed after 1 minute, check a block explorer and your email.", - "agree": "Agree", - "in_store": "In Store", - "generating_gift_card": "Generating Gift Card", - "payment_was_received": "Your payment was received.", - "proceed_after_one_minute": "If the screen doesn’t proceed after 1 minute, check your email.", - "order_id": "Order ID", - "gift_card_is_generated": "Gift Card is generated", - "open_gift_card": "Open Gift Card", - "contact_support": "Contact Support", - "gift_cards_unavailable": "Gift cards are available for purchase only with Monero, Bitcoin, and Litecoin at this time", - "background_sync_mode": "Background sync mode", - "sync_all_wallets": "Sync all wallets", - "introducing_cake_pay": "Introducing Cake Pay!", - "cake_pay_learn_more": "Instantly purchase and redeem gift cards in the app!\nSwipe left to right to learn more.", - "automatic": "Automatic", - "fixed_pair_not_supported": "This fixed pair is not supported with the selected exchanges", - "variable_pair_not_supported": "This variable pair is not supported with the selected exchanges", - "none_of_selected_providers_can_exchange": "None of the selected providers can make this exchange", - "choose_one": "Choose one", - "choose_from_available_options": "Choose from the available options:", - "custom_redeem_amount": "Custom Redeem Amount", - "add_custom_redemption": "Add Custom Redemption", - "remaining": "remaining", - "delete_wallet": "Delete wallet", - "delete_wallet_confirm_message": "Are you sure that you want to delete ${wallet_name} wallet?", - "low_fee": "Low fee", - "low_fee_alert": "You currently are using a low network fee priority. This could cause long waits, different rates, or canceled trades. We recommend setting a higher fee for a better experience.", - "ignor": "Ignore", - "use_suggested": "Use Suggested", - "do_not_share_warning_text": "Do not share these with anyone else, including support.\n\nYour funds can and will be stolen!", - "help": "help", - "all_transactions": "All transactions", - "all_trades": "All trades", - "connection_sync": "Connection and sync", - "security_and_backup": "Security and backup", - "create_backup": "Create backup", - "privacy_settings": "Privacy settings", - "privacy": "Privacy", - "display_settings": "Display settings", - "other_settings": "Other settings", - "auto_generate_subaddresses": "Auto generate subaddresses", - "require_pin_after": "Require PIN after", - "always": "Always", - "minutes_to_pin_code": "${minute} minutes", - "disable_exchange": "Disable exchange", - "advanced_settings": "Advanced Settings", - "settings_can_be_changed_later": "These settings can be changed later in the app settings", - "add_custom_node": "Add New Custom Node", - "disable_fiat": "Disable fiat", - "fiat_api": "Fiat API", - "disabled": "Disabled", - "enabled": "Enabled", - "tor_only": "Tor only", - "unmatched_currencies": "Your current wallet's currency does not match that of the scanned QR", - "orbot_running_alert": "Please make sure Orbot is running prior to connecting to this node.", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets", - "bitcoin_payments_require_1_confirmation": "Bitcoin payments require 1 confirmation, which can take 20 minutes or longer. Thanks for your patience! You will be emailed when the payment is confirmed.", - "send_to_this_address": "Send ${currency} ${tag}to this address", - "arrive_in_this_address": "${currency} ${tag}will arrive in this address", - "do_not_send": "Don't send", - "error_dialog_content": "Oops, we got some error.\n\nPlease send the crash report to our support team to make the application better.", - "scan_qr_code": "Scan QR code", - "cold_or_recover_wallet": "Add a cold wallet or recover a paper wallet", - "please_wait": "Please wait", - "sweeping_wallet": "Sweeping wallet", - "sweeping_wallet_alert": "This shouldn’t take long. DO NOT LEAVE THIS SCREEN OR THE SWEPT FUNDS MAY BE LOST.", - "invoice_details": "Invoice details", - "donation_link_details": "Donation link details", - "anonpay_description": "Generate ${type}. The recipient can ${method} with any supported cryptocurrency, and you will receive funds in this wallet.", - "create_invoice": "Create invoice", - "create_donation_link": "Create donation link", - "optional_email_hint": "Optional payee notification email", - "optional_description": "Optional description", - "optional_name": "Optional recipient name", - "clearnet_link": "Clearnet link", - "onion_link": "Onion link", - "decimal_places_error": "Too many decimal places", - "edit_node": "Edit Node", - "settings": "Settings", - "sell_monero_com_alert_content": "Selling Monero is not supported yet", - "error_text_input_below_minimum_limit": "Amount is less than the minimum", - "error_text_input_above_maximum_limit": "Amount is more than the maximum", - "show_market_place": "Show Marketplace", - "prevent_screenshots": "Prevent screenshots and screen recording", - "profile": "Profile", - "close": "Close", - "modify_2fa": "Modify Cake 2FA", - "disable_cake_2fa": "Disable Cake 2FA", - "question_to_disable_2fa": "Are you sure that you want to disable Cake 2FA? A 2FA code will no longer be needed to access the wallet and certain functions.", - "disable": "Disable", - "setup_2fa": "Setup Cake 2FA", - "verify_with_2fa": "Verify with Cake 2FA", - "totp_code": "TOTP Code", - "please_fill_totp": "Please fill in the 8-digit code present on your other device", - "totp_2fa_success": "Success! Cake 2FA enabled for this wallet. Remember to save your mnemonic seed in case you lose wallet access.", - "totp_verification_success": "Verification Successful!", - "totp_2fa_failure": "Incorrect code. Please try a different code or generate a new secret key. Use a compatible 2FA app that supports 8-digit codes and SHA512.", - "enter_totp_code": "Please enter the TOTP Code.", - "scan_qr_on_device": "Scan this QR code on another device", - "add_secret_code": "Or, add this secret code to an authenticator app", - "totp_secret_code": "TOTP Secret Code", - "setup_2fa_text": "Cake 2FA works using TOTP as the second authentication factor.\n\nCake 2FA's TOTP requires SHA-512 and 8 digit support; this provides increased security. More information and supported apps can be found in the guide.", - "setup_warning_2fa_text": "Cake 2FA is a second authentication for certain actions in the wallet. It is NOT as secure as cold storage.\n\nIf you lose access to your 2FA app or TOTP keys, you WILL lose access to this wallet. You will need to restore your wallet from the mnemonic seed.\n\nCake support will be unable to assist you if you lose access to your 2FA or mnemonic seeds.\nBefore using Cake 2FA, we recommend reading through the guide.", - "setup_totp_recommended": "Setup TOTP", - "disable_buy": "Disable buy action", - "disable_sell": "Disable sell action", - "cake_2fa_preset": "Cake 2FA Preset", - "monero_dark_theme": "Monero Dark Theme", - "bitcoin_dark_theme": "Bitcoin Dark Theme", - "bitcoin_light_theme": "Bitcoin Light Theme", - "high_contrast_theme": "High Contrast Theme", - "matrix_green_dark_theme": "Matrix Green Dark Theme", - "monero_light_theme": "Monero Light Theme", - "narrow": "Narrow", - "normal": "Normal", - "aggressive": "Aggressive", - "require_for_assessing_wallet": "Require for accessing wallet", - "require_for_sends_to_non_contacts": "Require for sends to non-contacts", - "require_for_sends_to_contacts": "Require for sends to contacts", - "require_for_sends_to_internal_wallets": "Require for sends to internal wallets", - "require_for_exchanges_to_internal_wallets": "Require for exchanges to internal wallets", - "require_for_adding_contacts": "Require for adding contacts", - "require_for_creating_new_wallets": "Require for creating new wallets", - "require_for_all_security_and_backup_settings": "Require for all security and backup settings", - "available_balance_description": "The “Available Balance” or “Confirmed Balance” are funds that can be spent immediately. If funds appear in the lower balance but not the top balance, then you must wait a few minutes for the incoming funds to get more network confirmations. After they get more confirmations, they will be spendable.", - "syncing_wallet_alert_title": "Your wallet is syncing", - "syncing_wallet_alert_content": "Your balance and transaction list may not be complete until it says “SYNCHRONIZED” at the top. Click/tap to learn more.", - "home_screen_settings": "Home screen settings", - "sort_by": "Sort by", - "search_add_token": "Search / Add token", - "edit_token": "Edit token", - "warning": "Warning", - "add_token_warning": "Do not edit or add tokens as instructed by scammers.\nAlways confirm token addresses with reputable sources!", - "add_token_disclaimer_check": "I have confirmed the token contract address and information using a reputable source. Adding malicious or incorrect information can result in a loss of funds.", - "token_contract_address": "Token contract address", - "token_name": "Token name eg: Tether", - "token_symbol": "Token symbol eg: USDT", - "token_decimal": "Token decimal", - "field_required": "This field is required", - "pin_at_top": "Pin ${token} at top", - "invalid_input": "Invalid input", - "fiat_balance": "Fiat Balance", - "gross_balance": "Gross Balance", - "alphabetical": "Alphabetical", - "generate_name": "Generate Name", - "balance_page": "Balance Page", - "share": "Share", - "slidable": "Slidable", - "manage_nodes": "Manage nodes", - "etherscan_history": "Etherscan history", - "template_name": "Template Name", - "change_rep": "Change Representative", - "change_rep_message": "Are you sure that you want to change representatives?", - "unsupported_asset": "We don't support this action for this asset. Please create or switch to a wallet of a supported asset type.", - "manage_pow_nodes": "Manage PoW nodes", - "support_title_live_chat": "Live support", - "support_description_live_chat": "Free and fast! Trained support representatives are available to assist", - "support_title_guides": "Cake Wallet guides", - "support_description_guides": "Documentation and support for common issues", - "support_title_other_links": "Other support links", - "support_description_other_links": "Join our communities or reach us or our partners through other methods", - "choose_derivation": "Choose Wallet Derivation", - "new_first_wallet_text": "Keep your crypto safe, piece of cake", - "select_destination": "Please select destination for the backup file.", - "save_to_downloads": "Save to Downloads", - "select_buy_provider_notice": "Select a buy provider above. You can skip this screen by setting your default buy provider in app settings.", - "onramper_option_description": "Quickly buy crypto with many payment methods. Available in most countries. Spreads and fees vary.", - "default_buy_provider": "Default Buy Provider", - "ask_each_time": "Ask each time", - "robinhood_option_description": "Buy and transfer instantly using your debit card, bank account, or Robinhood balance. USA only.", - "buy_provider_unavailable": "Provider currently unavailable.", - "signTransaction": "Sign Transaction", - "errorGettingCredentials": "Failed: Error while getting credentials", - "errorSigningTransaction": "An error has occured while signing transaction", - "pairingInvalidEvent": "Pairing Invalid Event", - "chains": "Chains", - "methods": "Methods", - "events": "Events", - "reject": "Reject", - "approve": "Approve", - "expiresOn": "Expires on", - "walletConnect": "WalletConnect", - "nullURIError": "URI is null", - "connectWalletPrompt": "Connect your wallet with WalletConnect to make transactions", - "newConnection": "New Connection", - "activeConnectionsPrompt": "Active connections will appear here", - "deleteConnectionConfirmationPrompt": "Are you sure that you want to delete the connection to", - "event": "Event", - "successful": "Successful", - "wouoldLikeToConnect": "would like to connect", - "message": "Message", - "do_not_have_enough_gas_asset": "You do not have enough ${currency} to make a transaction with the current blockchain network conditions. You need more ${currency} to pay blockchain network fees, even if you are sending a different asset.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Kindly wait for the dApp to finish processing.", - "copyWalletConnectLink": "Copy the WalletConnect link from dApp and paste here", - "enterWalletConnectURI": "Enter WalletConnect URI", - "seed_key": "Seed key", - "enter_seed_phrase": "Enter your seed phrase", - "change_rep_successful": "Successfully changed representative", - "add_contact": "Add contact", - "exchange_provider_unsupported": "${providerName} is no longer supported!", - "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", - "order_by": "Order by", - "creation_date": "Creation Date", - "group_by_type": "Group by type", - "importNFTs": "Import NFTs", - "noNFTYet": "No NFTs yet", - "address": "Address", - "enterTokenID": "Enter the token ID", - "tokenID": "ID", - "name": "Name", - "symbol": "Symbol", - "seed_phrase_length": "Seed phrase length", - "unavailable_balance": "Unavailable balance", - "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", - "unspent_change": "Change", - "tor_connection": "Tor connection", - "how_to_use": "How to use", - "seed_hex_form": "Wallet seed (hex form)", - "seedtype": "Seedtype", - "seedtype_legacy": "Legacy (25 words)", - "seedtype_polyseed": "Polyseed (16 words)", - "seed_language_czech": "Czech", - "seed_language_korean": "Korean", - "seed_language_chinese_traditional": "Chinese (Traditional)", - "ascending": "Ascending", - "descending": "Descending", - "dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe", - "polygonscan_history": "PolygonScan history", - "wallet_seed_legacy": "Legacy wallet seed", - "default_sell_provider": "Default Sell Provider", - "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.", - "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)", - "use_testnet": "Use Testnet", - "receivable_balance": "Receivable Balance", - "confirmed_tx": "Confirmed", - "transaction_details_source_address": "Source address", - "pause_wallet_creation": "Ability to create Haven Wallet is currently paused.", - "contractName": "Contract Name", - "contractSymbol": "Contract Symbol", - "description": "Description", - "camera_consent": "Your camera will be used to capture an image for identification purposes by ${provider}. Please check their Privacy Policy for details.", - "no_relays": "No relays", - "choose_relay": "Please choose a relay to use", - "no_relays_message": "We found a Nostr NIP-05 record for this user, but it does not contain any relays. Please instruct the recipient to add relays to their Nostr record.", - "no_relay_on_domain": "There isn't a relay for user's domain or the relay is unavailable. Please choose a relay to use." - "zzzz": "zzzz" + "you_will_send": "Convert from" } \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 6775b408c..8dc1af6fc 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -716,6 +716,7 @@ "use_card_info_two": "Los fondos se convierten a USD cuando se mantienen en la cuenta prepaga, no en monedas digitales.", "use_ssl": "Utilice SSL", "use_suggested": "Usar sugerido", + "use_testnet": "Use TestNet", "variable_pair_not_supported": "Este par de variables no es compatible con los intercambios seleccionados", "verification": "Verificación", "verify_with_2fa": "Verificar con Cake 2FA", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "Ahora tiene una tarjeta de débito", "you_pay": "Tú pagas", "you_will_get": "Convertir a", - "you_will_send": "Convertir de", - "yy": "YY", - "online": "En línea", - "offline": "fuera de línea", - "gift_card_number": "Número de tarjeta de regalo", - "pin_number": "Número PIN", - "total_saving": "Ahorro Total", - "last_30_days": "Últimos 30 días", - "avg_savings": "Ahorro promedio", - "view_all": "Ver todo", - "active_cards": "Tarjetas activas", - "delete_account": "Eliminar cuenta", - "cards": "Cartas", - "active": "Activo", - "redeemed": "Redimido", - "gift_card_balance_note": "Las tarjetas de regalo con saldo restante aparecerán aquí", - "gift_card_redeemed_note": "Las tarjetas de regalo que hayas canjeado aparecerán aquí", - "logout": "Cerrar sesión", - "add_tip": "Agregar sugerencia", - "percentageOf": "de ${amount}", - "is_percentage": "es", - "search_category": "Categoría de búsqueda", - "mark_as_redeemed": "Marcar como canjeado", - "more_options": "Más Opciones", - "awaiting_payment_confirmation": "Esperando confirmación de pago", - "transaction_sent_notice": "Si la pantalla no continúa después de 1 minuto, revisa un explorador de bloques y tu correo electrónico.", - "agree": "De acuerdo", - "in_store": "En la tienda", - "generating_gift_card": "Generando tarjeta de regalo", - "payment_was_received": "Su pago fue recibido.", - "proceed_after_one_minute": "Si la pantalla no continúa después de 1 minuto, revisa tu correo electrónico.", - "order_id": "Identificación del pedido", - "gift_card_is_generated": "Se genera la tarjeta de regalo", - "open_gift_card": "Abrir tarjeta de regalo", - "contact_support": "Contactar con Soporte", - "gift_cards_unavailable": "Las tarjetas de regalo están disponibles para comprar solo a través de Monero, Bitcoin y Litecoin en este momento", - "background_sync_mode": "Modo de sincronización en segundo plano", - "sync_all_wallets": "Sincronizar todas las billeteras", - "introducing_cake_pay": "¡Presentamos Cake Pay!", - "cake_pay_learn_more": "¡Compre y canjee tarjetas de regalo al instante en la aplicación!\nDeslice el dedo de izquierda a derecha para obtener más información.", - "automatic": "Automático", - "fixed_pair_not_supported": "Este par fijo no es compatible con los intercambios seleccionados", - "variable_pair_not_supported": "Este par de variables no es compatible con los intercambios seleccionados", - "none_of_selected_providers_can_exchange": "Ninguno de los proveedores seleccionados puede realizar este intercambio", - "choose_one": "Elige uno", - "choose_from_available_options": "Elija entre las opciones disponibles:", - "custom_redeem_amount": "Cantidad de canje personalizada", - "add_custom_redemption": "Agregar redención personalizada", - "remaining": "restante", - "delete_wallet": "Eliminar billetera", - "delete_wallet_confirm_message": "¿Está seguro de que desea eliminar la billetera ${wallet_name}?", - "low_fee": "Tarifa baja", - "low_fee_alert": "Actualmente está utilizando una prioridad de tarifa de red baja. Esto podría causar largas esperas, tarifas diferentes o transacciones canceladas. Recomendamos establecer una tarifa más alta para una mejor experiencia.", - "ignor": "Pasar por alto", - "use_suggested": "Usar sugerido", - "do_not_share_warning_text": "No comparta estos con nadie más, incluido el soporte.\n\n¡Sus fondos pueden ser y serán robados!", - "help": "ayuda", - "all_transactions": "Todas las transacciones", - "all_trades": "Todos los oficios", - "connection_sync": "Conexión y sincronización", - "security_and_backup": "Seguridad y respaldo", - "create_backup": "Crear copia de seguridad", - "privacy_settings": "Configuración de privacidad", - "privacy": "Privacidad", - "display_settings": "Configuración de pantalla", - "other_settings": "Otras configuraciones", - "require_pin_after": "Requerir PIN después de", - "always": "siempre", - "minutes_to_pin_code": "${minute} minutos", - "disable_exchange": "Deshabilitar intercambio", - "advanced_settings": "Ajustes avanzados", - "settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación", - "add_custom_node": "Agregar nuevo nodo personalizado", - "disable_fiat": "Deshabilitar fiat", - "fiat_api": "Fiat API", - "disabled": "Desactivado", - "enabled": "Activado", - "tor_only": "solo Tor", - "unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado", - "orbot_running_alert": "Asegúrese de que Orbot se esté ejecutando antes de conectarse a este nodo.", - "contact_list_contacts": "Contactos", - "contact_list_wallets": "Mis billeteras", - "bitcoin_payments_require_1_confirmation": "Los pagos de Bitcoin requieren 1 confirmación, que puede demorar 20 minutos o más. ¡Gracias por su paciencia! Se le enviará un correo electrónico cuando se confirme el pago.", - "send_to_this_address": "Enviar ${currency} ${tag}a esta dirección", - "arrive_in_this_address": "${currency} ${tag}llegará a esta dirección", - "do_not_send": "no enviar", - "error_dialog_content": "Vaya, tenemos un error.\n\nEnvíe el informe de bloqueo a nuestro equipo de soporte para mejorar la aplicación.", - "scan_qr_code": "Escanear código QR", - "cold_or_recover_wallet": "Agregue una billetera fría o recupere una billetera de papel", - "please_wait": "Espere por favor", - "sweeping_wallet": "Billetera de barrido", - "sweeping_wallet_alert": "Esto no debería llevar mucho tiempo. NO DEJES ESTA PANTALLA O SE PUEDEN PERDER LOS FONDOS BARRIDOS", - "decimal_places_error": "Demasiados lugares decimales", - "edit_node": "Editar nodo", - "invoice_details": "Detalles de la factura", - "donation_link_details": "Detalles del enlace de donación", - "anonpay_description": "Genera ${type}. El destinatario puede ${method} con cualquier criptomoneda admitida, y recibirá fondos en esta billetera.", - "create_invoice": "Crear factura", - "create_donation_link": "Crear enlace de donación", - "optional_email_hint": "Correo electrónico de notificación del beneficiario opcional", - "optional_description": "Descripción opcional", - "optional_name": "Nombre del destinatario opcional", - "clearnet_link": "enlace Clearnet", - "onion_link": "Enlace de cebolla", - "settings": "Configuraciones", - "sell_monero_com_alert_content": "Aún no se admite la venta de Monero", - "error_text_input_below_minimum_limit": "La cantidad es menos que mínima", - "error_text_input_above_maximum_limit": "La cantidad es más que el máximo", - "show_market_place": "Mostrar mercado", - "prevent_screenshots": "Evitar capturas de pantalla y grabación de pantalla", - "profile": "Perfil", - "close": "Cerca", - "modify_2fa": "Modificar torta 2FA", - "disable_cake_2fa": "Desactivar pastel 2FA", - "question_to_disable_2fa": "¿Está seguro de que desea deshabilitar Cake 2FA? Ya no se necesitará un código 2FA para acceder a la billetera y a ciertas funciones.", - "disable": "Desactivar", - "setup_2fa": "Configurar pastel 2FA", - "verify_with_2fa": "Verificar con Cake 2FA", - "totp_code": "Código TOTP", - "please_fill_totp": "Complete el código de 8 dígitos presente en su otro dispositivo", - "totp_2fa_success": "¡Éxito! Cake 2FA habilitado para esta billetera. Recuerde guardar su semilla mnemotécnica en caso de que pierda el acceso a la billetera.", - "totp_verification_success": "¡Verificación exitosa!", - "totp_2fa_failure": "Código incorrecto. Intente con un código diferente o genere una nueva clave secreta. Use una aplicación 2FA compatible que admita códigos de 8 dígitos y SHA512.", - "enter_totp_code": "Ingrese el código TOTP.", - "add_secret_code": "O agregue este código secreto a una aplicación de autenticación", - "totp_secret_code": "Código secreto TOTP", - "setup_2fa_text": "Cake 2FA funciona utilizando TOTP como segundo factor de autenticación.\n\nEl TOTP de Cake 2FA requiere SHA-512 y soporte de 8 dígitos; esto proporciona una mayor seguridad. Puede encontrar más información y aplicaciones compatibles en la guía.", - "setup_totp_recommended": "Configurar TOTP", - "disable_buy": "Desactivar acción de compra", - "disable_sell": "Desactivar acción de venta", - "cake_2fa_preset": "Pastel 2FA preestablecido", - "monero_dark_theme": "Tema oscuro de Monero", - "bitcoin_dark_theme": "Tema oscuro de Bitcoin", - "bitcoin_light_theme": "Tema de la luz de Bitcoin", - "high_contrast_theme": "Tema de alto contraste", - "matrix_green_dark_theme": "Matrix verde oscuro tema", - "monero_light_theme": "Tema ligero de Monero", - "auto_generate_subaddresses": "Generar subdirecciones automáticamente", - "narrow": "Angosto", - "normal": "Normal", - "aggressive": "Demasiado entusiasta", - "require_for_assessing_wallet": "Requerido para acceder a la billetera", - "require_for_sends_to_non_contacts": "Requerido para envíos a no contactos", - "require_for_sends_to_contacts": "Requerir para envíos a contactos", - "require_for_sends_to_internal_wallets": "Requerido para envíos a billeteras internas", - "require_for_exchanges_to_internal_wallets": "Requerido para intercambios a billeteras internas", - "require_for_adding_contacts": "Requerido para agregar contactos", - "require_for_creating_new_wallets": "Requerido para crear nuevas billeteras", - "require_for_all_security_and_backup_settings": "Requerido para todas las configuraciones de seguridad y copia de seguridad", - "available_balance_description": "Su saldo disponible es la cantidad de fondos que puede gastar. Los fondos que se muestran aquí se pueden gastar inmediatamente.", - "syncing_wallet_alert_title": "Tu billetera se está sincronizando", - "syncing_wallet_alert_content": "Es posible que su lista de saldo y transacciones no esté completa hasta que diga \"SINCRONIZADO\" en la parte superior. Haga clic/toque para obtener más información.", - "home_screen_settings": "Configuración de la pantalla de inicio", - "sort_by": "Ordenar por", - "search_add_token": "Buscar/Agregar token", - "edit_token": "Editar token", - "warning": "Advertencia", - "add_token_warning": "No edite ni agregue tokens según las instrucciones de los estafadores.\n¡Confirme siempre las direcciones de los tokens con fuentes acreditadas!", - "add_token_disclaimer_check": "He confirmado la dirección del contrato del token y la información utilizando una fuente confiable. Agregar información maliciosa o incorrecta puede resultar en una pérdida de fondos.", - "token_contract_address": "Dirección de contrato de token", - "token_name": "Nombre del token, por ejemplo: Tether", - "token_symbol": "Símbolo de token, por ejemplo: USDT", - "token_decimal": "Token decimal", - "field_required": "Este campo es obligatorio", - "pin_at_top": "pin ${token} en la parte superior", - "invalid_input": "Entrada inválida", - "fiat_balance": "Equilibrio Fiat", - "gross_balance": "Saldo bruto", - "alphabetical": "Alfabético", - "generate_name": "Generar nombre", - "balance_page": "Página de saldo", - "share": "Compartir", - "slidable": "deslizable", - "manage_nodes": "Administrar nodos", - "etherscan_history": "historia de etherscan", - "template_name": "Nombre de la plantilla", - "change_rep": "Representante de cambio", - "change_rep_message": "¿Estás seguro de que quieres cambiar de representante?", - "unsupported_asset": "No admitimos esta acción para este activo. Cree o cambie a una billetera de un tipo de activo admitido.", - "manage_pow_nodes": "Administrar nodos PoW", - "support_title_live_chat": "Soporte vital", - "support_description_live_chat": "¡GRATIS y RÁPIDO! Los representantes de apoyo capacitado están disponibles para ayudar", - "support_title_guides": "Guías de billetera para pastel", - "support_description_guides": "Documentación y apoyo para problemas comunes", - "support_title_other_links": "Otros enlaces de soporte", - "support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos", - "choose_derivation": "Elija la derivación de la billetera", - "new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura", - "select_destination": "Seleccione el destino del archivo de copia de seguridad.", - "save_to_downloads": "Guardar en Descargas", - "select_buy_provider_notice": "Seleccione un proveedor de compra arriba. Puede omitir esta pantalla configurando su proveedor de compra predeterminado en la configuración de la aplicación.", - "onramper_option_description": "Compre rápidamente cripto con muchos métodos de pago. Disponible en la mayoría de los países. Los diferenciales y las tarifas varían.", - "default_buy_provider": "Proveedor de compra predeterminado", - "ask_each_time": "Pregunta cada vez", - "buy_provider_unavailable": "Proveedor actualmente no disponible.", - "signTransaction": "Firmar transacción", - "errorGettingCredentials": "Error: error al obtener las credenciales", - "errorSigningTransaction": "Se ha producido un error al firmar la transacción.", - "pairingInvalidEvent": "Evento de emparejamiento no válido", - "chains": "Cadenas", - "methods": "Métodos", - "events": "Eventos", - "reject": "Rechazar", - "approve": "Aprobar", - "expiresOn": "Expira el", - "walletConnect": "MonederoConectar", - "nullURIError": "URI es nula", - "connectWalletPrompt": "Conecte su billetera con WalletConnect para realizar transacciones", - "newConnection": "Nueva conexión", - "activeConnectionsPrompt": "Las conexiones activas aparecerán aquí", - "deleteConnectionConfirmationPrompt": "¿Está seguro de que desea eliminar la conexión a", - "event": "Evento", - "successful": "Exitoso", - "wouoldLikeToConnect": "quisiera conectar", - "message": "Mensaje", - "do_not_have_enough_gas_asset": "No tienes suficiente ${currency} para realizar una transacción con las condiciones actuales de la red blockchain. Necesita más ${currency} para pagar las tarifas de la red blockchain, incluso si envía un activo diferente.", - "totp_auth_url": "URL de autenticación TOTP", - "awaitDAppProcessing": "Espere a que la dApp termine de procesarse.", - "copyWalletConnectLink": "Copie el enlace de WalletConnect de dApp y péguelo aquí", - "enterWalletConnectURI": "Ingrese el URI de WalletConnect", - "seed_key": "Llave de semilla", - "enter_seed_phrase": "Ingrese su frase de semillas", - "change_rep_successful": "Representante cambiado con éxito", - "add_contact": "Agregar contacto", - "exchange_provider_unsupported": "¡${providerName} ya no es compatible!", - "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.", - "order_by": "Ordenar", - "creation_date": "Fecha de creación", - "group_by_type": "Grupo por tipo", - "importNFTs": "Importar NFT", - "noNFTYet": "Aún no hay NFT", - "address": "DIRECCIÓN", - "enterTokenID": "Ingrese el ID del token", - "tokenID": "IDENTIFICACIÓN", - "name": "Nombre", - "symbol": "Símbolo", - "seed_phrase_length": "Longitud de la frase inicial", - "unavailable_balance": "Saldo no disponible", - "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", - "unspent_change": "Cambiar", - "tor_connection": "conexión tor", - "setup_warning_2fa_text": "Deberá restaurar su billetera a partir de la semilla mnemotécnica.\n\nEl soporte de Cake no podrá ayudarlo si pierde el acceso a su 2FA o a sus semillas mnemotécnicas.\nCake 2FA es una segunda autenticación para ciertas acciones en la billetera. Antes de usar Cake 2FA, recomendamos leer la guía.NO es tan seguro como el almacenamiento en frío.\n\nSi pierde el acceso a su aplicación 2FA o a sus claves TOTP, perderá el acceso a esta billetera. ", - "scan_qr_on_device": "Escanea este código QR en otro dispositivo", - "how_to_use": "Cómo utilizar", - "seed_hex_form": "Semilla de billetera (forma hexadecimal)", - "seedtype": "Type de semillas", - "seedtype_legacy": "Legado (25 palabras)", - "seedtype_polyseed": "Polieta (16 palabras)", - "seed_language_czech": "checo", - "seed_language_korean": "coreano", - "ascending": "Ascendente", - "descending": "Descendente", - "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", - "seed_language_chinese_traditional": "Chino (tradicional)", - "polygonscan_history": "Historial de PolygonScan", - "wallet_seed_legacy": "Semilla de billetera heredada", - "default_sell_provider": "Proveedor de venta predeterminado", - "select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.", - "custom_drag": "Custom (mantenía y arrastre)", - "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)", - "use_testnet": "Use TestNet", - "receivable_balance": "Saldo de cuentas por cobrar", - "confirmed_tx": "Confirmado", - "transaction_details_source_address": "Dirección de la fuente", - "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada.", - "contractName": "Nombre del contrato", - "contractSymbol": "Símbolo de contrato", - "description": "Descripción", - "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulte su Política de privacidad para obtener más detalles.", - "no_relays": "Sin relevos", - "choose_relay": "Por favor elija un relé para usar", - "no_relays_message": "Encontramos un registro Nostr NIP-05 para este usuario, pero no contiene ningún relé. Indique al destinatario que agregue retransmisiones a su registro Nostr.", - "no_relay_on_domain": "No hay una retransmisión para el dominio del usuario o la retransmisión no está disponible. Elija un relé para usar." - "zzzz": "zzzz" + "you_will_send": "Convertir de" } \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 7e097f7d5..32d3b2206 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -716,6 +716,7 @@ "use_card_info_two": "Les fonds sont convertis en USD lorsqu'ils sont détenus sur le compte prépayé, et non en devises numériques.", "use_ssl": "Utiliser SSL", "use_suggested": "Suivre la suggestion", + "use_testnet": "Utiliser TestNet", "variable_pair_not_supported": "Cette paire variable n'est pas prise en charge avec les échanges sélectionnés", "verification": "Vérification", "verify_with_2fa": "Vérifier avec Cake 2FA", @@ -774,282 +775,5 @@ "you_now_have_debit_card": "Vous avez maintenant une carte de débit", "you_pay": "Vous payez", "you_will_get": "Convertir vers", - "you_will_send": "Convertir depuis", - "yy": "AA", - "online": "En ligne", - "offline": "Hors ligne", - "gift_card_number": "Numéro de carte cadeau", - "pin_number": "Numéro PIN", - "total_saving": "Économies totales", - "last_30_days": "30 derniers jours", - "avg_savings": "Économies moy.", - "view_all": "Voir tout", - "active_cards": "Cartes actives", - "delete_account": "Supprimer le compte", - "cards": "Cartes", - "active": "Actives", - "redeemed": "Converties", - "gift_card_balance_note": "Les cartes-cadeaux avec un solde restant apparaîtront ici", - "gift_card_redeemed_note": "Les cartes-cadeaux que vous avez utilisées apparaîtront ici", - "logout": "Déconnexion", - "add_tip": "Ajouter un pourboire", - "percentageOf": "sur ${amount}", - "is_percentage": "est", - "search_category": "Catégorie de recherche", - "mark_as_redeemed": "Marquer comme convertie", - "more_options": "Plus d'options", - "awaiting_payment_confirmation": "En attente de confirmation de paiement", - "transaction_sent_notice": "Si l'écran ne continue pas après 1 minute, vérifiez un explorateur de blocs et votre e-mail.", - "agree": "d'accord", - "in_store": "En magasin", - "generating_gift_card": "Génération d'une carte-cadeau", - "payment_was_received": "Votre paiement a été reçu.", - "proceed_after_one_minute": "Si l'écran ne s'affiche pas après 1 minute, vérifiez vos e-mails.", - "order_id": "Numéro de commande", - "gift_card_is_generated": "La carte-cadeau est générée", - "open_gift_card": "Ouvrir la carte-cadeau", - "contact_support": "Contacter l'assistance", - "gift_cards_unavailable": "Les cartes-cadeaux ne sont disponibles à l'achat que via Monero, Bitcoin et Litecoin pour le moment", - "background_sync_mode": "Mode de synchronisation en arrière-plan", - "sync_all_wallets": "Synchroniser tous les portefeuilles", - "gift_cards": "Cartes-Cadeaux", - "introducing_cake_pay": "Présentation de Cake Pay !", - "cake_pay_learn_more": "Achetez et utilisez instantanément des cartes-cadeaux dans l'application !\nBalayer de gauche à droite pour en savoir plus.", - "automatic": "Automatique", - "fixed_pair_not_supported": "Cette paire fixe n'est pas prise en charge avec les échanges sélectionnés", - "variable_pair_not_supported": "Cette paire variable n'est pas prise en charge avec les échanges sélectionnés", - "none_of_selected_providers_can_exchange": "Aucun des prestataires sélectionnés ne peut effectuer cet échange", - "choose_one": "Choisissez-en un", - "choose_from_available_options": "Choisissez parmi les options disponibles :", - "custom_redeem_amount": "Montant d'échange personnalisé", - "add_custom_redemption": "Ajouter un remboursement personnalisé", - "remaining": "restant", - "delete_wallet": "Supprimer le portefeuille (wallet)", - "delete_wallet_confirm_message": "Êtes-vous sûr de vouloir supprimer le portefeuille (wallet) ${wallet_name}?", - "low_fee": "Frais modiques", - "low_fee_alert": "Vous utilisez actuellement une priorité de frais de réseau peu élevés. Cela pourrait entraîner de longues attentes, des taux différents ou des transactions annulées. Nous vous recommandons de fixer des frais plus élevés pour une meilleure expérience.", - "ignor": "Ignorer", - "use_suggested": "Suivre la suggestion", - "do_not_share_warning_text": "Ne les partagez avec personne, y compris avec l'assistance.\n\nVos fonds seraient inmanquablement volés !", - "help": "aide", - "all_transactions": "Toutes transactions", - "all_trades": "Tous échanges", - "connection_sync": "Connexion et synchronisation", - "security_and_backup": "Sécurité et sauvegarde", - "create_backup": "Créer une sauvegarde", - "privacy_settings": "Paramètres de confidentialité", - "privacy": "Confidentialité", - "display_settings": "Paramètres d'affichage", - "other_settings": "Autres paramètres", - "require_pin_after": "Code PIN requis après", - "always": "toujours", - "minutes_to_pin_code": "${minute} minutes", - "disable_exchange": "Désactiver l'échange", - "advanced_settings": "Réglages avancés", - "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application", - "add_custom_node": "Ajouter un nouveau nœud personnalisé", - "disable_fiat": "Désactiver les montants en fiat", - "fiat_api": "Fiat API", - "disabled": "Désactivé", - "enabled": "Activé", - "tor_only": "Tor uniquement", - "unmatched_currencies": "La devise de votre portefeuille (wallet) actuel ne correspond pas à celle du QR code scanné", - "orbot_running_alert": "Veuillez vous assurer qu'Orbot est en cours d'exécution avant de vous connecter à ce nœud.", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "Mes portefeuilles (wallets)", - "bitcoin_payments_require_1_confirmation": "Les paiements Bitcoin nécessitent 1 confirmation, ce qui peut prendre 20 minutes ou plus. Merci pour votre patience ! Vous serez averti par e-mail lorsque le paiement sera confirmé.", - "send_to_this_address": "Envoyer ${currency} ${tag}à cette adresse", - "arrive_in_this_address": "${currency} ${tag}arrivera à cette adresse", - "do_not_send": "Ne pas envoyer", - "error_dialog_content": "Oups, nous avons rencontré une erreur.\n\nMerci d'envoyer le rapport d'erreur à notre équipe d'assistance afin de nous permettre d'améliorer l'application.", - "scan_qr_code": "Scannez le QR code", - "cold_or_recover_wallet": "Ajoutez un portefeuille froid (cold wallet) ou récupérez un portefeuille papier (paper wallet)", - "please_wait": "Merci de patienter", - "sweeping_wallet": "Portefeuille (wallet) de consolidation", - "sweeping_wallet_alert": "Cette opération ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS CONSOLIDÉS POURRAIENT ÊTRE PERDUS", - "decimal_places_error": "Trop de décimales", - "edit_node": "Modifier le nœud", - "invoice_details": "Détails de la facture", - "donation_link_details": "Détails du lien de don", - "anonpay_description": "Générez ${type}. Le destinataire peut ${method} avec n'importe quelle crypto-monnaie prise en charge, et vous recevrez des fonds dans ce portefeuille (wallet).", - "create_invoice": "Créer une facture", - "create_donation_link": "Créer un lien de don", - "optional_email_hint": "E-mail de notification du bénéficiaire facultatif", - "optional_description": "Descriptif facultatif", - "optional_name": "Nom du destinataire facultatif", - "clearnet_link": "Lien Clearnet", - "settings": "Paramètres", - "onion_link": "Lien .onion", - "sell_monero_com_alert_content": "La vente de Monero n'est pas encore prise en charge", - "error_text_input_below_minimum_limit": "Le montant est inférieur au minimum", - "error_text_input_above_maximum_limit": "Le montant est supérieur au maximum", - "show_market_place": "Afficher la place de marché", - "prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran", - "profile": "Profil", - "close": "Fermer", - "modify_2fa": "Modifier les paramètres Cake 2FA", - "disable_cake_2fa": "Désactiver Cake 2FA", - "question_to_disable_2fa": "Êtes-vous sûr de vouloir désactiver Cake 2FA ? Un code 2FA ne sera plus nécessaire pour accéder au portefeuille (wallet) et à certaines fonctions.", - "disable": "Désactiver", - "setup_2fa": "Paramétrer Cake 2FA", - "verify_with_2fa": "Vérifier avec Cake 2FA", - "totp_code": "Code TOTP", - "please_fill_totp": "Veuillez renseigner le code à 8 chiffres affiché sur votre autre appareil", - "totp_2fa_success": "Succès! Cake 2FA est activé pour ce portefeuille. N'oubliez pas de sauvegarder votre phrase secrète (seed) au cas où vous perdriez l'accès au portefeuille (wallet).", - "totp_verification_success": "Vérification réussie !", - "totp_2fa_failure": "Code incorrect. Veuillez essayer un code différent ou générer un nouveau secret TOTP. Utilisez une application 2FA compatible qui prend en charge les codes à 8 chiffres et SHA512.", - "enter_totp_code": "Veuillez entrer le code TOTP.", - "add_secret_code": "Ou ajoutez ce code secret à une application d'authentification", - "totp_secret_code": "Secret TOTP", - "setup_2fa_text": "Cake 2FA fonctionne en utilisant TOTP comme deuxième facteur d'authentification.\n\nLe TOTP de Cake 2FA nécessite la prise en charge de SHA-512 et de 8 chiffres ; cela offre une sécurité accrue. Plus d’informations et les applications prises en charge peuvent être trouvées dans le guide.", - "setup_totp_recommended": "Configurer TOTP", - "disable_buy": "Désactiver l'action d'achat", - "disable_sell": "Désactiver l'action de vente", - "cake_2fa_preset": "Cake 2FA prédéfini", - "monero_dark_theme": "Thème sombre Monero", - "bitcoin_dark_theme": "Thème sombre Bitcoin", - "bitcoin_light_theme": "Thème léger Bitcoin", - "high_contrast_theme": "Thème à contraste élevé", - "matrix_green_dark_theme": "Thème Matrix Green Dark", - "monero_light_theme": "Thème de lumière Monero", - "auto_generate_subaddresses": "Générer automatiquement des sous-adresses", - "narrow": "Étroit", - "normal": "Normal", - "aggressive": "Agressif", - "require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille", - "require_for_sends_to_non_contacts": "Exiger pour les envois hors contacts", - "require_for_sends_to_contacts": "Exiger pour les envois aux contacts", - "require_for_sends_to_internal_wallets": "Exiger pour les envois vers des portefeuilles (wallets) internes", - "require_for_exchanges_to_internal_wallets": "Exiger pour les échanges vers des portefeuilles (wallets) internes", - "require_for_adding_contacts": "Requis pour ajouter des contacts", - "require_for_creating_new_wallets": "Nécessaire pour créer de nouveaux portefeuilles (wallets)", - "require_for_all_security_and_backup_settings": "Exiger pour tous les paramètres de sécurité et de sauvegarde", - "available_balance_description": "Le solde disponible est le montant que vous pouvez dépenser immédiatement. Il est calculé en soustrayant le solde gelé du solde total.", - "syncing_wallet_alert_title": "Votre portefeuille (wallet) est en cours de synchronisation", - "syncing_wallet_alert_content": "Votre solde et votre liste de transactions peuvent ne pas être à jour tant que la mention « SYNCHRONISÉ » n'apparaît en haut de l'écran. Cliquez/appuyez pour en savoir plus.", - "home_screen_settings": "Paramètres de l'écran d'accueil", - "sort_by": "Trier par", - "search_add_token": "Rechercher / Ajouter un token", - "edit_token": "Modifier le token", - "warning": "Avertissement", - "add_token_warning": "Ne modifiez pas ou n'ajoutez pas de tokens comme pourraient vous le suggérer des escrocs.\nConfirmez toujours les adresses de token auprès de sources fiables !", - "add_token_disclaimer_check": "J'ai confirmé l'adresse et les informations du contrat de token en utilisant une source fiable. L'ajout d'informations malveillantes ou incorrectes peut entraîner une perte de fonds.", - "token_contract_address": "Adresse du contrat de token", - "token_name": "Nom du token, par exemple : Tether", - "token_symbol": "Symbole de token, par exemple : USDT", - "token_decimal": "Décimales de token", - "field_required": "Ce champ est obligatoire", - "pin_at_top": "épingler ${token} en haut", - "invalid_input": "Entrée invalide", - "fiat_balance": "Solde fiat", - "gross_balance": "Solde brut", - "alphabetical": "Alphabétique", - "generate_name": "Générer un nom", - "balance_page": "Page Solde", - "share": "Partager", - "slidable": "Glissable", - "manage_nodes": "Gérer les nœuds", - "etherscan_history": "Historique d'Etherscan", - "template_name": "Nom du modèle", - "change_rep": "Changer de représentant", - "change_rep_message": "Êtes-vous sûr de vouloir changer de représentant ?", - "unsupported_asset": "Nous ne prenons pas en charge cette action pour cet élément. Veuillez créer ou passer à un portefeuille d'un type d'actif pris en charge.", - "manage_pow_nodes": "Gérer les nœuds PoW", - "support_title_live_chat": "Support en direct", - "support_description_live_chat": "GRATUIT ET RAPIDE ! Des représentants de soutien formé sont disponibles pour aider", - "support_title_guides": "Guides de Cake Wallet", - "support_description_guides": "Documentation et support pour les problèmes communs", - "support_title_other_links": "Autres liens d'assistance", - "support_description_other_links": "Rejoignez nos communautés ou contactez-nous ou nos partenaires à travers d'autres méthodes", - "choose_derivation": "Choisissez le chemin de dérivation du portefeuille", - "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", - "select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.", - "save_to_downloads": "Enregistrer dans les téléchargements", - "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", - "buy_provider_unavailable": "Fournisseur actuellement indisponible.", - "signTransaction": "Signer une transaction", - "errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification", - "errorSigningTransaction": "Une erreur s'est produite lors de la signature de la transaction", - "pairingInvalidEvent": "Événement de couplage non valide", - "chains": "Chaînes", - "methods": "Méthodes", - "events": "Événements", - "reject": "Rejeter", - "approve": "Approuver", - "expiresOn": "Expire le", - "walletConnect": "WalletConnect", - "nullURIError": "L'URI est nul", - "connectWalletPrompt": "Connectez votre portefeuille (wallet) avec WalletConnect pour effectuer des transactions", - "newConnection": "Nouvelle connexion", - "activeConnectionsPrompt": "Les connexions actives apparaîtront ici", - "deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à", - "event": "Événement", - "successful": "Réussi", - "wouoldLikeToConnect": "je voudrais me connecter", - "message": "Message", - "do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.", - "totp_auth_url": "URL D'AUTORISATION TOTP", - "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", - "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", - "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", - "seed_key": "Clé secrète (seed key)", - "enter_seed_phrase": "Entrez votre phrase secrète (seed)", - "change_rep_successful": "Représentant changé avec succès", - "add_contact": "Ajouter le contact", - "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", - "domain_looks_up": "Résolution de nom", - "require_for_exchanges_to_external_wallets": "Exiger pour les é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.", - "importNFTs": "Importer des NFT", - "noNFTYet": "Pas encore de NFT", - "address": "Adresse", - "enterTokenID": "Entrez l'ID du jeton", - "tokenID": "IDENTIFIANT", - "name": "Nom", - "symbol": "Symbole", - "seed_phrase_length": "Longueur de la phrase de départ", - "unavailable_balance": "Solde indisponible", - "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", - "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", - "unspent_change": "Changement", - "order_by": "Commandé par", - "creation_date": "Date de création", - "group_by_type": "Groupe par type", - "tor_connection": "Connexion Tor", - "setup_warning_2fa_text": "Vous devrez restaurer votre portefeuille à partir de la graine mnémonique.\n\nLe support Cake ne pourra pas vous aider si vous perdez l'accès à vos graines 2FA ou mnémoniques.\nCake 2FA est une seconde authentification pour certaines actions dans le portefeuille. Avant d'utiliser Cake 2FA, nous vous recommandons de lire le guide.Ce n’est PAS aussi sécurisé que l’entreposage frigorifique.\n\nSi vous perdez l'accès à votre application 2FA ou à vos clés TOTP, vous perdrez l'accès à ce portefeuille. ", - "scan_qr_on_device": "Scannez ce code QR sur un autre appareil", - "how_to_use": "Comment utiliser", - "seed_hex_form": "Graine du portefeuille (forme hexagonale)", - "seedtype": "Type de type graine", - "seedtype_legacy": "Héritage (25 mots)", - "seedtype_polyseed": "Polyseed (16 mots)", - "seed_language_czech": "tchèque", - "seed_language_korean": "coréen", - "seed_language_chinese_traditional": "Chinois (Traditionnel)", - "ascending": "Ascendant", - "descending": "Descendant", - "dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe", - "polygonscan_history": "Historique de PolygonScan", - "wallet_seed_legacy": "Graine de portefeuille hérité", - "default_sell_provider": "Fournisseur de vente par défaut", - "select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.", - "custom_drag": "Custom (maintenir et traîner)", - "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)", - "use_testnet": "Utiliser TestNet", - "receivable_balance": "Solde de créances", - "confirmed_tx": "Confirmé", - "transaction_details_source_address": "Adresse source", - "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue.", - "contractName": "Nom du contrat", - "contractSymbol": "Symbole du contrat", - "description": "Description", - "camera_consent": "Votre appareil photo sera utilisé pour capturer une image à des fins d'identification par ${provider}. Veuillez consulter leur politique de confidentialité pour plus de détails.", - "no_relays": "Pas de relais", - "choose_relay": "Veuillez choisir un relais à utiliser", - "no_relays_message": "Nous avons trouvé un enregistrement Nostr NIP-05 pour cet utilisateur, mais il ne contient aucun relais. Veuillez demander au destinataire d'ajouter des relais à son enregistrement Nostr.", - "no_relay_on_domain": "Il n'existe pas de relais pour le domaine de l'utilisateur ou le relais n'est pas disponible. Veuillez choisir un relais à utiliser." - "zzzz": "zzzz" + "you_will_send": "Convertir depuis" } \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 63f08e9ed..7dd7aee30 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -699,6 +699,7 @@ "use_card_info_two": "Ana canza kuɗi zuwa dalar Amurka lokacin da ake riƙe su a cikin asusun da aka riga aka biya, ba cikin agogon dijital ba.", "use_ssl": "Yi amfani da SSL", "use_suggested": "Amfani da Shawarwari", + "use_testnet": "Amfani da gwaji", "variable_pair_not_supported": "Ba a samun goyan bayan wannan m biyu tare da zaɓaɓɓun musayar", "verification": "tabbatar", "version": "Sigar ${currentVersion}", @@ -756,262 +757,5 @@ "you_now_have_debit_card": "Yanzu kana da katin zare kudi", "you_pay": "Ka Bayar", "you_will_get": "Maida zuwa", - "you_will_send": "Maida daga", - "yy": "YY", - "online": "Kan layi", - "offline": "Offline", - "gift_card_number": "Lambar katin kyauta", - "pin_number": "Lambar PIN", - "total_saving": "Jimlar Adana", - "last_30_days": "Kwanaki 30 na ƙarshe", - "avg_savings": "Matsakaici Adana", - "view_all": "Duba duka", - "active_cards": "Katunan aiki", - "delete_account": "Share Account", - "cards": "Katuna", - "active": "Mai aiki", - "redeemed": "An fanshi", - "gift_card_balance_note": "Katunan kyauta tare da ragowar ma'auni zasu bayyana anan", - "gift_card_redeemed_note": "Katunan kyauta da kuka fanshi zasu bayyana anan", - "logout": "Fita", - "add_tip": "Ƙara Tukwici", - "percentageOf": "na ${amount}", - "is_percentage": "shine", - "search_category": "Nemo nau'in", - "mark_as_redeemed": "Yi Alama Kamar An Fansa", - "more_options": "Ƙarin Zaɓuɓɓuka", - "awaiting_payment_confirmation": "Ana jiran Tabbacin Biyan Kuɗi", - "transaction_sent_notice": "Idan allon bai ci gaba ba bayan minti 1, duba mai binciken toshewa da imel ɗin ku.", - "agree": "Yarda", - "in_store": "A cikin Store", - "generating_gift_card": "Samar da Katin Kyauta", - "payment_was_received": "An karɓi kuɗin ku.", - "proceed_after_one_minute": "Idan allon bai ci gaba ba bayan minti 1, duba imel ɗin ku.", - "order_id": "Oda ID", - "gift_card_is_generated": "An samar da Katin Kyauta", - "open_gift_card": "Bude Katin Kyauta", - "contact_support": "Tuntuɓi Support", - "gift_cards_unavailable": "Ana samun katunan kyauta don siye kawai tare da Monero, Bitcoin, da Litecoin a wannan lokacin", - "introducing_cake_pay": "Gabatar da Cake Pay!", - "cake_pay_learn_more": "Nan take siya ku kwaso katunan kyaututtuka a cikin app!\nTake hagu zuwa dama don ƙarin koyo.", - "automatic": "Na atomatik", - "fixed_pair_not_supported": "Wannan kafaffen guda biyu ba shi da tallafi tare da zaɓaɓɓun musayar", - "variable_pair_not_supported": "Ba a samun goyan bayan wannan m biyu tare da zaɓaɓɓun musayar", - "none_of_selected_providers_can_exchange": "Babu ɗaya daga cikin zaɓaɓɓun masu samarwa da zai iya yin wannan musayar", - "choose_one": "Zaɓi ɗaya", - "choose_from_available_options": "Zaɓi daga zaɓuɓɓukan da ake da su:", - "custom_redeem_amount": "Adadin Fansa na Musamman", - "add_custom_redemption": "Ƙara Ceto na Musamman", - "remaining": "saura", - "delete_wallet": "Share walat", - "delete_wallet_confirm_message": "Shin kun tabbata cewa kuna son share jakar ${wallet_name}?", - "low_fee": "maras tsada", - "low_fee_alert": "A halin yanzu kuna amfani da ƙarancin fifikon kuɗin hanyar sadarwa. Wannan na iya haifar da dogon jira, farashi daban-daban, ko soke kasuwancin. Muna ba da shawarar saita farashi mafi girma don ƙwarewa mafi kyau.", - "ignor": "Yi watsi da shi", - "use_suggested": "Amfani da Shawarwari", - "do_not_share_warning_text": "Kada ku raba waɗannan ga kowa, gami da tallafi.\n\nZa a iya sace kuɗin ku kuma za a sace!", - "help": "taimako", - "all_transactions": "Dukan Ma'amaloli", - "all_trades": "Duk ciniki", - "connection_sync": "Haɗi da daidaitawa", - "security_and_backup": "Tsaro da madadin", - "create_backup": "Ƙirƙiri madadin", - "privacy_settings": "Saitunan sirri", - "privacy": "Keɓantawa", - "display_settings": "Nuni saituna", - "other_settings": "Sauran saituna", - "require_pin_after": "Bukatar PIN bayan", - "always": "Koyaushe", - "minutes_to_pin_code": "${minute} minti", - "disable_exchange": "Kashe musanya", - "advanced_settings": "Saitunan ci gaba", - "settings_can_be_changed_later": "Ana iya canza waɗannan saitunan daga baya a cikin saitunan app", - "add_custom_node": "Ƙara Sabon Kulli na Custom", - "disable_fiat": "Dakatar da fiat", - "fiat_api": "API ɗin Fiat", - "disabled": "tsaya", - "enabled": "An kunna", - "tor_only": "Tor kawai", - "unmatched_currencies": "Nau'in walat ɗin ku na yanzu bai dace da na lambar QR da aka bincika ba", - "contact_list_contacts": "Lambobin sadarwa", - "contact_list_wallets": "Wallets dina", - "bitcoin_payments_require_1_confirmation": "Akwatin Bitcoin na buɗe 1 sambumbu, da yake za ta samu mintuna 20 ko yawa. Ina kira ga sabuwar lafiya! Zaka sanarwa ta email lokacin da aka samu akwatin samun lambar waya.", - "send_to_this_address": "Aiko ${currency} ${tag} zuwa adireshin wannan", - "arrive_in_this_address": "${currency} ${tag} zai je wurin wannan adireshi", - "do_not_send": "Kada ka aika", - "error_dialog_content": "Ai, yanzu muka ga alamar kuskure. \n\nDa fatan, aika rahoton kuskuren da muka kira zuwa gasar tsarinmu don gaskiyar shirya.", - "cold_or_recover_wallet": "Samun kashi na baya ko samun kashi na kasa", - "please_wait": "Don Allah a rufe", - "sweeping_wallet": "Kashi na kasa", - "sweeping_wallet_alert": "Wannan ba zai samu lokacin mai tsaski. KADA KA SAMU KUNGIYARAN KUHON, ZAMAN DADIN BANKUNCI ZAI HAŘA", - "invoice_details": "Bayanin wadannan", - "donation_link_details": "Bayanin hanyar sadaka", - "anonpay_description": "Ƙirƙirar ${type}. Maƙiyantun mai nasara zai iya ${method} da duk abubuwan da ke samun lambar waya, kuma zaku samu kuɗin dama a wannan kashi.", - "create_invoice": "Sanya bayanin wadannan", - "create_donation_link": "Sanya hanyar sadaka", - "optional_email_hint": "Email na kayan taimako ga wadanda basu ba da maki", - "optional_description": "Bayanin zai iya ba da maki", - "optional_name": "Sunan mawallin zai iya ba da maki", - "clearnet_link": "Lambar makomar kwayoyi", - "onion_link": "Lambar onion", - "decimal_places_error": "Wadannan suna da tsawon harsuna", - "edit_node": "Shirya Node", - "settings": "Saiti", - "sell_monero_com_alert_content": "Selling Monero bai sami ƙarshen mai bukatar samun ba", - "error_text_input_below_minimum_limit": "Kudin ba a kamai", - "error_text_input_above_maximum_limit": "Kudin da ya kamata", - "show_market_place": "Nuna dan kasuwa", - "prevent_screenshots": "Fada lambobi da jarrabobi na kayan lambobi", - "disable_buy": "Kashe alama", - "disable_sell": "Kashe karbuwa", - "cake_2fa_preset": "Cake 2FA saiti", - "monero_dark_theme": "Monero Dark Jigo", - "bitcoin_dark_theme": "Bitcoin Dark Jigo", - "bitcoin_light_theme": "Jigon Hasken Bitcoin", - "high_contrast_theme": "Babban Jigon Kwatance", - "matrix_green_dark_theme": "Matrix Green Dark Jigo", - "monero_light_theme": "Jigon Hasken Monero", - "auto_generate_subaddresses": "Saɓaƙa subaddresses ta kai tsaye", - "narrow": "kunkuntar", - "normal": "Na al'ada", - "aggressive": "Mai tsananin kishi", - "require_for_assessing_wallet": "Bukatar samun damar walat", - "require_for_sends_to_non_contacts": "Bukatar aika zuwa waɗanda ba lambobin sadarwa ba", - "require_for_sends_to_contacts": "Bukatar aika zuwa lambobin sadarwa", - "require_for_sends_to_internal_wallets": "Bukatar aika zuwa wallet na ciki", - "require_for_exchanges_to_internal_wallets": "Bukatar musanya zuwa wallet na ciki", - "require_for_adding_contacts": "Bukatar ƙara lambobin sadarwa", - "require_for_creating_new_wallets": "Bukatar ƙirƙirar sabbin wallet", - "require_for_all_security_and_backup_settings": "Bukatar duk tsaro da saitunan wariyar ajiya", - "available_balance_description": "Ma'auni mai samuwa” ko ”,Tabbataccen Ma'auni”, kudade ne da za a iya kashewa nan da nan. Idan kudade sun bayyana a cikin ƙananan ma'auni amma ba babban ma'auni ba, to dole ne ku jira 'yan mintoci kaɗan don kudaden shiga don samun ƙarin tabbaci na hanyar sadarwa. Bayan sun sami ƙarin tabbaci, za a kashe su.", - "syncing_wallet_alert_title": "Walat ɗin ku yana aiki tare", - "syncing_wallet_alert_content": "Ma'aunin ku da lissafin ma'amala bazai cika ba har sai an ce \"SYNCHRONIZED\" a saman. Danna/matsa don ƙarin koyo.", - "home_screen_settings": "Saitunan allo na gida", - "sort_by": "Kasa", - "search_add_token": "Bincika / Ƙara alama", - "edit_token": "Gyara alamar", - "warning": "Gargadi", - "add_token_warning": "Kar a gyara ko ƙara alamu kamar yadda masu zamba suka umarta.\nKoyaushe tabbatar da adiresoshin alamar tare da sanannun tushe!", - "add_token_disclaimer_check": "Na tabbatar da adireshin kwangilar alamar da bayanin ta amfani da ingantaccen tushe. Ƙara bayanan ƙeta ko kuskure na iya haifar da asarar kuɗi.", - "token_contract_address": "Adireshin kwangilar Token", - "token_name": "Alamar sunan misali: Tether", - "token_symbol": "Alamar alama misali: USDT", - "token_decimal": "Alamar ƙima", - "field_required": "wannan fillin ana bukatansa", - "pin_at_top": "pin ${token} a sama", - "invalid_input": "Shigar da ba daidai ba", - "fiat_balance": "Fiat Balance", - "gross_balance": "Babban Ma'auni", - "alphabetical": "Harafi", - "generate_name": "Ƙirƙirar Suna", - "balance_page": "Ma'auni Page", - "share": "Raba", - "slidable": "Mai iya zamewa", - "etherscan_history": "Etherscan tarihin kowane zamani", - "template_name": "Sunan Samfura", - "change_rep": "Canza Wakili", - "change_rep_message": "Shin kun tabbata kuna son canza wakilai?", - "manage_nodes": "Sarrafa nodes", - "unsupported_asset": "Ba mu goyi bayan wannan aikin don wannan kadara. Da fatan za a ƙirƙira ko canza zuwa walat na nau'in kadara mai tallafi.", - "manage_pow_nodes": "Sarrafa PoW Nodes", - "support_title_live_chat": "Tallafi na Live", - "support_description_live_chat": "Kyauta da sauri! An horar da wakilan tallafi na tallafi don taimakawa", - "support_title_guides": "Jagorar Cake", - "support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun", - "support_title_other_links": "Sauran hanyoyin tallafi", - "support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi", - "choose_derivation": "Zaɓi walatawa", - "new_first_wallet_text": "A sauƙaƙe kiyaye kuzarin ku", - "select_destination": "Da fatan za a zaɓi wurin da za a yi wa madadin fayil ɗin.", - "save_to_downloads": "Ajiye zuwa Zazzagewa", - "select_buy_provider_notice": "Zaɓi mai ba da kyauta a sama. Zaka iya tsallake wannan allon ta hanyar saita mai ba da isasshen busasshen mai ba da isasshen busasshiyar saiti.", - "onramper_option_description": "Da sauri sayi Crypto tare da hanyoyin biyan kuɗi da yawa. Akwai a yawancin ƙasashe. Yaduwa da kudade sun bambanta.", - "default_buy_provider": "Tsohuwar Siyarwa", - "ask_each_time": "Tambaya kowane lokaci", - "buy_provider_unavailable": "Mai ba da kyauta a halin yanzu babu.", - "signTransaction": "Sa hannu Ma'amala", - "errorGettingCredentials": "Ba a yi nasara ba: Kuskure yayin samun takaddun shaida", - "errorSigningTransaction": "An sami kuskure yayin sanya hannu kan ciniki", - "pairingInvalidEvent": "Haɗa Lamarin mara inganci", - "chains": "Sarkoki", - "methods": "Hanyoyin", - "events": "Abubuwan da suka faru", - "reject": "Ƙi", - "approve": "Amincewa", - "expiresOn": "Yana ƙarewa", - "walletConnect": "WalletConnect", - "nullURIError": "URI banza ne", - "connectWalletPrompt": "Haɗa walat ɗin ku tare da WalletConnect don yin ma'amala", - "newConnection": "Sabuwar Haɗi", - "activeConnectionsPrompt": "Haɗin kai mai aiki zai bayyana a nan", - "deleteConnectionConfirmationPrompt": "Shin kun tabbata cewa kuna son share haɗin zuwa", - "event": "Lamarin", - "successful": "Nasara", - "wouoldLikeToConnect": "ina son haɗi", - "message": "Sako", - "do_not_have_enough_gas_asset": "Ba ku da isassun ${currency} don yin ma'amala tare da yanayin cibiyar sadarwar blockchain na yanzu. Kuna buƙatar ƙarin ${currency} don biyan kuɗaɗen cibiyar sadarwar blockchain, koda kuwa kuna aika wata kadara daban.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Da fatan za a jira dApp ya gama aiki.", - "copyWalletConnectLink": "Kwafi hanyar haɗin WalletConnect daga dApp kuma liƙa a nan", - "enterWalletConnectURI": "Shigar da WalletConnect URI", - "seed_key": "Maɓallin iri", - "enter_seed_phrase": "Shigar da Sert Sentarku", - "change_rep_successful": "An samu nasarar canzawa wakilin", - "add_contact": "Ƙara lamba", - "exchange_provider_unsupported": "${providerName}", - "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", - "order_by": "Oda ta", - "creation_date": "Ranar halitta", - "group_by_type": "Rukuni ta nau'in", - "importNFTs": "Shigo da NFTs", - "noNFTYet": "Babu NFTs tukuna", - "address": "Adireshi", - "enterTokenID": "Shigar da alamar alama", - "tokenID": "ID", - "name": "Suna", - "symbol": "Alama", - "seed_phrase_length": "Tsawon jimlar iri", - "unavailable_balance": "Ma'aunin da ba ya samuwa", - "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", - "unspent_change": "Canza", - "tor_connection": "Tor haɗin gwiwa", - "setup_2fa_text": "Cake 2FA yana aiki ta amfani da TOTP azaman ƙimar tabbatarwa ta biyu.\n\nCake 2FA's TOTP yana buƙatar tallafin lambobi SHA-512 da 8; wannan yana ba da ƙarin tsaro. Ana iya samun ƙarin bayani da ƙa'idodi masu goyan baya a cikin jagorar.", - "setup_warning_2fa_text": "Kuna buƙatar dawo da walat ɗin ku daga zuriyar mnemonic.\n\nTallafin kek ba zai iya taimaka muku ba idan kun rasa damar yin amfani da 2FA ko tsaba na mnemonic.\nCake 2FA tabbaci ne na biyu don wasu ayyuka a cikin walat. Kafin amfani da Cake 2FA, muna ba da shawarar karanta ta cikin jagorar.BA shi da tsaro kamar ajiyar sanyi.\n\nIdan ka rasa damar yin amfani da app ɗinka na 2FA ko maɓallan TOTP, ZA KA rasa damar shiga wannan wallet ɗin. ", - "add_secret_code": "Ko, ƙara wannan lambar sirrin zuwa ƙa'idar mai tabbatarwa", - "scan_qr_on_device": "Duba wannan lambar QR akan wata na'ura", - "how_to_use": "Yadda ake amfani da shi", - "seed_hex_form": "Gany Sero (form form)", - "seedtype": "Seedtype", - "seedtype_legacy": "Legacy (25 kalmomi)", - "seedtype_polyseed": "Polyseed (16 kalmomi)", - "seed_language_czech": "Czech", - "seed_language_korean": "Yaren Koriya", - "seed_language_chinese_traditional": "Sinanci (na gargajiya)", - "ascending": "Hau", - "descending": "Saukowa", - "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", - "polygonscan_history": "PolygonScan tarihin kowane zamani", - "wallet_seed_legacy": "Tallarin walat walat", - "setup_totp_recommended": "Saita TOTP", - "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", - "select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.", - "custom_drag": "Al'ada (riƙe da ja)", - "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", - "use_testnet": "Amfani da gwaji", - "receivable_balance": "Daidaituwa da daidaituwa", - "confirmed_tx": "Tabbatar", - "transaction_details_source_address": "Adireshin Incord", - "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet.", - "contractName": "Sunan Kwangila", - "contractSymbol": "Alamar Kwangila", - "description": "Bayani", - "camera_consent": "Za a yi amfani da kyamarar ku don ɗaukar hoto don dalilai na tantancewa ta ${provider}. Da fatan za a duba Manufar Sirri don cikakkun bayanai.", - "no_relays": "Babu relays", - "choose_relay": "Da fatan za a zaɓi gudun ba da sanda don amfani", - "no_relays_message": "Mun sami rikodin Nostr NIP-05 don wannan mai amfani, amma ba ya ƙunshe da kowane relays. Da fatan za a umurci mai karɓa ya ƙara relays zuwa rikodin su na Nostr.", - "no_relay_on_domain": "Babu gudun ba da sanda ga yankin mai amfani ko kuma ba a samu ba. Da fatan za a zaɓi gudun ba da sanda don amfani." - "zzzz": "zzzz" + "you_will_send": "Maida daga" } \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 126fa2568..dc49b5008 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -716,6 +716,7 @@ "use_card_info_two": "डिजिटल मुद्राओं में नहीं, प्रीपेड खाते में रखे जाने पर निधियों को यूएसडी में बदल दिया जाता है।", "use_ssl": "उपयोग SSL", "use_suggested": "सुझाए गए का प्रयोग करें", + "use_testnet": "टेस्टनेट का उपयोग करें", "variable_pair_not_supported": "यह परिवर्तनीय जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", "verification": "सत्यापन", "verify_with_2fa": "केक 2FA के साथ सत्यापित करें", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "अब आपके पास डेबिट कार्ड है", "you_pay": "आप भुगतान करते हैं", "you_will_get": "में बदलें", - "you_will_send": "से रूपांतरित करें", - "yy": "वाईवाई", - "online": "ऑनलाइन", - "offline": "ऑफ़लाइन", - "gift_card_number": "गिफ्ट कार्ड नंबर", - "pin_number": "पिन नंबर", - "total_saving": "कुल बचत", - "last_30_days": "पिछले 30 दिन", - "avg_savings": "औसत बचत", - "view_all": "सभी देखें", - "active_cards": "सक्रिय कार्ड", - "delete_account": "खाता हटाएं", - "cards": "कार्ड", - "active": "सक्रिय", - "redeemed": "रिडीम किया गया", - "gift_card_balance_note": "गिफ्ट कार्ड शेष राशि के साथ यहां दिखाई देंगे", - "gift_card_redeemed_note": "आपके द्वारा भुनाए गए उपहार कार्ड यहां दिखाई देंगे", - "logout": "लॉगआउट", - "add_tip": "टिप जोड़ें", - "percentageOf": "${amount} का", - "is_percentage": "है", - "search_category": "खोज श्रेणी", - "mark_as_redeemed": "रिडीम किए गए के रूप में चिह्नित करें", - "more_options": "और विकल्प", - "awaiting_payment_confirmation": "भुगतान की पुष्टि की प्रतीक्षा में", - "transaction_sent_notice": "अगर 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो ब्लॉक एक्सप्लोरर और अपना ईमेल देखें।", - "agree": "सहमत", - "in_store": "स्टोर में", - "generating_gift_card": "गिफ्ट कार्ड जनरेट कर रहा है", - "Payment_was_received": "आपका भुगतान प्राप्त हो गया था।", - "proceed_after_one_minute": "यदि 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो अपना ईमेल देखें।", - "order_id": "ऑर्डर आईडी", - "gift_card_is_generated": "गिफ्ट कार्ड जनरेट हुआ", - "open_gift_card": "गिफ्ट कार्ड खोलें", - "contact_support": "सहायता से संपर्क करें", - "gift_cards_unavailable": "उपहार कार्ड इस समय केवल मोनेरो, बिटकॉइन और लिटकोइन के माध्यम से खरीदने के लिए उपलब्ध हैं", - "background_sync_mode": "बैकग्राउंड सिंक मोड", - "sync_all_wallets": "सभी वॉलेट सिंक करें", - "introducing_cake_pay": "परिचय Cake Pay!", - "cake_pay_learn_more": "ऐप में उपहार कार्ड तुरंत खरीदें और रिडीम करें!\nअधिक जानने के लिए बाएं से दाएं स्वाइप करें।", - "automatic": "स्वचालित", - "fixed_pair_not_supported": "यह निश्चित जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", - "variable_pair_not_supported": "यह परिवर्तनीय जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", - "none_of_selected_providers_can_exchange": "चयनित प्रदाताओं में से कोई भी इस एक्सचेंज को नहीं बना सकता", - "choose_one": "एक का चयन", - "choose_from_available_options": "उपलब्ध विकल्पों में से चुनें:", - "custom_redeem_amount": "कस्टम रिडीम राशि", - "add_custom_redemption": "कस्टम रिडेम्पशन जोड़ें", - "remaining": "शेष", - "delete_wallet": "वॉलेट हटाएं", - "delete_wallet_confirm_message": "क्या आप वाकई ${wallet_name} वॉलेट हटाना चाहते हैं?", - "low_fee": "कम शुल्क", - "low_fee_alert": "आप वर्तमान में कम नेटवर्क शुल्क प्राथमिकता का उपयोग कर रहे हैं। यह लंबे इंतजार, अलग-अलग दरों या रद्द किए गए ट्रेडों का कारण बन सकता है। हम बेहतर अनुभव के लिए अधिक शुल्क निर्धारित करने की सलाह देते हैं।", - "ignor": "नज़रअंदाज़ करना", - "use_suggested": "सुझाए गए का प्रयोग करें", - "do_not_share_warning_text": "समर्थन सहित, इन्हें किसी और के साथ साझा न करें।\n\nआपके धन की चोरी हो सकती है और होगी!", - "help": "मदद करना", - "all_transactions": "सभी लेन - देन", - "all_trades": "सभी व्यापार", - "connection_sync": "कनेक्शन और सिंक", - "security_and_backup": "सुरक्षा और बैकअप", - "create_backup": "बैकअप बनाएँ", - "privacy_settings": "गोपनीयता सेटिंग्स", - "privacy": "गोपनीयता", - "display_settings": "प्रदर्शन सेटिंग्स", - "other_settings": "अन्य सेटिंग्स", - "require_pin_after": "इसके बाद पिन आवश्यक है", - "always": "हमेशा", - "minutes_to_pin_code": "${minute} मिनट", - "disable_exchange": "एक्सचेंज अक्षम करें", - "advanced_settings": "एडवांस सेटिंग", - "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है", - "add_custom_node": "नया कस्टम नोड जोड़ें", - "disable_fiat": "िएट को अक्षम करें", - "fiat_api": "फिएट पैसे API", - "disabled": "अक्षम", - "enabled": "सक्रिय", - "tor_only": "Tor केवल", - "unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती", - "orbot_running_alert": "कृपया सुनिश्चित करें कि इस नोड से कनेक्ट करने से पहले Orbot चल रहा है।", - "contact_list_contacts": "संपर्क", - "contact_list_wallets": "मेरा बटुआ", - "bitcoin_payments_require_1_confirmation": "बिटकॉइन भुगतान के लिए 1 पुष्टिकरण की आवश्यकता होती है, जिसमें 20 मिनट या अधिक समय लग सकता है। आपके धैर्य के लिए धन्यवाद! भुगतान की पुष्टि होने पर आपको ईमेल किया जाएगा।", - "send_to_this_address": "इस पते पर ${currency} ${tag}भेजें", - "arrive_in_this_address": "${currency} ${tag}इस पते पर पहुंचेंगे", - "do_not_send": "मत भेजो", - "error_dialog_content": "ओह, हमसे कुछ गड़बड़ी हुई है.\n\nएप्लिकेशन को बेहतर बनाने के लिए कृपया क्रैश रिपोर्ट हमारी सहायता टीम को भेजें।", - "scan_qr_code": "स्कैन क्यू आर कोड", - "cold_or_recover_wallet": "कोल्ड वॉलेट जोड़ें या पेपर वॉलेट पुनर्प्राप्त करें", - "please_wait": "कृपया प्रतीक्षा करें", - "sweeping_wallet": "स्वीपिंग वॉलेट", - "sweeping_wallet_alert": "इसमें अधिक समय नहीं लगना चाहिए। इस स्क्रीन को न छोड़ें या स्वैप्ट फंड खो सकते हैं", - "decimal_places_error": "बहुत अधिक दशमलव स्थान", - "edit_node": "नोड संपादित करें", - "invoice_details": "चालान विवरण", - "donation_link_details": "दान लिंक विवरण", - "anonpay_description": "${type} उत्पन्न करें। प्राप्तकर्ता किसी भी समर्थित क्रिप्टोकरेंसी के साथ ${method} कर सकता है, और आपको इस वॉलेट में धन प्राप्त होगा।", - "create_invoice": "इनवॉयस बनाएँ", - "create_donation_link": "दान लिंक बनाएं", - "optional_email_hint": "वैकल्पिक प्राप्तकर्ता सूचना ईमेल", - "optional_description": "वैकल्पिक विवरण", - "optional_name": "वैकल्पिक प्राप्तकर्ता नाम", - "clearnet_link": "क्लियरनेट लिंक", - "onion_link": "प्याज का लिंक", - "settings": "समायोजन", - "sell_monero_com_alert_content": "मोनेरो बेचना अभी तक समर्थित नहीं है", - "error_text_input_below_minimum_limit": "राशि न्यूनतम से कम है", - "error_text_input_above_maximum_limit": "राशि अधिकतम से अधिक है", - "show_market_place": "बाज़ार दिखाएँ", - "prevent_screenshots": "स्क्रीनशॉट और स्क्रीन रिकॉर्डिंग रोकें", - "profile": "प्रोफ़ाइल", - "close": "बंद करना", - "modify_2fa": "केक 2FA संशोधित करें", - "disable_cake_2fa": "केक 2FA अक्षम करें", - "question_to_disable_2fa": "क्या आप सुनिश्चित हैं कि आप Cake 2FA को अक्षम करना चाहते हैं? वॉलेट और कुछ कार्यों तक पहुँचने के लिए अब 2FA कोड की आवश्यकता नहीं होगी।", - "disable": "अक्षम करना", - "setup_2fa": "सेटअप केक 2FA", - "verify_with_2fa": "केक 2FA के साथ सत्यापित करें", - "totp_code": "टीओटीपी कोड", - "please_fill_totp": "कृपया अपने दूसरे डिवाइस पर मौजूद 8 अंकों का कोड भरें", - "totp_2fa_success": "सफलता! इस वॉलेट के लिए Cake 2FA सक्षम है। यदि आप वॉलेट एक्सेस खो देते हैं तो अपने स्मरक बीज को सहेजना याद रखें।", - "totp_verification_success": "सत्यापन सफल!", - "totp_2fa_failure": "गलत कोड़। कृपया एक अलग कोड का प्रयास करें या एक नई गुप्त कुंजी उत्पन्न करें। 8-अंकीय कोड और SHA512 का समर्थन करने वाले संगत 2FA ऐप का उपयोग करें।", - "enter_totp_code": "कृपया TOTP कोड दर्ज करें।", - "add_secret_code": "या, इस गुप्त कोड को प्रमाणक ऐप में जोड़ें", - "totp_secret_code": "टीओटीपी गुप्त कोड", - "setup_2fa_text": "केक 2FA दूसरे प्रमाणीकरण कारक के रूप में TOTP का उपयोग करके काम करता है।\n\nकेक 2FA के TOTP को SHA-512 और 8 अंकों के समर्थन की आवश्यकता है; इससे अधिक सुरक्षा मिलती है. अधिक जानकारी और समर्थित ऐप्स गाइड में पाए जा सकते हैं।", - "setup_totp_recommended": "सेटअप टीओटीपी", - "disable_buy": "खरीद कार्रवाई अक्षम करें", - "disable_sell": "बेचने की कार्रवाई अक्षम करें", - "cake_2fa_preset": "केक 2एफए प्रीसेट", - "monero_dark_theme": "मोनेरो डार्क थीम", - "bitcoin_dark_theme": "बिटकॉइन डार्क थीम", - "bitcoin_light_theme": "बिटकॉइन लाइट थीम", - "high_contrast_theme": "उच्च कंट्रास्ट थीम", - "matrix_green_dark_theme": "मैट्रिक्स ग्रीन डार्क थीम", - "monero_light_theme": "मोनेरो लाइट थीम", - "auto_generate_subaddresses": "स्वचालित रूप से उप-पते उत्पन्न करें", - "narrow": "सँकरा", - "normal": "सामान्य", - "aggressive": "ज्यादा", - "require_for_assessing_wallet": "वॉलेट तक पहुँचने के लिए आवश्यकता है", - "require_for_sends_to_non_contacts": "गैर-संपर्कों को भेजने की आवश्यकता", - "require_for_sends_to_contacts": "संपर्कों को भेजने के लिए आवश्यक है", - "require_for_sends_to_internal_wallets": "आंतरिक वॉलेट में भेजने की आवश्यकता है", - "require_for_exchanges_to_internal_wallets": "आंतरिक वॉलेट में आदान-प्रदान की आवश्यकता है", - "require_for_adding_contacts": "संपर्क जोड़ने के लिए आवश्यकता है", - "require_for_creating_new_wallets": "नए वॉलेट बनाने की आवश्यकता है", - "require_for_all_security_and_backup_settings": "सभी सुरक्षा और बैकअप सेटिंग्स की आवश्यकता है", - "available_balance_description": "उपलब्ध शेष या ”पुष्टिकृत शेष”, वे धनराशि हैं जिन्हें तुरंत खर्च किया जा सकता है। यदि फंड निचले बैलेंस में दिखाई देते हैं, लेकिन शीर्ष बैलेंस में नहीं, तो आपको आने वाले फंड के लिए अधिक नेटवर्क पुष्टिकरण प्राप्त करने के लिए कुछ मिनट इंतजार करना होगा। अधिक पुष्टि मिलने के बाद, वे खर्च करने योग्य हो जाएंगे।", - "syncing_wallet_alert_title": "आपका वॉलेट सिंक हो रहा है", - "syncing_wallet_alert_content": "आपकी शेष राशि और लेनदेन सूची तब तक पूरी नहीं हो सकती जब तक कि शीर्ष पर \"सिंक्रनाइज़्ड\" न लिखा हो। अधिक जानने के लिए क्लिक/टैप करें।", - "home_screen_settings": "होम स्क्रीन सेटिंग्स", - "sort_by": "इसके अनुसार क्रमबद्ध करें", - "search_add_token": "खोजें/टोकन जोड़ें", - "edit_token": "टोकन संपादित करें", - "warning": "चेतावनी", - "add_token_warning": "स्कैमर्स के निर्देशानुसार टोकन संपादित या जोड़ें न करें।\nहमेशा प्रतिष्ठित स्रोतों से टोकन पते की पुष्टि करें!", - "add_token_disclaimer_check": "मैंने एक प्रतिष्ठित स्रोत का उपयोग करके टोकन अनुबंध पते और जानकारी की पुष्टि की है। दुर्भावनापूर्ण या गलत जानकारी जोड़ने से धन की हानि हो सकती है।", - "token_contract_address": "टोकन अनुबंध पता", - "token_name": "टोकन नाम जैसे: टीथर", - "token_symbol": "टोकन प्रतीक जैसे: यूएसडीटी", - "token_decimal": "सांकेतिक दशमलव", - "field_required": "यह फ़ील्ड आवश्यक है", - "pin_at_top": "शीर्ष पर ${token} पिन करें", - "invalid_input": "अमान्य निवेश", - "fiat_balance": "फिएट बैलेंस", - "gross_balance": "सकल संतुलन", - "alphabetical": "वर्णमाला", - "generate_name": "नाम जनरेट करें", - "balance_page": "बैलेंस पेज", - "share": "शेयर करना", - "slidable": "फिसलने लायक", - "manage_nodes": "नोड्स प्रबंधित करें", - "etherscan_history": "इथरस्कैन इतिहास", - "template_name": "टेम्पलेट नाम", - "change_rep": "प्रतिनिधि बदलें", - "change_rep_message": "क्या आप वाकई प्रतिनिधियों को बदलना चाहते हैं?", - "unsupported_asset": "हम इस संपत्ति के लिए इस कार्रवाई का समर्थन नहीं करते हैं. कृपया समर्थित परिसंपत्ति प्रकार का वॉलेट बनाएं या उस पर स्विच करें।", - "manage_pow_nodes": "PoW नोड्स प्रबंधित करें", - "support_title_live_chat": "लाइव सहायता", - "support_description_live_chat": "मुक्त और तेजी से! प्रशिक्षित सहायता प्रतिनिधि सहायता के लिए उपलब्ध हैं", - "support_title_guides": "केक वॉलेट गाइड", - "support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन", - "support_title_other_links": "अन्य समर्थन लिंक", - "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें", - "choose_derivation": "वॉलेट व्युत्पत्ति चुनें", - "new_first_wallet_text": "आसानी से अपनी क्रिप्टोक्यूरेंसी को सुरक्षित रखें", - "select_destination": "कृपया बैकअप फ़ाइल के लिए गंतव्य का चयन करें।", - "save_to_downloads": "डाउनलोड में सहेजें", - "select_buy_provider_notice": "ऊपर एक खरीद प्रदाता का चयन करें। आप इस स्क्रीन को ऐप सेटिंग्स में अपना डिफ़ॉल्ट बाय प्रदाता सेट करके छोड़ सकते हैं।", - "onramper_option_description": "जल्दी से कई भुगतान विधियों के साथ क्रिप्टो खरीदें। अधिकांश देशों में उपलब्ध है। फैलता है और फीस अलग -अलग होती है।", - "default_buy_provider": "डिफ़ॉल्ट खरीद प्रदाता", - "ask_each_time": "हर बार पूछें", - "buy_provider_unavailable": "वर्तमान में प्रदाता अनुपलब्ध है।", - "signTransaction": "लेन-देन पर हस्ताक्षर करें", - "errorGettingCredentials": "विफल: क्रेडेंशियल प्राप्त करते समय त्रुटि", - "errorSigningTransaction": "लेन-देन पर हस्ताक्षर करते समय एक त्रुटि उत्पन्न हुई है", - "pairingInvalidEvent": "अमान्य ईवेंट युग्मित करना", - "chains": "चेन", - "methods": "तरीकों", - "events": "आयोजन", - "reject": "अस्वीकार करना", - "approve": "मंज़ूरी देना", - "expiresOn": "पर समय सीमा समाप्त", - "walletConnect": "वॉलेटकनेक्ट", - "nullURIError": "यूआरआई शून्य है", - "connectWalletPrompt": "लेन-देन करने के लिए अपने वॉलेट को वॉलेटकनेक्ट से कनेक्ट करें", - "newConnection": "नया कनेक्शन", - "activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे", - "deleteConnectionConfirmationPrompt": "क्या आप वाकई कनेक्शन हटाना चाहते हैं?", - "event": "आयोजन", - "successful": "सफल", - "wouoldLikeToConnect": "जुड़ना चाहेंगे", - "message": "संदेश", - "do_not_have_enough_gas_asset": "वर्तमान ब्लॉकचेन नेटवर्क स्थितियों में लेनदेन करने के लिए आपके पास पर्याप्त ${currency} नहीं है। ब्लॉकचेन नेटवर्क शुल्क का भुगतान करने के लिए आपको अधिक ${currency} की आवश्यकता है, भले ही आप एक अलग संपत्ति भेज रहे हों।", - "totp_auth_url": "TOTP प्रामाणिक यूआरएल", - "awaitDAppProcessing": "कृपया डीएपी की प्रोसेसिंग पूरी होने तक प्रतीक्षा करें।", - "copyWalletConnectLink": "dApp से वॉलेटकनेक्ट लिंक को कॉपी करें और यहां पेस्ट करें", - "enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें", - "seed_key": "बीज कुंजी", - "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", - "change_rep_successful": "सफलतापूर्वक बदलकर प्रतिनिधि", - "add_contact": "संपर्क जोड़ें", - "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!", - "domain_looks_up": "डोमेन लुकअप", - "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", - "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", - "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", - "order_by": "द्वारा आदेश", - "creation_date": "निर्माण तिथि", - "group_by_type": "प्रकार द्वारा समूह", - "importNFTs": "एनएफटी आयात करें", - "noNFTYet": "अभी तक कोई एनएफटी नहीं", - "address": "पता", - "enterTokenID": "टोकन आईडी दर्ज करें", - "tokenID": "पहचान", - "name": "नाम", - "symbol": "प्रतीक", - "seed_phrase_length": "बीज वाक्यांश की लंबाई", - "unavailable_balance": "अनुपलब्ध शेष", - "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", - "unspent_change": "परिवर्तन", - "tor_connection": "टोर कनेक्शन", - "setup_warning_2fa_text": "केक 2एफए वॉलेट में कुछ कार्यों के लिए दूसरा प्रमाणीकरण है। यह कोल्ड स्टोरेज जितना सुरक्षित नहीं है।\n\nयदि आप अपने 2एफए ऐप या टीओटीपी कुंजियों तक पहुंच खो देते हैं, तो आप इस वॉलेट तक पहुंच खो देंगे। आपको अपने बटुए को स्मरक बीज से पुनर्स्थापित करने की आवश्यकता होगी।\n\nयदि आप अपने 2एफए या निमोनिक बीजों तक पहुंच खो देते हैं तो केक समर्थन आपकी सहायता करने में असमर्थ होगा।\nकेक 2एफए का उपयोग करने से पहले, हम गाइड को पढ़ने की सलाह देते हैं।", - "scan_qr_on_device": "इस QR कोड को किसी अन्य डिवाइस पर स्कैन करें", - "how_to_use": "का उपयोग कैसे करें", - "seed_hex_form": "वॉलेट सीड (हेक्स फॉर्म)", - "seedtype": "बीज", - "seedtype_legacy": "विरासत (25 शब्द)", - "seedtype_polyseed": "पॉलीसीड (16 शब्द)", - "seed_language_czech": "चेक", - "seed_language_korean": "कोरियाई", - "seed_language_chinese_traditional": "चीनी पारंपरिक)", - "ascending": "आरोही", - "descending": "अवरोही", - "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", - "polygonscan_history": "पॉलीगॉनस्कैन इतिहास", - "wallet_seed_legacy": "विरासत बटुए बीज", - "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", - "select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", - "custom_drag": "कस्टम (पकड़ और खींचें)", - "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)", - "use_testnet": "टेस्टनेट का उपयोग करें", - "receivable_balance": "प्राप्य शेष", - "confirmed_tx": "की पुष्टि", - "transaction_details_source_address": "स्रोत पता", - "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।", - "contractName": "अनुबंध का नाम", - "contractSymbol": "अनुबंध चिह्न", - "description": "विवरण", - "camera_consent": "आपके कैमरे का उपयोग ${provider} द्वारा पहचान उद्देश्यों के लिए एक छवि कैप्चर करने के लिए किया जाएगा। विवरण के लिए कृपया उनकी गोपनीयता नीति जांचें।", - "no_relays": "कोई रिले नहीं", - "choose_relay": "कृपया उपयोग करने के लिए एक रिले चुनें", - "no_relays_message": "हमें इस उपयोगकर्ता के लिए एक Nostr NIP-05 रिकॉर्ड मिला, लेकिन इसमें कोई रिले नहीं है। कृपया प्राप्तकर्ता को अपने नॉस्ट्र रिकॉर्ड में रिले जोड़ने का निर्देश दें।", - "no_relay_on_domain": "उपयोगकर्ता के डोमेन के लिए कोई रिले नहीं है या रिले अनुपलब्ध है। कृपया उपयोग करने के लिए एक रिले चुनें।" - "zzzz": "ज़ज़्ज़" + "you_will_send": "से रूपांतरित करें" } \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 1ffcb73ec..5ceb0d35f 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -714,6 +714,7 @@ "use_card_info_two": "Sredstva se pretvaraju u USD kada se drže na prepaid računu, a ne u digitalnim valutama.", "use_ssl": "Koristi SSL", "use_suggested": "Koristite predloženo", + "use_testnet": "Koristite TestNet", "variable_pair_not_supported": "Ovaj par varijabli nije podržan s odabranim burzama", "verification": "Potvrda", "verify_with_2fa": "Provjerite s Cake 2FA", @@ -772,279 +773,5 @@ "you_now_have_debit_card": "Sada imate debitnu karticu", "you_pay": "Vi plaćate", "you_will_get": "Razmijeni u", - "you_will_send": "Razmijeni iz", - "yy": "GG", - "online": "Na mreži", - "offline": "izvan mreže", - "gift_card_number": "Broj darovne kartice", - "pin_number": "PIN broj", - "total_saving": "Ukupna ušteda", - "last_30_days": "Zadnjih 30 dana", - "avg_savings": "Prosj. ušteda", - "view_all": "Prikaži sve", - "active_cards": "Aktivne kartice", - "delete_account": "Izbriši račun", - "cards": "Kartice", - "active": "Aktivno", - "redeemed": "otkupljeno", - "gift_card_balance_note": "Ovdje će se pojaviti darovne kartice s preostalim saldom", - "gift_card_redeemed_note": "Poklon kartice koje ste iskoristili pojavit će se ovdje", - "logout": "Odjava", - "add_tip": "Dodaj savjet", - "percentageOf": "od ${amount}", - "is_percentage": "je", - "search_category": "Kategorija pretraživanja", - "mark_as_redeemed": "Označi kao otkupljeno", - "more_options": "Više opcija", - "awaiting_payment_confirmation": "Čeka se potvrda plaćanja", - "transaction_sent_notice": "Ako se zaslon ne nastavi nakon 1 minute, provjerite block explorer i svoju e-poštu.", - "agree": "Slažem se", - "in_store": "U trgovini", - "generating_gift_card": "Generiranje darovne kartice", - "payment_was_received": "Vaša uplata je primljena.", - "proceed_after_one_minute": "Ako se zaslon ne nastavi nakon 1 minute, provjerite svoju e-poštu.", - "order_id": "ID narudžbe", - "gift_card_is_generated": "Poklon kartica je generirana", - "open_gift_card": "Otvori darovnu karticu", - "contact_support": "Kontaktirajte podršku", - "gift_cards_unavailable": "Poklon kartice trenutno su dostupne za kupnju samo putem Monera, Bitcoina i Litecoina", - "background_sync_mode": "Sinkronizacija u pozadini", - "sync_all_wallets": "Sinkronizirajte sve novčanike", - "introducing_cake_pay": "Predstavljamo Cake Pay!", - "cake_pay_learn_more": "Azonnal vásárolhat és válthat be ajándékutalványokat az alkalmazásban!\nTovábbi információért csúsztassa balról jobbra az ujját.", - "automatic": "Automatski", - "fixed_pair_not_supported": "Ovaj fiksni par nije podržan s odabranim burzama", - "variable_pair_not_supported": "Ovaj par varijabli nije podržan s odabranim burzama", - "none_of_selected_providers_can_exchange": "Niti jedan od odabranih pružatelja usluga ne može izvršiti ovu razmjenu", - "choose_one": "Izaberi jedan", - "choose_from_available_options": "Odaberite neku od dostupnih opcija:", - "custom_redeem_amount": "Prilagođeni iznos otkupa", - "add_custom_redemption": "Dodaj prilagođeni otkup", - "remaining": "preostalo", - "delete_wallet": "Izbriši novčanik", - "delete_wallet_confirm_message": "Jeste li sigurni da želite izbrisati ${wallet_name} novčanik?", - "low_fee": "Niska naknada", - "low_fee_alert": "Trenutačno koristite niski prioritet mrežne naknade. To bi moglo uzrokovati duga čekanja, različite tečajeve ili otkazane trgovine. Preporučujemo postavljanje veće naknade za bolje iskustvo.", - "ignor": "Zanemariti", - "use_suggested": "Koristite predloženo", - "do_not_share_warning_text": "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nVaša sredstva mogu i bit će ukradena!", - "help": "pomozite", - "all_transactions": "Sve transakcije", - "all_trades": "Svi obrti", - "connection_sync": "Povezivanje i sinkronizacija", - "security_and_backup": "Sigurnost i sigurnosna kopija", - "create_backup": "Stvori sigurnosnu kopiju", - "privacy_settings": "Postavke privatnosti", - "privacy": "Privatnost", - "display_settings": "Postavke zaslona", - "other_settings": "Ostale postavke", - "require_pin_after": "Zahtijevaj PIN nakon", - "always": "Uvijek", - "minutes_to_pin_code": "${minute} minuta", - "disable_exchange": "Onemogući exchange", - "advanced_settings": "Napredne postavke", - "settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije", - "add_custom_node": "Dodaj novi prilagođeni čvor", - "disable_fiat": "Isključi, fiat", - "fiat_api": "Fiat API", - "disabled": "Onemogućeno", - "enabled": "Omogućeno", - "tor_only": "Samo Tor", - "unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u", - "orbot_running_alert": "Provjerite radi li Orbot prije spajanja na ovaj čvor.", - "contact_list_contacts": "Kontakti", - "contact_list_wallets": "Moji novčanici", - "bitcoin_payments_require_1_confirmation": "Bitcoin plaćanja zahtijevaju 1 potvrdu, što može potrajati 20 minuta ili dulje. Hvala na Vašem strpljenju! Dobit ćete e-poruku kada plaćanje bude potvrđeno.", - "send_to_this_address": "Pošaljite ${currency} ${tag}na ovu adresu", - "arrive_in_this_address": "${currency} ${tag}će stići na ovu adresu", - "do_not_send": "Ne šalji", - "error_dialog_content": "Ups, imamo grešku.\n\nPošaljite izvješće o padu našem timu za podršku kako bismo poboljšali aplikaciju.", - "scan_qr_code": "Skenirajte QR kod", - "cold_or_recover_wallet": "Dodajte hladni novčanik ili povratite papirnati novčanik", - "please_wait": "Molimo pričekajte", - "sweeping_wallet": "Čisti novčanik", - "sweeping_wallet_alert": "Ovo ne bi trebalo dugo trajati. NE NAPUŠTAJTE OVAJ ZASLON INAČE SE POBREŠENA SREDSTVA MOGU IZGUBITI", - "decimal_places_error": "Previše decimalnih mjesta", - "edit_node": "Uredi čvor", - "invoice_details": "Podaci o fakturi", - "donation_link_details": "Detalji veza za donacije", - "anonpay_description": "Generiraj ${type}. Primatelj može ${method} s bilo kojom podržanom kriptovalutom, a vi ćete primiti sredstva u ovaj novčanik.", - "create_invoice": "Izradite fakturu", - "create_donation_link": "Izradi poveznicu za donaciju", - "optional_email_hint": "Neobavezna e-pošta za obavijest primatelja", - "optional_description": "Opcijski opis", - "optional_name": "Izborno ime primatelja", - "clearnet_link": "Clearnet veza", - "onion_link": "Poveznica luka", - "settings": "Postavke", - "sell_monero_com_alert_content": "Prodaja Monera još nije podržana", - "error_text_input_below_minimum_limit": "Iznos je manji od minimalnog", - "error_text_input_above_maximum_limit": "Iznos je veći od maskimalnog", - "show_market_place": "Prikaži tržište", - "prevent_screenshots": "Spriječite snimke zaslona i snimanje zaslona", - "profile": "Profil", - "close": "Zatvoriti", - "modify_2fa": "Izmijenite tortu 2FA", - "disable_cake_2fa": "Onemogući Cake 2FA", - "question_to_disable_2fa": "Jeste li sigurni da želite onemogućiti Cake 2FA? 2FA kod više neće biti potreban za pristup novčaniku i određenim funkcijama.", - "disable": "Onemogući", - "setup_2fa": "Postavljanje torte 2FA", - "verify_with_2fa": "Provjerite s Cake 2FA", - "totp_code": "TOTP kod", - "please_fill_totp": "Unesite 8-znamenkasti kod koji se nalazi na vašem drugom uređaju", - "totp_2fa_success": "Uspjeh! Cake 2FA omogućen za ovaj novčanik. Ne zaboravite spremiti svoje mnemoničko sjeme u slučaju da izgubite pristup novčaniku.", - "totp_verification_success": "Provjera uspješna!", - "totp_2fa_failure": "Neispravan kod. Pokušajte s drugim kodom ili generirajte novi tajni ključ. Koristite kompatibilnu 2FA aplikaciju koja podržava 8-znamenkasti kod i SHA512.", - "enter_totp_code": "Unesite TOTP kod.", - "add_secret_code": "Ili dodajte ovaj tajni kod u aplikaciju za autentifikaciju", - "totp_secret_code": "TOTP tajni kod", - "setup_2fa_text": "Cake 2FA radi koristeći TOTP kao drugi faktor provjere autentičnosti.\n\nCake 2FA TOTP zahtijeva SHA-512 i podršku za 8 znamenki; ovo osigurava povećanu sigurnost. Više informacija i podržanih aplikacija možete pronaći u vodiču.", - "setup_totp_recommended": "Postavite TOTP", - "disable_buy": "Onemogući kupnju", - "disable_sell": "Onemogući akciju prodaje", - "cake_2fa_preset": "Cake 2FA Preset", - "monero_dark_theme": "Monero tamna tema", - "bitcoin_dark_theme": "Bitcoin Tamna tema", - "bitcoin_light_theme": "Bitcoin Light Theme", - "high_contrast_theme": "Tema visokog kontrasta", - "matrix_green_dark_theme": "Matrix Green Dark Theme", - "monero_light_theme": "Monero lagana tema", - "auto_generate_subaddresses": "Automatski generirajte podadrese", - "narrow": "Usko", - "normal": "Normalno", - "aggressive": "Preterano", - "require_for_assessing_wallet": "Potreban za pristup novčaniku", - "require_for_sends_to_non_contacts": "Zahtijeva za slanje nekontaktima", - "require_for_sends_to_contacts": "Zahtijeva za slanje kontaktima", - "require_for_sends_to_internal_wallets": "Zahtijeva za slanje u interne novčanike", - "require_for_exchanges_to_internal_wallets": "Potreban za razmjenu na interne novčanike", - "require_for_adding_contacts": "Zahtijeva za dodavanje kontakata", - "require_for_creating_new_wallets": "Potreban za kreiranje novih novčanika", - "require_for_all_security_and_backup_settings": "Zahtijeva za sve postavke sigurnosti i sigurnosne kopije", - "available_balance_description": "Dostupno stanje je iznos koji možete potrošiti. To je vaš saldo minus bilo kakve transakcije koje su još uvijek u tijeku.", - "syncing_wallet_alert_title": "Vaš novčanik se sinkronizira", - "syncing_wallet_alert_content": "Vaš saldo i popis transakcija možda neće biti potpuni sve dok na vrhu ne piše \"SINKRONIZIRANO\". Kliknite/dodirnite da biste saznali više.", - "home_screen_settings": "Postavke početnog zaslona", - "sort_by": "Poredaj po", - "search_add_token": "Traži / Dodaj token", - "edit_token": "Uredi token", - "warning": "Upozorenje", - "add_token_warning": "Nemojte uređivati niti dodavati tokene prema uputama prevaranata.\nUvijek potvrdite adrese tokena s uglednim izvorima!", - "add_token_disclaimer_check": "Potvrdio sam adresu i informacije o ugovoru o tokenu koristeći ugledni izvor. Dodavanje zlonamjernih ili netočnih informacija može dovesti do gubitka sredstava.", - "token_contract_address": "Adresa ugovora tokena", - "token_name": "Naziv tokena npr.: Tether", - "token_symbol": "Simbol tokena npr.: USDT", - "token_decimal": "Token decimalni", - "field_required": "ovo polje je obavezno", - "pin_at_top": "prikvači ${token} na vrh", - "invalid_input": "Pogrešan unos", - "fiat_balance": "Fiat Bilans", - "gross_balance": "Bruto bilanca", - "alphabetical": "Abecedno", - "generate_name": "Generiraj ime", - "balance_page": "Stranica sa stanjem", - "share": "Udio", - "slidable": "Klizna", - "manage_nodes": "Upravljanje čvorovima", - "etherscan_history": "Etherscan povijest", - "template_name": "Naziv predloška", - "change_rep_message": "Jeste li sigurni da želite promijeniti predstavnika?", - "unsupported_asset": "Ne podržavamo ovu radnju za ovaj materijal. Izradite ili prijeđite na novčanik podržane vrste sredstava.", - "manage_pow_nodes": "Upravljanje PoW čvorovima", - "support_title_live_chat": "Podrška uživo", - "support_title_guides": "Vodiči za torte", - "support_description_guides": "Dokumentacija i podrška za uobičajena pitanja", - "support_title_other_links": "Ostale veze za podršku", - "support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama", - "choose_derivation": "Odaberite izvedbu novčanika", - "new_first_wallet_text": "Jednostavno čuvajte svoju kripto valutu", - "select_destination": "Odaberite odredište za datoteku sigurnosne kopije.", - "save_to_downloads": "Spremi u Preuzimanja", - "select_buy_provider_notice": "Odaberite gornji davatelj kupnje. Ovaj zaslon možete preskočiti postavljanjem zadanog davatelja usluga kupnje u postavkama aplikacija.", - "onramper_option_description": "Brzo kupite kriptovalute s mnogim načinima plaćanja. Dostupno u većini zemalja. Širenja i naknade variraju.", - "default_buy_provider": "Zadani davatelj kupnje", - "ask_each_time": "Pitajte svaki put", - "buy_provider_unavailable": "Davatelj trenutno nije dostupan.", - "signTransaction": "Potpišite transakciju", - "errorGettingCredentials": "Neuspješno: Pogreška prilikom dobivanja vjerodajnica", - "errorSigningTransaction": "Došlo je do pogreške prilikom potpisivanja transakcije", - "pairingInvalidEvent": "Nevažeći događaj uparivanja", - "chains": "Lanci", - "methods": "Metode", - "events": "Događaji", - "reject": "Odbiti", - "approve": "Odobriti", - "expiresOn": "Istječe", - "walletConnect": "WalletConnect", - "nullURIError": "URI je nula", - "connectWalletPrompt": "Povežite svoj novčanik s WalletConnectom za obavljanje transakcija", - "newConnection": "Nova veza", - "activeConnectionsPrompt": "Ovdje će se pojaviti aktivne veze", - "deleteConnectionConfirmationPrompt": "Jeste li sigurni da želite izbrisati vezu s", - "event": "Događaj", - "successful": "Uspješno", - "wouoldLikeToConnect": "želio bi se povezati", - "message": "Poruka", - "do_not_have_enough_gas_asset": "Nemate dovoljno ${currency} da izvršite transakciju s trenutačnim uvjetima blockchain mreže. Trebate više ${currency} da platite naknade za blockchain mrežu, čak i ako šaljete drugu imovinu.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Molimo pričekajte da dApp završi obradu.", - "copyWalletConnectLink": "Kopirajte vezu WalletConnect iz dApp-a i zalijepite je ovdje", - "enterWalletConnectURI": "Unesite WalletConnect URI", - "seed_key": "Sjemenski ključ", - "enter_seed_phrase": "Unesite svoju sjemensku frazu", - "change_rep_successful": "Uspješno promijenjena reprezentativna", - "add_contact": "Dodaj kontakt", - "exchange_provider_unsupported": "${providerName} više nije podržan!", - "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", - "order_by": "Narediti", - "creation_date": "Datum stvaranja", - "group_by_type": "Grupirati", - "importNFTs": "Uvoz NFT-ova", - "noNFTYet": "Još nema NFT-ova", - "address": "Adresa", - "enterTokenID": "Unesite ID tokena", - "tokenID": "iskaznica", - "name": "Ime", - "symbol": "Simbol", - "seed_phrase_length": "Duljina početne fraze", - "unavailable_balance": "Nedostupno stanje", - "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", - "unspent_change": "Promijeniti", - "tor_connection": "Tor veza", - "setup_warning_2fa_text": "Morat ćete obnoviti svoj novčanik iz mnemoničkog sjemena.\n\nPodrška za kolače neće vam moći pomoći ako izgubite pristup svojim 2FA ili mnemoničkim izvorima.\nCake 2FA je druga provjera autentičnosti za određene radnje u novčaniku. Prije uporabe Cake 2FA preporučujemo da pročitate vodič.NIJE siguran kao hladno skladište.\n\nAko izgubite pristup svojoj 2FA aplikaciji ili TOTP ključevima, IZGUBIT ĆETE pristup ovom novčaniku. ", - "scan_qr_on_device": "Skenirajte ovaj QR kod na drugom uređaju", - "how_to_use": "Kako koristiti", - "seed_hex_form": "Sjeme novčanika (šesterokutni oblik)", - "seedtype": "Sjemenska vrsta", - "seedtype_legacy": "Nasljeđe (25 riječi)", - "seedtype_polyseed": "Poliseed (16 riječi)", - "seed_language_czech": "češki", - "seed_language_korean": "korejski", - "ascending": "Uzlazni", - "descending": "Silazni", - "seed_language_chinese_traditional": "Kinesko (tradicionalno)", - "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", - "polygonscan_history": "Povijest PolygonScan", - "wallet_seed_legacy": "Sjeme naslijeđenog novčanika", - "default_sell_provider": "Zadani dobavljač prodaje", - "select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.", - "custom_drag": "Prilagođeni (držite i povucite)", - "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)", - "use_testnet": "Koristite TestNet", - "receivable_balance": "Stanje potraživanja", - "confirmed_tx": "Potvrđen", - "transaction_details_source_address": "Adresa izvora", - "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana.", - "contractName": "Naziv ugovora", - "contractSymbol": "Simbol ugovora", - "description": "Opis", - "camera_consent": "Vaš će fotoaparat koristiti za snimanje slike u svrhu identifikacije od strane ${provider}. Pojedinosti potražite u njihovoj politici privatnosti.", - "no_relays": "Nema releja", - "choose_relay": "Odaberite relej za korištenje", - "no_relays_message": "Pronašli smo zapis Nostr NIP-05 za ovog korisnika, ali on ne sadrži nikakve releje. Uputite primatelja da doda releje u svoj Nostr zapis.", - "no_relay_on_domain": "Ne postoji relej za korisničku domenu ili je relej nedostupan. Odaberite relej za korištenje." - "zzzz": "zzzz" + "you_will_send": "Razmijeni iz" } \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index d1a9d19f8..dff9233b0 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -704,6 +704,7 @@ "use_card_info_two": "Dana dikonversi ke USD ketika disimpan dalam akun pra-bayar, bukan dalam mata uang digital.", "use_ssl": "Gunakan SSL", "use_suggested": "Gunakan yang Disarankan", + "use_testnet": "Gunakan TestNet", "variable_pair_not_supported": "Pasangan variabel ini tidak didukung dengan bursa yang dipilih", "verification": "Verifikasi", "verify_with_2fa": "Verifikasi dengan Cake 2FA", @@ -762,268 +763,5 @@ "you_now_have_debit_card": "Anda sekarang memiliki kartu debit", "you_pay": "Anda Membayar", "you_will_get": "Konversi ke", - "you_will_send": "Konversi dari", - "yy": "YY", - "online": "Online", - "offline": "Offline", - "gift_card_number": "Nomor Kartu Hadiah", - "pin_number": "Nomor PIN", - "total_saving": "Total Pembayaran", - "last_30_days": "30 hari terakhir", - "avg_savings": "Rata-rata Pembayaran", - "view_all": "Lihat Semua", - "active_cards": "Kartu Aktif", - "delete_account": "Hapus Akun", - "cards": "Kartu", - "active": "Aktif", - "redeemed": "Ditukar", - "gift_card_balance_note": "Kartu hadiah dengan saldo yang tersisa akan muncul di sini", - "gift_card_redeemed_note": "Kartu hadiah yang sudah Anda tukar akan muncul di sini", - "logout": "Keluar", - "add_tip": "Tambahkan Tip", - "percentageOf": "dari ${amount}", - "is_percentage": "adalah", - "search_category": "Cari kategori", - "mark_as_redeemed": "Tandai sebagai Ditukar", - "more_options": "Opsi Lainnya", - "awaiting_payment_confirmation": "Menunggu Konfirmasi Pembayaran", - "transaction_sent_notice": "Jika layar tidak bergerak setelah 1 menit, periksa block explorer dan email Anda.", - "agree": "Setuju", - "in_store": "Di Toko", - "generating_gift_card": "Membuat Kartu Hadiah", - "payment_was_received": "Pembayaran Anda telah diterima.", - "proceed_after_one_minute": "Jika layar tidak bergerak setelah 1 menit, periksa email Anda.", - "order_id": "ID Pesanan", - "gift_card_is_generated": "Kartu Hadiah telah dibuat", - "open_gift_card": "Buka Kartu Hadiah", - "contact_support": "Hubungi Dukungan", - "gift_cards_unavailable": "Kartu hadiah hanya tersedia untuk dibeli dengan Monero, Bitcoin, dan Litecoin saat ini", - "introducing_cake_pay": "Perkenalkan Cake Pay!", - "cake_pay_learn_more": "Beli dan tukar kartu hadiah secara instan di aplikasi!\nGeser ke kanan untuk informasi lebih lanjut.", - "automatic": "Otomatis", - "fixed_pair_not_supported": "Pasangan tetap ini tidak didukung dengan bursa yang dipilih", - "variable_pair_not_supported": "Pasangan variabel ini tidak didukung dengan bursa yang dipilih", - "none_of_selected_providers_can_exchange": "Tidak ada dari penyedia yang dipilih yang dapat melakukan pertukaran ini", - "choose_one": "Pilih satu", - "choose_from_available_options": "Pilih dari pilihan yang tersedia:", - "custom_redeem_amount": "Jumlah Tukar Kustom", - "add_custom_redemption": "Tambahkan Tukar Kustom", - "remaining": "sisa", - "delete_wallet": "Hapus dompet", - "delete_wallet_confirm_message": "Apakah Anda yakin ingin menghapus dompet ${wallet_name}?", - "low_fee": "Biaya rendah", - "low_fee_alert": "Anda saat ini menggunakan prioritas biaya jaringan rendah. Ini dapat menyebabkan tunggu yang lama, kurs yang berbeda, atau perdagangan yang dibatalkan. Kami merekomendasikan menetapkan biaya yang lebih tinggi untuk pengalaman yang lebih baik.", - "ignor": "Abaikan", - "use_suggested": "Gunakan yang Disarankan", - "do_not_share_warning_text": "Jangan berikan ini pada siapapun, termasuk dukungan.\n\nDana Anda bisa dan akan dicuri!", - "help": "bantuan", - "all_transactions": "Semua transaksi", - "all_trades": "Semua perdagangan", - "connection_sync": "Koneksi dan sinkronisasi", - "security_and_backup": "Keamanan dan cadangan", - "create_backup": "Buat cadangan", - "privacy_settings": "Pengaturan privasi", - "privacy": "Privasi", - "display_settings": "Pengaturan tampilan", - "other_settings": "Pengaturan lainnya", - "require_pin_after": "Meminta PIN setelah", - "always": "Selalu", - "minutes_to_pin_code": "${minute} menit", - "disable_exchange": "Nonaktifkan pertukaran", - "advanced_settings": "Pengaturan lanjutan", - "settings_can_be_changed_later": "Pengaturan ini dapat diubah nanti di pengaturan aplikasi", - "add_custom_node": "Tambahkan Node Kustom Baru", - "disable_fiat": "Nonaktifkan fiat", - "fiat_api": "API fiat", - "disabled": "Dinonaktifkan", - "enabled": "Diaktifkan", - "tor_only": "Hanya Tor", - "unmatched_currencies": "Mata uang dompet Anda saat ini tidak cocok dengan yang ditandai QR", - "orbot_running_alert": "Pastikan Orbot sedang berjalan sebelum menghubungkan ke node ini.", - "contact_list_contacts": "Kontak", - "contact_list_wallets": "Dompet Saya", - "decimal_places_error": "Terlalu banyak tempat desimal", - "edit_node": "Sunting Node", - "invoice_details": "Detail faktur", - "donation_link_details": "Detail tautan donasi", - "anonpay_description": "Hasilkan ${type}. Penerima dapat ${method} dengan cryptocurrency apa pun yang didukung, dan Anda akan menerima dana di dompet ini.", - "create_invoice": "Buat faktur", - "create_donation_link": "Buat tautan donasi", - "optional_email_hint": "Email pemberitahuan penerima pembayaran opsional", - "optional_description": "Deskripsi opsional", - "optional_name": "Nama penerima opsional", - "clearnet_link": "Tautan clearnet", - "onion_link": "Tautan bawang", - "sell_monero_com_alert_content": "Menjual Monero belum didukung", - "error_text_input_below_minimum_limit": "Jumlah kurang dari minimal", - "error_text_input_above_maximum_limit": "Jumlah lebih dari maksimal", - "show_market_place": "Tampilkan Pasar", - "prevent_screenshots": "Cegah tangkapan layar dan perekaman layar", - "profile": "Profil", - "close": "Menutup", - "modify_2fa": "Ubah Kue 2FA", - "disable_cake_2fa": "Nonaktifkan Kue 2FA", - "question_to_disable_2fa": "Apakah Anda yakin ingin menonaktifkan Cake 2FA? Kode 2FA tidak lagi diperlukan untuk mengakses dompet dan fungsi tertentu.", - "disable": "Cacat", - "setup_2fa": "Siapkan Kue 2FA", - "verify_with_2fa": "Verifikasi dengan Cake 2FA", - "totp_code": "Kode TOTP", - "please_fill_totp": "Harap isi kode 8 digit yang ada di perangkat Anda yang lain", - "totp_2fa_success": "Kesuksesan! Cake 2FA diaktifkan untuk dompet ini. Ingatlah untuk menyimpan benih mnemonik Anda jika Anda kehilangan akses dompet.", - "totp_verification_success": "Verifikasi Berhasil!", - "totp_2fa_failure": "Kode salah. Silakan coba kode lain atau buat kunci rahasia baru. Gunakan aplikasi 2FA yang kompatibel yang mendukung kode 8 digit dan SHA512.", - "enter_totp_code": "Masukkan Kode TOTP.", - "add_secret_code": "Atau, tambahkan kode rahasia ini ke aplikasi autentikator", - "totp_secret_code": "Kode Rahasia TOTP", - "setup_2fa_text": "Cake 2FA bekerja menggunakan TOTP sebagai faktor otentikasi kedua.\n\nTOTP Cake 2FA memerlukan SHA-512 dan dukungan 8 digit; ini memberikan peningkatan keamanan. Informasi lebih lanjut dan aplikasi yang didukung dapat ditemukan di panduan.", - "setup_totp_recommended": "Pengaturan TOTP", - "disable_buy": "Nonaktifkan tindakan beli", - "disable_sell": "Nonaktifkan aksi jual", - "auto_generate_subaddresses": "Menghasilkan subalamat secara otomatis", - "cake_2fa_preset": "Preset Kue 2FA", - "narrow": "Sempit", - "normal": "Normal", - "aggressive": "Terlalu bersemangat", - "require_for_assessing_wallet": "Diperlukan untuk mengakses dompet", - "require_for_sends_to_non_contacts": "Wajibkan untuk mengirim ke non-kontak", - "require_for_sends_to_contacts": "Membutuhkan untuk mengirim ke kontak", - "require_for_sends_to_internal_wallets": "Diperlukan untuk mengirim ke dompet internal", - "require_for_exchanges_to_internal_wallets": "Diperlukan untuk pertukaran ke dompet internal", - "require_for_adding_contacts": "Membutuhkan untuk menambahkan kontak", - "require_for_creating_new_wallets": "Diperlukan untuk membuat dompet baru", - "require_for_all_security_and_backup_settings": "Memerlukan untuk semua pengaturan keamanan dan pencadangan", - "available_balance_description": "“Saldo yang Tersedia” atau “Saldo yang Dikonfirmasi” adalah dana yang dapat langsung dibelanjakan. Jika dana muncul di saldo bawah tetapi tidak di saldo atas, maka Anda harus menunggu beberapa menit agar dana masuk mendapatkan konfirmasi jaringan lainnya. Setelah mereka mendapatkan lebih banyak konfirmasi, mereka akan dapat dibelanjakan.", - "syncing_wallet_alert_title": "Dompet Anda sedang disinkronkan", - "syncing_wallet_alert_content": "Saldo dan daftar transaksi Anda mungkin belum lengkap sampai tertulis “SYNCHRONIZED” di bagian atas. Klik/ketuk untuk mempelajari lebih lanjut.", - "home_screen_settings": "Pengaturan layar awal", - "sort_by": "Sortir dengan", - "search_add_token": "Cari / Tambahkan token", - "edit_token": "Mengedit token", - "warning": "Peringatan", - "add_token_warning": "Jangan mengedit atau menambahkan token seperti yang diinstruksikan oleh penipu.\nSelalu konfirmasikan alamat token dengan sumber tepercaya!", - "add_token_disclaimer_check": "Saya telah mengonfirmasi alamat dan informasi kontrak token menggunakan sumber yang memiliki reputasi baik. Menambahkan informasi jahat atau salah dapat mengakibatkan hilangnya dana.", - "token_contract_address": "Alamat kontrak token", - "token_name": "Nama token misalnya: Tether", - "token_symbol": "Simbol token misalnya: USDT", - "token_decimal": "Desimal token", - "field_required": "Bagian ini diperlukan", - "pin_at_top": "sematkan ${token} di atas", - "invalid_input": "Masukan tidak valid", - "fiat_balance": "Saldo Fiat", - "gross_balance": "Saldo Kotor", - "alphabetical": "Alfabetis", - "generate_name": "Hasilkan Nama", - "balance_page": "Halaman Saldo", - "share": "Membagikan", - "slidable": "Dapat digeser", - "monero_dark_theme": "Tema Gelap Monero", - "bitcoin_dark_theme": "Tema Gelap Bitcoin", - "bitcoin_light_theme": "Tema Cahaya Bitcoin", - "high_contrast_theme": "Tema Kontras Tinggi", - "matrix_green_dark_theme": "Tema Matrix Green Dark", - "monero_light_theme": "Tema Cahaya Monero", - "manage_nodes": "Kelola node", - "etherscan_history": "Sejarah Etherscan", - "template_name": "Nama Templat", - "change_rep": "Ubah Perwakilan", - "change_rep_message": "Apakah Anda yakin ingin mengubah perwakilan?", - "unsupported_asset": "Kami tidak mendukung tindakan ini untuk aset ini. Harap buat atau alihkan ke dompet dari jenis aset yang didukung.", - "manage_pow_nodes": "Kelola Node PoW", - "support_title_live_chat": "Dukungan langsung", - "support_description_live_chat": "Gratis dan Cepat! Perwakilan dukungan terlatih tersedia untuk membantu", - "support_title_guides": "Panduan Dompet Kue", - "support_description_guides": "Dokumentasi dan dukungan untuk masalah umum", - "support_title_other_links": "Tautan dukungan lainnya", - "support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain", - "choose_derivation": "Pilih dompet dompet", - "new_first_wallet_text": "Dengan mudah menjaga cryptocurrency Anda aman", - "select_destination": "Silakan pilih tujuan untuk file cadangan.", - "save_to_downloads": "Simpan ke Unduhan", - "select_buy_provider_notice": "Pilih penyedia beli di atas. Anda dapat melewatkan layar ini dengan mengatur penyedia pembelian default Anda di pengaturan aplikasi.", - "onramper_option_description": "Beli crypto dengan cepat dengan banyak metode pembayaran. Tersedia di sebagian besar negara. Spread dan biaya bervariasi.", - "default_buy_provider": "Penyedia beli default", - "ask_each_time": "Tanyakan setiap kali", - "buy_provider_unavailable": "Penyedia saat ini tidak tersedia.", - "signTransaction": "Tandatangani Transaksi", - "errorGettingCredentials": "Gagal: Terjadi kesalahan saat mendapatkan kredensial", - "errorSigningTransaction": "Terjadi kesalahan saat menandatangani transaksi", - "pairingInvalidEvent": "Menyandingkan Acara Tidak Valid", - "chains": "Rantai", - "methods": "Metode", - "events": "Acara", - "reject": "Menolak", - "approve": "Menyetujui", - "expiresOn": "Kadaluarsa pada", - "walletConnect": "DompetConnect", - "nullURIError": "URI adalah nol", - "connectWalletPrompt": "Hubungkan dompet Anda dengan WalletConnect untuk melakukan transaksi", - "newConnection": "Koneksi Baru", - "activeConnectionsPrompt": "Koneksi aktif akan muncul di sini", - "deleteConnectionConfirmationPrompt": "Apakah Anda yakin ingin menghapus koneksi ke", - "event": "Peristiwa", - "successful": "Berhasil", - "wouoldLikeToConnect": "ingin terhubung", - "message": "Pesan", - "do_not_have_enough_gas_asset": "Anda tidak memiliki cukup ${currency} untuk melakukan transaksi dengan kondisi jaringan blockchain saat ini. Anda memerlukan lebih banyak ${currency} untuk membayar biaya jaringan blockchain, meskipun Anda mengirimkan aset yang berbeda.", - "totp_auth_url": "URL Otentikasi TOTP", - "awaitDAppProcessing": "Mohon tunggu hingga dApp menyelesaikan pemrosesan.", - "copyWalletConnectLink": "Salin tautan WalletConnect dari dApp dan tempel di sini", - "enterWalletConnectURI": "Masukkan URI WalletConnect", - "seed_key": "Kunci benih", - "enter_seed_phrase": "Masukkan frasa benih Anda", - "change_rep_successful": "Berhasil mengubah perwakilan", - "add_contact": "Tambah kontak", - "exchange_provider_unsupported": "${providerName} tidak lagi didukung!", - "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", - "order_by": "Dipesan oleh", - "creation_date": "Tanggal Pembuatan", - "group_by_type": "Grup demi jenis", - "importNFTs": "Impor NFT", - "noNFTYet": "Belum ada NFT", - "address": "Alamat", - "enterTokenID": "Masukkan ID tokennya", - "tokenID": "PENGENAL", - "name": "Nama", - "symbol": "Simbol", - "seed_phrase_length": "Panjang frase benih", - "unavailable_balance": "Saldo tidak tersedia", - "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", - "unspent_change": "Mengubah", - "tor_connection": "koneksi Tor", - "setup_warning_2fa_text": "Anda perlu memulihkan dompet Anda dari benih mnemonik.\n\nDukungan kue tidak akan dapat membantu Anda jika Anda kehilangan akses ke 2FA atau benih mnemonik.\nCake 2FA adalah otentikasi kedua untuk tindakan tertentu di dompet. Sebelum menggunakan Cake 2FA, kami sarankan untuk membaca panduannya.Ini TIDAK seaman penyimpanan dingin.\n\nJika Anda kehilangan akses ke aplikasi 2FA atau kunci TOTP, Anda AKAN kehilangan akses ke dompet ini. ", - "scan_qr_on_device": "Pindai kode QR ini di perangkat lain", - "how_to_use": "Cara Penggunaan", - "seed_hex_form": "Biji dompet (bentuk hex)", - "seedtype": "Seedtype", - "seedtype_legacy": "Legacy (25 kata)", - "seedtype_polyseed": "Polyseed (16 kata)", - "seed_language_czech": "Ceko", - "seed_language_korean": "Korea", - "ascending": "Naik", - "descending": "Menurun", - "seed_language_chinese_traditional": "Cina (tradisional)", - "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", - "polygonscan_history": "Sejarah PolygonScan", - "wallet_seed_legacy": "Biji dompet warisan", - "default_sell_provider": "Penyedia Penjualan Default", - "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.", - "custom_drag": "Khusus (tahan dan seret)", - "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", - "use_testnet": "Gunakan TestNet", - "receivable_balance": "Saldo piutang", - "confirmed_tx": "Dikonfirmasi", - "transaction_details_source_address": "Alamat sumber", - "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda.", - "contractName": "Nama Kontrak", - "contractSymbol": "Simbol Kontrak", - "description": "Keterangan", - "camera_consent": "Kamera Anda akan digunakan untuk mengambil gambar untuk tujuan identifikasi oleh ${provider}. Silakan periksa Kebijakan Privasi mereka untuk detailnya.", - "no_relays": "Tidak ada relay", - "choose_relay": "Silakan pilih relai yang akan digunakan", - "no_relays_message": "Kami menemukan catatan Nostr NIP-05 untuk pengguna ini, tetapi tidak berisi relay apa pun. Harap instruksikan penerima untuk menambahkan relay ke catatan Nostr mereka.", - "no_relay_on_domain": "Tidak ada relai untuk domain pengguna atau relai tidak tersedia. Silakan pilih relai yang akan digunakan." - "zzzz": "zzzz" + "you_will_send": "Konversi dari" } \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index e0668dfe9..71a858d58 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -715,6 +715,7 @@ "use_card_info_two": "I fondi vengono convertiti in USD quando sono detenuti nel conto prepagato, non in valute digitali.", "use_ssl": "Usa SSL", "use_suggested": "Usa suggerito", + "use_testnet": "Usa TestNet", "variable_pair_not_supported": "Questa coppia di variabili non è supportata con gli scambi selezionati", "verification": "Verifica", "verify_with_2fa": "Verifica con Cake 2FA", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "Ora hai una carta di debito", "you_pay": "Tu paghi", "you_will_get": "Converti a", - "you_will_send": "Conveti da", - "yy": "YY", - "online": "in linea", - "offline": "Offline", - "gift_card_number": "Numero del buono regalo", - "pin_number": "Numero PIN", - "total_saving": "Risparmio totale", - "last_30_days": "Ultimi 30 giorni", - "avg_savings": "Risparmio medio", - "view_all": "Visualizza tutto", - "active_cards": "Carte attive", - "delete_account": "Elimina account", - "cards": "Carte", - "active": "Attivo", - "redeemed": "Redento", - "gift_card_balance_note": "Le carte regalo con un saldo residuo appariranno qui", - "gift_card_redeemed_note": "Le carte regalo che hai riscattato appariranno qui", - "logout": "Logout", - "add_tip": "Aggiungi suggerimento", - "percentageOf": "di ${amount}", - "is_percentage": "è", - "search_category": "Categoria di ricerca", - "mark_as_redeemed": "Segna come riscattato", - "more_options": "Altre opzioni", - "waiting_payment_confirmation": "In attesa di conferma del pagamento", - "transaction_sent_notice": "Se lo schermo non procede dopo 1 minuto, controlla un block explorer e la tua email.", - "agree": "d'accordo", - "in_store": "In negozio", - "generating_gift_card": "Generazione carta regalo", - "payment_was_received": "Il tuo pagamento è stato ricevuto.", - "proceed_after_one_minute": "Se lo schermo non procede dopo 1 minuto, controlla la tua email.", - "order_id": "ID ordine", - "gift_card_is_generated": "Il buono regalo è stato generato", - "open_gift_card": "Apri carta regalo", - "contact_support": "Contatta l'assistenza", - "gift_cards_unavailable": "Le carte regalo sono disponibili per l'acquisto solo tramite Monero, Bitcoin e Litecoin in questo momento", - "background_sync_mode": "Modalità di sincronizzazione in background", - "sync_all_wallets": "Sincronizza tutti i portafogli", - "introducing_cake_pay": "Presentazione di Cake Pay!", - "cake_pay_learn_more": "Acquista e riscatta istantaneamente carte regalo nell'app!\nScorri da sinistra a destra per saperne di più.", - "automatic": "Automatico", - "fixed_pair_not_supported": "Questa coppia fissa non è supportata con gli scambi selezionati", - "variable_pair_not_supported": "Questa coppia di variabili non è supportata con gli scambi selezionati", - "none_of_selected_providers_can_exchange": "Nessuno dei fornitori selezionati può effettuare questo scambio", - "choose_one": "Scegline uno", - "choose_from_available_options": "Scegli tra le opzioni disponibili:", - "custom_redeem_amount": "Importo di riscatto personalizzato", - "add_custom_redemption": "Aggiungi riscatto personalizzato", - "remaining": "rimanente", - "delete_wallet": "Elimina portafoglio", - "delete_wallet_confirm_message": "Sei sicuro di voler eliminare il portafoglio ${wallet_name}?", - "low_fee": "Tariffa bassa", - "low_fee_alert": "Attualmente stai utilizzando una priorità a tariffa di rete bassa. Ciò potrebbe causare lunghe attese, tariffe diverse o operazioni annullate. Ti consigliamo di impostare una tariffa più alta per un'esperienza migliore.", - "ignor": "Ignorare", - "use_suggested": "Usa suggerito", - "do_not_share_warning_text": "Non condividerli con nessun altro, incluso il supporto.\n\nI tuoi fondi possono e saranno rubati!", - "help": "aiuto", - "all_transactions": "Sve transakcije", - "all_trades": "Svi obrti", - "connection_sync": "Connessione e sincronizzazione", - "security_and_backup": "Sicurezza e backup", - "create_backup": "Crea backup", - "privacy_settings": "Impostazioni privacy", - "privacy": "Privacy", - "display_settings": "Impostazioni di visualizzazione", - "other_settings": "Altre impostazioni", - "require_pin_after": "Richiedi PIN dopo", - "always": "sempre", - "minutes_to_pin_code": "${minute} minuti", - "disable_exchange": "Disabilita scambio", - "advanced_settings": "Impostazioni avanzate", - "settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app", - "add_custom_node": "Aggiungi nuovo nodo personalizzato", - "disable_fiat": "Disabilita fiat", - "fiat_api": "Fiat API", - "disabled": "Disabilitato", - "enabled": "Abilitato", - "tor_only": "Solo Tor", - "unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato", - "orbot_running_alert": "Assicurati che Orbot sia in esecuzione prima di connetterti a questo nodo.", - "contact_list_contacts": "Contatti", - "contact_list_wallets": "I miei portafogli", - "bitcoin_payments_require_1_confirmation": "I pagamenti in bitcoin richiedono 1 conferma, che può richiedere 20 minuti o più. Grazie per la vostra pazienza! Riceverai un'e-mail quando il pagamento sarà confermato.", - "send_to_this_address": "Invia ${currency} ${tag}a questo indirizzo", - "arrive_in_this_address": "${currency} ${tag}arriverà a questo indirizzo", - "do_not_send": "Non inviare", - "error_dialog_content": "Spiacenti, abbiamo riscontrato un errore.\n\nSi prega di inviare il rapporto sull'arresto anomalo al nostro team di supporto per migliorare l'applicazione.", - "scan_qr_code": "Scansiona il codice QR", - "cold_or_recover_wallet": "Aggiungi un cold wallet o recupera un paper wallet", - "please_wait": "Attendere prego", - "sweeping_wallet": "Portafoglio ampio", - "sweeping_wallet_alert": "Questo non dovrebbe richiedere molto tempo. NON LASCIARE QUESTA SCHERMATA O I FONDI SPAZZATI POTREBBERO ANDARE PERSI", - "decimal_places_error": "Troppe cifre decimali", - "edit_node": "Modifica nodo", - "invoice_details": "Dettagli della fattura", - "donation_link_details": "Dettagli del collegamento alla donazione", - "anonpay_description": "Genera ${type}. Il destinatario può ${method} con qualsiasi criptovaluta supportata e riceverai fondi in questo portafoglio.", - "create_invoice": "Crea fattura", - "create_donation_link": "Crea un link per la donazione", - "optional_email_hint": "Email di notifica del beneficiario facoltativa", - "optional_description": "Descrizione facoltativa", - "optional_name": "Nome del destinatario facoltativo", - "clearnet_link": "Collegamento Clearnet", - "onion_link": "Collegamento a cipolla", - "settings": "Impostazioni", - "sell_monero_com_alert_content": "La vendita di Monero non è ancora supportata", - "error_text_input_below_minimum_limit": "L'ammontare è inferiore al minimo", - "error_text_input_above_maximum_limit": "L'ammontare è superiore al massimo", - "show_market_place": "Mostra mercato", - "prevent_screenshots": "Impedisci screenshot e registrazione dello schermo", - "profile": "Profilo", - "close": "Chiudere", - "modify_2fa": "Modifica Torta 2FA", - "disable_cake_2fa": "Disabilita Cake 2FA", - "question_to_disable_2fa": "Sei sicuro di voler disabilitare Cake 2FA? Non sarà più necessario un codice 2FA per accedere al portafoglio e ad alcune funzioni.", - "disable": "disattivare", - "setup_2fa": "Imposta la torta 2FA", - "verify_with_2fa": "Verifica con Cake 2FA", - "totp_code": "Codice TOTP", - "please_fill_totp": "Inserisci il codice di 8 cifre presente sull'altro tuo dispositivo", - "totp_2fa_success": "Successo! Cake 2FA abilitato per questo portafoglio. Ricordati di salvare il tuo seme mnemonico nel caso in cui perdi l'accesso al portafoglio.", - "totp_verification_success": "Verifica riuscita!", - "totp_2fa_failure": "Codice non corretto. Prova un codice diverso o genera una nuova chiave segreta. Utilizza un'app 2FA compatibile che supporti codici a 8 cifre e SHA512.", - "enter_totp_code": "Inserisci il codice TOTP.", - "add_secret_code": "Oppure aggiungi questo codice segreto a un'app di autenticazione", - "totp_secret_code": "TOTP codice segreto", - "setup_2fa_text": "Cake 2FA funziona utilizzando TOTP come secondo fattore di autenticazione.\n\nIl TOTP di Cake 2FA richiede il supporto SHA-512 e 8 cifre; ciò fornisce una maggiore sicurezza. Maggiori informazioni e app supportate sono disponibili nella guida.", - "setup_totp_recommended": "Imposta TOTP", - "disable_buy": "Disabilita l'azione di acquisto", - "disable_sell": "Disabilita l'azione di vendita", - "auto_generate_subaddresses": "Genera automaticamente sottindirizzi", - "cake_2fa_preset": "Torta 2FA Preset", - "narrow": "Stretto", - "normal": "Normale", - "aggressive": "Fervente", - "require_for_assessing_wallet": "Richiesto per l'accesso al portafoglio", - "require_for_sends_to_non_contacts": "Richiesto per invii a non contatti", - "require_for_sends_to_contacts": "Richiedi per gli invii ai contatti", - "require_for_sends_to_internal_wallets": "Richiesto per invii a portafogli interni", - "require_for_exchanges_to_internal_wallets": "Richiedi per gli scambi ai portafogli interni", - "require_for_adding_contacts": "Richiesto per l'aggiunta di contatti", - "require_for_creating_new_wallets": "Richiesto per la creazione di nuovi portafogli", - "require_for_all_security_and_backup_settings": "Richiedi per tutte le impostazioni di sicurezza e backup", - "available_balance_description": "Il saldo disponibile è il saldo totale meno i fondi congelati. I fondi congelati sono fondi che sono stati inviati ma non sono ancora stati confermati.", - "syncing_wallet_alert_title": "Il tuo portafoglio si sta sincronizzando", - "syncing_wallet_alert_content": "Il saldo e l'elenco delle transazioni potrebbero non essere completi fino a quando non viene visualizzato \"SYNCHRONIZED\" in alto. Clicca/tocca per saperne di più.", - "home_screen_settings": "Impostazioni della schermata iniziale", - "sort_by": "Ordina per", - "search_add_token": "Cerca / Aggiungi token", - "edit_token": "Modifica token", - "warning": "Avvertimento", - "add_token_warning": "Non modificare o aggiungere token come indicato dai truffatori.\nConferma sempre gli indirizzi dei token con fonti attendibili!", - "add_token_disclaimer_check": "Ho confermato l'indirizzo e le informazioni del contratto token utilizzando una fonte attendibile. L'aggiunta di informazioni dannose o errate può comportare una perdita di fondi.", - "token_contract_address": "Indirizzo del contratto token", - "token_name": "Nome del token, ad esempio: Tether", - "token_symbol": "Simbolo del token, ad esempio: USDT", - "token_decimal": "Decimale del token", - "field_required": "Questo campo è obbligatorio", - "pin_at_top": "fissa ${token} in alto", - "invalid_input": "Inserimento non valido", - "fiat_balance": "Equilibrio fiat", - "gross_balance": "Saldo lordo", - "alphabetical": "Alfabetico", - "generate_name": "Genera nome", - "balance_page": "Pagina di equilibrio", - "share": "Condividere", - "slidable": "Scorrevole", - "monero_dark_theme": "Tema scuro di Monero", - "bitcoin_dark_theme": "Tema oscuro di Bitcoin", - "bitcoin_light_theme": "Tema luce Bitcoin", - "high_contrast_theme": "Tema ad alto contrasto", - "matrix_green_dark_theme": "Tema Matrix verde scuro", - "monero_light_theme": "Tema leggero Monero", - "manage_nodes": "Gestisci i nodi", - "etherscan_history": "Storia Etherscan", - "template_name": "Nome modello", - "change_rep": "Cambia rappresentante", - "change_rep_message": "Sei sicuro di voler cambiare rappresentante?", - "unsupported_asset": "Non supportiamo questa azione per questa risorsa. Crea o passa a un portafoglio di un tipo di asset supportato.", - "manage_pow_nodes": "Gestisci i nodi PoW", - "support_title_live_chat": "Supporto dal vivo", - "support_description_live_chat": "Gratuito e veloce! I rappresentanti di supporto qualificati sono disponibili per assistere", - "support_title_guides": "Guide del portafoglio per torte", - "support_description_guides": "Documentazione e supporto per problemi comuni", - "support_title_other_links": "Altri collegamenti di supporto", - "support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi", - "choose_derivation": "Scegli la derivazione del portafoglio", - "new_first_wallet_text": "Mantieni facilmente la tua criptovaluta al sicuro", - "select_destination": "Seleziona la destinazione per il file di backup.", - "save_to_downloads": "Salva in Download", - "select_buy_provider_notice": "Seleziona un fornitore di acquisto sopra. È possibile saltare questa schermata impostando il provider di acquisto predefinito nelle impostazioni dell'app.", - "onramper_option_description": "Acquista rapidamente la criptovaluta con molti metodi di pagamento. Disponibile nella maggior parte dei paesi. Gli spread e le commissioni variano.", - "default_buy_provider": "Provider di acquisto predefinito", - "ask_each_time": "Chiedi ogni volta", - "buy_provider_unavailable": "Provider attualmente non disponibile.", - "signTransaction": "Firma la transazione", - "errorGettingCredentials": "Non riuscito: errore durante il recupero delle credenziali", - "errorSigningTransaction": "Si è verificato un errore durante la firma della transazione", - "pairingInvalidEvent": "Associazione evento non valido", - "chains": "Catene", - "methods": "Metodi", - "events": "Eventi", - "reject": "Rifiutare", - "approve": "Approvare", - "expiresOn": "Scade il", - "walletConnect": "PortafoglioConnetti", - "nullURIError": "L'URI è nullo", - "connectWalletPrompt": "Collega il tuo portafoglio con WalletConnect per effettuare transazioni", - "newConnection": "Nuova connessione", - "activeConnectionsPrompt": "Le connessioni attive verranno visualizzate qui", - "deleteConnectionConfirmationPrompt": "Sei sicuro di voler eliminare la connessione a", - "event": "Evento", - "successful": "Riuscito", - "wouoldLikeToConnect": "vorrei connettermi", - "message": "Messaggio", - "do_not_have_enough_gas_asset": "Non hai abbastanza ${currency} per effettuare una transazione con le attuali condizioni della rete blockchain. Hai bisogno di più ${currency} per pagare le commissioni della rete blockchain, anche se stai inviando una risorsa diversa.", - "totp_auth_url": "URL DI AUT. TOTP", - "awaitDAppProcessing": "Attendi gentilmente che la dApp termini l'elaborazione.", - "copyWalletConnectLink": "Copia il collegamento WalletConnect dalla dApp e incollalo qui", - "enterWalletConnectURI": "Inserisci l'URI di WalletConnect", - "seed_key": "Chiave di semi", - "enter_seed_phrase": "Inserisci la tua frase di semi", - "change_rep_successful": "Rappresentante modificato con successo", - "add_contact": "Aggiungi contatto", - "exchange_provider_unsupported": "${providerName} non è più supportato!", - "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", - "order_by": "Ordinato da", - "creation_date": "Data di creazione", - "group_by_type": "Gruppo per tipo", - "importNFTs": "Importa NFT", - "noNFTYet": "Nessun NFT ancora", - "address": "Indirizzo", - "enterTokenID": "Inserisci l'ID del token", - "tokenID": "ID", - "name": "Nome", - "symbol": "Simbolo", - "seed_phrase_length": "Lunghezza della frase seed", - "unavailable_balance": "Saldo non disponibile", - "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", - "unspent_change": "Modifica", - "tor_connection": "Connessione Tor", - "setup_warning_2fa_text": "Dovrai ripristinare il tuo portafoglio dal seme mnemonico.\n\nIl supporto di Cake non sarà in grado di assisterti se perdi l'accesso ai tuoi seed 2FA o mnemonici.\nCake 2FA è una seconda autenticazione per determinate azioni nel portafoglio. Prima di utilizzare Cake 2FA, ti consigliamo di leggere la guida.NON è sicuro come la conservazione a freddo.\n\nSe perdi l'accesso alla tua app 2FA o alle chiavi TOTP, perderai l'accesso a questo portafoglio. ", - "scan_qr_on_device": "Scansiona questo codice QR su un altro dispositivo", - "how_to_use": "Come usare", - "seed_hex_form": "Seme di portafoglio (forma esadecimale)", - "seedtype": "Seedtype", - "seedtype_legacy": "Legacy (25 parole)", - "seedtype_polyseed": "Polyseed (16 parole)", - "seed_language_czech": "ceco", - "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Cinese tradizionale)", - "ascending": "Ascendente", - "descending": "Discendente", - "dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa", - "polygonscan_history": "Cronologia PolygonScan", - "wallet_seed_legacy": "Seme di portafoglio legacy", - "default_sell_provider": "Fornitore di vendita predefinito", - "select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.", - "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)", - "use_testnet": "Usa TestNet", - "receivable_balance": "Bilanciamento creditizio", - "confirmed_tx": "Confermato", - "transaction_details_source_address": "Indirizzo di partenza", - "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa.", - "contractName": "Nome del contratto", - "contractSymbol": "Simbolo del contratto", - "description": "Descrizione", - "camera_consent": "La tua fotocamera verrà utilizzata per acquisire un'immagine a scopo identificativo da ${provider}. Si prega di controllare la loro Informativa sulla privacy per i dettagli.", - "no_relays": "Nessun relè", - "choose_relay": "Scegli un relè da utilizzare", - "no_relays_message": "Abbiamo trovato un record Nostr NIP-05 per questo utente, ma non contiene alcun relè. Si prega di indicare al destinatario di aggiungere inoltri al proprio record Nostr.", - "no_relay_on_domain": "Non esiste un inoltro per il dominio dell'utente oppure l'inoltro non è disponibile. Scegli un relè da utilizzare." - "zzzz": "Zzzz" + "you_will_send": "Conveti da" } \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 0c832726f..eca1b1792 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -716,6 +716,7 @@ "use_card_info_two": "デジタル通貨ではなく、プリペイドアカウントで保持されている場合、資金は米ドルに変換されます。", "use_ssl": "SSLを使用する", "use_suggested": "推奨を使用", + "use_testnet": "テストネットを使用します", "variable_pair_not_supported": "この変数ペアは、選択した取引所ではサポートされていません", "verification": "検証", "verify_with_2fa": "Cake 2FA で検証する", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "デビットカードができました", "you_pay": "あなたが支払う", "you_will_get": "に変換", - "you_will_send": "から変換", - "yy": "YY", - "online": "オンライン", - "offline": "オフライン", - "gift_card_number": "ギフトカード番号", - "pin_number": "PIN番号", - "total_saving": "合計節約額", - "last_30_days": "過去30日", - "avg_savings": "平均節約額", - "view_all": "すべて表示", - "active_cards": "アクティブカード", - "delete_account": "アカウントの削除", - "cards": "カード", - "active": "アクティブ", - "redeemed": "償還", - "gift_card_balance_note": "残高が残っているギフトカードがここに表示されます", - "gift_card_redeemed_note": "利用したギフトカードがここに表示されます", - "logout": "ログアウト", - "add_tip": "ヒントを追加", - "percentageOf": "of ${amount}", - "is_percentage": "is", - "search_category": "検索カテゴリ", - "mark_as_redeemed": "償還済みとしてマーク", - "more_options": "その他のオプション", - "awaiting_payment_confirmation": "支払い確認を待っています", - "transaction_sent_notice": "1分経っても画面が進まない場合は、ブロックエクスプローラーとメールアドレスを確認してください。", - "agree": "同意する", - "in_store": "インストア", - "generated_gift_card": "ギフトカードの生成", - "payment_was_received": "お支払いを受け取りました。", - "proceed_after_one_minute": "1分経っても画面が進まない場合は、メールを確認してください。", - "order_id": "注文ID", - "gift_card_is_generated": "ギフトカードが生成されます", - "open_gift_card": "オープンギフトカード", - "contact_support": "サポートに連絡する", - "gift_cards_unavailable": "現時点では、ギフトカードはMonero、Bitcoin、Litecoinからのみ購入できます。", - "background_sync_mode": "バックグラウンド同期モード", - "sync_all_wallets": "すべてのウォレットを同期", - "introducing_cake_pay": "序章Cake Pay!", - "cake_pay_learn_more": "アプリですぐにギフトカードを購入して引き換えましょう!\n左から右にスワイプして詳細をご覧ください。", - "automatic": "自動", - "fixed_pair_not_supported": "この固定ペアは、選択したエクスチェンジではサポートされていません", - "variable_pair_not_supported": "この変数ペアは、選択した取引所ではサポートされていません", - "none_of_selected_providers_can_exchange": "選択したプロバイダーはいずれもこの交換を行うことができません", - "choose_one": "1 つ選択してください", - "choose_from_available_options": "利用可能なオプションから選択してください:", - "custom_redeem_amount": "カスタム交換金額", - "add_custom_redemption": "カスタム引き換えを追加", - "remaining": "残り", - "delete_wallet": "ウォレットを削除", - "delete_wallet_confirm_message": "${wallet_name} ウォレットを削除してもよろしいですか?", - "low_fee": "低料金", - "low_fee_alert": "現在、低ネットワーク料金優先度を使用しています。これにより、長い待ち時間、異なるレート、またはキャンセルされた取引が発生する可能性があります。より良い体験のために、より高い料金を設定することをお勧めします。", - "ignor": "無視", - "use_suggested": "推奨を使用", - "do_not_share_warning_text": "サポートを含め、これらを他の誰とも共有しないでください。\n\nあなたの資金は盗まれる可能性があります!", - "help": "ヘルプ", - "all_transactions": "全取引", - "all_trades": "すべての取引", - "connection_sync": "接続と同期", - "security_and_backup": "セキュリティとバックアップ", - "create_backup": "バックアップを作成", - "privacy_settings": "プライバシー設定", - "privacy": "プライバシー", - "display_settings": "表示設定", - "other_settings": "その他の設定", - "require_pin_after": "後に PIN が必要", - "always": "いつも", - "minutes_to_pin_code": "${minute} 分", - "disable_exchange": "交換を無効にする", - "advanced_settings": "高度な設定", - "settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます", - "add_custom_node": "新しいカスタム ノードを追加", - "disable_fiat": "フィアットを無効にする", - "fiat_api": "不換紙幣 API", - "disabled": "無効", - "enabled": "有効", - "tor_only": "Torのみ", - "unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません", - "orbot_running_alert": "このノードに接続する前に、Orbot が実行されていることを確認してください", - "contact_list_contacts": "連絡先", - "contact_list_wallets": "マイウォレット", - "bitcoin_payments_require_1_confirmation": "ビットコインの支払いには 1 回の確認が必要で、これには 20 分以上かかる場合があります。お待ち頂きまして、ありがとうございます!支払いが確認されると、メールが送信されます。", - "send_to_this_address": "${currency} ${tag}をこのアドレスに送金", - "arrive_in_this_address": "${currency} ${tag}はこの住所に到着します", - "do_not_send": "送信しない", - "error_dialog_content": "エラーが発生しました。\n\nアプリケーションを改善するために、クラッシュ レポートをサポート チームに送信してください。", - "scan_qr_code": "QRコードをスキャン", - "cold_or_recover_wallet": "コールド ウォレットを追加するか、ペーパー ウォレットを復元する", - "please_wait": "お待ちください", - "sweeping_wallet": "スイープウォレット", - "sweeping_wallet_alert": "これには時間がかかりません。この画面から離れないでください。そうしないと、スイープ ファンドが失われる可能性があります", - "decimal_places_error": "小数点以下の桁数が多すぎる", - "edit_node": "ノードを編集", - "invoice_details": "請求の詳細", - "donation_link_details": "寄付リンクの詳細", - "anonpay_description": "${type} を生成します。受取人はサポートされている任意の暗号通貨で ${method} でき、あなたはこのウォレットで資金を受け取ります。", - "create_invoice": "請求書の作成", - "create_donation_link": "寄付リンクを作成", - "optional_email_hint": "オプションの受取人通知メール", - "optional_description": "オプションの説明", - "optional_name": "オプションの受信者名", - "clearnet_link": "クリアネット リンク", - "onion_link": "オニオンリンク", - "settings": "設定", - "sell_monero_com_alert_content": "モネロの販売はまだサポートされていません", - "error_text_input_below_minimum_limit": "金額は最小額より少ない", - "error_text_input_above_maximum_limit": "金額は最大値を超えています", - "show_market_place": "マーケットプレイスを表示", - "prevent_screenshots": "スクリーンショットと画面録画を防止する", - "profile": "プロフィール", - "close": "近い", - "modify_2fa": "ケーキの 2FA を変更する", - "disable_cake_2fa": "Cake 2FA を無効にする", - "question_to_disable_2fa": "Cake 2FA を無効にしてもよろしいですか?ウォレットと特定の機能にアクセスするために 2FA コードは必要なくなります。", - "disable": "無効にする", - "setup_2fa": "セットアップ ケーキ 2FA", - "verify_with_2fa": "Cake 2FA で検証する", - "totp_code": "TOTP コード", - "please_fill_totp": "他のデバイスにある 8 桁のコードを入力してください", - "totp_2fa_success": "成功!このウォレットでは Cake 2FA が有効になっています。ウォレットへのアクセスを失った場合に備えて、ニーモニック シードを忘れずに保存してください。", - "totp_verification_success": "検証成功!", - "totp_2fa_failure": "コードが正しくありません。 別のコードを試すか、新しい秘密鍵を生成してください。 8 桁のコードと SHA512 をサポートする互換性のある 2FA アプリを使用してください。", - "enter_totp_code": "TOTPコードを入力してください。", - "add_secret_code": "または、このシークレット コードを認証アプリに追加します", - "totp_secret_code": "TOTPシークレットコード", - "setup_2fa_text": "Cake 2FA は、TOTP を 2 番目の認証要素として使用して機能します。\n\nCake 2FA の TOTP には SHA-512 と 8 桁のサポートが必要です。これによりセキュリティが強化されます。詳細とサポートされているアプリについてはガイドをご覧ください。", - "setup_totp_recommended": "TOTPのセットアップ", - "disable_buy": "購入アクションを無効にする", - "disable_sell": "販売アクションを無効にする", - "cake_2fa_preset": "ケーキ 2FA プリセット", - "narrow": "狭い", - "normal": "普通", - "aggressive": "熱心すぎる", - "require_for_assessing_wallet": "ウォレットにアクセスするために必要です", - "require_for_sends_to_non_contacts": "非連絡先への送信に必須", - "require_for_sends_to_contacts": "連絡先に送信する場合に必須", - "require_for_sends_to_internal_wallets": "内部ウォレットへの送信に必須", - "require_for_exchanges_to_internal_wallets": "内部ウォレットへの交換に必要", - "require_for_adding_contacts": "連絡先の追加に必要", - "require_for_creating_new_wallets": "新しいウォレットを作成するために必要です", - "require_for_all_security_and_backup_settings": "すべてのセキュリティおよびバックアップ設定に必須", - "available_balance_description": "利用可能な残高は、ウォレットの残高から冷凍残高を差し引いたものです。", - "syncing_wallet_alert_title": "ウォレットは同期中です", - "syncing_wallet_alert_content": "上部に「同期済み」と表示されるまで、残高と取引リストが完了していない可能性があります。詳細については、クリック/タップしてください。", - "home_screen_settings": "ホーム画面の設定", - "sort_by": "並び替え", - "search_add_token": "トークンの検索/追加", - "edit_token": "トークンの編集", - "warning": "警告", - "add_token_warning": "詐欺師の指示に従ってトークンを編集または追加しないでください。\nトークン アドレスは常に信頼できる情報源で確認してください。", - "add_token_disclaimer_check": "信頼できる情報源を使用して、トークン コントラクトのアドレスと情報を確認しました。 悪意のある情報や不正確な情報を追加すると、資金が失われる可能性があります。", - "token_contract_address": "トークンコントラクトアドレス", - "token_name": "トークン名 例: Tether", - "token_symbol": "トークンシンボル 例: USDT", - "token_decimal": "トークン10進数", - "field_required": "この項目は必須です", - "pin_at_top": "${token} を上部に固定します", - "invalid_input": "無効入力", - "fiat_balance": "フィアットバランス", - "gross_balance": "グロス残高", - "alphabetical": "アルファベット順", - "generate_name": "名前の生成", - "balance_page": "残高ページ", - "share": "共有", - "slidable": "スライド可能", - "monero_dark_theme": "モネロダークテーマ", - "bitcoin_dark_theme": "ビットコインダークテーマ", - "bitcoin_light_theme": "ビットコインライトテーマ", - "high_contrast_theme": "ハイコントラストテーマ", - "matrix_green_dark_theme": "マトリックスグリーンダークテーマ", - "monero_light_theme": "モネロ ライト テーマ", - "manage_nodes": "ノードの管理", - "etherscan_history": "イーサスキャンの歴史", - "template_name": "テンプレート名", - "change_rep": "代表者の変更", - "change_rep_message": "代表者を変更してもよろしいですか?", - "unsupported_asset": "このアセットに対するこのアクションはサポートされていません。サポートされているアセットタイプのウォレットを作成するか、ウォレットに切り替えてください。", - "manage_pow_nodes": "PoWノードの管理", - "support_title_live_chat": "ライブサポート", - "support_description_live_chat": "無料で速い!訓練されたサポート担当者が支援することができます", - "support_title_guides": "ケーキウォレットガイド", - "support_description_guides": "一般的な問題のドキュメントとサポート", - "support_title_other_links": "その他のサポートリンク", - "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください", - "choose_derivation": "ウォレット派生を選択します", - "new_first_wallet_text": "暗号通貨を簡単に安全に保ちます", - "select_destination": "バックアップファイルの保存先を選択してください。", - "auto_generate_subaddresses": "Autoはサブアドレスを生成します", - "save_to_downloads": "ダウンロードに保存", - "select_buy_provider_notice": "上記の購入プロバイダーを選択してください。デフォルトの購入プロバイダーをアプリ設定で設定して、この画面をスキップできます。", - "onramper_option_description": "多くの支払い方法で暗号をすばやく購入してください。ほとんどの国で利用可能です。スプレッドと料金は異なります。", - "default_buy_provider": "デフォルトの購入プロバイダー", - "ask_each_time": "毎回尋ねてください", - "buy_provider_unavailable": "現在、プロバイダーは利用できません。", - "signTransaction": "トランザクションに署名する", - "errorGettingCredentials": "失敗: 認証情報の取得中にエラーが発生しました", - "errorSigningTransaction": "トランザクションの署名中にエラーが発生しました", - "pairingInvalidEvent": "ペアリング無効イベント", - "chains": "チェーン", - "methods": "メソッド", - "events": "イベント", - "reject": "拒否する", - "approve": "承認する", - "expiresOn": "有効期限は次のとおりです", - "walletConnect": "ウォレットコネクト", - "nullURIError": "URIがnullです", - "connectWalletPrompt": "ウォレットを WalletConnect に接続して取引を行う", - "newConnection": "新しい接続", - "activeConnectionsPrompt": "アクティブな接続がここに表示されます", - "deleteConnectionConfirmationPrompt": "への接続を削除してもよろしいですか?", - "event": "イベント", - "successful": "成功", - "wouoldLikeToConnect": "接続したいです", - "message": "メッセージ", - "do_not_have_enough_gas_asset": "現在のブロックチェーン ネットワークの状況では、トランザクションを行うのに十分な ${currency} がありません。別のアセットを送信する場合でも、ブロックチェーン ネットワーク料金を支払うにはさらに ${currency} が必要です。", - "totp_auth_url": "TOTP認証URL", - "awaitDAppProcessing": "dAppの処理が完了するまでお待ちください。", - "copyWalletConnectLink": "dApp から WalletConnect リンクをコピーし、ここに貼り付けます", - "enterWalletConnectURI": "WalletConnect URI を入力してください", - "seed_key": "シードキー", - "enter_seed_phrase": "シードフレーズを入力してください", - "change_rep_successful": "代表者の変更に成功しました", - "add_contact": "連絡先を追加", - "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!", - "domain_looks_up": "ドメイン検索", - "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", - "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", - "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", - "order_by": "注文", - "creation_date": "作成日", - "group_by_type": "タイプごとにグループ", - "importNFTs": "NFTのインポート", - "noNFTYet": "NFTはまだありません", - "address": "住所", - "enterTokenID": "トークンIDを入力してください", - "tokenID": "ID", - "name": "名前", - "symbol": "シンボル", - "seed_phrase_length": "シードフレーズの長さ", - "unavailable_balance": "利用できない残高", - "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", - "unspent_change": "変化", - "tor_connection": "Tor接続", - "setup_warning_2fa_text": "Cake 2FA は、ウォレット内の特定のアクションに対する 2 番目の認証です。冷蔵保存ほど安全ではありません。\n\n2FA アプリまたは TOTP キーにアクセスできなくなると、このウォレットにもアクセスできなくなります。ニーモニックシードからウォレットを復元する必要があります。\n\n2FA またはニーモニック シードにアクセスできなくなった場合、Cake サポートはサポートできません。\nCake 2FA を使用する前に、ガイドを一読することをお勧めします。", - "scan_qr_on_device": "別のデバイスでこの QR コードをスキャンします", - "how_to_use": "使い方", - "seed_hex_form": "ウォレットシード(ヘックスフォーム)", - "seedtype": "SeedType", - "seedtype_legacy": "レガシー(25語)", - "seedtype_polyseed": "ポリシード(16語)", - "seed_language_czech": "チェコ", - "seed_language_korean": "韓国語", - "seed_language_chinese_traditional": "中国の伝統的な)", - "ascending": "上昇", - "descending": "下降", - "dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け", - "polygonscan_history": "ポリゴンスキャン履歴", - "wallet_seed_legacy": "レガシーウォレットシード", - "default_sell_provider": "デフォルトの販売プロバイダー", - "select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。", - "custom_drag": "カスタム(ホールドとドラッグ)", - "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)", - "use_testnet": "テストネットを使用します", - "receivable_balance": "売掛金残高", - "confirmed_tx": "確認済み", - "transaction_details_source_address": "ソースアドレス", - "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。", - "contractName": "契約名", - "contractSymbol": "契約記号", - "description": "説明", - "camera_consent": "あなたのカメラは、${provider}_ までに識別目的で画像を撮影するために使用されます。詳細については、プライバシー ポリシーをご確認ください。", - "no_relays": "リレーなし", - "choose_relay": "使用するリレーを選択してください", - "no_relays_message": "このユーザーの Nostr NIP-05 レコードが見つかりましたが、リレーは含まれていません。受信者に Nostr レコードにリレーを追加するよう指示してください。", - "no_relay_on_domain": "ユーザーのドメインのリレーが存在しないか、リレーが使用できません。使用するリレーを選択してください。" - "zzzz": "zzzz" + "you_will_send": "から変換" } \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 344673de5..8ae20c7f3 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -714,6 +714,7 @@ "use_card_info_two": "디지털 화폐가 아닌 선불 계정에 보유하면 자금이 USD로 변환됩니다.", "use_ssl": "SSL 사용", "use_suggested": "추천 사용", + "use_testnet": "TestNet을 사용하십시오", "variable_pair_not_supported": "이 변수 쌍은 선택한 교환에서 지원되지 않습니다.", "verification": "검증", "verify_with_2fa": "케이크 2FA로 확인", @@ -772,279 +773,5 @@ "you_now_have_debit_card": "이제 직불카드가 있습니다.", "you_pay": "당신이 지불합니다", "you_will_get": "로 변환하다", - "you_will_send": "다음에서 변환", - "YY": "YY", - "online": "온라인", - "offline": "오프라인", - "gift_card_number": "기프트 카드 번호", - "pin_number": "PIN 번호", - "total_saving": "총 절감액", - "last_30_days": "지난 30일", - "avg_savings": "평균 절감액", - "view_all": "모두 보기", - "active_cards": "활성 카드", - "delete_account": "계정 삭제", - "cards": "카드", - "active": "활성", - "redeemed": "구함", - "gift_card_balance_note": "잔액이 남아 있는 기프트 카드가 여기에 표시됩니다.", - "gift_card_redeemed_note": "사용한 기프트 카드가 여기에 표시됩니다.", - "logout": "로그아웃", - "add_tip": "팁 추가", - "percentageOf": "${amount} 중", - "is_percentage": "이다", - "search_category": "검색 카테고리", - "mark_as_redeemed": "사용한 것으로 표시", - "more_options": "추가 옵션", - "awaiting_payment_confirmation": "결제 확인 대기 중", - "transaction_sent_notice": "1분 후에도 화면이 진행되지 않으면 블록 익스플로러와 이메일을 확인하세요.", - "agree": "동의하다", - "in_store": "매장 내", - "generating_gift_card": "기프트 카드 생성 중", - "payment_was_received": "결제가 접수되었습니다.", - "proceed_after_one_minute": "1분 후에도 화면이 진행되지 않으면 이메일을 확인하세요.", - "order_id": "주문 ID", - "gift_card_is_generated": "기프트 카드가 생성되었습니다", - "open_gift_card": "기프트 카드 열기", - "contact_support": "지원팀에 문의", - "gift_cards_unavailable": "기프트 카드는 현재 Monero, Bitcoin 및 Litecoin을 통해서만 구매할 수 있습니다.", - "background_sync_mode": "백그라운드 동기화 모드", - "sync_all_wallets": "모든 지갑 동기화", - "introducing_cake_pay": "소개 Cake Pay!", - "cake_pay_learn_more": "앱에서 즉시 기프트 카드를 구매하고 사용하세요!\n자세히 알아보려면 왼쪽에서 오른쪽으로 스와이프하세요.", - "automatic": "자동적 인", - "fixed_pair_not_supported": "이 고정 쌍은 선택한 교환에서 지원되지 않습니다.", - "variable_pair_not_supported": "이 변수 쌍은 선택한 교환에서 지원되지 않습니다.", - "none_of_selected_providers_can_exchange": "선택한 공급자 중 누구도 이 교환을 할 수 없습니다.", - "choose_one": "하나 선택", - "choose_from_available_options": "사용 가능한 옵션에서 선택:", - "custom_redeem_amount": "사용자 지정 상환 금액", - "add_custom_redemption": "사용자 지정 상환 추가", - "remaining": "남은", - "delete_wallet": "지갑 삭제", - "delete_wallet_confirm_message": "${wallet_name} 지갑을 삭제하시겠습니까?", - "low_fee": "낮은 수수료", - "low_fee_alert": "현재 낮은 네트워크 요금 우선 순위를 사용하고 있습니다. 이로 인해 긴 대기 시간, 다른 요금 또는 취소된 거래가 발생할 수 있습니다. 더 나은 경험을 위해 더 높은 요금을 설정하는 것이 좋습니다.", - "ignor": "무시하다", - "use_suggested": "추천 사용", - "do_not_share_warning_text": "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n귀하의 자금은 도난당할 수 있고 도난당할 수 있습니다!", - "help": "돕다", - "all_transactions": "모든 거래 창구", - "all_trades": "A모든 거래", - "connection_sync": "연결 및 동기화", - "security_and_backup": "보안 및 백업", - "create_backup": "백업 생성", - "privacy_settings": "개인정보 설정", - "privacy": "프라이버시", - "display_settings": "디스플레이 설정", - "other_settings": "기타 설정", - "require_pin_after": "다음 이후에 PIN 필요", - "always": "언제나", - "minutes_to_pin_code": "${minute}분", - "disable_exchange": "교환 비활성화", - "advanced_settings": "고급 설정", - "settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다.", - "add_custom_node": "새 사용자 정의 노드 추가", - "disable_fiat": "법정화폐 비활성화", - "fiat_api": "명목 화폐 API", - "disabled": "장애가 있는", - "enabled": "사용", - "tor_only": "Tor 뿐", - "unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다.", - "orbot_running_alert": "이 노드에 연결하기 전에 Orbot이 실행 중인지 확인하십시오.", - "contact_list_contacts": "콘택트 렌즈", - "contact_list_wallets": "내 지갑", - "bitcoin_payments_require_1_confirmation": "비트코인 결제는 1번의 확인이 필요하며 20분 이상이 소요될 수 있습니다. 기다려 주셔서 감사합니다! 결제가 확인되면 이메일이 전송됩니다.", - "send_to_this_address": "이 주소로 ${currency} ${tag}송금", - "arrive_in_this_address": "${currency} ${tag}이(가) 이 주소로 도착합니다", - "do_not_send": "보내지 마세요", - "error_dialog_content": "죄송합니다. 오류가 발생했습니다.\n\n응용 프로그램을 개선하려면 지원 팀에 충돌 보고서를 보내주십시오.", - "scan_qr_code": "QR 코드 스캔", - "cold_or_recover_wallet": "콜드 지갑 추가 또는 종이 지갑 복구", - "please_wait": "기다리세요", - "sweeping_wallet": "스위핑 지갑", - "sweeping_wallet_alert": "오래 걸리지 않습니다. 이 화면을 떠나지 마십시오. 그렇지 않으면 스웹트 자금이 손실될 수 있습니다.", - "decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.", - "edit_node": "노드 편집", - "invoice_details": "인보이스 세부정보", - "donation_link_details": "기부 링크 세부정보", - "anonpay_description": "${type} 생성. 수신자는 지원되는 모든 암호화폐로 ${method}할 수 있으며 이 지갑에서 자금을 받게 됩니다.", - "create_invoice": "인보이스 생성", - "create_donation_link": "기부 링크 만들기", - "optional_email_hint": "선택적 수취인 알림 이메일", - "optional_description": "선택적 설명", - "optional_name": "선택적 수신자 이름", - "clearnet_link": "클리어넷 링크", - "onion_link": "양파 링크", - "settings": "설정", - "sell_monero_com_alert_content": "지원되지 않습니다.", - "error_text_input_below_minimum_limit": "금액이 최소보다 적습니다.", - "error_text_input_above_maximum_limit": "금액이 최대 값보다 많습니다.", - "show_market_place": "마켓플레이스 표시", - "prevent_screenshots": "스크린샷 및 화면 녹화 방지", - "profile": "프로필", - "close": "닫다", - "modify_2fa": "수정 케이크 2FA", - "disable_cake_2fa": "케이크 2FA 비활성화", - "question_to_disable_2fa": "Cake 2FA를 비활성화하시겠습니까? 지갑 및 특정 기능에 액세스하는 데 더 이상 2FA 코드가 필요하지 않습니다.", - "disable": "장애를 입히다", - "setup_2fa": "케이크 2FA 설정", - "verify_with_2fa": "케이크 2FA로 확인", - "totp_code": "TOTP 코드", - "please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.", - "totp_2fa_success": "성공! 이 지갑에 케이크 2FA가 활성화되었습니다. 지갑 액세스 권한을 잃을 경우를 대비하여 니모닉 시드를 저장하는 것을 잊지 마십시오.", - "totp_verification_success": "확인 성공!", - "totp_2fa_failure": "잘못된 코드입니다. 다른 코드를 시도하거나 새 비밀 키를 생성하십시오. 8자리 코드와 SHA512를 지원하는 호환되는 2FA 앱을 사용하세요.", - "enter_totp_code": "TOTP 코드를 입력하세요.", - "add_secret_code": "또는 이 비밀 코드를 인증 앱에 추가하세요.", - "totp_secret_code": "TOTP 비밀 코드", - "setup_2fa_text": "Cake 2FA는 TOTP를 두 번째 인증 요소로 사용하여 작동합니다.\n\nCake 2FA의 TOTP에는 SHA-512 및 8자리 지원이 필요합니다. 이는 보안을 강화합니다. 자세한 정보와 지원되는 앱은 가이드에서 확인할 수 있습니다.", - "setup_totp_recommended": "TOTP 설정", - "disable_buy": "구매 행동 비활성화", - "disable_sell": "판매 조치 비활성화", - "cake_2fa_preset": "케이크 2FA 프리셋", - "narrow": "좁은", - "normal": "정상", - "aggressive": "지나치게 열심인", - "require_for_assessing_wallet": "지갑 접근을 위해 필요", - "require_for_sends_to_non_contacts": "비접촉자에게 보내는 데 필요", - "require_for_sends_to_contacts": "연락처로 보내기에 필요", - "require_for_sends_to_internal_wallets": "내부 지갑으로 보내는 데 필요", - "require_for_exchanges_to_internal_wallets": "내부 지갑으로의 교환에 필요", - "require_for_adding_contacts": "연락처 추가에 필요", - "require_for_creating_new_wallets": "새 지갑 생성에 필요", - "require_for_all_security_and_backup_settings": "모든 보안 및 백업 설정에 필요", - "available_balance_description": "이 지갑에서 사용할 수 있는 잔액입니다. 이 잔액은 블록체인에서 가져온 것이며, Cake Wallet이 사용할 수 없습니다.", - "syncing_wallet_alert_title": "지갑 동기화 중", - "syncing_wallet_alert_content": "상단에 \"동기화됨\"이라고 표시될 때까지 잔액 및 거래 목록이 완전하지 않을 수 있습니다. 자세히 알아보려면 클릭/탭하세요.", - "home_screen_settings": "홈 화면 설정", - "sort_by": "정렬 기준", - "search_add_token": "검색 / 토큰 추가", - "edit_token": "토큰 편집", - "warning": "경고", - "add_token_warning": "사기꾼의 지시에 따라 토큰을 편집하거나 추가하지 마십시오.\n항상 신뢰할 수 있는 출처를 통해 토큰 주소를 확인하세요!", - "add_token_disclaimer_check": "신뢰할 수 있는 출처를 통해 토큰 컨트랙트 주소와 정보를 확인했습니다. 악의적이거나 잘못된 정보를 추가하면 자금 손실이 발생할 수 있습니다.", - "token_contract_address": "토큰 계약 주소", - "token_name": "토큰 이름 예: Tether", - "token_symbol": "토큰 기호 예: USDT", - "token_decimal": "토큰 십진수", - "field_required": "이 필드는 필수입니다", - "pin_at_top": "상단에 ${token} 고정", - "invalid_input": "잘못된 입력", - "fiat_balance": "피아트 잔액", - "gross_balance": "총 잔액", - "alphabetical": "알파벳순", - "generate_name": "이름 생성", - "balance_page": "잔액 페이지", - "share": "공유하다", - "slidable": "슬라이딩 가능", - "monero_dark_theme": "모네로 다크 테마", - "bitcoin_dark_theme": "비트코인 다크 테마", - "bitcoin_light_theme": "비트코인 라이트 테마", - "high_contrast_theme": "고대비 테마", - "matrix_green_dark_theme": "매트릭스 그린 다크 테마", - "monero_light_theme": "모네로 라이트 테마", - "manage_nodes": "노드 관리", - "etherscan_history": "이더스캔 역사", - "template_name": "템플릿 이름", - "unsupported_asset": "이 저작물에 대해 이 작업을 지원하지 않습니다. 지원되는 자산 유형의 지갑을 생성하거나 전환하십시오.", - "manage_pow_nodes": "PoW 노드 관리", - "support_title_live_chat": "실시간 지원", - "support_description_live_chat": "자유롭고 빠릅니다! 훈련 된 지원 담당자가 지원할 수 있습니다", - "support_title_guides": "케이크 지갑 가이드", - "support_description_guides": "일반적인 문제에 대한 문서화 및 지원", - "support_title_other_links": "다른 지원 링크", - "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오.", - "choose_derivation": "지갑 파생을 선택하십시오", - "new_first_wallet_text": "cryptocurrency를 쉽게 안전하게 유지하십시오", - "select_destination": "백업 파일의 대상을 선택하십시오.", - "auto_generate_subaddresses": "자동 생성 서브 아드 드레스", - "save_to_downloads": "다운로드에 저장", - "select_buy_provider_notice": "위의 구매 제공자를 선택하십시오. 앱 설정에서 기본 구매 제공자를 설정 하여이 화면을 건너 뛸 수 있습니다.", - "onramper_option_description": "많은 결제 방법으로 암호화를 신속하게 구입하십시오. 대부분의 국가에서 사용할 수 있습니다. 스프레드와 수수료는 다양합니다.", - "default_buy_provider": "기본 구매 제공자", - "ask_each_time": "매번 물어보십시오", - "buy_provider_unavailable": "제공자는 현재 사용할 수 없습니다.", - "signTransaction": "거래 서명", - "errorGettingCredentials": "실패: 자격 증명을 가져오는 중 오류가 발생했습니다.", - "errorSigningTransaction": "거래에 서명하는 동안 오류가 발생했습니다.", - "pairingInvalidEvent": "잘못된 이벤트 페어링", - "chains": "쇠사슬", - "methods": "행동 양식", - "events": "이벤트", - "reject": "거부하다", - "approve": "승인하다", - "expiresOn": "만료 날짜", - "walletConnect": "월렛커넥트", - "nullURIError": "URI가 null입니다.", - "connectWalletPrompt": "거래를 하려면 WalletConnect에 지갑을 연결하세요.", - "newConnection": "새로운 연결", - "activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다", - "deleteConnectionConfirmationPrompt": "다음 연결을 삭제하시겠습니까?", - "event": "이벤트", - "successful": "성공적인", - "wouoldLikeToConnect": "연결하고 싶습니다", - "message": "메시지", - "do_not_have_enough_gas_asset": "현재 블록체인 네트워크 조건으로 거래를 하기에는 ${currency}이(가) 충분하지 않습니다. 다른 자산을 보내더라도 블록체인 네트워크 수수료를 지불하려면 ${currency}가 더 필요합니다.", - "totp_auth_url": "TOTP 인증 URL", - "awaitDAppProcessing": "dApp이 처리를 마칠 때까지 기다려주세요.", - "copyWalletConnectLink": "dApp에서 WalletConnect 링크를 복사하여 여기에 붙여넣으세요.", - "enterWalletConnectURI": "WalletConnect URI를 입력하세요.", - "seed_key": "시드 키", - "enter_seed_phrase": "시드 문구를 입력하십시오", - "change_rep_successful": "대리인이 성공적으로 변경되었습니다", - "add_contact": "주소록에 추가", - "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!", - "domain_looks_up": "도메인 조회", - "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", - "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", - "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", - "order_by": "주문", - "creation_date": "생산 일", - "group_by_type": "유형별 그룹", - "importNFTs": "NFT 가져오기", - "noNFTYet": "아직 NFT가 없습니다", - "address": "주소", - "enterTokenID": "토큰 ID를 입력하세요", - "tokenID": "ID", - "name": "이름", - "symbol": "상징", - "seed_phrase_length": "시드 문구 길이", - "unavailable_balance": "사용할 수 없는 잔액", - "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", - "unspent_change": "변화", - "tor_connection": "토르 연결", - "setup_warning_2fa_text": "Cake 2FA는 지갑의 특정 작업에 대한 두 번째 인증입니다. 냉장 보관만큼 안전하지 않습니다.\n\n2FA 앱 또는 TOTP 키에 대한 액세스 권한을 상실하면 이 지갑에 대한 액세스 권한도 잃게 됩니다. 니모닉 시드에서 지갑을 복원해야 합니다.\n\n2FA 또는 니모닉 시드에 액세스할 수 없는 경우 Cake 지원팀에서 도움을 드릴 수 없습니다.\nCake 2FA를 사용하기 전에 가이드를 읽어 보시기 바랍니다.", - "scan_qr_on_device": "다른 기기에서 이 QR 코드를 스캔하세요.", - "how_to_use": "사용하는 방법", - "seed_hex_form": "지갑 씨앗 (16 진 양식)", - "seedtype": "시드 타입", - "seedtype_legacy": "레거시 (25 단어)", - "seedtype_polyseed": "다문 (16 단어)", - "seed_language_czech": "체코 사람", - "seed_language_korean": "한국인", - "seed_language_chinese_traditional": "중국 전통)", - "ascending": "오름차순", - "descending": "내림차순", - "dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용", - "polygonscan_history": "다각형 스캔 기록", - "wallet_seed_legacy": "레거시 지갑 시드", - "default_sell_provider": "기본 판매 공급자", - "select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.", - "custom_drag": "사용자 정의 (홀드 앤 드래그)", - "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)", - "use_testnet": "TestNet을 사용하십시오", - "receivable_balance": "채권 잔액", - "confirmed_tx": "확인", - "transaction_details_source_address": "소스 주소", - "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다.", - "contractName": "계약명", - "contractSymbol": "계약 기호", - "description": "설명", - "camera_consent": "귀하의 카메라는 ${provider}의 식별 목적으로 이미지를 캡처하는 데 사용됩니다. 자세한 내용은 해당 개인정보 보호정책을 확인하세요.", - "no_relays": "릴레이 없음", - "choose_relay": "사용할 릴레이를 선택해주세요", - "no_relays_message": "이 사용자에 대한 Nostr NIP-05 레코드를 찾았지만 릴레이가 포함되어 있지 않습니다. 수신자에게 Nostr 기록에 릴레이를 추가하도록 지시하십시오.", - "no_relay_on_domain": "사용자 도메인에 릴레이가 없거나 릴레이를 사용할 수 없습니다. 사용할 릴레이를 선택해주세요." - "zzzz": "zzzz" + "you_will_send": "다음에서 변환" } \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index b48f20770..79db86552 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -714,6 +714,7 @@ "use_card_info_two": "ဒစ်ဂျစ်တယ်ငွေကြေးများဖြင့်မဟုတ်ဘဲ ကြိုတင်ငွေပေးချေသည့်အကောင့်တွင် သိမ်းထားသည့်အခါ ရန်ပုံငွေများကို USD သို့ ပြောင်းလဲပါသည်။", "use_ssl": "SSL ကိုသုံးပါ။", "use_suggested": "အကြံပြုထားသည်ကို အသုံးပြုပါ။", + "use_testnet": "testnet ကိုသုံးပါ", "variable_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပြောင်းလဲနိုင်သောအတွဲကို ပံ့ပိုးမထားပါ။", "verification": "စိစစ်ခြင်း။", "verify_with_2fa": "Cake 2FA ဖြင့် စစ်ဆေးပါ။", @@ -772,279 +773,5 @@ "you_now_have_debit_card": "ယခု သင့်တွင် ဒက်ဘစ်ကတ်တစ်ခုရှိသည်။", "you_pay": "သင်ပေးချေပါ။", "you_will_get": "သို့ပြောင်းပါ။", - "you_will_send": "မှပြောင်းပါ။", - "yy": "YY", - "online": "အွန်လိုင်း", - "offline": "အော့ဖ်လိုင်း", - "gift_card_number": "လက်ဆောင်ကတ်နံပါတ်", - "pin_number": "လျှို့ဝှက်နံပါတ်", - "total_saving": "စုစုပေါင်းစုဆောင်းငွေ", - "last_30_days": "လွန်ခဲ့သော ရက် 30", - "avg_savings": "ပျမ်းမျှ စုဆောင်းငွေ", - "view_all": "အားလုံးကိုကြည့်ရှုပါ။", - "active_cards": "အသက်ဝင်သောကတ်များ", - "delete_account": "အကောင့်ဖျက်ပါ။", - "cards": "ကတ်များ", - "active": "အသက်ဝင်သည်။", - "redeemed": "ရွေးနှုတ်ခဲ့သည်။", - "gift_card_balance_note": "လက်ကျန်လက်ကျန်ရှိသည့် လက်ဆောင်ကတ်များ ဤနေရာတွင် ပေါ်လာပါမည်။", - "gift_card_redeemed_note": "သင်ရွေးယူထားသော လက်ဆောင်ကတ်များ ဤနေရာတွင် ပေါ်လာပါမည်။", - "logout": "ထွက်လိုက်ပါ။", - "add_tip": "အကြံပြုချက်ထည့်ပါ။", - "percentageOf": "${amount} ၏", - "is_percentage": "သည်", - "search_category": "ရှာဖွေမှုအမျိုးအစား", - "mark_as_redeemed": "ရွေးနှုတ်ခြင်းအဖြစ် အမှတ်အသားပြုပါ။", - "more_options": "နောက်ထပ် ရွေးချယ်စရာများ", - "awaiting_payment_confirmation": "ငွေပေးချေမှု အတည်ပြုချက်ကို စောင့်မျှော်နေပါသည်။", - "transaction_sent_notice": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက၊ ပိတ်ဆို့ရှာဖွေသူနှင့် သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", - "agree": "သဘောတူသည်။", - "in_store": "စတိုးတွင်", - "generating_gift_card": "လက်ဆောင်ကတ်ထုတ်ပေးခြင်း။", - "payment_was_received": "သင့်ငွေပေးချေမှုကို လက်ခံရရှိခဲ့သည်။", - "proceed_after_one_minute": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", - "order_id": "မှာယူမှု ID", - "gift_card_is_generated": "Gift Card ထုတ်ပေးပါသည်။", - "open_gift_card": "Gift Card ကိုဖွင့်ပါ။", - "contact_support": "ပံ့ပိုးကူညီမှုထံ ဆက်သွယ်ပါ။", - "gift_cards_unavailable": "လက်ဆောင်ကတ်များကို ယခုအချိန်တွင် Monero၊ Bitcoin နှင့် Litecoin တို့ဖြင့်သာ ဝယ်ယူနိုင်ပါပြီ။", - "introducing_cake_pay": "Cake Pay ကို မိတ်ဆက်ခြင်း။", - "cake_pay_learn_more": "အက်ပ်ရှိ လက်ဆောင်ကတ်များကို ချက်ချင်းဝယ်ယူပြီး ကူပွန်ဖြင့် လဲလှယ်ပါ။\nပိုမိုလေ့လာရန် ဘယ်မှညာသို့ ပွတ်ဆွဲပါ။", - "automatic": "အလိုအလျောက်", - "fixed_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပုံသေအတွဲကို ပံ့ပိုးမထားပါ။", - "variable_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပြောင်းလဲနိုင်သောအတွဲကို ပံ့ပိုးမထားပါ။", - "none_of_selected_providers_can_exchange": "ရွေးချယ်ထားသော ဝန်ဆောင်မှုပေးသူများမှ ဤလဲလှယ်မှုကို ပြုလုပ်၍မရပါ။", - "choose_one": "တစ်ခုရွေးပါ။", - "choose_from_available_options": "ရနိုင်သောရွေးချယ်မှုများမှ ရွေးပါ-", - "custom_redeem_amount": "စိတ်ကြိုက်သုံးငွေပမာဏ", - "add_custom_redemption": "စိတ်ကြိုက်ရွေးယူမှုကို ထည့်ပါ။", - "remaining": "ကျန်", - "delete_wallet": "ပိုက်ဆံအိတ်ကို ဖျက်ပါ။", - "delete_wallet_confirm_message": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖျက်လိုသည်မှာ သေချာပါသလား။", - "low_fee": "အနိမ့်ကြေး", - "low_fee_alert": "သင်သည် လက်ရှိတွင် သက်သာသော ကွန်ရက်အခကြေးငွေဦးစားပေးကို အသုံးပြုနေပါသည်။ ၎င်းသည် အကြာကြီးစောင့်ဆိုင်းခြင်း၊ မတူညီသောနှုန်းထားများ သို့မဟုတ် ပယ်ဖျက်ထားသော ကုန်သွယ်မှုများကို ဖြစ်စေနိုင်သည်။ ပိုမိုကောင်းမွန်သော အတွေ့အကြုံအတွက် ပိုမိုမြင့်မားသော အခကြေးငွေ သတ်မှတ်ပေးရန် အကြံပြုအပ်ပါသည်။", - "ignor": "လျစ်လျူရှုပါ။", - "use_suggested": "အကြံပြုထားသည်ကို အသုံးပြုပါ။", - "do_not_share_warning_text": "ပံ့ပိုးကူညီမှုအပါအဝင် ဤအရာများကို အခြားမည်သူနှင့်မျှ မမျှဝေပါနှင့်။\n\nသင့်ငွေများကို ခိုးယူခံရနိုင်သည်!", - "help": "ကူညီပါ", - "all_transactions": "အရောင်းအဝယ်အားလုံး", - "all_trades": "ကုန်သွယ်မှုအားလုံး", - "connection_sync": "ချိတ်ဆက်မှုနှင့် ထပ်တူပြုခြင်း။", - "security_and_backup": "လုံခြုံရေးနှင့် မိတ္တူ", - "create_backup": "အရန်သိမ်းခြင်းကို ဖန်တီးပါ။", - "privacy_settings": "Privacy settings တွေကို", - "privacy": "ကိုယ်ရေးကိုယ်တာ", - "display_settings": "ပြသရန် ဆက်တင်များ", - "other_settings": "အခြားဆက်တင်များ", - "require_pin_after": "ပြီးနောက် PIN လိုအပ်ပါသည်။", - "always": "အမြဲတမ်း", - "minutes_to_pin_code": "${minute} မိနစ်", - "disable_exchange": "လဲလှယ်မှုကို ပိတ်ပါ။", - "advanced_settings": "အဆင့်မြင့်ချိန်ညှိချက်များ", - "settings_can_be_changed_later": "အက်ပ်ဆက်တင်များတွင် ဤဆက်တင်များကို နောက်ပိုင်းတွင် ပြောင်းလဲနိုင်သည်။", - "add_custom_node": "စိတ်ကြိုက် Node အသစ်ကို ထည့်ပါ။", - "disable_fiat": "Fiat ကိုပိတ်ပါ။", - "fiat_api": "Fiat API", - "disabled": "မသန်စွမ်း", - "enabled": "ဖွင့်ထားသည်။", - "tor_only": "Tor သာ", - "unmatched_currencies": "သင့်လက်ရှိပိုက်ဆံအိတ်၏ငွေကြေးသည် စကင်ဖတ်ထားသော QR နှင့် မကိုက်ညီပါ။", - "orbot_running_alert": "ဤ node သို့မချိတ်ဆက်မီ Orbot အလုပ်လုပ်နေကြောင်း သေချာပါစေ။", - "contact_list_contacts": "အဆက်အသွယ်များ", - "contact_list_wallets": "ကျွန်ုပ်၏ ပိုက်ဆံအိတ်များ", - "bitcoin_payments_require_1_confirmation": "Bitcoin ငွေပေးချေမှုများသည် မိနစ် 20 သို့မဟုတ် ထို့ထက်ပိုကြာနိုင်သည် 1 အတည်ပြုချက် လိုအပ်သည်။ မင်းရဲ့စိတ်ရှည်မှုအတွက် ကျေးဇူးတင်ပါတယ်။ ငွေပေးချေမှုကို အတည်ပြုပြီးသောအခါ သင့်ထံ အီးမေးလ်ပို့ပါမည်။", - "send_to_this_address": "ဤလိပ်စာသို့ ${currency} ${tag}သို့ ပို့ပါ။", - "arrive_in_this_address": "${currency} ${tag}ဤလိပ်စာသို့ ရောက်ရှိပါမည်။", - "do_not_send": "မပို့ပါနှင့်", - "error_dialog_content": "အိုး၊ ကျွန်ုပ်တို့တွင် အမှားအယွင်းအချို့ရှိသည်။\n\nအပလီကေးရှင်းကို ပိုမိုကောင်းမွန်စေရန်အတွက် ပျက်စီးမှုအစီရင်ခံစာကို ကျွန်ုပ်တို့၏ပံ့ပိုးကူညီရေးအဖွဲ့ထံ ပေးပို့ပါ။", - "scan_qr_code": "QR ကုဒ်ကို စကင်န်ဖတ်ပါ။", - "cold_or_recover_wallet": "အေးသောပိုက်ဆံအိတ်ထည့်ပါ သို့မဟုတ် စက္ကူပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", - "please_wait": "ကျေးဇူးပြုပြီးခဏစောင့်ပါ", - "sweeping_wallet": "ိုက်ဆံအိတ် တံမြက်လှည်း", - "sweeping_wallet_alert": "ဒါက ကြာကြာမခံသင့်ပါဘူး။ ဤစခရင်ကို ချန်မထားပါနှင့် သို့မဟုတ် ထုတ်ယူထားသော ရန်ပုံငွေများ ဆုံးရှုံးနိုင်သည်", - "decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။", - "edit_node": "Node ကို တည်းဖြတ်ပါ။", - "invoice_details": "ပြေစာအသေးစိတ်", - "donation_link_details": "လှူဒါန်းရန်လင့်ခ်အသေးစိတ်", - "anonpay_description": "${type} ကို ဖန်တီးပါ။ လက်ခံသူက ${method} ကို ပံ့ပိုးပေးထားသည့် cryptocurrency တစ်ခုခုဖြင့် လုပ်ဆောင်နိုင်ပြီး၊ သင်သည် ဤပိုက်ဆံအိတ်တွင် ရံပုံငွေများ ရရှိမည်ဖြစ်သည်။", - "create_invoice": "ပြေစာဖန်တီးပါ။", - "create_donation_link": "လှူဒါန်းမှုလင့်ခ်ကို ဖန်တီးပါ။", - "optional_email_hint": "ရွေးချယ်နိုင်သော ငွေလက်ခံသူ အကြောင်းကြားချက် အီးမေးလ်", - "optional_description": "ရွေးချယ်နိုင်သော ဖော်ပြချက်", - "optional_name": "ရွေးချယ်နိုင်သော လက်ခံသူအမည်", - "clearnet_link": "Clearnet လင့်ခ်", - "onion_link": "ကြက်သွန်လင့်", - "settings": "ဆက်တင်များ", - "sell_monero_com_alert_content": "Monero ရောင်းချခြင်းကို မပံ့ပိုးရသေးပါ။", - "error_text_input_below_minimum_limit": "ပမာဏသည် အနိမ့်ဆုံးထက်နည်းသည်။", - "error_text_input_above_maximum_limit": "ပမာဏသည် အများဆုံးထက် ပိုများသည်။", - "show_market_place": "စျေးကွက်ကိုပြသပါ။", - "prevent_screenshots": "ဖန်သားပြင်ဓာတ်ပုံများနှင့် မျက်နှာပြင်ရိုက်ကူးခြင်းကို တားဆီးပါ။", - "profile": "ကိုယ်ရေးအကျဉ်း", - "close": "အနီးကပ်", - "modify_2fa": "ကိတ်မုန့် 2FA ကို ပြင်ဆင်ပါ။", - "disable_cake_2fa": "ကိတ်မုန့် 2FA ကို ပိတ်ပါ။", - "question_to_disable_2fa": "Cake 2FA ကို ပိတ်လိုသည်မှာ သေချာပါသလား။ ပိုက်ဆံအိတ်နှင့် အချို့သောလုပ်ဆောင်ချက်များကို အသုံးပြုရန်အတွက် 2FA ကုဒ်တစ်ခု မလိုအပ်တော့ပါ။", - "disable": "ပိတ်ပါ။", - "setup_2fa": "ကိတ်မုန့် 2FA စနစ်ထည့်သွင်းပါ။", - "verify_with_2fa": "Cake 2FA ဖြင့် စစ်ဆေးပါ။", - "totp_code": "TOTP ကုဒ်", - "please_fill_totp": "သင့်အခြားစက်တွင်ရှိသော ဂဏန်း ၈ လုံးကုဒ်ကို ကျေးဇူးပြု၍ ဖြည့်ပါ။", - "totp_2fa_success": "အောင်မြင် ဤပိုက်ဆံအိတ်အတွက် ကိတ်မုန့် 2FA ကို ဖွင့်ထားသည်။ ပိုက်ဆံအိတ်ဝင်ရောက်ခွင့်ဆုံးရှုံးသွားသောအခါတွင် သင်၏ mnemonic မျိုးစေ့များကို သိမ်းဆည်းရန် မမေ့ပါနှင့်။", - "totp_verification_success": "အတည်ပြုခြင်း အောင်မြင်ပါသည်။", - "totp_2fa_failure": "ကုဒ်မမှန်ပါ။ ကျေးဇူးပြု၍ အခြားကုဒ်တစ်ခုကို စမ်းကြည့်ပါ သို့မဟုတ် လျှို့ဝှက်သော့အသစ်တစ်ခု ဖန်တီးပါ။ ဂဏန်း ၈ လုံးကုဒ်များနှင့် SHA512 ကို ပံ့ပိုးပေးသည့် တွဲဖက်အသုံးပြုနိုင်သော 2FA အက်ပ်ကို အသုံးပြုပါ။", - "enter_totp_code": "ကျေးဇူးပြု၍ TOTP ကုဒ်ကို ထည့်ပါ။", - "add_secret_code": "သို့မဟုတ် ဤလျှို့ဝှက်ကုဒ်ကို အထောက်အထားစိစစ်ခြင်းအက်ပ်တစ်ခုသို့ ထည့်ပါ။", - "totp_secret_code": "TOTP လျှို့ဝှက်ကုဒ်", - "setup_2fa_text": "ကိတ်မုန့် 2FA သည် TOTP ကို ဒုတိယ စစ်မှန်ကြောင်းအထောက်အထားအဖြစ် အသုံးပြု၍ လုပ်ဆောင်သည်။\n\nကိတ်မုန့် 2FA ၏ TOTP သည် SHA-512 နှင့် 8 ဂဏန်းပံ့ပိုးမှု လိုအပ်သည်။ ဒါက လုံခြုံရေးကို တိုးမြှင့်ပေးတယ်။ နောက်ထပ်အချက်အလက်များနှင့် ပံ့ပိုးပေးထားသောအက်ပ်များကို လမ်းညွှန်တွင် တွေ့နိုင်ပါသည်။", - "setup_totp_recommended": "TOTP စနစ်ထည့်သွင်းပါ။", - "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", - "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။", - "cake_2fa_preset": "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", - "narrow": "ကျဉ်းသော", - "normal": "ပုံမှန်", - "aggressive": "စိတ်အားထက်သန်ခြင်း။", - "require_for_assessing_wallet": "ပိုက်ဆံအိတ်ကို ဝင်သုံးရန် လိုအပ်သည်။", - "require_for_sends_to_non_contacts": "အဆက်အသွယ်မရှိသူများထံ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_sends_to_contacts": "အဆက်အသွယ်များထံ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_sends_to_internal_wallets": "အတွင်းပိုင်း ပိုက်ဆံအိတ်များသို့ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_exchanges_to_internal_wallets": "အတွင်းပိုင်းပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", - "require_for_adding_contacts": "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", - "require_for_creating_new_wallets": "ပိုက်ဆံအိတ်အသစ်များ ဖန်တီးရန် လိုအပ်သည်။", - "require_for_all_security_and_backup_settings": "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", - "available_balance_description": "သင့်ရဲ့ အကောင့်တွင် ရရှိနိုင်သော ငွေကျန်ငွေကို ပြန်လည်ပေးသွင်းပါ။", - "syncing_wallet_alert_title": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်နေပါသည်။", - "syncing_wallet_alert_content": "သင်၏လက်ကျန်နှင့် ငွေပေးငွေယူစာရင်းသည် ထိပ်တွင် \"Synchronizeed\" ဟုပြောသည်အထိ မပြီးမြောက်နိုင်ပါ။ ပိုမိုလေ့လာရန် နှိပ်/နှိပ်ပါ။", - "home_screen_settings": "ပင်မစခရင် ဆက်တင်များ", - "sort_by": "အလိုက်စဥ်သည်", - "search_add_token": "ရှာဖွေရန် / တိုကင်ထည့်ပါ။", - "edit_token": "တိုကင်ကို တည်းဖြတ်ပါ။", - "warning": "သတိပေးချက်", - "add_token_warning": "လိမ်လည်သူများ ညွှန်ကြားထားသည့်အတိုင်း တိုကင်များကို တည်းဖြတ်ခြင်း သို့မဟုတ် မထည့်ပါနှင့်။\nဂုဏ်သိက္ခာရှိသော အရင်းအမြစ်များဖြင့် အမြဲတမ်း တိုကင်လိပ်စာများကို အတည်ပြုပါ။", - "add_token_disclaimer_check": "ဂုဏ်သိက္ခာရှိသော အရင်းအမြစ်ကို အသုံးပြု၍ တိုကင်စာချုပ်လိပ်စာနှင့် အချက်အလက်ကို ကျွန်ုပ်အတည်ပြုပြီးဖြစ်သည်။ အန္တရာယ်ရှိသော သို့မဟုတ် မမှန်ကန်သော အချက်အလက်များကို ထည့်သွင်းခြင်းသည် ရန်ပုံငွေများ ဆုံးရှုံးသွားနိုင်သည်။", - "token_contract_address": "တိုကင်စာချုပ်လိပ်စာ", - "token_name": "တိုကင်အမည် ဥပမာ- Tether", - "token_symbol": "တိုကင်သင်္ကေတ ဥပမာ- USDT", - "token_decimal": "တိုကင်ဒဿမ", - "field_required": "ဤစာကွက်လပ်မှာဖြည့်ရန်လိုအပ်ပါသည်", - "pin_at_top": "အပေါ်တွင် ${token} ပင်ထိုးပါ။", - "invalid_input": "ထည့်သွင်းမှု မမှန်ကန်ပါ။", - "fiat_balance": "Fiat Balance", - "gross_balance": "စုစုပေါင်းလက်ကျန်ငွေ", - "alphabetical": "အက္ခရာစဉ်", - "generate_name": "အမည်ဖန်တီးပါ။", - "balance_page": "လက်ကျန်စာမျက်နှာ", - "share": "မျှဝေပါ။", - "slidable": "လျှောချနိုင်သည်။", - "monero_dark_theme": "Monero Dark အပြင်အဆင်", - "bitcoin_dark_theme": "Bitcoin Dark Theme", - "bitcoin_light_theme": "Bitcoin Light အပြင်အဆင်", - "high_contrast_theme": "အလင်းအမှောင် မြင့်မားသော အပြင်အဆင်", - "matrix_green_dark_theme": "Matrix Green Dark အပြင်အဆင်", - "monero_light_theme": "Monero Light အပြင်အဆင်", - "manage_nodes": "ဆုံမှတ်များကို စီမံပါ။", - "etherscan_history": "Etherscan သမိုင်း", - "template_name": "နမူနာပုံစံ", - "change_rep": "ကိုယ်စားလှယ်ပြောင်းပါ။", - "change_rep_message": "ကိုယ်စားလှယ်ပြောင်းလိုသည်မှာ သေချာပါသလား။", - "unsupported_asset": "ဤပိုင်ဆိုင်မှုအတွက် ဤလုပ်ဆောင်ချက်ကို ကျွန်ုပ်တို့ မပံ့ပိုးပါ။ ကျေးဇူးပြု၍ ပံ့ပိုးပေးထားသော ပိုင်ဆိုင်မှုအမျိုးအစား၏ ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", - "manage_pow_nodes": "PoW Nodes ကို စီမံပါ။", - "support_title_live_chat": "တိုက်ရိုက်ပံ့ပိုးမှု", - "support_description_live_chat": "အခမဲ့နှင့်အစာရှောင်ခြင်း! လေ့ကျင့်ထားသောထောက်ခံသူကိုယ်စားလှယ်များသည်ကူညီနိုင်သည်", - "support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ", - "support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု", - "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", - "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ", - "choose_derivation": "ပိုက်ဆံအိတ်ကိုရွေးချယ်ပါ", - "new_first_wallet_text": "သင့်ရဲ့ cryptocurrencrencres ကိုအလွယ်တကူလုံခြုံစွာထားရှိပါ", - "select_destination": "အရန်ဖိုင်အတွက် ဦးတည်ရာကို ရွေးပါ။", - "auto_generate_subaddresses": "အော်တို Generate Subaddresses", - "save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။", - "select_buy_provider_notice": "အပေါ်ကဝယ်သူတစ် ဦး ကိုရွေးချယ်ပါ။ သင်၏ default 0 ယ်သူအား app settings တွင် setting လုပ်ခြင်းဖြင့်ဤ screen ကိုကျော်သွားနိုင်သည်။", - "onramper_option_description": "ငွေပေးချေမှုနည်းလမ်းများစွာဖြင့် Crypto ကိုလျင်မြန်စွာ 0 ယ်ပါ။ နိုင်ငံအများစုတွင်ရရှိနိုင်ပါသည်။ ဖြန့်ဖြူးနှင့်အခကြေးငွေကွဲပြားခြားနားသည်။", - "default_buy_provider": "Default Provider ကိုဝယ်ပါ", - "ask_each_time": "တစ်ခုချင်းစီကိုအချိန်မေးပါ", - "buy_provider_unavailable": "လက်ရှိတွင်လက်ရှိမရနိုင်ပါ။", - "signTransaction": "ငွေလွှဲဝင်ပါ။", - "errorGettingCredentials": "မအောင်မြင်ပါ- အထောက်အထားများ ရယူနေစဉ် အမှားအယွင်း", - "errorSigningTransaction": "ငွေပေးငွေယူ လက်မှတ်ထိုးစဉ် အမှားအယွင်းတစ်ခု ဖြစ်ပေါ်ခဲ့သည်။", - "pairingInvalidEvent": "မမှန်ကန်သောဖြစ်ရပ်ကို တွဲချိတ်ခြင်း။", - "chains": "ဆွဲကြိုး", - "methods": "နည်းလမ်းများ", - "events": "အဲ့ဒါနဲ့", - "reject": "ငြင်းပယ်ပါ။", - "approve": "လက်မခံပါ။", - "expiresOn": "သက်တမ်းကုန်သည်။", - "walletConnect": "Wallet ချိတ်ဆက်မှု", - "nullURIError": "URI သည် null ဖြစ်သည်။", - "connectWalletPrompt": "အရောင်းအဝယ်ပြုလုပ်ရန် သင့်ပိုက်ဆံအိတ်ကို WalletConnect နှင့် ချိတ်ဆက်ပါ။", - "newConnection": "ချိတ်ဆက်မှုအသစ်", - "activeConnectionsPrompt": "လက်ရှိချိတ်ဆက်မှုများ ဤနေရာတွင် ပေါ်လာပါမည်။", - "deleteConnectionConfirmationPrompt": "ချိတ်ဆက်မှုကို ဖျက်လိုသည်မှာ သေချာပါသလား။", - "event": "ပွဲ", - "successful": "အောင်မြင်တယ်။", - "wouoldLikeToConnect": "ချိတ်ဆက်ချင်ပါတယ်။", - "message": "မက်ဆေ့ချ်", - "do_not_have_enough_gas_asset": "လက်ရှိ blockchain ကွန်ရက်အခြေအနေများနှင့် အရောင်းအဝယ်ပြုလုပ်ရန် သင့်တွင် ${currency} လုံလောက်မှုမရှိပါ။ သင်သည် မတူညီသော ပိုင်ဆိုင်မှုတစ်ခုကို ပေးပို့နေသော်လည်း blockchain ကွန်ရက်အခကြေးငွေကို ပေးဆောင်ရန် သင်သည် နောက်ထပ် ${currency} လိုအပ်ပါသည်။", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "ကျေးဇူးပြု၍ dApp ကို စီမံလုပ်ဆောင်ခြင်း အပြီးသတ်ရန် စောင့်ပါ။", - "copyWalletConnectLink": "dApp မှ WalletConnect လင့်ခ်ကို ကူးယူပြီး ဤနေရာတွင် ကူးထည့်ပါ။", - "enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။", - "seed_key": "မျိုးစေ့သော့", - "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", - "change_rep_successful": "အောင်မြင်စွာကိုယ်စားလှယ်ပြောင်းလဲသွားတယ်", - "add_contact": "အဆက်အသွယ်ထည့်ပါ။", - "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!", - "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", - "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", - "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", - "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", - "order_by": "အမှာစာ", - "creation_date": "ဖန်တီးမှုနေ့စွဲ", - "group_by_type": "အမျိုးအစားအလိုက်အုပ်စုဖွဲ့", - "importNFTs": "NFTs များကို တင်သွင်းပါ။", - "noNFTYet": "NFTs မရှိသေးပါ။", - "address": "လိပ်စာ", - "enterTokenID": "တိုကင် ID ကိုထည့်ပါ။", - "tokenID": "အမှတ်သညာ", - "name": "နာမည်", - "symbol": "သင်္ကေတ", - "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", - "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", - "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", - "unspent_change": "ပေြာင်းလဲခြင်း", - "tor_connection": "Tor ချိတ်ဆက်မှု", - "setup_warning_2fa_text": "ကိတ်မုန့် 2FA သည် ပိုက်ဆံအိတ်ရှိ အချို့သော လုပ်ဆောင်ချက်များ အတွက် ဒုတိယ စစ်မှန်ကြောင်း အထောက်အထား ဖြစ်သည်။ ၎င်းသည် အအေးခန်းကဲ့သို့ မလုံခြုံပါ။\n\nသင်၏ 2FA အက်ပ် သို့မဟုတ် TOTP သော့များကို အသုံးပြုခွင့် ဆုံးရှုံးပါက၊ သင်သည် ဤပိုက်ဆံအိတ်သို့ ဝင်ရောက်ခွင့် ဆုံးရှုံးမည်ဖြစ်သည်။ သင့်ပိုက်ဆံအိတ်ကို mnemonic မျိုးစေ့မှ ပြန်လည်ရယူရန် လိုအပ်မည်ဖြစ်သည်။\n\nသင်သည် သင်၏ 2FA သို့မဟုတ် mnemonic အစေ့များကို အသုံးပြုခွင့်ဆုံးရှုံးသွားပါက ကိတ်မုန့်ပံ့ပိုးကူညီမှု မပေးနိုင်ပါ။\nCake 2FA ကို အသုံးမပြုမီ၊ လမ်းညွှန်ချက်မှတစ်ဆင့် ဖတ်ရန် အကြံပြုအပ်ပါသည်။", - "scan_qr_on_device": "အခြားစက်တွင် ဤ QR ကုဒ်ကို စကင်ဖတ်ပါ။", - "how_to_use": "အသုံးပြုနည်း", - "seed_hex_form": "ပိုက်ဆံအိတ်မျိုးစေ့ (Hex Form)", - "seedtype": "မျိုးပွားခြင်း", - "seedtype_legacy": "အမွေအနှစ် (စကားလုံး 25 လုံး)", - "seedtype_polyseed": "polyseed (စကားလုံး 16 လုံး)", - "seed_language_czech": "ချက်", - "seed_language_korean": "ကိုးရီးယား", - "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)", - "ascending": "တက်", - "descending": "ဆင်း", - "dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်", - "polygonscan_history": "PolygonScan မှတ်တမ်း", - "wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့", - "default_sell_provider": "ပုံသေရောင်းချပေးသူ", - "select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။", - "custom_drag": "စိတ်ကြိုက် (Drag)", - "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)", - "use_testnet": "testnet ကိုသုံးပါ", - "receivable_balance": "လက်ကျန်ငွေ", - "confirmed_tx": "အတည်ပြုသည်", - "transaction_details_source_address": "အရင်းအမြစ်လိပ်စာ", - "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။", - "contractName": "စာချုပ်အမည်", - "contractSymbol": "စာချုပ်သင်္ကေတ", - "description": "ဖော်ပြချက်", - "camera_consent": "မှတ်ပုံတင်ခြင်းရည်ရွယ်ချက်များအတွက် ${provider} တွင် သင့်ကင်မရာကို အသုံးပြုပါမည်။ အသေးစိတ်အတွက် ၎င်းတို့၏ ကိုယ်ရေးကိုယ်တာမူဝါဒကို စစ်ဆေးပါ။", - "no_relays": "Relay မရှိပါ။", - "choose_relay": "အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။", - "no_relays_message": "ဤအသုံးပြုသူအတွက် Nostr NIP-05 မှတ်တမ်းကို ကျွန်ုပ်တို့တွေ့ရှိသော်လည်း ၎င်းတွင် မည်သည့် relays မှ မပါဝင်ပါ။ ကျေးဇူးပြု၍ လက်ခံသူကို ၎င်းတို့၏ Nostr မှတ်တမ်းတွင် ထပ်လောင်းထည့်ရန် ညွှန်ကြားပါ။", - "no_relay_on_domain": "အသုံးပြုသူ၏ဒိုမိန်းအတွက် ထပ်ဆင့်လွှင့်ခြင်း မရှိပါ သို့မဟုတ် ထပ်ဆင့်လွှင့်ခြင်း မရနိုင်ပါ။ အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။" - "zzzz": "မိုးခေဇဇ်" + "you_will_send": "မှပြောင်းပါ။" } \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 8a4799e36..a38826921 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -715,6 +715,7 @@ "use_card_info_two": "Tegoeden worden omgezet naar USD wanneer ze op de prepaid-rekening staan, niet in digitale valuta.", "use_ssl": "Gebruik SSL", "use_suggested": "Gebruik aanbevolen", + "use_testnet": "Gebruik testnet", "variable_pair_not_supported": "Dit variabelenpaar wordt niet ondersteund met de geselecteerde uitwisselingen", "verification": "Verificatie", "verify_with_2fa": "Controleer met Cake 2FA", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "Je hebt nu een debetkaart", "you_pay": "U betaalt", "you_will_get": "Converteren naar", - "you_will_send": "Converteren van", - "yy": "JJ", - "online": "online", - "offline": "Offline", - "gift_card_number": "Cadeaukaartnummer", - "pin_number": "PIN-nummer", - "total_saving": "Totale besparingen", - "last_30_days": "Laatste 30 dagen", - "avg_savings": "Gem. besparingen", - "view_all": "Alles bekijken", - "active_cards": "Actieve kaarten", - "delete_account": "Account verwijderen", - "cards": "Kaarten", - "active": "Actief", - "redeemed": "Verzilverd", - "gift_card_balance_note": "Cadeaukaarten met een resterend saldo verschijnen hier", - "gift_card_redeemed_note": "Cadeaubonnen die je hebt ingewisseld, verschijnen hier", - "logout": "Uitloggen", - "add_tip": "Tip toevoegen", - "percentageOf": "van ${amount}", - "is_percentage": "is", - "search_category": "Zoek categorie", - "mark_as_redeemed": "Markeer als ingewisseld", - "more_options": "Meer opties", - "waiting_payment_confirmation": "In afwachting van betalingsbevestiging", - "transaction_sent_notice": "Als het scherm na 1 minuut niet verder gaat, controleer dan een blokverkenner en je e-mail.", - "agree": "mee eens", - "in_store": "In winkel", - "generating_gift_card": "Cadeaubon genereren", - "payment_was_received": "Uw betaling is ontvangen.", - "proceed_after_one_minute": "Als het scherm na 1 minuut niet verder gaat, controleer dan uw e-mail.", - "order_id": "Order-ID", - "gift_card_is_generated": "Cadeaukaart is gegenereerd", - "open_gift_card": "Geschenkkaart openen", - "contact_support": "Contact opnemen met ondersteuning", - "gift_cards_unavailable": "Cadeaubonnen kunnen momenteel alleen worden gekocht via Monero, Bitcoin en Litecoin", - "background_sync_mode": "Achtergrondsynchronisatiemodus", - "sync_all_wallets": "Alle portemonnees synchroniseren", - "introducing_cake_pay": "Introductie van Cake Pay!", - "cake_pay_learn_more": "Koop en wissel cadeaubonnen direct in de app in!\nSwipe van links naar rechts voor meer informatie.", - "automatic": "automatisch", - "fixed_pair_not_supported": "Dit vaste paar wordt niet ondersteund bij de geselecteerde exchanges", - "variable_pair_not_supported": "Dit variabelenpaar wordt niet ondersteund met de geselecteerde uitwisselingen", - "none_of_selected_providers_can_exchange": "Geen van de geselecteerde providers kan deze uitwisseling maken", - "choose_one": "Kies er een", - "choose_from_available_options": "Kies uit de beschikbare opties:", - "custom_redeem_amount": "Aangepast inwisselbedrag", - "add_custom_redemption": "Voeg aangepaste inwisseling toe", - "remaining": "resterende", - "delete_wallet": "Portemonnee verwijderen", - "delete_wallet_confirm_message": "Weet u zeker dat u de portemonnee van ${wallet_name} wilt verwijderen?", - "low_fee": "Lage vergoeding", - "low_fee_alert": "U gebruikt momenteel een lage prioriteit voor netwerkkosten. Dit kan lange wachttijden, andere tarieven of geannuleerde transacties veroorzaken. We raden aan een hogere vergoeding in te stellen voor een betere ervaring.", - "ignor": "Negeren", - "use_suggested": "Gebruik aanbevolen", - "do_not_share_warning_text": "Deel deze met niemand anders, ook niet met support.\n\nUw geld kan en zal worden gestolen!", - "help": "helpen", - "all_transactions": "Alle transacties", - "all_trades": "Alle transacties", - "connection_sync": "Verbinding en synchronisatie", - "security_and_backup": "Beveiliging en back-up", - "create_backup": "Maak een back-up", - "privacy_settings": "Privacy-instellingen", - "privacy": "Privacy", - "display_settings": "Weergave-instellingen", - "other_settings": "Andere instellingen", - "require_pin_after": "Pincode vereist na", - "always": "altijd", - "minutes_to_pin_code": "${minute} minuten", - "disable_exchange": "Uitwisseling uitschakelen", - "advanced_settings": "Geavanceerde instellingen", - "settings_can_be_changed_later": "Deze instellingen kunnen later worden gewijzigd in de app-instellingen", - "add_custom_node": "Voeg een nieuw aangepast knooppunt toe", - "disable_fiat": "Schakel Fiat uit", - "fiat_api": "Fiat API", - "disabled": "Gehandicapt", - "enabled": "Ingeschakeld", - "tor_only": "Alleen Tor", - "unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR", - "orbot_running_alert": "Zorg ervoor dat Orbot actief is voordat u verbinding maakt met dit knooppunt.", - "contact_list_contacts": "Contacten", - "contact_list_wallets": "Mijn portefeuilles", - "bitcoin_payments_require_1_confirmation": "Bitcoin-betalingen vereisen 1 bevestiging, wat 20 minuten of langer kan duren. Dank voor uw geduld! U ontvangt een e-mail wanneer de betaling is bevestigd.", - "send_to_this_address": "Stuur ${currency} ${tag}naar dit adres", - "arrive_in_this_address": "${currency} ${tag}komt aan op dit adres", - "do_not_send": "Niet sturen", - "error_dialog_content": "Oeps, er is een fout opgetreden.\n\nStuur het crashrapport naar ons ondersteuningsteam om de applicatie te verbeteren.", - "scan_qr_code": "Scan QR-code", - "cold_or_recover_wallet": "Voeg een cold wallet toe of herstel een paper wallet", - "please_wait": "Even geduld aub", - "sweeping_wallet": "Vegende portemonnee", - "sweeping_wallet_alert": "Dit duurt niet lang. VERLAAT DIT SCHERM NIET, ANDERS KAN HET SWEPT-GELD VERLOREN WORDEN", - "decimal_places_error": "Te veel decimalen", - "edit_node": "Knooppunt bewerken", - "invoice_details": "Factuurgegevens", - "donation_link_details": "Details van de donatielink", - "anonpay_description": "Genereer ${type}. De ontvanger kan ${method} gebruiken met elke ondersteunde cryptocurrency en u ontvangt geld in deze portemonnee", - "create_invoice": "Factuur maken", - "create_donation_link": "Maak een donatielink aan", - "optional_email_hint": "Optionele kennisgeving per e-mail aan de begunstigde", - "optional_description": "Optionele beschrijving", - "optional_name": "Optionele naam ontvanger", - "clearnet_link": "Clearnet-link", - "onion_link": "Ui koppeling", - "settings": "Instellingen", - "sell_monero_com_alert_content": "Het verkopen van Monero wordt nog niet ondersteund", - "error_text_input_below_minimum_limit": "Bedrag is minder dan minimaal", - "error_text_input_above_maximum_limit": "Bedrag is meer dan maximaal", - "show_market_place": "Toon Marktplaats", - "prevent_screenshots": "Voorkom screenshots en schermopname", - "profile": "Profiel", - "close": "Dichtbij", - "modify_2fa": "Wijzig Cake 2FA", - "disable_cake_2fa": "Taart 2FA uitschakelen", - "question_to_disable_2fa": "Weet je zeker dat je Cake 2FA wilt uitschakelen? Er is geen 2FA-code meer nodig om toegang te krijgen tot de portemonnee en bepaalde functies.", - "disable": "Uitzetten", - "setup_2fa": "Opstelling Taart 2FA", - "verify_with_2fa": "Controleer met Cake 2FA", - "totp_code": "TOTP-code", - "please_fill_totp": "Vul de 8-cijferige code in die op uw andere apparaat aanwezig is", - "totp_2fa_success": "Succes! Cake 2FA ingeschakeld voor deze portemonnee. Vergeet niet om uw geheugensteuntje op te slaan voor het geval u de toegang tot de portemonnee kwijtraakt.", - "totp_verification_success": "Verificatie geslaagd!", - "totp_2fa_failure": "Foute code. Probeer een andere code of genereer een nieuwe geheime sleutel. Gebruik een compatibele 2FA-app die 8-cijferige codes en SHA512 ondersteunt.", - "enter_totp_code": "Voer de TOTP-code in.", - "add_secret_code": "Of voeg deze geheime code toe aan een authenticator-app", - "totp_secret_code": "TOTP-geheime code", - "setup_2fa_text": "Cake 2FA werkt met TOTP als tweede authenticatiefactor.\n\nCake 2FA's TOTP vereist SHA-512 en 8-cijferige ondersteuning; dit zorgt voor meer veiligheid. Meer informatie en ondersteunde apps vindt u in de gids.", - "setup_totp_recommended": "TOTP instellen", - "disable_buy": "Koopactie uitschakelen", - "disable_sell": "Verkoopactie uitschakelen", - "auto_generate_subaddresses": "Automatisch subadressen genereren", - "cake_2fa_preset": "Taart 2FA Voorinstelling", - "narrow": "Smal", - "normal": "Normaal", - "aggressive": "Overijverig", - "require_for_assessing_wallet": "Vereist voor toegang tot portemonnee", - "require_for_sends_to_non_contacts": "Vereist voor verzendingen naar niet-contacten", - "require_for_sends_to_contacts": "Vereist voor verzending naar contacten", - "require_for_sends_to_internal_wallets": "Vereist voor verzendingen naar interne portefeuilles", - "require_for_exchanges_to_internal_wallets": "Vereist voor uitwisselingen naar interne portefeuilles", - "require_for_adding_contacts": "Vereist voor het toevoegen van contacten", - "require_for_creating_new_wallets": "Vereist voor het maken van nieuwe portefeuilles", - "require_for_all_security_and_backup_settings": "Vereist voor alle beveiligings- en back-upinstellingen", - "available_balance_description": "Beschikbaar saldo is het saldo dat u kunt uitgeven. Het kan lager zijn dan uw totale saldo als u onlangs geld hebt verzonden.", - "syncing_wallet_alert_title": "Uw portemonnee wordt gesynchroniseerd", - "syncing_wallet_alert_content": "Uw saldo- en transactielijst is mogelijk pas compleet als er bovenaan 'GESYNCHRONISEERD' staat. Klik/tik voor meer informatie.", - "home_screen_settings": "Instellingen voor het startscherm", - "sort_by": "Sorteer op", - "search_add_token": "Token zoeken / toevoegen", - "edit_token": "Token bewerken", - "warning": "Waarschuwing", - "add_token_warning": "Bewerk of voeg geen tokens toe volgens de instructies van oplichters.\nBevestig tokenadressen altijd met betrouwbare bronnen!", - "add_token_disclaimer_check": "Ik heb het adres en de informatie van het tokencontract bevestigd met behulp van een betrouwbare bron. Het toevoegen van kwaadaardige of onjuiste informatie kan leiden tot verlies van geld.", - "token_contract_address": "Token contractadres", - "token_name": "Tokennaam bijv.: Tether", - "token_symbol": "Tokensymbool bijv.: USDT", - "token_decimal": "Token decimaal", - "field_required": "dit veld is verplicht", - "pin_at_top": "speld ${token} bovenaan", - "invalid_input": "Ongeldige invoer", - "fiat_balance": "Fiat Balans", - "gross_balance": "Bruto saldo", - "alphabetical": "Alfabetisch", - "generate_name": "Naam genereren", - "balance_page": "Saldo pagina", - "share": "Deel", - "slidable": "Verschuifbaar", - "monero_dark_theme": "Monero donker thema", - "bitcoin_dark_theme": "Bitcoin donker thema", - "bitcoin_light_theme": "Bitcoin Light-thema", - "high_contrast_theme": "Thema met hoog contrast", - "matrix_green_dark_theme": "Matrix groen donker thema", - "monero_light_theme": "Monero Light-thema", - "manage_nodes": "Beheer knooppunten", - "etherscan_history": "Etherscan-geschiedenis", - "template_name": "Sjabloonnaam", - "change_rep": "Vertegenwoordiger wijzigen", - "change_rep_message": "Weet u zeker dat u van vertegenwoordiger wilt veranderen?", - "unsupported_asset": "We ondersteunen deze actie niet voor dit item. Maak of schakel over naar een portemonnee van een ondersteund activatype.", - "manage_pow_nodes": "PoW-knooppunten beheren", - "support_title_live_chat": "Live ondersteuning", - "support_description_live_chat": "Gratis en snel! Getrainde ondersteuningsvertegenwoordigers zijn beschikbaar om te helpen", - "support_title_guides": "Cake -portemonnee gidsen", - "support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen", - "support_title_other_links": "Andere ondersteuningslinks", - "support_description_other_links": "Word lid van onze gemeenschappen of bereik ons ​​onze partners via andere methoden", - "choose_derivation": "Kies portemonnee -afleiding", - "new_first_wallet_text": "Houd uw cryptocurrency gemakkelijk veilig", - "select_destination": "Selecteer de bestemming voor het back-upbestand.", - "save_to_downloads": "Opslaan in downloads", - "select_buy_provider_notice": "Selecteer hierboven een koopprovider. U kunt dit scherm overslaan door uw standaard kopenprovider in te stellen in app -instellingen.", - "onramper_option_description": "Koop snel crypto met veel betaalmethoden. Beschikbaar in de meeste landen. Spreads en vergoedingen variëren.", - "default_buy_provider": "Standaard Koopprovider", - "ask_each_time": "Vraag het elke keer", - "buy_provider_unavailable": "Provider momenteel niet beschikbaar.", - "signTransaction": "Transactie ondertekenen", - "errorGettingCredentials": "Mislukt: fout bij het ophalen van inloggegevens", - "errorSigningTransaction": "Er is een fout opgetreden tijdens het ondertekenen van de transactie", - "pairingInvalidEvent": "Koppelen Ongeldige gebeurtenis", - "chains": "Ketens", - "methods": "Methoden", - "events": "Evenementen", - "reject": "Afwijzen", - "approve": "Goedkeuren", - "expiresOn": "Verloopt op", - "walletConnect": "WalletConnect", - "nullURIError": "URI is nul", - "connectWalletPrompt": "Verbind uw portemonnee met WalletConnect om transacties uit te voeren", - "newConnection": "Nieuwe verbinding", - "activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven", - "deleteConnectionConfirmationPrompt": "Weet u zeker dat u de verbinding met", - "event": "Evenement", - "successful": "Succesvol", - "wouoldLikeToConnect": "wil graag verbinden", - "message": "Bericht", - "do_not_have_enough_gas_asset": "U heeft niet genoeg ${currency} om een transactie uit te voeren met de huidige blockchain-netwerkomstandigheden. U heeft meer ${currency} nodig om blockchain-netwerkkosten te betalen, zelfs als u een ander item verzendt.", - "totp_auth_url": "TOTP AUTH-URL", - "awaitDAppProcessing": "Wacht tot de dApp klaar is met verwerken.", - "copyWalletConnectLink": "Kopieer de WalletConnect-link van dApp en plak deze hier", - "enterWalletConnectURI": "Voer WalletConnect-URI in", - "seed_key": "Zaadsleutel", - "enter_seed_phrase": "Voer uw zaadzin in", - "change_rep_successful": "Met succes veranderde vertegenwoordiger", - "add_contact": "Contactpersoon toevoegen", - "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!", - "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", - "order_by": "Bestellen door", - "creation_date": "Aanmaakdatum", - "group_by_type": "Groep voor type", - "importNFTs": "NFT's importeren", - "noNFTYet": "Nog geen NFT's", - "address": "Adres", - "enterTokenID": "Voer de token-ID in", - "tokenID": "ID kaart", - "name": "Naam", - "symbol": "Symbool", - "seed_phrase_length": "Lengte van de zaadzin", - "unavailable_balance": "Onbeschikbaar saldo", - "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", - "unspent_change": "Wijziging", - "tor_connection": "Tor-verbinding", - "setup_warning_2fa_text": "U moet uw portemonnee herstellen vanuit het geheugensteuntje.\n\nCake Support kan u niet helpen als u de toegang tot uw 2FA- of mnemonic-zaden verliest.\nCake 2FA is een tweede authenticatie voor bepaalde acties in de portemonnee. Voordat u Cake 2FA gebruikt, raden wij u aan de handleiding door te lezen.Het is NIET zo veilig als koude opslag.\n\nAls u de toegang tot uw 2FA-app of TOTP-sleutels verliest, verliest u de toegang tot deze portemonnee. ", - "scan_qr_on_device": "Scan deze QR-code op een ander apparaat", - "how_to_use": "Hoe te gebruiken", - "seed_hex_form": "Portemonnee zaad (hexvorm)", - "seedtype": "Zaadtype", - "seedtype_legacy": "Legacy (25 woorden)", - "seedtype_polyseed": "Polyseed (16 woorden)", - "seed_language_czech": "Tsjechisch", - "seed_language_korean": "Koreaans", - "ascending": "Stijgend", - "descending": "Aflopend", - "seed_language_chinese_traditional": "Chinese (traditionele)", - "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", - "polygonscan_history": "PolygonScan-geschiedenis", - "wallet_seed_legacy": "Legacy portemonnee zaad", - "default_sell_provider": "Standaard verkoopaanbieder", - "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.", - "custom_drag": "Custom (vasthouden en slepen)", - "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)", - "use_testnet": "Gebruik testnet", - "receivable_balance": "Het saldo", - "confirmed_tx": "Bevestigd", - "transaction_details_source_address": "Bron adres", - "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken.", - "contractName": "Contractnaam", - "contractSymbol": "Contractsymbool", - "description": "Beschrijving", - "camera_consent": "Uw camera wordt gebruikt om vóór ${provider} een beeld vast te leggen voor identificatiedoeleinden. Raadpleeg hun privacybeleid voor meer informatie.", - "no_relays": "Geen relais", - "choose_relay": "Kies een relais dat u wilt gebruiken", - "no_relays_message": "We hebben een Nostr NIP-05-record voor deze gebruiker gevonden, maar deze bevat geen relays. Instrueer de ontvanger om relays toe te voegen aan zijn Nostr-record.", - "no_relay_on_domain": "Er is geen relay voor het domein van de gebruiker of de relay is niet beschikbaar. Kies een relais dat u wilt gebruiken." - "zzzz": "Zzzz" + "you_will_send": "Converteren van" } \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index bca2b718c..fa8decbee 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -716,6 +716,7 @@ "use_card_info_two": "Środki są przeliczane na USD, gdy są przechowywane na koncie przedpłaconym, a nie w walutach cyfrowych.", "use_ssl": "Użyj SSL", "use_suggested": "Użyj sugerowane", + "use_testnet": "Użyj testne", "variable_pair_not_supported": "Ta para zmiennych nie jest obsługiwana na wybranych giełdach", "verification": "Weryfikacja", "verify_with_2fa": "Sprawdź za pomocą Cake 2FA", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "Masz teraz kartę debetową", "you_pay": "Płacisz", "you_will_get": "Konwertuj na", - "you_will_send": "Konwertuj z", - "yy": "RR", - "online": "online", - "offline": "Offline", - "gift_card_number": "Numer karty podarunkowej", - "pin_number": "Numer PIN", - "total_saving": "Całkowite oszczędności", - "last_30_days": "Ostatnie 30 dni", - "avg_savings": "Śr. oszczędności", - "view_all": "Wyświetl wszystko", - "active_cards": "Aktywne karty", - "delete_account": "Usuń konto", - "cards": "Karty", - "active": "Aktywny", - "redeemed": "wykupione", - "gift_card_balance_note": "Tutaj pojawią się karty podarunkowe z pozostałym saldem", - "gift_card_redeemed_note": "Karty podarunkowe, które wykorzystałeś, pojawią się tutaj", - "logout": "Wyloguj", - "add_tip": "Dodaj wskazówkę", - "percentageOf": "z ${amount}", - "is_percentage": "jest", - "search_category": "Kategoria wyszukiwania", - "mark_as_redeemed": "Oznacz jako wykorzystany", - "more_options": "Więcej opcji", - "awaiting_payment_confirmation": "Oczekiwanie na potwierdzenie płatności", - "transaction_sent_notice": "Jeśli ekran nie zmieni się po 1 minucie, sprawdź eksplorator bloków i swój e-mail.", - "agree": "Zgadzam się", - "in_store": "W Sklepie", - "generating_gift_card": "Generowanie karty podarunkowej", - "payment_was_received": "Twoja płatność została otrzymana.", - "proceed_after_one_minute": "Jeśli ekran nie przejdzie dalej po 1 minucie, sprawdź pocztę.", - "order_id": "Identyfikator zamówienia", - "gift_card_is_generated": "Karta podarunkowa jest generowana", - "open_gift_card": "Otwórz kartę podarunkową", - "contact_support": "Skontaktuj się z pomocą techniczną", - "gift_cards_unavailable": "Karty podarunkowe można obecnie kupić tylko za pośrednictwem Monero, Bitcoin i Litecoin", - "background_sync_mode": "Tryb synchronizacji w tle", - "sync_all_wallets": "Synchronizuj wszystkie portfele", - "introducing_cake_pay": "Przedstawiamy Cake Pay!", - "cake_pay_learn_more": "Kupuj i wykorzystuj karty podarunkowe od razu w aplikacji!\nPrzesuń od lewej do prawej, aby dowiedzieć się więcej.", - "automatic": "Automatyczny", - "fixed_pair_not_supported": "Ta stała para nie jest obsługiwana na wybranych giełdach", - "variable_pair_not_supported": "Ta para zmiennych nie jest obsługiwana na wybranych giełdach", - "none_of_selected_providers_can_exchange": "Żaden z wybranych dostawców nie może dokonać tej wymiany", - "choose_one": "Wybierz jeden", - "choose_from_available_options": "Wybierz z dostępnych opcji:", - "custom_redeem_amount": "Niestandardowa kwota wykorzystania", - "add_custom_redemption": "Dodaj niestandardowe wykorzystanie", - "remaining": "pozostałe", - "delete_wallet": "Usuń portfel", - "delete_wallet_confirm_message": "Czy na pewno chcesz usunąć portfel ${wallet_name}?", - "low_fee": "Niska opłata", - "low_fee_alert": "Obecnie korzystasz z niskiego priorytetu opłaty sieciowej. Może to spowodować długie oczekiwanie, różne stawki lub anulowane transakcje. Zalecamy ustawienie wyższej opłaty, aby zapewnić lepsze wrażenia.", - "ignor": "Ignorować", - "use_suggested": "Użyj sugerowane", - "do_not_share_warning_text": "NIE udostępniaj ich nikomu innemu, w tym pomocy technicznej.\n\nTwoje środki wtedy prawdopodobnie zostaną skradzione!", - "help": "pomoc", - "all_transactions": "Wszystkie transakcje", - "all_trades": "Wszystkie operacje", - "connection_sync": "Połączenie i synchronizacja", - "security_and_backup": "Bezpieczeństwo i kopia zapasowa", - "create_backup": "Utwórz kopię zapasową", - "privacy_settings": "Ustawienia prywatności", - "privacy": "Prywatność", - "display_settings": "Ustawienia wyświetlania", - "other_settings": "Inne ustawienia", - "require_pin_after": "Wymagaj kodu PIN po", - "always": "zawsze", - "minutes_to_pin_code": "${minute} minut", - "disable_exchange": "Wyłącz wymianę", - "advanced_settings": "Zaawansowane ustawienia", - "settings_can_be_changed_later": "Te ustawienia można później zmienić w ustawieniach aplikacji", - "add_custom_node": "Dodaj nowy węzeł niestandardowy", - "disable_fiat": "Wyłącz waluty FIAT", - "fiat_api": "API Walut FIAT", - "disabled": "Wyłączone", - "enabled": "Włączone", - "tor_only": "Tylko sieć Tor", - "unmatched_currencies": "Waluta Twojego obecnego portfela nie zgadza się z waluctą zeskanowanego kodu QR", - "orbot_running_alert": "Upewnij się, że Orbot działa przed połączeniem z tym węzłem.", - "contact_list_contacts": "Łączność", - "contact_list_wallets": "Moje portfele", - "bitcoin_payments_require_1_confirmation": "Płatności Bitcoin wymagają 1 potwierdzenia, co może zająć 20 minut lub dłużej. Dziękuję za cierpliwość! Otrzymasz wiadomość e-mail, gdy płatność zostanie potwierdzona.", - "send_to_this_address": "Wyślij ${currency} ${tag}na ten adres", - "arrive_in_this_address": "${currency} ${tag}dotrze na ten adres", - "do_not_send": "Nie wysyłaj", - "error_dialog_content": "Ups, wystąpił błąd.\n\nPrześlij raport o awarii do naszego zespołu wsparcia, aby ulepszyć aplikację.", - "scan_qr_code": "Skanowania QR code", - "cold_or_recover_wallet": "Dodaj zimny portfel lub odzyskaj portfel papierowy", - "please_wait": "Proszę czekać", - "sweeping_wallet": "Zamiatanie portfela", - "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", - "decimal_places_error": "Za dużo miejsc dziesiętnych", - "edit_node": "Edytuj węzeł", - "invoice_details": "Dane do faktury", - "donation_link_details": "Szczegóły linku darowizny", - "anonpay_description": "Wygeneruj ${type}. Odbiorca może ${method} z dowolną obsługiwaną kryptowalutą, a Ty otrzymasz środki w tym portfelu.", - "create_invoice": "Wystaw fakturę", - "create_donation_link": "Utwórz link do darowizny", - "optional_email_hint": "Opcjonalny e-mail z powiadomieniem odbiorcy płatności", - "optional_description": "Opcjonalny opis", - "optional_name": "Opcjonalna nazwa odbiorcy", - "clearnet_link": "łącze Clearnet", - "onion_link": "Łącznik cebulowy", - "settings": "Ustawienia", - "sell_monero_com_alert_content": "Sprzedaż Monero nie jest jeszcze obsługiwana", - "error_text_input_below_minimum_limit": "Kwota jest mniejsza niż minimalna", - "error_text_input_above_maximum_limit": "Kwota jest większa niż maksymalna", - "show_market_place": "Pokaż rynek", - "prevent_screenshots": "Zapobiegaj zrzutom ekranu i nagrywaniu ekranu", - "profile": "Profil", - "close": "Zamknąć", - "modify_2fa": "Zmodyfikuj ciasto 2FA", - "disable_cake_2fa": "Wyłącz Cake 2FA", - "question_to_disable_2fa": "Czy na pewno chcesz wyłączyć Cake 2FA? Kod 2FA nie będzie już potrzebny do uzyskania dostępu do portfela i niektórych funkcji.", - "disable": "Wyłączyć", - "setup_2fa": "Skonfiguruj ciasto 2FA", - "verify_with_2fa": "Sprawdź za pomocą Cake 2FA", - "totp_code": "Kod TOTP", - "please_fill_totp": "Wpisz 8-cyfrowy kod znajdujący się na drugim urządzeniu", - "totp_2fa_success": "Powodzenie! Cake 2FA włączony dla tego portfela. Pamiętaj, aby zapisać swoje mnemoniczne ziarno na wypadek utraty dostępu do portfela.", - "totp_verification_success": "Weryfikacja powiodła się!", - "totp_2fa_failure": "Błędny kod. Spróbuj użyć innego kodu lub wygeneruj nowy tajny klucz. Użyj kompatybilnej aplikacji 2FA, która obsługuje 8-cyfrowe kody i SHA512.", - "enter_totp_code": "Wprowadź kod TOTP.", - "add_secret_code": "Możesz też dodać ten tajny kod do aplikacji uwierzytelniającej", - "totp_secret_code": "Tajny kod TOTP", - "setup_2fa_text": "Cake 2FA działa przy użyciu TOTP jako drugiego czynnika uwierzytelniającego.\n\nTOTP Cake 2FA wymaga obsługi SHA-512 i 8 cyfr; zapewnia to większe bezpieczeństwo. Więcej informacji i obsługiwane aplikacje znajdziesz w przewodniku.", - "setup_totp_recommended": "Skonfiguruj TOTP", - "disable_buy": "Wyłącz akcję kupna", - "disable_sell": "Wyłącz akcję sprzedaży", - "auto_generate_subaddresses": "Automatycznie generuj podadresy", - "cake_2fa_preset": "Ciasto 2FA Preset", - "narrow": "Wąski", - "normal": "Normalna", - "aggressive": "Nadgorliwy", - "require_for_assessing_wallet": "Wymagaj dostępu do portfela", - "require_for_sends_to_non_contacts": "Wymagaj wysyłania do osób niekontaktowych", - "require_for_sends_to_contacts": "Wymagaj wysyłania do kontaktów", - "require_for_sends_to_internal_wallets": "Wymagaj wysyłania do portfeli wewnętrznych", - "require_for_exchanges_to_internal_wallets": "Wymagaj wymiany do portfeli wewnętrznych", - "require_for_adding_contacts": "Wymagane do dodania kontaktów", - "require_for_creating_new_wallets": "Wymagane do tworzenia nowych portfeli", - "require_for_all_security_and_backup_settings": "Wymagaj dla wszystkich ustawień zabezpieczeń i kopii zapasowych", - "available_balance_description": "Dostępne saldo jest równoważne z saldem portfela minus zamrożone saldo.", - "syncing_wallet_alert_title": "Twój portfel się synchronizuje", - "syncing_wallet_alert_content": "Twoje saldo i lista transakcji mogą nie być kompletne, dopóki u góry nie pojawi się napis „SYNCHRONIZOWANY”. Kliknij/stuknij, aby dowiedzieć się więcej.", - "home_screen_settings": "Ustawienia ekranu głównego", - "sort_by": "Sortuj według", - "search_add_token": "Wyszukaj / Dodaj token", - "edit_token": "Edytuj token", - "warning": "Ostrzeżenie", - "add_token_warning": "Nie edytuj ani nie dodawaj tokenów zgodnie z instrukcjami oszustów.\nZawsze potwierdzaj adresy tokenów z renomowanymi źródłami!", - "add_token_disclaimer_check": "Potwierdziłem adres kontraktu tokena i informacje, korzystając z renomowanego źródła. Dodanie złośliwych lub niepoprawnych informacji może spowodować utratę środków.", - "token_contract_address": "Adres kontraktu tokena", - "token_name": "Nazwa tokena, np.: Tether", - "token_symbol": "Symbol tokena np.: USDT", - "token_decimal": "Token dziesiętny", - "field_required": "To pole jest wymagane", - "pin_at_top": "przypnij ${token} na górze", - "invalid_input": "Nieprawidłowe dane wejściowe", - "fiat_balance": "Bilans Fiata", - "gross_balance": "Saldo brutto", - "alphabetical": "Alfabetyczny", - "generate_name": "Wygeneruj nazwę", - "balance_page": "Strona salda", - "share": "Udział", - "slidable": "Przesuwne", - "monero_dark_theme": "Ciemny motyw Monero", - "bitcoin_dark_theme": "Ciemny motyw Bitcoina", - "bitcoin_light_theme": "Lekki motyw Bitcoin", - "high_contrast_theme": "Motyw o wysokim kontraście", - "matrix_green_dark_theme": "Matrix Zielony ciemny motyw", - "monero_light_theme": "Lekki motyw Monero", - "manage_nodes": "Zarządzaj węzłami", - "etherscan_history": "Historia Etherscanu", - "template_name": "Nazwa szablonu", - "change_rep": "Zmień przedstawiciela", - "change_rep_message": "Czy na pewno chcesz zmienić przedstawiciela?", - "unsupported_asset": "Nie obsługujemy tego działania w przypadku tego zasobu. Utwórz lub przełącz się na portfel obsługiwanego typu aktywów.", - "manage_pow_nodes": "Zarządzaj węzłami PoW", - "support_title_live_chat": "Wsparcie na żywo", - "support_description_live_chat": "Darmowe i szybkie! Do pomocy są dostępni przeszkoleni przedstawiciele wsparcia", - "support_title_guides": "Przewodniki portfela ciasta", - "support_description_guides": "Dokumentacja i wsparcie dla typowych problemów", - "support_title_other_links": "Inne linki wsparcia", - "support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod", - "choose_derivation": "Wybierz wyprowadzenie portfela", - "new_first_wallet_text": "Łatwo zapewnić bezpieczeństwo kryptowalut", - "select_destination": "Wybierz miejsce docelowe dla pliku kopii zapasowej.", - "save_to_downloads": "Zapisz w Pobranych", - "select_buy_provider_notice": "Wybierz powyższe dostawcę zakupu. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę zakupu w ustawieniach aplikacji.", - "onramper_option_description": "Szybko kup kryptowaluty z wieloma metodami płatności. Dostępne w większości krajów. Spready i opłaty różnią się.", - "default_buy_provider": "Domyślny dostawca zakupu", - "ask_each_time": "Zapytaj za każdym razem", - "buy_provider_unavailable": "Dostawca obecnie niedostępny.", - "signTransaction": "Podpisz transakcję", - "errorGettingCredentials": "Niepowodzenie: Błąd podczas uzyskiwania poświadczeń", - "errorSigningTransaction": "Wystąpił błąd podczas podpisywania transakcji", - "pairingInvalidEvent": "Nieprawidłowe zdarzenie parowania", - "chains": "Więzy", - "methods": "Metody", - "events": "Wydarzenia", - "reject": "Odrzucić", - "approve": "Zatwierdzić", - "expiresOn": "Upływa w dniu", - "walletConnect": "PortfelPołącz", - "nullURIError": "URI ma wartość zerową", - "connectWalletPrompt": "Połącz swój portfel z WalletConnect, aby dokonywać transakcji", - "newConnection": "Nowe połączenie", - "activeConnectionsPrompt": "Tutaj pojawią się aktywne połączenia", - "deleteConnectionConfirmationPrompt": "Czy na pewno chcesz usunąć połączenie z", - "event": "Wydarzenie", - "successful": "Udany", - "wouoldLikeToConnect": "chciałbym się połączyć", - "message": "Wiadomość", - "do_not_have_enough_gas_asset": "Nie masz wystarczającej ilości ${currency}, aby dokonać transakcji przy bieżących warunkach sieci blockchain. Potrzebujesz więcej ${currency}, aby uiścić opłaty za sieć blockchain, nawet jeśli wysyłasz inny zasób.", - "totp_auth_url": "Adres URL TOTP AUTH", - "awaitDAppProcessing": "Poczekaj, aż dApp zakończy przetwarzanie.", - "copyWalletConnectLink": "Skopiuj link do WalletConnect z dApp i wklej tutaj", - "enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect", - "seed_key": "Klucz nasion", - "enter_seed_phrase": "Wprowadź swoją frazę nasienną", - "change_rep_successful": "Pomyślnie zmienił przedstawiciela", - "add_contact": "Dodaj kontakt", - "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!", - "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", - "order_by": "Zamów przez", - "creation_date": "Data utworzenia", - "group_by_type": "Grupa według typu", - "importNFTs": "Importuj NFT", - "noNFTYet": "Nie ma jeszcze NFT", - "address": "Adres", - "enterTokenID": "Wprowadź identyfikator tokena", - "tokenID": "ID", - "name": "Nazwa", - "symbol": "Symbol", - "seed_phrase_length": "Długość frazy początkowej", - "unavailable_balance": "Niedostępne saldo", - "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", - "unspent_change": "Zmiana", - "tor_connection": "Połączenie Torem", - "setup_warning_2fa_text": "Będziesz musiał przywrócić swój portfel z nasion mnemonicznych.\n\nWsparcie Cake nie będzie w stanie Ci pomóc, jeśli utracisz dostęp do swoich nasion 2FA lub mnemoników.\nCake 2FA to drugie uwierzytelnienie niektórych działań w portfelu. Przed użyciem Cake 2FA zalecamy zapoznanie się z instrukcją.NIE jest tak bezpieczne jak przechowywanie w chłodni.\n\nJeśli utracisz dostęp do aplikacji 2FA lub kluczy TOTP, UTRAcisz dostęp do tego portfela. ", - "scan_qr_on_device": "Zeskanuj ten kod QR na innym urządzeniu", - "how_to_use": "Jak używać", - "seed_hex_form": "Nasiona portfela (forma sześciokątna)", - "seedtype": "Sedtype", - "seedtype_legacy": "Dziedzictwo (25 słów)", - "seedtype_polyseed": "Poliqueed (16 słów)", - "seed_language_czech": "Czech", - "seed_language_korean": "koreański", - "seed_language_chinese_traditional": "Chiński tradycyjny)", - "ascending": "Wznoszący się", - "descending": "Schodzenie", - "dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie", - "polygonscan_history": "Historia PolygonScan", - "wallet_seed_legacy": "Dziedziczne ziarno portfela", - "default_sell_provider": "Domyślny dostawca sprzedaży", - "select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.", - "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", - "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)", - "use_testnet": "Użyj testne", - "receivable_balance": "Saldo należności", - "confirmed_tx": "Potwierdzony", - "transaction_details_source_address": "Adres źródłowy", - "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana.", - "contractName": "Nazwa umowy", - "contractSymbol": "Symbol kontraktu", - "description": "Opis", - "camera_consent": "Twój aparat zostanie użyty do przechwycenia obrazu w celach identyfikacyjnych przez ${provider}. Aby uzyskać szczegółowe informacje, sprawdź ich Politykę prywatności.", - "no_relays": "Żadnych przekaźników", - "choose_relay": "Wybierz przekaźnik, którego chcesz użyć", - "no_relays_message": "Znaleźliśmy rekord Nostr NIP-05 dla tego użytkownika, ale nie zawiera on żadnych przekaźników. Poinstruuj odbiorcę, aby dodał przekaźniki do swojego rekordu Nostr.", - "no_relay_on_domain": "Brak przekaźnika dla domeny użytkownika lub przekaźnik jest niedostępny. Wybierz przekaźnik, którego chcesz użyć." - "zzzz": "Zzzz" + "you_will_send": "Konwertuj z" } \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 0e62399c6..d43a13fc0 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -714,6 +714,7 @@ "use_card_info_two": "Os fundos são convertidos para USD quando mantidos na conta pré-paga, não em moedas digitais.", "use_ssl": "Use SSL", "use_suggested": "Uso sugerido", + "use_testnet": "Use testNet", "variable_pair_not_supported": "Este par de variáveis não é compatível com as trocas selecionadas", "verification": "Verificação", "verify_with_2fa": "Verificar com Cake 2FA", @@ -773,281 +774,5 @@ "you_now_have_debit_card": "Agora você tem um cartão de débito", "you_pay": "Você paga", "you_will_get": "Converter para", - "you_will_send": "Converter de", - "yy": "aa", - "online": "Online", - "offline": "offline", - "gift_card_number": "Número do cartão-presente", - "pin_number": "Número PIN", - "total_saving": "Economia total", - "last_30_days": "Últimos 30 dias", - "avg_savings": "Poupança média", - "view_all": "Ver todos", - "active_cards": "Cartões ativos", - "delete_account": "Excluir conta", - "cards": "Cartões", - "active": "Ativo", - "redeemed": "Resgatado", - "gift_card_balance_note": "Os cartões-presente com saldo restante aparecerão aqui", - "gift_card_redeemed_note": "Os cartões-presente que você resgatou aparecerão aqui", - "logout": "Logout", - "add_tip": "Adicionar Dica", - "percentageOf": "de ${amount}", - "is_percentage": "é", - "search_category": "Categoria de pesquisa", - "mark_as_redemed": "Marcar como resgatado", - "more_options": "Mais opções", - "waiting_payment_confirmation": "Aguardando confirmação de pagamento", - "transaction_sent_notice": "Se a tela não prosseguir após 1 minuto, verifique um explorador de blocos e seu e-mail.", - "agree": "Concordo", - "in_store": "Na loja", - "generating_gift_card": "Gerando Cartão Presente", - "payment_was_received": "Seu pagamento foi recebido.", - "proceed_after_one_minute": "Se a tela não prosseguir após 1 minuto, verifique seu e-mail.", - "order_id": "ID do pedido", - "gift_card_is_generated": "Cartão presente é gerado", - "open_gift_card": "Abrir vale-presente", - "contact_support": "Contatar Suporte", - "gift_cards_unavailable": "Os cartões-presente estão disponíveis para compra apenas através do Monero, Bitcoin e Litecoin no momento", - "background_sync_mode": "Modo de sincronização em segundo plano", - "sync_all_wallets": "Sincronize todas as carteiras", - "introducing_cake_pay": "Apresentando o Cake Pay!", - "cake_pay_learn_more": "Compre e resgate vales-presente instantaneamente no app!\nDeslize da esquerda para a direita para saber mais.", - "automatic": "Automático", - "fixed_pair_not_supported": "Este par fixo não é compatível com as exchanges selecionadas", - "variable_pair_not_supported": "Este par de variáveis não é compatível com as trocas selecionadas", - "none_of_selected_providers_can_exchange": "Nenhum dos provedores selecionados pode fazer esta troca", - "choose_one": "Escolha um", - "choose_from_available_options": "Escolha entre as opções disponíveis:", - "custom_redeem_amount": "Valor de resgate personalizado", - "add_custom_redemption": "Adicionar resgate personalizado", - "remaining": "restante", - "delete_wallet": "Excluir carteira", - "delete_wallet_confirm_message": "Tem certeza de que deseja excluir a carteira ${wallet_name}?", - "low_fee": "Taxa baixa", - "low_fee_alert": "No momento, você está usando uma prioridade de taxa de rede baixa. Isso pode causar longas esperas, taxas diferentes ou negociações canceladas. Recomendamos definir uma taxa mais alta para uma melhor experiência.", - "ignor": "Ignorar", - "use_suggested": "Uso sugerido", - "do_not_share_warning_text": "Não os compartilhe com mais ninguém, incluindo suporte.\n\nSeus fundos podem e serão roubados!", - "help": "ajuda", - "all_transactions": "Todas as transacções", - "all_trades": "Todas as negociações", - "connection_sync": "Conexão e sincronização", - "security_and_backup": "Segurança e backup", - "create_backup": "Criar backup", - "privacy_settings": "Configurações de privacidade", - "privacy": "Privacidade", - "display_settings": "Configurações de exibição", - "other_settings": "Outras configurações", - "require_pin_after": "Exigir PIN após", - "always": "sempre", - "minutes_to_pin_code": "${minute} minutos", - "disable_exchange": "Desativar troca", - "advanced_settings": "Configurações avançadas", - "settings_can_be_changed_later": "Essas configurações podem ser alteradas posteriormente nas configurações do aplicativo", - "add_custom_node": "Adicionar novo nó personalizado", - "disable_fiat": "Desativar fiat", - "fiat_api": "API da Fiat", - "disabled": "Desabilitado", - "enabled": "Habilitado", - "tor_only": "Tor apenas", - "unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado", - "orbot_running_alert": "Certifique-se de que o Orbot esteja em execução antes de se conectar a este nó.", - "contact_list_contacts": "Contatos", - "contact_list_wallets": "minhas carteiras", - "bitcoin_payments_require_1_confirmation": "Os pagamentos em Bitcoin exigem 1 confirmação, o que pode levar 20 minutos ou mais. Obrigado pela sua paciência! Você receberá um e-mail quando o pagamento for confirmado.", - "send_to_this_address": "Envie ${currency} ${tag}para este endereço", - "arrive_in_this_address": "${currency} ${tag}chegará neste endereço", - "do_not_send": "não envie", - "error_dialog_content": "Ops, houve algum erro.\n\nPor favor, envie o relatório de falha para nossa equipe de suporte para melhorar o aplicativo.", - "scan_qr_code": "Escanear código QR", - "cold_or_recover_wallet": "Adicione uma cold wallet ou recupere uma paper wallet", - "please_wait": "Por favor, aguarde", - "sweeping_wallet": "Carteira varrendo", - "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", - "decimal_places_error": "Muitas casas decimais", - "edit_node": "Editar nó", - "invoice_details": "Detalhes da fatura", - "donation_link_details": "Detalhes do link de doação", - "anonpay_description": "Gere ${type}. O destinatário pode ${method} com qualquer criptomoeda suportada e você receberá fundos nesta carteira.", - "create_invoice": "Criar recibo", - "create_donation_link": "Criar link de doação", - "optional_email_hint": "E-mail opcional de notificação do beneficiário", - "optional_description": "Descrição opcional", - "optional_name": "Nome do destinatário opcional", - "clearnet_link": "link clear net", - "onion_link": "ligação de cebola", - "settings": "Configurações", - "sell_monero_com_alert_content": "A venda de Monero ainda não é suportada", - "error_text_input_below_minimum_limit": "O valor é menor que o mínimo", - "error_text_input_above_maximum_limit": "O valor é superior ao máximo", - "show_market_place": "Mostrar mercado", - "prevent_screenshots": "Evite capturas de tela e gravação de tela", - "profile": "Perfil", - "close": "Fechar", - "modify_2fa": "Modificar o Cake 2FA", - "disable_cake_2fa": "Desabilitar o Cake 2FA", - "question_to_disable_2fa": "Tem certeza de que deseja desativar o Cake 2FA? Um código 2FA não será mais necessário para acessar a carteira e certas funções.", - "disable": "Desativar", - "setup_2fa": "Configurar o Cake 2FA", - "verify_with_2fa": "Verificar com Cake 2FA", - "totp_code": "Código TOTP", - "please_fill_totp": "Por favor, preencha o código de 8 dígitos presente em seu outro dispositivo", - "totp_2fa_success": "Sucesso! Cake 2FA ativado para esta carteira. Lembre-se de salvar sua semente mnemônica caso perca o acesso à carteira.", - "totp_verification_success": "Verificação bem-sucedida!", - "totp_2fa_failure": "Código incorreto. Tente um código diferente ou gere uma nova chave secreta. Use um aplicativo 2FA compatível com códigos de 8 dígitos e SHA512.", - "enter_totp_code": "Digite o código TOTP.", - "add_secret_code": "Ou adicione este código secreto a um aplicativo autenticador", - "totp_secret_code": "Código Secreto TOTP", - "setup_2fa_text": "Cake 2FA funciona usando TOTP como segundo fator de autenticação.\n\nO TOTP do Cake 2FA requer suporte SHA-512 e 8 dígitos; isso proporciona maior segurança. Mais informações e aplicativos suportados podem ser encontrados no guia.", - "setup_totp_recommended": "Configurar TOTP", - "disable_buy": "Desativar ação de compra", - "disable_sell": "Desativar ação de venda", - "auto_generate_subaddresses": "Gerar subendereços automaticamente", - "cake_2fa_preset": "Predefinição de bolo 2FA", - "narrow": "Estreito", - "normal": "Normal", - "aggressive": "excessivamente zeloso", - "require_for_assessing_wallet": "Requer para acessar a carteira", - "require_for_sends_to_non_contacts": "Exigir para envios para não-contatos", - "require_for_sends_to_contacts": "Exigir para envios para contatos", - "require_for_sends_to_internal_wallets": "Exigir envios para carteiras internas", - "require_for_exchanges_to_internal_wallets": "Requer trocas para carteiras internas", - "require_for_adding_contacts": "Requer para adicionar contatos", - "require_for_creating_new_wallets": "Requer para criar novas carteiras", - "require_for_all_security_and_backup_settings": "Exigir todas as configurações de segurança e backup", - "available_balance_description": "Seu saldo disponível é o saldo total menos o saldo congelado. O saldo congelado é o saldo que você não pode gastar, mas que ainda não foi confirmado na blockchain. O saldo congelado é geralmente o resultado de transações recentes.", - "syncing_wallet_alert_title": "Sua carteira está sincronizando", - "syncing_wallet_alert_content": "Seu saldo e lista de transações podem não estar completos até que diga “SYNCHRONIZED” no topo. Clique/toque para saber mais.", - "home_screen_settings": "Configurações da tela inicial", - "sort_by": "Ordenar por", - "search_add_token": "Pesquisar / Adicionar token", - "edit_token": "Editar símbolo", - "warning": "Aviso", - "add_token_warning": "Não edite ou adicione tokens de acordo com as instruções dos golpistas.\nSempre confirme os endereços de token com fontes confiáveis!", - "add_token_disclaimer_check": "Confirmei o endereço e as informações do contrato de token usando uma fonte confiável. Adicionar informações maliciosas ou incorretas pode resultar em perda de fundos.", - "token_contract_address": "Endereço do contrato de token", - "token_name": "Nome do token, por exemplo: Tether", - "token_symbol": "Símbolo de token, por exemplo: USDT", - "token_decimal": "Token decimal", - "field_required": "Este campo é obrigatório", - "pin_at_top": "fixe ${token} no topo", - "invalid_input": "Entrada inválida", - "fiat_balance": "Equilíbrio Fiat", - "gross_balance": "Saldo Bruto", - "alphabetical": "alfabética", - "generate_name": "Gerar nome", - "balance_page": "Página de saldo", - "share": "Compartilhar", - "slidable": "Deslizável", - "monero_dark_theme": "Monero Tema Escuro", - "bitcoin_dark_theme": "Tema escuro Bitcoin", - "bitcoin_light_theme": "Tema claro de bitcoin", - "high_contrast_theme": "Tema de alto contraste", - "matrix_green_dark_theme": "Tema escuro verde matrix", - "monero_light_theme": "Monero Light Theme", - "manage_nodes": "Gerenciar nós", - "etherscan_history": "história Etherscan", - "template_name": "Nome do modelo", - "change_rep": "Alterar representante", - "change_rep_message": "Tem certeza de que deseja alterar os representantes?", - "unsupported_asset": "Não oferecemos suporte a esta ação para este recurso. Crie ou mude para uma carteira de um tipo de ativo compatível.", - "manage_pow_nodes": "Gerenciar nós PoW", - "support_title_live_chat": "Apoio ao vivo", - "support_description_live_chat": "Livre e rápido! Representantes de suporte treinado estão disponíveis para ajudar", - "support_title_guides": "Guias da carteira de bolo", - "support_description_guides": "Documentação e suporte para problemas comuns", - "support_title_other_links": "Outros links de suporte", - "support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos", - "choose_derivation": "Escolha a derivação da carteira", - "new_first_wallet_text": "Mantenha sua criptomoeda facilmente segura", - "select_destination": "Selecione o destino para o arquivo de backup.", - "save_to_downloads": "Salvar em Downloads", - "select_buy_provider_notice": "Selecione um provedor de compra acima. Você pode pular esta tela definindo seu provedor de compra padrão nas configurações de aplicativos.", - "onramper_option_description": "Compre rapidamente criptografia com muitos métodos de pagamento. Disponível na maioria dos países. Os spreads e taxas variam.", - "default_buy_provider": "Provedor de compra padrão", - "ask_each_time": "Pergunte cada vez", - "buy_provider_unavailable": "Provedor atualmente indisponível.", - "signTransaction": "Assinar transação", - "errorGettingCredentials": "Falha: Erro ao obter credenciais", - "errorSigningTransaction": "Ocorreu um erro ao assinar a transação", - "pairingInvalidEvent": "Emparelhamento de evento inválido", - "chains": "Correntes", - "methods": "Métodos", - "events": "Eventos", - "reject": "Rejeitar", - "approve": "Aprovar", - "expiresOn": "Expira em", - "walletConnect": "CarteiraConectada", - "nullURIError": "URI é nulo", - "connectWalletPrompt": "Conecte sua carteira ao WalletConnect para fazer transações", - "newConnection": "Nova conexão", - "activeConnectionsPrompt": "Conexões ativas aparecerão aqui", - "deleteConnectionConfirmationPrompt": "Tem certeza de que deseja excluir a conexão com", - "event": "Evento", - "successful": "Bem-sucedido", - "wouoldLikeToConnect": "gostaria de me conectar", - "message": "Mensagem", - "do_not_have_enough_gas_asset": "Você não tem ${currency} suficiente para fazer uma transação com as condições atuais da rede blockchain. Você precisa de mais ${currency} para pagar as taxas da rede blockchain, mesmo se estiver enviando um ativo diferente.", - "totp_auth_url": "URL de autenticação TOTP", - "awaitDAppProcessing": "Aguarde até que o dApp termine o processamento.", - "copyWalletConnectLink": "Copie o link WalletConnect do dApp e cole aqui", - "enterWalletConnectURI": "Insira o URI do WalletConnect", - "seed_key": "Chave de semente", - "enter_seed_phrase": "Digite sua frase de semente", - "change_rep_successful": "Mudou com sucesso o representante", - "add_contact": "Adicionar contato", - "exchange_provider_unsupported": "${providerName} não é mais suportado!", - "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", - "order_by": "Ordenar por", - "creation_date": "Data de criação", - "group_by_type": "Grupo por tipo", - "importNFTs": "Importar NFTs", - "noNFTYet": "Ainda não há NFT", - "address": "Endereço", - "enterTokenID": "Insira o ID do token", - "tokenID": "EU IA", - "name": "Nome", - "symbol": "Símbolo", - "seed_phrase_length": "Comprimento da frase-semente", - "unavailable_balance": "Saldo indisponível", - "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", - "unspent_change": "Mudar", - "tor_connection": "Conexão Tor", - "setup_warning_2fa_text": "Você precisará restaurar sua carteira a partir da semente mnemônica.\n\nO suporte do Cake não poderá ajudá-lo se você perder o acesso ao seu 2FA ou sementes mnemônicas.\nCake 2FA é uma segunda autenticação para determinadas ações na carteira. Antes de usar o Cake 2FA, recomendamos a leitura do guia.NÃO é tão seguro quanto o armazenamento refrigerado.\n\nSe você perder o acesso ao seu aplicativo 2FA ou às chaves TOTP, você perderá o acesso a esta carteira. ", - "scan_qr_on_device": "Digitalize este código QR em outro dispositivo", - "how_to_use": "Como usar", - "seed_hex_form": "Semente de carteira (forma hexadecimal)", - "seedtype": "SeedType", - "seedtype_legacy": "Legado (25 palavras)", - "seedtype_polyseed": "Polyseed (16 palavras)", - "seed_language_czech": "Tcheco", - "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Chinês tradicional)", - "ascending": "Ascendente", - "descending": "descendente", - "dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa", - "polygonscan_history": "História do PolygonScan", - "wallet_seed_legacy": "Semente de carteira herdada", - "default_sell_provider": "Provedor de venda padrão", - "select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.", - "custom_drag": "Personalizado (segure e arraste)", - "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", - "use_testnet": "Use testNet", - "receivable_balance": "Saldo a receber", - "confirmed_tx": "Confirmado", - "transaction_details_source_address": "Endereço de Origem", - "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada.", - "contractName": "Nome do contrato", - "contractSymbol": "Símbolo do Contrato", - "description": "Descrição", - "camera_consent": "Sua câmera será usada para capturar uma imagem para fins de identificação por ${provider}. Por favor, verifique a Política de Privacidade para obter detalhes.", - "no_relays": "Sem relés", - "choose_relay": "Escolha um relé para usar", - "no_relays_message": "Encontramos um registro Nostr NIP-05 para este usuário, mas ele não contém nenhum relé. Instrua o destinatário a adicionar retransmissões ao seu registro Nostr.", - "no_relay_on_domain": "Não há uma retransmissão para o domínio do usuário ou a retransmissão está indisponível. Escolha um relé para usar." - "zzzz": "ZZZZ" + "you_will_send": "Converter de" } \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 6d20cac2c..7271ccb2a 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -716,6 +716,7 @@ "use_card_info_two": "Средства конвертируются в доллары США, когда они хранятся на предоплаченном счете, а не в цифровых валютах.", "use_ssl": "Использовать SSL", "use_suggested": "Использовать предложенный", + "use_testnet": "Используйте Testnet", "variable_pair_not_supported": "Эта пара переменных не поддерживается выбранными биржами.", "verification": "Проверка", "verify_with_2fa": "Подтвердить с помощью Cake 2FA", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "Теперь у вас есть дебетовая карта", "you_pay": "Вы платите", "you_will_get": "Конвертировать в", - "you_will_send": "Конвертировать из", - "yy": "ГГ", - "online": "Онлайн", - "offline": "Не в сети", - "gift_card_number": "Номер подарочной карты", - "pin_number": "ПИН-код", - "total_saving": "Общая экономия", - "last_30_days": "Последние 30 дней", - "avg_savings": "Средняя экономия", - "view_all": "Просмотреть все", - "active_cards": "Активные карты", - "delete_account": "Удалить аккаунт", - "cards": "Карты", - "active": "Активный", - "redeemed": "искуплен", - "gift_card_balance_note": "Здесь будут отображаться подарочные карты с остатком на балансе", - "gift_card_redeemed_note": "Здесь будут отображаться использованные вами подарочные карты", - "logout": "Выйти", - "add_tip": "Добавить подсказку", - "percentageOf": "из ${amount}", - "is_percentage": "есть", - "search_category": "Категория поиска", - "mark_as_redeemed": "Отметить как погашенный", - "more_options": "Дополнительные параметры", - "awaiting_payment_confirmation": "Ожидается подтверждения платежа", - "transaction_sent_notice": "Если экран не отображается через 1 минуту, проверьте обозреватель блоков и свою электронную почту.", - "agree": "согласен", - "in_store": "В магазине", - "generating_gift_card": "Создание подарочной карты", - "payment_was_received": "Ваш платеж получен.", - "proceed_after_one_minute": "Если через 1 минуту экран не отображается, проверьте свою электронную почту.", - "order_id": "Идентификатор заказа", - "gift_card_is_generated": "Подарочная карта сгенерирована", - "open_gift_card": "Открыть подарочную карту", - "contact_support": "Связаться со службой поддержки", - "gift_cards_unavailable": "В настоящее время подарочные карты можно приобрести только через Monero, Bitcoin и Litecoin.", - "background_sync_mode": "Режим фоновой синхронизации", - "sync_all_wallets": "Синхронизировать все кошельки", - "introducing_cake_pay": "Представляем Cake Pay!", - "cake_pay_learn_more": "Мгновенно покупайте и используйте подарочные карты в приложении!\nПроведите по экрану слева направо, чтобы узнать больше.", - "automatic": "автоматический", - "fixed_pair_not_supported": "Эта фиксированная пара не поддерживается выбранными биржами.", - "variable_pair_not_supported": "Эта пара переменных не поддерживается выбранными биржами.", - "none_of_selected_providers_can_exchange": "Ни один из выбранных провайдеров не может совершить этот обмен", - "choose_one": "Выбери один", - "choose_from_available_options": "Выберите из доступных вариантов:", - "custom_redeem_amount": "Пользовательская сумма погашения", - "add_custom_redemption": "Добавить пользовательское погашение", - "remaining": "осталось", - "delete_wallet": "Удалить кошелек", - "delete_wallet_confirm_message": "Вы уверены, что хотите удалить кошелек ${wallet_name}?", - "low_fee": "Низкая комиссия", - "low_fee_alert": "В настоящее время вы используете низкий приоритет платы за сеть. Это может привести к длительному ожиданию, изменению ставок или отмене сделок. Мы рекомендуем установить более высокую плату для лучшего опыта.", - "ignor": "Игнорировать", - "use_suggested": "Использовать предложенный", - "do_not_share_warning_text": "Не сообщайте их никому, включая техподдержку.\n\nВаши средства могут и будут украдены!", - "help": "помощь", - "all_transactions": "Все транзакции", - "all_trades": "Все сделки", - "connection_sync": "Подключение и синхронизация", - "security_and_backup": "Безопасность и резервное копирование", - "create_backup": "Создать резервную копию", - "privacy_settings": "Настройки конфиденциальности", - "privacy": "Конфиденциальность", - "display_settings": "Настройки отображения", - "other_settings": "Другие настройки", - "require_pin_after": "Требовать ПИН после", - "always": "всегда", - "minutes_to_pin_code": "${minute} минут", - "disable_exchange": "Отключить обмен", - "advanced_settings": "Расширенные настройки", - "settings_can_be_changed_later": "Эти настройки можно изменить позже в настройках приложения.", - "add_custom_node": "Добавить новый пользовательский узел", - "disable_fiat": "Отключить фиат", - "fiat_api": "Фиат API", - "disabled": "Отключено", - "enabled": "Включено", - "tor_only": "Только Tor", - "unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода.", - "orbot_running_alert": "Перед подключением к этому узлу убедитесь, что Orbot запущен.", - "contact_list_contacts": "Контакты", - "contact_list_wallets": "Мои кошельки", - "bitcoin_payments_require_1_confirmation": "Биткойн-платежи требуют 1 подтверждения, что может занять 20 минут или дольше. Спасибо тебе за твое терпение! Вы получите электронное письмо, когда платеж будет подтвержден.", - "send_to_this_address": "Отправить ${currency} ${tag}на этот адрес", - "arrive_in_this_address": "${currency} ${tag}придет на этот адрес", - "do_not_send": "Не отправлять", - "error_dialog_content": "Ой, у нас какая-то ошибка.\n\nПожалуйста, отправьте отчет о сбое в нашу службу поддержки, чтобы сделать приложение лучше.", - "scan_qr_code": "Сканировать QR-код", - "cold_or_recover_wallet": "Добавьте холодный кошелек или восстановите бумажный кошелек", - "please_wait": "Пожалуйста, подождите", - "sweeping_wallet": "Подметание кошелька", - "sweeping_wallet_alert": "Это не должно занять много времени. НЕ ПОКИДАЙТЕ ЭТОТ ЭКРАН, ИНАЧЕ ВЫЧИСЛЕННЫЕ СРЕДСТВА МОГУТ БЫТЬ ПОТЕРЯНЫ", - "decimal_places_error": "Слишком много десятичных знаков", - "edit_node": "Редактировать узел", - "invoice_details": "Детали счета", - "donation_link_details": "Информация о ссылке для пожертвований", - "anonpay_description": "Создайте ${type}. Получатель может использовать ${method} с любой поддерживаемой криптовалютой, и вы получите средства на этот кошелек.", - "create_invoice": "Создать счет", - "create_donation_link": "Создать ссылку для пожертвований", - "optional_email_hint": "Необязательное электронное письмо с уведомлением получателя платежа", - "optional_description": "Дополнительное описание", - "optional_name": "Необязательное имя получателя", - "clearnet_link": "Клирнет ссылка", - "onion_link": "Луковая ссылка", - "settings": "Настройки", - "sell_monero_com_alert_content": "Продажа Monero пока не поддерживается", - "error_text_input_below_minimum_limit": "Сумма меньше минимальной", - "error_text_input_above_maximum_limit": "Сумма больше максимальной", - "show_market_place": "Показать торговую площадку", - "prevent_screenshots": "Предотвратить скриншоты и запись экрана", - "profile": "Профиль", - "close": "Закрывать", - "modify_2fa": "Изменить торт 2FA", - "disable_cake_2fa": "Отключить торт 2FA", - "question_to_disable_2fa": "Вы уверены, что хотите отключить Cake 2FA? Код 2FA больше не потребуется для доступа к кошельку и некоторым функциям.", - "disable": "Запрещать", - "setup_2fa": "Настройка торта 2FA", - "verify_with_2fa": "Подтвердить с помощью Cake 2FA", - "totp_code": "TOTP-код", - "please_fill_totp": "Пожалуйста, введите 8-значный код на другом устройстве", - "totp_2fa_success": "Успех! Для этого кошелька включена двухфакторная аутентификация Cake. Не забудьте сохранить мнемоническое семя на случай, если вы потеряете доступ к кошельку.", - "totp_verification_success": "Проверка прошла успешно!", - "totp_2fa_failure": "Неверный код. Пожалуйста, попробуйте другой код или создайте новый секретный ключ. Используйте совместимое приложение 2FA, которое поддерживает 8-значные коды и SHA512.", - "enter_totp_code": "Пожалуйста, введите TOTP-код.", - "add_secret_code": "Или добавьте этот секретный код в приложение для аутентификации.", - "totp_secret_code": "Секретный код ТОТП", - "setup_2fa_text": "Cake 2FA работает с использованием TOTP в качестве второго фактора аутентификации.\n\nTOTP Cake 2FA требует SHA-512 и поддержки 8 цифр; это обеспечивает повышенную безопасность. Дополнительную информацию и поддерживаемые приложения можно найти в руководстве.", - "setup_totp_recommended": "Настройка ТОТП", - "disable_buy": "Отключить действие покупки", - "disable_sell": "Отключить действие продажи", - "cake_2fa_preset": "Торт 2FA Preset", - "narrow": "Узкий", - "normal": "Нормальный", - "aggressive": "чрезмерно усердный", - "require_for_assessing_wallet": "Требовать для доступа к кошельку", - "require_for_sends_to_non_contacts": "Требовать для отправки не контактам", - "require_for_sends_to_contacts": "Требовать для отправки контактам", - "require_for_sends_to_internal_wallets": "Требовать отправки на внутренние кошельки", - "require_for_exchanges_to_internal_wallets": "Требовать для обмена на внутренние кошельки", - "require_for_adding_contacts": "Требовать добавления контактов", - "require_for_creating_new_wallets": "Требовать для создания новых кошельков", - "require_for_all_security_and_backup_settings": "Требовать все настройки безопасности и резервного копирования", - "available_balance_description": "Доступный баланс - это средства, которые вы можете использовать для покупки или продажи криптовалюты.", - "syncing_wallet_alert_title": "Ваш кошелек синхронизируется", - "syncing_wallet_alert_content": "Ваш баланс и список транзакций могут быть неполными, пока вверху не будет написано «СИНХРОНИЗИРОВАНО». Щелкните/коснитесь, чтобы узнать больше.", - "home_screen_settings": "Настройки главного экрана", - "sort_by": "Сортировать по", - "search_add_token": "Поиск / Добавить токен", - "edit_token": "Изменить токен", - "warning": "Предупреждение", - "add_token_warning": "Не редактируйте и не добавляйте токены по указанию мошенников.\nВсегда подтверждайте адреса токенов из авторитетных источников!", - "add_token_disclaimer_check": "Я подтвердил адрес контракта токена и информацию, используя авторитетный источник. Добавление вредоносной или неверной информации может привести к потере средств.", - "token_contract_address": "Адрес контракта токена", - "token_name": "Имя токена, например: Tether", - "token_symbol": "Символ токена, например: USDT", - "token_decimal": "Десятичный токен", - "field_required": "Это поле обязательно к заполнению", - "pin_at_top": "закрепить ${token} вверху", - "invalid_input": "Неверный Ввод", - "fiat_balance": "Фиатный баланс", - "gross_balance": "Валовой баланс", - "alphabetical": "Алфавитный", - "generate_name": "Создать имя", - "balance_page": "Страница баланса", - "share": "Делиться", - "slidable": "Скользящий", - "monero_dark_theme": "Темная тема Monero", - "bitcoin_dark_theme": "Биткойн Темная тема", - "bitcoin_light_theme": "Легкая биткойн-тема", - "high_contrast_theme": "Высококонтрастная тема", - "matrix_green_dark_theme": "Матрица Зеленая Темная Тема", - "monero_light_theme": "Светлая тема Monero", - "manage_nodes": "Управление узлами", - "etherscan_history": "История Эфириума", - "template_name": "Имя Шаблона", - "change_rep": "Изменить представителя", - "change_rep_message": "Вы уверены, что хотите сменить представителя?", - "unsupported_asset": "Мы не поддерживаем это действие для этого объекта. Пожалуйста, создайте или переключитесь на кошелек поддерживаемого типа активов.", - "manage_pow_nodes": "Управление узлами PoW", - "support_title_live_chat": "Живая поддержка", - "support_description_live_chat": "Бесплатно и быстро! Обученные представители поддержки доступны для оказания помощи", - "support_title_guides": "Корт -гиды", - "support_description_guides": "Документация и поддержка общих вопросов", - "support_title_other_links": "Другие ссылки на поддержку", - "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов", - "choose_derivation": "Выберите вывод кошелька", - "new_first_wallet_text": "Легко сохранить свою криптовалюту в безопасности", - "select_destination": "Пожалуйста, выберите место для файла резервной копии.", - "auto_generate_subaddresses": "Авто генерируйте Subaddresses", - "save_to_downloads": "Сохранить в загрузках", - "select_buy_provider_notice": "Выберите поставщика покупки выше. Вы можете пропустить этот экран, установив поставщика покупки по умолчанию в настройках приложения.", - "onramper_option_description": "Быстро купите крипто со многими способами оплаты. Доступно в большинстве стран. Спреды и сборы различаются.", - "default_buy_provider": "По умолчанию поставщик покупки", - "ask_each_time": "Спросите каждый раз", - "buy_provider_unavailable": "Поставщик в настоящее время недоступен.", - "signTransaction": "Подписать транзакцию", - "errorGettingCredentials": "Не удалось: ошибка при получении учетных данных.", - "errorSigningTransaction": "Произошла ошибка при подписании транзакции", - "pairingInvalidEvent": "Недействительное событие сопряжения", - "chains": "Цепи", - "methods": "Методы", - "events": "События", - "reject": "Отклонять", - "approve": "Утвердить", - "expiresOn": "Годен до", - "walletConnect": "КошелекПодключиться", - "nullURIError": "URI имеет значение null", - "connectWalletPrompt": "Подключите свой кошелек к WalletConnect для совершения транзакций.", - "newConnection": "Новое соединение", - "activeConnectionsPrompt": "Здесь появятся активные подключения", - "deleteConnectionConfirmationPrompt": "Вы уверены, что хотите удалить подключение к", - "event": "Событие", - "successful": "Успешный", - "wouoldLikeToConnect": "хотел бы подключиться", - "message": "Сообщение", - "do_not_have_enough_gas_asset": "У вас недостаточно ${currency} для совершения транзакции при текущих условиях сети блокчейн. Вам нужно больше ${currency} для оплаты комиссий за сеть блокчейна, даже если вы отправляете другой актив.", - "totp_auth_url": "URL-адрес TOTP-АВТОРИЗАЦИИ", - "awaitDAppProcessing": "Пожалуйста, подождите, пока dApp завершит обработку.", - "copyWalletConnectLink": "Скопируйте ссылку WalletConnect из dApp и вставьте сюда.", - "enterWalletConnectURI": "Введите URI WalletConnect", - "seed_key": "Ключ семян", - "enter_seed_phrase": "Введите свою семенную фразу", - "change_rep_successful": "Успешно изменил представитель", - "add_contact": "Добавить контакт", - "exchange_provider_unsupported": "${providerName} больше не поддерживается!", - "domain_looks_up": "Поиск доменов", - "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", - "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", - "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", - "order_by": "Сортировать по", - "creation_date": "Дата создания", - "group_by_type": "Группа по типу", - "importNFTs": "Импортировать NFT", - "noNFTYet": "NFT пока нет", - "address": "Адрес", - "enterTokenID": "Введите идентификатор токена", - "tokenID": "ИДЕНТИФИКАТОР", - "name": "Имя", - "symbol": "Символ", - "seed_phrase_length": "Длина исходной фразы", - "unavailable_balance": "Недоступный баланс", - "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", - "unspent_change": "Изменять", - "tor_connection": "Тор соединение", - "setup_warning_2fa_text": "Cake 2FA — это вторая аутентификация для определенных действий в кошельке. Это НЕ так безопасно, как холодное хранение.\n\nЕсли вы потеряете доступ к своему приложению 2FA или ключам TOTP, вы потеряете доступ к этому кошельку. Вам нужно будет восстановить свой кошелек из мнемонического сида.\n\nСлужба поддержки Cake не сможет вам помочь, если вы потеряете доступ к своим 2FA или мнемоническим идентификаторам.\nПрежде чем использовать Cake 2FA, мы рекомендуем прочитать руководство.", - "scan_qr_on_device": "Отсканируйте этот QR-код на другом устройстве", - "how_to_use": "Как использовать", - "seed_hex_form": "Семя кошелька (шестнадцатеричная форма)", - "seedtype": "SEEDTYPE", - "seedtype_legacy": "Наследие (25 слов)", - "seedtype_polyseed": "Полиса (16 слов)", - "seed_language_czech": "Чешский", - "seed_language_korean": "Корейский", - "seed_language_chinese_traditional": "Китайский традиционный)", - "ascending": "Восходящий", - "descending": "Нисходящий", - "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе", - "polygonscan_history": "История PolygonScan", - "wallet_seed_legacy": "Наследие семя кошелька", - "default_sell_provider": "Поставщик продаж по умолчанию", - "select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.", - "custom_drag": "Пользователь (удерживайте и перетаскивайте)", - "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon).", - "use_testnet": "Используйте Testnet", - "receivable_balance": "Баланс дебиторской задолженности", - "confirmed_tx": "Подтвержденный", - "transaction_details_source_address": "Адрес источника", - "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена.", - "contractName": "Название контракта", - "contractSymbol": "Символ контракта", - "description": "Описание", - "camera_consent": "Ваша камера будет использоваться для захвата изображения в целях идентификации ${provider}. Пожалуйста, ознакомьтесь с их Политикой конфиденциальности для получения подробной информации.", - "no_relays": "Нет реле", - "choose_relay": "Пожалуйста, выберите реле для использования", - "no_relays_message": "Мы нашли запись Nostr NIP-05 для этого пользователя, но она не содержит никаких реле. Попросите получателя добавить реле в свою запись Nostr.", - "no_relay_on_domain": "Для домена пользователя реле не существует или реле недоступно. Пожалуйста, выберите реле для использования." - "zzzz": "zzzz" + "you_will_send": "Конвертировать из" } \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index e8d6ebba4..0b6373417 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -714,6 +714,7 @@ "use_card_info_two": "เงินจะถูกแปลงค่าเป็นดอลลาร์สหรัฐเมื่อถือไว้ในบัญชีสำรองเงิน ไม่ใช่สกุลเงินดิจิตอล", "use_ssl": "ใช้ SSL", "use_suggested": "ใช้ที่แนะนำ", + "use_testnet": "ใช้ testnet", "variable_pair_not_supported": "คู่ความสัมพันธ์ที่เปลี่ยนแปลงได้นี้ไม่สนับสนุนกับหุ้นที่เลือก", "verification": "การตรวจสอบ", "verify_with_2fa": "ตรวจสอบกับ Cake 2FA", @@ -772,279 +773,5 @@ "you_now_have_debit_card": "ขณะนี้คุณมีบัตรเดบิต", "you_pay": "คุณจ่าย", "you_will_get": "แปลงเป็น", - "you_will_send": "แปลงจาก", - "yy": "ปี", - "online": "ออนไลน์", - "offline": "ออฟไลน์", - "gift_card_number": "หมายเลขบัตรของขวัญ", - "pin_number": "หมายเลข PIN", - "total_saving": "ประหยัดรวม", - "last_30_days": "30 วันล่าสุด", - "avg_savings": "ประหยัดเฉลี่ย", - "view_all": "ดูทั้งหมด", - "active_cards": "บัตรที่ใช้งานได้", - "delete_account": "ลบบัญชี", - "cards": "บัตร", - "active": "ทำงาน", - "redeemed": "แลกของขวัญ", - "gift_card_balance_note": "บัตรของขวัญที่มียอดคงเหลือจะปรากฏที่นี่", - "gift_card_redeemed_note": "บัตรของขวัญที่คุณแลกไปแล้วจะปรากฏที่นี่", - "logout": "ออกจากระบบ", - "add_tip": "เพิ่มคำแนะนำ", - "percentageOf": "${amount} ของ", - "is_percentage": "เป็น", - "search_category": "ค้นหาหมวดหมู่", - "mark_as_redeemed": "ทำเครื่องหมายว่าเคยใช้แล้ว", - "more_options": "ตัวเลือกเพิ่มเติม", - "awaiting_payment_confirmation": "รอการยืนยันการชำระเงิน", - "transaction_sent_notice": "ถ้าหน้าจอไม่ขึ้นหลังจาก 1 นาทีแล้ว ให้ตรวจสอบ block explorer และอีเมลของคุณ", - "agree": "ยอมรับ", - "in_store": "ในร้าน", - "generating_gift_card": "กำลังสร้างบัตรของขวัญ", - "payment_was_received": "การชำระเงินของคุณได้รับการรับทราบแล้ว", - "proceed_after_one_minute": "หากหน้าจอไม่ดำเนินการหลังจาก 1 นาทีโปรดตรวจสอบอีเมลของคุณ", - "order_id": "เลขที่ออร์เดอร์", - "gift_card_is_generated": "บัตรของขวัญถูกสร้างขึ้น", - "open_gift_card": "เปิดบัตรของขวัญ", - "contact_support": "ติดต่อฝ่ายสนับสนุน", - "gift_cards_unavailable": "บัตรของขวัญจะมีจำหน่ายเฉพาะกับ Monero, Bitcoin, และ Litecoin เท่านั้นในขณะนี้", - "introducing_cake_pay": "ยินดีต้อนรับสู่ Cake Pay!", - "cake_pay_learn_more": "ซื้อและเบิกบัตรของขวัญในแอพพลิเคชันทันที!\nกระแทกขวาไปซ้ายเพื่อเรียนรู้เพิ่มเติม", - "automatic": "อัตโนมัติ", - "fixed_pair_not_supported": "คู่ความสัมพันธ์ที่ถูกกำหนดไว้นี้ไม่สนับสนุนกับหุ้นที่เลือก", - "variable_pair_not_supported": "คู่ความสัมพันธ์ที่เปลี่ยนแปลงได้นี้ไม่สนับสนุนกับหุ้นที่เลือก", - "none_of_selected_providers_can_exchange": "ไม่มีผู้ให้บริการที่เลือกที่สามารถแลกเปลี่ยนนี้ได้", - "choose_one": "เลือกหนึ่งรายการ", - "choose_from_available_options": "เลือกจากตัวเลือกที่มีอยู่:", - "custom_redeem_amount": "จำนวนรับคืนที่กำหนดเอง", - "add_custom_redemption": "เพิ่มการรับคืนที่กำหนดเอง", - "remaining": "เหลืออยู่", - "delete_wallet": "ลบกระเป๋า", - "delete_wallet_confirm_message": "คุณแน่ใจหรือว่าต้องการลบกระเป๋า${wallet_name}?", - "low_fee": "ค่าธรรมเนียมต่ำ", - "low_fee_alert": "ขณะนี้คุณกำลังใช้ค่าธรรมเนียมของเครือข่ายที่มีความสำคัญต่ำ ซึ่งอาจทำให้เกิดการรอนาน ราคาที่แตกต่างกัน หรือยกเลิกการซื้อขาย เราแนะนำให้กำหนดค่าธรรมเนียมที่สูงขึ้นเพื่อประสบการณ์ที่ดีขึ้น", - "ignor": "ละเว้น", - "use_suggested": "ใช้ที่แนะนำ", - "do_not_share_warning_text": "อย่าแชร์ข้อมูลนี้กับใครอื่น รวมถึงฝ่ายสนับสนุนด้วย\n\nการเงินของคุณอาจถูกขโมยโดยไม่หวังดี!", - "help": "ช่วยเหลือ", - "all_transactions": "การทำธุรกรรมทั้งหมด", - "all_trades": "การซื้อขายทั้งหมด", - "connection_sync": "การเชื่อมต่อและการซิงค์", - "security_and_backup": "ความปลอดภัยและการสำรองข้อมูล", - "create_backup": "สร้างการสำรองข้อมูล", - "privacy_settings": "การตั้งค่าความเป็นส่วนตัว", - "privacy": "ความเป็นส่วนตัว", - "display_settings": "การตั้งค่าการแสดงผล", - "other_settings": "การตั้งค่าอื่น ๆ", - "require_pin_after": "ต้องการ PIN หลังจาก", - "always": "เสมอ", - "minutes_to_pin_code": "${minute} นาที", - "disable_exchange": "ปิดใช้งานการแลกเปลี่ยน", - "advanced_settings": "ตั้งค่าขั้นสูง", - "settings_can_be_changed_later": "การตั้งค่านี้สามารถเปลี่ยนแปลงได้ภายหลังในการตั้งค่าแอพฯ", - "add_custom_node": "เพิ่มจุดโหนดแบบกำหนดเอง", - "disable_fiat": "ปิดใช้งานสกุลเงินตรา", - "fiat_api": "API สกุลเงินตรา", - "disabled": "ปิดใช้งาน", - "enabled": "เปิดใช้งาน", - "tor_only": "Tor เท่านั้น", - "unmatched_currencies": "สกุลเงินของกระเป๋าปัจจุบันของคุณไม่ตรงกับของ QR ที่สแกน", - "orbot_running_alert": "โปรดตรวจสอบว่า Orbot กำลังทำงานก่อนที่จะเชื่อมต่อกับโหนดนี้", - "contact_list_contacts": "ติดต่อ", - "contact_list_wallets": "กระเป๋าเงินของฉัน", - "bitcoin_payments_require_1_confirmation": "การชำระเงินด้วย Bitcoin ต้องการการยืนยัน 1 ครั้ง ซึ่งอาจใช้เวลา 20 นาทีหรือนานกว่านั้น ขอบคุณสำหรับความอดทนของคุณ! คุณจะได้รับอีเมลเมื่อการชำระเงินได้รับการยืนยัน", - "send_to_this_address": "ส่ง ${currency} ${tag}ไปยังที่อยู่นี้", - "arrive_in_this_address": "${currency} ${tag}จะมาถึงที่อยู่นี้", - "do_not_send": "อย่าส่ง", - "error_dialog_content": "อ๊ะ เราพบข้อผิดพลาดบางอย่าง\n\nโปรดส่งรายงานข้อขัดข้องไปยังทีมสนับสนุนของเราเพื่อปรับปรุงแอปพลิเคชันให้ดียิ่งขึ้น", - "scan_qr_code": "สแกนรหัส QR", - "cold_or_recover_wallet": "เพิ่มกระเป๋าเงินเย็นหรือกู้คืนกระเป๋าเงินกระดาษ", - "please_wait": "โปรดรอ", - "sweeping_wallet": "กวาดกระเป๋าสตางค์", - "sweeping_wallet_alert": "การดำเนินการนี้ใช้เวลาไม่นาน อย่าออกจากหน้าจอนี้ มิฉะนั้นเงินที่กวาดไปอาจสูญหาย", - "decimal_places_error": "ทศนิยมมากเกินไป", - "edit_node": "แก้ไขโหนด", - "invoice_details": "รายละเอียดใบแจ้งหนี้", - "donation_link_details": "รายละเอียดลิงค์บริจาค", - "anonpay_description": "สร้าง ${type} ผู้รับสามารถ ${method} ด้วยสกุลเงินดิจิทัลที่รองรับ และคุณจะได้รับเงินในกระเป๋าสตางค์นี้", - "create_invoice": "สร้างใบแจ้งหนี้", - "create_donation_link": "สร้างลิงค์บริจาค", - "optional_email_hint": "อีเมลแจ้งผู้รับเงินเพิ่มเติม", - "optional_description": "คำอธิบายเพิ่มเติม", - "optional_name": "ชื่อผู้รับเพิ่มเติม", - "clearnet_link": "ลิงค์เคลียร์เน็ต", - "onion_link": "ลิงค์หัวหอม", - "settings": "การตั้งค่า", - "sell_monero_com_alert_content": "ยังไม่รองรับการขาย Monero", - "error_text_input_below_minimum_limit": "จำนวนเงินน้อยกว่าขั้นต่ำ", - "error_text_input_above_maximum_limit": "จำนวนเงินสูงกว่าค่าสูงสุด", - "show_market_place": "แสดงตลาดกลาง", - "prevent_screenshots": "ป้องกันภาพหน้าจอและการบันทึกหน้าจอ", - "profile": "ประวัติโดยย่อ", - "close": "ปิด", - "modify_2fa": "แก้ไขเค้ก 2FA", - "disable_cake_2fa": "ปิดการใช้งานเค้ก 2FA", - "question_to_disable_2fa": "คุณแน่ใจหรือไม่ว่าต้องการปิดการใช้งาน Cake 2FA ไม่จำเป็นต้องใช้รหัส 2FA ในการเข้าถึงกระเป๋าเงินและฟังก์ชั่นบางอย่างอีกต่อไป", - "disable": "ปิดการใช้งาน", - "setup_2fa": "ตั้งค่าเค้ก 2FA", - "verify_with_2fa": "ตรวจสอบกับ Cake 2FA", - "totp_code": "รหัสทีโอพี", - "please_fill_totp": "กรุณากรอกรหัส 8 หลักที่อยู่ในอุปกรณ์อื่นของคุณ", - "totp_2fa_success": "ความสำเร็จ! Cake 2FA เปิดใช้งานสำหรับกระเป๋าเงินนี้ อย่าลืมบันทึกเมล็ดช่วยจำของคุณในกรณีที่คุณสูญเสียการเข้าถึงกระเป๋าเงิน", - "totp_verification_success": "การยืนยันสำเร็จ!", - "totp_2fa_failure": "รหัสไม่ถูกต้อง. โปรดลองใช้รหัสอื่นหรือสร้างรหัสลับใหม่ ใช้แอพ 2FA ที่เข้ากันได้ซึ่งรองรับรหัส 8 หลักและ SHA512", - "enter_totp_code": "กรุณาใส่รหัสทีโอที", - "add_secret_code": "หรือเพิ่มรหัสลับนี้ลงในแอปตรวจสอบความถูกต้อง", - "totp_secret_code": "รหัสลับ TOTP", - "setup_2fa_text": "Cake 2FA ทำงานโดยใช้ TOTP เป็นปัจจัยการตรวจสอบสิทธิ์ที่สอง\n\nTOTP ของ Cake 2FA ต้องการการสนับสนุน SHA-512 และ 8 หลัก สิ่งนี้ให้ความปลอดภัยเพิ่มขึ้น ข้อมูลเพิ่มเติมและแอปที่รองรับมีอยู่ในคำแนะนำ", - "setup_totp_recommended": "ตั้งค่า TOTP", - "disable_buy": "ปิดการใช้งานการซื้อ", - "disable_sell": "ปิดการใช้งานการขาย", - "cake_2fa_preset": "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", - "narrow": "แคบ", - "normal": "ปกติ", - "aggressive": "กระตือรือร้นมากเกินไป", - "require_for_assessing_wallet": "จำเป็นสำหรับการเข้าถึงกระเป๋าเงิน", - "require_for_sends_to_non_contacts": "จำเป็นต้องส่งไปยังผู้ที่ไม่ได้ติดต่อ", - "require_for_sends_to_contacts": "จำเป็นต้องส่งไปยังผู้ติดต่อ", - "require_for_sends_to_internal_wallets": "จำเป็นต้องส่งไปยังกระเป๋าเงินภายใน", - "require_for_exchanges_to_internal_wallets": "ต้องการการแลกเปลี่ยนไปยังกระเป๋าเงินภายใน", - "require_for_adding_contacts": "ต้องการสำหรับการเพิ่มผู้ติดต่อ", - "require_for_creating_new_wallets": "จำเป็นสำหรับการสร้างกระเป๋าเงินใหม่", - "require_for_all_security_and_backup_settings": "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", - "available_balance_description": "จำนวนเงินที่คุณสามารถใช้ได้ในการซื้อหรือขาย", - "syncing_wallet_alert_title": "กระเป๋าสตางค์ของคุณกำลังซิงค์", - "syncing_wallet_alert_content": "รายการยอดเงินและธุรกรรมของคุณอาจไม่สมบูรณ์จนกว่าจะมีข้อความว่า “ซิงโครไนซ์” ที่ด้านบน คลิก/แตะเพื่อเรียนรู้เพิ่มเติม่", - "home_screen_settings": "การตั้งค่าหน้าจอหลัก", - "sort_by": "เรียงตาม", - "search_add_token": "ค้นหา / เพิ่มโทเค็น", - "edit_token": "แก้ไขโทเค็น", - "warning": "คำเตือน", - "add_token_warning": "ห้ามแก้ไขหรือเพิ่มโทเค็นตามคำแนะนำของนักต้มตุ๋น\nยืนยันที่อยู่โทเค็นกับแหล่งที่มาที่เชื่อถือได้เสมอ!", - "add_token_disclaimer_check": "ฉันได้ยืนยันที่อยู่และข้อมูลของสัญญาโทเค็นโดยใช้แหล่งข้อมูลที่เชื่อถือได้ การเพิ่มข้อมูลที่เป็นอันตรายหรือไม่ถูกต้องอาจทำให้สูญเสียเงินได้", - "token_contract_address": "ที่อยู่สัญญาโทเค็น", - "token_name": "ชื่อโทเค็น เช่น Tether", - "token_symbol": "สัญลักษณ์โทเค็น เช่น USDT", - "token_decimal": "โทเค็นทศนิยม", - "field_required": "ช่องนี้จำเป็น", - "pin_at_top": "ปักหมุด ${token} ที่ด้านบน", - "invalid_input": "อินพุตไม่ถูกต้อง", - "fiat_balance": "เฟียต บาลานซ์", - "gross_balance": "ยอดคงเหลือ", - "alphabetical": "ตามตัวอักษร", - "generate_name": "สร้างชื่อ", - "balance_page": "หน้ายอดคงเหลือ", - "share": "แบ่งปัน", - "slidable": "เลื่อนได้", - "monero_dark_theme": "ธีมมืด Monero", - "bitcoin_dark_theme": "ธีมมืด Bitcoin", - "bitcoin_light_theme": "ธีมแสง Bitcoin", - "high_contrast_theme": "ธีมความคมชัดสูง", - "matrix_green_dark_theme": "ธีมเมทริกซ์สีเขียวเข้ม", - "monero_light_theme": "ธีมแสง Monero", - "manage_nodes": "จัดการโหนด", - "etherscan_history": "ประวัติอีเธอร์สแกน", - "template_name": "ชื่อแม่แบบ", - "change_rep": "เปลี่ยนผู้แทน", - "change_rep_message": "คุณแน่ใจหรือไม่ว่าต้องการเปลี่ยนตัวแทน", - "unsupported_asset": "เราไม่สนับสนุนการกระทำนี้สำหรับเนื้อหานี้ โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงินประเภทสินทรัพย์ที่รองรับ", - "manage_pow_nodes": "จัดการโหนด PoW", - "support_title_live_chat": "การสนับสนุนสด", - "support_description_live_chat": "ฟรีและรวดเร็ว! ตัวแทนฝ่ายสนับสนุนที่ผ่านการฝึกอบรมพร้อมให้ความช่วยเหลือ", - "support_title_guides": "คู่มือกระเป๋าเงินเค้ก", - "support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป", - "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", - "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ", - "choose_derivation": "เลือก Wallet Derivation", - "new_first_wallet_text": "ทำให้สกุลเงินดิจิตอลของคุณปลอดภัยได้อย่างง่ายดาย", - "select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรอง", - "auto_generate_subaddresses": "Auto สร้าง subaddresses", - "save_to_downloads": "บันทึกลงดาวน์โหลด", - "select_buy_provider_notice": "เลือกผู้ให้บริการซื้อด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการซื้อเริ่มต้นในการตั้งค่าแอป", - "onramper_option_description": "ซื้อ crypto อย่างรวดเร็วด้วยวิธีการชำระเงินจำนวนมาก มีให้บริการในประเทศส่วนใหญ่ สเปรดและค่าธรรมเนียมแตกต่างกันไป", - "default_buy_provider": "ผู้ให้บริการซื้อเริ่มต้น", - "ask_each_time": "ถามทุกครั้ง", - "buy_provider_unavailable": "ผู้ให้บริการไม่สามารถใช้งานได้ในปัจจุบัน", - "signTransaction": "ลงนามในการทำธุรกรรม", - "errorGettingCredentials": "ล้มเหลว: เกิดข้อผิดพลาดขณะรับข้อมูลรับรอง", - "errorSigningTransaction": "เกิดข้อผิดพลาดขณะลงนามธุรกรรม", - "pairingInvalidEvent": "การจับคู่เหตุการณ์ที่ไม่ถูกต้อง", - "chains": "ห่วงโซ่", - "methods": "วิธีการ", - "events": "กิจกรรม", - "reject": "ปฏิเสธ", - "approve": "อนุมัติ", - "expiresOn": "หมดอายุวันที่", - "walletConnect": "WalletConnect", - "nullURIError": "URI เป็นโมฆะ", - "connectWalletPrompt": "เชื่อมต่อกระเป๋าเงินของคุณด้วย WalletConnect เพื่อทำธุรกรรม", - "newConnection": "การเชื่อมต่อใหม่", - "activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะปรากฏที่นี่", - "deleteConnectionConfirmationPrompt": "คุณแน่ใจหรือไม่ว่าต้องการลบการเชื่อมต่อไปยัง", - "event": "เหตุการณ์", - "successful": "ประสบความสำเร็จ", - "wouoldLikeToConnect": "ต้องการเชื่อมต่อ", - "message": "ข้อความ", - "do_not_have_enough_gas_asset": "คุณมี ${currency} ไม่เพียงพอที่จะทำธุรกรรมกับเงื่อนไขเครือข่ายบล็อคเชนในปัจจุบัน คุณต้องมี ${currency} เพิ่มขึ้นเพื่อชำระค่าธรรมเนียมเครือข่ายบล็อคเชน แม้ว่าคุณจะส่งสินทรัพย์อื่นก็ตาม", - "totp_auth_url": "URL การตรวจสอบสิทธิ์ TOTP", - "awaitDAppProcessing": "โปรดรอให้ dApp ประมวลผลเสร็จสิ้น", - "copyWalletConnectLink": "คัดลอกลิงก์ WalletConnect จาก dApp แล้ววางที่นี่", - "enterWalletConnectURI": "เข้าสู่ WalletConnect URI", - "seed_key": "คีย์เมล็ดพันธุ์", - "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", - "change_rep_successful": "เปลี่ยนตัวแทนสำเร็จ", - "add_contact": "เพิ่มผู้ติดต่อ", - "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!", - "domain_looks_up": "การค้นหาโดเมน", - "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", - "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", - "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", - "order_by": "สั่งโดย", - "creation_date": "วันที่สร้าง", - "group_by_type": "กลุ่มตามประเภท", - "importNFTs": "นำเข้า NFT", - "noNFTYet": "ยังไม่มี NFT", - "address": "ที่อยู่", - "enterTokenID": "ป้อนรหัสโทเค็น", - "tokenID": "บัตรประจำตัวประชาชน", - "name": "ชื่อ", - "symbol": "เครื่องหมาย", - "seed_phrase_length": "ความยาววลีของเมล็ด", - "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", - "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", - "unspent_change": "เปลี่ยน", - "tor_connection": "การเชื่อมต่อทอร์", - "setup_warning_2fa_text": "Cake 2FA เป็นการรับรองความถูกต้องครั้งที่สองสำหรับการกระทำบางอย่างในกระเป๋าเงิน มันไม่ปลอดภัยเท่ากับห้องเย็น\n\nหากคุณสูญเสียการเข้าถึงแอป 2FA หรือคีย์ TOTP คุณจะสูญเสียการเข้าถึงกระเป๋าเงินนี้ คุณจะต้องกู้คืนกระเป๋าเงินของคุณจากเมล็ดช่วยในการจำ\n\nการสนับสนุนเค้กจะไม่สามารถช่วยเหลือคุณได้หากคุณสูญเสียการเข้าถึง 2FA หรือเมล็ดช่วยในการจำ\nก่อนใช้ Cake 2FA เราขอแนะนำให้อ่านคำแนะนำโดยละเอียด", - "scan_qr_on_device": "สแกนโค้ด QR นี้บนอุปกรณ์อื่น", - "how_to_use": "วิธีใช้", - "seed_hex_form": "เมล็ดกระเป๋าเงิน (รูปแบบฐานสิบหก)", - "seedtype": "เมล็ดพันธุ์", - "seedtype_legacy": "มรดก (25 คำ)", - "seedtype_polyseed": "โพลีส (16 คำ)", - "seed_language_czech": "ภาษาเช็ก", - "seed_language_korean": "เกาหลี", - "seed_language_chinese_traditional": "จีน (ดั้งเดิม)", - "ascending": "จากน้อยไปมาก", - "descending": "ลงมา", - "dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", - "polygonscan_history": "ประวัติ PolygonScan", - "wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก", - "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", - "select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป", - "custom_drag": "กำหนดเอง (ค้างและลาก)", - "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", - "use_testnet": "ใช้ testnet", - "receivable_balance": "ยอดลูกหนี้", - "confirmed_tx": "ซึ่งยืนยันแล้ว", - "transaction_details_source_address": "ที่อยู่แหล่งกำเนิด", - "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว", - "contractName": "ชื่อสัญญา", - "contractSymbol": "สัญลักษณ์สัญญา", - "description": "คำอธิบาย", - "camera_consent": "กล้องของคุณจะถูกนำมาใช้เพื่อจับภาพเพื่อวัตถุประสงค์ในการระบุตัวตนภายใน ${provider} โปรดตรวจสอบนโยบายความเป็นส่วนตัวเพื่อดูรายละเอียด", - "no_relays": "ไม่มีรีเลย์", - "choose_relay": "กรุณาเลือกรีเลย์ที่จะใช้", - "no_relays_message": "เราพบบันทึก Nostr NIP-05 สำหรับผู้ใช้รายนี้ แต่ไม่มีรีเลย์ใดๆ โปรดแนะนำให้ผู้รับเพิ่มรีเลย์ลงในบันทึก Nostr ของตน", - "no_relay_on_domain": "ไม่มีการส่งต่อสำหรับโดเมนของผู้ใช้ หรือการส่งต่อไม่พร้อมใช้งาน กรุณาเลือกรีเลย์ที่จะใช้" - "zzzz": "zzzz" + "you_will_send": "แปลงจาก" } \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 51063b60d..273536cbb 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -710,6 +710,7 @@ "use_card_info_two": "Ang mga pondo ay na -convert sa USD kapag gaganapin sila sa prepaid account, hindi sa mga digital na pera.", "use_ssl": "Gumamit ng SSL", "use_suggested": "Gumamit ng iminungkahing", + "use_testnet": "Gumamit ng testnet", "variable_pair_not_supported": "Ang variable na pares na ito ay hindi suportado sa mga napiling palitan", "verification": "Pag -verify", "verify_with_2fa": "Mag -verify sa cake 2FA", @@ -768,275 +769,5 @@ "you_now_have_debit_card": "Mayroon ka na ngayong debit card", "you_pay": "Magbabayad ka", "you_will_get": "Mag -convert sa", - "you_will_send": "I -convert mula sa", - "yy": "YY", - "online": "Online", - "offline": "Offline", - "gift_card_number": "Numero ng regalo card", - "pin_number": "Numero ng pin", - "total_saving": "Kabuuang pagtitipid", - "last_30_days": "Huling 30 araw", - "avg_savings": "Avg. Matitipid", - "view_all": "Tingnan lahat", - "active_cards": "Mga aktibong kard", - "delete_account": "Tanggalin ang account", - "cards": "Mga Card", - "active": "Aktibo", - "redeemed": "Tinubos", - "gift_card_balance_note": "Ang mga kard ng regalo na may natitirang balanse ay lilitaw dito", - "gift_card_redeemed_note": "Ang mga kard ng regalo na iyong tinubos ay lilitaw dito", - "logout": "Mag -logout", - "add_tip": "Magdagdag ng tip", - "percentageOf": "ng ${amount}", - "is_percentage": "ay", - "search_category": "Kategorya ng paghahanap", - "mark_as_redeemed": "Markahan bilang tinubos", - "more_options": "Higit pang mga pagpipilian", - "awaiting_payment_confirmation": "Naghihintay ng kumpirmasyon sa pagbabayad", - "transaction_sent_notice": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang isang block explorer at ang iyong email.", - "agree": "Sumang -ayon", - "in_store": "Nakatago", - "generating_gift_card": "Bumubuo ng Gift Card", - "payment_was_received": "Natanggap ang iyong pagbabayad.", - "proceed_after_one_minute": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang iyong email.", - "order_id": "Order id", - "gift_card_is_generated": "Ang card ng regalo ay nabuo", - "open_gift_card": "Buksan ang Gift Card", - "contact_support": "Makipag -ugnay sa suporta", - "gift_cards_unavailable": "Magagamit ang mga gift card para sa pagbili lamang kasama ang Monero, Bitcoin, at Litecoin sa oras na ito", - "background_sync_mode": "Mode ng pag -sync ng background", - "sync_all_wallets": "I -sync ang lahat ng mga pitaka", - "introducing_cake_pay": "Ipinakikilala ang cake pay!", - "cake_pay_learn_more": "Agad na bumili at tubusin ang mga kard ng regalo sa app!\nMag -swipe pakaliwa sa kanan upang matuto nang higit pa.", - "automatic": "Awtomatiko", - "fixed_pair_not_supported": "Ang nakapirming pares na ito ay hindi suportado sa mga napiling palitan", - "variable_pair_not_supported": "Ang variable na pares na ito ay hindi suportado sa mga napiling palitan", - "none_of_selected_providers_can_exchange": "Wala sa mga napiling tagapagkaloob na maaaring gumawa ng palitan na ito", - "choose_one": "Pumili ng isa", - "choose_from_available_options": "Pumili mula sa magagamit na mga pagpipilian:", - "custom_redeem_amount": "Pasadyang tinubos ang halaga", - "add_custom_redemption": "Magdagdag ng pasadyang pagtubos", - "remaining": "natitira", - "delete_wallet": "Tanggalin ang pitaka", - "delete_wallet_confirm_message": "Sigurado ka bang nais mong tanggalin ang ${wallet_name} wallet?", - "low_fee": "Mababang bayad", - "low_fee_alert": "Kasalukuyan kang gumagamit ng isang mababang priyoridad sa bayad sa network. Maaari itong maging sanhi ng mahabang paghihintay, iba't ibang mga rate, o kanselahin ang mga trading. Inirerekumenda namin ang pagtatakda ng isang mas mataas na bayad para sa isang mas mahusay na karanasan.", - "ignor": "Huwag pansinin", - "use_suggested": "Gumamit ng iminungkahing", - "do_not_share_warning_text": "Huwag ibahagi ang mga ito sa sinumang iba pa, kabilang ang suporta.\n\nAng iyong mga pondo ay maaari at ninakaw!", - "help": "Tulong", - "all_transactions": "Lahat ng mga transaksyon", - "all_trades": "Lahat ng mga kalakal", - "connection_sync": "Koneksyon at pag -sync", - "security_and_backup": "Seguridad at backup", - "create_backup": "Gumawa ng backup", - "privacy_settings": "Settings para sa pagsasa-pribado", - "privacy": "Privacy", - "display_settings": "Mga setting ng pagpapakita", - "other_settings": "Iba pang mga setting", - "auto_generate_subaddresses": "Ang Auto ay bumubuo ng mga subaddresses", - "require_pin_after": "Nangangailangan ng pin pagkatapos", - "always": "Palagi", - "minutes_to_pin_code": "${minute} minuto", - "disable_exchange": "Huwag paganahin ang palitan", - "advanced_settings": "Mga Advanced na Setting", - "settings_can_be_changed_later": "Ang mga setting na ito ay maaaring mabago mamaya sa mga setting ng app", - "add_custom_node": "Magdagdag ng bagong pasadyang node", - "disable_fiat": "Huwag paganahin ang Fiat", - "fiat_api": "Fiat API", - "disabled": "Hindi pinagana", - "enabled": "Pinagana", - "tor_only": "Tor lang", - "unmatched_currencies": "Ang pera ng iyong kasalukuyang pitaka ay hindi tumutugma sa na -scan na QR", - "orbot_running_alert": "Mangyaring tiyakin na ang Orbot ay tumatakbo bago kumonekta sa node na ito.", - "contact_list_contacts": "Mga contact", - "contact_list_wallets": "Ang mga wallets ko", - "bitcoin_payments_require_1_confirmation": "Ang mga pagbabayad sa Bitcoin ay nangangailangan ng 1 kumpirmasyon, na maaaring tumagal ng 20 minuto o mas mahaba. Salamat sa iyong pasensya! Mag -email ka kapag nakumpirma ang pagbabayad.", - "send_to_this_address": "Magpadala ng ${currency} ${tag} sa address na ito", - "arrive_in_this_address": "Ang ${currency} ${tag} ay darating sa address na ito", - "do_not_send": "Huwag magpadala", - "error_dialog_content": "Oops, nakakuha kami ng ilang error.\n\nMangyaring ipadala ang ulat ng pag -crash sa aming koponan ng suporta upang maging mas mahusay ang application.", - "scan_qr_code": "I -scan ang QR Code", - "cold_or_recover_wallet": "Magdagdag ng isang malamig na pitaka o mabawi ang isang wallet ng papel", - "please_wait": "Mangyaring maghintay", - "sweeping_wallet": "Pagwawalis ng pitaka", - "sweeping_wallet_alert": "Hindi ito dapat magtagal. Huwag iwanan ang screen na ito o maaaring mawala ang mga pondo ng swept.", - "invoice_details": "Mga detalye ng invoice", - "donation_link_details": "Mga Detalye ng Link ng Donasyon", - "anonpay_description": "Bumuo ng ${type}. Ang tatanggap ay maaaring ${method} na may anumang suportadong cryptocurrency, at makakatanggap ka ng mga pondo sa pitaka na ito.", - "create_invoice": "Lumikha ng invoice", - "create_donation_link": "Lumikha ng link ng donasyon", - "optional_email_hint": "Opsyonal na Payee Notification Email", - "optional_description": "Opsyonal na paglalarawan", - "optional_name": "Opsyonal na pangalan ng tatanggap", - "clearnet_link": "Link ng Clearnet", - "onion_link": "Link ng Onion", - "decimal_places_error": "Masyadong maraming mga lugar na desimal", - "edit_node": "I -edit ang node", - "settings": "Mga setting", - "sell_monero_com_alert_content": "Ang pagbebenta ng Monero ay hindi pa suportado", - "error_text_input_below_minimum_limit": "Ang halaga ay mas mababa sa minimum", - "error_text_input_above_maximum_limit": "Ang halaga ay higit pa sa maximum", - "show_market_place": "Ipakita ang Marketplace", - "prevent_screenshots": "Maiwasan ang mga screenshot at pag -record ng screen", - "profile": "Profile", - "close": "Malapit", - "modify_2fa": "Baguhin ang cake 2FA", - "disable_cake_2fa": "Huwag paganahin ang cake 2FA", - "question_to_disable_2fa": "Sigurado ka bang nais mong huwag paganahin ang cake 2fa? Ang isang 2FA code ay hindi na kinakailangan upang ma -access ang pitaka at ilang mga pag -andar.", - "disable": "Huwag paganahin", - "setup_2fa": "Setup cake 2fa", - "verify_with_2fa": "Mag -verify sa cake 2FA", - "totp_code": "TOTP code", - "please_fill_totp": "Mangyaring punan ang 8-digit na code na naroroon sa iyong iba pang aparato", - "totp_2fa_success": "Tagumpay! Pinagana ang cake 2FA para sa pitaka na ito. Tandaan na i -save ang iyong mnemonic seed kung sakaling mawalan ka ng pag -access sa pitaka.", - "totp_verification_success": "Matagumpay ang pagpapatunay!", - "totp_2fa_failure": "Maling code. Mangyaring subukan ang ibang code o makabuo ng isang bagong lihim na susi. Gumamit ng isang katugmang 2FA app na sumusuporta sa 8-digit na mga code at SHA512.", - "enter_totp_code": "Mangyaring ipasok ang TOTP code.", - "add_secret_code": "O, idagdag ang sikretong code na ito sa isang authenticator app", - "totp_secret_code": "TOTP Secret Code", - "setup_2fa_text": "Gumagana ang Cake 2FA gamit ang TOTP bilang pangalawang kadahilanan sa pagpapatunay.\n\nAng TOTP ng Cake 2FA ay nangangailangan ng SHA-512 at 8 digit na suporta; nagbibigay ito ng mas mataas na seguridad. Higit pang impormasyon at suportadong app ang makikita sa gabay.", - "setup_totp_recommended": "I-setup ang TOTP", - "disable_buy": "Huwag paganahin ang pagkilos ng pagbili", - "disable_sell": "Huwag paganahin ang pagkilos ng pagbebenta", - "monero_dark_theme": "Monero Madilim na Tema", - "bitcoin_dark_theme": "Bitcoin Madilim na Tema", - "bitcoin_light_theme": "Tema ng ilaw ng bitcoin", - "high_contrast_theme": "Mataas na tema ng kaibahan", - "matrix_green_dark_theme": "Matrix Green Madilim na Tema", - "monero_light_theme": "Tema ng Monero Light", - "cake_2fa_preset": "Cake 2fa preset", - "narrow": "Makitid", - "normal": "Normal", - "aggressive": "Agresibo", - "require_for_assessing_wallet": "Nangangailangan para sa pag -access ng pitaka", - "require_for_sends_to_non_contacts": "Nangangailangan para sa pagpapadala sa mga hindi contact", - "require_for_sends_to_contacts": "Nangangailangan para sa pagpapadala sa mga contact", - "require_for_sends_to_internal_wallets": "Nangangailangan para sa pagpapadala sa mga panloob na mga pitaka", - "require_for_exchanges_to_internal_wallets": "Nangangailangan para sa mga palitan sa mga panloob na mga pitaka", - "require_for_adding_contacts": "Nangangailangan para sa pagdaragdag ng mga contact", - "require_for_creating_new_wallets": "Nangangailangan para sa paglikha ng mga bagong pitaka", - "require_for_all_security_and_backup_settings": "Nangangailangan para sa lahat ng mga setting ng seguridad at backup", - "available_balance_description": "Ang \"magagamit na balanse\" o \"nakumpirma na balanse\" ay mga pondo na maaaring gastusin kaagad. Kung lumilitaw ang mga pondo sa mas mababang balanse ngunit hindi ang nangungunang balanse, dapat kang maghintay ng ilang minuto para sa mga papasok na pondo upang makakuha ng mas maraming mga kumpirmasyon sa network. Matapos silang makakuha ng higit pang mga kumpirmasyon, gugugol sila.", - "syncing_wallet_alert_title": "Ang iyong pitaka ay nag -sync", - "syncing_wallet_alert_content": "Ang iyong balanse at listahan ng transaksyon ay maaaring hindi kumpleto hanggang sa sabihin nito na \"naka -synchronize\" sa tuktok. Mag -click/tap upang malaman ang higit pa.", - "home_screen_settings": "Mga setting ng home screen", - "sort_by": "Pag -uri -uriin sa pamamagitan ng", - "search_add_token": "Maghanap / Magdagdag ng Token", - "edit_token": "I -edit ang token", - "warning": "Babala", - "add_token_warning": "Huwag i -edit o magdagdag ng mga token tulad ng itinuro ng mga scammers.\nLaging kumpirmahin ang mga token address na may mga kagalang -galang na mapagkukunan!", - "add_token_disclaimer_check": "Kinumpirma ko ang address ng kontrata ng token at impormasyon gamit ang isang kagalang -galang na mapagkukunan. Ang pagdaragdag ng nakakahamak o hindi tamang impormasyon ay maaaring magresulta sa pagkawala ng mga pondo.", - "token_contract_address": "Token Address ng Kontrata", - "token_name": "Pangalan ng Token hal: Tether", - "token_symbol": "Simbolo ng token hal: USDT", - "token_decimal": "Token Decimal", - "field_required": "Kinakailangan ang patlang na ito", - "pin_at_top": "Pin ${token} sa tuktok", - "invalid_input": "Di -wastong input", - "fiat_balance": "Balanse ng fiat", - "gross_balance": "Balanse ng gross", - "alphabetical": "Alpabeto", - "generate_name": "Bumuo ng pangalan", - "balance_page": "Pahina ng Balanse", - "share": "Ibahagi", - "slidable": "Slidable", - "manage_nodes": "Pamahalaan ang mga node", - "etherscan_history": "Kasaysayan ng Etherscan", - "template_name": "Pangalan ng Template", - "support_title_live_chat": "Live na suporta", - "support_description_live_chat": "Libre at mabilis! Ang mga bihasang kinatawan ng suporta ay magagamit upang tulungan", - "support_title_guides": "Mga Gabay sa Wallet ng cake", - "support_description_guides": "Dokumentasyon at suporta para sa mga karaniwang isyu", - "support_title_other_links": "Iba pang mga link sa suporta", - "support_description_other_links": "Sumali sa aming mga komunidad o maabot sa amin ang aming mga kasosyo sa pamamagitan ng iba pang mga pamamaraan", - "select_destination": "Mangyaring piliin ang patutunguhan para sa backup file.", - "save_to_downloads": "I -save sa mga pag -download", - "select_buy_provider_notice": "Pumili ng provider ng pagbili sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na provider ng pagbili sa mga setting ng app.", - "onramper_option_description": "Mabilis na bumili ng crypto na may maraming paraan ng pagbabayad. Available sa karamihan ng mga bansa. Iba-iba ang mga spread at bayarin.", - "default_buy_provider": "Default na Provider ng Pagbili", - "ask_each_time": "Magtanong sa bawat oras", - "robinhood_option_description": "Bumili at ilipat kaagad gamit ang iyong debit card, bank account, o balanse ng Robinhood. USA lang.", - "buy_provider_unavailable": "Kasalukuyang hindi available ang provider.", - "signTransaction": "Mag-sign Transaksyon", - "errorGettingCredentials": "Nabigo: Error habang kumukuha ng mga kredensyal", - "errorSigningTransaction": "May naganap na error habang pinipirmahan ang transaksyon", - "pairingInvalidEvent": "Pagpares ng Di-wastong Kaganapan", - "chains": "Mga tanikala", - "methods": "Paraan", - "events": "Mga kaganapan", - "reject": "Tanggihan", - "approve": "Aprubahan", - "expiresOn": "Mag-e-expire sa", - "walletConnect": "WalletConnect", - "nullURIError": "Ang URI ay null", - "connectWalletPrompt": "Ikonekta ang iyong wallet sa WalletConnect upang gumawa ng mga transaksyon", - "newConnection": "Bagong Koneksyon", - "activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon", - "deleteConnectionConfirmationPrompt": "Sigurado ka bang gusto mong tanggalin ang koneksyon sa", - "event": "Kaganapan", - "successful": "Matagumpay", - "wouoldLikeToConnect": "gustong kumonekta", - "message": "Mensahe", - "do_not_have_enough_gas_asset": "Wala kang sapat na ${currency} para gumawa ng transaksyon sa kasalukuyang kundisyon ng network ng blockchain. Kailangan mo ng higit pang ${currency} upang magbayad ng mga bayarin sa network ng blockchain, kahit na nagpapadala ka ng ibang asset.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Pakihintay na matapos ang pagproseso ng dApp.", - "copyWalletConnectLink": "Kopyahin ang link ng WalletConnect mula sa dApp at i-paste dito", - "enterWalletConnectURI": "Ilagay ang WalletConnect URI", - "seed_key": "Seed Key", - "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", - "change_rep_successful": "Matagumpay na nagbago ng kinatawan", - "add_contact": "Magdagdag ng contact", - "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", - "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", - "order_by": "Iniutos ni", - "creation_date": "Petsa ng paglikha", - "group_by_type": "Pangkat ayon sa uri", - "importNFTs": "Mag-import ng mga NFT", - "noNFTYet": "Wala pang NFT", - "address": "Address", - "enterTokenID": "Ilagay ang token ID", - "tokenID": "ID", - "name": "Pangalan", - "symbol": "Simbolo", - "seed_phrase_length": "Haba ng parirala ng binhi", - "unavailable_balance": "Hindi available na balanse", - "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", - "unspent_change": "Baguhin", - "tor_connection": "Koneksyon ng Tor", - "setup_warning_2fa_text": "Kakailanganin mong ibalik ang iyong wallet mula sa mnemonic seed.\n\nHindi ka matutulungan ng suporta sa cake kung mawawalan ka ng access sa iyong 2FA o mnemonic seeds.\nAng Cake 2FA ay pangalawang pagpapatotoo para sa ilang partikular na pagkilos sa wallet. Bago gamitin ang Cake 2FA, inirerekomenda naming basahin ang gabay.HINDI ito kasing-secure ng malamig na imbakan.\n\nKung nawalan ka ng access sa iyong 2FA app o TOTP keys, MAWAWALA ka ng access sa wallet na ito. ", - "scan_qr_on_device": "I-scan ang QR code na ito sa ibang device", - "how_to_use": "Paano gamitin", - "seed_hex_form": "Wallet seed (hex form)", - "seedtype_legacy": "Pamana (25 salita)", - "seedtype_polyseed": "Polyseed (16 na salita)", - "seed_language_czech": "Czech", - "seed_language_korean": "Korean", - "seed_language_chinese_traditional": "Intsik (tradisyonal)", - "ascending": "Umakyat", - "descending": "Pababang", - "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe", - "polygonscan_history": "Kasaysayan ng PolygonScan", - "wallet_seed_legacy": "Legacy wallet seed", - "default_sell_provider": "Default na Sell Provider", - "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", - "custom_drag": "Pasadyang (hawakan at i -drag)", - "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)", - "use_testnet": "Gumamit ng testnet", - "receivable_balance": "Natatanggap na balanse", - "confirmed_tx": "Nakumpirma", - "transaction_details_source_address": "SOURCE ADDRESS", - "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet.", - "contractName": "Pangalan ng Kontrata", - "contractSymbol": "Simbolo ng Kontrata", - "description": "Paglalarawan", - "camera_consent": "Gagamitin ang iyong camera upang kumuha ng larawan para sa mga layunin ng pagkakakilanlan sa pamamagitan ng ${provider}. Pakisuri ang kanilang Patakaran sa Privacy para sa mga detalye.", - "no_relays": "Walang mga relay", - "choose_relay": "Mangyaring pumili ng relay na gagamitin", - "no_relays_message": "Nakakita kami ng Nostr NIP-05 record para sa user na ito, ngunit hindi ito naglalaman ng anumang mga relay. Mangyaring atasan ang tatanggap na magdagdag ng mga relay sa kanilang Nostr record.", - "no_relay_on_domain": "Walang relay para sa domain ng user o hindi available ang relay. Mangyaring pumili ng relay na gagamitin." - "zzzz": "Zzzz" + "you_will_send": "I -convert mula sa" } \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index b1eea2354..27facfdc5 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -714,6 +714,7 @@ "use_card_info_two": "Paralar, dijital para birimlerinde değil, ön ödemeli hesapta tutulduğunda USD'ye dönüştürülür.", "use_ssl": "SSL kullan", "use_suggested": "Önerileni Kullan", + "use_testnet": "TestNet kullanın", "variable_pair_not_supported": "Bu değişken paritesi seçilen borsalarda desteklenmemekte", "verification": "Doğrulama", "verify_with_2fa": "Cake 2FA ile Doğrulayın", @@ -772,279 +773,5 @@ "you_now_have_debit_card": "Artık bir ön ödemeli kartın var", "you_pay": "Şu kadar ödeyeceksin: ", "you_will_get": "Biçimine dönüştür:", - "you_will_send": "Biçiminden dönüştür:", - "yy": "YY", - "online": "Çevrimiçi", - "offline": "Çevrimdışı", - "gift_card_number": "Hediye kartı numarası", - "pin_number": "PIN kodu", - "total_saving": "Toplam Tasarruf", - "last_30_days": "Son 30 gün", - "avg_savings": "Ortalama Tasarruf", - "view_all": "Hepsini göster", - "active_cards": "Aktif kartlar", - "delete_account": "Hesabı sil", - "cards": "Kartlar", - "active": "Aktif", - "redeemed": "Kullanılmış", - "gift_card_balance_note": "Bakiyesi kalan olan hediye kartları burada görünecek", - "gift_card_redeemed_note": "Harcadığın hediye kartları burada görünecek", - "logout": "Çıkış yap", - "add_tip": "Bahşiş Ekle", - "percentageOf": "of ${amount}", - "is_percentage": "is", - "search_category": "Kategori ara", - "mark_as_redeemed": "Harcanmış olarak işaretle", - "more_options": "Daha Fazla Seçenek", - "awaiting_payment_confirmation": "Ödemenin onaylanması bekleniyor", - "transaction_sent_notice": "Ekran 1 dakika sonra ilerlemezse, blok gezgininden ve e-postanızdan kontrol edin.", - "agree": "Kabul Et", - "in_store": "Mağazada", - "generating_gift_card": "Hediye Kartı Oluşturuluyor", - "payment_was_received": "Ödemeniz alındı.", - "proceed_after_one_minute": "Ekran 1 dakika sonra ilerlemezse, e-postanızı kontrol edin.", - "order_id": "Sipariş ID'si", - "gift_card_is_generated": "Hediye Kartı oluşturuldu", - "open_gift_card": "Hediye Kartını Aç", - "contact_support": "Destek ile İletişime Geç", - "gift_cards_unavailable": "Hediye kartları şu anda yalnızca Monero, Bitcoin ve Litecoin ile satın alınabilir", - "introducing_cake_pay": "Cake Pay ile tanışın!", - "cake_pay_learn_more": "Uygulamada anında hediye kartları satın alın ve harcayın!\nDaha fazla öğrenmek için soldan sağa kaydır.", - "automatic": "Otomatik", - "fixed_pair_not_supported": "Bu sabit paritesi seçilen borsalarda desteklenmemekte", - "variable_pair_not_supported": "Bu değişken paritesi seçilen borsalarda desteklenmemekte", - "none_of_selected_providers_can_exchange": "Seçilen sağlayıcılardan hiçbiri bu takası yapamaz", - "choose_one": "Birini seç", - "choose_from_available_options": "Mevcut seçenekler arasından seçim yap:", - "custom_redeem_amount": "Özel Harcama Tutarı", - "add_custom_redemption": "Özel Bozdurma Ekle", - "remaining": "kalan", - "delete_wallet": "Cüzdanı sil", - "delete_wallet_confirm_message": "${wallet_name} isimli cüzdanını silmek istediğinden emin misin?", - "low_fee": "Düşük komisyon", - "low_fee_alert": "Şu anda düşük bir ağ ücreti önceliği kullanıyorsunuz. Bu durum uzun beklemeler, farklı oranlar veya iptal edilen işlemlere neden olabilir. Daha iyi bir deneyim için daha yüksek bir ücret belirlemenizi öneririz.", - "ignor": "Yoksay", - "use_suggested": "Önerileni Kullan", - "do_not_share_warning_text": "Bunları destek de dahil olmak üzere başka kimseyle paylaşma.\n\nParan çalınabilir ve çalınacaktır!", - "help": "yardım", - "all_transactions": "Tüm transferler", - "all_trades": "Tüm takaslar", - "connection_sync": "Bağlantı ve senkronizasyon", - "security_and_backup": "Güvenlik ve yedekleme", - "create_backup": "Yedek oluştur", - "privacy_settings": "Gizlilik ayarları", - "privacy": "Gizlilik", - "display_settings": "Görüntü ayarları", - "other_settings": "Diğer ayarlar", - "require_pin_after": "Şu kadar süre sonra PIN iste", - "always": "Her Zaman", - "minutes_to_pin_code": "${minute} dakika", - "disable_exchange": "Borsayı devre dışı bırak", - "advanced_settings": "Gelişmiş Ayarlar", - "settings_can_be_changed_later": "Bu ayarlar daha sonra uygulama ayarlarından da değiştirilebilir", - "add_custom_node": "Yeni Özel Düğüm Ekleme", - "disable_fiat": "İtibari paraları devre dışı bırak", - "fiat_api": "İtibari Para API", - "disabled": "Devre dışı", - "enabled": "Etkin", - "tor_only": "Yalnızca Tor", - "unmatched_currencies": "Mevcut cüzdanınızın para birimi taranan QR ile eşleşmiyor", - "orbot_running_alert": "Lütfen bu düğüme bağlanmadan önce Orbot'un çalıştığından emin olun.", - "contact_list_contacts": "Rehberim", - "contact_list_wallets": "Cüzdanlarım", - "bitcoin_payments_require_1_confirmation": "Bitcoin ödemeleri, 20 dakika veya daha uzun sürebilen 1 onay gerektirir. Sabrınız için teşekkürler! Ödeme onaylandığında e-posta ile bilgilendirileceksiniz.", - "send_to_this_address": "Bu adrese ${currency} ${tag}gönder", - "arrive_in_this_address": "${currency} ${tag}bu adrese ulaşacak", - "do_not_send": "Gönderme", - "error_dialog_content": "Hay aksi, bir hatamız var.\n\nUygulamayı daha iyi hale getirmek için lütfen kilitlenme raporunu destek ekibimize gönderin.", - "scan_qr_code": "QR kodunu tarayın", - "cold_or_recover_wallet": "Soğuk bir cüzdan ekleyin veya bir kağıt cüzdanı kurtarın", - "please_wait": "Lütfen bekleyin", - "sweeping_wallet": "Süpürme cüzdanı", - "sweeping_wallet_alert": "Bu uzun sürmemeli. BU EKRANDAN BIRAKMAYIN YOKSA SÜPÜRÜLEN FONLAR KAYBOLABİLİR", - "decimal_places_error": "Çok fazla ondalık basamak", - "edit_node": "Düğümü Düzenle", - "invoice_details": "fatura detayları", - "donation_link_details": "Bağış bağlantısı ayrıntıları", - "anonpay_description": "${type} oluşturun. Alıcı, desteklenen herhangi bir kripto para birimi ile ${method} yapabilir ve bu cüzdanda para alırsınız.", - "create_invoice": "Fatura oluşturmak", - "create_donation_link": "Bağış bağlantısı oluştur", - "optional_email_hint": "İsteğe bağlı alacaklı bildirim e-postası", - "optional_description": "İsteğe bağlı açıklama", - "optional_name": "İsteğe bağlı alıcı adı", - "clearnet_link": "Net bağlantı", - "onion_link": "soğan bağlantısı", - "settings": "ayarlar", - "sell_monero_com_alert_content": "Monero satışı henüz desteklenmiyor", - "error_text_input_below_minimum_limit": "Miktar minimumdan daha azdır", - "error_text_input_above_maximum_limit": "Miktar maksimumdan daha fazla", - "show_market_place": "Pazar Yerini Göster", - "prevent_screenshots": "Ekran görüntülerini ve ekran kaydını önleyin", - "profile": "Profil", - "close": "Kapalı", - "modify_2fa": "Cake 2FA'yı Değiştirin", - "disable_cake_2fa": "Cake 2FA'yı Devre Dışı Bırak", - "question_to_disable_2fa": "Cake 2FA'yı devre dışı bırakmak istediğinizden emin misiniz? M-cüzdana ve belirli işlevlere erişmek için artık 2FA koduna gerek kalmayacak.", - "disable": "Devre dışı bırakmak", - "setup_2fa": "Kurulum Pastası 2FA", - "verify_with_2fa": "Cake 2FA ile Doğrulayın", - "totp_code": "TOTP Kodu", - "please_fill_totp": "Lütfen diğer cihazınızda bulunan 8 haneli kodu girin", - "totp_2fa_success": "Başarı! Bu cüzdan için Cake 2FA etkinleştirildi. Mnemonic seed'inizi cüzdan erişiminizi kaybetme ihtimaline karşı kaydetmeyi unutmayın.", - "totp_verification_success": "Doğrulama Başarılı!", - "totp_2fa_failure": "Yanlış kod. Lütfen farklı bir kod deneyin veya yeni bir gizli anahtar oluşturun. 8 basamaklı kodları ve SHA512'yi destekleyen uyumlu bir 2FA uygulaması kullanın.", - "enter_totp_code": "Lütfen TOTP Kodunu giriniz.", - "add_secret_code": "Veya bu gizli kodu bir kimlik doğrulama uygulamasına ekleyin", - "totp_secret_code": "TOTP Gizli Kodu", - "setup_2fa_text": "Cake 2FA, ikinci kimlik doğrulama faktörü olarak TOTP'yi kullanarak çalışır.\n\nCake 2FA'nın TOTP'si SHA-512 ve 8 haneli destek gerektirir; bu daha fazla güvenlik sağlar. Daha fazla bilgi ve desteklenen uygulamalar kılavuzda bulunabilir.", - "setup_totp_recommended": "TOTP'yi kur", - "disable_buy": "Satın alma işlemini devre dışı bırak", - "disable_sell": "Satış işlemini devre dışı bırak", - "auto_generate_subaddresses": "Alt adresleri otomatik olarak oluştur", - "cake_2fa_preset": "Kek 2FA Ön Ayarı", - "narrow": "Dar", - "normal": "Normal", - "aggressive": "Aşırı duyarlı", - "require_for_assessing_wallet": "Cüzdana erişmek için gerekli", - "require_for_sends_to_non_contacts": "Kişi olmayan kişilere göndermeler için gerekli kıl", - "require_for_sends_to_contacts": "Kişilere göndermeler için gerekli kıl", - "require_for_sends_to_internal_wallets": "Dahili cüzdanlara yapılan gönderimler için gereklilik", - "require_for_exchanges_to_internal_wallets": "Dahili cüzdanlara değişim gerektir", - "require_for_adding_contacts": "Kişi eklemek için gerekli", - "require_for_creating_new_wallets": "Yeni cüzdan oluşturmak için gerekli", - "require_for_all_security_and_backup_settings": "Tüm güvenlik ve yedekleme ayarları için iste", - "available_balance_description": "Bu, cüzdanınızda harcayabileceğiniz miktar. Bu miktar, cüzdanınızdan çekilebilecek toplam bakiyeden daha düşük olabilir, çünkü bazı fonlar henüz kullanılamaz durumda olabilir.", - "syncing_wallet_alert_title": "Cüzdanınız senkronize ediliyor", - "syncing_wallet_alert_content": "Bakiyeniz ve işlem listeniz, en üstte \"SENKRONİZE EDİLDİ\" yazana kadar tamamlanmamış olabilir. Daha fazla bilgi edinmek için tıklayın/dokunun.", - "home_screen_settings": "Ana ekran ayarları", - "sort_by": "Göre sırala", - "search_add_token": "Belirteç Ara / Ekle", - "edit_token": "Belirteci düzenle", - "warning": "Uyarı", - "add_token_warning": "Dolandırıcıların talimatına göre jetonları düzenlemeyin veya eklemeyin.\nBelirteç adreslerini her zaman saygın kaynaklarla onaylayın!", - "add_token_disclaimer_check": "Belirteç sözleşmesi adresini ve bilgilerini saygın bir kaynak kullanarak onayladım. Kötü amaçlı veya yanlış bilgilerin eklenmesi para kaybına neden olabilir.", - "token_contract_address": "Token sözleşme adresi", - "token_name": "Belirteç adı, örneğin: Tether", - "token_symbol": "Jeton sembolü, örneğin: USDT", - "token_decimal": "Belirteç ondalık", - "field_required": "Bu alan gereklidir", - "pin_at_top": "${token} üstte sabitle", - "invalid_input": "Geçersiz Giriş", - "fiat_balance": "Fiat Bakiyesi", - "gross_balance": "Brüt Bakiye", - "alphabetical": "Alfabetik", - "generate_name": "İsim Oluştur", - "balance_page": "Bakiye Sayfası", - "share": "Paylaşmak", - "slidable": "kaydırılabilir", - "monero_dark_theme": "Monero Koyu Tema", - "bitcoin_dark_theme": "Bitcoin Karanlık Teması", - "bitcoin_light_theme": "Bitcoin Hafif Tema", - "high_contrast_theme": "Yüksek Kontrastlı Tema", - "matrix_green_dark_theme": "Matrix Yeşil Koyu Tema", - "monero_light_theme": "Monero Hafif Tema", - "manage_nodes": "Düğümleri yönet", - "etherscan_history": "Etherscan geçmişi", - "template_name": "şablon adı", - "change_rep": "Temsilciyi Değiştir", - "change_rep_message": "Temsilcileri değiştirmek istediğinizden emin misiniz?", - "unsupported_asset": "Bu öğe için bu eylemi desteklemiyoruz. Lütfen desteklenen bir varlık türünde bir cüzdan oluşturun veya cüzdana geçiş yapın.", - "manage_pow_nodes": "PoW Düğümlerini Yönet", - "support_title_live_chat": "Canlı destek", - "support_description_live_chat": "Ücretsiz ve hızlı! Eğitimli destek temsilcileri yardımcı olmak için mevcuttur", - "support_title_guides": "Kek Cüzdan Kılavuzları", - "support_description_guides": "Ortak sorunlara belge ve destek", - "support_title_other_links": "Diğer destek bağlantıları", - "support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın", - "choose_derivation": "Cüzdan türevini seçin", - "new_first_wallet_text": "Kripto para biriminizi kolayca güvende tutun", - "select_destination": "Lütfen yedekleme dosyası için hedef seçin.", - "save_to_downloads": "İndirilenlere Kaydet", - "select_buy_provider_notice": "Yukarıda bir satın alma sağlayıcısı seçin. App ayarlarında varsayılan satın alma sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", - "onramper_option_description": "Birçok ödeme yöntemi ile hızlı bir şekilde kripto satın alın. Çoğu ülkede mevcuttur. Forma ve ücretler değişir.", - "default_buy_provider": "Varsayılan Satın Alma Sağlayıcısı", - "ask_each_time": "Her seferinde sor", - "buy_provider_unavailable": "Sağlayıcı şu anda kullanılamıyor.", - "signTransaction": "İşlem İmzala", - "errorGettingCredentials": "Başarısız: Kimlik bilgileri alınırken hata oluştu", - "errorSigningTransaction": "İşlem imzalanırken bir hata oluştu", - "pairingInvalidEvent": "Geçersiz Etkinliği Eşleştirme", - "chains": "Zincirler", - "methods": "Yöntemler", - "events": "Olaylar", - "reject": "Reddetmek", - "approve": "Onaylamak", - "expiresOn": "Tarihinde sona eriyor", - "walletConnect": "WalletConnect", - "nullURIError": "URI boş", - "connectWalletPrompt": "İşlem yapmak için cüzdanınızı WalletConnect'e bağlayın", - "newConnection": "Yeni bağlantı", - "activeConnectionsPrompt": "Aktif bağlantılar burada görünecek", - "deleteConnectionConfirmationPrompt": "Bağlantıyı silmek istediğinizden emin misiniz?", - "event": "Etkinlik", - "successful": "Başarılı", - "wouoldLikeToConnect": "bağlanmak istiyorum", - "message": "İleti", - "do_not_have_enough_gas_asset": "Mevcut blockchain ağ koşullarıyla işlem yapmak için yeterli ${currency} paranız yok. Farklı bir varlık gönderiyor olsanız bile blockchain ağ ücretlerini ödemek için daha fazla ${currency} miktarına ihtiyacınız var.", - "totp_auth_url": "TOTP YETKİ URL'si", - "awaitDAppProcessing": "Lütfen dApp'in işlemeyi bitirmesini bekleyin.", - "copyWalletConnectLink": "WalletConnect bağlantısını dApp'ten kopyalayıp buraya yapıştırın", - "enterWalletConnectURI": "WalletConnect URI'sini girin", - "seed_key": "Tohum", - "enter_seed_phrase": "Tohum ifadenizi girin", - "change_rep_successful": "Temsilciyi başarıyla değiştirdi", - "add_contact": "Kişi ekle", - "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!", - "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", - "order_by": "Tarafından sipariş", - "creation_date": "Oluşturulma tarihi", - "group_by_type": "Türüne göre grup", - "importNFTs": "NFT'leri içe aktar", - "noNFTYet": "Henüz NFT yok", - "address": "Adres", - "enterTokenID": "Belirteç kimliğini girin", - "tokenID": "İD", - "name": "İsim", - "symbol": "Sembol", - "seed_phrase_length": "Çekirdek cümle uzunluğu", - "unavailable_balance": "Kullanılamayan bakiye", - "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", - "unspent_change": "Değiştirmek", - "tor_connection": "Tor bağlantısı", - "setup_warning_2fa_text": "Cüzdanınızı anımsatıcı tohumdan geri yüklemeniz gerekecek.\n\n2FA veya anımsatıcı tohumlarınıza erişiminizi kaybederseniz pasta desteği size yardımcı olamayacaktır.\nCake 2FA, cüzdandaki belirli eylemler için ikinci bir kimlik doğrulamadır. Cake 2FA'yı kullanmadan önce kılavuzu okumanızı öneririz.Soğuk hava deposu kadar güvenli DEĞİLDİR.\n\n2FA uygulamanıza veya TOTP anahtarlarınıza erişiminizi kaybederseniz bu cüzdana erişimi KAYBEDECEKSİNİZ. ", - "scan_qr_on_device": "Bu QR kodunu başka bir cihazda tarayın", - "how_to_use": "Nasıl kullanılır", - "seed_hex_form": "Cüzdan tohumu (onaltılık form)", - "seedtype": "Tohum", - "seedtype_legacy": "Miras (25 kelime)", - "seedtype_polyseed": "Polyseed (16 kelime)", - "seed_language_czech": "Çek", - "seed_language_korean": "Koreli", - "seed_language_chinese_traditional": "Çin geleneği)", - "ascending": "Yükselen", - "descending": "Azalan", - "dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için", - "polygonscan_history": "PolygonScan geçmişi", - "wallet_seed_legacy": "Eski cüzdan tohumu", - "default_sell_provider": "Varsayılan Satış Sağlayıcısı", - "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", - "custom_drag": "Özel (Bekle ve Sürükle)", - "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", - "use_testnet": "TestNet kullanın", - "receivable_balance": "Alacak bakiyesi", - "confirmed_tx": "Onaylanmış", - "transaction_details_source_address": "Kaynak adresi", - "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı.", - "contractName": "Sözleşme Adı", - "contractSymbol": "Sözleşme Sembolü", - "description": "Tanım", - "camera_consent": "Kameranız ${provider} tarihine kadar tanımlama amacıyla bir görüntü yakalamak için kullanılacaktır. Ayrıntılar için lütfen Gizlilik Politikalarını kontrol edin.", - "no_relays": "Röle yok", - "choose_relay": "Lütfen kullanmak için bir röle seçin", - "no_relays_message": "Bu kullanıcı için bir Nostr NIP-05 kaydı bulduk ancak bu kayıt herhangi bir aktarma içermiyor. Lütfen alıcıya Nostr kayıtlarına aktarma eklemesi talimatını verin.", - "no_relay_on_domain": "Kullanıcının alanı için bir geçiş yok veya geçiş kullanılamıyor. Lütfen kullanmak için bir röle seçin." - "zzzz": "zzzz" + "you_will_send": "Biçiminden dönüştür:" } \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 67a3a5fbc..569cb770d 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -716,6 +716,7 @@ "use_card_info_two": "Кошти конвертуються в долари США, якщо вони зберігаються на передплаченому рахунку, а не в цифрових валютах.", "use_ssl": "Використати SSL", "use_suggested": "Використати запропоноване", + "use_testnet": "Використовуйте тестову мережу", "variable_pair_not_supported": "Ця пара змінних не підтримується вибраними біржами", "verification": "Перевірка", "verify_with_2fa": "Перевірте за допомогою Cake 2FA", @@ -774,281 +775,5 @@ "you_now_have_debit_card": "Тепер у вас є дебетова картка", "you_pay": "Ви платите", "you_will_get": "Конвертувати в", - "you_will_send": "Конвертувати з", - "yy": "YY", - "online": "Онлайн", - "offline": "Офлайн", - "gift_card_number": "Номер подарункової картки", - "pin_number": "PIN-код", - "total_saving": "Загальна економія", - "last_30_days": "Останні 30 днів", - "avg_savings": "Середня економія", - "view_all": "Переглянути все", - "active_cards": "Активні картки", - "delete_account": "Видалити обліковий запис", - "cards": "Картки", - "active": "Активний", - "redeeded": "Викуплено", - "gift_card_balance_note": "Тут з'являться подарункові картки із залишком на балансі", - "gift_card_redeemed_note": "Подарункові картки, які ви активували, відображатимуться тут", - "logout": "Вийти", - "add_tip": "Додати підказку", - "percentageOf": "${amount}", - "is_percentage": "є", - "search_category": "Категорія пошуку", - "mark_as_redeemed": "Позначити як погашене", - "more_options": "Більше параметрів", - "awaiting_payment_confirmation": "Очікується підтвердження платежу", - "transaction_sent_notice": "Якщо екран не відображається через 1 хвилину, перевірте провідник блоків і свою електронну пошту.", - "agree": "Згоден", - "in_store": "У магазині", - "generating_gift_card": "Створення подарункової картки", - "payment_was_received": "Ваш платіж отримано.", - "proceed_after_one_minute": "Якщо екран не продовжується через 1 хвилину, перевірте свою електронну пошту.", - "order_id": "Ідентифікатор замовлення", - "gift_card_is_generated": "Подарункова картка створена", - "open_gift_card": "Відкрити подарункову картку", - "contact_support": "Звернутися до служби підтримки", - "gift_cards_unavailable": "Наразі подарункові картки можна придбати лише через Monero, Bitcoin і Litecoin", - "background_sync_mode": "Фоновий режим синхронізації", - "sync_all_wallets": "Синхронізувати всі гаманці", - "introducing_cake_pay": "Представляємо Cake Pay!", - "cake_pay_learn_more": "Миттєво купуйте та активуйте подарункові картки в додатку!\nПроведіть пальцем зліва направо, щоб дізнатися більше.", - "automatic": "Автоматичний", - "fixed_pair_not_supported": "Ця фіксована пара не підтримується вибраними біржами", - "variable_pair_not_supported": "Ця пара змінних не підтримується вибраними біржами", - "none_of_selected_providers_can_exchange": "Жоден із вибраних провайдерів не може здійснити цей обмін", - "choose_one": "Вибери один", - "choose_from_available_options": "Виберіть із доступних варіантів:", - "custom_redeem_amount": "Власна сума викупу", - "add_custom_redemption": "Додати спеціальне погашення", - "remaining": "залишилося", - "delete_wallet": "Видалити гаманець", - "delete_wallet_confirm_message": "Ви впевнені, що хочете видалити гаманець ${wallet_name}?", - "low_fee": "Низька плата", - "low_fee_alert": "Зараз ви використовуєте низький пріоритет плати за мережу. Це може спричинити тривале очікування, інший курс або скасування угод. Ми рекомендуємо встановити вищу плату для кращого досвіду.", - "ignor": "Ігнорувати", - "use_suggested": "Використати запропоноване", - "do_not_share_warning_text": "Не діліться цим нікому, включно зі службою підтримки.\n\nВаші кошти можуть і будуть вкрадені!", - "help": "допомога", - "all_transactions": "Всі транзакції", - "all_trades": "Всі операції", - "connection_sync": "Підключення та синхронізація", - "security_and_backup": "Безпека та резервне копіювання", - "create_backup": "Створити резервну копію", - "privacy_settings": "Налаштування конфіденційності", - "privacy": "Конфіденційність", - "display_settings": "Налаштування дисплея", - "other_settings": "Інші налаштування", - "require_pin_after": "Вимагати PIN після", - "always": "Завжди", - "minutes_to_pin_code": "${minute} хвилин", - "disable_exchange": "Вимкнути exchange", - "advanced_settings": "Розширені налаштування", - "settings_can_be_changed_later": "Ці параметри можна змінити пізніше в налаштуваннях програми", - "add_custom_node": "Додати новий спеціальний вузол", - "disable_fiat": "Вимкнути фиат", - "fiat_api": "Фіат API", - "disabled": "Вимкнено", - "enabled": "Увімкнено", - "tor_only": "Тільки Tor", - "unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду", - "orbot_running_alert": "Перед підключенням до цього вузла переконайтеся, що Orbot запущено.", - "contact_list_contacts": "Контакти", - "contact_list_wallets": "Мої гаманці", - "bitcoin_payments_require_1_confirmation": "Платежі Bitcoin потребують 1 підтвердження, яке може зайняти 20 хвилин або більше. Дякую за Ваше терпіння! Ви отримаєте електронний лист, коли платіж буде підтверджено.", - "send_to_this_address": "Надіслати ${currency} ${tag}на цю адресу", - "arrive_in_this_address": "${currency} ${tag}надійде на цю адресу", - "do_not_send": "Не надсилайте", - "error_dialog_content": "На жаль, ми отримали помилку.\n\nБудь ласка, надішліть звіт про збій нашій команді підтримки, щоб покращити додаток.", - "scan_qr_code": "Відскануйте QR-код", - "cold_or_recover_wallet": "Додайте холодний гаманець або відновіть паперовий гаманець", - "please_wait": "Будь ласка, зачекайте", - "sweeping_wallet": "Підмітаня гаманця", - "sweeping_wallet_alert": "Це не повинно зайняти багато часу. НЕ ЗАЛИШАЙТЕ ЦЬОГО ЕКРАНУ, АБО КОШТИ МОЖУТЬ БУТИ ВТРАЧЕНІ", - "decimal_places_error": "Забагато знаків після коми", - "edit_node": "Редагувати вузол", - "invoice_details": "Реквізити рахунку-фактури", - "donation_link_details": "Деталі посилання для пожертв", - "anonpay_description": "Згенерувати ${type}. Одержувач може ${method} будь-якою підтримуваною криптовалютою, і ви отримаєте кошти на цей гаманець.", - "create_invoice": "Створити рахунок-фактуру", - "create_donation_link": "Створити посилання для пожертв", - "optional_email_hint": "Додаткова електронна адреса для сповіщення одержувача", - "optional_description": "Додатковий опис", - "optional_name": "Додаткове ім'я одержувача", - "clearnet_link": "Посилання Clearnet", - "onion_link": "Посилання на цибулю", - "settings": "Налаштування", - "sell_monero_com_alert_content": "Продаж Monero ще не підтримується", - "error_text_input_below_minimum_limit": "Сума менша мінімальної", - "error_text_input_above_maximum_limit": "Сума більше максимальної", - "show_market_place": "Відображати маркетплейс", - "prevent_screenshots": "Запобігати знімкам екрана та запису екрана", - "profile": "Профіль", - "close": "Закрити", - "modify_2fa": "Змінити торт 2FA", - "disable_cake_2fa": "Вимкнути Cake 2FA", - "question_to_disable_2fa": "Ви впевнені, що хочете вимкнути Cake 2FA? Код 2FA більше не потрібен для доступу до гаманця та певних функцій.", - "disable": "Вимкнути", - "setup_2fa": "Налаштування Cake 2FA", - "verify_with_2fa": "Перевірте за допомогою Cake 2FA", - "totp_code": "Код TOTP", - "please_fill_totp": "Будь ласка, введіть 8-значний код, наявний на вашому іншому пристрої", - "totp_2fa_success": "Успіх! Cake 2FA увімкнено для цього гаманця. Пам’ятайте про збереження мнемоніки на випадок, якщо ви втратите доступ до гаманця.", - "totp_verification_success": "Перевірка успішна!", - "totp_2fa_failure": "Невірний код. Спробуйте інший код або створіть новий секретний ключ. Використовуйте сумісний додаток 2FA, який підтримує 8-значні коди та SHA512.", - "enter_totp_code": "Будь ласка, введіть код TOTP.", - "add_secret_code": "Або додайте цей секретний код до програми автентифікації", - "totp_secret_code": "Секретний код TOTP", - "setup_2fa_text": "Cake 2FA працює з використанням TOTP як другого фактора автентифікації.\n\nДля TOTP Cake 2FA потрібен SHA-512 і підтримка 8 цифр; це забезпечує підвищену безпеку. Додаткову інформацію та підтримувані програми можна знайти в посібнику.", - "setup_totp_recommended": "Налаштувати TOTP", - "disable_buy": "Вимкнути дію покупки", - "disable_sell": "Вимкнути дію продажу", - "auto_generate_subaddresses": "Автоматично генерувати підадреси", - "cake_2fa_preset": "Торт 2FA Preset", - "narrow": "вузькі", - "normal": "нормальний", - "aggressive": "Надто старанний", - "require_for_assessing_wallet": "Потрібен доступ до гаманця", - "require_for_sends_to_non_contacts": "Вимагати для надсилання неконтактним особам", - "require_for_sends_to_contacts": "Вимагати для надсилання контактам", - "require_for_sends_to_internal_wallets": "Вимагати надсилання на внутрішні гаманці", - "require_for_exchanges_to_internal_wallets": "Вимагати обміну на внутрішні гаманці", - "require_for_adding_contacts": "Потрібен для додавання контактів", - "require_for_creating_new_wallets": "Потрібно для створення нових гаманців", - "require_for_all_security_and_backup_settings": "Вимагати всіх налаштувань безпеки та резервного копіювання", - "available_balance_description": "Це сума, яку ви можете витратити, не включаючи невизначені кошти. Це може бути менше, ніж загальний баланс, якщо ви витратили кошти, які ще не підтверджені.", - "syncing_wallet_alert_title": "Ваш гаманець синхронізується", - "syncing_wallet_alert_content": "Ваш баланс та список транзакцій може бути неповним, доки вгорі не буде написано «СИНХРОНІЗОВАНО». Натисніть/торкніться, щоб дізнатися більше.", - "home_screen_settings": "Налаштування головного екрана", - "sort_by": "Сортувати за", - "search_add_token": "Пошук / Додати маркер", - "edit_token": "Редагувати маркер", - "warning": "УВАГА", - "add_token_warning": "Не редагуйте та не додавайте токени за вказівками шахраїв.\nЗавжди підтверджуйте адреси токенів у авторитетних джерелах!", - "add_token_disclaimer_check": "Я підтвердив адресу та інформацію щодо договору маркера, використовуючи авторитетне джерело. Додавання зловмисної або невірної інформації може призвести до втрати коштів.", - "token_contract_address": "Адреса договору маркера", - "token_name": "Назва токена, наприклад: Tether", - "token_symbol": "Символ маркера, наприклад: USDT", - "token_decimal": "Токен десятковий", - "field_required": "Це поле є обов'язковим", - "pin_at_top": "закріпити ${token} зверху", - "invalid_input": "Неправильні дані", - "fiat_balance": "Фіат Баланс", - "gross_balance": "Валовий баланс", - "alphabetical": "Алфавітний", - "generate_name": "Згенерувати назву", - "balance_page": "Сторінка балансу", - "share": "Поділіться", - "slidable": "Розсувний", - "monero_dark_theme": "Темна тема Monero", - "bitcoin_dark_theme": "Темна тема Bitcoin", - "bitcoin_light_theme": "Світла тема Bitcoin", - "high_contrast_theme": "Тема високої контрастності", - "matrix_green_dark_theme": "Зелена темна тема Matrix", - "monero_light_theme": "Легка тема Monero", - "manage_nodes": "Керуйте вузлами", - "etherscan_history": "Історія Etherscan", - "template_name": "Назва шаблону", - "change_rep": "Зміна представника", - "change_rep_message": "Ви впевнені, що хочете змінити представника?", - "unsupported_asset": "Ми не підтримуємо цю дію для цього ресурсу. Створіть або перейдіть на гаманець підтримуваного типу активів.", - "manage_pow_nodes": "Керуйте вузлами PoW", - "support_title_live_chat": "Жива підтримка", - "support_description_live_chat": "Безкоштовно і швидко! Навчені представники підтримки доступні для надання допомоги", - "support_title_guides": "Поклики для гаманців тортів", - "support_description_guides": "Документація та підтримка загальних питань", - "support_title_other_links": "Інші посилання на підтримку", - "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами", - "choose_derivation": "Виберіть деривацію гаманця", - "new_first_wallet_text": "Легко зберігайте свою криптовалюту в безпеці", - "select_destination": "Виберіть місце призначення для файлу резервної копії.", - "save_to_downloads": "Зберегти до завантажень", - "select_buy_provider_notice": "Виберіть постачальника купівлі вище. Ви можете пропустити цей екран, встановивши свого постачальника купівлі за замовчуванням у налаштуваннях додатків.", - "onramper_option_description": "Швидко купуйте криптовалюту з багатьма методами оплати. Доступний у більшості країн. Поширення та збори різняться.", - "default_buy_provider": "Постачальник покупки за замовчуванням", - "ask_each_time": "Запитайте кожен раз", - "buy_provider_unavailable": "В даний час постачальник недоступний.", - "signTransaction": "Підписати транзакцію", - "errorGettingCredentials": "Помилка: помилка під час отримання облікових даних", - "errorSigningTransaction": "Під час підписання транзакції сталася помилка", - "pairingInvalidEvent": "Недійсна подія сполучення", - "chains": "Ланцюги", - "methods": "методи", - "events": "Події", - "reject": "Відхиляти", - "approve": "Затвердити", - "expiresOn": "Термін дії закінчується", - "walletConnect": "WalletConnect", - "nullURIError": "URI нульовий", - "connectWalletPrompt": "Підключіть свій гаманець до WalletConnect, щоб здійснювати транзакції", - "newConnection": "Нове підключення", - "activeConnectionsPrompt": "Тут з’являться активні підключення", - "deleteConnectionConfirmationPrompt": "Ви впевнені, що хочете видалити з’єднання з", - "event": "Подія", - "successful": "Успішний", - "wouoldLikeToConnect": "хотів би підключитися", - "message": "повідомлення", - "do_not_have_enough_gas_asset": "У вас недостатньо ${currency}, щоб здійснити трансакцію з поточними умовами мережі блокчейн. Вам потрібно більше ${currency}, щоб сплатити комісію мережі блокчейн, навіть якщо ви надсилаєте інший актив.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Зачекайте, доки dApp завершить обробку.", - "copyWalletConnectLink": "Скопіюйте посилання WalletConnect із dApp і вставте сюди", - "enterWalletConnectURI": "Введіть URI WalletConnect", - "seed_key": "Насіннєвий ключ", - "enter_seed_phrase": "Введіть свою насіннєву фразу", - "change_rep_successful": "Успішно змінив представник", - "add_contact": "Додати контакт", - "exchange_provider_unsupported": "${providerName} більше не підтримується!", - "domain_looks_up": "Пошук доменів", - "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", - "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", - "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", - "order_by": "Сортувати за", - "creation_date": "Дата створення", - "group_by_type": "Група за типом", - "importNFTs": "Імпорт NFT", - "noNFTYet": "NFT ще немає", - "address": "Адреса", - "enterTokenID": "Введіть ідентифікатор токена", - "tokenID": "ID", - "name": "Ім'я", - "symbol": "символ", - "seed_phrase_length": "Довжина початкової фрази", - "unavailable_balance": "Недоступний баланс", - "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", - "unspent_change": "Зміна", - "tor_connection": "Підключення Tor", - "setup_warning_2fa_text": "Cake 2FA — друга аутентифікація для певних дій у гаманці. Це НЕ так безпечно, як холодне зберігання.\n\nЯкщо ви втратите доступ до своєї програми 2FA або ключів TOTP, ви втратите доступ до цього гаманця. Вам потрібно буде відновити свій гаманець з мнемоніки.\n\nСлужба підтримки Cake не зможе вам допомогти, якщо ви втратите доступ до 2FA або мнемонічних насадок.\nПеред використанням Cake 2FA рекомендуємо прочитати інструкцію.", - "scan_qr_on_device": "Відскануйте цей QR-код на іншому пристрої", - "how_to_use": "Як використовувати", - "seed_hex_form": "Насіння гаманця (шістнадцяткова форма)", - "seedtype": "Насіннєвий тип", - "seedtype_legacy": "Спадщина (25 слів)", - "seedtype_polyseed": "Полісей (16 слів)", - "seed_language_czech": "Чеський", - "seed_language_korean": "Корейський", - "ascending": "Висхід", - "descending": "Низхідний", - "dfx_option_description": "Купуйте криптовалюту за EUR і CHF. До 990 євро без додаткового KYC. Для роздрібних і корпоративних клієнтів у Європі", - "seed_language_chinese_traditional": "Китайський (традиційний)", - "polygonscan_history": "Історія PolygonScan", - "wallet_seed_legacy": "Спадець насіння гаманця", - "default_sell_provider": "Постачальник продажу за замовчуванням", - "select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.", - "custom_drag": "На замовлення (утримуйте та перетягується)", - "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)", - "use_testnet": "Використовуйте тестову мережу", - "receivable_balance": "Баланс дебіторської заборгованості", - "confirmed_tx": "Підтверджений", - "transaction_details_source_address": "Адреса джерела", - "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено.", - "contractName": "Назва контракту", - "contractSymbol": "Контракт символ", - "description": "опис", - "camera_consent": "Ваша камера використовуватиметься для зйомки зображення з метою ідентифікації ${provider}. Будь ласка, ознайомтеся з їхньою політикою конфіденційності, щоб дізнатися більше.", - "no_relays": "Без реле", - "choose_relay": "Будь ласка, виберіть реле для використання", - "no_relays_message": "Ми знайшли запис Nostr NIP-05 для цього користувача, але він не містить жодних реле. Будь ласка, попросіть одержувача додати реле до свого запису Nostr.", - "no_relay_on_domain": "Немає ретранслятора для домену користувача або ретранслятор недоступний. Будь ласка, виберіть реле для використання." - "zzzz": "ZZZZ" + "you_will_send": "Конвертувати з" } \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 352ec16d3..c92535ae5 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -708,6 +708,7 @@ "use_card_info_two": "رقوم کو امریکی ڈالر میں تبدیل کیا جاتا ہے جب پری پیڈ اکاؤنٹ میں رکھا جاتا ہے، ڈیجیٹل کرنسیوں میں نہیں۔", "use_ssl": "SSL استعمال کریں۔", "use_suggested": "تجویز کردہ استعمال کریں۔", + "use_testnet": "ٹیسٹ نیٹ استعمال کریں", "variable_pair_not_supported": "یہ متغیر جوڑا منتخب ایکسچینجز کے ساتھ تعاون یافتہ نہیں ہے۔", "verification": "تصدیق", "verify_with_2fa": "کیک 2FA سے تصدیق کریں۔", @@ -766,272 +767,5 @@ "you_now_have_debit_card": "اب آپ کے پاس ڈیبٹ کارڈ ہے۔", "you_pay": "تم ادا کرو", "you_will_get": "میں تبدیل کریں۔", - "you_will_send": "سے تبدیل کریں۔", - "yy": "YY", - "online": "آن لائن", - "offline": "آف لائن", - "gift_card_number": "گفٹ کارڈ نمبر", - "pin_number": "پن نمبر", - "total_saving": "کل بچت", - "last_30_days": "آخری 30 دن", - "avg_savings": "اوسط بچت", - "view_all": "سب دیکھیں", - "active_cards": "فعال کارڈز", - "delete_account": "کھاتہ مٹا دو", - "cards": "کارڈز", - "active": "فعال", - "redeemed": "چھڑایا", - "gift_card_balance_note": "باقی بیلنس والے گفٹ کارڈز یہاں ظاہر ہوں گے۔", - "gift_card_redeemed_note": "آپ نے جن گفٹ کارڈز کو بھنایا ہے وہ یہاں ظاہر ہوں گے۔", - "logout": "لاگ آوٹ", - "add_tip": "ٹپ شامل کریں۔", - "percentageOf": "${amount} کا", - "is_percentage": "ہے", - "search_category": "زمرہ تلاش کریں۔", - "mark_as_redeemed": "ریڈیم کے بطور نشان زد کریں۔", - "more_options": "مزید زرائے", - "awaiting_payment_confirmation": "ادائیگی کی تصدیق کے منتظر", - "transaction_sent_notice": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے، تو بلاک ایکسپلورر اور اپنا ای میل چیک کریں۔", - "agree": "متفق", - "in_store": "اسٹور میں", - "generating_gift_card": "گفٹ کارڈ تیار کرنا", - "payment_was_received": "آپ کی ادائیگی موصول ہو گئی۔", - "proceed_after_one_minute": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے تو اپنا ای میل چیک کریں۔", - "order_id": "ID آرڈر کریں۔", - "gift_card_is_generated": "گفٹ کارڈ بنتا ہے۔", - "open_gift_card": "گفٹ کارڈ کھولیں۔", - "contact_support": "سپورٹ سے رابطہ کریں۔", - "gift_cards_unavailable": "گفٹ کارڈز اس وقت صرف Monero، Bitcoin اور Litecoin کے ساتھ خریداری کے لیے دستیاب ہیں۔", - "introducing_cake_pay": "Cake پے کا تعارف!", - "cake_pay_learn_more": "ایپ میں فوری طور پر گفٹ کارڈز خریدیں اور بھنائیں!\\nمزید جاننے کے لیے بائیں سے دائیں سوائپ کریں۔", - "automatic": "خودکار", - "fixed_pair_not_supported": "یہ مقررہ جوڑا منتخب کردہ تبادلے کے ساتھ تعاون یافتہ نہیں ہے۔", - "variable_pair_not_supported": "یہ متغیر جوڑا منتخب ایکسچینجز کے ساتھ تعاون یافتہ نہیں ہے۔", - "none_of_selected_providers_can_exchange": "منتخب فراہم کنندگان میں سے کوئی بھی یہ تبادلہ نہیں کر سکتا", - "choose_one": "ایک کا انتخاب کریں", - "choose_from_available_options": "دستیاب اختیارات میں سے انتخاب کریں:", - "custom_redeem_amount": "حسب ضرورت چھڑانے کی رقم", - "add_custom_redemption": "حسب ضرورت چھٹکارا شامل کریں۔", - "remaining": "باقی", - "delete_wallet": "پرس کو حذف کریں۔", - "delete_wallet_confirm_message": "کیا آپ واقعی ${wallet_name} والیٹ کو حذف کرنا چاہتے ہیں؟", - "low_fee": "کم فیس", - "low_fee_alert": "آپ فی الحال کم نیٹ ورک فیس کی ترجیح استعمال کر رہے ہیں۔ یہ طویل انتظار، مختلف شرحوں، یا منسوخ شدہ تجارتوں کا سبب بن سکتا ہے۔ ہم بہتر تجربہ کے لیے زیادہ فیس مقرر کرنے کی تجویز کرتے ہیں۔", - "ignor": "نظر انداز کرنا", - "use_suggested": "تجویز کردہ استعمال کریں۔", - "do_not_share_warning_text": "سپورٹ سمیت کسی اور کے ساتھ ان کا اشتراک نہ کریں۔\\n\\nآپ کے فنڈز چوری ہو سکتے ہیں اور ہو جائیں گے!", - "help": "مدد", - "all_transactions": "تمام لین دین", - "all_trades": "تمام تجارت", - "connection_sync": "کنکشن اور مطابقت پذیری", - "security_and_backup": "سیکیورٹی اور بیک اپ", - "create_backup": "بیک اپ بنائیں", - "privacy_settings": "رازداری کی ترتیبات", - "privacy": "رازداری", - "display_settings": "ڈسپلے کی ترتیبات", - "other_settings": "دیگر ترتیبات", - "require_pin_after": "اس کے بعد PIN کی ضرورت ہے۔", - "always": "ہمیشہ", - "minutes_to_pin_code": "${minute} منٹ", - "disable_exchange": "تبادلے کو غیر فعال کریں۔", - "advanced_settings": "اعلی درجے کی ترتیبات", - "settings_can_be_changed_later": "ان ترتیبات کو بعد میں ایپ کی ترتیبات میں تبدیل کیا جا سکتا ہے۔", - "add_custom_node": "نیا کسٹم نوڈ شامل کریں۔", - "disable_fiat": "فیاٹ کو غیر فعال کریں۔", - "fiat_api": "Fiat API", - "disabled": "معذور", - "enabled": "فعال", - "tor_only": "صرف Tor", - "unmatched_currencies": "آپ کے پرس کی موجودہ کرنسی اسکین شدہ QR سے مماثل نہیں ہے۔", - "orbot_running_alert": "براہ کرم یقینی بنائیں کہ اس نوڈ سے منسلک ہونے سے پہلے Orbot چل رہا ہے۔", - "contact_list_contacts": "رابطے", - "contact_list_wallets": "میرے بٹوے", - "send_to_this_address": "اس پتے پر ${currency} ${tag} بھیجیں۔", - "arrive_in_this_address": "${currency} ${tag}اس پتے پر پہنچے گا۔", - "do_not_send": "مت بھیجیں۔", - "error_dialog_content": "افوہ، ہمیں کچھ خرابی ملی۔\n\nایپلی کیشن کو بہتر بنانے کے لیے براہ کرم کریش رپورٹ ہماری سپورٹ ٹیم کو بھیجیں۔", - "decimal_places_error": "بہت زیادہ اعشاریہ جگہیں۔", - "edit_node": "نوڈ میں ترمیم کریں۔", - "invoice_details": "رسید کی تفصیلات", - "donation_link_details": "عطیہ کے لنک کی تفصیلات", - "anonpay_description": "${type} بنائیں۔ وصول کنندہ کسی بھی تعاون یافتہ کرپٹو کرنسی کے ساتھ ${method} کرسکتا ہے، اور آپ کو اس بٹوے میں فنڈز موصول ہوں گے۔", - "create_invoice": "انوائس بنائیں", - "create_donation_link": "عطیہ کا لنک بنائیں", - "optional_email_hint": "اختیاری وصول کنندہ کی اطلاع کا ای میل", - "optional_description": "اختیاری تفصیل", - "optional_name": "اختیاری وصول کنندہ کا نام", - "clearnet_link": "کلیرنیٹ لنک", - "onion_link": "پیاز کا لنک", - "sell_monero_com_alert_content": "Monero فروخت کرنا ابھی تک تعاون یافتہ نہیں ہے۔", - "error_text_input_below_minimum_limit": "رقم کم از کم سے کم ہے۔", - "error_text_input_above_maximum_limit": "رقم زیادہ سے زیادہ سے زیادہ ہے۔", - "show_market_place": "بازار دکھائیں۔", - "prevent_screenshots": "اسکرین شاٹس اور اسکرین ریکارڈنگ کو روکیں۔", - "profile": "پروفائل", - "close": "بند کریں", - "modify_2fa": "کیک 2FA میں ترمیم کریں۔", - "disable_cake_2fa": "کیک 2FA کو غیر فعال کریں۔", - "question_to_disable_2fa": "کیا آپ واقعی کیک 2FA کو غیر فعال کرنا چاہتے ہیں؟ بٹوے اور بعض افعال تک رسائی کے لیے اب 2FA کوڈ کی ضرورت نہیں ہوگی۔", - "disable": "غیر فعال کریں۔", - "setup_2fa": "سیٹ اپ کیک 2FA", - "verify_with_2fa": "کیک 2FA سے تصدیق کریں۔", - "totp_code": "TOTP کوڈ", - "please_fill_totp": "براہ کرم اپنے دوسرے آلے پر موجود 8 ہندسوں کا کوڈ پُر کریں۔", - "totp_2fa_success": "کامیابی! کیک 2FA اس بٹوے کے لیے فعال ہے۔ بٹوے تک رسائی سے محروم ہونے کی صورت میں اپنے یادداشت کے بیج کو محفوظ کرنا یاد رکھیں۔", - "totp_verification_success": "توثیق کامیاب!", - "totp_2fa_failure": "غلط کوڈ. براہ کرم ایک مختلف کوڈ آزمائیں یا ایک نئی خفیہ کلید بنائیں۔ ایک ہم آہنگ 2FA ایپ استعمال کریں جو 8 ہندسوں کے کوڈز اور SHA512 کو سپورٹ کرتی ہو۔", - "enter_totp_code": "براہ کرم TOTP کوڈ درج کریں۔", - "add_secret_code": " ۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮟﯿﻣ ﭗﯾﺍ ﮦﺪﻨﻨﮐ ﻖﯾﺪﺼﺗ ﻮﮐ ﮈﻮﮐ ﮧﯿﻔﺧ ﺱﺍ ،ﺎﯾ", - "totp_secret_code": "TOTP خفیہ کوڈ", - "setup_2fa_text": " ۔ﮯﮨ ﺎﺗﺮﮐ ﻡﺎﮐ ﮯﺋﻮﮨ ﮯﺗﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﺎﮐ TOTP ﺮﭘ ﺭﻮﻃ ﮯﮐ ﺮﺼﻨﻋ ﯽﻘﯾﺪﺼﺗ ﮮﺮﺳﻭﺩ 2FA ﮏﯿﮐ", - "setup_totp_recommended": "TOTP ۔ﮟﯾﺮﮐ ﭖﺍ ﭧﯿﺳ", - "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", - "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔", - "cake_2fa_preset": "کیک 2FA پیش سیٹ", - "narrow": "تنگ", - "normal": "نارمل", - "aggressive": "حد سے زیادہ پرجوش", - "require_for_assessing_wallet": "بٹوے تک رسائی کے لیے درکار ہے۔", - "require_for_sends_to_non_contacts": "غیر رابطوں کو بھیجنے کی ضرورت ہے۔", - "require_for_sends_to_contacts": "رابطوں کو بھیجنے کی ضرورت ہے۔", - "require_for_sends_to_internal_wallets": "اندرونی بٹوے پر بھیجنے کے لیے درکار ہے۔", - "require_for_exchanges_to_internal_wallets": "اندرونی بٹوے میں تبادلے کی ضرورت ہے۔", - "require_for_adding_contacts": "رابطوں کو شامل کرنے کی ضرورت ہے۔", - "require_for_creating_new_wallets": "نئے بٹوے بنانے کی ضرورت ہے۔", - "require_for_all_security_and_backup_settings": "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", - "available_balance_description": "”دستیاب بیلنس” یا ”تصدیق شدہ بیلنس” وہ فنڈز ہیں جو فوری طور پر خرچ کیے جا سکتے ہیں۔ اگر فنڈز کم بیلنس میں ظاہر ہوتے ہیں لیکن اوپر کے بیلنس میں نہیں، تو آپ کو مزید نیٹ ورک کی تصدیقات حاصل کرنے کے لیے آنے والے فنڈز کے لیے چند منٹ انتظار کرنا چاہیے۔ مزید تصدیق حاصل کرنے کے بعد، وہ قابل خرچ ہوں گے۔", - "syncing_wallet_alert_title": "آپ کا بٹوہ مطابقت پذیر ہو رہا ہے۔", - "syncing_wallet_alert_content": "آپ کے بیلنس اور لین دین کی فہرست اس وقت تک مکمل نہیں ہو سکتی جب تک کہ یہ سب سے اوپر \"SYNCRONIZED\" نہ کہے۔ مزید جاننے کے لیے کلک/تھپتھپائیں۔", - "home_screen_settings": "ہوم اسکرین کی ترتیبات", - "sort_by": "ترتیب دیں", - "search_add_token": "تلاش کریں / ٹوکن شامل کریں۔", - "edit_token": "ٹوکن میں ترمیم کریں۔", - "warning": "وارننگ", - "add_token_warning": "سکیمرز کی ہدایت کے مطابق ٹوکن میں ترمیم یا اضافہ نہ کریں۔\nہمیشہ معتبر ذرائع سے ٹوکن پتوں کی تصدیق کریں!", - "add_token_disclaimer_check": "میں نے ایک معتبر ذریعہ کا استعمال کرتے ہوئے ٹوکن کنٹریکٹ ایڈریس اور معلومات کی تصدیق کی ہے۔ بدنیتی پر مبنی یا غلط معلومات شامل کرنے کے نتیجے میں فنڈز ضائع ہو سکتے ہیں۔", - "token_contract_address": "ٹوکن کنٹریکٹ ایڈریس", - "token_name": "ٹوکن کا نام جیسے: Tether", - "token_symbol": "ٹوکن کی علامت جیسے: USDT", - "token_decimal": "ٹوکن اعشاریہ", - "field_required": "اس کو پر کرنا ضروری ہے", - "pin_at_top": "اوپر ${token} کو پن کریں۔", - "invalid_input": "غلط ان پٹ", - "fiat_balance": "فیاٹ بیلنس", - "gross_balance": "مجموعی بیلنس", - "alphabetical": "حروف تہجی کے مطابق", - "generate_name": "نام پیدا کریں۔", - "balance_page": "بیلنس صفحہ", - "share": "بانٹیں", - "slidable": "سلائیڈ ایبل", - "monero_dark_theme": "مونیرو ڈارک تھیم", - "bitcoin_dark_theme": "بٹ کوائن ڈارک تھیم", - "bitcoin_light_theme": "بٹ کوائن لائٹ تھیم", - "high_contrast_theme": "ہائی کنٹراسٹ تھیم", - "matrix_green_dark_theme": "میٹرکس گرین ڈارک تھیم", - "monero_light_theme": "مونیرو لائٹ تھیم", - "manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", - "etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ", - "template_name": "ٹیمپلیٹ کا نام", - "change_rep": "۔ﮟﯾﺮﮐ ﻞﯾﺪﺒﺗ ﮦﺪﻨﺋﺎﻤﻧ", - "change_rep_message": "؟ﮟﯿﮨ ﮯﺘﮨﺎﭼ ﺎﻧﺮﮐ ﻞﯾﺪﺒﺗ ﻮﮐ ﮞﻭﺪﻨﺋﺎﻤﻧ ﯽﻌﻗﺍﻭ ﭖﺁ ﺎﯿﮐ", - "unsupported_asset": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﺱﺮﭘ ﺎﮐ ﻢﺴﻗ ﯽﮐ ﮧﺛﺎﺛﺍ ﮧﺘﻓﺎﯾ ﻥﻭﺎﻌﺗ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮟﯿﮨ ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﺖﯾﺎﻤﺣ ﯽﮐ ﯽﺋﺍﻭﺭﺭﺎﮐ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﮧﺛﺎﺛﺍ ﺱﺍ ﻢﮨ", - "manage_pow_nodes": "PoW ۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", - "support_title_live_chat": "براہ راست مدد", - "support_description_live_chat": "مفت اور تیز! تربیت یافتہ معاون نمائندے مدد کے لئے دستیاب ہیں", - "support_title_guides": "کیک پرس گائڈز", - "support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد", - "support_title_other_links": "دوسرے سپورٹ لنکس", - "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں", - "choose_derivation": "پرس سے ماخوذ منتخب کریں", - "new_first_wallet_text": "آسانی سے اپنے cryptocurrency محفوظ رکھیں", - "select_destination": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﻝﺰﻨﻣ ﮯﯿﻟ ﮯﮐ ﻞﺋﺎﻓ ﭖﺍ ﮏﯿﺑ ﻡﺮﮐ ﮦﺍﺮﺑ", - "auto_generate_subaddresses": "آٹو سب ایڈریس تیار کرتا ہے", - "save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ", - "select_buy_provider_notice": "اوپر خریدنے والا خریدنے والا منتخب کریں۔ آپ ایپ کی ترتیبات میں اپنے پہلے سے طے شدہ خریدنے والے کو ترتیب دے کر اس اسکرین کو چھوڑ سکتے ہیں۔", - "onramper_option_description": "ادائیگی کے بہت سے طریقوں سے جلدی سے کرپٹو خریدیں۔ زیادہ تر ممالک میں دستیاب ہے۔ پھیلاؤ اور فیس مختلف ہوتی ہے۔", - "default_buy_provider": "پہلے سے طے شدہ خریدنے والا", - "ask_each_time": "ہر بار پوچھیں", - "buy_provider_unavailable": "فراہم کنندہ فی الحال دستیاب نہیں ہے۔", - "signTransaction": "۔ﮟﯾﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ", - "errorGettingCredentials": "۔ﯽﺑﺍﺮﺧ ﮟﯿﻣ ﮯﻧﺮﮐ ﻞﺻﺎﺣ ﺩﺎﻨﺳﺍ :ﻡﺎﮐﺎﻧ", - "errorSigningTransaction": "۔ﮯﮨ ﯽﺌﮔﺁ ﺶﯿﭘ ﯽﺑﺍﺮﺧ ﮏﯾﺍ ﺖﻗﻭ ﮯﺗﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ", - "pairingInvalidEvent": "ﭧﻧﻮﯾﺍ ﻂﻠﻏ ﺎﻧﺎﻨﺑ ﺍﮌﻮﺟ", - "chains": "ﮟﯾﺮﯿﺠﻧﺯ", - "methods": "ﮯﻘﯾﺮﻃ", - "events": "ﺕﺎﺒﯾﺮﻘﺗ", - "reject": "ﺎﻧﺮﮐ ﺩﺭ", - "approve": "ﻭﺮﮐ ﺭﻮﻈﻨﻣ", - "expiresOn": "ﺩﺎﻌﯿﻣ ﯽﻣﺎﺘﺘﺧﺍ", - "walletConnect": "WalletConnect", - "nullURIError": "URI ۔ﮯﮨ ﻡﺪﻌﻟﺎﮐ", - "connectWalletPrompt": "۔ﮟﯾﮌﻮﺟ ﮫﺗﺎﺳ ﮯﮐ WalletConnect ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻦﯾﺩ ﻦﯿﻟ", - "newConnection": "ﻦﺸﮑﻨﮐ ﺎﯿﻧ", - "activeConnectionsPrompt": "۔ﮯﮔ ﮞﻮﮨ ﺮﮨﺎﻇ ﮞﺎﮩﯾ ﺰﻨﺸﮑﻨﮐ ﻝﺎﻌﻓ", - "deleteConnectionConfirmationPrompt": "۔ﮟﯿﮨ ﮯﺘﮨﺎﭼ ﺎﻧﺮﮐ ﻑﺬﺣ ﻮﮐ ﻦﺸﮑﻨﮐ ﭖﺁ ﮧﮐ ﮯﮨ ﻦﯿﻘﯾ ﻮﮐ ﭖﺁ ﺎﯿﮐ", - "event": "ﺐﯾﺮﻘﺗ", - "successful": "ﺏﺎﯿﻣﺎﮐ", - "wouoldLikeToConnect": "؟ﮯﮔ ﮟﯿﮨﺎﭼ ﺎﻧﮍﺟ", - "message": "ﻡﺎﻐﯿﭘ", - "do_not_have_enough_gas_asset": "آپ کے پاس موجودہ بلاکچین نیٹ ورک کی شرائط کے ساتھ لین دین کرنے کے لیے کافی ${currency} نہیں ہے۔ آپ کو بلاکچین نیٹ ورک کی فیس ادا کرنے کے لیے مزید ${currency} کی ضرورت ہے، چاہے آپ کوئی مختلف اثاثہ بھیج رہے ہوں۔", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﮓﻨﺴﯿﺳﻭﺮﭘ ﮯﮐ dApp ﻡﺮﮐ ﮦﺍﺮﺑ", - "copyWalletConnectLink": "dApp ﮯﺳ WalletConnect ۔ﮟﯾﺮﮐ ﭧﺴﯿﭘ ﮞﺎﮩﯾ ﺭﻭﺍ ﮟﯾﺮﮐ ﯽﭘﺎﮐ ﻮﮐ ﮏﻨﻟ", - "enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ", - "seed_key": "بیج کی کلید", - "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", - "change_rep_successful": "نمائندہ کو کامیابی کے ساتھ تبدیل کیا", - "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", - "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!", - "domain_looks_up": "ڈومین تلاش کرنا", - "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", - "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", - "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", - "order_by": "آرڈر بذریعہ", - "creation_date": "بنانے کی تاریخ", - "group_by_type": "قسم کے لحاظ سے گروپ", - "importNFTs": "NFTs ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", - "noNFTYet": "۔ﮟﯿﮨ ﮟﯿﮩﻧ NFTs ﯽﺋﻮﮐ ﮏﺗ ﯽﮭﺑﺍ", - "address": "ﮧﺘﭘ", - "enterTokenID": " ۔ﮟﯾﺮﮐ ﺝﺭﺩ ID ﻦﮐﻮﭨ", - "tokenID": "ID", - "name": "ﻡﺎﻧ", - "symbol": "ﺖﻣﻼﻋ", - "seed_phrase_length": "ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", - "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", - "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", - "unspent_change": "تبدیل کریں", - "setup_warning_2fa_text": " ۔ﯽﮔﻮﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻧﺮﮐ ﻝﺎﺤﺑ ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﺳ ﺞﯿﺑ ﮯﮐ ﺖﺷﺍﺩﺩﺎﯾ ﻮﮐ ﭖﺁ", - "scan_qr_on_device": " ۔ﮟﯾﺮﮐ ﻦﯿﮑﺳﺍ ﺮﭘ ﺲﺋﺍﻮﯾﮈ ﺭﻭﺍ ﯽﺴﮐ ﻮﮐ ﮈﻮﮐ QR ﺱﺍ", - "how_to_use": " ﮧﻘﯾﺮﻃ ﺎﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ", - "seed_hex_form": "پرس بیج (ہیکس فارم)", - "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ", - "seedtype": "سیڈ ٹائپ", - "seedtype_legacy": "میراث (25 الفاظ)", - "seedtype_polyseed": "پالیسیڈ (16 الفاظ)", - "seed_language_czech": "چیک", - "seed_language_korean": "کورین", - "seed_language_chinese_traditional": "چینی (روایتی)", - "ascending": "چڑھنے", - "descending": "اترتے ہوئے", - "dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ", - "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ", - "wallet_seed_legacy": "میراثی پرس کا بیج", - "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", - "select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ", - "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", - "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ", - "use_testnet": "ٹیسٹ نیٹ استعمال کریں", - "receivable_balance": "قابل وصول توازن", - "confirmed_tx": "تصدیق", - "transaction_details_source_address": "ماخذ ایڈریس", - "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ", - "contractName": "ﻡﺎﻧ ﺎﮐ ﮦﺪﮨﺎﻌﻣ", - "contractSymbol": "ﺖﻣﻼﻋ ﯽﮐ ﮦﺪﮨﺎﻌﻣ", - "description": "ﻞﯿﺼﻔﺗ", - "camera_consent": "۔ﮟﯿﮭﮑﯾﺩ ﯽﺴﯿﻟﺎﭘ ﯽﺴﯾﻮﯿﺋﺍﺮﭘ ﯽﮐ ﻥﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﺕﻼ${provider}ﯿﺼﻔﺗ ۔ﺎﮔ ﮯﺋﺎﺟ ﺎﯿﮐ ﻝﺎﻤﻌﺘﺳﺍ ﮯﯿﻟ", - "no_relays": "۔ﮟﯿﮩﻧ ﮯﻠﯾﺭ ﯽﺋﻮﮐ", - "choose_relay": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ", - "no_relays_message": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮯﻠﯾﺭ ﮟﯿﻣ ﮈﺭﺎﮑﯾﺭ ﺮﭩﺳﻮﻧ ﮯﻨﭘﺍ ﮦﻭ ﮧﮐ ﮟﯾﺩ ﺖﯾﺍﺪﮨ ﻮﮐ ﮦﺪﻨﻨﮐ ﻝﻮﺻﻭ ﻡﺮﮐ ﮦﺍﺮﺑ ۔", - "no_relay_on_domain": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮯﮨ ﮟﯿﮩﻧ ﺏﺎﯿﺘﺳﺩ ﮯﻠﯾﺭ ﺎﯾ ﮯﮨ ﮟ" - "zzzz": "زیڈز" + "you_will_send": "سے تبدیل کریں۔" } \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 5a4e8fb46..a3607a4e2 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -712,6 +712,7 @@ "use_card_info_two": "A pààrọ̀ owó sí owó Amẹ́ríkà tó bá wà nínú àkanti t'á ti fikún tẹ́lẹ̀tẹ́lẹ̀. A kò kó owó náà nínú owó ayélujára.", "use_ssl": "Lo SSL", "use_suggested": "Lo àbá", + "use_testnet": "Lo tele", "variable_pair_not_supported": "A kì í ṣe k'á fi àwọn ilé pàṣípààrọ̀ yìí ṣe pàṣípààrọ̀ irú owó méji yìí", "verification": "Ìjẹ́rìísí", "verify_with_2fa": "Ṣeẹda pẹlu Cake 2FA", @@ -768,277 +769,5 @@ "you_now_have_debit_card": "Ẹ ni káàdì ìrajà lọ́wọ́lọ́wọ́", "you_pay": "Ẹ sàn", "you_will_get": "Ṣe pàṣípààrọ̀ sí", - "you_will_send": "Ṣe pàṣípààrọ̀ láti", - "yy": "Ọd", - "online": "Lórí ayélujára", - "offline": "kò wà lórí ayélujára", - "gift_card_number": "Òǹkà káàdì ìrajì", - "pin_number": "Òǹkà ìdánimọ̀ àdáni", - "total_saving": "Owó t'ẹ́ ti pamọ́", - "last_30_days": "Ọ̀jọ̀ mọ́gbọ̀n tó kọjà", - "avg_savings": "Ìpamọ́ l’óòrèkóòrè", - "view_all": "Wo gbogbo nǹkan kan", - "active_cards": "Àwọn káàdì títàn", - "delete_account": "Pa ìṣàmúlò", - "cards": "Àwọn káàdì", - "active": "Ó títàn", - "redeemed": "Ó lílò", - "gift_card_balance_note": "Àwọn káàdì ìrajà t'á lò nínú irú kan ìtajà tíwọn ṣì ní owó máa fihàn ḿbí", - "gift_card_redeemed_note": "Àwọn káàdì ìrajà t'á lò nínú irú kan ìtajà t'ẹ́ ti lò máa fihàn ḿbí", - "logout": "Jáde", - "add_tip": "Fún owó àfikún", - "percentageOf": "láti ${amount}", - "is_percentage": "jẹ́", - "search_category": "Wá nínú ẹgbẹ́", - "mark_as_redeemed": "Fún orúkọ lílò", - "more_options": "Ìyàn àfikún", - "awaiting_payment_confirmation": "À ń dúró de ìjẹ́rìísí àránṣẹ́", - "transaction_sent_notice": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ olùṣèwádìí àkójọpọ̀ àti ímeèlì yín wò.", - "agree": "Jọ rò", - "in_store": "A níyí", - "generating_gift_card": "À ń dá káàdì ìrajà t'á lò nínú irú kan ìtajà", - "payment_was_received": "Àránṣẹ́ yín ti dé.", - "proceed_after_one_minute": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ ímeèlì yín wò.", - "order_id": "Àmì ìdánimọ̀ ti ìbéèrè", - "gift_card_is_generated": "A ti dá káàdí ìrajà t'á lò nínú irú kan ìtajà", - "open_gift_card": "Ṣí káàdí ìrajà t'á lò nínú irú kan ìtajà", - "contact_support": "Bá ìranlọ́wọ́ sọ̀rọ̀", - "gift_cards_unavailable": "A lè fi Monero, Bitcoin, àti Litecoin nìkan ra káàdí ìrajà t'á lò nínú irú kan ìtajà lọ́wọ́lọ́wọ́", - "introducing_cake_pay": "Ẹ bá Cake Pay!", - "cake_pay_learn_more": "Láìpẹ́ ra àti lo àwọn káàdí ìrajà t'á lò nínú irú kan ìtajà nínú áàpù!\nẸ tẹ̀ òsì de ọ̀tún láti kọ́ jù.", - "automatic": "Ó máa ń ṣàdédé", - "fixed_pair_not_supported": "A kì í ṣe k'á fi àwọn ilé pàṣípààrọ̀ yìí ṣe pàṣípààrọ̀ irú owó méji yìí", - "variable_pair_not_supported": "A kì í ṣe k'á fi àwọn ilé pàṣípààrọ̀ yìí ṣe pàṣípààrọ̀ irú owó méji yìí", - "none_of_selected_providers_can_exchange": "Àwọn ilé pàṣípààrọ̀ yíyàn kò lè ṣe pàṣípààrọ̀ yìí", - "choose_one": "Ẹ yàn kan", - "choose_from_available_options": "Ẹ yàn láti àwọn ìyàn yìí:", - "custom_redeem_amount": "Iye owó l'á máa ná", - "add_custom_redemption": "Tẹ̀ iye owó t'ẹ́ fẹ́ ná", - "remaining": "ìyókù", - "delete_wallet": "Pa àpamọ́wọ́", - "delete_wallet_confirm_message": "Ṣó dá ẹ lójú pé ẹ fẹ́ pa àpamọ́wọ́ ${wallet_name}?", - "low_fee": "Owó àfikún kékeré", - "low_fee_alert": "Ẹ ń fi owó àfikún kékeré fún àwọn àránṣẹ́ yín lágbára. Eleyìí lè pẹ́ gba àránṣẹ́ yín. Ó sì lè dá àwọn iye mìíràn t'á ṣẹ́ owó sí. Ó sì lè pa àwọn pàṣípààrọ̀. A dábàá pé k'ẹ́ lo owó àfikún títobi láti ṣe àṣejèrè.", - "ignor": "Ṣàìfiyèsí", - "use_suggested": "Lo àbá", - "do_not_share_warning_text": "Ẹ kò pín wọnyìí sí ẹnikẹ́ni. Ẹ sì kò pin wọnyìí sí ìranlọ́wọ́. Ẹnikẹ́ni lè jí owó yín! Wọ́n máa jí owó yín!", - "help": "ìranlọ́wọ́", - "all_transactions": "Gbogbo àwọn àránṣẹ́", - "all_trades": "Gbogbo àwọn pàṣípààrọ̀", - "connection_sync": "Ìkànpọ̀ àti ìbádọ́gba", - "security_and_backup": "Ìṣọ́ àti ẹ̀dà nípamọ́", - "create_backup": "Ṣẹ̀dà nípamọ́", - "privacy_settings": "Ààtò àdáni", - "privacy": "Ìdáwà", - "display_settings": "Fihàn àwọn ààtò", - "other_settings": "Àwọn ààtò mìíràn", - "require_pin_after": "Ẹ nílò òǹkà ìdánimọ̀ àdáni láàárín", - "always": "Ní gbogbo àwọn ìgbà", - "minutes_to_pin_code": "${minute} ìṣẹ́jú", - "disable_exchange": "Pa ilé pàṣípààrọ̀", - "advanced_settings": "Awọn eto ilọsiwaju", - "settings_can_be_changed_later": "Ẹ lè pààrọ̀ àwọn ààtò yìí nínú ààtò áàpù t’ó bá yá", - "add_custom_node": "Fikún apẹka títun t'ẹ́ pààrọ̀", - "disable_fiat": "Pa owó tí ìjọba pàṣẹ wa lò", - "fiat_api": "Ojú ètò áàpù owó tí ìjọba pàṣẹ wa lò", - "disabled": "Wọ́n tí a ti pa", - "enabled": "Wọ́n tíwọn ti tan", - "tor_only": "Tor nìkan", - "unmatched_currencies": "Irú owó ti àpamọ́wọ́ yín kì í ṣe irú ti yíya àmì ìlujá", - "contact_list_contacts": "Àwọn olùbásọ̀rọ̀", - "contact_list_wallets": "Àwọn àpamọ́wọ́ mi", - "bitcoin_payments_require_1_confirmation": "Àwọn àránṣẹ́ Bitcoin nílò ìjẹ́rìísí kan. Ó lè lo ìṣéjú ogun tàbí ìṣéjú jù. A dúpẹ́ fún sùúrù yín! Ẹ máa gba ímeèlì t'ó bá jẹ́rìísí àránṣẹ́ náà.", - "send_to_this_address": "Ẹ fi ${currency} ${tag}ránṣẹ́ sí àdírẹ́sì yìí", - "arrive_in_this_address": "${currency} ${tag} máa dé sí àdírẹ́sì yìí", - "do_not_send": "Ẹ kò ránṣ", - "error_dialog_content": "Àṣìṣe ti dé.\n\nẸ jọ̀wọ́, fi àkọsílẹ̀ àṣìṣe ránṣẹ́ sí ẹgbẹ́ ìranlọ́wọ́ wa kí áàpù wa bá túbọ̀ dára.", - "cold_or_recover_wallet": "Fi owo aisan tabi yiyewo owo iwe iwe", - "please_wait": "Jọwọ saa", - "sweeping_wallet": "Fi owo iwe iwe wofo", - "sweeping_wallet_alert": "Yio kọja pada si ikan yii. Kì yoo daadaa leede yii tabi owo ti o ti fi se iwe iwe naa yoo gbe.", - "invoice_details": "Iru awọn ẹya ọrọ", - "donation_link_details": "Iru awọn ẹya ọrọ ti o funni", - "anonpay_description": "Ṣe akọkọ ${type}. Awọn alabara le ${method} pẹlu eyikeyi iwo ise ati owo yoo wọle si iwe iwe yii.", - "create_invoice": "Ṣe iwe iwe", - "create_donation_link": "Ṣe kọọkan alabara asopọ", - "optional_email_hint": "Ṣeto imọ-ẹrọ iye fun owo ti o gbọdọjọ", - "optional_description": "Ṣeto ẹru iye", - "optional_name": "Ṣeto orukọ ti o ni", - "clearnet_link": "Kọja ilọ oke", - "onion_link": "Kọja ilọ alubosa", - "decimal_places_error": "Oọ̀rọ̀ ayipada ti o wa ni o dara julọ", - "edit_node": "Tun awọn ọwọnrin ṣiṣe", - "settings": "Awọn aseṣe", - "sell_monero_com_alert_content": "Kọ ju lọwọ Monero ko ṣe ni ibamu", - "error_text_input_below_minimum_limit": "Iye jọwọ ni o kere ti o wọle diẹ", - "error_text_input_above_maximum_limit": "Iye jọwọ ni o yẹ diẹ ti o wọle diẹ", - "show_market_place": "Wa Sopọ Pataki", - "prevent_screenshots": "Pese asapọ ti awọn ẹrọ eto aṣa", - "profile": "profaili", - "close": "sunmo", - "modify_2fa": "Fi iṣiro 2FA sii Cake", - "disable_cake_2fa": "Ko 2FA Cake sii", - "question_to_disable_2fa": "Ṣe o wa daadaa pe o fẹ ko 2FA Cake? Ko si itumọ ti a yoo nilo lati ranse si iwe iwe naa ati eyikeyi iṣẹ ti o ni.", - "disable": "Ko si", - "setup_2fa": "Ṣeto Cake 2FA", - "verify_with_2fa": "Ṣeẹda pẹlu Cake 2FA", - "totp_code": "Koodu TOTP", - "please_fill_totp": "Jọwọ bọ ti ẹrọ ti o wọle ni 8-digits ti o wa ni eto miiran re", - "totp_2fa_success": "Pelu ogo! Cake 2FA ti fi sii lori iwe iwe yii. Tọ, mọ iye ẹrọ miiran akojọrọ jẹki o kọ ipin eto.", - "totp_verification_success": "Ìbẹrẹ dọkita!", - "totp_2fa_failure": "Koodu ti o daju ko ri. Jọwọ jẹ koodu miiran tabi ṣiṣẹ iwe kiakia. Lo fun 2FA eto ti o ba ṣe ni jẹ 2FA ti o gba idaniloju 8-digits ati SHA512.", - "enter_totp_code": "Jọwọ pọ koodu TOTP.", - "add_secret_code": "Tabi, ṣafikun koodu aṣiri yii si ohun elo onijeri kan", - "totp_secret_code": "Koodu iye TOTP", - "setup_2fa_text": "Akara oyinbo 2FA ṣiṣẹ ni lilo TOTP bi ifosiwewe ijẹrisi keji.\n\nAkara oyinbo 2FA's TOTP nilo SHA-512 ati atilẹyin oni-nọmba 8; eyi pese aabo ti o pọ sii. Alaye diẹ sii ati awọn ohun elo atilẹyin ni a le rii ninu itọsọna naa.", - "setup_totp_recommended": "Ṣeto TOTP", - "disable_buy": "Ko iṣọrọ ọja", - "disable_sell": "Ko iṣọrọ iṣọrọ", - "cake_2fa_preset": "Cake 2FA Tito", - "narrow": "Taara", - "normal": "Deede", - "aggressive": "Onítara", - "require_for_assessing_wallet": "Beere fun wiwọle si apamọwọ", - "require_for_sends_to_non_contacts": "Beere fun fifiranṣẹ si awọn ti kii ṣe awọn olubasọrọ", - "require_for_sends_to_contacts": "Beere fun fifiranṣẹ si awọn olubasọrọ", - "require_for_sends_to_internal_wallets": "Beere fun fifiranṣẹ si awọn apamọwọ inu", - "require_for_exchanges_to_internal_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ inu", - "require_for_adding_contacts": "Beere fun fifi awọn olubasọrọ kun", - "require_for_creating_new_wallets": "Beere fun ṣiṣẹda titun Woleti", - "require_for_all_security_and_backup_settings": "Beere fun gbogbo aabo ati awọn eto afẹyinti", - "available_balance_description": "“Iwọntunwọnsi Wa” tabi “Iwọntunwọnsi Ijẹrisi” jẹ awọn owo ti o le ṣee lo lẹsẹkẹsẹ. Ti awọn owo ba han ni iwọntunwọnsi kekere ṣugbọn kii ṣe iwọntunwọnsi oke, lẹhinna o gbọdọ duro iṣẹju diẹ fun awọn owo ti nwọle lati gba awọn ijẹrisi nẹtiwọọki diẹ sii. Lẹhin ti wọn gba awọn ijẹrisi diẹ sii, wọn yoo jẹ inawo.", - "syncing_wallet_alert_title": "Apamọwọ rẹ n muṣiṣẹpọ", - "syncing_wallet_alert_content": "Iwontunws.funfun rẹ ati atokọ idunadura le ma pari titi ti yoo fi sọ “SYNCHRONIZED” ni oke. Tẹ/tẹ ni kia kia lati ni imọ siwaju sii.", - "home_screen_settings": "Awọn eto iboju ile", - "sort_by": "Sa pelu", - "search_add_token": "Wa / Fi àmi kun", - "edit_token": "Ṣatunkọ àmi", - "warning": "Ikilo", - "add_token_warning": "Ma ṣe ṣatunkọ tabi ṣafikun awọn ami bi a ti fun ni aṣẹ nipasẹ awọn scammers.\nNigbagbogbo jẹrisi awọn adirẹsi ami pẹlu awọn orisun olokiki!", - "add_token_disclaimer_check": "Mo ti jẹrisi adirẹsi adehun ami ati alaye nipa lilo orisun olokiki kan. Fifi irira tabi alaye ti ko tọ le ja si isonu ti owo.", - "token_contract_address": "Àmi guide adirẹsi", - "token_name": "Orukọ àmi fun apẹẹrẹ: Tether", - "token_symbol": "Aami aami fun apẹẹrẹ: USDT", - "token_decimal": "Àmi eleemewa", - "field_required": "E ni lati se nkan si aye yi", - "pin_at_top": "pin ${tokini} ni oke", - "invalid_input": "Iṣawọle ti ko tọ", - "fiat_balance": "Fiat Iwontunws.funfun", - "gross_balance": "Iwontunws.funfun apapọ", - "alphabetical": "Labidibi", - "generate_name": "Ṣẹda Orukọ", - "balance_page": "Oju-iwe iwọntunwọnsi", - "share": "Pinpin", - "slidable": "Slidable", - "manage_nodes": "Ṣakoso awọn apa", - "etherscan_history": "Etherscan itan", - "template_name": "Orukọ Awoṣe", - "change_rep": "Yi Aṣoju", - "change_rep_message": "Ṣe o da ọ loju pe o fẹ yi awọn aṣoju pada?", - "unsupported_asset": "A ko ṣe atilẹyin iṣẹ yii fun dukia yii. Jọwọ ṣẹda tabi yipada si apamọwọ iru dukia atilẹyin.", - "manage_pow_nodes": "Ṣakoso awọn Nodes PoW", - "support_title_live_chat": "Atilẹyin ifiwe", - "support_description_live_chat": "Free ati sare! Ti oṣiṣẹ awọn aṣoju wa lati ṣe iranlọwọ", - "support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo", - "support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ", - "support_title_other_links": "Awọn ọna asopọ atilẹyin miiran", - "support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran", - "choose_derivation": "Yan awọn apamọwọ apamọwọ", - "new_first_wallet_text": "Ni rọọrun jẹ ki o jẹ ki o jẹ ki o jẹ ki a mu", - "monero_dark_theme": "Monero Dudu Akori", - "bitcoin_dark_theme": "Bitcoin Dark Akori", - "bitcoin_light_theme": "Bitcoin Light Akori", - "high_contrast_theme": "Akori Iyatọ giga", - "matrix_green_dark_theme": "Matrix Green Dark Akori", - "monero_light_theme": "Monero Light Akori", - "select_destination": "Jọwọ yan ibi ti o nlo fun faili afẹyinti.", - "auto_generate_subaddresses": "Aṣiṣe Ibi-Afọwọkọ", - "save_to_downloads": "Fipamọ si Awọn igbasilẹ", - "select_buy_provider_notice": "Yan olupese Ra loke. O le skii iboju yii nipa ṣiṣeto olupese rẹ ni awọn eto App.", - "onramper_option_description": "Ni kiakia Ra Crypto pẹlu ọpọlọpọ awọn ọna isanwo. Wa ni ọpọlọpọ awọn orilẹ-ede. Itankale ati awọn idiyele yatọ.", - "default_buy_provider": "Aiyipada Ra Olupese", - "ask_each_time": "Beere lọwọ kọọkan", - "buy_provider_unavailable": "Olupese lọwọlọwọ ko si.", - "signTransaction": "Wole Idunadura", - "errorGettingCredentials": "Kuna: Aṣiṣe lakoko gbigba awọn iwe-ẹri", - "errorSigningTransaction": "Aṣiṣe kan ti waye lakoko ti o fowo si iṣowo", - "pairingInvalidEvent": "Pipọpọ Iṣẹlẹ Ti ko tọ", - "chains": "Awọn ẹwọn", - "methods": "Awọn ọna", - "events": "Awọn iṣẹlẹ", - "reject": "Kọ", - "approve": "Fi ọwọ si", - "expiresOn": "Ipari lori", - "walletConnect": "Asopọmọra apamọwọ", - "nullURIError": "URI jẹ asan", - "connectWalletPrompt": "So apamọwọ rẹ pọ pẹlu WalletConnect lati ṣe awọn iṣowo", - "newConnection": "Tuntun Asopọ", - "activeConnectionsPrompt": "Awọn asopọ ti nṣiṣe lọwọ yoo han nibi", - "deleteConnectionConfirmationPrompt": "Ṣe o da ọ loju pe o fẹ paarẹ asopọ si", - "event": "Iṣẹlẹ", - "successful": "Aseyori", - "wouoldLikeToConnect": "yoo fẹ lati sopọ", - "message": "Ifiranṣẹ", - "do_not_have_enough_gas_asset": "O ko ni to ${currency} lati ṣe idunadura kan pẹlu awọn ipo nẹtiwọki blockchain lọwọlọwọ. O nilo diẹ sii ${currency} lati san awọn owo nẹtiwọọki blockchain, paapaa ti o ba nfi dukia miiran ranṣẹ.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Fi inurere duro fun dApp lati pari sisẹ.", - "copyWalletConnectLink": "Daakọ ọna asopọ WalletConnect lati dApp ki o si lẹẹmọ nibi", - "enterWalletConnectURI": "Tẹ WalletConnect URI sii", - "seed_key": "Bọtini Ose", - "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", - "change_rep_successful": "Ni ifijišẹ yipada aṣoju", - "add_contact": "Fi olubasọrọ kun", - "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!", - "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", - "order_by": "Bere fun nipasẹ", - "creation_date": "Ọjọ ẹda", - "group_by_type": "Ẹgbẹ nipasẹ Iru", - "importNFTs": "Gbe awọn NFT wọle", - "noNFTYet": "Ko si awọn NFT sibẹsibẹ", - "address": "Adirẹsi", - "enterTokenID": "Tẹ ID ami sii", - "tokenID": "ID", - "name": "Oruko", - "symbol": "Aami", - "seed_phrase_length": "Gigun gbolohun irugbin", - "unavailable_balance": "Iwontunwonsi ti ko si", - "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", - "unspent_change": "Yipada", - "tor_connection": "Tor asopọ", - "setup_warning_2fa_text": "Iwọ yoo nilo lati mu pada apamọwọ rẹ lati inu irugbin mnemonic.\n\nAtilẹyin akara oyinbo kii yoo ni anfani lati ṣe iranlọwọ fun ọ ti o ba padanu iraye si 2FA tabi awọn irugbin mnemonic rẹ.\nAkara oyinbo 2FA jẹ ijẹrisi keji fun awọn iṣe kan ninu apamọwọ. Ṣaaju lilo akara oyinbo 2FA, a ṣeduro kika nipasẹ itọsọna naa.Ko ṣe aabo bi ibi ipamọ tutu.\n\nTi o ba padanu iraye si ohun elo 2FA tabi awọn bọtini TOTP, iwọ YOO padanu iraye si apamọwọ yii. ", - "scan_qr_on_device": "Ṣe ayẹwo koodu QR yii lori ẹrọ miiran", - "how_to_use": "Bawo ni lati lo", - "seed_hex_form": "Irú Opamọwọ apamọwọ (HOX)", - "seedtype": "Irugbin-seetypu", - "seedtype_legacy": "Legacy (awọn ọrọ 25)", - "seedtype_polyseed": "Polyseed (awọn ọrọ 16)", - "seed_language_czech": "Czech", - "seed_language_korean": "Ara ẹni", - "seed_language_chinese_traditional": "Kannada (ibile)", - "ascending": "Goke", - "descending": "Sọkalẹ", - "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", - "polygonscan_history": "PolygonScan itan", - "wallet_seed_legacy": "Irugbin akole", - "default_sell_provider": "Aiyipada Olupese Tita", - "select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.", - "custom_drag": "Aṣa (mu ati fa)", - "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)", - "use_testnet": "Lo tele", - "receivable_balance": "Iwontunws.funfun ti o gba", - "confirmed_tx": "Jẹrisi", - "transaction_details_source_address": "Adirẹsi orisun", - "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ.", - "contractName": "Orukọ adehun", - "contractSymbol": "Aami adehun", - "description": "Apejuwe", - "camera_consent": "Kamẹra rẹ yoo ṣee lo lati ya aworan kan fun awọn idi idanimọ nipasẹ ${provider}. Jọwọ ṣayẹwo Ilana Aṣiri wọn fun awọn alaye.", - "no_relays": "Ko si relays", - "choose_relay": "Jọwọ yan yii lati lo", - "no_relays_message": "A ri igbasilẹ Nostr NIP-05 fun olumulo yii, ṣugbọn ko ni eyikeyi awọn iṣipopada ninu. Jọwọ sọ fun olugba lati ṣafikun awọn isunmọ si igbasilẹ Nostr wọn.", - "no_relay_on_domain": "Ko si iṣipopada fun agbegbe olumulo tabi yiyi ko si. Jọwọ yan yii lati lo." - "zzzz": "zzzz" + "you_will_send": "Ṣe pàṣípààrọ̀ láti" } \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c7db31bd5..1bf1c9f84 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -715,6 +715,7 @@ "use_card_info_two": "预付账户中的资金转换为美元,不是数字货币。", "use_ssl": "使用SSL", "use_suggested": "使用建议", + "use_testnet": "使用TestNet", "variable_pair_not_supported": "所选交易所不支持此变量对", "verification": "验证", "verify_with_2fa": "用 Cake 2FA 验证", @@ -773,281 +774,5 @@ "you_now_have_debit_card": "你现在有一张借记卡", "you_pay": "你付钱", "you_will_get": "转换到", - "you_will_send": "转换自", - "yy": "YY", - "online": "在线", - "offline": "离线", - "gift_card_number": "礼品卡号", - "pin_number": "PIN 码", - "total_saving": "总储蓄", - "last_30_days": "过去 30 天", - "avg_savings": "平均储蓄", - "view_all": "查看全部", - "active_cards": "活动卡", - "delete_account": "删除账户", - "cards": "卡片", - "active": "活跃", - "redeemed": "赎回", - "gift_card_balance_note": "有余额的礼品卡会出现在这里", - "gift_card_redeemed_note": "您兑换的礼品卡会出现在这里", - "logout": "注销", - "add_tip": "添加提示", - "percentageOf": "${amount}", - "is_percentage": "是", - "search_category": "搜索类别", - "mark_as_redeemed": "标记为已赎回", - "more_options": "更多选项", - "awaiting_payment_confirmation": "等待付款确认", - "transaction_sent_notice": "如果屏幕在 1 分钟后没有继续,请检查区块浏览器和您的电子邮件。", - "agree": "同意", - "in_store": "店内", - "generating_gift_card": "生成礼品卡", - "payment_was_received": "您的付款已收到。", - "proceed_after_one_minute": "如果屏幕在 1 分钟后没有继续,请检查您的电子邮件。", - "order_id": "订单编号", - "gift_card_is_generated": "礼品卡生成", - "open_gift_card": "打开礼品卡", - "contact_support": "联系支持", - "gift_cards_unavailable": "目前只能通过门罗币、比特币和莱特币购买礼品卡", - "background_sync_mode": "后台同步模式", - "sync_all_wallets": "同步所有钱包", - "introducing_cake_pay": "介绍 Cake Pay!", - "cake_pay_learn_more": "立即在应用中购买和兑换礼品卡!\n从左向右滑动以了解详情。", - "automatic": "自动的", - "fixed_pair_not_supported": "所选交易所不支持此固定货币对", - "variable_pair_not_supported": "所选交易所不支持此变量对", - "none_of_selected_providers_can_exchange": "选定的供应商都不能进行此交换", - "choose_one": "选一个", - "choose_from_available_options": "从可用选项中选择:", - "custom_redeem_amount": "自定义兑换金额", - "add_custom_redemption": "添加自定义兑换", - "remaining": "剩余", - "delete_wallet": "删除钱包", - "delete_wallet_confirm_message": "您确定要删除 ${wallet_name} 钱包吗?", - "low_fee": "费用低", - "low_fee_alert": "您当前正在使用低网络费用优先级。这可能会导致长时间等待、不同的费率或取消交易。我们建议设置更高的费用以获得更好的体验。", - "ignor": "忽视", - "use_suggested": "使用建议", - "do_not_share_warning_text": "请勿与其他任何人分享这些信息,包括支持人员。\n\n您的资金可能而且将会被盗!", - "help": "帮助", - "all_transactions": "所有交易", - "all_trades": "所有的变化", - "connection_sync": "连接和同步", - "security_and_backup": "安全和备份", - "create_backup": "创建备份", - "privacy_settings": "隐私设置", - "privacy": "隐私", - "display_settings": "显示设置", - "other_settings": "其他设置", - "require_pin_after": "之后需要 PIN", - "always": "总是", - "minutes_to_pin_code": "${minute} 分钟", - "disable_exchange": "禁用交换", - "advanced_settings": "高级设置", - "settings_can_be_changed_later": "稍后可以在应用设置中更改这些设置", - "add_custom_node": "添加新的自定义节点", - "disable_fiat": "禁用法令", - "fiat_api": "法币API", - "disabled": "禁用", - "enabled": "启用", - "tor_only": "仅限 Tor", - "unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配", - "orbot_running_alert": "请确保 Orbot 在连接到此节点之前正在运行。", - "contact_list_contacts": "联系人", - "contact_list_wallets": "我的钱包", - "bitcoin_payments_require_1_confirmation": "比特币支付需要 1 次确认,这可能需要 20 分钟或更长时间。谢谢你的耐心!确认付款后,您将收到电子邮件。", - "send_to_this_address": "发送 ${currency} ${tag}到这个地址", - "arrive_in_this_address": "${currency} ${tag}将到达此地址", - "do_not_send": "不要发送", - "error_dialog_content": "糟糕,我们遇到了一些错误。\n\n请将崩溃报告发送给我们的支持团队,以改进应用程序。", - "scan_qr_code": "扫描二维码", - "cold_or_recover_wallet": "添加冷钱包或恢复纸钱包", - "please_wait": "请稍等", - "sweeping_wallet": "扫一扫钱包", - "sweeping_wallet_alert": "\n这应该不会花很长时间。请勿离开此屏幕,否则可能会丢失所掠取的资金", - "decimal_places_error": "小数位太多", - "edit_node": "编辑节点", - "invoice_details": "发票明细", - "donation_link_details": "捐赠链接详情", - "anonpay_description": "生成 ${type}。收款人可以使用任何受支持的加密货币 ${method},您将在此钱包中收到资金。", - "create_invoice": "创建发票", - "create_donation_link": "创建捐赠链接", - "optional_email_hint": "可选的收款人通知电子邮件", - "optional_description": "可选说明", - "optional_name": "可选收件人姓名", - "clearnet_link": "明网链接", - "onion_link": "洋葱链接", - "settings": "设置", - "sell_monero_com_alert_content": "尚不支持出售门罗币", - "error_text_input_below_minimum_limit": "金额小于最小值", - "error_text_input_above_maximum_limit": "金额大于最大值", - "show_market_place": "显示市场", - "prevent_screenshots": "防止截屏和录屏", - "profile": "轮廓", - "close": "关闭", - "modify_2fa": "修改蛋糕2FA", - "disable_cake_2fa": "禁用蛋糕 2FA", - "question_to_disable_2fa": "您确定要禁用 Cake 2FA 吗?访问钱包和某些功能将不再需要 2FA 代码。", - "disable": "停用", - "setup_2fa": "设置蛋糕 2FA", - "verify_with_2fa": "用 Cake 2FA 验证", - "totp_code": "TOTP代码", - "please_fill_totp": "请填写您其他设备上的 8 位代码", - "totp_2fa_success": "成功!为此钱包启用了 Cake 2FA。请记住保存您的助记词种子,以防您无法访问钱包。", - "totp_verification_success": "验证成功!", - "totp_2fa_failure": "不正确的代码。 请尝试不同的代码或生成新的密钥。 使用支持 8 位代码和 SHA512 的兼容 2FA 应用程序。", - "enter_totp_code": "请输入 TOTP 代码。", - "add_secret_code": "或者,将此密码添加到身份验证器应用程序中", - "totp_secret_code": "TOTP密码", - "setup_2fa_text": "Cake 2FA 使用 TOTP 作为第二个身份验证因素。\n\nCake 2FA 的 TOTP 需要 SHA-512 和 8 位数字支持;这提供了更高的安全性。更多信息和支持的应用程序可以在指南中找到。", - "setup_totp_recommended": "设置 TOTP", - "disable_buy": "禁用购买操作", - "disable_sell": "禁用卖出操作", - "cake_2fa_preset": "蛋糕 2FA 预设", - "narrow": "狭窄的", - "normal": "普通的", - "aggressive": "过分热心", - "require_for_assessing_wallet": "需要访问钱包", - "require_for_sends_to_non_contacts": "需要发送给非联系人", - "require_for_sends_to_contacts": "需要发送给联系人", - "require_for_sends_to_internal_wallets": "需要发送到内部钱包", - "require_for_exchanges_to_internal_wallets": "需要兑换到内部钱包", - "require_for_adding_contacts": "需要添加联系人", - "require_for_creating_new_wallets": "创建新钱包的要求", - "require_for_all_security_and_backup_settings": "需要所有安全和备份设置", - "available_balance_description": "可用余额是您可以使用的金额。冻结余额是您当前正在等待确认的金额。", - "syncing_wallet_alert_title": "您的钱包正在同步", - "syncing_wallet_alert_content": "您的余额和交易列表可能不完整,直到顶部显示“已同步”。单击/点击以了解更多信息。", - "home_screen_settings": "主屏幕设置", - "sort_by": "排序方式", - "search_add_token": "搜索/添加令牌", - "edit_token": "编辑令牌", - "warning": "警告", - "add_token_warning": "请勿按照诈骗者的指示编辑或添加令牌。\n始终通过信誉良好的来源确认代币地址!", - "add_token_disclaimer_check": "我已使用信誉良好的来源确认了代币合约地址和信息。 添加恶意或不正确的信息可能会导致资金损失。", - "token_contract_address": "代币合约地址", - "token_name": "代币名称例如:Tether", - "token_symbol": "代币符号例如:USDT", - "token_decimal": "令牌十进制", - "field_required": "此字段是必需的", - "pin_at_top": "将 ${token} 固定在顶部", - "invalid_input": "输入无效", - "fiat_balance": "法币余额", - "gross_balance": "毛余额", - "alphabetical": "按字母顺序", - "generate_name": "生成名称", - "balance_page": "余额页", - "share": "分享", - "slidable": "可滑动", - "manage_nodes": "管理节点", - "etherscan_history": "以太扫描历史", - "template_name": "模板名称", - "change_rep": "变革代表", - "change_rep_message": "您确定要更换代表吗?", - "unsupported_asset": "我们不支持针对该资产采取此操作。请创建或切换到支持的资产类型的钱包。", - "manage_pow_nodes": "管理 PoW 节点", - "support_title_live_chat": "实时支持", - "support_description_live_chat": "免费快速!训练有素的支持代表可以协助", - "support_title_guides": "蛋糕钱包指南", - "support_description_guides": "对常见问题的文档和支持", - "support_title_other_links": "其他支持链接", - "support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴", - "choose_derivation": "选择钱包推导", - "new_first_wallet_text": "轻松确保您的加密货币安全", - "monero_dark_theme": "门罗币深色主题", - "bitcoin_dark_theme": "比特币黑暗主题", - "bitcoin_light_theme": "比特币浅色主题", - "high_contrast_theme": "高对比度主题", - "matrix_green_dark_theme": "矩阵绿暗主题", - "monero_light_theme": "门罗币浅色主题", - "select_destination": "请选择备份文件的目的地。", - "auto_generate_subaddresses": "自动生成子辅助", - "save_to_downloads": "保存到下载", - "select_buy_provider_notice": "在上面选择买入提供商。您可以通过在应用程序设置中设置默认的购买提供商来跳过此屏幕。", - "onramper_option_description": "快速使用许多付款方式购买加密货币。在大多数国家 /地区可用。利差和费用各不相同。", - "default_buy_provider": "默认购买提供商", - "ask_each_time": "每次问", - "buy_provider_unavailable": "提供者目前不可用。", - "signTransaction": "签署交易", - "errorGettingCredentials": "失败:获取凭据时出错", - "errorSigningTransaction": "签署交易时发生错误", - "pairingInvalidEvent": "配对无效事件", - "chains": "链条", - "methods": "方法", - "events": "活动", - "reject": "拒绝", - "approve": "批准", - "expiresOn": "到期", - "walletConnect": "钱包连接", - "nullURIError": "URI 为空", - "connectWalletPrompt": "将您的钱包与 WalletConnect 连接以进行交易", - "newConnection": "新连接", - "activeConnectionsPrompt": "活动连接将出现在这里", - "deleteConnectionConfirmationPrompt": "您确定要删除与", - "event": "事件", - "successful": "成功的", - "wouoldLikeToConnect": "想要连接", - "message": "信息", - "do_not_have_enough_gas_asset": "您没有足够的 ${currency} 来在当前的区块链网络条件下进行交易。即使您发送的是不同的资产,您也需要更多的 ${currency} 来支付区块链网络费用。", - "totp_auth_url": "TOTP 授权 URL", - "awaitDAppProcessing": "请等待 dApp 处理完成。", - "copyWalletConnectLink": "从 dApp 复制 WalletConnect 链接并粘贴到此处", - "enterWalletConnectURI": "输入 WalletConnect URI", - "seed_key": "种子钥匙", - "enter_seed_phrase": "输入您的种子短语", - "change_rep_successful": "成功改变了代表", - "add_contact": "增加联系人", - "exchange_provider_unsupported": "${providerName}不再支持!", - "domain_looks_up": "域名查找", - "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", - "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", - "switchToETHWallet": "请切换到以太坊钱包并重试", - "order_by": "订购", - "creation_date": "创建日期", - "group_by_type": "按类型组", - "importNFTs": "导入 NFT", - "noNFTYet": "还没有 NFT", - "address": "地址", - "enterTokenID": "输入令牌 ID", - "tokenID": "ID", - "name": "姓名", - "symbol": "象征", - "seed_phrase_length": "种子短语长度", - "unavailable_balance": "不可用余额", - "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", - "unspent_change": "改变", - "tor_connection": "Tor连接", - "setup_warning_2fa_text": "Cake 2FA 是对钱包中某些操作的二次验证。它不如冷藏那么安全。\n\n如果您无法访问 2FA 应用程序或 TOTP 密钥,您将无法访问此钱包。您需要从助记词种子中恢复您的钱包。\n\n如果您无法访问 2FA 或助记词种子,Cake 支持将无法为您提供帮助。\n在使用 Cake 2FA 之前,我们建议您阅读该指南。", - "scan_qr_on_device": "在另一台设备上扫描此二维码", - "how_to_use": "如何使用", - "seed_hex_form": "钱包种子(十六进制形式)", - "seedtype": "籽粒", - "seedtype_legacy": "遗产(25个单词)", - "seedtype_polyseed": "多种物品(16个单词)", - "seed_language_czech": "捷克", - "seed_language_korean": "韩国人", - "seed_language_chinese_traditional": "中国传统的)", - "ascending": "上升", - "descending": "下降", - "dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户", - "polygonscan_history": "多边形扫描历史", - "wallet_seed_legacy": "旧的钱包种子", - "default_sell_provider": "默认销售提供商", - "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。", - "custom_drag": "定制(保持和拖动)", - "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)", - "use_testnet": "使用TestNet", - "receivable_balance": "应收余额", - "confirmed_tx": "确认的", - "transaction_details_source_address": "源地址", - "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。", - "contractName": "合约名称", - "contractSymbol": "合约符号", - "description": "描述", - "camera_consent": "${provider} 将使用您的相机拍摄图像以供识别之用。请查看他们的隐私政策了解详情。", - "no_relays": "无继电器", - "choose_relay": "请选择要使用的继电器", - "no_relays_message": "我们找到了该用户的 Nostr NIP-05 记录,但它不包含任何中继。请指示收件人将中继添加到他们的 Nostr 记录中。", - "no_relay_on_domain": "用户域没有中继或中继不可用。请选择要使用的继电器。" - "zzzz": "ZZZZ" + "you_will_send": "转换自" } \ No newline at end of file From e3404c55fee7d75298faaf8d2240314e52f815e5 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 6 Feb 2024 22:34:36 +0200 Subject: [PATCH 41/59] Fix translation [skip ci] --- res/values/strings_ar.arb | 3 ++- res/values/strings_bg.arb | 3 ++- res/values/strings_cs.arb | 3 ++- res/values/strings_de.arb | 3 ++- res/values/strings_en.arb | 3 ++- res/values/strings_es.arb | 3 ++- res/values/strings_fr.arb | 3 ++- res/values/strings_ha.arb | 3 ++- res/values/strings_hi.arb | 3 ++- res/values/strings_hr.arb | 3 ++- res/values/strings_id.arb | 3 ++- res/values/strings_it.arb | 3 ++- res/values/strings_ja.arb | 3 ++- res/values/strings_ko.arb | 3 ++- res/values/strings_my.arb | 3 ++- res/values/strings_nl.arb | 3 ++- res/values/strings_pl.arb | 3 ++- res/values/strings_pt.arb | 3 ++- res/values/strings_ru.arb | 3 ++- res/values/strings_th.arb | 3 ++- res/values/strings_tl.arb | 3 ++- res/values/strings_tr.arb | 3 ++- res/values/strings_uk.arb | 3 ++- res/values/strings_ur.arb | 3 ++- res/values/strings_yo.arb | 3 ++- res/values/strings_zh.arb | 3 ++- 26 files changed, 52 insertions(+), 26 deletions(-) diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index d834bfd90..d4be5671c 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -771,5 +771,6 @@ "you_now_have_debit_card": "لديك الآن بطاقة ائتمان", "you_pay": "انت تدفع", "you_will_get": "حول الى", - "you_will_send": "تحويل من" + "you_will_send": "تحويل من", + "yy": "نعم" } \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 3f5f8ce93..5c553e91b 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -767,5 +767,6 @@ "you_now_have_debit_card": "Вече имате дебитна карта", "you_pay": "Вие плащате", "you_will_get": "Обръщане в", - "you_will_send": "Обръщане от" + "you_will_send": "Обръщане от", + "yy": "Да" } \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index be36f3d28..59ccf1c6b 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -767,5 +767,6 @@ "you_now_have_debit_card": "Nyní máte debetní kartu", "you_pay": "Zaplatíte", "you_will_get": "Směnit na", - "you_will_send": "Směnit z" + "you_will_send": "Směnit z", + "yy": "Yy" } \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 9c1102261..ebe630b5f 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "Sie haben jetzt eine Debitkarte", "you_pay": "Sie bezahlen", "you_will_get": "Konvertieren zu", - "you_will_send": "Konvertieren von" + "you_will_send": "Konvertieren von", + "yy": "Yy" } \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 1065876d3..f38fc2230 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -776,5 +776,6 @@ "you_now_have_debit_card": "You now have a debit card", "you_pay": "You Pay", "you_will_get": "Convert to", - "you_will_send": "Convert from" + "you_will_send": "Convert from", + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 8dc1af6fc..0523dcd7e 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "Ahora tiene una tarjeta de débito", "you_pay": "Tú pagas", "you_will_get": "Convertir a", - "you_will_send": "Convertir de" + "you_will_send": "Convertir de", + "yy": "Yy" } \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 32d3b2206..1f9fe281a 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "Vous avez maintenant une carte de débit", "you_pay": "Vous payez", "you_will_get": "Convertir vers", - "you_will_send": "Convertir depuis" + "you_will_send": "Convertir depuis", + "yy": "Oui" } \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 7dd7aee30..aa00fca35 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -757,5 +757,6 @@ "you_now_have_debit_card": "Yanzu kana da katin zare kudi", "you_pay": "Ka Bayar", "you_will_get": "Maida zuwa", - "you_will_send": "Maida daga" + "you_will_send": "Maida daga", + "yy": "Rant" } \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index dc49b5008..4605e2cfe 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "अब आपके पास डेबिट कार्ड है", "you_pay": "आप भुगतान करते हैं", "you_will_get": "में बदलें", - "you_will_send": "से रूपांतरित करें" + "you_will_send": "से रूपांतरित करें", + "yy": "Y Y" } \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 5ceb0d35f..3735c4495 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -773,5 +773,6 @@ "you_now_have_debit_card": "Sada imate debitnu karticu", "you_pay": "Vi plaćate", "you_will_get": "Razmijeni u", - "you_will_send": "Razmijeni iz" + "you_will_send": "Razmijeni iz", + "yy": "Yy" } \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index dff9233b0..92e6fc74e 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -763,5 +763,6 @@ "you_now_have_debit_card": "Anda sekarang memiliki kartu debit", "you_pay": "Anda Membayar", "you_will_get": "Konversi ke", - "you_will_send": "Konversi dari" + "you_will_send": "Konversi dari", + "yy": "Y Y" } \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 71a858d58..194a0adb3 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "Ora hai una carta di debito", "you_pay": "Tu paghi", "you_will_get": "Converti a", - "you_will_send": "Conveti da" + "you_will_send": "Conveti da", + "yy": "Sì" } \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index eca1b1792..4f7b37dc7 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "デビットカードができました", "you_pay": "あなたが支払う", "you_will_get": "に変換", - "you_will_send": "から変換" + "you_will_send": "から変換", + "yy": "yy" } \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 8ae20c7f3..b42c0e8fc 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -773,5 +773,6 @@ "you_now_have_debit_card": "이제 직불카드가 있습니다.", "you_pay": "당신이 지불합니다", "you_will_get": "로 변환하다", - "you_will_send": "다음에서 변환" + "you_will_send": "다음에서 변환", + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 79db86552..6a8026942 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -773,5 +773,6 @@ "you_now_have_debit_card": "ယခု သင့်တွင် ဒက်ဘစ်ကတ်တစ်ခုရှိသည်။", "you_pay": "သင်ပေးချေပါ။", "you_will_get": "သို့ပြောင်းပါ။", - "you_will_send": "မှပြောင်းပါ။" + "you_will_send": "မှပြောင်းပါ။", + "yy": "y" } \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a38826921..4cf4a12f1 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "Je hebt nu een debetkaart", "you_pay": "U betaalt", "you_will_get": "Converteren naar", - "you_will_send": "Converteren van" + "you_will_send": "Converteren van", + "yy": "Yy" } \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index fa8decbee..c9604ddbe 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "Masz teraz kartę debetową", "you_pay": "Płacisz", "you_will_get": "Konwertuj na", - "you_will_send": "Konwertuj z" + "you_will_send": "Konwertuj z", + "yy": "Tak" } \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index d43a13fc0..20ecacf0e 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -774,5 +774,6 @@ "you_now_have_debit_card": "Agora você tem um cartão de débito", "you_pay": "Você paga", "you_will_get": "Converter para", - "you_will_send": "Converter de" + "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 7271ccb2a..4f932a4e3 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "Теперь у вас есть дебетовая карта", "you_pay": "Вы платите", "you_will_get": "Конвертировать в", - "you_will_send": "Конвертировать из" + "you_will_send": "Конвертировать из", + "yy": "Да" } \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 0b6373417..62bc8a7f7 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -773,5 +773,6 @@ "you_now_have_debit_card": "ขณะนี้คุณมีบัตรเดบิต", "you_pay": "คุณจ่าย", "you_will_get": "แปลงเป็น", - "you_will_send": "แปลงจาก" + "you_will_send": "แปลงจาก", + "yy": "yy" } \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 273536cbb..7990a44f8 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -769,5 +769,6 @@ "you_now_have_debit_card": "Mayroon ka na ngayong debit card", "you_pay": "Magbabayad ka", "you_will_get": "Mag -convert sa", - "you_will_send": "I -convert mula sa" + "you_will_send": "I -convert mula sa", + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 27facfdc5..e93eab792 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -773,5 +773,6 @@ "you_now_have_debit_card": "Artık bir ön ödemeli kartın var", "you_pay": "Şu kadar ödeyeceksin: ", "you_will_get": "Biçimine dönüştür:", - "you_will_send": "Biçiminden dönüştür:" + "you_will_send": "Biçiminden dönüştür:", + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 569cb770d..d29468fc6 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -775,5 +775,6 @@ "you_now_have_debit_card": "Тепер у вас є дебетова картка", "you_pay": "Ви платите", "you_will_get": "Конвертувати в", - "you_will_send": "Конвертувати з" + "you_will_send": "Конвертувати з", + "yy": "Yy" } \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index c92535ae5..2c5edd286 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -767,5 +767,6 @@ "you_now_have_debit_card": "اب آپ کے پاس ڈیبٹ کارڈ ہے۔", "you_pay": "تم ادا کرو", "you_will_get": "میں تبدیل کریں۔", - "you_will_send": "سے تبدیل کریں۔" + "you_will_send": "سے تبدیل کریں۔", + "yy": "yy" } \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index a3607a4e2..a8a42104d 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -769,5 +769,6 @@ "you_now_have_debit_card": "Ẹ ni káàdì ìrajà lọ́wọ́lọ́wọ́", "you_pay": "Ẹ sàn", "you_will_get": "Ṣe pàṣípààrọ̀ sí", - "you_will_send": "Ṣe pàṣípààrọ̀ láti" + "you_will_send": "Ṣe pàṣípààrọ̀ láti", + "yy": "Yy" } \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 1bf1c9f84..4bbff3587 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -774,5 +774,6 @@ "you_now_have_debit_card": "你现在有一张借记卡", "you_pay": "你付钱", "you_will_get": "转换到", - "you_will_send": "转换自" + "you_will_send": "转换自", + "yy": "是的" } \ No newline at end of file From 7956ecc86bde313114170cf2ba84a74091c59ac4 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 6 Feb 2024 22:40:49 +0200 Subject: [PATCH 42/59] Update strings_fr.arb [skip ci] --- res/values/strings_fr.arb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 1f9fe281a..3deba475f 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -776,5 +776,5 @@ "you_pay": "Vous payez", "you_will_get": "Convertir vers", "you_will_send": "Convertir depuis", - "yy": "Oui" -} \ No newline at end of file + "yy": "AA" +} From 2e6ba71e57abb885e98acd50ed763d4316556f64 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 8 Feb 2024 17:33:24 -0300 Subject: [PATCH 43/59] fix: async isChange function not being awaited, refactor to reduce looping into a single place --- cw_bitcoin/lib/electrum_wallet.dart | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 783f39fa1..3180c28a0 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -507,20 +507,20 @@ abstract class ElectrumWalletBase Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future updateUnspent() async { - final unspent = await Future.wait(walletAddresses.allAddresses.map((address) => electrumClient + List updatedUnspentCoins = []; + + await Future.wait(walletAddresses.allAddresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, network) - .then((unspent) => unspent.map((unspent) { + .then((unspent) => Future.forEach>(unspent, (unspent) async { try { - return BitcoinUnspent.fromJSON(address, unspent); - } catch (_) { - return null; - } - }).whereNotNull()))); - unspentCoins = unspent.expand((e) => e).toList(); - unspentCoins.forEach((coin) async { - final tx = await fetchTransactionInfo(hash: coin.hash, height: 0); - coin.isChange = tx?.direction == TransactionDirection.outgoing; - }); + final coin = BitcoinUnspent.fromJSON(address, unspent); + final tx = await fetchTransactionInfo(hash: coin.hash, height: 0); + coin.isChange = tx?.direction == TransactionDirection.outgoing; + updatedUnspentCoins.add(coin); + } catch (_) {} + })))); + + unspentCoins = updatedUnspentCoins; if (unspentCoinsInfo.isEmpty) { unspentCoins.forEach((coin) => _addCoinInfo(coin)); From f8cadfa11233ce32fdbc955e095f4e0a2d274a0c Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 9 Feb 2024 11:19:55 -0300 Subject: [PATCH 44/59] fix: _address vs address, missing p2sh --- cw_bitcoin/lib/address_from_output.dart | 2 + cw_bitcoin/lib/bitcoin_address_record.dart | 8 +- .../lib/bitcoin_receive_page_option.dart | 4 + cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 3 + cw_bitcoin/lib/electrum_wallet.dart | 6 +- cw_bitcoin/lib/electrum_wallet_addresses.dart | 102 +++++++++++------- cw_bitcoin/lib/utils.dart | 4 + cw_bitcoin/pubspec.lock | 2 +- .../screens/dashboard/pages/address_page.dart | 3 + 9 files changed, 87 insertions(+), 47 deletions(-) diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index 74606dca6..50b178d2c 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -11,6 +11,8 @@ String addressFromOutputScript(Script script, BasedUtxoNetwork network) { return P2shAddress.fromScriptPubkey(script: script).toAddress(network); case SegwitAddresType.p2wpkh: return P2wpkhAddress.fromScriptPubkey(script: script).toAddress(network); + case P2shAddressType.p2pkhInP2sh: + return P2shAddress.fromScriptPubkey(script: script).toAddress(network); case SegwitAddresType.p2wsh: return P2wshAddress.fromScriptPubkey(script: script).toAddress(network); case SegwitAddresType.p2tr: diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index 502fdced4..3952bdbd6 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -12,7 +12,7 @@ class BitcoinAddressRecord { int balance = 0, String name = '', bool isUsed = false, - this.type, + required this.type, }) : _txCount = txCount, _balance = balance, _name = name, @@ -32,7 +32,7 @@ class BitcoinAddressRecord { type: decoded['type'] != null && decoded['type'] != '' ? BitcoinAddressType.values .firstWhere((type) => type.toString() == decoded['type'] as String) - : null, + : SegwitAddresType.p2wpkh, ); } @@ -67,7 +67,7 @@ class BitcoinAddressRecord { String get cashAddr => bitbox.Address.toCashAddress(address); - BitcoinAddressType? type; + BitcoinAddressType type; String toJSON() => json.encode({ 'address': address, @@ -77,6 +77,6 @@ class BitcoinAddressRecord { 'txCount': txCount, 'name': name, 'balance': balance, - 'type': type?.toString() ?? '', + 'type': type.toString(), }); } diff --git a/cw_bitcoin/lib/bitcoin_receive_page_option.dart b/cw_bitcoin/lib/bitcoin_receive_page_option.dart index 7ce653c51..e58c2cc5d 100644 --- a/cw_bitcoin/lib/bitcoin_receive_page_option.dart +++ b/cw_bitcoin/lib/bitcoin_receive_page_option.dart @@ -3,6 +3,7 @@ import 'package:cw_core/receive_page_option.dart'; class BitcoinReceivePageOption implements ReceivePageOption { static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH)'); + static const p2sh = BitcoinReceivePageOption._('Segwit-Compatible (P2SH)'); static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)'); static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)'); static const p2pkh = BitcoinReceivePageOption._('Legacy (P2PKH)'); @@ -17,6 +18,7 @@ class BitcoinReceivePageOption implements ReceivePageOption { static const all = [ BitcoinReceivePageOption.p2wpkh, + BitcoinReceivePageOption.p2sh, BitcoinReceivePageOption.p2tr, BitcoinReceivePageOption.p2wsh, BitcoinReceivePageOption.p2pkh @@ -30,6 +32,8 @@ class BitcoinReceivePageOption implements ReceivePageOption { return BitcoinReceivePageOption.p2wsh; case P2pkhAddressType.p2pkh: return BitcoinReceivePageOption.p2pkh; + case P2shAddressType.p2wpkhInP2sh: + return BitcoinReceivePageOption.p2pkh; case SegwitAddresType.p2wpkh: default: return BitcoinReceivePageOption.p2wpkh; diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index 6207f6e14..f12577492 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -32,6 +32,9 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S if (addressType == SegwitAddresType.p2wsh) return generateP2WSHAddress(hd: hd, index: index, network: network); + if (addressType == P2shAddressType.p2wpkhInP2sh) + return generateP2SHAddress(hd: hd, index: index, network: network); + return generateP2WPKHAddress(hd: hd, index: index, network: network); } } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 3180c28a0..d904e67d5 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -157,7 +157,7 @@ abstract class ElectrumWalletBase Future startSync() async { try { syncStatus = AttemptingSyncStatus(); - await walletAddresses.discoverAddresses(); + await walletAddresses.discoverAddressesAll(); await updateTransactions(); _subscribeForUpdates(); await updateUnspent(); @@ -849,6 +849,8 @@ class EstimatedTxResult { BitcoinBaseAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) { if (P2pkhAddress.regex.hasMatch(address)) { return P2pkhAddress.fromAddress(address: address, network: network); + } else if (P2shAddress.regex.hasMatch(address)) { + return P2shAddress.fromAddress(address: address, network: network); } else if (P2wshAddress.regex.hasMatch(address)) { return P2wshAddress.fromAddress(address: address, network: network); } else if (P2trAddress.regex.hasMatch(address)) { @@ -861,6 +863,8 @@ BitcoinBaseAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) BitcoinAddressType _getScriptType(BitcoinBaseAddress type) { if (type is P2pkhAddress) { return P2pkhAddressType.p2pkh; + } else if (type is P2shAddress) { + return P2shAddressType.p2wpkhInP2sh; } else if (type is P2wshAddress) { return SegwitAddresType.p2wsh; } else if (type is P2trAddress) { diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index b213b601d..2713f7e3f 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -65,7 +65,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { String get addressPageTypeStr => addressPageType.toString(); @computed - List get addresses => _addresses.where(_isAddressTypeMatch).toList(); + List get addresses => _addresses.where(_isAddressPageTypeMatch).toList(); @computed List get allAddresses => _addresses; @@ -80,7 +80,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { String get address { String receiveAddress; - final typeMatchingReceiveAddresses = receiveAddresses.where(_isAddressTypeMatch); + final typeMatchingReceiveAddresses = receiveAddresses.where(_isAddressPageTypeMatch); if ((isEnabledAutoGenerateSubaddress && receiveAddresses.isEmpty) || typeMatchingReceiveAddresses.isEmpty) { @@ -151,15 +151,28 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return acc; }); - Future discoverAddresses() async { + Future discoverAddressesAll() async { await _discoverAddresses(false); await _discoverAddresses(true); + await _discoverAddresses(false, type: P2pkhAddressType.p2pkh); + await _discoverAddresses(true, type: P2pkhAddressType.p2pkh); + await _discoverAddresses(false, type: P2shAddressType.p2wpkhInP2sh); + await _discoverAddresses(true, type: P2shAddressType.p2wpkhInP2sh); + await _discoverAddresses(false, type: SegwitAddresType.p2tr); + await _discoverAddresses(true, type: SegwitAddresType.p2tr); + await _discoverAddresses(false, type: SegwitAddresType.p2wsh); + await _discoverAddresses(true, type: SegwitAddresType.p2wsh); + updateReceiveAddresses(); await updateAddressesInBox(); } @override Future init() async { await _generateInitialAddresses(); + await _generateInitialAddresses(type: P2pkhAddressType.p2pkh); + await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh); + await _generateInitialAddresses(type: SegwitAddresType.p2tr); + await _generateInitialAddresses(type: SegwitAddresType.p2wsh); updateReceiveAddresses(); updateChangeAddresses(); await updateAddressesInBox(); @@ -199,11 +212,11 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { 0, (int acc, addressRecord) => addressRecord.isHidden == false ? acc + 1 : acc); final address = BitcoinAddressRecord( - getAddress(index: newAddressIndex, hd: mainHd, addressType: addressPageType), - index: newAddressIndex, - isHidden: false, - name: label, - ); + getAddress(index: newAddressIndex, hd: mainHd, addressType: addressPageType), + index: newAddressIndex, + isHidden: false, + name: label, + type: addressPageType); addresses.add(address); return address; } @@ -240,31 +253,36 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { void updateReceiveAddresses() { receiveAddresses.removeRange(0, receiveAddresses.length); final newAddresses = - addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); + _addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); receiveAddresses.addAll(newAddresses); } @action void updateChangeAddresses() { changeAddresses.removeRange(0, changeAddresses.length); - final newAddresses = - addresses.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed); + final newAddresses = _addresses.where((addressRecord) => + addressRecord.isHidden && + !addressRecord.isUsed && + // TODO: feature to change change address type. For now fixed to p2wpkh, the cheapest type + addressRecord.type == SegwitAddresType.p2wpkh); changeAddresses.addAll(newAddresses); } @action - Future _discoverAddresses(bool isHidden) async { + Future _discoverAddresses(bool isHidden, + {BitcoinAddressType type = SegwitAddresType.p2wpkh}) async { var hasAddrUse = true; List addrs; + final matchingAddresses = _addresses.where((addr) => _addressMatchHidden(addr, isHidden, type)); - if (addresses.where((addr) => addr.isHidden == isHidden).isNotEmpty) { - addrs = addresses.where((addr) => addr.isHidden == isHidden).toList(); + if (matchingAddresses.isNotEmpty) { + addrs = matchingAddresses.toList(); } else { addrs = await _createNewAddresses( - isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, - startIndex: 0, - isHidden: isHidden, - ); + isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, + startIndex: 0, + isHidden: isHidden, + type: type); } while (hasAddrUse) { @@ -277,51 +295,55 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final start = addrs.length; final count = start + gap; - final batch = await _createNewAddresses(count, startIndex: start, isHidden: isHidden); + final batch = + await _createNewAddresses(count, startIndex: start, isHidden: isHidden, type: type); addrs.addAll(batch); } addAddresses(addrs); } - Future _generateInitialAddresses() async { + Future _generateInitialAddresses( + {BitcoinAddressType type = SegwitAddresType.p2wpkh}) async { var countOfReceiveAddresses = 0; var countOfHiddenAddresses = 0; - addresses.forEach((addr) { - if (addr.isHidden) { - countOfHiddenAddresses += 1; - return; - } + _addresses.forEach((addr) { + if (_isAddressByType(addr, type)) { + if (addr.isHidden) { + countOfHiddenAddresses += 1; + return; + } - countOfReceiveAddresses += 1; + countOfReceiveAddresses += 1; + } }); if (countOfReceiveAddresses < defaultReceiveAddressesCount) { final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses; final newAddresses = await _createNewAddresses(addressesCount, - startIndex: countOfReceiveAddresses, isHidden: false); - addresses.addAll(newAddresses); + startIndex: countOfReceiveAddresses, isHidden: false, type: type); + _addresses.addAll(newAddresses); } if (countOfHiddenAddresses < defaultChangeAddressesCount) { final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses; final newAddresses = await _createNewAddresses(addressesCount, - startIndex: countOfHiddenAddresses, isHidden: true); - addresses.addAll(newAddresses); + startIndex: countOfHiddenAddresses, isHidden: true, type: type); + _addresses.addAll(newAddresses); } } Future> _createNewAddresses(int count, - {int startIndex = 0, bool isHidden = false}) async { + {int startIndex = 0, bool isHidden = false, BitcoinAddressType? type}) async { final list = []; for (var i = startIndex; i < count + startIndex; i++) { final address = BitcoinAddressRecord( - getAddress(index: i, hd: _getHd(isHidden), addressType: addressPageType), + getAddress(index: i, hd: _getHd(isHidden), addressType: type ?? addressPageType), index: i, isHidden: isHidden, - type: addressPageType, + type: type ?? addressPageType, ); list.add(address); } @@ -346,17 +368,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action Future setAddressType(BitcoinAddressType type) async { _addressPageType = type; - - await discoverAddresses(); - await saveAddressesInBox(); } - bool _isAddressTypeMatch(BitcoinAddressRecord addressRecord) { - // Old wallets before address types were introduced will have an empty address record type - return addressPageType == SegwitAddresType.p2wpkh - ? addressRecord.type == null || addressRecord.type == addressPageType - : addressRecord.type == addressPageType; + bool _isAddressPageTypeMatch(BitcoinAddressRecord addressRecord) { + return _isAddressByType(addressRecord, addressPageType); } bitcoin.HDWallet _getHd(bool isHidden) => isHidden ? sideHd : mainHd; + bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) => + addr.type == type || (addr.type == null && type == SegwitAddresType.p2wpkh); + bool _addressMatchHidden(BitcoinAddressRecord addr, bool isHidden, BitcoinAddressType type) => + _isAddressByType(addr, type) && addr.isHidden == isHidden; } diff --git a/cw_bitcoin/lib/utils.dart b/cw_bitcoin/lib/utils.dart index 1f4e5e7b6..b156ccba3 100644 --- a/cw_bitcoin/lib/utils.dart +++ b/cw_bitcoin/lib/utils.dart @@ -16,6 +16,10 @@ String generateP2WPKHAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhAddress().toAddress(network); +String generateP2SHAddress( + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhInP2sh().toAddress(network); + String generateP2WSHAddress( {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => ECPublic.fromHex(hd.derive(index).pubKey!).toP2wshAddress().toAddress(network); diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 07c97deb3..25e6f269d 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v1 - resolved-ref: "318986da9cb03e4c18da2e6c0daf3e62aef7eb72" + resolved-ref: "9611e9db77e92a8434e918cdfb620068f6fcb1aa" url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "4.0.0" diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index e38a8f16d..7b7c84c28 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -233,6 +233,9 @@ class AddressPage extends BasePage { case BitcoinReceivePageOption.p2pkh: addressListViewModel.setAddressType(P2pkhAddressType.p2pkh); break; + case BitcoinReceivePageOption.p2sh: + addressListViewModel.setAddressType(P2shAddressType.p2wpkhInP2sh); + break; case BitcoinReceivePageOption.p2wpkh: addressListViewModel.setAddressType(SegwitAddresType.p2wpkh); break; From 10a2aef4d48ba856e0333e3726a4b51454552708 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Fri, 9 Feb 2024 16:00:19 -0300 Subject: [PATCH 45/59] fix: minor mistake in storing p2sh page type [skip ci] --- cw_bitcoin/lib/bitcoin_receive_page_option.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/bitcoin_receive_page_option.dart b/cw_bitcoin/lib/bitcoin_receive_page_option.dart index e58c2cc5d..2e246f532 100644 --- a/cw_bitcoin/lib/bitcoin_receive_page_option.dart +++ b/cw_bitcoin/lib/bitcoin_receive_page_option.dart @@ -33,7 +33,7 @@ class BitcoinReceivePageOption implements ReceivePageOption { case P2pkhAddressType.p2pkh: return BitcoinReceivePageOption.p2pkh; case P2shAddressType.p2wpkhInP2sh: - return BitcoinReceivePageOption.p2pkh; + return BitcoinReceivePageOption.p2sh; case SegwitAddresType.p2wpkh: default: return BitcoinReceivePageOption.p2wpkh; From 2333d130930dfe9c9d11be0086582422b7c8bfd9 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Mon, 12 Feb 2024 09:10:33 -0300 Subject: [PATCH 46/59] refactor: use already matched addresses property --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 1792e3baf..99af4cec3 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -314,15 +314,13 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { var countOfReceiveAddresses = 0; var countOfHiddenAddresses = 0; - _addresses.forEach((addr) { - if (_isAddressByType(addr, type)) { - if (addr.isHidden) { - countOfHiddenAddresses += 1; - return; - } - - countOfReceiveAddresses += 1; + addresses.forEach((addr) { + if (addr.isHidden) { + countOfHiddenAddresses += 1; + return; } + + countOfReceiveAddresses += 1; }); if (countOfReceiveAddresses < defaultReceiveAddressesCount) { From f33a785ec3a967160862cb6e473cc981449aac5f Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Mon, 12 Feb 2024 12:21:23 -0300 Subject: [PATCH 47/59] feat: improved perfomance for fetching transaction histories --- cw_bitcoin/lib/bitcoin_address_record.dart | 22 +++- cw_bitcoin/lib/bitcoin_wallet.dart | 4 +- cw_bitcoin/lib/bitcoin_wallet_service.dart | 10 +- cw_bitcoin/lib/electrum_wallet.dart | 100 ++++++++---------- cw_bitcoin/lib/electrum_wallet_addresses.dart | 64 ++++++----- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 4 +- cw_bitcoin/lib/litecoin_wallet.dart | 4 +- .../lib/src/bitcoin_cash_wallet.dart | 3 +- cw_core/lib/wallet_addresses.dart | 1 - cw_core/lib/wallet_info.dart | 3 + 10 files changed, 121 insertions(+), 94 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index b45fec2f7..d8d908230 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:bitbox/bitbox.dart' as bitbox; import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:cw_bitcoin/script_hash.dart' as sh; class BitcoinAddressRecord { BitcoinAddressRecord( @@ -13,12 +14,16 @@ class BitcoinAddressRecord { String name = '', bool isUsed = false, required this.type, + String? scriptHash, + required this.network, }) : _txCount = txCount, _balance = balance, _name = name, - _isUsed = isUsed; + _isUsed = isUsed, + scriptHash = + scriptHash ?? (network != null ? sh.scriptHash(address, network: network) : null); - factory BitcoinAddressRecord.fromJSON(String jsonSource) { + factory BitcoinAddressRecord.fromJSON(String jsonSource, BasedUtxoNetwork? network) { final decoded = json.decode(jsonSource) as Map; return BitcoinAddressRecord( @@ -33,6 +38,10 @@ class BitcoinAddressRecord { ? BitcoinAddressType.values .firstWhere((type) => type.toString() == decoded['type'] as String) : SegwitAddresType.p2wpkh, + scriptHash: decoded['scriptHash'] as String?, + network: (decoded['network'] as String?) == null + ? network + : BasedUtxoNetwork.fromName(decoded['network'] as String), ); } @@ -46,6 +55,8 @@ class BitcoinAddressRecord { int _balance; String _name; bool _isUsed; + String? scriptHash; + BasedUtxoNetwork? network; int get txCount => _txCount; @@ -69,6 +80,11 @@ class BitcoinAddressRecord { BitcoinAddressType type; + String updateScriptHash(BasedUtxoNetwork network) { + scriptHash = sh.scriptHash(address, network: network); + return scriptHash!; + } + String toJSON() => json.encode({ 'address': address, 'index': index, @@ -78,5 +94,7 @@ class BitcoinAddressRecord { 'name': name, 'balance': balance, 'type': type.toString(), + 'scriptHash': scriptHash, + 'network': network?.value, }); } diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 38c774104..3b3e9c636 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -92,7 +92,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, + walletInfo.network != null ? BasedUtxoNetwork.fromName(walletInfo.network!) : null); + return BitcoinWallet( mnemonic: snp.mnemonic, password: password, diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 893b90500..2b8c489d2 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -25,12 +25,15 @@ class BitcoinWalletService extends WalletService create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async { + final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet; + credentials.walletInfo?.network = network.value; + final wallet = await BitcoinWalletBase.create( mnemonic: await generateMnemonic(), password: credentials.password!, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, - network: (isTestnet ?? false) ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet, + network: network, ); await wallet.save(); await wallet.init(); @@ -106,12 +109,15 @@ class BitcoinWalletService extends WalletService updateUnspent() async { List updatedUnspentCoins = []; + final addressesSet = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); + await Future.wait(walletAddresses.allAddresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, network) .then((unspent) => Future.forEach>(unspent, (unspent) async { try { final coin = BitcoinUnspent.fromJSON(address, unspent); - final tx = await fetchTransactionInfo(hash: coin.hash, height: 0); + final tx = await fetchTransactionInfo( + hash: coin.hash, height: 0, myAddresses: addressesSet); coin.isChange = tx?.direction == TransactionDirection.outgoing; updatedUnspentCoins.add(coin); } catch (_) {} @@ -633,12 +636,11 @@ abstract class ElectrumWalletBase } Future fetchTransactionInfo( - {required String hash, required int height}) async { + {required String hash, required int height, required Set myAddresses}) async { try { - final tx = await getTransactionExpanded(hash: hash, height: height); - final addresses = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); - return ElectrumTransactionInfo.fromElectrumBundle(tx, walletInfo.type, network, - addresses: addresses, height: height); + return ElectrumTransactionInfo.fromElectrumBundle( + await getTransactionExpanded(hash: hash, height: height), walletInfo.type, network, + addresses: myAddresses, height: height); } catch (_) { return null; } @@ -646,61 +648,45 @@ abstract class ElectrumWalletBase @override Future> fetchTransactions() async { - final addressHashes = {}; - final normalizedHistories = >[]; - final newTxCounts = {}; - - walletAddresses.allAddresses.forEach((addressRecord) { - final sh = scriptHash(addressRecord.address, network: network); - addressHashes[sh] = addressRecord; - newTxCounts[sh] = 0; - }); - try { - final histories = addressHashes.keys.map((scriptHash) => - electrumClient.getHistory(scriptHash).then((history) => {scriptHash: history})); - final historyResults = await Future.wait(histories); + final Map historiesWithDetails = {}; + final addressesSet = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); - historyResults.forEach((history) { - history.entries.forEach((historyItem) { - if (historyItem.value.isNotEmpty) { - final address = addressHashes[historyItem.key]; - address?.setAsUsed(); - newTxCounts[historyItem.key] = historyItem.value.length; - normalizedHistories.addAll(historyItem.value); - } - }); - }); + await Future.wait(walletAddresses.allAddresses.map((addressRecord) => electrumClient + .getHistory(addressRecord.scriptHash ?? addressRecord.updateScriptHash(network)) + .then((history) async { + if (history.isNotEmpty) { + addressRecord.setAsUsed(); - for (var sh in addressHashes.keys) { - var balanceData = await electrumClient.getBalance(sh); - var addressRecord = addressHashes[sh]; - if (addressRecord != null) { - addressRecord.balance = balanceData['confirmed'] as int? ?? 0; - } - } + await Future.wait(history.map((transaction) async { + final txid = transaction['tx_hash'] as String; + final storedTx = transactionHistory.transactions[txid]; - addressHashes.forEach((sh, addressRecord) { - addressRecord.txCount = newTxCounts[sh] ?? 0; - }); + if (storedTx != null) { + // TODO: updated confs & time + historiesWithDetails[txid] = storedTx; + } else { + final tx = await fetchTransactionInfo( + hash: txid, + height: transaction['height'] as int, + myAddresses: addressesSet, + ); + if (tx != null) { + historiesWithDetails[txid] = tx; - final historiesWithDetails = await Future.wait(normalizedHistories.map((transaction) { - try { - return fetchTransactionInfo( - hash: transaction['tx_hash'] as String, height: transaction['height'] as int); - } catch (_) { - return Future.value(null); - } - })); + // Got a new transaction fetched, add it to the transaction history + // instead of waiting all to finish, and next time it will be faster + transactionHistory.addOne(tx); + await transactionHistory.save(); + } + } - return historiesWithDetails.fold>( - {}, (acc, tx) { - if (tx == null) { - return acc; - } - acc[tx.id] = acc[tx.id]?.updated(tx) ?? tx; - return acc; - }); + return Future.value(null); + })); + } + }))); + + return historiesWithDetails; } catch (e) { print(e.toString()); return {}; @@ -714,10 +700,8 @@ abstract class ElectrumWalletBase } _isTransactionUpdating = true; - final transactions = await fetchTransactions(); - transactionHistory.addMany(transactions); + await fetchTransactions(); walletAddresses.updateReceiveAddresses(); - await transactionHistory.save(); _isTransactionUpdating = false; } catch (e, stacktrace) { print(stacktrace); diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 99af4cec3..d7943b57e 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -24,6 +24,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { Map? initialRegularAddressIndex, Map? initialChangeAddressIndex, }) : _addresses = ObservableList.of((initialAddresses ?? []).toSet()), + addresses = ObservableList.of(([]).toSet()), receiveAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed) .toSet()), @@ -35,7 +36,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { _addressPageType = walletInfo.addressPageType != null ? BitcoinAddressType.fromValue(walletInfo.addressPageType!) : SegwitAddresType.p2wpkh, - super(walletInfo); + super(walletInfo) { + updateAddressesByMatch(); + } static const defaultReceiveAddressesCount = 22; static const defaultChangeAddressesCount = 17; @@ -46,7 +49,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { static String toLegacy(String address) => bitbox.Address.toLegacyAddress(address); final ObservableList _addresses; - + // Matched by addressPageType + late ObservableList addresses; final ObservableList receiveAddresses; final ObservableList changeAddresses; final ElectrumClient electrumClient; @@ -64,17 +68,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @override String get addressPageTypeStr => addressPageType.toString(); - @computed - List get addresses => _addresses.where(_isAddressPageTypeMatch).toList(); - @computed List get allAddresses => _addresses; - void set addresses(List addresses) { - _addresses.clear(); - _addresses.addAll(addresses); - } - @override @computed String get address { @@ -162,7 +158,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { await _discoverAddresses(true, type: SegwitAddresType.p2tr); await _discoverAddresses(false, type: SegwitAddresType.p2wsh); await _discoverAddresses(true, type: SegwitAddresType.p2wsh); + updateAddressesByMatch(); updateReceiveAddresses(); + updateChangeAddresses(); await updateAddressesInBox(); } @@ -173,6 +171,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh); await _generateInitialAddresses(type: SegwitAddresType.p2tr); await _generateInitialAddresses(type: SegwitAddresType.p2wsh); + updateAddressesByMatch(); updateReceiveAddresses(); updateChangeAddresses(); await updateAddressesInBox(); @@ -212,12 +211,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { 0, (int acc, addressRecord) => addressRecord.isHidden == false ? acc + 1 : acc); final address = BitcoinAddressRecord( - getAddress(index: newAddressIndex, hd: mainHd, addressType: addressPageType), - index: newAddressIndex, - isHidden: false, - name: label, - type: addressPageType); - addresses.add(address); + getAddress(index: newAddressIndex, hd: mainHd, addressType: addressPageType), + index: newAddressIndex, + isHidden: false, + name: label, + type: addressPageType, + network: network, + ); + _addresses.add(address); + updateAddressesByMatch(); return address; } @@ -249,6 +251,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { _addresses.insert(index, addressRecord); } + @action + void updateAddressesByMatch() { + addresses.clear(); + addresses.addAll(_addresses.where(_isAddressPageTypeMatch).toList()); + } + @action void updateReceiveAddresses() { receiveAddresses.removeRange(0, receiveAddresses.length); @@ -271,15 +279,13 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action Future _discoverAddresses(bool isHidden, {BitcoinAddressType type = SegwitAddresType.p2wpkh}) async { - var hasAddrUse = true; List addrs; - final matchingAddresses = _addresses.where((addr) => _addressMatchHidden(addr, isHidden, type)); + final matchingAddresses = + _addresses.where((addr) => _addressMatchesTypeAndHidden(addr, isHidden, type)); - if (addresses.isNotEmpty) { + if (matchingAddresses.isNotEmpty) { if (!isHidden) { - final receiveAddressesList = - _addresses.where((addr) => _addressMatchHidden(addr, isHidden, type)).toList(); - validateSideHdAddresses(receiveAddressesList); + _validateSideHdAddresses(matchingAddresses.toList()); } addrs = matchingAddresses.toList(); @@ -291,6 +297,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { type: type); } + var hasAddrUse = true; while (hasAddrUse) { final addr = addrs.last.address; hasAddrUse = await _hasAddressUsed(addr); @@ -327,14 +334,14 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses; final newAddresses = await _createNewAddresses(addressesCount, startIndex: countOfReceiveAddresses, isHidden: false, type: type); - _addresses.addAll(newAddresses); + addAddresses(newAddresses); } if (countOfHiddenAddresses < defaultChangeAddressesCount) { final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses; final newAddresses = await _createNewAddresses(addressesCount, startIndex: countOfHiddenAddresses, isHidden: true, type: type); - _addresses.addAll(newAddresses); + addAddresses(newAddresses); } } @@ -348,6 +355,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { index: i, isHidden: isHidden, type: type ?? addressPageType, + network: network, ); list.add(address); } @@ -361,6 +369,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { addressesSet.addAll(addresses); this._addresses.clear(); this._addresses.addAll(addressesSet); + updateAddressesByMatch(); } Future _hasAddressUsed(String address) async { @@ -369,7 +378,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return transactionHistory.isNotEmpty; } - void validateSideHdAddresses(List addrWithTransactions) { + void _validateSideHdAddresses(List addrWithTransactions) { addrWithTransactions.forEach((element) { if (element.address != getAddress(index: element.index, hd: mainHd, addressType: element.type)) @@ -380,6 +389,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action Future setAddressType(BitcoinAddressType type) async { _addressPageType = type; + walletInfo.addressPageType = addressPageTypeStr; + await walletInfo.save(); } bool _isAddressPageTypeMatch(BitcoinAddressRecord addressRecord) { @@ -388,6 +399,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { bitcoin.HDWallet _getHd(bool isHidden) => isHidden ? sideHd : mainHd; bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) => addr.type == type; - bool _addressMatchHidden(BitcoinAddressRecord addr, bool isHidden, BitcoinAddressType type) => + bool _addressMatchesTypeAndHidden( + BitcoinAddressRecord addr, bool isHidden, BitcoinAddressType type) => _isAddressByType(addr, type) && addr.isHidden == isHidden; } diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 96879cc18..98c3753db 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -32,7 +32,7 @@ class ElectrumWalletSnapshot { Map regularAddressIndex; Map changeAddressIndex; - static Future load(String name, WalletType type, String password) async { + static Future load(String name, WalletType type, String password, BasedUtxoNetwork? network) async { final path = await pathForWallet(name: name, type: type); final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map; @@ -40,7 +40,7 @@ class ElectrumWalletSnapshot { final mnemonic = data['mnemonic'] as String; final addresses = addressesTmp .whereType() - .map((addr) => BitcoinAddressRecord.fromJSON(addr)) + .map((addr) => BitcoinAddressRecord.fromJSON(addr, network)) .toList(); final balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 1ce9555ac..d2379d5a5 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -1,3 +1,4 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -86,7 +87,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password); + final snp = + await ElectrumWalletSnapshot.load(name, walletInfo.type, password, LitecoinNetwork.mainnet); return LitecoinWallet( mnemonic: snp.mnemonic, password: password, diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 5cea061f5..66cc5fd96 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -94,7 +94,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWalletSnapshot.load( + name, walletInfo.type, password, BitcoinCashNetwork.mainnet); return BitcoinCashWallet( mnemonic: snp.mnemonic, password: password, diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index 9b82a6252..4b093cdf2 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -32,7 +32,6 @@ abstract class WalletAddresses { walletInfo.addresses = addressesMap; walletInfo.addressInfos = addressInfos; walletInfo.usedAddresses = usedAddresses.toList(); - walletInfo.addressPageType = addressPageTypeStr; if (walletInfo.isInBox) { await walletInfo.save(); diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index 3867157f0..2a44175a7 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -151,6 +151,9 @@ class WalletInfo extends HiveObject { @HiveField(18) String? addressPageType; + @HiveField(19) + String? network; + String get yatLastUsedAddress => yatLastUsedAddressRaw ?? ''; set yatLastUsedAddress(String address) { From c0dc53018ee76b92ddc9a9f2eb5b226c2c2b4d0a Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Tue, 13 Feb 2024 17:59:49 -0300 Subject: [PATCH 48/59] feat: continue perfomance change, improve address discovery only to last address by type with history --- cw_bitcoin/lib/electrum_transaction_info.dart | 3 +- cw_bitcoin/lib/electrum_wallet.dart | 112 +++++++++++++----- cw_bitcoin/lib/electrum_wallet_addresses.dart | 93 +++++---------- 3 files changed, 112 insertions(+), 96 deletions(-) diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index 89baf2f8e..cfea0e089 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -11,11 +11,12 @@ import 'package:cw_core/wallet_type.dart'; class ElectrumTransactionBundle { ElectrumTransactionBundle(this.originalTransaction, - {required this.ins, required this.confirmations, this.time}); + {required this.ins, required this.confirmations, this.time, required this.height}); final BtcTransaction originalTransaction; final List ins; final int? time; final int confirmations; + final int height; } class ElectrumTransactionInfo extends TransactionInfo { diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 4aaa80df6..16051871e 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -157,7 +157,6 @@ abstract class ElectrumWalletBase Future startSync() async { try { syncStatus = AttemptingSyncStatus(); - await walletAddresses.discoverAddressesAll(); await updateTransactions(); _subscribeForUpdates(); await updateUnspent(); @@ -632,7 +631,8 @@ abstract class ElectrumWalletBase } } - return ElectrumTransactionBundle(original, ins: ins, time: time, confirmations: confirmations); + return ElectrumTransactionBundle(original, + ins: ins, time: time, confirmations: confirmations, height: height); } Future fetchTransactionInfo( @@ -641,7 +641,11 @@ abstract class ElectrumWalletBase return ElectrumTransactionInfo.fromElectrumBundle( await getTransactionExpanded(hash: hash, height: height), walletInfo.type, network, addresses: myAddresses, height: height); - } catch (_) { + } catch (e) { + if (e is FormatException) { + await Future.delayed(const Duration(seconds: 2)); + return fetchTransactionInfo(hash: hash, height: height, myAddresses: myAddresses); + } return null; } } @@ -651,40 +655,86 @@ abstract class ElectrumWalletBase try { final Map historiesWithDetails = {}; final addressesSet = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); + final currentHeight = await electrumClient.getCurrentBlockChainTip() ?? 0; - await Future.wait(walletAddresses.allAddresses.map((addressRecord) => electrumClient - .getHistory(addressRecord.scriptHash ?? addressRecord.updateScriptHash(network)) - .then((history) async { - if (history.isNotEmpty) { - addressRecord.setAsUsed(); + await Future.wait(ADDRESS_TYPES.map((type) { + final addressesByType = walletAddresses.allAddresses.where((addr) => addr.type == type); - await Future.wait(history.map((transaction) async { - final txid = transaction['tx_hash'] as String; - final storedTx = transactionHistory.transactions[txid]; + return Future.wait(addressesByType.map((addressRecord) async { + final history = await _fetchAddressHistory(addressRecord, addressesSet, currentHeight); - if (storedTx != null) { - // TODO: updated confs & time - historiesWithDetails[txid] = storedTx; - } else { - final tx = await fetchTransactionInfo( - hash: txid, - height: transaction['height'] as int, - myAddresses: addressesSet, - ); - if (tx != null) { - historiesWithDetails[txid] = tx; + if (history.isNotEmpty) { + addressRecord.txCount = history.length; + historiesWithDetails.addAll(history); - // Got a new transaction fetched, add it to the transaction history - // instead of waiting all to finish, and next time it will be faster - transactionHistory.addOne(tx); - await transactionHistory.save(); - } - } + final matchedAddresses = + addressesByType.where((addr) => addr.isHidden == addressRecord.isHidden); - return Future.value(null); - })); + final isLastUsedAddress = + history.isNotEmpty && addressRecord.address == matchedAddresses.last.address; + + if (isLastUsedAddress) { + await walletAddresses.discoverAddresses( + matchedAddresses.toList(), + addressRecord.isHidden, + (address, addressesSet) => + _fetchAddressHistory(address, addressesSet, currentHeight) + .then((history) => history.isNotEmpty ? address.address : null), + type: type); } - }))); + } + })); + })); + + return historiesWithDetails; + } catch (e) { + print(e.toString()); + return {}; + } + } + + Future> _fetchAddressHistory( + BitcoinAddressRecord addressRecord, Set addressesSet, int currentHeight) async { + try { + final Map historiesWithDetails = {}; + + final history = await electrumClient + .getHistory(addressRecord.scriptHash ?? addressRecord.updateScriptHash(network)); + + if (history.isNotEmpty) { + addressRecord.setAsUsed(); + + await Future.wait(history.map((transaction) async { + final txid = transaction['tx_hash'] as String; + final height = transaction['height'] as int; + final storedTx = transactionHistory.transactions[txid]; + + if (storedTx != null) { + if (height > 0) { + storedTx.height = height; + // the tx's block itself is the first confirmation so add 1 + storedTx.confirmations = currentHeight - height + 1; + storedTx.isPending = storedTx.confirmations == 0; + } + + historiesWithDetails[txid] = storedTx; + } else { + final tx = + await fetchTransactionInfo(hash: txid, height: height, myAddresses: addressesSet); + + if (tx != null) { + historiesWithDetails[txid] = tx; + + // Got a new transaction fetched, add it to the transaction history + // instead of waiting all to finish, and next time it will be faster + transactionHistory.addOne(tx); + await transactionHistory.save(); + } + } + + return Future.value(null); + })); + } return historiesWithDetails; } catch (e) { diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index d7943b57e..56db4b284 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -3,7 +3,6 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitbox/bitbox.dart' as bitbox; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum.dart'; -import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; @@ -13,6 +12,14 @@ part 'electrum_wallet_addresses.g.dart'; class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses; +const List ADDRESS_TYPES = [ + SegwitAddresType.p2wpkh, + P2pkhAddressType.p2pkh, + SegwitAddresType.p2tr, + SegwitAddresType.p2wsh, + P2shAddressType.p2wpkhInP2sh, +]; + abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { ElectrumWalletAddressesBase( WalletInfo walletInfo, { @@ -147,23 +154,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return acc; }); - Future discoverAddressesAll() async { - await _discoverAddresses(false); - await _discoverAddresses(true); - await _discoverAddresses(false, type: P2pkhAddressType.p2pkh); - await _discoverAddresses(true, type: P2pkhAddressType.p2pkh); - await _discoverAddresses(false, type: P2shAddressType.p2wpkhInP2sh); - await _discoverAddresses(true, type: P2shAddressType.p2wpkhInP2sh); - await _discoverAddresses(false, type: SegwitAddresType.p2tr); - await _discoverAddresses(true, type: SegwitAddresType.p2tr); - await _discoverAddresses(false, type: SegwitAddresType.p2wsh); - await _discoverAddresses(true, type: SegwitAddresType.p2wsh); - updateAddressesByMatch(); - updateReceiveAddresses(); - updateChangeAddresses(); - await updateAddressesInBox(); - } - @override Future init() async { await _generateInitialAddresses(); @@ -277,43 +267,24 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } @action - Future _discoverAddresses(bool isHidden, + Future discoverAddresses(List addressList, bool isHidden, + Future Function(BitcoinAddressRecord, Set) getAddressHistory, {BitcoinAddressType type = SegwitAddresType.p2wpkh}) async { - List addrs; - final matchingAddresses = - _addresses.where((addr) => _addressMatchesTypeAndHidden(addr, isHidden, type)); - - if (matchingAddresses.isNotEmpty) { - if (!isHidden) { - _validateSideHdAddresses(matchingAddresses.toList()); - } - - addrs = matchingAddresses.toList(); - } else { - addrs = await _createNewAddresses( - isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, - startIndex: 0, - isHidden: isHidden, - type: type); + if (!isHidden) { + _validateSideHdAddresses(addressList.toList()); } - var hasAddrUse = true; - while (hasAddrUse) { - final addr = addrs.last.address; - hasAddrUse = await _hasAddressUsed(addr); + final newAddresses = await _createNewAddresses(gap, + startIndex: addressList.length, isHidden: isHidden, type: type); + addAddresses(newAddresses); - if (!hasAddrUse) { - break; - } + final addressesWithHistory = await Future.wait(newAddresses + .map((addr) => getAddressHistory(addr, _addresses.map((e) => e.address).toSet()))); + final isLastAddressUsed = addressesWithHistory.last == addressList.last.address; - final start = addrs.length; - final count = start + gap; - final batch = - await _createNewAddresses(count, startIndex: start, isHidden: isHidden, type: type); - addrs.addAll(batch); + if (isLastAddressUsed) { + discoverAddresses(addressList, isHidden, getAddressHistory, type: type); } - - addAddresses(addrs); } Future _generateInitialAddresses( @@ -321,13 +292,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { var countOfReceiveAddresses = 0; var countOfHiddenAddresses = 0; - addresses.forEach((addr) { - if (addr.isHidden) { - countOfHiddenAddresses += 1; - return; - } + _addresses.forEach((addr) { + if (addr.type == type) { + if (addr.isHidden) { + countOfHiddenAddresses += 1; + return; + } - countOfReceiveAddresses += 1; + countOfReceiveAddresses += 1; + } }); if (countOfReceiveAddresses < defaultReceiveAddressesCount) { @@ -372,12 +345,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { updateAddressesByMatch(); } - Future _hasAddressUsed(String address) async { - final sh = scriptHash(address, network: network); - final transactionHistory = await electrumClient.getHistory(sh); - return transactionHistory.isNotEmpty; - } - void _validateSideHdAddresses(List addrWithTransactions) { addrWithTransactions.forEach((element) { if (element.address != @@ -389,6 +356,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action Future setAddressType(BitcoinAddressType type) async { _addressPageType = type; + updateAddressesByMatch(); walletInfo.addressPageType = addressPageTypeStr; await walletInfo.save(); } @@ -399,7 +367,4 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { bitcoin.HDWallet _getHd(bool isHidden) => isHidden ? sideHd : mainHd; bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) => addr.type == type; - bool _addressMatchesTypeAndHidden( - BitcoinAddressRecord addr, bool isHidden, BitcoinAddressType type) => - _isAddressByType(addr, type) && addr.isHidden == isHidden; } From 53ed8fa1b2acd2554795f892b7cda12c5f9c10b9 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Tue, 13 Feb 2024 18:24:43 -0300 Subject: [PATCH 49/59] fix: make sure transaction list is sorted by date --- .../dashboard/dashboard_view_model.dart | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index a794c2262..da5eb0373 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -148,17 +148,21 @@ abstract class DashboardViewModelBase with Store { monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id) .toList(); - transactions = ObservableList.of(_accountTransactions.map((transaction) => - TransactionListItem( - transaction: transaction, - balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore))); + final sortedTransactions = [..._accountTransactions]; + sortedTransactions.sort((a, b) => a.date.compareTo(b.date)); + + transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem( + transaction: transaction, + balanceViewModel: balanceViewModel, + settingsStore: appStore.settingsStore))); } else { - transactions = ObservableList.of(wallet.transactionHistory.transactions.values.map( - (transaction) => TransactionListItem( - transaction: transaction, - balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore))); + final sortedTransactions = [...wallet.transactionHistory.transactions.values]; + sortedTransactions.sort((a, b) => a.date.compareTo(b.date)); + + transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem( + transaction: transaction, + balanceViewModel: balanceViewModel, + settingsStore: appStore.settingsStore))); } // TODO: nano sub-account generation is disabled: From dd43498d5c3e4fb3a0293c3d01ed66aec71ce1d5 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 15 Feb 2024 14:30:24 -0300 Subject: [PATCH 50/59] refactor: isTestnet only for bitcoin --- cw_bitcoin/lib/litecoin_wallet_service.dart | 35 +- .../lib/src/bitcoin_cash_wallet_service.dart | 42 +- cw_core/lib/wallet_service.dart | 6 +- cw_ethereum/lib/ethereum_wallet_service.dart | 7 +- cw_evm/lib/evm_chain_wallet_service.dart | 6 +- cw_haven/lib/haven_wallet_service.dart | 53 +-- cw_monero/lib/monero_wallet_service.dart | 8 +- cw_nano/lib/nano_wallet_service.dart | 6 +- cw_polygon/lib/polygon_wallet_service.dart | 8 +- lib/bitcoin/cw_bitcoin.dart | 379 +++++++++--------- lib/core/wallet_creation_service.dart | 23 +- tool/configure.dart | 5 + 12 files changed, 298 insertions(+), 280 deletions(-) diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 3d7462fa1..248804ca1 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -12,10 +12,8 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:collection/collection.dart'; -class LitecoinWalletService extends WalletService< - BitcoinNewWalletCredentials, - BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { +class LitecoinWalletService extends WalletService { LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -25,7 +23,7 @@ class LitecoinWalletService extends WalletService< WalletType getType() => WalletType.litecoin; @override - Future create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async { + Future create(BitcoinNewWalletCredentials credentials) async { final wallet = await LitecoinWalletBase.create( mnemonic: await generateMnemonic(), password: credentials.password!, @@ -43,12 +41,14 @@ class LitecoinWalletService 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()))!; try { final wallet = await LitecoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, + password: password, + name: name, + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); saveBackup(name); @@ -56,7 +56,9 @@ class LitecoinWalletService extends WalletService< } catch (_) { await restoreWalletFilesFromBackup(name); final wallet = await LitecoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, + password: password, + name: name, + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; @@ -65,17 +67,16 @@ class LitecoinWalletService 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 LitecoinWalletBase.open( password: password, name: currentName, @@ -94,12 +95,12 @@ class LitecoinWalletService extends WalletService< @override Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async => + BitcoinRestoreWalletFromWIFCredentials credentials) async => throw UnimplementedError(); @override Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { + BitcoinRestoreWalletFromSeedCredentials credentials) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } 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 8ad7da8bf..1b442dfc4 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -15,8 +15,7 @@ import 'package:collection/collection.dart'; import 'package:hive/hive.dart'; class BitcoinCashWalletService extends WalletService { + BitcoinCashRestoreWalletFromSeedCredentials, BitcoinCashRestoreWalletFromWIFCredentials> { BitcoinCashWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -30,13 +29,12 @@ class BitcoinCashWalletService extends WalletService create( - credentials, {bool? isTestnet}) async { + Future create(credentials) async { final strength = (credentials.seedPhraseLength == 12) ? 128 : (credentials.seedPhraseLength == 24) - ? 256 - : 128; + ? 256 + : 128; final wallet = await BitcoinCashWalletBase.create( mnemonic: await Mnemonic.generate(strength: strength), password: credentials.password!, @@ -49,21 +47,25 @@ class BitcoinCashWalletService extends WalletService 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()))!; try { final wallet = await BitcoinCashWalletBase.open( - password: password, name: name, walletInfo: walletInfo, + password: password, + name: name, + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); saveBackup(name); return wallet; - } catch(_) { + } catch (_) { await restoreWalletFilesFromBackup(name); final wallet = await BitcoinCashWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + password: password, + name: name, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; } @@ -71,17 +73,16 @@ class BitcoinCashWalletService extends WalletService 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 BitcoinCashWalletBase.open( password: password, name: currentName, @@ -99,15 +100,14 @@ class BitcoinCashWalletService extends WalletService - restoreFromKeys(credentials, {bool? isTestnet}) { + Future restoreFromKeys(credentials) { // TODO: implement restoreFromKeys throw UnimplementedError('restoreFromKeys() is not implemented'); } @override Future restoreFromSeed( - BitcoinCashRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { + BitcoinCashRestoreWalletFromSeedCredentials credentials) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinCashMnemonicIsIncorrectException(); } diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index 22981b9db..3b4908386 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -9,11 +9,11 @@ abstract class WalletService { WalletType getType(); - Future create(N credentials, {bool? isTestnet}); + Future create(N credentials); - Future restoreFromSeed(RFS credentials, {bool? isTestnet}); + Future restoreFromSeed(RFS credentials); - Future restoreFromKeys(RFK credentials, {bool? isTestnet}); + Future restoreFromKeys(RFK credentials); Future openWallet(String name, String password); diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 105da984a..3b8f9b34f 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -16,7 +16,7 @@ class EthereumWalletService extends EVMChainWalletService { WalletType getType() => WalletType.ethereum; @override - Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}) async { + Future create(EVMChainNewWalletCredentials credentials) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -52,7 +52,6 @@ class EthereumWalletService extends EVMChainWalletService { saveBackup(name); return wallet; } catch (_) { - await restoreWalletFilesFromBackup(name); final wallet = await EthereumWallet.open( @@ -84,7 +83,7 @@ class EthereumWalletService extends EVMChainWalletService { } @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, {bool? isTestnet}) async { + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials) async { final wallet = EthereumWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -101,7 +100,7 @@ class EthereumWalletService extends EVMChainWalletService { @override Future restoreFromSeed( - EVMChainRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { + EVMChainRestoreWalletFromSeedCredentials credentials) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw EthereumMnemonicIsIncorrectException(); } diff --git a/cw_evm/lib/evm_chain_wallet_service.dart b/cw_evm/lib/evm_chain_wallet_service.dart index d77a3a81a..988a38684 100644 --- a/cw_evm/lib/evm_chain_wallet_service.dart +++ b/cw_evm/lib/evm_chain_wallet_service.dart @@ -22,7 +22,7 @@ abstract class EVMChainWalletService extends WalletSer WalletType getType(); @override - Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}); + Future create(EVMChainNewWalletCredentials credentials); @override Future openWallet(String name, String password); @@ -31,10 +31,10 @@ abstract class EVMChainWalletService extends WalletSer Future rename(String currentName, String password, String newName); @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, {bool? isTestnet}); + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials); @override - Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}); + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials); @override Future isWalletExit(String name) async => diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index d4808c2d6..110d01fea 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -22,10 +22,7 @@ class HavenNewWalletCredentials extends WalletCredentials { class HavenRestoreWalletFromSeedCredentials extends WalletCredentials { HavenRestoreWalletFromSeedCredentials( - {required String name, - required String password, - required int height, - required this.mnemonic}) + {required String name, required String password, required int height, required this.mnemonic}) : super(name: name, password: password, height: height); final String mnemonic; @@ -53,14 +50,12 @@ class HavenRestoreWalletFromKeysCredentials extends WalletCredentials { final String spendKey; } -class HavenWalletService extends WalletService< - HavenNewWalletCredentials, - HavenRestoreWalletFromSeedCredentials, - HavenRestoreWalletFromKeysCredentials> { +class HavenWalletService extends WalletService { HavenWalletService(this.walletInfoSource); final Box walletInfoSource; - + static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync(); @@ -68,13 +63,11 @@ class HavenWalletService extends WalletService< WalletType getType() => WalletType.haven; @override - Future create(HavenNewWalletCredentials credentials, {bool? isTestnet}) async { + Future create(HavenNewWalletCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.createWallet( - path: path, - password: credentials.password!, - language: credentials.language); + path: path, password: credentials.password!, language: credentials.language); final wallet = HavenWallet(walletInfo: credentials.walletInfo!); await wallet.init(); return wallet; @@ -106,10 +99,9 @@ class HavenWalletService extends WalletService< await repairOldAndroidWallet(name); } - await haven_wallet_manager - .openWalletAsync({'path': path, 'password': password}); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; + await haven_wallet_manager.openWalletAsync({'path': path, 'password': password}); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = HavenWallet(walletInfo: walletInfo); final isValid = wallet.walletAddresses.validate(); @@ -126,12 +118,10 @@ class HavenWalletService extends WalletService< // TODO: Implement Exception for wallet list service. if ((e.toString().contains('bad_alloc') || - (e is WalletOpeningException && - (e.message == 'std::bad_alloc' || - e.message.contains('bad_alloc')))) || + (e is WalletOpeningException && + (e.message == 'std::bad_alloc' || e.message.contains('bad_alloc')))) || (e.toString().contains('does not correspond') || - (e is WalletOpeningException && - e.message.contains('does not correspond')))) { + (e is WalletOpeningException && e.message.contains('does not correspond')))) { await restoreOrResetWalletFiles(name); return openWallet(name, password); } @@ -156,10 +146,9 @@ class HavenWalletService extends WalletService< } @override - Future rename( - String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhere( - (info) => info.id == WalletBase.idFor(currentName, getType())); + Future rename(String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); final currentWallet = HavenWallet(walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); @@ -173,8 +162,7 @@ class HavenWalletService extends WalletService< } @override - Future restoreFromKeys( - HavenRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { + Future restoreFromKeys(HavenRestoreWalletFromKeysCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.restoreFromKeys( @@ -197,8 +185,7 @@ class HavenWalletService extends WalletService< } @override - Future restoreFromSeed( - HavenRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { + Future restoreFromSeed(HavenRestoreWalletFromSeedCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.restoreFromSeed( @@ -223,16 +210,14 @@ class HavenWalletService extends WalletService< return; } - final oldAndroidWalletDirPath = - await outdatedAndroidPathForWalletDir(name: name); + final oldAndroidWalletDirPath = await outdatedAndroidPathForWalletDir(name: name); final dir = Directory(oldAndroidWalletDirPath); if (!dir.existsSync()) { return; } - final newWalletDirPath = - await pathForWalletDir(name: name, type: getType()); + final newWalletDirPath = await pathForWalletDir(name: name, type: getType()); dir.listSync().forEach((f) { final file = File(f.path); diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 1f33dbb3d..3dea7fc0e 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -68,7 +68,7 @@ class MoneroWalletService extends WalletService WalletType.monero; @override - Future create(MoneroNewWalletCredentials credentials, {bool? isTestnet}) async { + Future create(MoneroNewWalletCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); @@ -203,8 +203,7 @@ class MoneroWalletService extends WalletService restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials, - {bool? isTestnet}) async { + Future restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.restoreFromKeys( @@ -228,8 +227,7 @@ class MoneroWalletService extends WalletService restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials, - {bool? isTestnet}) async { + Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials) async { // Restore from Polyseed if (Polyseed.isValidSeed(credentials.mnemonic)) { return restoreFromPolyseed(credentials); diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index 7ab502d49..a76f0393d 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -26,7 +26,7 @@ class NanoWalletService extends WalletService WalletType.nano; @override - Future create(NanoNewWalletCredentials credentials, {bool? isTestnet}) async { + Future create(NanoNewWalletCredentials credentials) async { // nano standard: DerivationType derivationType = DerivationType.nano; String seedKey = NanoSeeds.generateSeed(); @@ -79,7 +79,7 @@ class NanoWalletService extends WalletService restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { + Future restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials) async { if (credentials.seedKey.contains(' ')) { throw Exception("Invalid key!"); } else { @@ -113,7 +113,7 @@ class NanoWalletService extends WalletService restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { + Future restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials) async { if (credentials.mnemonic.contains(' ')) { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw nm.NanoMnemonicIsIncorrectException(); diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index c370b8841..32688e7e3 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -19,7 +19,7 @@ class PolygonWalletService extends EVMChainWalletService { WalletType getType() => WalletType.polygon; @override - Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}) async { + Future create(EVMChainNewWalletCredentials credentials) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -62,7 +62,7 @@ class PolygonWalletService extends EVMChainWalletService { password: password, walletInfo: walletInfo, ); - + await wallet.init(); await wallet.save(); return wallet; @@ -70,7 +70,7 @@ class PolygonWalletService extends EVMChainWalletService { } @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, {bool? isTestnet}) async { + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials) async { final wallet = PolygonWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -87,7 +87,7 @@ class PolygonWalletService extends EVMChainWalletService { @override Future restoreFromSeed( - EVMChainRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { + EVMChainRestoreWalletFromSeedCredentials credentials) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw PolygonMnemonicIsIncorrectException(); } diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 43f9a4e63..cbc965a27 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -1,196 +1,211 @@ part of 'bitcoin.dart'; class CWBitcoin extends Bitcoin { - @override - TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium; - - @override - WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({ - required String name, - required String mnemonic, - required String password}) - => BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password); - - @override - WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({ - required String name, - required String password, - required String wif, - WalletInfo? walletInfo}) - => BitcoinRestoreWalletFromWIFCredentials(name: name, password: password, wif: wif, walletInfo: walletInfo); - - @override - WalletCredentials createBitcoinNewWalletCredentials({ - required String name, - WalletInfo? walletInfo}) - => BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo); - - @override - List getWordList() => wordlist; - - @override - Map getWalletKeys(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - final keys = bitcoinWallet.keys; - - return { - 'wif': keys.wif, - 'privateKey': keys.privateKey, - 'publicKey': keys.publicKey - }; - } - - @override - List getTransactionPriorities() - => BitcoinTransactionPriority.all; - - @override - List getLitecoinTransactionPriorities() - => LitecoinTransactionPriority.all; - - @override - TransactionPriority deserializeBitcoinTransactionPriority(int raw) - => BitcoinTransactionPriority.deserialize(raw: raw); - - @override - TransactionPriority deserializeLitecoinTransactionPriority(int raw) - => LitecoinTransactionPriority.deserialize(raw: raw); - - @override - int getFeeRate(Object wallet, TransactionPriority priority) { - final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.feeRate(priority); - } - - @override - Future generateNewAddress(Object wallet, String label) async { - final bitcoinWallet = wallet as ElectrumWallet; - await bitcoinWallet.walletAddresses.generateNewAddress(label: label); - await wallet.save(); - } - - @override - Future updateAddress(Object wallet,String address, String label) async { - final bitcoinWallet = wallet as ElectrumWallet; - bitcoinWallet.walletAddresses.updateAddress(address, label); - await wallet.save(); - } - - @override - Object createBitcoinTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}) - => BitcoinTransactionCredentials( - outputs.map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) - .toList(), - priority: priority as BitcoinTransactionPriority, - feeRate: feeRate); - - @override - Object createBitcoinTransactionCredentialsRaw(List outputs, {TransactionPriority? priority, required int feeRate}) - => BitcoinTransactionCredentials( - outputs, - priority: priority != null ? priority as BitcoinTransactionPriority : null, - feeRate: feeRate); - - @override - List getAddresses(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.walletAddresses.addresses - .map((BitcoinAddressRecord addr) => addr.address) - .toList(); - } - - @override - @computed - List getSubAddresses(Object wallet) { - final electrumWallet = wallet as ElectrumWallet; - return electrumWallet.walletAddresses.addresses - .map((BitcoinAddressRecord addr) => ElectrumSubAddress( - id: addr.index, - name: addr.name, - address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address, - txCount: addr.txCount, - balance: addr.balance, - isChange: addr.isHidden)) - .toList(); - } - - @override - String getAddress(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.walletAddresses.address; - } - - @override - String formatterBitcoinAmountToString({required int amount}) - => bitcoinAmountToString(amount: amount); - - @override - double formatterBitcoinAmountToDouble({required int amount}) - => bitcoinAmountToDouble(amount: amount); - - @override - int formatterStringDoubleToBitcoinAmount(String amount) - => stringDoubleToBitcoinAmount(amount); + @override + TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium; @override - String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate) - => (priority as BitcoinTransactionPriority).labelWithRate(rate); - - @override - List getUnspents(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.unspentCoins; - } - - Future updateUnspents(Object wallet) async { - final bitcoinWallet = wallet as ElectrumWallet; - await bitcoinWallet.updateUnspent(); - } - - WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource) { - return BitcoinWalletService(walletInfoSource, unspentCoinSource); - } - - WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource) { - return LitecoinWalletService(walletInfoSource, unspentCoinSource); - } - - @override - TransactionPriority getBitcoinTransactionPriorityMedium() - => BitcoinTransactionPriority.medium; + WalletCredentials createBitcoinRestoreWalletFromSeedCredentials( + {required String name, required String mnemonic, required String password}) => + BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password); @override - TransactionPriority getLitecoinTransactionPriorityMedium() - => LitecoinTransactionPriority.medium; + WalletCredentials createBitcoinRestoreWalletFromWIFCredentials( + {required String name, + required String password, + required String wif, + WalletInfo? walletInfo}) => + BitcoinRestoreWalletFromWIFCredentials( + name: name, password: password, wif: wif, walletInfo: walletInfo); @override - TransactionPriority getBitcoinTransactionPrioritySlow() - => BitcoinTransactionPriority.slow; - + WalletCredentials createBitcoinNewWalletCredentials( + {required String name, WalletInfo? walletInfo}) => + BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo); + @override - TransactionPriority getLitecoinTransactionPrioritySlow() - => LitecoinTransactionPriority.slow; + List getWordList() => wordlist; - @override - Future setAddressType(Object wallet, dynamic option) async { - final bitcoinWallet = wallet as ElectrumWallet; - await bitcoinWallet.walletAddresses.setAddressType(option as BitcoinAddressType); - } + @override + Map getWalletKeys(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + final keys = bitcoinWallet.keys; - @override - BitcoinReceivePageOption getSelectedAddressType(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - return BitcoinReceivePageOption.fromType(bitcoinWallet.walletAddresses.addressPageType); - } + return { + 'wif': keys.wif, + 'privateKey': keys.privateKey, + 'publicKey': keys.publicKey + }; + } - @override - List getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all; + @override + List getTransactionPriorities() => BitcoinTransactionPriority.all; + + @override + List getLitecoinTransactionPriorities() => LitecoinTransactionPriority.all; + + @override + TransactionPriority deserializeBitcoinTransactionPriority(int raw) => + BitcoinTransactionPriority.deserialize(raw: raw); + + @override + TransactionPriority deserializeLitecoinTransactionPriority(int raw) => + LitecoinTransactionPriority.deserialize(raw: raw); + + @override + int getFeeRate(Object wallet, TransactionPriority priority) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.feeRate(priority); + } + + @override + Future generateNewAddress(Object wallet, String label) async { + final bitcoinWallet = wallet as ElectrumWallet; + await bitcoinWallet.walletAddresses.generateNewAddress(label: label); + await wallet.save(); + } + + @override + Future updateAddress(Object wallet, String address, String label) async { + final bitcoinWallet = wallet as ElectrumWallet; + bitcoinWallet.walletAddresses.updateAddress(address, label); + await wallet.save(); + } + + @override + Object createBitcoinTransactionCredentials(List outputs, + {required TransactionPriority priority, int? feeRate}) => + BitcoinTransactionCredentials( + outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount)) + .toList(), + priority: priority as BitcoinTransactionPriority, + feeRate: feeRate); + + @override + Object createBitcoinTransactionCredentialsRaw(List outputs, + {TransactionPriority? priority, required int feeRate}) => + BitcoinTransactionCredentials(outputs, + priority: priority != null ? priority as BitcoinTransactionPriority : null, + feeRate: feeRate); + + @override + List getAddresses(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.walletAddresses.addresses + .map((BitcoinAddressRecord addr) => addr.address) + .toList(); + } + + @override + @computed + List getSubAddresses(Object wallet) { + final electrumWallet = wallet as ElectrumWallet; + return electrumWallet.walletAddresses.addresses + .map((BitcoinAddressRecord addr) => ElectrumSubAddress( + id: addr.index, + name: addr.name, + address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address, + txCount: addr.txCount, + balance: addr.balance, + isChange: addr.isHidden)) + .toList(); + } + + @override + String getAddress(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.walletAddresses.address; + } + + @override + String formatterBitcoinAmountToString({required int amount}) => + bitcoinAmountToString(amount: amount); + + @override + double formatterBitcoinAmountToDouble({required int amount}) => + bitcoinAmountToDouble(amount: amount); + + @override + int formatterStringDoubleToBitcoinAmount(String amount) => stringDoubleToBitcoinAmount(amount); + + @override + String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate) => + (priority as BitcoinTransactionPriority).labelWithRate(rate); + + @override + List getUnspents(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.unspentCoins; + } + + Future updateUnspents(Object wallet) async { + final bitcoinWallet = wallet as ElectrumWallet; + await bitcoinWallet.updateUnspent(); + } + + WalletService createBitcoinWalletService( + Box walletInfoSource, Box unspentCoinSource) { + return BitcoinWalletService(walletInfoSource, unspentCoinSource); + } + + WalletService createLitecoinWalletService( + Box walletInfoSource, Box unspentCoinSource) { + return LitecoinWalletService(walletInfoSource, unspentCoinSource); + } + + @override + TransactionPriority getBitcoinTransactionPriorityMedium() => BitcoinTransactionPriority.medium; + + @override + TransactionPriority getLitecoinTransactionPriorityMedium() => LitecoinTransactionPriority.medium; + + @override + TransactionPriority getBitcoinTransactionPrioritySlow() => BitcoinTransactionPriority.slow; + + @override + TransactionPriority getLitecoinTransactionPrioritySlow() => LitecoinTransactionPriority.slow; + + @override + Future setAddressType(Object wallet, dynamic option) async { + final bitcoinWallet = wallet as ElectrumWallet; + await bitcoinWallet.walletAddresses.setAddressType(option as BitcoinAddressType); + } + + @override + BitcoinReceivePageOption getSelectedAddressType(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return BitcoinReceivePageOption.fromType(bitcoinWallet.walletAddresses.addressPageType); + } + + @override + List getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all; + + @override + Future create(WalletService service, WalletCredentials credentials, + {bool? isTestnet}) => + (service as BitcoinWalletService) + .create(credentials as BitcoinNewWalletCredentials, isTestnet: isTestnet); + + @override + Future restoreFromKeys(WalletService service, WalletCredentials credentials, + {bool? isTestnet}) => + (service as BitcoinWalletService).restoreFromKeys( + credentials as BitcoinRestoreWalletFromWIFCredentials, + isTestnet: isTestnet); + + @override + Future restoreFromSeed(WalletService service, WalletCredentials credentials, + {bool? isTestnet}) => + (service as BitcoinWalletService).restoreFromSeed( + credentials as BitcoinRestoreWalletFromSeedCredentials, + isTestnet: isTestnet); } diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index a97b3a9d0..addbef5b3 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -1,8 +1,8 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -63,7 +63,12 @@ class WalletCreationService { credentials.seedPhraseLength = settingsStore.seedPhraseLength.value; } await keyService.saveWalletPassword(password: password, walletName: credentials.name); - final wallet = await _service!.create(credentials, isTestnet: isTestnet); + WalletBase? wallet; + if (type == WalletType.bitcoin) { + wallet = await bitcoin!.create(_service!, credentials, isTestnet: isTestnet); + } else { + wallet = await _service!.create(credentials); + } if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( @@ -78,7 +83,12 @@ class WalletCreationService { final password = generateWalletPassword(); credentials.password = password; await keyService.saveWalletPassword(password: password, walletName: credentials.name); - final wallet = await _service!.restoreFromKeys(credentials, isTestnet: isTestnet); + WalletBase? wallet; + if (type == WalletType.bitcoin) { + wallet = await bitcoin!.restoreFromKeys(_service!, credentials, isTestnet: isTestnet); + } else { + wallet = await _service!.restoreFromKeys(credentials); + } if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( @@ -93,7 +103,12 @@ class WalletCreationService { final password = generateWalletPassword(); credentials.password = password; await keyService.saveWalletPassword(password: password, walletName: credentials.name); - final wallet = await _service!.restoreFromSeed(credentials, isTestnet: isTestnet); + WalletBase? wallet; + if (type == WalletType.bitcoin) { + wallet = await bitcoin!.restoreFromSeed(_service!, credentials, isTestnet: isTestnet); + } else { + wallet = await _service!.restoreFromSeed(credentials); + } if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( diff --git a/tool/configure.dart b/tool/configure.dart index aaacc4c36..e296f847d 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -72,12 +72,14 @@ import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; +import 'package:cw_bitcoin/bitcoin_wallet.dart'; import 'package:cw_bitcoin/bitcoin_wallet_service.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; +import 'package:cw_core/wallet_base.dart'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:mobx/mobx.dart'; """; @@ -140,6 +142,9 @@ abstract class Bitcoin { Future setAddressType(Object wallet, dynamic option); BitcoinReceivePageOption getSelectedAddressType(Object wallet); List getBitcoinReceivePageOptions(); + Future create(WalletService service, WalletCredentials credentials, {bool? isTestnet}); + Future restoreFromKeys(WalletService service, WalletCredentials credentials, {bool? isTestnet}); + Future restoreFromSeed(WalletService service, WalletCredentials credentials, {bool? isTestnet}); } """; From a395c7b040b9bd208c4eaf088a39e2b42bdd27ad Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 15 Feb 2024 14:54:36 -0300 Subject: [PATCH 51/59] fix: walletInfo type null case --- cw_bitcoin/lib/electrum_wallet.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 16051871e..c17affd58 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -386,7 +386,9 @@ abstract class ElectrumWalletBase 'account_index': walletAddresses.currentReceiveAddressIndexByType, 'change_address_index': walletAddresses.currentChangeAddressIndexByType, 'addresses': walletAddresses.allAddresses.map((addr) => addr.toJSON()).toList(), - 'address_page_type': walletInfo.addressPageType.toString(), + 'address_page_type': walletInfo.addressPageType == null + ? SegwitAddresType.p2wpkh.toString() + : walletInfo.addressPageType.toString(), 'balance': balance[currency]?.toJSON(), 'network_type': network == BitcoinNetwork.testnet ? 'testnet' : 'mainnet', }); From 90ca341289d443ecba656a28229411718a113167 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 15 Feb 2024 14:54:45 -0300 Subject: [PATCH 52/59] fix: deprecated p2pk --- cw_bitcoin/lib/address_from_output.dart | 2 -- lib/core/address_validator.dart | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index 50b178d2c..73bc101c4 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -3,8 +3,6 @@ import 'package:bitcoin_base/bitcoin_base.dart'; String addressFromOutputScript(Script script, BasedUtxoNetwork network) { try { switch (script.getAddressType()) { - case PubKeyAddressType.p2pk: - return P2pkAddress.fromScriptPubkey(script: script).toAddress(network); case P2pkhAddressType.p2pkh: return P2pkhAddress.fromScriptPubkey(script: script).toAddress(network); case P2shAddressType.p2pkInP2sh: diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 3505ef182..6964dfa94 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -263,7 +263,7 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)8[0-9a-zA-Z]{94}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[0-9a-zA-Z]{106}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.btc: - return '([^0-9a-zA-Z]|^)${P2pkAddress.regex.pattern}|\$)' + return '([^0-9a-zA-Z]|^)${P2pkhAddress.regex.pattern}|\$)' '([^0-9a-zA-Z]|^)${P2shAddress.regex.pattern}|\$)' '([^0-9a-zA-Z]|^)${P2wpkhAddress.regex.pattern}|\$)' '([^0-9a-zA-Z]|^)${P2wshAddress.regex.pattern}|\$)' From fd99ef0a42292a67dc74543cc5a93ec8ffb76f08 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 15 Feb 2024 15:45:18 -0300 Subject: [PATCH 53/59] refactor: make condition more readable --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 56db4b284..7895271be 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -89,10 +89,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { typeMatchingReceiveAddresses.isEmpty) { receiveAddress = generateNewAddress().address; } else { - if (previousAddressRecord != null && previousAddressRecord!.type == addressPageType) { - receiveAddress = (typeMatchingReceiveAddresses.first.address != addresses.first.address) - ? previousAddressRecord!.address - : typeMatchingReceiveAddresses.first.address; + final previousAddressMatchesType = + previousAddressRecord != null && previousAddressRecord!.type == addressPageType; + + if (previousAddressMatchesType && + typeMatchingReceiveAddresses.first.address != addresses.first.address) { + receiveAddress = previousAddressRecord!.address; } else { receiveAddress = typeMatchingReceiveAddresses.first.address; } From a310562e9c4cfe569610f14e2ba78c27ec031747 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 15 Feb 2024 16:09:08 -0300 Subject: [PATCH 54/59] refactor: remove unnecessary Str variant --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 6 +----- cw_core/lib/wallet_addresses.dart | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 7895271be..2e5c96102 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -71,10 +71,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @computed BitcoinAddressType get addressPageType => _addressPageType; - @computed - @override - String get addressPageTypeStr => addressPageType.toString(); - @computed List get allAddresses => _addresses; @@ -359,7 +355,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { Future setAddressType(BitcoinAddressType type) async { _addressPageType = type; updateAddressesByMatch(); - walletInfo.addressPageType = addressPageTypeStr; + walletInfo.addressPageType = addressPageType.toString(); await walletInfo.save(); } diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index 4b093cdf2..d8c84c80c 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -20,8 +20,6 @@ abstract class WalletAddresses { Set usedAddresses = {}; - String? addressPageTypeStr; - Future init(); Future updateAddressesInBox(); From ec82704c909beee01b4c9c6c5dacabe1494ca497 Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 15 Feb 2024 16:11:11 -0300 Subject: [PATCH 55/59] refactor: make condition more readable --- cw_bitcoin/lib/electrum_wallet.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index c17affd58..6b4da9c03 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -233,7 +233,8 @@ abstract class ElectrumWalletBase ), ); - if (inputsCount != null ? i + 1 == inputsCount : !sendAll && leftAmount <= 0) { + bool amountIsAcquired = !sendAll && leftAmount <= 0; + if ((inputsCount == null && amountIsAcquired) || inputsCount == i + 1) { break; } } From 1434e5afbf009cf8eed552ca490aaad63e4bb7db Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 15 Feb 2024 16:16:12 -0300 Subject: [PATCH 56/59] fix: infinite loop possible --- cw_bitcoin/lib/electrum_wallet.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 6b4da9c03..9cd534b65 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -639,13 +639,16 @@ abstract class ElectrumWalletBase } Future fetchTransactionInfo( - {required String hash, required int height, required Set myAddresses}) async { + {required String hash, + required int height, + required Set myAddresses, + bool? retryOnFailure}) async { try { return ElectrumTransactionInfo.fromElectrumBundle( await getTransactionExpanded(hash: hash, height: height), walletInfo.type, network, addresses: myAddresses, height: height); } catch (e) { - if (e is FormatException) { + if (e is FormatException && retryOnFailure == true) { await Future.delayed(const Duration(seconds: 2)); return fetchTransactionInfo(hash: hash, height: height, myAddresses: myAddresses); } @@ -722,8 +725,8 @@ abstract class ElectrumWalletBase historiesWithDetails[txid] = storedTx; } else { - final tx = - await fetchTransactionInfo(hash: txid, height: height, myAddresses: addressesSet); + final tx = await fetchTransactionInfo( + hash: txid, height: height, myAddresses: addressesSet, retryOnFailure: true); if (tx != null) { historiesWithDetails[txid] = tx; From 8cd1693b6b18318ef8adb4c374c733a49f13e422 Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Thu, 15 Feb 2024 22:54:48 +0200 Subject: [PATCH 57/59] Revert removing isTestnet from other wallets [skip ci] --- cw_bitcoin/lib/litecoin_wallet_service.dart | 35 ++++++------ .../lib/src/bitcoin_cash_wallet_service.dart | 18 +++---- cw_core/lib/wallet_service.dart | 6 +-- cw_ethereum/lib/ethereum_wallet_service.dart | 9 ++-- cw_evm/lib/evm_chain_wallet_service.dart | 6 +-- cw_haven/lib/haven_wallet_service.dart | 53 ++++++++++++------- cw_monero/lib/monero_wallet_service.dart | 8 +-- cw_nano/lib/nano_wallet_service.dart | 6 +-- cw_polygon/lib/polygon_wallet_service.dart | 9 ++-- lib/bitcoin/cw_bitcoin.dart | 20 ------- lib/core/wallet_creation_service.dart | 22 ++------ tool/configure.dart | 5 -- 12 files changed, 84 insertions(+), 113 deletions(-) diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 248804ca1..3d7462fa1 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -12,8 +12,10 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:collection/collection.dart'; -class LitecoinWalletService extends WalletService { +class LitecoinWalletService extends WalletService< + BitcoinNewWalletCredentials, + BitcoinRestoreWalletFromSeedCredentials, + BitcoinRestoreWalletFromWIFCredentials> { LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -23,7 +25,7 @@ class LitecoinWalletService extends WalletService 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!, @@ -41,14 +43,12 @@ class LitecoinWalletService extends WalletService 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()))!; try { final wallet = await LitecoinWalletBase.open( - password: password, - name: name, - walletInfo: walletInfo, + password: password, name: name, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); saveBackup(name); @@ -56,9 +56,7 @@ class LitecoinWalletService extends WalletService 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 LitecoinWalletBase.open( password: password, name: currentName, @@ -95,12 +94,12 @@ class LitecoinWalletService extends WalletService restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async => throw UnimplementedError(); @override Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } 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 1b442dfc4..df8e841f8 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -2,10 +2,7 @@ import 'dart:io'; import 'package:bip39/bip39.dart'; import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; -import 'package:cw_core/balance.dart'; import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; @@ -29,12 +26,9 @@ class BitcoinCashWalletService extends WalletService create(credentials) async { - final strength = (credentials.seedPhraseLength == 12) - ? 128 - : (credentials.seedPhraseLength == 24) - ? 256 - : 128; + Future create(credentials, {bool? isTestnet}) async { + final strength = credentials.seedPhraseLength == 24 ? 256 : 128; + final wallet = await BitcoinCashWalletBase.create( mnemonic: await Mnemonic.generate(strength: strength), password: credentials.password!, @@ -100,14 +94,14 @@ class BitcoinCashWalletService extends WalletService restoreFromKeys(credentials) { + Future restoreFromKeys(credentials, {bool? isTestnet}) { // TODO: implement restoreFromKeys throw UnimplementedError('restoreFromKeys() is not implemented'); } @override - Future restoreFromSeed( - BitcoinCashRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinCashRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinCashMnemonicIsIncorrectException(); } diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index 3b4908386..22981b9db 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -9,11 +9,11 @@ abstract class WalletService { WalletType getType(); - Future create(N credentials); + Future create(N credentials, {bool? isTestnet}); - Future restoreFromSeed(RFS credentials); + Future restoreFromSeed(RFS credentials, {bool? isTestnet}); - Future restoreFromKeys(RFK credentials); + Future restoreFromKeys(RFK credentials, {bool? isTestnet}); Future openWallet(String name, String password); diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 3b8f9b34f..53c8bfea9 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -16,7 +16,7 @@ class EthereumWalletService extends EVMChainWalletService { WalletType getType() => WalletType.ethereum; @override - Future create(EVMChainNewWalletCredentials credentials) async { + Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -83,7 +83,8 @@ class EthereumWalletService extends EVMChainWalletService { } @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials) async { + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, + {bool? isTestnet}) async { final wallet = EthereumWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -99,8 +100,8 @@ class EthereumWalletService extends EVMChainWalletService { } @override - Future restoreFromSeed( - EVMChainRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw EthereumMnemonicIsIncorrectException(); } diff --git a/cw_evm/lib/evm_chain_wallet_service.dart b/cw_evm/lib/evm_chain_wallet_service.dart index 988a38684..d77a3a81a 100644 --- a/cw_evm/lib/evm_chain_wallet_service.dart +++ b/cw_evm/lib/evm_chain_wallet_service.dart @@ -22,7 +22,7 @@ abstract class EVMChainWalletService extends WalletSer WalletType getType(); @override - Future create(EVMChainNewWalletCredentials credentials); + Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}); @override Future openWallet(String name, String password); @@ -31,10 +31,10 @@ abstract class EVMChainWalletService extends WalletSer Future rename(String currentName, String password, String newName); @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials); + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, {bool? isTestnet}); @override - Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials); + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}); @override Future isWalletExit(String name) async => diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index 110d01fea..d4808c2d6 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -22,7 +22,10 @@ class HavenNewWalletCredentials extends WalletCredentials { class HavenRestoreWalletFromSeedCredentials extends WalletCredentials { HavenRestoreWalletFromSeedCredentials( - {required String name, required String password, required int height, required this.mnemonic}) + {required String name, + required String password, + required int height, + required this.mnemonic}) : super(name: name, password: password, height: height); final String mnemonic; @@ -50,12 +53,14 @@ class HavenRestoreWalletFromKeysCredentials extends WalletCredentials { final String spendKey; } -class HavenWalletService extends WalletService { +class HavenWalletService extends WalletService< + HavenNewWalletCredentials, + HavenRestoreWalletFromSeedCredentials, + HavenRestoreWalletFromKeysCredentials> { HavenWalletService(this.walletInfoSource); final Box walletInfoSource; - + static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync(); @@ -63,11 +68,13 @@ class HavenWalletService extends WalletService 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( - path: path, password: credentials.password!, language: credentials.language); + path: path, + password: credentials.password!, + language: credentials.language); final wallet = HavenWallet(walletInfo: credentials.walletInfo!); await wallet.init(); return wallet; @@ -99,9 +106,10 @@ class HavenWalletService extends WalletService info.id == WalletBase.idFor(name, getType()))!; + await haven_wallet_manager + .openWalletAsync({'path': path, 'password': password}); + final walletInfo = walletInfoSource.values.firstWhereOrNull( + (info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = HavenWallet(walletInfo: walletInfo); final isValid = wallet.walletAddresses.validate(); @@ -118,10 +126,12 @@ class HavenWalletService extends WalletService rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values - .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); + Future rename( + String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values.firstWhere( + (info) => info.id == WalletBase.idFor(currentName, getType())); final currentWallet = HavenWallet(walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); @@ -162,7 +173,8 @@ class HavenWalletService extends WalletService restoreFromKeys(HavenRestoreWalletFromKeysCredentials credentials) async { + Future restoreFromKeys( + HavenRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.restoreFromKeys( @@ -185,7 +197,8 @@ class HavenWalletService extends WalletService restoreFromSeed(HavenRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed( + HavenRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.restoreFromSeed( @@ -210,14 +223,16 @@ class HavenWalletService extends WalletService 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()); @@ -203,7 +203,8 @@ class MoneroWalletService extends WalletService restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials) async { + Future restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials, + {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.restoreFromKeys( @@ -227,7 +228,8 @@ class MoneroWalletService extends WalletService restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { // Restore from Polyseed if (Polyseed.isValidSeed(credentials.mnemonic)) { return restoreFromPolyseed(credentials); diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index a76f0393d..7ab502d49 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -26,7 +26,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(); @@ -79,7 +79,7 @@ class NanoWalletService extends WalletService restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials) async { + Future restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { if (credentials.seedKey.contains(' ')) { throw Exception("Invalid key!"); } else { @@ -113,7 +113,7 @@ class NanoWalletService extends WalletService restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (credentials.mnemonic.contains(' ')) { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw nm.NanoMnemonicIsIncorrectException(); diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 32688e7e3..59e14abbf 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -19,7 +19,7 @@ class PolygonWalletService extends EVMChainWalletService { WalletType getType() => WalletType.polygon; @override - Future create(EVMChainNewWalletCredentials credentials) async { + Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -70,7 +70,8 @@ class PolygonWalletService extends EVMChainWalletService { } @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials) async { + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, + {bool? isTestnet}) async { final wallet = PolygonWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -86,8 +87,8 @@ class PolygonWalletService extends EVMChainWalletService { } @override - Future restoreFromSeed( - EVMChainRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw PolygonMnemonicIsIncorrectException(); } diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index cbc965a27..2effb2176 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -188,24 +188,4 @@ class CWBitcoin extends Bitcoin { @override List getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all; - - @override - Future create(WalletService service, WalletCredentials credentials, - {bool? isTestnet}) => - (service as BitcoinWalletService) - .create(credentials as BitcoinNewWalletCredentials, isTestnet: isTestnet); - - @override - Future restoreFromKeys(WalletService service, WalletCredentials credentials, - {bool? isTestnet}) => - (service as BitcoinWalletService).restoreFromKeys( - credentials as BitcoinRestoreWalletFromWIFCredentials, - isTestnet: isTestnet); - - @override - Future restoreFromSeed(WalletService service, WalletCredentials credentials, - {bool? isTestnet}) => - (service as BitcoinWalletService).restoreFromSeed( - credentials as BitcoinRestoreWalletFromSeedCredentials, - isTestnet: isTestnet); } diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index addbef5b3..31a893ad6 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_info.dart'; @@ -63,12 +62,7 @@ class WalletCreationService { credentials.seedPhraseLength = settingsStore.seedPhraseLength.value; } await keyService.saveWalletPassword(password: password, walletName: credentials.name); - WalletBase? wallet; - if (type == WalletType.bitcoin) { - wallet = await bitcoin!.create(_service!, credentials, isTestnet: isTestnet); - } else { - wallet = await _service!.create(credentials); - } + final wallet = await _service!.create(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( @@ -83,12 +77,7 @@ class WalletCreationService { final password = generateWalletPassword(); credentials.password = password; await keyService.saveWalletPassword(password: password, walletName: credentials.name); - WalletBase? wallet; - if (type == WalletType.bitcoin) { - wallet = await bitcoin!.restoreFromKeys(_service!, credentials, isTestnet: isTestnet); - } else { - wallet = await _service!.restoreFromKeys(credentials); - } + final wallet = await _service!.restoreFromKeys(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( @@ -103,12 +92,7 @@ class WalletCreationService { final password = generateWalletPassword(); credentials.password = password; await keyService.saveWalletPassword(password: password, walletName: credentials.name); - WalletBase? wallet; - if (type == WalletType.bitcoin) { - wallet = await bitcoin!.restoreFromSeed(_service!, credentials, isTestnet: isTestnet); - } else { - wallet = await _service!.restoreFromSeed(credentials); - } + final wallet = await _service!.restoreFromSeed(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( diff --git a/tool/configure.dart b/tool/configure.dart index e296f847d..aaacc4c36 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -72,14 +72,12 @@ import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; -import 'package:cw_bitcoin/bitcoin_wallet.dart'; import 'package:cw_bitcoin/bitcoin_wallet_service.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; -import 'package:cw_core/wallet_base.dart'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:mobx/mobx.dart'; """; @@ -142,9 +140,6 @@ abstract class Bitcoin { Future setAddressType(Object wallet, dynamic option); BitcoinReceivePageOption getSelectedAddressType(Object wallet); List getBitcoinReceivePageOptions(); - Future create(WalletService service, WalletCredentials credentials, {bool? isTestnet}); - Future restoreFromKeys(WalletService service, WalletCredentials credentials, {bool? isTestnet}); - Future restoreFromSeed(WalletService service, WalletCredentials credentials, {bool? isTestnet}); } """; From b3a6a7936375c88b190061e71bad7e733f234ecc Mon Sep 17 00:00:00 2001 From: Rafael Saes Date: Thu, 15 Feb 2024 18:29:03 -0300 Subject: [PATCH 58/59] refactor: rename addresses when matched by receive type --- cw_bitcoin/lib/electrum_wallet.dart | 5 +++-- cw_bitcoin/lib/electrum_wallet_addresses.dart | 17 +++++++++-------- .../lib/src/bitcoin_cash_wallet.dart | 2 +- lib/bitcoin/cw_bitcoin.dart | 4 ++-- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 9cd534b65..873fe2977 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -115,8 +115,9 @@ abstract class ElectrumWalletBase @observable SyncStatus syncStatus; - List get scriptHashes => - walletAddresses.addresses.map((addr) => scriptHash(addr.address, network: network)).toList(); + List get scriptHashes => walletAddresses.addressesByReceiveType + .map((addr) => scriptHash(addr.address, network: network)) + .toList(); List get publicScriptHashes => walletAddresses.allAddresses .where((addr) => !addr.isHidden) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 2e5c96102..5880f5a19 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -31,7 +31,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { Map? initialRegularAddressIndex, Map? initialChangeAddressIndex, }) : _addresses = ObservableList.of((initialAddresses ?? []).toSet()), - addresses = ObservableList.of(([]).toSet()), + addressesByReceiveType = + ObservableList.of(([]).toSet()), receiveAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed) .toSet()), @@ -57,7 +58,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final ObservableList _addresses; // Matched by addressPageType - late ObservableList addresses; + late ObservableList addressesByReceiveType; final ObservableList receiveAddresses; final ObservableList changeAddresses; final ElectrumClient electrumClient; @@ -89,7 +90,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { previousAddressRecord != null && previousAddressRecord!.type == addressPageType; if (previousAddressMatchesType && - typeMatchingReceiveAddresses.first.address != addresses.first.address) { + typeMatchingReceiveAddresses.first.address != addressesByReceiveType.first.address) { receiveAddress = previousAddressRecord!.address; } else { receiveAddress = typeMatchingReceiveAddresses.first.address; @@ -137,7 +138,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { BitcoinAddressRecord? previousAddressRecord; @computed - int get totalCountOfReceiveAddresses => addresses.fold(0, (acc, addressRecord) { + int get totalCountOfReceiveAddresses => addressesByReceiveType.fold(0, (acc, addressRecord) { if (!addressRecord.isHidden) { return acc + 1; } @@ -145,7 +146,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { }); @computed - int get totalCountOfChangeAddresses => addresses.fold(0, (acc, addressRecord) { + int get totalCountOfChangeAddresses => addressesByReceiveType.fold(0, (acc, addressRecord) { if (addressRecord.isHidden) { return acc + 1; } @@ -195,7 +196,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } BitcoinAddressRecord generateNewAddress({String label = ''}) { - final newAddressIndex = addresses.fold( + final newAddressIndex = addressesByReceiveType.fold( 0, (int acc, addressRecord) => addressRecord.isHidden == false ? acc + 1 : acc); final address = BitcoinAddressRecord( @@ -241,8 +242,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action void updateAddressesByMatch() { - addresses.clear(); - addresses.addAll(_addresses.where(_isAddressPageTypeMatch).toList()); + addressesByReceiveType.clear(); + addressesByReceiveType.addAll(_addresses.where(_isAddressPageTypeMatch).toList()); } @action diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 66cc5fd96..3c40cf9e9 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -328,7 +328,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { @override String signMessage(String message, {String? address = null}) { final index = address != null - ? walletAddresses.addresses + ? walletAddresses.allAddresses .firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address)) .index : null; diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 2effb2176..f9c20d45e 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -100,7 +100,7 @@ class CWBitcoin extends Bitcoin { @override List getAddresses(Object wallet) { final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.walletAddresses.addresses + return bitcoinWallet.walletAddresses.addressesByReceiveType .map((BitcoinAddressRecord addr) => addr.address) .toList(); } @@ -109,7 +109,7 @@ class CWBitcoin extends Bitcoin { @computed List getSubAddresses(Object wallet) { final electrumWallet = wallet as ElectrumWallet; - return electrumWallet.walletAddresses.addresses + return electrumWallet.walletAddresses.addressesByReceiveType .map((BitcoinAddressRecord addr) => ElectrumSubAddress( id: addr.index, name: addr.name, From 6fae0172e7f773d82fa7c5d89f8e38902b71bcad Mon Sep 17 00:00:00 2001 From: OmarHatem Date: Tue, 20 Feb 2024 19:23:00 +0200 Subject: [PATCH 59/59] Make the beta build [skip ci] Remove app_env.fish --- assets/text/Release_Notes.txt | 8 ++-- scripts/android/app_env.fish | 75 ----------------------------------- scripts/android/app_env.sh | 4 +- scripts/ios/app_env.sh | 4 +- 4 files changed, 7 insertions(+), 84 deletions(-) delete mode 100644 scripts/android/app_env.fish diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 2f5130bea..ac032e354 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,5 +1,3 @@ -Bitcoin transactions fixes and enhancements -EVM wallets enhancements (Ethereum and Polygon) -Improve wallet recovery and error tolerance -Enhance Background sync for Monero wallets -Bug fixes \ No newline at end of file +Support ALL Bitcoin address types (Legacy, Segwit (both variants), Taproot) +Enhance Sending/Receiving flow for Bitcoin +Improve fee calculations in Bitcoin \ No newline at end of file diff --git a/scripts/android/app_env.fish b/scripts/android/app_env.fish deleted file mode 100644 index be82ab9e6..000000000 --- a/scripts/android/app_env.fish +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env fish - -set APP_ANDROID_NAME "" -set APP_ANDROID_VERSION "" -set APP_ANDROID_BUILD_VERSION "" -set APP_ANDROID_ID "" -set APP_ANDROID_PACKAGE "" -set APP_ANDROID_SCHEME "" - -set MONERO_COM "monero.com" -set CAKEWALLET "cakewallet" -set HAVEN "haven" - -set -l TYPES $MONERO_COM $CAKEWALLET $HAVEN -set APP_ANDROID_TYPE $argv[1] - -set MONERO_COM_NAME "Monero.com" -set MONERO_COM_VERSION "1.10.0" -set MONERO_COM_BUILD_NUMBER 72 -set MONERO_COM_BUNDLE_ID "com.monero.app" -set MONERO_COM_PACKAGE "com.monero.app" -set MONERO_COM_SCHEME "monero.com" - -set CAKEWALLET_NAME "Cake Wallet" -set CAKEWALLET_VERSION "4.13.0" -set CAKEWALLET_BUILD_NUMBER 189 -set CAKEWALLET_BUNDLE_ID "com.cakewallet.cake_wallet" -set CAKEWALLET_PACKAGE "com.cakewallet.cake_wallet" -set CAKEWALLET_SCHEME "cakewallet" - -set HAVEN_NAME "Haven" -set HAVEN_VERSION "1.0.0" -set HAVEN_BUILD_NUMBER 1 -set HAVEN_BUNDLE_ID "com.cakewallet.haven" -set HAVEN_PACKAGE "com.cakewallet.haven" - -if not contains $APP_ANDROID_TYPE $TYPES - echo "Wrong app type." - return 1 - exit 1 -end - -switch $APP_ANDROID_TYPE - case $MONERO_COM - set APP_ANDROID_NAME $MONERO_COM_NAME - set APP_ANDROID_VERSION $MONERO_COM_VERSION - set APP_ANDROID_BUILD_NUMBER $MONERO_COM_BUILD_NUMBER - set APP_ANDROID_BUNDLE_ID $MONERO_COM_BUNDLE_ID - set APP_ANDROID_PACKAGE $MONERO_COM_PACKAGE - set APP_ANDROID_SCHEME $MONERO_COM_SCHEME - ;; - case $CAKEWALLET - set APP_ANDROID_NAME $CAKEWALLET_NAME - set APP_ANDROID_VERSION $CAKEWALLET_VERSION - set APP_ANDROID_BUILD_NUMBER $CAKEWALLET_BUILD_NUMBER - set APP_ANDROID_BUNDLE_ID $CAKEWALLET_BUNDLE_ID - set APP_ANDROID_PACKAGE $CAKEWALLET_PACKAGE - set APP_ANDROID_SCHEME $CAKEWALLET_SCHEME - ;; - case $HAVEN - set APP_ANDROID_NAME $HAVEN_NAME - set APP_ANDROID_VERSION $HAVEN_VERSION - set APP_ANDROID_BUILD_NUMBER $HAVEN_BUILD_NUMBER - set APP_ANDROID_BUNDLE_ID $HAVEN_BUNDLE_ID - set APP_ANDROID_PACKAGE $HAVEN_PACKAGE - ;; -end - -export APP_ANDROID_TYPE -export APP_ANDROID_NAME -export APP_ANDROID_VERSION -export APP_ANDROID_BUILD_NUMBER -export APP_ANDROID_BUNDLE_ID -export APP_ANDROID_PACKAGE -export APP_ANDROID_SCHEME diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index f659239e7..9251ec31a 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -22,8 +22,8 @@ MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.3" -CAKEWALLET_BUILD_NUMBER=192 +CAKEWALLET_VERSION="4.14.0" +CAKEWALLET_BUILD_NUMBER=193 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index bb4ca77f8..47d80013c 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=73 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.3" -CAKEWALLET_BUILD_NUMBER=212 +CAKEWALLET_VERSION="4.14.0" +CAKEWALLET_BUILD_NUMBER=213 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven"