Sp enhancements (#1672)
* fix: enhance regex, fix multiline * feat: improve scan msg, fix missing txs, use date api * feat: node fixes, enhance send modal, TX list tag & filter, refactors * fix: continuous scanning * fix: missing close * fix: resubscribe tweaks * feat: use mempool api setting toggle * handle any failure of height API and fallback to the old method [skip ci] --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
Rafael committed
Sep 20, 2024 at 14:24 UTC
3a391f10a37e4f8726fb6d374fe3aa217a78a1b7
61 files changed
+872
-531
cw_bitcoin/lib/address_to_output_script.dart
deleted
-14
@@ -1,14 +0,0 @@
1
-import 'dart:typed_data';
2
-import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin;
3
-
4
-List<int> addressToOutputScript(String address, bitcoin.BasedUtxoNetwork network) {
5
- try {
6
- if (network == bitcoin.BitcoinCashNetwork.mainnet) {
7
- return bitcoin.BitcoinCashAddress(address).baseAddress.toScriptPubKey().toBytes();
8
- }
9
- return bitcoin.addressToOutputScript(address: address, network: network);
10
- } catch (err) {
11
- print(err);
12
- return Uint8List(0);
13
- }
14
-}
cw_bitcoin/lib/bitcoin_address_record.dart
+3
-4
@@ -1,7 +1,6 @@
1
import 'dart:convert';
2
3
import 'package:bitcoin_base/bitcoin_base.dart';
4
-import 'package:cw_bitcoin/script_hash.dart' as sh;
4
5
abstract class BaseBitcoinAddressRecord {
6
BaseBitcoinAddressRecord(
@@ -65,8 +64,8 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
64
required super.type,
65
String? scriptHash,
66
required super.network,
68
- }) : scriptHash =
69
- scriptHash ?? (network != null ? sh.scriptHash(address, network: network) : null);
67
+ }) : scriptHash = scriptHash ??
68
+ (network != null ? BitcoinAddressUtils.scriptHash(address, network: network) : null);
69
70
factory BitcoinAddressRecord.fromJSON(String jsonSource, {BasedUtxoNetwork? network}) {
71
final decoded = json.decode(jsonSource) as Map;
@@ -92,7 +91,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
91
92
String getScriptHash(BasedUtxoNetwork network) {
93
if (scriptHash != null) return scriptHash!;
95
- scriptHash = sh.scriptHash(address, network: network);
94
+ scriptHash = BitcoinAddressUtils.scriptHash(address, network: network);
95
return scriptHash!;
96
}
97
cw_bitcoin/lib/electrum.dart
+24
-34
@@ -4,7 +4,6 @@ import 'dart:io';
4
import 'dart:typed_data';
5
import 'package:bitcoin_base/bitcoin_base.dart';
6
import 'package:cw_bitcoin/bitcoin_amount_format.dart';
7
-import 'package:cw_bitcoin/script_hash.dart';
7
import 'package:flutter/foundation.dart';
8
import 'package:rxdart/rxdart.dart';
9
@@ -48,6 +47,7 @@ class ElectrumClient {
47
final Map<String, SocketTask> _tasks;
48
Map<String, SocketTask> get tasks => _tasks;
49
final Map<String, String> _errors;
50
+ ConnectionStatus _connectionStatus = ConnectionStatus.disconnected;
51
bool _isConnected;
52
Timer? _aliveTimer;
53
String unterminatedString;
@@ -57,11 +57,13 @@ class ElectrumClient {
57
58
Future<void> connectToUri(Uri uri, {bool? useSSL}) async {
59
this.uri = uri;
60
- this.useSSL = useSSL;
61
- await connect(host: uri.host, port: uri.port, useSSL: useSSL);
60
+ if (useSSL != null) {
61
+ this.useSSL = useSSL;
62
+ }
63
+ await connect(host: uri.host, port: uri.port);
64
}
65
64
- Future<void> connect({required String host, required int port, bool? useSSL}) async {
66
+ Future<void> connect({required String host, required int port}) async {
67
_setConnectionStatus(ConnectionStatus.connecting);
68
69
try {
@@ -80,15 +82,26 @@ class ElectrumClient {
82
onBadCertificate: (_) => true,
83
);
84
}
83
- } catch (_) {
84
- _setConnectionStatus(ConnectionStatus.failed);
85
+ } catch (e) {
86
+ if (e is HandshakeException) {
87
+ useSSL = !(useSSL ?? false);
88
+ }
89
+
90
+ if (_connectionStatus != ConnectionStatus.connecting) {
91
+ _setConnectionStatus(ConnectionStatus.failed);
92
+ }
93
+
94
return;
95
}
96
97
if (socket == null) {
89
- _setConnectionStatus(ConnectionStatus.failed);
98
+ if (_connectionStatus != ConnectionStatus.connecting) {
99
+ _setConnectionStatus(ConnectionStatus.failed);
100
+ }
101
+
102
return;
103
}
104
+
105
_setConnectionStatus(ConnectionStatus.connected);
106
107
socket!.listen(
@@ -118,7 +131,7 @@ class ElectrumClient {
131
socket?.destroy();
132
_setConnectionStatus(ConnectionStatus.disconnected);
133
}
121
- } catch(e) {
134
+ } catch (e) {
135
print(e.toString());
136
}
137
},
@@ -217,25 +230,6 @@ class ElectrumClient {
230
return [];
231
});
232
220
- Future<List<Map<String, dynamic>>> getListUnspentWithAddress(
221
- String address, BasedUtxoNetwork network) =>
222
- call(
223
- method: 'blockchain.scripthash.listunspent',
224
- params: [scriptHash(address, network: network)]).then((dynamic result) {
225
- if (result is List) {
226
- return result.map((dynamic val) {
227
- if (val is Map<String, dynamic>) {
228
- val['address'] = address;
229
- return val;
230
- }
231
-
232
- return <String, dynamic>{};
233
- }).toList();
234
- }
235
-
236
- return [];
237
- });
238
-
233
Future<List<Map<String, dynamic>>> getListUnspent(String scriptHash) =>
234
call(method: 'blockchain.scripthash.listunspent', params: [scriptHash])
235
.then((dynamic result) {
@@ -272,16 +266,12 @@ class ElectrumClient {
266
try {
267
final result = await callWithTimeout(
268
method: 'blockchain.transaction.get', params: [hash, verbose], timeout: 10000);
275
- if (result is Map<String, dynamic>) {
276
- return result;
277
- }
269
+ return result;
270
} on RequestFailedTimeoutException catch (_) {
271
return <String, dynamic>{};
272
} catch (e) {
281
- print("getTransaction: ${e.toString()}");
273
return <String, dynamic>{};
274
}
284
- return <String, dynamic>{};
275
}
276
277
Future<Map<String, dynamic>> getTransactionVerbose({required String hash}) =>
@@ -326,9 +316,8 @@ class ElectrumClient {
316
await call(method: 'blockchain.block.get_header', params: [height]) as Map<String, dynamic>;
317
318
BehaviorSubject<Object>? tweaksSubscribe({required int height, required int count}) {
329
- _id += 1;
319
return subscribe<Object>(
331
- id: 'blockchain.tweaks.subscribe:${height + count}',
320
+ id: 'blockchain.tweaks.subscribe',
321
method: 'blockchain.tweaks.subscribe',
322
params: [height, count, false],
323
);
@@ -539,6 +528,7 @@ class ElectrumClient {
528
529
void _setConnectionStatus(ConnectionStatus status) {
530
onConnectionStatusChange?.call(status);
531
+ _connectionStatus = status;
532
_isConnected = status == ConnectionStatus.connected;
533
}
534
cw_bitcoin/lib/electrum_transaction_info.dart
+20
-14
@@ -23,20 +23,24 @@ class ElectrumTransactionBundle {
23
24
class ElectrumTransactionInfo extends TransactionInfo {
25
List<BitcoinSilentPaymentsUnspent>? unspents;
26
-
27
- ElectrumTransactionInfo(this.type,
28
- {required String id,
29
- int? height,
30
- required int amount,
31
- int? fee,
32
- List<String>? inputAddresses,
33
- List<String>? outputAddresses,
34
- required TransactionDirection direction,
35
- required bool isPending,
36
- required DateTime date,
37
- required int confirmations,
38
- String? to,
39
- this.unspents}) {
26
+ bool isReceivedSilentPayment;
27
+
28
+ ElectrumTransactionInfo(
29
+ this.type, {
30
+ required String id,
31
+ int? height,
32
+ required int amount,
33
+ int? fee,
34
+ List<String>? inputAddresses,
35
+ List<String>? outputAddresses,
36
+ required TransactionDirection direction,
37
+ required bool isPending,
38
+ required DateTime date,
39
+ required int confirmations,
40
+ String? to,
41
+ this.unspents,
42
+ this.isReceivedSilentPayment = false,
43
+ }) {
44
this.id = id;
45
this.height = height;
46
this.amount = amount;
@@ -202,6 +206,7 @@ class ElectrumTransactionInfo extends TransactionInfo {
206
.map((unspent) =>
207
BitcoinSilentPaymentsUnspent.fromJSON(null, unspent as Map<String, dynamic>))
208
.toList(),
209
+ isReceivedSilentPayment: data['isReceivedSilentPayment'] as bool? ?? false,
210
);
211
}
212
@@ -252,6 +257,7 @@ class ElectrumTransactionInfo extends TransactionInfo {
257
m['unspents'] = unspents?.map((e) => e.toJson()).toList() ?? [];
258
m['inputAddresses'] = inputAddresses;
259
m['outputAddresses'] = outputAddresses;
260
+ m['isReceivedSilentPayment'] = isReceivedSilentPayment;
261
return m;
262
}
263
cw_bitcoin/lib/electrum_wallet.dart
+113
-86
@@ -24,7 +24,6 @@ import 'package:cw_bitcoin/electrum_transaction_info.dart';
24
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
25
import 'package:cw_bitcoin/exceptions.dart';
26
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
27
-import 'package:cw_bitcoin/script_hash.dart';
27
import 'package:cw_bitcoin/utils.dart';
28
import 'package:cw_core/crypto_currency.dart';
29
import 'package:cw_core/node.dart';
@@ -51,8 +50,6 @@ part 'electrum_wallet.g.dart';
50
51
class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet;
52
54
-const int TWEAKS_COUNT = 25;
55
-
53
abstract class ElectrumWalletBase
54
extends WalletBase<ElectrumBalance, ElectrumTransactionHistory, ElectrumTransactionInfo>
55
with Store, WalletKeysFile {
@@ -166,12 +163,12 @@ abstract class ElectrumWalletBase
163
Set<String> get addressesSet => walletAddresses.allAddresses.map((addr) => addr.address).toSet();
164
165
List<String> get scriptHashes => walletAddresses.addressesByReceiveType
169
- .map((addr) => scriptHash(addr.address, network: network))
166
+ .map((addr) => (addr as BitcoinAddressRecord).getScriptHash(network))
167
.toList();
168
169
List<String> get publicScriptHashes => walletAddresses.allAddresses
170
.where((addr) => !addr.isHidden)
174
- .map((addr) => scriptHash(addr.address, network: network))
171
+ .map((addr) => addr.getScriptHash(network))
172
.toList();
173
174
String get xpub => accountHD.publicKey.toExtended;
@@ -212,7 +209,7 @@ abstract class ElectrumWalletBase
209
silentPaymentsScanningActive = active;
210
211
if (active) {
215
- syncStatus = StartingScanSyncStatus();
212
+ syncStatus = AttemptingScanSyncStatus();
213
214
final tip = await getUpdatedChainTip();
215
@@ -290,12 +287,7 @@ abstract class ElectrumWalletBase
287
}
288
289
@action
293
- Future<void> _setListeners(
294
- int height, {
295
- int? chainTipParam,
296
- bool? doSingleScan,
297
- bool? usingSupportedNode,
298
- }) async {
290
+ Future<void> _setListeners(int height, {int? chainTipParam, bool? doSingleScan}) async {
291
final chainTip = chainTipParam ?? await getUpdatedChainTip();
292
293
if (chainTip == height) {
@@ -303,7 +295,7 @@ abstract class ElectrumWalletBase
295
return;
296
}
297
306
- syncStatus = StartingScanSyncStatus();
298
+ syncStatus = AttemptingScanSyncStatus();
299
300
if (_isolate != null) {
301
final runningIsolate = await _isolate!;
@@ -550,7 +542,8 @@ abstract class ElectrumWalletBase
542
electrumClient.onConnectionStatusChange = _onConnectionStatusChange;
543
544
await electrumClient.connectToUri(node.uri, useSSL: node.useSSL);
553
- } catch (e) {
545
+ } catch (e, stacktrace) {
546
+ print(stacktrace);
547
print(e.toString());
548
syncStatus = FailedSyncStatus();
549
}
@@ -592,7 +585,7 @@ abstract class ElectrumWalletBase
585
allInputsAmount += utx.value;
586
leftAmount = leftAmount - utx.value;
587
595
- final address = addressTypeFromStr(utx.address, network);
588
+ final address = RegexUtils.addressTypeFromStr(utx.address, network);
589
ECPrivate? privkey;
590
bool? isSilentPayment = false;
591
@@ -796,10 +789,11 @@ abstract class ElectrumWalletBase
789
}
790
791
final changeAddress = await walletAddresses.getChangeAddress();
799
- final address = addressTypeFromStr(changeAddress, network);
792
+ final address = RegexUtils.addressTypeFromStr(changeAddress, network);
793
outputs.add(BitcoinOutput(
794
address: address,
795
value: BigInt.from(amountLeftForChangeAndFee),
796
+ isChange: true,
797
));
798
799
int estimatedSize;
@@ -833,8 +827,12 @@ abstract class ElectrumWalletBase
827
828
if (!_isBelowDust(amountLeftForChange)) {
829
// Here, lastOutput already is change, return the amount left without the fee to the user's address.
836
- outputs[outputs.length - 1] =
837
- BitcoinOutput(address: lastOutput.address, value: BigInt.from(amountLeftForChange));
830
+ outputs[outputs.length - 1] = BitcoinOutput(
831
+ address: lastOutput.address,
832
+ value: BigInt.from(amountLeftForChange),
833
+ isSilentPayment: lastOutput.isSilentPayment,
834
+ isChange: true,
835
+ );
836
} else {
837
// If has change that is lower than dust, will end up with tx rejected by network rules, so estimate again without the added change
838
outputs.removeLast();
@@ -938,18 +936,27 @@ abstract class ElectrumWalletBase
936
937
credentialsAmount += outputAmount;
938
941
- final address =
942
- addressTypeFromStr(out.isParsedAddress ? out.extractedAddress! : out.address, network);
939
+ final address = RegexUtils.addressTypeFromStr(
940
+ out.isParsedAddress ? out.extractedAddress! : out.address, network);
941
+ final isSilentPayment = address is SilentPaymentAddress;
942
944
- if (address is SilentPaymentAddress) {
943
+ if (isSilentPayment) {
944
hasSilentPayment = true;
945
}
946
947
if (sendAll) {
948
// The value will be changed after estimating the Tx size and deducting the fee from the total to be sent
950
- outputs.add(BitcoinOutput(address: address, value: BigInt.from(0)));
949
+ outputs.add(BitcoinOutput(
950
+ address: address,
951
+ value: BigInt.from(0),
952
+ isSilentPayment: isSilentPayment,
953
+ ));
954
} else {
952
- outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount)));
955
+ outputs.add(BitcoinOutput(
956
+ address: address,
957
+ value: BigInt.from(outputAmount),
958
+ isSilentPayment: isSilentPayment,
959
+ ));
960
}
961
}
962
@@ -1089,7 +1096,8 @@ abstract class ElectrumWalletBase
1096
});
1097
}
1098
1092
- unspentCoins.removeWhere((utxo) => estimatedTx.utxos.any((e) => e.utxo.txHash == utxo.hash));
1099
+ unspentCoins
1100
+ .removeWhere((utxo) => estimatedTx.utxos.any((e) => e.utxo.txHash == utxo.hash));
1101
1102
await updateBalance();
1103
});
@@ -1237,12 +1245,7 @@ abstract class ElectrumWalletBase
1245
1246
@action
1247
@override
1240
- Future<void> rescan({
1241
- required int height,
1242
- int? chainTip,
1243
- ScanData? scanData,
1244
- bool? doSingleScan,
1245
- }) async {
1248
+ Future<void> rescan({required int height, bool? doSingleScan}) async {
1249
silentPaymentsScanningActive = true;
1250
_setListeners(height, doSingleScan: doSingleScan);
1251
}
@@ -1460,7 +1463,7 @@ abstract class ElectrumWalletBase
1463
final addressRecord =
1464
walletAddresses.allAddresses.firstWhere((element) => element.address == address);
1465
1463
- final btcAddress = addressTypeFromStr(addressRecord.address, network);
1466
+ final btcAddress = RegexUtils.addressTypeFromStr(addressRecord.address, network);
1467
final privkey = generateECPrivate(
1468
hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
1469
index: addressRecord.index,
@@ -1501,7 +1504,7 @@ abstract class ElectrumWalletBase
1504
}
1505
1506
final address = addressFromOutputScript(out.scriptPubKey, network);
1504
- final btcAddress = addressTypeFromStr(address, network);
1507
+ final btcAddress = RegexUtils.addressTypeFromStr(address, network);
1508
outputs.add(BitcoinOutput(address: btcAddress, value: BigInt.from(out.amount.toInt())));
1509
}
1510
@@ -1597,8 +1600,6 @@ abstract class ElectrumWalletBase
1600
Future<ElectrumTransactionBundle> getTransactionExpanded(
1601
{required String hash, int? height}) async {
1602
String transactionHex;
1600
- // TODO: time is not always available, and calculating it from height is not always accurate.
1601
- // Add settings to choose API provider and use and http server instead of electrum for this.
1603
int? time;
1604
int? confirmations;
1605
@@ -1606,6 +1607,29 @@ abstract class ElectrumWalletBase
1607
1608
if (verboseTransaction.isEmpty) {
1609
transactionHex = await electrumClient.getTransactionHex(hash: hash);
1610
+
1611
+ if (height != null && await checkIfMempoolAPIIsEnabled()) {
1612
+ final blockHash = await http.get(
1613
+ Uri.parse(
1614
+ "http://mempool.cakewallet.com:8999/api/v1/block-height/$height",
1615
+ ),
1616
+ );
1617
+
1618
+ if (blockHash.statusCode == 200 &&
1619
+ blockHash.body.isNotEmpty &&
1620
+ jsonDecode(blockHash.body) != null) {
1621
+ final blockResponse = await http.get(
1622
+ Uri.parse(
1623
+ "http://mempool.cakewallet.com:8999/api/v1/block/${blockHash.body}",
1624
+ ),
1625
+ );
1626
+ if (blockResponse.statusCode == 200 &&
1627
+ blockResponse.body.isNotEmpty &&
1628
+ jsonDecode(blockResponse.body)['timestamp'] != null) {
1629
+ time = int.parse(jsonDecode(blockResponse.body)['timestamp'].toString());
1630
+ }
1631
+ }
1632
+ }
1633
} else {
1634
transactionHex = verboseTransaction['hex'] as String;
1635
time = verboseTransaction['time'] as int?;
@@ -1860,7 +1884,7 @@ abstract class ElectrumWalletBase
1884
final balanceFutures = <Future<Map<String, dynamic>>>[];
1885
for (var i = 0; i < addresses.length; i++) {
1886
final addressRecord = addresses[i];
1863
- final sh = scriptHash(addressRecord.address, network: network);
1887
+ final sh = addressRecord.getScriptHash(network);
1888
final balanceFuture = electrumClient.getBalance(sh);
1889
balanceFutures.add(balanceFuture);
1890
}
@@ -1900,7 +1924,10 @@ abstract class ElectrumWalletBase
1924
}
1925
1926
return ElectrumBalance(
1903
- confirmed: totalConfirmed, unconfirmed: totalUnconfirmed, frozen: totalFrozen);
1927
+ confirmed: totalConfirmed,
1928
+ unconfirmed: totalUnconfirmed,
1929
+ frozen: totalFrozen,
1930
+ );
1931
}
1932
1933
Future<void> updateBalance() async {
@@ -1968,7 +1995,7 @@ abstract class ElectrumWalletBase
1995
1996
List<int> possibleRecoverIds = [0, 1];
1997
1971
- final baseAddress = addressTypeFromStr(address, network);
1998
+ final baseAddress = RegexUtils.addressTypeFromStr(address, network);
1999
2000
for (int recoveryId in possibleRecoverIds) {
2001
final pubKey = sig.recoverPublicKey(messageHash, Curves.generatorSecp256k1, recoveryId);
@@ -2061,7 +2088,8 @@ abstract class ElectrumWalletBase
2088
_isTryingToConnect = true;
2089
2090
Timer(Duration(seconds: 5), () {
2064
- if (this.syncStatus is NotConnectedSyncStatus || this.syncStatus is LostConnectionSyncStatus) {
2091
+ if (this.syncStatus is NotConnectedSyncStatus ||
2092
+ this.syncStatus is LostConnectionSyncStatus) {
2093
this.electrumClient.connectToUri(
2094
node!.uri,
2095
useSSL: node!.useSSL ?? false,
@@ -2192,21 +2220,22 @@ Future<void> startRefresh(ScanData scanData) async {
2220
2221
BehaviorSubject<Object>? tweaksSubscription = null;
2222
2195
- final syncingStatus = scanData.isSingleScan
2196
- ? SyncingSyncStatus(1, 0)
2197
- : SyncingSyncStatus.fromHeightValues(scanData.chainTip, initialSyncHeight, syncHeight);
2198
-
2199
- // Initial status UI update, send how many blocks left to scan
2200
- scanData.sendPort.send(SyncResponse(syncHeight, syncingStatus));
2201
-
2223
final electrumClient = scanData.electrumClient;
2224
await electrumClient.connectToUri(
2225
scanData.node?.uri ?? Uri.parse("tcp://electrs.cakewallet.com:50001"),
2226
useSSL: scanData.node?.useSSL ?? false,
2227
);
2228
2229
+ int getCountPerRequest(int syncHeight) {
2230
+ if (scanData.isSingleScan) {
2231
+ return 1;
2232
+ }
2233
+
2234
+ final amountLeft = scanData.chainTip - syncHeight + 1;
2235
+ return amountLeft;
2236
+ }
2237
+
2238
if (tweaksSubscription == null) {
2209
- final count = scanData.isSingleScan ? 1 : TWEAKS_COUNT;
2239
final receiver = Receiver(
2240
scanData.silentAddress.b_scan.toHex(),
2241
scanData.silentAddress.B_spend.toHex(),
@@ -2215,16 +2244,45 @@ Future<void> startRefresh(ScanData scanData) async {
2244
scanData.labelIndexes.length,
2245
);
2246
2218
- tweaksSubscription = await electrumClient.tweaksSubscribe(height: syncHeight, count: count);
2219
- tweaksSubscription?.listen((t) async {
2247
+ // Initial status UI update, send how many blocks in total to scan
2248
+ final initialCount = getCountPerRequest(syncHeight);
2249
+ scanData.sendPort.send(SyncResponse(syncHeight, StartingScanSyncStatus(syncHeight)));
2250
+
2251
+ tweaksSubscription = await electrumClient.tweaksSubscribe(
2252
+ height: syncHeight,
2253
+ count: initialCount,
2254
+ );
2255
+
2256
+ Future<void> listenFn(t) async {
2257
final tweaks = t as Map<String, dynamic>;
2258
+ final msg = tweaks["message"];
2259
+ // success or error msg
2260
+ final noData = msg != null;
2261
2222
- if (tweaks["message"] != null) {
2262
+ if (noData) {
2263
// re-subscribe to continue receiving messages, starting from the next unscanned height
2224
- electrumClient.tweaksSubscribe(height: syncHeight + 1, count: count);
2264
+ final nextHeight = syncHeight + 1;
2265
+ final nextCount = getCountPerRequest(nextHeight);
2266
+
2267
+ if (nextCount > 0) {
2268
+ tweaksSubscription?.close();
2269
+
2270
+ final nextTweaksSubscription = electrumClient.tweaksSubscribe(
2271
+ height: nextHeight,
2272
+ count: nextCount,
2273
+ );
2274
+ nextTweaksSubscription?.listen(listenFn);
2275
+ }
2276
+
2277
return;
2278
}
2279
2280
+ // Continuous status UI update, send how many blocks left to scan
2281
+ final syncingStatus = scanData.isSingleScan
2282
+ ? SyncingSyncStatus(1, 0)
2283
+ : SyncingSyncStatus.fromHeightValues(scanData.chainTip, initialSyncHeight, syncHeight);
2284
+ scanData.sendPort.send(SyncResponse(syncHeight, syncingStatus));
2285
+
2286
final blockHeight = tweaks.keys.first;
2287
final tweakHeight = int.parse(blockHeight);
2288
@@ -2264,6 +2322,7 @@ Future<void> startRefresh(ScanData scanData) async {
2322
: DateTime.now(),
2323
confirmations: scanData.chainTip - tweakHeight + 1,
2324
unspents: [],
2325
+ isReceivedSilentPayment: true,
2326
);
2327
2328
addToWallet.forEach((label, value) {
@@ -2318,16 +2377,6 @@ Future<void> startRefresh(ScanData scanData) async {
2377
} catch (_) {}
2378
2379
syncHeight = tweakHeight;
2321
- scanData.sendPort.send(
2322
- SyncResponse(
2323
- syncHeight,
2324
- SyncingSyncStatus.fromHeightValues(
2325
- scanData.chainTip,
2326
- initialSyncHeight,
2327
- syncHeight,
2328
- ),
2329
- ),
2330
- );
2380
2381
if (tweakHeight >= scanData.chainTip || scanData.isSingleScan) {
2382
if (tweakHeight >= scanData.chainTip)
@@ -2343,7 +2392,9 @@ Future<void> startRefresh(ScanData scanData) async {
2392
await tweaksSubscription!.close();
2393
await electrumClient.close();
2394
}
2346
- });
2395
+ }
2396
+
2397
+ tweaksSubscription?.listen(listenFn);
2398
}
2399
2400
if (tweaksSubscription == null) {
@@ -2373,6 +2424,7 @@ class EstimatedTxResult {
2424
final int fee;
2425
final int amount;
2426
final bool spendsSilentPayment;
2427
+ // final bool sendsToSilentPayment;
2428
final bool hasChange;
2429
final bool isSendAll;
2430
final String? memo;
@@ -2386,31 +2438,6 @@ class PublicKeyWithDerivationPath {
2438
final String publicKey;
2439
}
2440
2389
-BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) {
2390
- if (network is BitcoinCashNetwork) {
2391
- if (!address.startsWith("bitcoincash:") &&
2392
- (address.startsWith("q") || address.startsWith("p"))) {
2393
- address = "bitcoincash:$address";
2394
- }
2395
-
2396
- return BitcoinCashAddress(address).baseAddress;
2397
- }
2398
-
2399
- if (P2pkhAddress.regex.hasMatch(address)) {
2400
- return P2pkhAddress.fromAddress(address: address, network: network);
2401
- } else if (P2shAddress.regex.hasMatch(address)) {
2402
- return P2shAddress.fromAddress(address: address, network: network);
2403
- } else if (P2wshAddress.regex.hasMatch(address)) {
2404
- return P2wshAddress.fromAddress(address: address, network: network);
2405
- } else if (P2trAddress.regex.hasMatch(address)) {
2406
- return P2trAddress.fromAddress(address: address, network: network);
2407
- } else if (SilentPaymentAddress.regex.hasMatch(address)) {
2408
- return SilentPaymentAddress.fromAddress(address);
2409
- } else {
2410
- return P2wpkhAddress.fromAddress(address: address, network: network);
2411
- }
2412
-}
2413
-
2441
BitcoinAddressType _getScriptType(BitcoinBaseAddress type) {
2442
if (type is P2pkhAddress) {
2443
return P2pkhAddressType.p2pkh;
cw_bitcoin/lib/litecoin_wallet.dart
+1
-1
@@ -301,7 +301,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
301
302
List<int> possibleRecoverIds = [0, 1];
303
304
- final baseAddress = addressTypeFromStr(address, network);
304
+ final baseAddress = RegexUtils.addressTypeFromStr(address, network);
305
306
for (int recoveryId in possibleRecoverIds) {
307
final pubKey = sig.recoverPublicKey(messageHash, Curves.generatorSecp256k1, recoveryId);
cw_bitcoin/lib/pending_bitcoin_transaction.dart
+13
@@ -47,6 +47,19 @@ class PendingBitcoinTransaction with PendingTransaction {
47
@override
48
int? get outputCount => _tx.outputs.length;
49
50
+ List<TxOutput> get outputs => _tx.outputs;
51
+
52
+ bool get hasSilentPayment => _tx.hasSilentPayment;
53
+
54
+ PendingChange? get change {
55
+ try {
56
+ final change = _tx.outputs.firstWhere((out) => out.isChange);
57
+ return PendingChange(change.scriptPubKey.toAddress(), BtcUtils.fromSatoshi(change.amount));
58
+ } catch (_) {
59
+ return null;
60
+ }
61
+ }
62
+
63
final List<void Function(ElectrumTransactionInfo transaction)> _listeners;
64
65
@override
cw_bitcoin/lib/script_hash.dart
deleted
-19
@@ -1,19 +0,0 @@
1
-import 'package:crypto/crypto.dart';
2
-import 'package:cw_bitcoin/address_to_output_script.dart';
3
-import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin;
4
-
5
-String scriptHash(String address, {required bitcoin.BasedUtxoNetwork network}) {
6
- final outputScript = addressToOutputScript(address, network);
7
- final parts = sha256.convert(outputScript).toString().split('');
8
- var res = '';
9
-
10
- for (var i = parts.length - 1; i >= 0; i--) {
11
- final char = parts[i];
12
- i--;
13
- final nextChar = parts[i];
14
- res += nextChar;
15
- res += char;
16
- }
17
-
18
- return res;
19
-}
cw_bitcoin/pubspec.lock
+2
-2
@@ -70,8 +70,8 @@ packages:
70
dependency: "direct overridden"
71
description:
72
path: "."
73
- ref: cake-update-v5
74
- resolved-ref: ff2b10eb27b0254ce4518d054332d97d77d9b380
73
+ ref: cake-update-v7
74
+ resolved-ref: bc49e3b1cba601828f8ddc3d016188d8c2499088
75
url: "https://github.com/cake-tech/bitcoin_base"
76
source: git
77
version: "4.7.0"
cw_bitcoin/pubspec.yaml
+1
-1
@@ -57,7 +57,7 @@ dependency_overrides:
57
bitcoin_base:
58
git:
59
url: https://github.com/cake-tech/bitcoin_base
60
- ref: cake-update-v5
60
+ ref: cake-update-v7
61
62
# For information on the generic Dart part of this file, see the
63
# following page: https://dart.dev/tools/pub/pubspec
cw_bitcoin_cash/pubspec.yaml
+1
-1
@@ -42,7 +42,7 @@ dependency_overrides:
42
bitcoin_base:
43
git:
44
url: https://github.com/cake-tech/bitcoin_base
45
- ref: cake-update-v5
45
+ ref: cake-update-v7
46
47
# For information on the generic Dart part of this file, see the
48
# following page: https://dart.dev/tools/pub/pubspec
cw_core/lib/get_height_by_date.dart
+10
-1
@@ -267,6 +267,16 @@ const bitcoinDates = {
267
"2023-01": 769810,
268
};
269
270
+Future<int> getBitcoinHeightByDateAPI({required DateTime date}) async {
271
+ final response = await http.get(
272
+ Uri.parse(
273
+ "http://mempool.cakewallet.com:8999/api/v1/mining/blocks/timestamp/${(date.millisecondsSinceEpoch / 1000).round()}",
274
+ ),
275
+ );
276
+
277
+ return jsonDecode(response.body)['height'] as int;
278
+}
279
+
280
int getBitcoinHeightByDate({required DateTime date}) {
281
String dateKey = '${date.year}-${date.month.toString().padLeft(2, '0')}';
282
final closestKey = bitcoinDates.keys
@@ -377,4 +387,3 @@ int getWowneroHeightByDate({required DateTime date}) {
387
388
return wowDates[closestKey] ?? 0;
389
}
380
-
cw_core/lib/pending_transaction.dart
+8
@@ -1,3 +1,10 @@
1
+class PendingChange {
2
+ final String address;
3
+ final String amount;
4
+
5
+ PendingChange(this.address, this.amount);
6
+}
7
+
8
mixin PendingTransaction {
9
String get id;
10
String get amountFormatted;
@@ -5,6 +12,7 @@ mixin PendingTransaction {
12
String? feeRate;
13
String get hex;
14
int? get outputCount => null;
15
+ PendingChange? change;
16
17
Future<void> commit();
18
}
cw_core/lib/sync_status.dart
+8
@@ -4,6 +4,9 @@ abstract class SyncStatus {
4
}
5
6
class StartingScanSyncStatus extends SyncStatus {
7
+ StartingScanSyncStatus(this.beginHeight);
8
+
9
+ final int beginHeight;
10
@override
11
double progress() => 0.0;
12
}
@@ -59,6 +62,11 @@ class AttemptingSyncStatus extends SyncStatus {
62
double progress() => 0.0;
63
}
64
65
+class AttemptingScanSyncStatus extends SyncStatus {
66
+ @override
67
+ double progress() => 0.0;
68
+}
69
+
70
class FailedSyncStatus extends NotConnectedSyncStatus {}
71
72
class ConnectingSyncStatus extends SyncStatus {
cw_nano/pubspec.lock
+2
-2
@@ -117,10 +117,10 @@ packages:
117
dependency: "direct overridden"
118
description:
119
name: build_runner_core
120
- sha256: "0671ad4162ed510b70d0eb4ad6354c249f8429cab4ae7a4cec86bbc2886eb76e"
120
+ sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292"
121
url: "https://pub.dev"
122
source: hosted
123
- version: "7.2.7+1"
123
+ version: "7.2.7"
124
built_collection:
125
dependency: transitive
126
description:
lib/bitcoin/cw_bitcoin.dart
+46
-2
@@ -361,7 +361,7 @@ class CWBitcoin extends Bitcoin {
361
continue;
362
}
363
364
- final sh = scriptHash(address, network: network);
364
+ final sh = BitcoinAddressUtils.scriptHash(address, network: network);
365
final history = await electrumClient.getHistory(sh);
366
367
final balance = await electrumClient.getBalance(sh);
@@ -522,7 +522,20 @@ class CWBitcoin extends Bitcoin {
522
}
523
524
@override
525
- int getHeightByDate({required DateTime date}) => getBitcoinHeightByDate(date: date);
525
+ Future<bool> checkIfMempoolAPIIsEnabled(Object wallet) async {
526
+ final bitcoinWallet = wallet as ElectrumWallet;
527
+ return await bitcoinWallet.checkIfMempoolAPIIsEnabled();
528
+ }
529
+
530
+ @override
531
+ Future<int> getHeightByDate({required DateTime date, bool? bitcoinMempoolAPIEnabled}) async {
532
+ if (bitcoinMempoolAPIEnabled ?? false) {
533
+ try {
534
+ return await getBitcoinHeightByDateAPI(date: date);
535
+ } catch (_) {}
536
+ }
537
+ return await getBitcoinHeightByDate(date: date);
538
+ }
539
540
@override
541
Future<void> rescan(Object wallet, {required int height, bool? doSingleScan}) async {
@@ -547,4 +560,35 @@ class CWBitcoin extends Bitcoin {
560
final bitcoinWallet = wallet as ElectrumWallet;
561
await bitcoinWallet.updateFeeRates();
562
}
563
+
564
+ @override
565
+ List<Output> updateOutputs(PendingTransaction pendingTransaction, List<Output> outputs) {
566
+ final pendingTx = pendingTransaction as PendingBitcoinTransaction;
567
+
568
+ if (!pendingTx.hasSilentPayment) {
569
+ return outputs;
570
+ }
571
+
572
+ final updatedOutputs = outputs.map((output) {
573
+
574
+ try {
575
+ final pendingOut = pendingTx!.outputs[outputs.indexOf(output)];
576
+ final updatedOutput = output;
577
+
578
+ updatedOutput.stealthAddress = P2trAddress.fromScriptPubkey(script: pendingOut.scriptPubKey)
579
+ .toAddress(BitcoinNetwork.mainnet);
580
+ return updatedOutput;
581
+ } catch (_) {}
582
+
583
+ return output;
584
+ }).toList();
585
+
586
+ return updatedOutputs;
587
+ }
588
+
589
+ @override
590
+ bool txIsReceivedSilentPayment(TransactionInfo txInfo) {
591
+ final tx = txInfo as ElectrumTransactionInfo;
592
+ return tx.isReceivedSilentPayment;
593
+ }
594
}
lib/core/address_validator.dart
+65
-56
@@ -5,32 +5,40 @@ import 'package:cake_wallet/solana/solana.dart';
5
import 'package:cw_core/crypto_currency.dart';
6
import 'package:cw_core/erc20_token.dart';
7
8
+const BEFORE_REGEX = '(^|\s)';
9
+const AFTER_REGEX = '(\$|\s)';
10
+
11
class AddressValidator extends TextValidator {
12
AddressValidator({required CryptoCurrency type})
13
: super(
14
errorMessage: S.current.error_text_address,
15
useAdditionalValidation: type == CryptoCurrency.btc
13
- ? (String txt) => validateAddress(address: txt, network: BitcoinNetwork.mainnet)
16
+ ? (String txt) => BitcoinAddressUtils.validateAddress(
17
+ address: txt,
18
+ network: BitcoinNetwork.mainnet,
19
+ )
20
: null,
21
pattern: getPattern(type),
22
length: getLength(type));
23
24
static String getPattern(CryptoCurrency type) {
25
+ var pattern = "";
26
if (type is Erc20Token) {
20
- return '0x[0-9a-zA-Z]';
27
+ pattern = '0x[0-9a-zA-Z]';
28
}
29
switch (type) {
30
case CryptoCurrency.xmr:
24
- return '^4[0-9a-zA-Z]{94}\$|^8[0-9a-zA-Z]{94}\$|^[0-9a-zA-Z]{106}\$';
31
+ pattern = '4[0-9a-zA-Z]{94}|8[0-9a-zA-Z]{94}|[0-9a-zA-Z]{106}';
32
case CryptoCurrency.ada:
26
- return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$'
27
- '|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
33
+ pattern = '[0-9a-zA-Z]{59}|[0-9a-zA-Z]{92}|[0-9a-zA-Z]{104}'
34
+ '|[0-9a-zA-Z]{105}|addr1[0-9a-zA-Z]{98}';
35
case CryptoCurrency.btc:
29
- return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$|^${SilentPaymentAddress.regex.pattern}\$';
36
+ pattern =
37
+ '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
38
case CryptoCurrency.nano:
31
- return '[0-9a-zA-Z_]';
39
+ pattern = '[0-9a-zA-Z_]';
40
case CryptoCurrency.banano:
33
- return '[0-9a-zA-Z_]';
41
+ pattern = '[0-9a-zA-Z_]';
42
case CryptoCurrency.usdc:
43
case CryptoCurrency.usdcpoly:
44
case CryptoCurrency.usdtPoly:
@@ -66,11 +74,11 @@ class AddressValidator extends TextValidator {
74
case CryptoCurrency.dydx:
75
case CryptoCurrency.steth:
76
case CryptoCurrency.shib:
69
- return '0x[0-9a-zA-Z]';
77
+ pattern = '0x[0-9a-zA-Z]';
78
case CryptoCurrency.xrp:
71
- return '^[0-9a-zA-Z]{34}\$|^X[0-9a-zA-Z]{46}\$';
79
+ pattern = '[0-9a-zA-Z]{34}|X[0-9a-zA-Z]{46}';
80
case CryptoCurrency.xhv:
73
- return '^hvx|hvi|hvs[0-9a-zA-Z]';
81
+ pattern = 'hvx|hvi|hvs[0-9a-zA-Z]';
82
case CryptoCurrency.xag:
83
case CryptoCurrency.xau:
84
case CryptoCurrency.xaud:
@@ -92,40 +100,43 @@ class AddressValidator extends TextValidator {
100
case CryptoCurrency.dash:
101
case CryptoCurrency.eos:
102
case CryptoCurrency.wow:
95
- return '[0-9a-zA-Z]';
103
+ pattern = '[0-9a-zA-Z]';
104
case CryptoCurrency.bch:
97
- 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}\$';
105
+ pattern =
106
+ '(?!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}';
107
case CryptoCurrency.bnb:
99
- return '[0-9a-zA-Z]';
108
+ pattern = '[0-9a-zA-Z]';
109
case CryptoCurrency.ltc:
101
- return '^(?!(ltc|LTC)1)[0-9a-zA-Z]*\$|(^LTC1[A-Z0-9]*\$)|(^ltc1[a-z0-9]*\$)';
110
+ pattern = '(?!(ltc|LTC)1)[0-9a-zA-Z]*|(LTC1[A-Z0-9]*)|(ltc1[a-z0-9]*)';
111
case CryptoCurrency.hbar:
103
- return '[0-9a-zA-Z.]';
112
+ pattern = '[0-9a-zA-Z.]';
113
case CryptoCurrency.zaddr:
105
- return '^zs[0-9a-zA-Z]{75}';
114
+ pattern = 'zs[0-9a-zA-Z]{75}';
115
case CryptoCurrency.zec:
107
- return '^t1[0-9a-zA-Z]{33}\$|^t3[0-9a-zA-Z]{33}\$';
116
+ pattern = 't1[0-9a-zA-Z]{33}|t3[0-9a-zA-Z]{33}';
117
case CryptoCurrency.dcr:
109
- return 'D[ksecS]([0-9a-zA-Z])+';
118
+ pattern = 'D[ksecS]([0-9a-zA-Z])+';
119
case CryptoCurrency.rvn:
111
- return '[Rr]([1-9a-km-zA-HJ-NP-Z]){33}';
120
+ pattern = '[Rr]([1-9a-km-zA-HJ-NP-Z]){33}';
121
case CryptoCurrency.near:
113
- return '[0-9a-f]{64}';
122
+ pattern = '[0-9a-f]{64}';
123
case CryptoCurrency.rune:
115
- return 'thor1[0-9a-z]{38}';
124
+ pattern = 'thor1[0-9a-z]{38}';
125
case CryptoCurrency.scrt:
117
- return 'secret1[0-9a-z]{38}';
126
+ pattern = 'secret1[0-9a-z]{38}';
127
case CryptoCurrency.stx:
119
- return 'S[MP][0-9a-zA-Z]+';
128
+ pattern = 'S[MP][0-9a-zA-Z]+';
129
case CryptoCurrency.kmd:
121
- return 'R[0-9a-zA-Z]{33}';
130
+ pattern = 'R[0-9a-zA-Z]{33}';
131
case CryptoCurrency.pivx:
123
- return 'D([1-9a-km-zA-HJ-NP-Z]){33}';
132
+ pattern = 'D([1-9a-km-zA-HJ-NP-Z]){33}';
133
case CryptoCurrency.btcln:
125
- return '^(lnbc|LNBC)([0-9]{1,}[a-zA-Z0-9]+)';
134
+ pattern = '(lnbc|LNBC)([0-9]{1,}[a-zA-Z0-9]+)';
135
default:
127
- return '[0-9a-zA-Z]';
136
+ pattern = '[0-9a-zA-Z]';
137
}
138
+
139
+ return '$BEFORE_REGEX$pattern$AFTER_REGEX';
140
}
141
142
static List<int>? getLength(CryptoCurrency type) {
@@ -266,56 +277,54 @@ class AddressValidator extends TextValidator {
277
}
278
279
static String? getAddressFromStringPattern(CryptoCurrency type) {
280
+ String? pattern = null;
281
+
282
switch (type) {
283
case CryptoCurrency.xmr:
284
case CryptoCurrency.wow:
272
- return '([^0-9a-zA-Z]|^)4[0-9a-zA-Z]{94}([^0-9a-zA-Z]|\$)'
273
- '|([^0-9a-zA-Z]|^)8[0-9a-zA-Z]{94}([^0-9a-zA-Z]|\$)'
274
- '|([^0-9a-zA-Z]|^)[0-9a-zA-Z]{106}([^0-9a-zA-Z]|\$)';
285
+ pattern = '4[0-9a-zA-Z]{94}'
286
+ '|8[0-9a-zA-Z]{94}'
287
+ '|[0-9a-zA-Z]{106}';
288
case CryptoCurrency.btc:
276
- return '([^0-9a-zA-Z]|^)([1mn][a-km-zA-HJ-NP-Z1-9]{25,34})([^0-9a-zA-Z]|\$)' //P2pkhAddress type
277
- '|([^0-9a-zA-Z]|^)([23][a-km-zA-HJ-NP-Z1-9]{25,34})([^0-9a-zA-Z]|\$)' //P2shAddress type
278
- '|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{25,39})([^0-9a-zA-Z]|\$)' //P2wpkhAddress type
279
- '|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{40,80})([^0-9a-zA-Z]|\$)' //P2wshAddress type
280
- '|([^0-9a-zA-Z]|^)((bc|tb)1p([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59}|[ac-hj-np-z02-9]{8,89}))([^0-9a-zA-Z]|\$)' //P2trAddress type
281
- '|${SilentPaymentAddress.regex.pattern}\$';
282
-
289
+ pattern =
290
+ '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
291
case CryptoCurrency.ltc:
284
- return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)'
285
- '|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)'
286
- '|([^0-9a-zA-Z]|^)ltc[a-zA-Z0-9]{26,45}([^0-9a-zA-Z]|\$)';
292
+ pattern = '^L[a-zA-Z0-9]{26,33}'
293
+ '|[LM][a-km-zA-HJ-NP-Z1-9]{26,33}'
294
+ '|ltc[a-zA-Z0-9]{26,45}';
295
case CryptoCurrency.eth:
288
- return '0x[0-9a-zA-Z]{42}';
296
+ pattern = '0x[0-9a-zA-Z]{42}';
297
case CryptoCurrency.maticpoly:
290
- return '0x[0-9a-zA-Z]{42}';
298
+ pattern = '0x[0-9a-zA-Z]{42}';
299
case CryptoCurrency.nano:
292
- return 'nano_[0-9a-zA-Z]{60}';
300
+ pattern = 'nano_[0-9a-zA-Z]{60}';
301
case CryptoCurrency.banano:
294
- return 'ban_[0-9a-zA-Z]{60}';
302
+ pattern = 'ban_[0-9a-zA-Z]{60}';
303
case CryptoCurrency.bch:
296
- return 'bitcoincash:q[0-9a-zA-Z]{41}([^0-9a-zA-Z]|\$)'
297
- '|bitcoincash:q[0-9a-zA-Z]{42}([^0-9a-zA-Z]|\$)'
298
- '|([^0-9a-zA-Z]|^)q[0-9a-zA-Z]{41}([^0-9a-zA-Z]|\$)'
299
- '|([^0-9a-zA-Z]|^)q[0-9a-zA-Z]{42}([^0-9a-zA-Z]|\$)';
304
+ pattern = '(bitcoincash:)?q[0-9a-zA-Z]{41,42}';
305
case CryptoCurrency.sol:
301
- return '([^0-9a-zA-Z]|^)[1-9A-HJ-NP-Za-km-z]{43,44}([^0-9a-zA-Z]|\$)';
306
+ pattern = '[1-9A-HJ-NP-Za-km-z]{43,44}';
307
case CryptoCurrency.trx:
303
- return '(T|t)[1-9A-HJ-NP-Za-km-z]{33}';
308
+ pattern = '(T|t)[1-9A-HJ-NP-Za-km-z]{33}';
309
default:
310
if (type.tag == CryptoCurrency.eth.title) {
306
- return '0x[0-9a-zA-Z]{42}';
311
+ pattern = '0x[0-9a-zA-Z]{42}';
312
}
313
if (type.tag == CryptoCurrency.maticpoly.tag) {
309
- return '0x[0-9a-zA-Z]{42}';
314
+ pattern = '0x[0-9a-zA-Z]{42}';
315
}
316
if (type.tag == CryptoCurrency.sol.title) {
312
- return '([^0-9a-zA-Z]|^)[1-9A-HJ-NP-Za-km-z]{43,44}([^0-9a-zA-Z]|\$)';
317
+ pattern = '[1-9A-HJ-NP-Za-km-z]{43,44}';
318
}
319
if (type.tag == CryptoCurrency.trx.title) {
315
- return '(T|t)[1-9A-HJ-NP-Za-km-z]{33}';
320
+ pattern = '(T|t)[1-9A-HJ-NP-Za-km-z]{33}';
321
}
322
+ }
323
318
- return null;
324
+ if (pattern != null) {
325
+ return "$BEFORE_REGEX$pattern$AFTER_REGEX";
326
}
327
+
328
+ return null;
329
}
330
}
lib/core/sync_status_title.dart
+5
-1
@@ -53,7 +53,11 @@ String syncStatusTitle(SyncStatus syncStatus) {
53
}
54
55
if (syncStatus is StartingScanSyncStatus) {
56
- return S.current.sync_status_starting_scan;
56
+ return S.current.sync_status_starting_scan(syncStatus.beginHeight.toString());
57
+ }
58
+
59
+ if (syncStatus is AttemptingScanSyncStatus) {
60
+ return S.current.sync_status_attempting_scan;
61
}
62
63
return '';
lib/entities/parse_address_from_domain.dart
+2
-3
@@ -51,7 +51,7 @@ class AddressResolver {
51
throw Exception('Unexpected token: $type for getAddressFromStringPattern');
52
}
53
54
- final match = RegExp(addressPattern).firstMatch(raw);
54
+ final match = RegExp(addressPattern, multiLine: true).firstMatch(raw);
55
return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_|ban_'),
56
(Match match) {
57
String group = match.group(0)!;
@@ -213,8 +213,7 @@ class AddressResolver {
213
await NostrProfileHandler.processRelays(context, nostrProfile!, text);
214
215
if (nostrUserData != null) {
216
- String? addressFromBio = extractAddressByType(
217
- raw: nostrUserData.about, type: currency);
216
+ String? addressFromBio = extractAddressByType(raw: nostrUserData.about, type: currency);
217
if (addressFromBio != null) {
218
return ParsedAddress.nostrAddress(
219
address: addressFromBio,
lib/src/screens/dashboard/pages/transactions_page.dart
+8
-4
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/bitcoin/bitcoin.dart';
2
import 'package:cake_wallet/src/screens/dashboard/widgets/anonpay_transaction_row.dart';
3
import 'package:cake_wallet/src/screens/dashboard/widgets/order_row.dart';
4
import 'package:cake_wallet/themes/extensions/placeholder_theme.dart';
@@ -52,7 +53,7 @@ class TransactionsPage extends StatelessWidget {
53
try {
54
final uri = Uri.parse(
55
"https://guides.cakewallet.com/docs/FAQ/why_are_my_funds_not_appearing/");
55
- launchUrl(uri, mode: LaunchMode.externalApplication);
56
+ launchUrl(uri, mode: LaunchMode.externalApplication);
57
} catch (_) {}
58
},
59
title: S.of(context).syncing_wallet_alert_title,
@@ -84,7 +85,7 @@ class TransactionsPage extends StatelessWidget {
85
86
final transaction = item.transaction;
87
final transactionType = dashboardViewModel.type == WalletType.ethereum &&
87
- transaction.evmSignatureName == 'approval'
88
+ transaction.evmSignatureName == 'approval'
89
? ' (${transaction.evmSignatureName})'
90
: '';
91
@@ -100,8 +101,11 @@ class TransactionsPage extends StatelessWidget {
101
? ''
102
: item.formattedFiatAmount,
103
isPending: transaction.isPending,
103
- title: item.formattedTitle +
104
- item.formattedStatus + ' $transactionType',
104
+ title:
105
+ item.formattedTitle + item.formattedStatus + ' $transactionType',
106
+ isReceivedSilentPayment:
107
+ dashboardViewModel.type == WalletType.bitcoin &&
108
+ bitcoin!.txIsReceivedSilentPayment(transaction),
109
),
110
);
111
}
lib/src/screens/dashboard/widgets/transaction_raw.dart
+80
-46
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/generated/i18n.dart';
2
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
3
import 'package:flutter/material.dart';
4
import 'package:cw_core/transaction_direction.dart';
@@ -5,14 +6,16 @@ import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
6
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
7
8
class TransactionRow extends StatelessWidget {
8
- TransactionRow(
9
- {required this.direction,
10
- required this.formattedDate,
11
- required this.formattedAmount,
12
- required this.formattedFiatAmount,
13
- required this.isPending,
14
- required this.title,
15
- required this.onTap});
9
+ TransactionRow({
10
+ required this.direction,
11
+ required this.formattedDate,
12
+ required this.formattedAmount,
13
+ required this.formattedFiatAmount,
14
+ required this.isPending,
15
+ required this.isReceivedSilentPayment,
16
+ required this.title,
17
+ required this.onTap,
18
+ });
19
20
final VoidCallback onTap;
21
final TransactionDirection direction;
@@ -20,6 +23,7 @@ class TransactionRow extends StatelessWidget {
23
final String formattedAmount;
24
final String formattedFiatAmount;
25
final bool isPending;
26
+ final bool isReceivedSilentPayment;
27
final String title;
28
29
@override
@@ -38,50 +42,80 @@ class TransactionRow extends StatelessWidget {
42
width: 36,
43
decoration: BoxDecoration(
44
shape: BoxShape.circle,
41
- color: Theme.of(context).extension<TransactionTradeTheme>()!.rowsColor
42
- ),
43
- child: Image.asset(
44
- direction == TransactionDirection.incoming
45
- ? 'assets/images/down_arrow.png'
46
- : 'assets/images/up_arrow.png'),
45
+ color: Theme.of(context).extension<TransactionTradeTheme>()!.rowsColor),
46
+ child: Image.asset(direction == TransactionDirection.incoming
47
+ ? 'assets/images/down_arrow.png'
48
+ : 'assets/images/up_arrow.png'),
49
),
50
SizedBox(width: 12),
51
Expanded(
52
child: Column(
51
- mainAxisSize: MainAxisSize.min,
52
- children: [
53
- Row(
54
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
55
- children: <Widget>[
56
- Text(title,
57
- style: TextStyle(
58
- fontSize: 16,
59
- fontWeight: FontWeight.w500,
60
- color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)),
61
- Text(formattedAmount,
62
- style: TextStyle(
63
- fontSize: 16,
64
- fontWeight: FontWeight.w500,
65
- color: Theme.of(context).extension<DashboardPageTheme>()!.textColor))
66
- ]),
67
- SizedBox(height: 5),
68
- Row(
69
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
70
- children: <Widget>[
71
- Text(formattedDate,
72
- style: TextStyle(
73
- fontSize: 14,
74
- color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)),
75
- Text(formattedFiatAmount,
76
- style: TextStyle(
77
- fontSize: 14,
78
- color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
79
- ])
80
- ],
81
- )
82
- )
53
+ mainAxisSize: MainAxisSize.min,
54
+ children: [
55
+ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[
56
+ Row(
57
+ children: [
58
+ Text(title,
59
+ style: TextStyle(
60
+ fontSize: 16,
61
+ fontWeight: FontWeight.w500,
62
+ color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
63
+ )),
64
+ if (isReceivedSilentPayment) TxTag(tag: S.of(context).silent_payment),
65
+ ],
66
+ ),
67
+ Text(formattedAmount,
68
+ style: TextStyle(
69
+ fontSize: 16,
70
+ fontWeight: FontWeight.w500,
71
+ color: Theme.of(context).extension<DashboardPageTheme>()!.textColor))
72
+ ]),
73
+ SizedBox(height: 5),
74
+ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[
75
+ Text(formattedDate,
76
+ style: TextStyle(
77
+ fontSize: 14,
78
+ color:
79
+ Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)),
80
+ Text(formattedFiatAmount,
81
+ style: TextStyle(
82
+ fontSize: 14,
83
+ color:
84
+ Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
85
+ ])
86
+ ],
87
+ ))
88
],
89
),
90
));
91
}
92
}
93
+
94
+// A tag to add context to a transaction
95
+// example use: differ silent payments from regular txs
96
+class TxTag extends StatelessWidget {
97
+ TxTag({required this.tag});
98
+
99
+ final String tag;
100
+
101
+ @override
102
+ Widget build(BuildContext context) {
103
+ return Container(
104
+ height: 17,
105
+ padding: EdgeInsets.only(left: 6, right: 6),
106
+ decoration: BoxDecoration(
107
+ borderRadius: BorderRadius.all(Radius.circular(8.5)),
108
+ color: Theme.of(context).extension<TransactionTradeTheme>()!.rowsColor,
109
+ ),
110
+ alignment: Alignment.center,
111
+ child: Text(
112
+ tag.toLowerCase(),
113
+ style: TextStyle(
114
+ color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
115
+ fontSize: 9,
116
+ fontWeight: FontWeight.w600,
117
+ ),
118
+ ),
119
+ );
120
+ }
121
+}
lib/src/screens/rescan/rescan_page.dart
+1
@@ -37,6 +37,7 @@ class RescanPage extends BasePage {
37
toggleSingleScan: () =>
38
_rescanViewModel.doSingleScan = !_rescanViewModel.doSingleScan,
39
walletType: _rescanViewModel.wallet.type,
40
+ bitcoinMempoolAPIEnabled: _rescanViewModel.isBitcoinMempoolAPIEnabled,
41
)),
42
Observer(
43
builder: (_) => LoadingPrimaryButton(
lib/src/screens/send/send_page.dart
+25
-25
@@ -68,11 +68,11 @@ class SendPage extends BasePage {
68
69
@override
70
Function(BuildContext)? get pushToNextWidget => (context) {
71
- FocusScopeNode currentFocus = FocusScope.of(context);
72
- if (!currentFocus.hasPrimaryFocus) {
73
- currentFocus.focusedChild?.unfocus();
74
- }
75
- };
71
+ FocusScopeNode currentFocus = FocusScope.of(context);
72
+ if (!currentFocus.hasPrimaryFocus) {
73
+ currentFocus.focusedChild?.unfocus();
74
+ }
75
+ };
76
77
@override
78
Widget? leading(BuildContext context) {
@@ -212,26 +212,25 @@ class SendPage extends BasePage {
212
final count = sendViewModel.outputs.length;
213
214
return count > 1
215
- ? Semantics (
216
- label: 'Page Indicator',
217
- hint: 'Swipe to change receiver',
218
- excludeSemantics: true,
219
- child:
220
- SmoothPageIndicator(
221
- controller: controller,
222
- count: count,
223
- effect: ScrollingDotsEffect(
224
- spacing: 6.0,
225
- radius: 6.0,
226
- dotWidth: 6.0,
227
- dotHeight: 6.0,
228
- dotColor: Theme.of(context)
229
- .extension<SendPageTheme>()!
230
- .indicatorDotColor,
231
- activeDotColor: Theme.of(context)
232
- .extension<SendPageTheme>()!
233
- .templateBackgroundColor),
234
- ))
215
+ ? Semantics(
216
+ label: 'Page Indicator',
217
+ hint: 'Swipe to change receiver',
218
+ excludeSemantics: true,
219
+ child: SmoothPageIndicator(
220
+ controller: controller,
221
+ count: count,
222
+ effect: ScrollingDotsEffect(
223
+ spacing: 6.0,
224
+ radius: 6.0,
225
+ dotWidth: 6.0,
226
+ dotHeight: 6.0,
227
+ dotColor: Theme.of(context)
228
+ .extension<SendPageTheme>()!
229
+ .indicatorDotColor,
230
+ activeDotColor: Theme.of(context)
231
+ .extension<SendPageTheme>()!
232
+ .templateBackgroundColor),
233
+ ))
234
: Offstage();
235
},
236
),
@@ -478,6 +477,7 @@ class SendPage extends BasePage {
477
feeValue: sendViewModel.pendingTransaction!.feeFormatted,
478
feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
479
outputs: sendViewModel.outputs,
480
+ change: sendViewModel.pendingTransaction!.change,
481
rightButtonText: S.of(_dialogContext).send,
482
leftButtonText: S.of(_dialogContext).cancel,
483
actionRightButton: () async {
lib/src/screens/send/widgets/confirm_sending_alert.dart
+133
-92
@@ -1,6 +1,7 @@
1
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
2
import 'package:cake_wallet/palette.dart';
3
import 'package:cake_wallet/view_model/send/output.dart';
4
+import 'package:cw_core/pending_transaction.dart';
5
import 'package:flutter/material.dart';
6
import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
7
import 'package:cake_wallet/generated/i18n.dart';
@@ -21,6 +22,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
22
required this.feeValue,
23
required this.feeFiatAmount,
24
required this.outputs,
25
+ this.change,
26
required this.leftButtonText,
27
required this.rightButtonText,
28
required this.actionLeftButton,
@@ -44,6 +46,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
46
final String feeValue;
47
final String feeFiatAmount;
48
final List<Output> outputs;
49
+ final PendingChange? change;
50
final String leftButtonText;
51
final String rightButtonText;
52
final VoidCallback actionLeftButton;
@@ -101,6 +104,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
104
feeValue: feeValue,
105
feeFiatAmount: feeFiatAmount,
106
outputs: outputs,
107
+ change: change,
108
onDispose: onDispose);
109
}
110
@@ -117,6 +121,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
121
required this.feeValue,
122
required this.feeFiatAmount,
123
required this.outputs,
124
+ this.change,
125
required this.onDispose}) {}
126
127
final String? paymentId;
@@ -130,6 +135,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
135
final String feeValue;
136
final String feeFiatAmount;
137
final List<Output> outputs;
138
+ final PendingChange? change;
139
final Function? onDispose;
140
141
@override
@@ -145,6 +151,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
151
feeValue: feeValue,
152
feeFiatAmount: feeFiatAmount,
153
outputs: outputs,
154
+ change: change,
155
onDispose: onDispose);
156
}
157
@@ -161,6 +168,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
168
required this.feeValue,
169
required this.feeFiatAmount,
170
required this.outputs,
171
+ this.change,
172
this.onDispose})
173
: recipientTitle = '' {
174
recipientTitle = outputs.length > 1
@@ -179,6 +187,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
187
final String feeValue;
188
final String feeFiatAmount;
189
final List<Output> outputs;
190
+ final PendingChange? change;
191
final Function? onDispose;
192
193
final double backgroundHeight = 160;
@@ -391,100 +400,57 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
400
decoration: TextDecoration.none,
401
),
402
),
394
- outputs.length > 1
395
- ? ListView.builder(
396
- padding: EdgeInsets.only(top: 0),
397
- shrinkWrap: true,
398
- physics: NeverScrollableScrollPhysics(),
399
- itemCount: outputs.length,
400
- itemBuilder: (context, index) {
401
- final item = outputs[index];
402
- final _address =
403
- item.isParsedAddress ? item.extractedAddress : item.address;
404
- final _amount = item.cryptoAmount.replaceAll(',', '.');
405
-
406
- return Column(
407
- children: [
408
- if (item.isParsedAddress)
409
- Padding(
410
- padding: EdgeInsets.only(top: 8),
411
- child: Text(
412
- item.parsedAddress.name,
413
- textAlign: TextAlign.center,
414
- style: TextStyle(
415
- fontSize: 14,
416
- fontWeight: FontWeight.w600,
417
- fontFamily: 'Lato',
418
- color: PaletteDark.pigeonBlue,
419
- decoration: TextDecoration.none,
420
- ),
421
- )),
422
- Padding(
423
- padding: EdgeInsets.only(top: 8),
424
- child: Text(
425
- _address,
426
- style: TextStyle(
427
- fontSize: 10,
428
- fontWeight: FontWeight.w600,
429
- fontFamily: 'Lato',
430
- color: PaletteDark.pigeonBlue,
431
- decoration: TextDecoration.none,
432
- ),
433
- )),
434
- Padding(
435
- padding: EdgeInsets.only(top: 8),
436
- child: Row(
437
- mainAxisSize: MainAxisSize.max,
438
- mainAxisAlignment: MainAxisAlignment.end,
439
- children: [
440
- Text(
441
- _amount,
442
- style: TextStyle(
443
- fontSize: 10,
444
- fontWeight: FontWeight.w600,
445
- fontFamily: 'Lato',
446
- color: PaletteDark.pigeonBlue,
447
- decoration: TextDecoration.none,
448
- ),
449
- )
450
- ],
451
- ))
452
- ],
453
- );
454
- })
455
- : Column(children: [
456
- if (outputs.first.isParsedAddress)
457
- Padding(
458
- padding: EdgeInsets.only(top: 8),
459
- child: Text(
460
- outputs.first.parsedAddress.name,
461
- textAlign: TextAlign.center,
462
- style: TextStyle(
463
- fontSize: 14,
464
- fontWeight: FontWeight.w600,
465
- fontFamily: 'Lato',
466
- color: PaletteDark.pigeonBlue,
467
- decoration: TextDecoration.none,
468
- ),
469
- )),
470
- Padding(
471
- padding: EdgeInsets.only(top: 8),
472
- child: Text(
473
- outputs.first.isParsedAddress
474
- ? outputs.first.extractedAddress
475
- : outputs.first.address,
476
- style: TextStyle(
477
- fontSize: 10,
478
- fontWeight: FontWeight.w600,
479
- fontFamily: 'Lato',
480
- color: PaletteDark.pigeonBlue,
481
- decoration: TextDecoration.none,
482
- ),
483
- )),
484
- ])
403
+ ListView.builder(
404
+ padding: EdgeInsets.only(top: 0),
405
+ shrinkWrap: true,
406
+ physics: NeverScrollableScrollPhysics(),
407
+ itemCount: outputs.length,
408
+ itemBuilder: (context, index) {
409
+ final item = outputs[index];
410
+ final _address =
411
+ item.isParsedAddress ? item.extractedAddress : item.address;
412
+ final _amount = item.cryptoAmount.replaceAll(',', '.');
413
+
414
+ return Column(
415
+ children: [
416
+ if (item.isParsedAddress)
417
+ AddressText(text: item.parsedAddress.name),
418
+ AddressText(text: _address, fontSize: 10),
419
+ if (stealthAddressText(item.stealthAddress) != null)
420
+ AddressText(
421
+ text: stealthAddressText(item.stealthAddress)!, fontSize: 10),
422
+ AmountText(text: _amount),
423
+ ],
424
+ );
425
+ },
426
+ )
427
],
428
),
487
- )
429
+ ),
430
+ if (change != null)
431
+ Padding(
432
+ padding: EdgeInsets.only(top: 16),
433
+ child: Column(
434
+ children: [
435
+ Text(
436
+ S.of(context).send_change_to_you,
437
+ style: TextStyle(
438
+ fontSize: 16,
439
+ fontWeight: FontWeight.normal,
440
+ fontFamily: 'Lato',
441
+ color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
442
+ decoration: TextDecoration.none,
443
+ ),
444
+ ),
445
+ Column(
446
+ children: [
447
+ AddressText(text: change!.address, fontSize: 10),
448
+ AmountText(text: change!.amount),
449
+ ],
450
+ )
451
+ ],
452
+ ),
453
+ )
454
],
455
))),
456
if (showScrollbar)
@@ -539,3 +505,78 @@ class ExpirationTimeWidget extends StatelessWidget {
505
);
506
}
507
}
508
+
509
+class AddressText extends StatelessWidget {
510
+ final String text;
511
+ final double fontSize;
512
+ final FontWeight fontWeight;
513
+ final TextAlign? textAlign;
514
+
515
+ const AddressText({
516
+ required this.text,
517
+ this.fontSize = 14,
518
+ this.fontWeight = FontWeight.w600,
519
+ this.textAlign,
520
+ });
521
+
522
+ @override
523
+ Widget build(BuildContext context) {
524
+ return Padding(
525
+ padding: EdgeInsets.only(top: 8),
526
+ child: Text(
527
+ text,
528
+ style: TextStyle(
529
+ fontSize: fontSize,
530
+ fontWeight: fontWeight,
531
+ fontFamily: 'Lato',
532
+ color: PaletteDark.pigeonBlue,
533
+ decoration: TextDecoration.none,
534
+ ),
535
+ ),
536
+ );
537
+ }
538
+}
539
+
540
+class AmountText extends StatelessWidget {
541
+ final String text;
542
+ final double fontSize;
543
+ final FontWeight fontWeight;
544
+ final TextAlign? textAlign;
545
+
546
+ const AmountText({
547
+ required this.text,
548
+ this.fontSize = 10,
549
+ this.fontWeight = FontWeight.w600,
550
+ this.textAlign,
551
+ });
552
+
553
+ @override
554
+ Widget build(BuildContext context) {
555
+ return Padding(
556
+ padding: EdgeInsets.only(top: 8),
557
+ child: Row(
558
+ mainAxisSize: MainAxisSize.max,
559
+ mainAxisAlignment: MainAxisAlignment.end,
560
+ children: [
561
+ Text(
562
+ text,
563
+ style: TextStyle(
564
+ fontSize: fontSize,
565
+ fontWeight: fontWeight,
566
+ fontFamily: 'Lato',
567
+ color: PaletteDark.pigeonBlue,
568
+ decoration: TextDecoration.none,
569
+ ),
570
+ )
571
+ ],
572
+ ));
573
+ }
574
+}
575
+
576
+String? stealthAddressText(String? stealthAddress) {
577
+ if (stealthAddress == null) {
578
+ return null;
579
+ }
580
+
581
+ return stealthAddress.isNotEmpty ? "-> $stealthAddress" : null;
582
+}
lib/src/screens/settings/privacy_page.dart
+13
-13
@@ -58,8 +58,8 @@ class PrivacyPage extends BasePage {
58
if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
59
SettingsSwitcherCell(
60
title: _privacySettingsViewModel.isMoneroWallet
61
- ? S.current.auto_generate_subaddresses
62
- : S.current.auto_generate_addresses,
61
+ ? S.current.auto_generate_subaddresses
62
+ : S.current.auto_generate_addresses,
63
value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
64
onValueChange: (BuildContext _, bool value) {
65
_privacySettingsViewModel.setAutoGenerateSubaddresses(value);
@@ -115,21 +115,21 @@ class PrivacyPage extends BasePage {
115
),
116
if (_privacySettingsViewModel.canUseMempoolFeeAPI)
117
SettingsSwitcherCell(
118
- title: S.current.live_fee_rates,
118
+ title: S.current.enable_mempool_api,
119
value: _privacySettingsViewModel.useMempoolFeeAPI,
120
onValueChange: (BuildContext _, bool isEnabled) async {
121
if (!isEnabled) {
122
final bool confirmation = await showPopUp<bool>(
123
- context: context,
124
- builder: (BuildContext context) {
125
- return AlertWithTwoActions(
126
- alertTitle: S.of(context).warning,
127
- alertContent: S.of(context).disable_fee_api_warning,
128
- rightButtonText: S.of(context).confirm,
129
- leftButtonText: S.of(context).cancel,
130
- actionRightButton: () => Navigator.of(context).pop(true),
131
- actionLeftButton: () => Navigator.of(context).pop(false));
132
- }) ??
123
+ context: context,
124
+ builder: (BuildContext context) {
125
+ return AlertWithTwoActions(
126
+ alertTitle: S.of(context).warning,
127
+ alertContent: S.of(context).disable_fee_api_warning,
128
+ rightButtonText: S.of(context).confirm,
129
+ leftButtonText: S.of(context).cancel,
130
+ actionRightButton: () => Navigator.of(context).pop(true),
131
+ actionLeftButton: () => Navigator.of(context).pop(false));
132
+ }) ??
133
false;
134
if (confirmation) {
135
_privacySettingsViewModel.setUseMempoolFeeAPI(isEnabled);
lib/src/widgets/blockchain_height_widget.dart
+11
-3
@@ -20,6 +20,7 @@ class BlockchainHeightWidget extends StatefulWidget {
20
this.isSilentPaymentsScan = false,
21
this.toggleSingleScan,
22
this.doSingleScan = false,
23
+ this.bitcoinMempoolAPIEnabled,
24
required this.walletType,
25
}) : super(key: key);
26
@@ -29,6 +30,7 @@ class BlockchainHeightWidget extends StatefulWidget {
30
final bool hasDatePicker;
31
final bool isSilentPaymentsScan;
32
final bool doSingleScan;
33
+ final Future<bool>? bitcoinMempoolAPIEnabled;
34
final Function()? toggleSingleScan;
35
final WalletType walletType;
36
@@ -79,7 +81,8 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
81
child: BaseTextFormField(
82
focusNode: widget.focusNode,
83
controller: restoreHeightController,
82
- keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
84
+ keyboardType:
85
+ TextInputType.numberWithOptions(signed: false, decimal: false),
86
hintText: widget.isSilentPaymentsScan
87
? S.of(context).silent_payments_scan_from_height
88
: S.of(context).widgets_restore_from_blockheight,
@@ -146,7 +149,9 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
149
: S.of(context).restore_from_date_or_blockheight,
150
textAlign: TextAlign.center,
151
style: TextStyle(
149
- fontSize: 12, fontWeight: FontWeight.normal, color: Theme.of(context).hintColor),
152
+ fontSize: 12,
153
+ fontWeight: FontWeight.normal,
154
+ color: Theme.of(context).hintColor),
155
),
156
)
157
]
@@ -166,7 +171,10 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
171
if (date != null) {
172
int height;
173
if (widget.isSilentPaymentsScan) {
169
- height = bitcoin!.getHeightByDate(date: date);
174
+ height = await bitcoin!.getHeightByDate(
175
+ date: date,
176
+ bitcoinMempoolAPIEnabled: await widget.bitcoinMempoolAPIEnabled,
177
+ );
178
} else {
179
if (widget.walletType == WalletType.monero) {
180
height = monero!.getHeightByDate(date: date);
lib/store/dashboard/transaction_filter_store.dart
+34
-25
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/bitcoin/bitcoin.dart';
2
import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
3
import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart';
4
import 'package:mobx/mobx.dart';
@@ -6,12 +7,13 @@ import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
7
8
part 'transaction_filter_store.g.dart';
9
9
-class TransactionFilterStore = TransactionFilterStoreBase
10
- with _$TransactionFilterStore;
10
+class TransactionFilterStore = TransactionFilterStoreBase with _$TransactionFilterStore;
11
12
abstract class TransactionFilterStoreBase with Store {
13
- TransactionFilterStoreBase() : displayIncoming = true,
14
- displayOutgoing = true;
13
+ TransactionFilterStoreBase()
14
+ : displayIncoming = true,
15
+ displayOutgoing = true,
16
+ displaySilentPayments = true;
17
18
@observable
19
bool displayIncoming;
@@ -19,6 +21,9 @@ abstract class TransactionFilterStoreBase with Store {
21
@observable
22
bool displayOutgoing;
23
24
+ @observable
25
+ bool displaySilentPayments;
26
+
27
@observable
28
DateTime? startDate;
29
@@ -26,31 +31,36 @@ abstract class TransactionFilterStoreBase with Store {
31
DateTime? endDate;
32
33
@computed
29
- bool get displayAll => displayIncoming && displayOutgoing;
34
+ bool get displayAll => displayIncoming && displayOutgoing && displaySilentPayments;
35
36
@action
37
void toggleAll() {
38
if (displayAll) {
39
displayOutgoing = false;
40
displayIncoming = false;
41
+ displaySilentPayments = false;
42
} else {
43
displayOutgoing = true;
44
displayIncoming = true;
45
+ displaySilentPayments = true;
46
}
47
}
48
42
-
49
@action
50
void toggleIncoming() {
51
displayIncoming = !displayIncoming;
52
}
53
48
-
54
@action
55
void toggleOutgoing() {
56
displayOutgoing = !displayOutgoing;
57
}
58
59
+ @action
60
+ void toggleSilentPayments() {
61
+ displaySilentPayments = !displaySilentPayments;
62
+ }
63
+
64
@action
65
void changeStartDate(DateTime date) => startDate = date;
66
@@ -59,34 +69,33 @@ abstract class TransactionFilterStoreBase with Store {
69
70
List<ActionListItem> filtered({required List<ActionListItem> transactions}) {
71
var _transactions = <ActionListItem>[];
62
- final needToFilter = !displayAll ||
63
- (startDate != null && endDate != null);
72
+ final needToFilter = !displayAll || (startDate != null && endDate != null);
73
74
if (needToFilter) {
75
_transactions = transactions.where((item) {
76
var allowed = true;
77
78
if (allowed && startDate != null && endDate != null) {
70
- if(item is TransactionListItem){
71
- allowed = (startDate?.isBefore(item.transaction.date) ?? false)
72
- && (endDate?.isAfter(item.transaction.date) ?? false);
73
- }else if(item is AnonpayTransactionListItem){
74
- allowed = (startDate?.isBefore(item.transaction.createdAt) ?? false)
75
- && (endDate?.isAfter(item.transaction.createdAt) ?? false);
76
- }
79
+ if (item is TransactionListItem) {
80
+ allowed = (startDate?.isBefore(item.transaction.date) ?? false) &&
81
+ (endDate?.isAfter(item.transaction.date) ?? false);
82
+ } else if (item is AnonpayTransactionListItem) {
83
+ allowed = (startDate?.isBefore(item.transaction.createdAt) ?? false) &&
84
+ (endDate?.isAfter(item.transaction.createdAt) ?? false);
85
+ }
86
}
87
88
if (allowed && (!displayAll)) {
80
- if(item is TransactionListItem){
81
- allowed = (displayOutgoing &&
82
- item.transaction.direction ==
83
- TransactionDirection.outgoing) ||
84
- (displayIncoming &&
85
- item.transaction.direction == TransactionDirection.incoming);
86
- } else if(item is AnonpayTransactionListItem){
89
+ if (item is TransactionListItem) {
90
+ allowed =
91
+ (displayOutgoing && item.transaction.direction == TransactionDirection.outgoing) ||
92
+ (displayIncoming &&
93
+ item.transaction.direction == TransactionDirection.incoming &&
94
+ !bitcoin!.txIsReceivedSilentPayment(item.transaction)) ||
95
+ (displaySilentPayments && bitcoin!.txIsReceivedSilentPayment(item.transaction));
96
+ } else if (item is AnonpayTransactionListItem) {
97
allowed = displayIncoming;
98
}
89
-
99
}
100
101
return allowed;
@@ -97,4 +106,4 @@ abstract class TransactionFilterStoreBase with Store {
106
107
return _transactions;
108
}
100
-}
\ No newline at end of file
109
+}
lib/view_model/dashboard/dashboard_view_model.dart
+11
-3
@@ -88,6 +88,11 @@ abstract class DashboardViewModelBase with Store {
88
value: () => transactionFilterStore.displayOutgoing,
89
caption: S.current.outgoing,
90
onChanged: transactionFilterStore.toggleOutgoing),
91
+ FilterItem(
92
+ value: () => transactionFilterStore.displaySilentPayments,
93
+ caption: S.current.silent_payments,
94
+ onChanged: transactionFilterStore.toggleSilentPayments,
95
+ ),
96
// FilterItem(
97
// value: () => false,
98
// caption: S.current.transactions_by_date,
@@ -376,12 +381,15 @@ abstract class DashboardViewModelBase with Store {
381
// to not cause work duplication, this will do the job as well, it will be slightly less precise
382
// about what happened - but still enough.
383
// if (keys['privateSpendKey'] == List.generate(64, (index) => "0").join("")) "Private spend key is 0",
379
- if (keys['privateViewKey'] == List.generate(64, (index) => "0").join("")) "private view key is 0",
384
+ if (keys['privateViewKey'] == List.generate(64, (index) => "0").join(""))
385
+ "private view key is 0",
386
// if (keys['publicSpendKey'] == List.generate(64, (index) => "0").join("")) "public spend key is 0",
381
- if (keys['publicViewKey'] == List.generate(64, (index) => "0").join("")) "public view key is 0",
387
+ if (keys['publicViewKey'] == List.generate(64, (index) => "0").join(""))
388
+ "public view key is 0",
389
// if (wallet.seed == null) "wallet seed is null",
390
// if (wallet.seed == "") "wallet seed is empty",
384
- if (monero!.getSubaddressList(wallet).getAll(wallet)[0].address == "41d7FXjswpK1111111111111111111111111111111111111111111111111111111111111111111111111111112KhNi4")
391
+ if (monero!.getSubaddressList(wallet).getAll(wallet)[0].address ==
392
+ "41d7FXjswpK1111111111111111111111111111111111111111111111111111111111111111111111111111112KhNi4")
393
"primary address is invalid, you won't be able to receive / spend funds",
394
];
395
return errors;
lib/view_model/rescan_view_model.dart
+4
@@ -29,6 +29,10 @@ abstract class RescanViewModelBase with Store {
29
@computed
30
bool get isSilentPaymentsScan => wallet.type == WalletType.bitcoin;
31
32
+ @computed
33
+ Future<bool> get isBitcoinMempoolAPIEnabled async =>
34
+ wallet.type == WalletType.bitcoin && await bitcoin!.checkIfMempoolAPIIsEnabled(wallet);
35
+
36
@action
37
Future<void> rescanCurrentWallet({required int restoreHeight}) async {
38
state = RescanWalletState.rescaning;
lib/view_model/send/output.dart
+11
-8
@@ -79,6 +79,9 @@ abstract class OutputBase with Store {
79
bool get isParsedAddress =>
80
parsedAddress.parseFrom != ParseFrom.notParsed && parsedAddress.name.isNotEmpty;
81
82
+ @observable
83
+ String? stealthAddress;
84
+
85
@computed
86
int get formattedCryptoAmount {
87
int amount = 0;
@@ -134,9 +137,8 @@ abstract class OutputBase with Store {
137
final trc20EstimatedFee = tron!.getTronTRC20EstimatedFee(_wallet) ?? 0;
138
return double.parse(trc20EstimatedFee.toString());
139
}
137
-
140
}
139
-
141
+
142
if (_wallet.type == WalletType.solana) {
143
return solana!.getEstimateFees(_wallet) ?? 0.0;
144
}
@@ -145,16 +147,16 @@ abstract class OutputBase with Store {
147
_settingsStore.priority[_wallet.type]!, formattedCryptoAmount);
148
149
if (_wallet.type == WalletType.bitcoin) {
148
- if (_settingsStore.priority[_wallet.type] == bitcoin!.getBitcoinTransactionPriorityCustom()) {
149
- fee = bitcoin!.getEstimatedFeeWithFeeRate(_wallet,
150
- _settingsStore.customBitcoinFeeRate,formattedCryptoAmount);
150
+ if (_settingsStore.priority[_wallet.type] ==
151
+ bitcoin!.getBitcoinTransactionPriorityCustom()) {
152
+ fee = bitcoin!.getEstimatedFeeWithFeeRate(
153
+ _wallet, _settingsStore.customBitcoinFeeRate, formattedCryptoAmount);
154
}
155
156
return bitcoin!.formatterBitcoinAmountToDouble(amount: fee);
157
}
158
156
- if (_wallet.type == WalletType.litecoin ||
157
- _wallet.type == WalletType.bitcoinCash) {
159
+ if (_wallet.type == WalletType.litecoin || _wallet.type == WalletType.bitcoinCash) {
160
return bitcoin!.formatterBitcoinAmountToDouble(amount: fee);
161
}
162
@@ -249,7 +251,8 @@ abstract class OutputBase with Store {
251
try {
252
final fiat = calculateFiatAmount(
253
price: _fiatConversationStore.prices[cryptoCurrencyHandler()]!,
252
- cryptoAmount: sendAll ? cryptoFullBalance.replaceAll(",", ".") : cryptoAmount.replaceAll(',', '.'));
254
+ cryptoAmount:
255
+ sendAll ? cryptoFullBalance.replaceAll(",", ".") : cryptoAmount.replaceAll(',', '.'));
256
if (fiatAmount != fiat) {
257
fiatAmount = fiat;
258
}
lib/view_model/send/send_view_model.dart
+9
-2
@@ -375,6 +375,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
375
throw Exception("THORChain does not support Taproot addresses");
376
}
377
}
378
+
379
+ if (wallet.type == WalletType.bitcoin) {
380
+ final updatedOutputs = bitcoin!.updateOutputs(pendingTransaction!, outputs);
381
+
382
+ if (outputs.length == updatedOutputs.length) {
383
+ outputs = ObservableList.of(updatedOutputs);
384
+ }
385
+ }
386
+
387
state = ExecutedSuccessfullyState();
388
return pendingTransaction;
389
} catch (e) {
@@ -414,8 +423,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
423
}
424
425
Future<void> _executeReplaceByFee(TransactionInfo tx, String newFee) async {
417
-
418
-
426
clearOutputs();
427
final output = outputs.first;
428
output.address = tx.outputAddresses?.first ?? '';
pubspec_base.yaml
+2
-2
@@ -100,7 +100,7 @@ dependencies:
100
bitcoin_base:
101
git:
102
url: https://github.com/cake-tech/bitcoin_base
103
- ref: cake-update-v5
103
+ ref: cake-update-v7
104
ledger_flutter: ^1.0.1
105
hashlib: ^1.19.2
106
@@ -138,7 +138,7 @@ dependency_overrides:
138
bitcoin_base:
139
git:
140
url: https://github.com/cake-tech/bitcoin_base
141
- ref: cake-update-v5
141
+ ref: cake-update-v7
142
143
flutter_icons:
144
image_path: "assets/images/app_logo.png"
res/values/strings_ar.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "تحرير الرمز المميز",
233
"electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل",
234
"email_address": "عنوان البريد الالكترونى",
235
+ "enable_mempool_api": "MEMPOOL API للحصول على رسوم وتواريخ دقيقة",
236
"enable_replace_by_fee": "تمكين الاستبدال",
236
- "enable_silent_payments_scanning": "تمكين المسح الضوئي للمدفوعات الصامتة",
237
+ "enable_silent_payments_scanning": "ابدأ في مسح المدفوعات الصامتة ، حتى يتم الوصول إلى الطرف",
238
"enabled": "ممكنة",
239
"enter_amount": "أدخل المبلغ",
240
"enter_backup_password": "أدخل كلمة المرور الاحتياطية هنا",
@@ -295,6 +296,7 @@
296
"failed_authentication": "${state_error} فشل المصادقة.",
297
"faq": "الأسئلة الشائعة",
298
"features": "سمات",
299
+ "fee_rate": "معدل الرسوم",
300
"fetching": "جار الجلب",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "الرصيد فيات",
@@ -610,6 +612,7 @@
612
"send": "إرسال",
613
"send_address": "عنوان ${cryptoCurrency}",
614
"send_amount": "مقدار:",
615
+ "send_change_to_you": "تغيير لك:",
616
"send_creating_transaction": " يتم إنشاء المعاملة",
617
"send_error_currency": "العملة يجب أن تحتوي على أرقام فقط",
618
"send_error_minimum_value": "الحد الأدنى لقيمة المبلغ هو 0.01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "التوقيع غير صالح للرسالة المقدمة",
680
"signTransaction": " ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ",
681
"signup_for_card_accept_terms": "قم بالتسجيل للحصول على البطاقة وقبول الشروط.",
682
+ "silent_payment": "الدفع الصامت",
683
"silent_payments": "مدفوعات صامتة",
684
"silent_payments_always_scan": "حدد المدفوعات الصامتة دائمًا المسح الضوئي",
685
"silent_payments_disclaimer": "العناوين الجديدة ليست هويات جديدة. إنها إعادة استخدام هوية موجودة مع ملصق مختلف.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ",
713
"symbol": "ﺰﻣﺭ",
714
"sync_all_wallets": "مزامنة جميع المحافظ",
715
+ "sync_status_attempting_scan": "محاولة المسح",
716
"sync_status_attempting_sync": "جاري محاولة المزامنة",
717
"sync_status_connected": "متصل",
718
"sync_status_connecting": "يتم التوصيل",
719
"sync_status_failed_connect": "انقطع الاتصال",
720
"sync_status_not_connected": "غير متصل",
716
- "sync_status_starting_scan": "بدء المسح",
721
+ "sync_status_starting_scan": "بدء المسح الضوئي (من ${height})",
722
"sync_status_starting_sync": "بدء المزامنة",
723
"sync_status_syncronized": "متزامن",
724
"sync_status_syncronizing": "يتم المزامنة",
res/values/strings_bg.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Редактиране на токена",
233
"electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят",
234
"email_address": "Имейл адрес",
235
+ "enable_mempool_api": "Mempool API за точни такси и дати",
236
"enable_replace_by_fee": "Активиране на замяна по забрана",
236
- "enable_silent_payments_scanning": "Активирайте безшумните плащания за сканиране",
237
+ "enable_silent_payments_scanning": "Започнете да сканирате безшумните плащания, докато се достигне съветът",
238
"enabled": "Активирано",
239
"enter_amount": "Въведете сума",
240
"enter_backup_password": "Въведете парола за възстановяване",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Неуспешно удостоверяване. ${state_error}",
297
"faq": "FAQ",
298
"features": "Характеристика",
299
+ "fee_rate": "Такса ставка",
300
"fetching": "Обработване",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Фиат Баланс",
@@ -610,6 +612,7 @@
612
"send": "Изпрати",
613
"send_address": "${cryptoCurrency} адрес",
614
"send_amount": "Сума:",
615
+ "send_change_to_you": "Променете, на вас:",
616
"send_creating_transaction": "Създаване на транзакция",
617
"send_error_currency": "Валутата може да съдържа само числа",
618
"send_error_minimum_value": "Минималната сума е 0.01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "Подписът не е валиден за даденото съобщение",
680
"signTransaction": "Подпишете транзакция",
681
"signup_for_card_accept_terms": "Регистрайте се за картата и приемете условията.",
682
+ "silent_payment": "Безшумно плащане",
683
"silent_payments": "Мълчаливи плащания",
684
"silent_payments_always_scan": "Задайте мълчаливи плащания винаги сканиране",
685
"silent_payments_disclaimer": "Новите адреси не са нови идентичности. Това е повторна употреба на съществуваща идентичност с различен етикет.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)",
713
"symbol": "Символ",
714
"sync_all_wallets": "Синхронизирайте всички портфейли",
715
+ "sync_status_attempting_scan": "Опит за сканиране",
716
"sync_status_attempting_sync": "ОПИТ ЗА СИНХРОНИЗАЦИЯ",
717
"sync_status_connected": "СВЪРЗВАНЕ",
718
"sync_status_connecting": "СВЪРЗВАНЕ",
719
"sync_status_failed_connect": "НЕУСПЕШНО СВЪРЗВАНЕ",
720
"sync_status_not_connected": "НЯМА ВРЪЗКА",
716
- "sync_status_starting_scan": "Стартово сканиране",
721
+ "sync_status_starting_scan": "Стартиране на сканиране (от ${height})",
722
"sync_status_starting_sync": "ЗАПОЧВАНЕ НА СИНХРОНИЗАЦИЯ",
723
"sync_status_syncronized": "СИНХРОНИЗИРАНО",
724
"sync_status_syncronizing": "СИНХРОНИЗИРАНЕ",
res/values/strings_cs.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Upravit token",
233
"electrum_address_disclaimer": "Po každém použití je generována nová adresa, ale předchozí adresy také stále fungují",
234
"email_address": "E-mailová adresa",
235
+ "enable_mempool_api": "Mempool API pro přesné poplatky a data",
236
"enable_replace_by_fee": "Povolit výměnu podle poplatku",
236
- "enable_silent_payments_scanning": "Povolte skenování tichých plateb",
237
+ "enable_silent_payments_scanning": "Začněte skenovat tiché platby, dokud není dosaženo špičky",
238
"enabled": "Povoleno",
239
"enter_amount": "Zadejte částku",
240
"enter_backup_password": "Zde zadejte své heslo pro zálohy",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Ověřování selhalo. ${state_error}",
297
"faq": "FAQ",
298
"features": "Funkce",
299
+ "fee_rate": "Sazba poplatků",
300
"fetching": "Načítá se",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Fiat Balance",
@@ -610,6 +612,7 @@
612
"send": "Poslat",
613
"send_address": "${cryptoCurrency} adresa",
614
"send_amount": "Částka:",
615
+ "send_change_to_you": "Změňte, vám:",
616
"send_creating_transaction": "Vytváření transakce",
617
"send_error_currency": "Měna může obsahovat pouze čísla",
618
"send_error_minimum_value": "Minimální částka je 0,01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "Podpis není platný pro danou zprávu",
680
"signTransaction": "Podepsat transakci",
681
"signup_for_card_accept_terms": "Zaregistrujte se pro kartu a souhlaste s podmínkami.",
682
+ "silent_payment": "Tichá platba",
683
"silent_payments": "Tiché platby",
684
"silent_payments_always_scan": "Nastavit tiché platby vždy skenování",
685
"silent_payments_disclaimer": "Nové adresy nejsou nové identity. Je to opětovné použití existující identity s jiným štítkem.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)",
713
"symbol": "Symbol",
714
"sync_all_wallets": "Synchronizovat všechny peněženky",
715
+ "sync_status_attempting_scan": "Pokus o skenování",
716
"sync_status_attempting_sync": "ZAHAJUJI SYNCHR.",
717
"sync_status_connected": "PŘIPOJENO",
718
"sync_status_connecting": "PŘIPOJOVÁNÍ",
719
"sync_status_failed_connect": "ODPOJENO",
720
"sync_status_not_connected": "NEPŘIPOJENO",
716
- "sync_status_starting_scan": "Počáteční skenování",
721
+ "sync_status_starting_scan": "Počáteční skenování (z ${height})",
722
"sync_status_starting_sync": "SPOUŠTĚNÍ SYNCHRONIZACE",
723
"sync_status_syncronized": "SYNCHRONIZOVÁNO",
724
"sync_status_syncronizing": "SYNCHRONIZUJI",
res/values/strings_de.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Token bearbeiten",
233
"electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin",
234
"email_address": "E-Mail-Adresse",
235
+ "enable_mempool_api": "Mempool -API für genaue Gebühren und Daten",
236
"enable_replace_by_fee": "Aktivieren Sie Ersatz für Fee",
236
- "enable_silent_payments_scanning": "Aktivieren Sie stille Zahlungen Scannen",
237
+ "enable_silent_payments_scanning": "Scannen Sie stille Zahlungen, bis die Spitze erreicht ist",
238
"enabled": "Ermöglicht",
239
"enter_amount": "Betrag eingeben",
240
"enter_backup_password": "Sicherungskennwort hier eingeben",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Authentifizierung fehlgeschlagen. ${state_error}",
297
"faq": "Häufig gestellte Fragen",
298
"features": "Merkmale",
299
+ "fee_rate": "Gebührenpreis",
300
"fetching": "Frage ab",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Fiat Balance",
@@ -611,6 +613,7 @@
613
"send": "Senden",
614
"send_address": "${cryptoCurrency}-Adresse",
615
"send_amount": "Betrag:",
616
+ "send_change_to_you": "Verändere dich zu dir:",
617
"send_creating_transaction": "Erstelle Transaktion",
618
"send_error_currency": "Die Währung darf nur Zahlen enthalten",
619
"send_error_minimum_value": "Der Mindestbetrag ist 0,01",
@@ -677,6 +680,7 @@
680
"signature_invalid_error": "Die Signatur gilt nicht für die angegebene Nachricht",
681
"signTransaction": "Transaktion unterzeichnen",
682
"signup_for_card_accept_terms": "Melden Sie sich für die Karte an und akzeptieren Sie die Bedingungen.",
683
+ "silent_payment": "Stille Zahlung",
684
"silent_payments": "Stille Zahlungen",
685
"silent_payments_always_scan": "Setzen Sie stille Zahlungen immer scannen",
686
"silent_payments_disclaimer": "Neue Adressen sind keine neuen Identitäten. Es ist eine Wiederverwendung einer bestehenden Identität mit einem anderen Etikett.",
@@ -709,12 +713,13 @@
713
"switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)",
714
"symbol": "Symbol",
715
"sync_all_wallets": "Alle Wallets synchronisieren",
716
+ "sync_status_attempting_scan": "Versuch Scan",
717
"sync_status_attempting_sync": "SYNC VERSUCHEN",
718
"sync_status_connected": "VERBUNDEN",
719
"sync_status_connecting": "VERBINDEN",
720
"sync_status_failed_connect": "GETRENNT",
721
"sync_status_not_connected": "NICHT VERBUNDEN",
717
- "sync_status_starting_scan": "Scan beginnen",
722
+ "sync_status_starting_scan": "SCAN starten (von ${height})",
723
"sync_status_starting_sync": "STARTE SYNCHRONISIERUNG",
724
"sync_status_syncronized": "SYNCHRONISIERT",
725
"sync_status_syncronizing": "SYNCHRONISIERE",
res/values/strings_en.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Edit token",
233
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work",
234
"email_address": "Email Address",
235
+ "enable_mempool_api": "Mempool API for accurate fees and dates",
236
"enable_replace_by_fee": "Enable Replace-By-Fee",
236
- "enable_silent_payments_scanning": "Enable silent payments scanning",
237
+ "enable_silent_payments_scanning": "Start scanning silent payments, until the tip is reached",
238
"enabled": "Enabled",
239
"enter_amount": "Enter Amount",
240
"enter_backup_password": "Enter backup password here",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Failed authentication. ${state_error}",
297
"faq": "FAQ",
298
"features": "Features",
299
+ "fee_rate": "Fee rate",
300
"fetching": "Fetching",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Fiat Balance",
@@ -611,6 +613,7 @@
613
"send": "Send",
614
"send_address": "${cryptoCurrency} address",
615
"send_amount": "Amount:",
616
+ "send_change_to_you": "Change, to you:",
617
"send_creating_transaction": "Creating transaction",
618
"send_error_currency": "Currency can only contain numbers",
619
"send_error_minimum_value": "Minimum value of amount is 0.01",
@@ -677,6 +680,7 @@
680
"signature_invalid_error": "The signature is not valid for the message given",
681
"signTransaction": "Sign Transaction",
682
"signup_for_card_accept_terms": "Sign up for the card and accept the terms.",
683
+ "silent_payment": "Silent Payment",
684
"silent_payments": "Silent Payments",
685
"silent_payments_always_scan": "Set Silent Payments always scanning",
686
"silent_payments_disclaimer": "New addresses are not new identities. It is a re-use of an existing identity with a different label.",
@@ -709,12 +713,13 @@
713
"switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)",
714
"symbol": "Symbol",
715
"sync_all_wallets": "Sync all wallets",
716
+ "sync_status_attempting_scan": "ATTEMPTING SCAN",
717
"sync_status_attempting_sync": "ATTEMPTING SYNC",
718
"sync_status_connected": "CONNECTED",
719
"sync_status_connecting": "CONNECTING",
720
"sync_status_failed_connect": "DISCONNECTED",
721
"sync_status_not_connected": "NOT CONNECTED",
717
- "sync_status_starting_scan": "STARTING SCAN",
722
+ "sync_status_starting_scan": "STARTING SCAN (from ${height})",
723
"sync_status_starting_sync": "STARTING SYNC",
724
"sync_status_syncronized": "SYNCHRONIZED",
725
"sync_status_syncronizing": "SYNCHRONIZING",
res/values/strings_es.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Editar token",
233
"electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando",
234
"email_address": "Dirección de correo electrónico",
235
+ "enable_mempool_api": "API de Mempool para tarifas y fechas precisas",
236
"enable_replace_by_fee": "Habilitar reemplazar por tarea",
236
- "enable_silent_payments_scanning": "Habilitar escaneo de pagos silenciosos",
237
+ "enable_silent_payments_scanning": "Comience a escanear pagos silenciosos, hasta que se alcance la punta",
238
"enabled": "Activado",
239
"enter_amount": "Ingrese la cantidad",
240
"enter_backup_password": "Ingrese la contraseña de respaldo aquí",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Autenticación fallida. ${state_error}",
297
"faq": "FAQ",
298
"features": "Características",
299
+ "fee_rate": "Tarifa",
300
"fetching": "Cargando",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Equilibrio Fiat",
@@ -611,6 +613,7 @@
613
"send": "Enviar",
614
"send_address": "Dirección de ${cryptoCurrency}",
615
"send_amount": "Cantidad:",
616
+ "send_change_to_you": "Cambiar, a ti:",
617
"send_creating_transaction": "Creando transacción",
618
"send_error_currency": "La moneda solo puede contener números",
619
"send_error_minimum_value": "El valor mínimo de la cantidad es 0.01",
@@ -677,6 +680,7 @@
680
"signature_invalid_error": "La firma no es válida para el mensaje dado",
681
"signTransaction": "Firmar transacción",
682
"signup_for_card_accept_terms": "Regístrese para obtener la tarjeta y acepte los términos.",
683
+ "silent_payment": "Pago silencioso",
684
"silent_payments": "Pagos silenciosos",
685
"silent_payments_always_scan": "Establecer pagos silenciosos siempre escaneando",
686
"silent_payments_disclaimer": "Las nuevas direcciones no son nuevas identidades. Es una reutilización de una identidad existente con una etiqueta diferente.",
@@ -709,12 +713,13 @@
713
"switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)",
714
"symbol": "Símbolo",
715
"sync_all_wallets": "Sincronizar todas las billeteras",
716
+ "sync_status_attempting_scan": "Intento de escaneo",
717
"sync_status_attempting_sync": "INTENTAR SINCRONIZAR",
718
"sync_status_connected": "CONECTADO",
719
"sync_status_connecting": "CONECTANDO",
720
"sync_status_failed_connect": "DESCONECTADO",
721
"sync_status_not_connected": "NO CONECTADO",
717
- "sync_status_starting_scan": "Escaneo inicial",
722
+ "sync_status_starting_scan": "Iniciar escaneo (de ${height})",
723
"sync_status_starting_sync": "EMPEZANDO A SINCRONIZAR",
724
"sync_status_syncronized": "SINCRONIZADO",
725
"sync_status_syncronizing": "SINCRONIZANDO",
res/values/strings_fr.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Modifier le token",
233
"electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner",
234
"email_address": "Adresse e-mail",
235
+ "enable_mempool_api": "API Mempool pour les frais et dates précis",
236
"enable_replace_by_fee": "Activer Remplace-by-Fee",
236
- "enable_silent_payments_scanning": "Activer la numérisation des paiements silencieux",
237
+ "enable_silent_payments_scanning": "Commencez à scanner les paiements silencieux, jusqu'à ce que la pointe soit atteinte",
238
"enabled": "Activé",
239
"enter_amount": "Entrez le montant",
240
"enter_backup_password": "Entrez le mot de passe de sauvegarde ici",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Échec d'authentification. ${state_error}",
297
"faq": "FAQ",
298
"features": "Caractéristiques",
299
+ "fee_rate": "Taux de frais",
300
"fetching": "Récupération",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Solde fiat",
@@ -610,6 +612,7 @@
612
"send": "Envoyer",
613
"send_address": "adresse ${cryptoCurrency}",
614
"send_amount": "Montant :",
615
+ "send_change_to_you": "Changer, pour vous:",
616
"send_creating_transaction": "Création de la transaction",
617
"send_error_currency": "La monnaie ne peut contenir que des nombres",
618
"send_error_minimum_value": "La valeur minimale du montant est 0.01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "La signature n'est pas valable pour le message donné",
680
"signTransaction": "Signer une transaction",
681
"signup_for_card_accept_terms": "Inscrivez-vous pour la carte et acceptez les conditions.",
682
+ "silent_payment": "Paiement silencieux",
683
"silent_payments": "Paiements silencieux",
684
"silent_payments_always_scan": "Définir les paiements silencieux toujours à la scanne",
685
"silent_payments_disclaimer": "Les nouvelles adresses ne sont pas de nouvelles identités. Il s'agit d'une réutilisation d'une identité existante avec une étiquette différente.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)",
713
"symbol": "Symbole",
714
"sync_all_wallets": "Synchroniser tous les portefeuilles",
715
+ "sync_status_attempting_scan": "Tentative de numérisation",
716
"sync_status_attempting_sync": "TENTATIVE DE SYNCHRONISATION",
717
"sync_status_connected": "CONNECTÉ",
718
"sync_status_connecting": "CONNEXION EN COURS",
719
"sync_status_failed_connect": "DÉCONNECTÉ",
720
"sync_status_not_connected": "NON CONNECTÉ",
716
- "sync_status_starting_scan": "Démarrage",
721
+ "sync_status_starting_scan": "Démarrer la numérisation (à partir de ${height})",
722
"sync_status_starting_sync": "DÉBUT DE SYNCHRO",
723
"sync_status_syncronized": "SYNCHRONISÉ",
724
"sync_status_syncronizing": "SYNCHRONISATION EN COURS",
res/values/strings_ha.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Gyara alamar",
233
"electrum_address_disclaimer": "Muna samar da sababbin adireshi duk lokacin da kuka yi amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki",
234
"email_address": "Adireshin i-mel",
235
+ "enable_mempool_api": "Mampool API don ingantattun kudade da kwanakin",
236
"enable_replace_by_fee": "Ba da damar maye gurbin-by-kudin",
236
- "enable_silent_payments_scanning": "Kunna biya biya",
237
+ "enable_silent_payments_scanning": "Fara bincika biya na shiru, har sai tip ɗin ya kai",
238
"enabled": "An kunna",
239
"enter_amount": "Shigar da Adadi",
240
"enter_backup_password": "Shigar da kalmar wucewa ta madadin nan",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Binne wajen shiga. ${state_error}",
297
"faq": "FAQ",
298
"features": "Fasas",
299
+ "fee_rate": "Kudi",
300
"fetching": "Daukewa",
301
"fiat_api": "API ɗin Fiat",
302
"fiat_balance": "Fiat Balance",
@@ -612,6 +614,7 @@
614
"send": "Aika",
615
"send_address": "${cryptoCurrency} address",
616
"send_amount": "Adadi:",
617
+ "send_change_to_you": "Canza, a gare ku:",
618
"send_creating_transaction": "Ƙirƙirar ciniki",
619
"send_error_currency": "Kudi zai iya ƙunsar lambobi kawai",
620
"send_error_minimum_value": "Mafi ƙarancin ƙimar adadin shine 0.01",
@@ -678,6 +681,7 @@
681
"signature_invalid_error": "Sa hannu ba shi da inganci ga sakon da aka bayar",
682
"signTransaction": "Sa hannu Ma'amala",
683
"signup_for_card_accept_terms": "Yi rajista don katin kuma karɓi sharuɗɗan.",
684
+ "silent_payment": "Biya silent",
685
"silent_payments": "Biya silent",
686
"silent_payments_always_scan": "Saita biya na shiru koyaushe",
687
"silent_payments_disclaimer": "Sabbin adiresoshin ba sabon tsari bane. Wannan shine sake amfani da asalin asalin tare da wata alama daban.",
@@ -710,12 +714,13 @@
714
"switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)",
715
"symbol": "Alama",
716
"sync_all_wallets": "Sync Duk Wallet",
717
+ "sync_status_attempting_scan": "Yunƙurin scan",
718
"sync_status_attempting_sync": "KWAFI",
719
"sync_status_connected": "HANNU",
720
"sync_status_connecting": "HADA",
721
"sync_status_failed_connect": "BABU INTERNET",
722
"sync_status_not_connected": "BABU INTERNET",
718
- "sync_status_starting_scan": "Fara scan",
723
+ "sync_status_starting_scan": "Farawa Scan (daga ${height})",
724
"sync_status_starting_sync": "KWAFI",
725
"sync_status_syncronized": "KYAU",
726
"sync_status_syncronizing": "KWAFI",
res/values/strings_hi.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "टोकन संपादित करें",
233
"electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं",
234
"email_address": "ईमेल पता",
235
+ "enable_mempool_api": "सटीक शुल्क और तिथियों के लिए मेमपूल एपीआई",
236
"enable_replace_by_fee": "प्रतिस्थापित-दर-शुल्क सक्षम करें",
236
- "enable_silent_payments_scanning": "मूक भुगतान स्कैनिंग सक्षम करें",
237
+ "enable_silent_payments_scanning": "साइलेंट पेमेंट्स को स्कैन करना शुरू करें, जब तक कि टिप तक पहुंच न जाए",
238
"enabled": "सक्रिय",
239
"enter_amount": "राशि दर्ज करें",
240
"enter_backup_password": "यहां बैकअप पासवर्ड डालें",
@@ -295,6 +296,7 @@
296
"failed_authentication": "प्रमाणीकरण विफल. ${state_error}",
297
"faq": "FAQ",
298
"features": "विशेषताएँ",
299
+ "fee_rate": "शुल्क दर",
300
"fetching": "ला रहा है",
301
"fiat_api": "फिएट पैसे API",
302
"fiat_balance": "फिएट बैलेंस",
@@ -612,6 +614,7 @@
614
"send": "संदेश",
615
"send_address": "${cryptoCurrency} पता",
616
"send_amount": "रकम:",
617
+ "send_change_to_you": "बदलो, आप को:",
618
"send_creating_transaction": "लेन-देन बनाना",
619
"send_error_currency": "मुद्रा में केवल संख्याएँ हो सकती हैं",
620
"send_error_minimum_value": "राशि का न्यूनतम मूल्य 0.01 है",
@@ -678,6 +681,7 @@
681
"signature_invalid_error": "हस्ताक्षर दिए गए संदेश के लिए मान्य नहीं है",
682
"signTransaction": "लेन-देन पर हस्ताक्षर करें",
683
"signup_for_card_accept_terms": "कार्ड के लिए साइन अप करें और शर्तें स्वीकार करें।",
684
+ "silent_payment": "मूक भुगतान",
685
"silent_payments": "मूक भुगतान",
686
"silent_payments_always_scan": "मूक भुगतान हमेशा स्कैनिंग सेट करें",
687
"silent_payments_disclaimer": "नए पते नई पहचान नहीं हैं। यह एक अलग लेबल के साथ एक मौजूदा पहचान का पुन: उपयोग है।",
@@ -710,12 +714,13 @@
714
"switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)",
715
"symbol": "प्रतीक",
716
"sync_all_wallets": "सभी वॉलेट सिंक करें",
717
+ "sync_status_attempting_scan": "स्कैन का प्रयास",
718
"sync_status_attempting_sync": "सिंक करने का प्रयास",
719
"sync_status_connected": "जुड़े हुए",
720
"sync_status_connecting": "कनेक्ट",
721
"sync_status_failed_connect": "डिस्कनेक्ट किया गया",
722
"sync_status_not_connected": "जुड़े नहीं हैं",
718
- "sync_status_starting_scan": "स्कैन शुरू करना",
723
+ "sync_status_starting_scan": "स्कैन शुरू करना (${height} से)",
724
"sync_status_starting_sync": "सिताज़ा करना",
725
"sync_status_syncronized": "सिंक्रनाइज़",
726
"sync_status_syncronizing": "सिंक्रनाइज़ करने",
res/values/strings_hr.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Uredi token",
233
"electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek",
234
"email_address": "Adresa e-pošte",
235
+ "enable_mempool_api": "Mempool API za točne naknade i datume",
236
"enable_replace_by_fee": "Omogući zamjenu",
236
- "enable_silent_payments_scanning": "Omogući skeniranje tihih plaćanja",
237
+ "enable_silent_payments_scanning": "Započnite skeniranje tihih plaćanja, dok se ne postigne savjet",
238
"enabled": "Omogućeno",
239
"enter_amount": "Unesite iznos",
240
"enter_backup_password": "Unesite svoju lozinku za sigurnosnu kopiju ovdje",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Autentifikacija neuspješna. ${state_error}",
297
"faq": "FAQ",
298
"features": "Značajke",
299
+ "fee_rate": "Stopa naknade",
300
"fetching": "Dohvaćanje",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Fiat Bilans",
@@ -610,6 +612,7 @@
612
"send": "Pošalji",
613
"send_address": "${cryptoCurrency} adresa",
614
"send_amount": "Iznos:",
615
+ "send_change_to_you": "Promijenite, u vas:",
616
"send_creating_transaction": "Izrada transakcije",
617
"send_error_currency": "Iznos smije sadržavati samo brojeve",
618
"send_error_minimum_value": "Minimalna vrijednost iznosa je 0.01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "Potpis ne vrijedi za danu poruku",
680
"signTransaction": "Potpišite transakciju",
681
"signup_for_card_accept_terms": "Prijavite se za karticu i prihvatite uvjete.",
682
+ "silent_payment": "Tiho plaćanje",
683
"silent_payments": "Tiha plaćanja",
684
"silent_payments_always_scan": "Postavite tiho plaćanje uvijek skeniranje",
685
"silent_payments_disclaimer": "Nove adrese nisu novi identiteti. To je ponovna upotreba postojećeg identiteta s drugom oznakom.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)",
713
"symbol": "Simbol",
714
"sync_all_wallets": "Sinkronizirajte sve novčanike",
715
+ "sync_status_attempting_scan": "Pokušaj skeniranja",
716
"sync_status_attempting_sync": "POKUŠAJ SINKRONIZACIJE",
717
"sync_status_connected": "SPOJENO",
718
"sync_status_connecting": "SPAJANJE",
719
"sync_status_failed_connect": "ISKLJUČENO",
720
"sync_status_not_connected": "NIJE POVEZANO",
716
- "sync_status_starting_scan": "Početno skeniranje",
721
+ "sync_status_starting_scan": "Početno skeniranje (od ${height})",
722
"sync_status_starting_sync": "ZAPOČINJEMO SINKRONIZIRANJE",
723
"sync_status_syncronized": "SINKRONIZIRANO",
724
"sync_status_syncronizing": "SINKRONIZIRANJE",
res/values/strings_hy.arb
+7
-2
@@ -231,8 +231,9 @@
231
"edit_token": "Փոփոխել տոկեն",
232
"electrum_address_disclaimer": "Մենք ստեղծում ենք նոր հասցե ամեն անգամ, երբ դուք օգտագործում եք այն, բայց նախորդ հասցեները շարունակում են աշխատել",
233
"email_address": "Էլ. փոստի հասցե",
234
+ "enable_mempool_api": "Mempool API ճշգրիտ վճարների եւ ամսաթվերի համար",
235
"enable_replace_by_fee": "Միացնել փոխարինումը միջնորդավճարով",
235
- "enable_silent_payments_scanning": "Միացնել Լուռ Վճարումների սկանավորումը",
236
+ "enable_silent_payments_scanning": "Սկսեք սկանավորել լուռ վճարումները, մինչեւ որ ծայրը հասնի",
237
"enabled": "Միացված",
238
"enter_amount": "Մուտքագրեք գումար",
239
"enter_backup_password": "Մուտքագրեք կրկնօրինակի գաղտնաբառը",
@@ -294,6 +295,7 @@
295
"failed_authentication": "Վավերացումը ձախողվեց. ${state_error}",
296
"faq": "Հաճախ տրվող հարցեր",
297
"features": "Հատկանիշներ",
298
+ "fee_rate": "Վճարման տոկոսադրույքը",
299
"fetching": "Ստացվում է",
300
"fiat_api": "Fiat API",
301
"fiat_balance": "Fiat մնացորդ",
@@ -610,6 +612,7 @@
612
"send": "Ուղարկել",
613
"send_address": "${cryptoCurrency} հասցե",
614
"send_amount": "Քանակ՝",
615
+ "send_change_to_you": "Փոփոխություն, ձեզ համար.",
616
"send_creating_transaction": "Ստեղծել գործարք",
617
"send_error_currency": "Արժույթը կարող է պարունակել միայն թվեր",
618
"send_error_minimum_value": "Քանակի նվազագույն արժեքը 0.01 է",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "Կնիքը անվավեր է տրված հաղորդագրության համար",
680
"signTransaction": "Կնքել Գործարք",
681
"signup_for_card_accept_terms": "Գրանցվել քարտի համար և ընդունել պայմանները",
682
+ "silent_payment": "Լուռ վճարում",
683
"silent_payments": "Լուռ Վճարումներ",
684
"silent_payments_always_scan": "Միացնել Լուռ Վճարումներ մշտական սկանավորումը",
685
"silent_payments_disclaimer": "Նոր հասցեները նոր ինքնություն չեն։ Դա այլ պիտակով գոյություն ունեցող ինքնության վերագործածում է",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Խնդրում ենք անցնել EVM համատեղելի դրամապանակ և փորձել կրկին (Ethereum, Polygon)",
713
"symbol": "Նշան",
714
"sync_all_wallets": "Համաժամեցնել բոլոր դրամապանակները",
715
+ "sync_status_attempting_scan": "Փորձի սկան",
716
"sync_status_attempting_sync": "ՀԱՄԱԺԱՄԵՑՄԱՆ ՓՈՐՁ",
717
"sync_status_connected": "ՄԻԱՑՎԱԾԷ",
718
"sync_status_connecting": "ՄԻԱՑՎՈՒՄ Է",
719
"sync_status_failed_connect": "ՉՄԻԱՑԱՎ",
720
"sync_status_not_connected": "ՄԻԱՑՎԱԾ ՉԷ",
716
- "sync_status_starting_scan": "ՍԿԱՆԱՎՈՐՈՒՄԸ ՍԿՍՎՈՒՄ Է",
721
+ "sync_status_starting_scan": "Սկսած սկան (${height})",
722
"sync_status_starting_sync": "ՀԱՄԱԺԱՄԵՑՈՒՄԸ ՍԿՍՎՈՒՄ Է",
723
"sync_status_syncronized": "ՀԱՄԱԺԱՄԵՑՎԱԾԷ",
724
"sync_status_syncronizing": "ՀԱՄԱԺԱՄԵՑՎՈՒՄ Է",
res/values/strings_id.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Mengedit token",
233
"electrum_address_disclaimer": "Kami menghasilkan alamat baru setiap kali Anda menggunakan satu, tetapi alamat sebelumnya tetap berfungsi",
234
"email_address": "Alamat Email",
235
+ "enable_mempool_api": "API Mempool untuk biaya dan tanggal yang akurat",
236
"enable_replace_by_fee": "Aktifkan ganti-by-fee",
236
- "enable_silent_payments_scanning": "Aktifkan pemindaian pembayaran diam",
237
+ "enable_silent_payments_scanning": "Mulailah memindai pembayaran diam, sampai ujung tercapai",
238
"enabled": "Diaktifkan",
239
"enter_amount": "Masukkan Jumlah",
240
"enter_backup_password": "Masukkan kata sandi cadangan di sini",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Otentikasi gagal. ${state_error}",
297
"faq": "Pertanyaan yang Sering Diajukan",
298
"features": "Fitur",
299
+ "fee_rate": "Tarif biaya",
300
"fetching": "Mengambil",
301
"fiat_api": "API fiat",
302
"fiat_balance": "Saldo Fiat",
@@ -613,6 +615,7 @@
615
"send": "Mengirim",
616
"send_address": "Alamat ${cryptoCurrency}",
617
"send_amount": "Jumlah:",
618
+ "send_change_to_you": "Ubah, untukmu:",
619
"send_creating_transaction": "Membuat transaksi",
620
"send_error_currency": "Mata uang hanya dapat berisi angka",
621
"send_error_minimum_value": "Nilai minimum jumlah adalah 0.01",
@@ -679,6 +682,7 @@
682
"signature_invalid_error": "Tanda tangan tidak valid untuk pesan yang diberikan",
683
"signTransaction": "Tandatangani Transaksi",
684
"signup_for_card_accept_terms": "Daftar untuk kartu dan terima syarat dan ketentuan.",
685
+ "silent_payment": "Pembayaran diam",
686
"silent_payments": "Pembayaran diam",
687
"silent_payments_always_scan": "Tetapkan pembayaran diam selalu pemindaian",
688
"silent_payments_disclaimer": "Alamat baru bukanlah identitas baru. Ini adalah penggunaan kembali identitas yang ada dengan label yang berbeda.",
@@ -711,12 +715,13 @@
715
"switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)",
716
"symbol": "Simbol",
717
"sync_all_wallets": "Sinkronkan semua dompet",
718
+ "sync_status_attempting_scan": "Mencoba memindai",
719
"sync_status_attempting_sync": "MENCOBA SINKRONISASI",
720
"sync_status_connected": "TERHUBUNG",
721
"sync_status_connecting": "MENGHUBUNGKAN",
722
"sync_status_failed_connect": "GAGAL TERHUBUNG",
723
"sync_status_not_connected": "TIDAK TERHUBUNG",
719
- "sync_status_starting_scan": "Mulai pindai",
724
+ "sync_status_starting_scan": "Mulai pemindaian (dari ${height})",
725
"sync_status_starting_sync": "MULAI SINKRONISASI",
726
"sync_status_syncronized": "SUDAH TERSINKRONISASI",
727
"sync_status_syncronizing": "SEDANG SINKRONISASI",
res/values/strings_it.arb
+7
-2
@@ -233,8 +233,9 @@
233
"edit_token": "Modifica token",
234
"electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare",
235
"email_address": "Indirizzo e-mail",
236
+ "enable_mempool_api": "API di Mempool per commissioni e date accurate",
237
"enable_replace_by_fee": "Abilita sostituzione per fee",
237
- "enable_silent_payments_scanning": "Abilita la scansione dei pagamenti silenziosi",
238
+ "enable_silent_payments_scanning": "Inizia a scansionare i pagamenti silenziosi, fino a raggiungere la punta",
239
"enabled": "Abilitato",
240
"enter_amount": "Inserisci importo",
241
"enter_backup_password": "Inserisci la password di backup qui",
@@ -296,6 +297,7 @@
297
"failed_authentication": "Autenticazione fallita. ${state_error}",
298
"faq": "Domande Frequenti",
299
"features": "Caratteristiche",
300
+ "fee_rate": "Tasso di commissione",
301
"fetching": "Recupero",
302
"fiat_api": "Fiat API",
303
"fiat_balance": "Equilibrio fiat",
@@ -612,6 +614,7 @@
614
"send": "Invia",
615
"send_address": "${cryptoCurrency} indirizzo",
616
"send_amount": "Ammontare:",
617
+ "send_change_to_you": "Cambiamento, a te:",
618
"send_creating_transaction": "Creazione della transazione",
619
"send_error_currency": "L'ammontare può contenere solo numeri",
620
"send_error_minimum_value": "L'ammontare minimo è 0.01",
@@ -678,6 +681,7 @@
681
"signature_invalid_error": "La firma non è valida per il messaggio dato",
682
"signTransaction": "Firma la transazione",
683
"signup_for_card_accept_terms": "Registrati per la carta e accetta i termini.",
684
+ "silent_payment": "Pagamento silenzioso",
685
"silent_payments": "Pagamenti silenziosi",
686
"silent_payments_always_scan": "Impostare i pagamenti silenziosi che scansionano sempre",
687
"silent_payments_disclaimer": "I nuovi indirizzi non sono nuove identità. È un riutilizzo di un'identità esistente con un'etichetta diversa.",
@@ -710,12 +714,13 @@
714
"switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)",
715
"symbol": "Simbolo",
716
"sync_all_wallets": "Sincronizza tutti i portafogli",
717
+ "sync_status_attempting_scan": "Tentando la scansione",
718
"sync_status_attempting_sync": "TENTATIVO DI SINCRONIZZAZIONE",
719
"sync_status_connected": "CONNESSO",
720
"sync_status_connecting": "CONNESSIONE",
721
"sync_status_failed_connect": "DISCONNESSO",
722
"sync_status_not_connected": "NON CONNESSO",
718
- "sync_status_starting_scan": "Scansione di partenza",
723
+ "sync_status_starting_scan": "Avvia scansione (da ${height})",
724
"sync_status_starting_sync": "INIZIO SINC",
725
"sync_status_syncronized": "SINCRONIZZATO",
726
"sync_status_syncronizing": "SINCRONIZZAZIONE",
res/values/strings_ja.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "トークンの編集",
233
"electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します",
234
"email_address": "メールアドレス",
235
+ "enable_mempool_api": "正確な料金と日付のMempool API",
236
"enable_replace_by_fee": "交換ごとに有効にします",
236
- "enable_silent_payments_scanning": "サイレントペイメントスキャンを有効にします",
237
+ "enable_silent_payments_scanning": "先端に達するまで、サイレント決済のスキャンを開始します",
238
"enabled": "有効",
239
"enter_amount": "金額を入力",
240
"enter_backup_password": "ここにバックアップパスワードを入力してください",
@@ -295,6 +296,7 @@
296
"failed_authentication": "認証失敗. ${state_error}",
297
"faq": "FAQ",
298
"features": "特徴",
299
+ "fee_rate": "料金金利",
300
"fetching": "フェッチング",
301
"fiat_api": "不換紙幣 API",
302
"fiat_balance": "フィアットバランス",
@@ -611,6 +613,7 @@
613
"send": "送る",
614
"send_address": "${cryptoCurrency} 住所",
615
"send_amount": "量:",
616
+ "send_change_to_you": "あなたに変更:",
617
"send_creating_transaction": "トランザクションを作成する",
618
"send_error_currency": "通貨には数字のみを含めることができます",
619
"send_error_minimum_value": "金額の最小値は0.01です",
@@ -677,6 +680,7 @@
680
"signature_invalid_error": "署名は、指定されたメッセージに対して無効です",
681
"signTransaction": "トランザクションに署名する",
682
"signup_for_card_accept_terms": "カードにサインアップして、利用規約に同意してください。",
683
+ "silent_payment": "サイレント支払い",
684
"silent_payments": "サイレント支払い",
685
"silent_payments_always_scan": "サイレント決済を常にスキャンします",
686
"silent_payments_disclaimer": "新しいアドレスは新しいアイデンティティではありません。これは、異なるラベルを持つ既存のアイデンティティの再利用です。",
@@ -709,12 +713,13 @@
713
"switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)",
714
"symbol": "シンボル",
715
"sync_all_wallets": "すべてのウォレットを同期",
716
+ "sync_status_attempting_scan": "スキャンの試み",
717
"sync_status_attempting_sync": "同期を試みています",
718
"sync_status_connected": "接続済み",
719
"sync_status_connecting": "接続中",
720
"sync_status_failed_connect": "切断されました",
721
"sync_status_not_connected": "接続されていません",
717
- "sync_status_starting_scan": "スキャンを開始します",
722
+ "sync_status_starting_scan": "スキャンを開始する(${height} から)",
723
"sync_status_starting_sync": "同期の開始",
724
"sync_status_syncronized": "同期された",
725
"sync_status_syncronizing": "同期",
res/values/strings_ko.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "토큰 편집",
233
"electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.",
234
"email_address": "이메일 주소",
235
+ "enable_mempool_api": "정확한 수수료 및 날짜에 대한 Mempool API",
236
"enable_replace_by_fee": "대체별로 활성화하십시오",
236
- "enable_silent_payments_scanning": "무음 지불 스캔을 활성화합니다",
237
+ "enable_silent_payments_scanning": "팁에 도달 할 때까지 사일런트 지불을 스캔하기 시작합니다.",
238
"enabled": "사용",
239
"enter_amount": "금액 입력",
240
"enter_backup_password": "여기에 백업 비밀번호를 입력하세요.",
@@ -295,6 +296,7 @@
296
"failed_authentication": "인증 실패. ${state_error}",
297
"faq": "FAQ",
298
"features": "특징",
299
+ "fee_rate": "수수료",
300
"fetching": "가져 오는 중",
301
"fiat_api": "명목 화폐 API",
302
"fiat_balance": "피아트 잔액",
@@ -611,6 +613,7 @@
613
"send": "보내다",
614
"send_address": "${cryptoCurrency} 주소",
615
"send_amount": "양:",
616
+ "send_change_to_you": "당신에게 변경 :",
617
"send_creating_transaction": "거래 생성",
618
"send_error_currency": "통화는 숫자 만 포함 할 수 있습니다",
619
"send_error_minimum_value": "금액의 최소값은 0.01입니다",
@@ -677,6 +680,7 @@
680
"signature_invalid_error": "서명은 주어진 메시지에 유효하지 않습니다",
681
"signTransaction": "거래 서명",
682
"signup_for_card_accept_terms": "카드에 가입하고 약관에 동의합니다.",
683
+ "silent_payment": "조용한 지불",
684
"silent_payments": "조용한 지불",
685
"silent_payments_always_scan": "무음금을 항상 스캔합니다",
686
"silent_payments_disclaimer": "새로운 주소는 새로운 정체성이 아닙니다. 다른 레이블로 기존 신원을 재사용하는 것입니다.",
@@ -709,12 +713,13 @@
713
"switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)",
714
"symbol": "상징",
715
"sync_all_wallets": "모든 지갑 동기화",
716
+ "sync_status_attempting_scan": "스캔 시도",
717
"sync_status_attempting_sync": "동기화 시도 중",
718
"sync_status_connected": "연결됨",
719
"sync_status_connecting": "연결 중",
720
"sync_status_failed_connect": "연결 해제",
721
"sync_status_not_connected": "연결되지 않은",
717
- "sync_status_starting_scan": "스캔 시작",
722
+ "sync_status_starting_scan": "시작 스캔 (${height} 에서)",
723
"sync_status_starting_sync": "동기화 시작",
724
"sync_status_syncronized": "동기화",
725
"sync_status_syncronizing": "동기화",
res/values/strings_my.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "တိုကင်ကို တည်းဖြတ်ပါ။",
233
"electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။",
234
"email_address": "အီးမေးလ်လိပ်စာ",
235
+ "enable_mempool_api": "Mempool API တိကျသောအခကြေးငွေနှင့်ရက်စွဲများအတွက်",
236
"enable_replace_by_fee": "အစားထိုး - by- အခကြေးငွေ enable",
236
- "enable_silent_payments_scanning": "အသံတိတ်ငွေပေးချေမှုကို scanable လုပ်ပါ",
237
+ "enable_silent_payments_scanning": "အစွန်အဖျားသို့ရောက်ရှိသည်အထိအသံတိတ်ငွေပေးချေမှုကိုစကင်ဖတ်စစ်ဆေးပါ",
238
"enabled": "ဖွင့်ထားသည်။",
239
"enter_amount": "ပမာဏကို ထည့်ပါ။",
240
"enter_backup_password": "အရန်စကားဝှက်ကို ဤနေရာတွင် ထည့်ပါ။",
@@ -295,6 +296,7 @@
296
"failed_authentication": "အထောက်အထားစိစစ်ခြင်း မအောင်မြင်ပါ။. ${state_error}",
297
"faq": "အမြဲမေးလေ့ရှိသောမေးခွန်းများ",
298
"features": "အင်္ဂါရပ်များ",
299
+ "fee_rate": "ကြေးနှုန်း",
300
"fetching": "ခေါ်ယူခြင်း။",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Fiat Balance",
@@ -610,6 +612,7 @@
612
"send": "ပို့ပါ။",
613
"send_address": "${cryptoCurrency} လိပ်စာ",
614
"send_amount": "ပမာဏ-",
615
+ "send_change_to_you": "ပြောင်းလဲမှု,",
616
"send_creating_transaction": "အရောင်းအဝယ်ပြုလုပ်ခြင်း။",
617
"send_error_currency": "ငွေကြေးတွင် နံပါတ်များသာ ပါဝင်နိုင်သည်။",
618
"send_error_minimum_value": "ပမာဏ၏ အနည်းဆုံးတန်ဖိုးမှာ 0.01 ဖြစ်သည်။",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "အဆိုပါလက်မှတ်ပေးထားသောမက်ဆေ့ခ်ျကိုများအတွက်မမှန်ကန်ပါ",
680
"signTransaction": "ငွေလွှဲဝင်ပါ။",
681
"signup_for_card_accept_terms": "ကတ်အတွက် စာရင်းသွင်းပြီး စည်းကမ်းချက်များကို လက်ခံပါ။",
682
+ "silent_payment": "အသံတိတ်ငွေပေးချေမှု",
683
"silent_payments": "အသံတိတ်ငွေပေးချေမှု",
684
"silent_payments_always_scan": "အမြဲတမ်း scanning အမြဲ scanning",
685
"silent_payments_disclaimer": "လိပ်စာအသစ်များသည်အထောက်အထားအသစ်များမဟုတ်ပါ။ ၎င်းသည်ကွဲပြားခြားနားသောတံဆိပ်ဖြင့်ရှိပြီးသားဝိသေသလက်ခဏာကိုပြန်လည်အသုံးပြုခြင်းဖြစ်သည်။",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)",
713
"symbol": "သင်္ကေတ",
714
"sync_all_wallets": "အားလုံးပိုက်ဆံအိတ်စည်းညှိ",
715
+ "sync_status_attempting_scan": "scan ကြိုးစားနေ",
716
"sync_status_attempting_sync": "ချိန်ကိုက်ခြင်းကို ကြိုးစားနေသည်။",
717
"sync_status_connected": "ချိတ်ဆက်ထားသည်။",
718
"sync_status_connecting": "ချိတ်ဆက်ခြင်း။",
719
"sync_status_failed_connect": "အဆက်အသွယ်ဖြတ်ထားသည်။",
720
"sync_status_not_connected": "မချိတ်ဆက်ပါ။",
716
- "sync_status_starting_scan": "စကင်ဖတ်စစ်ဆေးမှု",
721
+ "sync_status_starting_scan": "စကင်ဖတ်စစ်ဆေးမှုစတင်ခြင်း (${height})",
722
"sync_status_starting_sync": "စင့်ခ်လုပ်ခြင်း။",
723
"sync_status_syncronized": "ထပ်တူပြုထားသည်။",
724
"sync_status_syncronizing": "ထပ်တူပြုခြင်း။",
res/values/strings_nl.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Token bewerken",
233
"electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken",
234
"email_address": "E-mailadres",
235
+ "enable_mempool_api": "Mempool API voor nauwkeurige kosten en datums",
236
"enable_replace_by_fee": "Schakel vervangen door een fee",
236
- "enable_silent_payments_scanning": "Schakel stille betalingen in scannen in",
237
+ "enable_silent_payments_scanning": "Begin met het scannen van stille betalingen, totdat de tip is bereikt",
238
"enabled": "Ingeschakeld",
239
"enter_amount": "Voer Bedrag in",
240
"enter_backup_password": "Voer hier een back-upwachtwoord in",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Mislukte authenticatie. ${state_error}",
297
"faq": "FAQ",
298
"features": "Functies",
299
+ "fee_rate": "Tarief",
300
"fetching": "Ophalen",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Fiat Balans",
@@ -610,6 +612,7 @@
612
"send": "Sturen",
613
"send_address": "${cryptoCurrency}-adres",
614
"send_amount": "Bedrag:",
615
+ "send_change_to_you": "Verander, aan jou:",
616
"send_creating_transaction": "Transactie maken",
617
"send_error_currency": "Valuta kan alleen cijfers bevatten",
618
"send_error_minimum_value": "Minimale waarde van bedrag is 0,01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "De handtekening is niet geldig voor het gegeven bericht",
680
"signTransaction": "Transactie ondertekenen",
681
"signup_for_card_accept_terms": "Meld je aan voor de kaart en accepteer de voorwaarden.",
682
+ "silent_payment": "Stille betaling",
683
"silent_payments": "Stille betalingen",
684
"silent_payments_always_scan": "Stel stille betalingen in het scannen",
685
"silent_payments_disclaimer": "Nieuwe adressen zijn geen nieuwe identiteiten. Het is een hergebruik van een bestaande identiteit met een ander label.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)",
713
"symbol": "Symbool",
714
"sync_all_wallets": "Alle portemonnees synchroniseren",
715
+ "sync_status_attempting_scan": "Proberen scan",
716
"sync_status_attempting_sync": "SYNCHRONISATIE PROBEREN",
717
"sync_status_connected": "VERBONDEN",
718
"sync_status_connecting": "AANSLUITING",
719
"sync_status_failed_connect": "LOSGEKOPPELD",
720
"sync_status_not_connected": "NIET VERBONDEN",
716
- "sync_status_starting_scan": "Startscan",
721
+ "sync_status_starting_scan": "SCAN starten (van ${height})",
722
"sync_status_starting_sync": "BEGINNEN MET SYNCHRONISEREN",
723
"sync_status_syncronized": "SYNCHRONIZED",
724
"sync_status_syncronizing": "SYNCHRONISEREN",
res/values/strings_pl.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Edytuj token",
233
"electrum_address_disclaimer": "Za każdym razem, gdy wykorzystasz adres, dla wiekszej prywatności generujemy nowy, ale poprzednie adresy nadal działają, i moga odbierać środki",
234
"email_address": "Adres e-mail",
235
+ "enable_mempool_api": "Mempool API dla dokładnych opłat i dat",
236
"enable_replace_by_fee": "Włącz wymianę po lewej",
236
- "enable_silent_payments_scanning": "Włącz skanowanie cichych płatności",
237
+ "enable_silent_payments_scanning": "Zacznij skanować ciche płatności, aż do osiągnięcia wskazówki",
238
"enabled": "Włączone",
239
"enter_amount": "Wprowadź kwotę",
240
"enter_backup_password": "Wprowadź tutaj hasło kopii zapasowej",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Nieudane uwierzytelnienie. ${state_error}",
297
"faq": "FAQ",
298
"features": "Cechy",
299
+ "fee_rate": "Stawka opłaty",
300
"fetching": "Pobieranie",
301
"fiat_api": "API Walut FIAT",
302
"fiat_balance": "Bilans Fiata",
@@ -610,6 +612,7 @@
612
"send": "Wyślij",
613
"send_address": "Adres ${cryptoCurrency}",
614
"send_amount": "Ilość:",
615
+ "send_change_to_you": "Zmień do ciebie:",
616
"send_creating_transaction": "Tworzenie transakcji",
617
"send_error_currency": "Waluta może zawierać tylko cyfry",
618
"send_error_minimum_value": "Minimalna wartość to 0,01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "Podpis nie jest ważny dla podanej wiadomości",
680
"signTransaction": "Podpisz transakcję",
681
"signup_for_card_accept_terms": "Zarejestruj się, aby otrzymać kartę i zaakceptuj warunki.",
682
+ "silent_payment": "Cicha płatność",
683
"silent_payments": "Ciche płatności",
684
"silent_payments_always_scan": "Ustaw ciche płatności zawsze skanowanie",
685
"silent_payments_disclaimer": "Nowe adresy nie są nową tożsamością. Jest to ponowne wykorzystanie istniejącej tożsamości z inną etykietą.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)",
713
"symbol": "Symbol",
714
"sync_all_wallets": "Synchronizuj wszystkie portfele",
715
+ "sync_status_attempting_scan": "Próba skanowania",
716
"sync_status_attempting_sync": "PRÓBA SYNCHRONIZACJI",
717
"sync_status_connected": "POŁĄCZONY",
718
"sync_status_connecting": "ŁĄCZENIE",
719
"sync_status_failed_connect": "POŁĄCZENIE NIEUDANE",
720
"sync_status_not_connected": "NIE POŁĄCZONY",
716
- "sync_status_starting_scan": "Rozpoczęcie skanowania",
721
+ "sync_status_starting_scan": "Rozpoczęcie skanowania (od ${height})",
722
"sync_status_starting_sync": "ROZPOCZĘCIE SYNCHRONIZACJI",
723
"sync_status_syncronized": "ZSYNCHRONIZOWANO",
724
"sync_status_syncronizing": "SYNCHRONIZACJA",
res/values/strings_pt.arb
+9
-4
@@ -143,7 +143,7 @@
143
"confirm_fee_deduction": "Confirme dedução da taxa",
144
"confirm_fee_deduction_content": "Você concorda em deduzir a taxa da saída?",
145
"confirm_sending": "Confirmar o envio",
146
- "confirm_silent_payments_switch_node": "Seu nó atual não suporta pagamentos silenciosos \\ Ncake Wallet mudará para um nó compatível, apenas para digitalização",
146
+ "confirm_silent_payments_switch_node": "Seu nó atual não suporta pagamentos silenciosos \n A Cake Wallet mudará para um nó compatível, apenas para escanear",
147
"confirmations": "Confirmações",
148
"confirmed": "Saldo Confirmado",
149
"confirmed_tx": "Confirmado",
@@ -232,8 +232,9 @@
232
"edit_token": "Editar símbolo",
233
"electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando",
234
"email_address": "Endereço de e-mail",
235
+ "enable_mempool_api": "Mempool API para taxas e datas precisas",
236
"enable_replace_by_fee": "Habilite substituir por taxa",
236
- "enable_silent_payments_scanning": "Ativar escaneamento de pagamentos silenciosos",
237
+ "enable_silent_payments_scanning": "Comece a escanear pagamentos silenciosos, até que o topo seja alcançada",
238
"enabled": "Habilitado",
239
"enter_amount": "Digite o valor",
240
"enter_backup_password": "Digite a senha de backup aqui",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Falha na autenticação. ${state_error}",
297
"faq": "FAQ",
298
"features": "Funcionalidades",
299
+ "fee_rate": "Taxa de transação",
300
"fetching": "Buscando",
301
"fiat_api": "API da Fiat",
302
"fiat_balance": "Equilíbrio Fiat",
@@ -612,6 +614,7 @@
614
"send": "Enviar",
615
"send_address": "Endereço ${cryptoCurrency}",
616
"send_amount": "Montante:",
617
+ "send_change_to_you": "Troco, para você:",
618
"send_creating_transaction": "Criando transação",
619
"send_error_currency": "A moeda só pode conter números",
620
"send_error_minimum_value": "O valor mínimo da quantia é 0,01",
@@ -678,8 +681,9 @@
681
"signature_invalid_error": "A assinatura não é válida para a mensagem dada",
682
"signTransaction": "Assinar transação",
683
"signup_for_card_accept_terms": "Cadastre-se no cartão e aceite os termos.",
684
+ "silent_payment": "Pagamento silencioso",
685
"silent_payments": "Pagamentos silenciosos",
682
- "silent_payments_always_scan": "Defina pagamentos silenciosos sempre digitalizando",
686
+ "silent_payments_always_scan": "Defina pagamentos silenciosos sempre escaneando",
687
"silent_payments_disclaimer": "Novos endereços não são novas identidades. É uma reutilização de uma identidade existente com um rótulo diferente.",
688
"silent_payments_display_card": "Mostrar cartão de pagamento silencioso",
689
"silent_payments_scan_from_date": "Escanear a partir da data",
@@ -710,12 +714,13 @@
714
"switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)",
715
"symbol": "Símbolo",
716
"sync_all_wallets": "Sincronize todas as carteiras",
717
+ "sync_status_attempting_scan": "TENTANDO ESCANEAR",
718
"sync_status_attempting_sync": "TENTANDO SINCRONIZAR",
719
"sync_status_connected": "CONECTADO",
720
"sync_status_connecting": "CONECTANDO",
721
"sync_status_failed_connect": "DESCONECTADO",
722
"sync_status_not_connected": "DESCONECTADO",
718
- "sync_status_starting_scan": "Diretor inicial",
723
+ "sync_status_starting_scan": "Começando scan (de ${height})",
724
"sync_status_starting_sync": "INICIANDO SINCRONIZAÇÃO",
725
"sync_status_syncronized": "SINCRONIZADO",
726
"sync_status_syncronizing": "SINCRONIZANDO",
res/values/strings_ru.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Изменить токен",
233
"electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.",
234
"email_address": "Адрес электронной почты",
235
+ "enable_mempool_api": "Mempool API за точные сборы и даты",
236
"enable_replace_by_fee": "Включить замену за пикой",
236
- "enable_silent_payments_scanning": "Включить сканирование безмолвных платежей",
237
+ "enable_silent_payments_scanning": "Начните сканировать безмолвные платежи, пока не будет достигнут наконечник",
238
"enabled": "Включено",
239
"enter_amount": "Введите сумму",
240
"enter_backup_password": "Введите пароль резервной копии",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Ошибка аутентификации. ${state_error}",
297
"faq": "FAQ",
298
"features": "Функции",
299
+ "fee_rate": "Плата",
300
"fetching": "Загрузка",
301
"fiat_api": "Фиат API",
302
"fiat_balance": "Фиатный баланс",
@@ -611,6 +613,7 @@
613
"send": "Отправить",
614
"send_address": "${cryptoCurrency} адрес",
615
"send_amount": "Сумма:",
616
+ "send_change_to_you": "Изменить, для вас:",
617
"send_creating_transaction": "Создать транзакцию",
618
"send_error_currency": "Валюта может содержать только цифры",
619
"send_error_minimum_value": "Mинимальная сумма 0.01",
@@ -677,6 +680,7 @@
680
"signature_invalid_error": "Подпись недопустима для данного сообщения",
681
"signTransaction": "Подписать транзакцию",
682
"signup_for_card_accept_terms": "Подпишитесь на карту и примите условия.",
683
+ "silent_payment": "Молчаливый платеж",
684
"silent_payments": "Молчаливые платежи",
685
"silent_payments_always_scan": "Установить молчаливые платежи всегда сканирование",
686
"silent_payments_disclaimer": "Новые адреса не являются новыми личностями. Это повторное использование существующей идентичности с другой этикеткой.",
@@ -709,12 +713,13 @@
713
"switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon).",
714
"symbol": "Символ",
715
"sync_all_wallets": "Синхронизировать все кошельки",
716
+ "sync_status_attempting_scan": "Попытка сканирования",
717
"sync_status_attempting_sync": "ПОПЫТКА СИНХРОНИЗАЦИИ",
718
"sync_status_connected": "ПОДКЛЮЧЕНО",
719
"sync_status_connecting": "ПОДКЛЮЧЕНИЕ",
720
"sync_status_failed_connect": "ОТКЛЮЧЕНО",
721
"sync_status_not_connected": "НЕ ПОДКЛЮЧЁН",
717
- "sync_status_starting_scan": "Начальное сканирование",
722
+ "sync_status_starting_scan": "Начальное сканирование (от ${height})",
723
"sync_status_starting_sync": "НАЧАЛО СИНХРОНИЗАЦИИ",
724
"sync_status_syncronized": "СИНХРОНИЗИРОВАН",
725
"sync_status_syncronizing": "СИНХРОНИЗАЦИЯ",
res/values/strings_th.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "แก้ไขโทเค็น",
233
"electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป",
234
"email_address": "ที่อยู่อีเมล",
235
+ "enable_mempool_api": "Mempool API สำหรับค่าธรรมเนียมและวันที่ที่ถูกต้อง",
236
"enable_replace_by_fee": "เปิดใช้งานการเปลี่ยนโดยค่าธรรมเนียม",
236
- "enable_silent_payments_scanning": "เปิดใช้งานการสแกนการชำระเงินแบบเงียบ",
237
+ "enable_silent_payments_scanning": "เริ่มสแกนการชำระเงินแบบเงียบจนกว่าจะถึงปลาย",
238
"enabled": "เปิดใช้งาน",
239
"enter_amount": "กรอกจำนวน",
240
"enter_backup_password": "ป้อนรหัสผ่านสำรองที่นี่",
@@ -295,6 +296,7 @@
296
"failed_authentication": "การยืนยันสิทธิ์ล้มเหลว ${state_error}",
297
"faq": "คำถามที่พบบ่อย",
298
"features": "คุณสมบัติ",
299
+ "fee_rate": "อัตราค่าธรรมเนียม",
300
"fetching": "กำลังโหลด",
301
"fiat_api": "API สกุลเงินตรา",
302
"fiat_balance": "เฟียต บาลานซ์",
@@ -610,6 +612,7 @@
612
"send": "ส่ง",
613
"send_address": "ที่อยู่ ${cryptoCurrency}",
614
"send_amount": "จำนวน:",
615
+ "send_change_to_you": "เปลี่ยนเป็นคุณ:",
616
"send_creating_transaction": "กำลังสร้างธุรกรรม",
617
"send_error_currency": "สกุลเงินสามารถเป็นเลขเท่านั้น",
618
"send_error_minimum_value": "จำนวนขั้นต่ำของจำนวนเงินคือ 0.01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "ลายเซ็นไม่ถูกต้องสำหรับข้อความที่ให้ไว้",
680
"signTransaction": "ลงนามในการทำธุรกรรม",
681
"signup_for_card_accept_terms": "ลงทะเบียนสำหรับบัตรและยอมรับเงื่อนไข",
682
+ "silent_payment": "การชำระเงินแบบเงียบ",
683
"silent_payments": "การชำระเงินเงียบ",
684
"silent_payments_always_scan": "ตั้งค่าการชำระเงินแบบเงียบเสมอ",
685
"silent_payments_disclaimer": "ที่อยู่ใหม่ไม่ใช่ตัวตนใหม่ มันเป็นการใช้ซ้ำของตัวตนที่มีอยู่ด้วยฉลากที่แตกต่างกัน",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)",
713
"symbol": "เครื่องหมาย",
714
"sync_all_wallets": "ซิงค์กระเป๋าเงินทั้งหมด",
715
+ "sync_status_attempting_scan": "พยายามสแกน",
716
"sync_status_attempting_sync": "พยายามซิงโครไนซ์",
717
"sync_status_connected": "เชื่อมต่อแล้ว",
718
"sync_status_connecting": "กำลังเชื่อมต่อ",
719
"sync_status_failed_connect": "การเชื่อมต่อล้มเหลว",
720
"sync_status_not_connected": "ไม่ได้เชื่อมต่อ",
716
- "sync_status_starting_scan": "เริ่มการสแกน",
721
+ "sync_status_starting_scan": "การสแกนเริ่มต้น (จาก ${height})",
722
"sync_status_starting_sync": "กำลังเริ่มซิงโครไนซ์",
723
"sync_status_syncronized": "ซิงโครไนซ์แล้ว",
724
"sync_status_syncronizing": "กำลังซิงโครไนซ์",
res/values/strings_tl.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "I-edit ang token",
233
"electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana",
234
"email_address": "Email Address",
235
+ "enable_mempool_api": "Mempool API para sa tumpak na bayad at mga petsa",
236
"enable_replace_by_fee": "Paganahin ang Replace-By-Fee",
236
- "enable_silent_payments_scanning": "Paganahin ang pag-scan ng mga tahimik na pagbabayad",
237
+ "enable_silent_payments_scanning": "Simulan ang pag -scan ng tahimik na pagbabayad, hanggang sa maabot ang tip",
238
"enabled": "Pinagana",
239
"enter_amount": "Ipasok ang halaga",
240
"enter_backup_password": "Ipasok ang backup na password dito",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Nabigo ang pagpapatunay. ${state_error}",
297
"faq": "FAQ",
298
"features": "Mga tampok",
299
+ "fee_rate": "Rate ng bayad",
300
"fetching": "Pagkuha",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "Balanse ng fiat",
@@ -610,6 +612,7 @@
612
"send": "Ipadala",
613
"send_address": "${cryptoCurrency} address",
614
"send_amount": "Halaga:",
615
+ "send_change_to_you": "Baguhin, sa iyo:",
616
"send_creating_transaction": "Paglikha ng transaksyon",
617
"send_error_currency": "Ang halaga ay maaari lamang maglaman ng mga numero",
618
"send_error_minimum_value": "Ang minimum na halaga ay 0.01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "Ang lagda ay hindi wasto para sa ibinigay na mensahe",
680
"signTransaction": "Mag-sign ang Transaksyon",
681
"signup_for_card_accept_terms": "Mag-sign up para sa card at tanggapin ang mga tuntunin.",
682
+ "silent_payment": "Tahimik na pagbabayad",
683
"silent_payments": "Tahimik na pagbabayad",
684
"silent_payments_always_scan": "Itakda ang mga tahimik na pagbabayad na laging nag-scan",
685
"silent_payments_disclaimer": "Ang mga bagong address ay hindi mga bagong pagkakakilanlan. Ito ay isang muling paggamit ng isang umiiral na pagkakakilanlan na may ibang label.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)",
713
"symbol": "Simbolo",
714
"sync_all_wallets": "I-sync ang lahat ng mga wallet",
715
+ "sync_status_attempting_scan": "Pagtatangka ng pag -scan",
716
"sync_status_attempting_sync": "SINUSUBUKANG I-SYNC",
717
"sync_status_connected": "KONEKTADO",
718
"sync_status_connecting": "KUMOKENEKTA",
719
"sync_status_failed_connect": "NADISKONEKTA",
720
"sync_status_not_connected": "HINDI KONEKTADO",
716
- "sync_status_starting_scan": "SIMULA SA PAG-SCAN",
721
+ "sync_status_starting_scan": "Simula sa pag -scan (mula sa ${height})",
722
"sync_status_starting_sync": "SIMULA SA PAG-SYNC",
723
"sync_status_syncronized": "NAKA-SYNCHRONIZE",
724
"sync_status_syncronizing": "PAG-SYNCHRONIZE",
res/values/strings_tr.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Belirteci düzenle",
233
"electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder",
234
"email_address": "E-posta Adresi",
235
+ "enable_mempool_api": "Doğru ücretler ve tarihler için Mempool API'si",
236
"enable_replace_by_fee": "Farklı Değiştir'i Etkinleştir",
236
- "enable_silent_payments_scanning": "Sessiz ödeme taramasını etkinleştirin",
237
+ "enable_silent_payments_scanning": "Bahşiş ulaşılıncaya kadar sessiz ödemeleri taramaya başlayın",
238
"enabled": "Etkin",
239
"enter_amount": "Miktar Girin",
240
"enter_backup_password": "Yedekleme parolasını buraya gir",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Doğrulama başarısız oldu. ${state_error}",
297
"faq": "SSS",
298
"features": "Özellikler",
299
+ "fee_rate": "Ücret oranı",
300
"fetching": "Getiriliyor",
301
"fiat_api": "İtibari Para API",
302
"fiat_balance": "Fiat Bakiyesi",
@@ -610,6 +612,7 @@
612
"send": "Para Gönder",
613
"send_address": "${cryptoCurrency} adresi",
614
"send_amount": "Miktar:",
615
+ "send_change_to_you": "Değiştir, size:",
616
"send_creating_transaction": "İşlem oluşturuluyor",
617
"send_error_currency": "Para birimi sadece sayı içerebilir",
618
"send_error_minimum_value": "Minimum tutar değeri 0.01'dir",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "İmza verilen mesaj için geçerli değil",
680
"signTransaction": "İşlem İmzala",
681
"signup_for_card_accept_terms": "Kart için kaydol ve koşulları kabul et.",
682
+ "silent_payment": "Sessiz Ödeme",
683
"silent_payments": "Sessiz ödemeler",
684
"silent_payments_always_scan": "Sessiz ödemeleri her zaman tarama ayarlayın",
685
"silent_payments_disclaimer": "Yeni adresler yeni kimlikler değildir. Farklı bir etikete sahip mevcut bir kimliğin yeniden kullanımıdır.",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)",
713
"symbol": "Sembol",
714
"sync_all_wallets": "Tüm cüzdanları senkronize edin",
715
+ "sync_status_attempting_scan": "Tarama deneme",
716
"sync_status_attempting_sync": "SENKRONİZE EDİLMEYE ÇALIŞILIYOR",
717
"sync_status_connected": "BAĞLANILDI",
718
"sync_status_connecting": "BAĞLANILIYOR",
719
"sync_status_failed_connect": "BAĞLANTI KESİLDİ",
720
"sync_status_not_connected": "BAĞLI DEĞİL",
716
- "sync_status_starting_scan": "Başlangıç taraması",
721
+ "sync_status_starting_scan": "Başlangıç taraması (${height})",
722
"sync_status_starting_sync": "SENKRONİZE BAŞLATILIYOR",
723
"sync_status_syncronized": "SENKRONİZE EDİLDİ",
724
"sync_status_syncronizing": "SENKRONİZE EDİLİYOR",
res/values/strings_uk.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "Редагувати маркер",
233
"electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати",
234
"email_address": "Адреса електронної пошти",
235
+ "enable_mempool_api": "API Mempool для точних зборів та дат",
236
"enable_replace_by_fee": "Увімкнути заміну з комісією",
236
- "enable_silent_payments_scanning": "Увімкнути мовчазні платежі сканування",
237
+ "enable_silent_payments_scanning": "Почніть сканувати мовчазні платежі, поки не буде досягнуто наконечника",
238
"enabled": "Увімкнено",
239
"enter_amount": "Введіть суму",
240
"enter_backup_password": "Введіть пароль резервної копії",
@@ -295,6 +296,7 @@
296
"failed_authentication": "Помилка аутентифікації. ${state_error}",
297
"faq": "FAQ",
298
"features": "Особливості",
299
+ "fee_rate": "Ставка плати",
300
"fetching": "Завантаження",
301
"fiat_api": "Фіат API",
302
"fiat_balance": "Фіат Баланс",
@@ -611,6 +613,7 @@
613
"send": "Відправити",
614
"send_address": "${cryptoCurrency} адреса",
615
"send_amount": "Сума:",
616
+ "send_change_to_you": "Зміна, для вас:",
617
"send_creating_transaction": "Створити транзакцію",
618
"send_error_currency": "Валюта може містити тільки цифри",
619
"send_error_minimum_value": "Мінімальна сума 0.01",
@@ -677,6 +680,7 @@
680
"signature_invalid_error": "Підпис не є дійсним для наведеного повідомлення",
681
"signTransaction": "Підписати транзакцію",
682
"signup_for_card_accept_terms": "Зареєструйтеся на картку та прийміть умови.",
683
+ "silent_payment": "Мовчазний платіж",
684
"silent_payments": "Мовчазні платежі",
685
"silent_payments_always_scan": "Встановити мовчазні платежі завжди сканувати",
686
"silent_payments_disclaimer": "Нові адреси - це не нові ідентичності. Це повторне використання існуючої ідентичності з іншою етикеткою.",
@@ -709,12 +713,13 @@
713
"switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)",
714
"symbol": "символ",
715
"sync_all_wallets": "Синхронізувати всі гаманці",
716
+ "sync_status_attempting_scan": "Спроба сканування",
717
"sync_status_attempting_sync": "СПРОБА СИНХРОНІЗАЦІЇ",
718
"sync_status_connected": "ПІДКЛЮЧЕНО",
719
"sync_status_connecting": "ПІДКЛЮЧЕННЯ",
720
"sync_status_failed_connect": "ВІДКЛЮЧЕНО",
721
"sync_status_not_connected": "НЕ ПІДКЛЮЧЕННИЙ",
717
- "sync_status_starting_scan": "Початок сканування",
722
+ "sync_status_starting_scan": "Початок сканування (від ${height})",
723
"sync_status_starting_sync": "ПОЧАТОК СИНХРОНІЗАЦІЇ",
724
"sync_status_syncronized": "СИНХРОНІЗОВАНИЙ",
725
"sync_status_syncronizing": "СИНХРОНІЗАЦІЯ",
res/values/strings_ur.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "ٹوکن میں ترمیم کریں۔",
233
"electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔",
234
"email_address": "ای میل اڈریس",
235
+ "enable_mempool_api": "درست فیسوں اور تاریخوں کے لئے میمپول API",
236
"enable_replace_by_fee": "فی فیس کو تبدیل کریں",
236
- "enable_silent_payments_scanning": "خاموش ادائیگیوں کو اسکیننگ کے قابل بنائیں",
237
+ "enable_silent_payments_scanning": "خاموش ادائیگیوں کو اسکین کرنا شروع کریں ، جب تک کہ نوک نہ پہنچ جائے",
238
"enabled": "فعال",
239
"enter_amount": "رقم درج کریں۔",
240
"enter_backup_password": "یہاں بیک اپ پاس ورڈ درج کریں۔",
@@ -295,6 +296,7 @@
296
"failed_authentication": "ناکام تصدیق۔ ${state_error}",
297
"faq": "عمومی سوالات",
298
"features": "خصوصیات",
299
+ "fee_rate": "فیس کی شرح",
300
"fetching": "لا رہا ہے۔",
301
"fiat_api": "Fiat API",
302
"fiat_balance": "فیاٹ بیلنس",
@@ -612,6 +614,7 @@
614
"send": "بھیجیں",
615
"send_address": "${cryptoCurrency} پتہ",
616
"send_amount": "رقم:",
617
+ "send_change_to_you": "آپ کو تبدیل کریں:",
618
"send_creating_transaction": "لین دین کی تخلیق",
619
"send_error_currency": "کرنسی صرف نمبروں پر مشتمل ہو سکتی ہے۔",
620
"send_error_minimum_value": "رقم کی کم از کم قیمت 0.01 ہے۔",
@@ -678,6 +681,7 @@
681
"signature_invalid_error": "دستخط دیئے گئے پیغام کے لئے درست نہیں ہے",
682
"signTransaction": "۔ﮟﯾﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ",
683
"signup_for_card_accept_terms": "کارڈ کے لیے سائن اپ کریں اور شرائط کو قبول کریں۔",
684
+ "silent_payment": "خاموش ادائیگی",
685
"silent_payments": "خاموش ادائیگی",
686
"silent_payments_always_scan": "خاموش ادائیگی ہمیشہ اسکیننگ کریں",
687
"silent_payments_disclaimer": "نئے پتے نئی شناخت نہیں ہیں۔ یہ ایک مختلف لیبل کے ساتھ موجودہ شناخت کا دوبارہ استعمال ہے۔",
@@ -710,12 +714,13 @@
714
"switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ",
715
"symbol": "ﺖﻣﻼﻋ",
716
"sync_all_wallets": "تمام بٹوے کو ہم آہنگ کریں",
717
+ "sync_status_attempting_scan": "اسکین کی کوشش کرنا",
718
"sync_status_attempting_sync": "ہم آہنگی کی کوشش کر رہا ہے۔",
719
"sync_status_connected": "منسلک",
720
"sync_status_connecting": "جڑ رہا ہے۔",
721
"sync_status_failed_connect": "منقطع",
722
"sync_status_not_connected": "منسلک نہیں",
718
- "sync_status_starting_scan": "اسکین شروع کرنا",
723
+ "sync_status_starting_scan": "اسکین شروع کرنا (${height})",
724
"sync_status_starting_sync": "مطابقت پذیری شروع کر رہا ہے۔",
725
"sync_status_syncronized": "مطابقت پذیر",
726
"sync_status_syncronizing": "مطابقت پذیری",
res/values/strings_vi.arb
+10
-9
@@ -140,8 +140,8 @@
140
"confirm": "Xác nhận",
141
"confirm_delete_template": "Thao tác này sẽ xóa mẫu này. Bạn có muốn tiếp tục không?",
142
"confirm_delete_wallet": "Thao tác này sẽ xóa ví này. Bạn có muốn tiếp tục không?",
143
- "confirm_fee_deduction": "Xác nhận Khấu trừ Phí",
143
"confirm_fee_dedction_content": "Bạn có đồng ý trừ phí từ đầu ra không?",
144
+ "confirm_fee_deduction": "Xác nhận Khấu trừ Phí",
145
"confirm_sending": "Xác nhận gửi",
146
"confirm_silent_payments_switch_node": "Nút hiện tại của bạn không hỗ trợ thanh toán im lặng\\nCake Wallet sẽ chuyển sang một nút tương thích chỉ để quét",
147
"confirmations": "Xác nhận",
@@ -230,6 +230,7 @@
230
"edit_token": "Chỉnh sửa token",
231
"electrum_address_disclaimer": "Chúng tôi tạo địa chỉ mới mỗi khi bạn sử dụng, nhưng các địa chỉ cũ vẫn tiếp tục hoạt động",
232
"email_address": "Địa chỉ Email",
233
+ "enable_mempool_api": "API Mempool cho các khoản phí và ngày chính xác",
234
"enable_replace_by_fee": "Bật Thay thế Bằng Phí",
235
"enable_silent_payments_scanning": "Bật quét thanh toán im lặng",
236
"enabled": "Đã bật",
@@ -298,7 +299,7 @@
299
"fiat_balance": "Số dư Fiat",
300
"field_required": "Trường này là bắt buộc",
301
"fill_code": "Vui lòng điền mã xác minh được gửi đến email của bạn",
301
- "filter_by": "Lọc theo",
302
+ "filter_by": "Lọc theo",
303
"first_wallet_text": "Ví tuyệt vời cho Monero, Bitcoin, Ethereum, Litecoin, và Haven",
304
"fixed_pair_not_supported": "Cặp tỷ giá cố định này không được hỗ trợ với các sàn giao dịch đã chọn",
305
"fixed_rate": "Tỷ giá cố định",
@@ -398,7 +399,7 @@
399
"new_subaddress_label_name": "Tên nhãn",
400
"new_subaddress_title": "Địa chỉ mới",
401
"new_template": "Mẫu mới",
401
- "new_wallet": "Ví mới",
402
+ "new_wallet": "Ví mới",
403
"newConnection": "Kết nối mới",
404
"no_cards_found": "Không tìm thấy thẻ",
405
"no_id_needed": "Không cần ID!",
@@ -498,7 +499,7 @@
499
"red_dark_theme": "Chủ đề tối đỏ",
500
"red_light_theme": "Chủ đề sáng đỏ",
501
"redeemed": "Đã đổi",
501
- "refund_address": "Địa chỉ hoàn tiền",
502
+ "refund_address": "Địa chỉ hoàn tiền",
503
"reject": "Từ chối",
504
"remaining": "còn lại",
505
"remove": "Gỡ bỏ",
@@ -598,7 +599,7 @@
599
"seedtype": "Loại hạt giống",
600
"seedtype_legacy": "Di sản (25 từ)",
601
"seedtype_polyseed": "Polyseed (16 từ)",
601
- "seedtype_wownero": "Wownero (14 từ)",
602
+ "seedtype_wownero": "Wownero (14 từ)",
603
"select_backup_file": "Chọn tệp sao lưu",
604
"select_buy_provider_notice": "Chọn nhà cung cấp mua ở trên. Bạn có thể bỏ qua màn hình này bằng cách thiết lập nhà cung cấp mua mặc định trong cài đặt ứng dụng.",
605
"select_destination": "Vui lòng chọn đích cho tệp sao lưu.",
@@ -698,7 +699,7 @@
699
"support_description_guides": "Tài liệu và hỗ trợ cho các vấn đề phổ biến",
700
"support_description_live_chat": "Miễn phí và nhanh chóng! Các đại diện hỗ trợ được đào tạo sẵn sàng hỗ trợ",
701
"support_description_other_links": "Tham gia cộng đồng của chúng tôi hoặc liên hệ với chúng tôi hoặc các đối tác của chúng tôi qua các phương pháp khác",
701
- "support_title_guides": "Hướng dẫn Cake Wallet",
702
+ "support_title_guides": "Hướng dẫn Cake Wallet",
703
"support_title_live_chat": "Hỗ trợ trực tiếp",
704
"support_title_other_links": "Liên kết hỗ trợ khác",
705
"sweeping_wallet": "Quét ví",
@@ -712,7 +713,7 @@
713
"sync_status_connecting": "ĐANG KẾT NỐI",
714
"sync_status_failed_connect": "ĐÃ NGẮT KẾT NỐI",
715
"sync_status_not_connected": "CHƯA KẾT NỐI",
715
- "sync_status_starting_scan": "ĐANG BẮT ĐẦU QUÉT",
716
+ "sync_status_starting_scan": "ĐANG BẮT ĐẦU QUÉT (${height})",
717
"sync_status_starting_sync": "ĐANG BẮT ĐẦU ĐỒNG BỘ",
718
"sync_status_syncronized": "ĐÃ ĐỒNG BỘ",
719
"sync_status_syncronizing": "ĐANG ĐỒNG BỘ",
@@ -798,7 +799,7 @@
799
"trongrid_history": "Lịch sử TronGrid",
800
"trusted": "Đã tin cậy",
801
"tx_commit_exception_no_dust_on_change": "Giao dịch bị từ chối với số tiền này. Với số tiền này bạn có thể gửi ${min} mà không cần đổi tiền lẻ hoặc ${max} trả lại tiền lẻ.",
801
- "tx_commit_failed": "Giao dịch không thành công. Vui lòng liên hệ với hỗ trợ.",
802
+ "tx_commit_failed": "Giao dịch không thành công. Vui lòng liên hệ với hỗ trợ.",
803
"tx_invalid_input": "Bạn đang sử dụng loại đầu vào sai cho loại thanh toán này",
804
"tx_no_dust_exception": "Giao dịch bị từ chối vì gửi một số tiền quá nhỏ. Vui lòng thử tăng số tiền.",
805
"tx_not_enough_inputs_exception": "Không đủ đầu vào có sẵn. Vui lòng chọn thêm dưới Coin Control",
@@ -897,4 +898,4 @@
898
"you_will_get": "Chuyển đổi thành",
899
"you_will_send": "Chuyển đổi từ",
900
"yy": "YY"
900
-}
901
+}
\ No newline at end of file
res/values/strings_yo.arb
+7
-2
@@ -233,8 +233,9 @@
233
"edit_token": "Ṣatunkọ àmi",
234
"electrum_address_disclaimer": "A dá àwọn àdírẹ́sì títun ní gbogbo àwọn ìgbà t'ẹ́ lo ó kan ṣùgbọ́n ẹ lè tẹ̀síwájú lo àwọn àdírẹ́sì tẹ́lẹ̀tẹ́lẹ̀.",
235
"email_address": "Àdírẹ́sì ímeèlì",
236
+ "enable_mempool_api": "Mempool API fun awọn owo deede ati awọn ọjọ",
237
"enable_replace_by_fee": "Mu ki o rọpo",
237
- "enable_silent_payments_scanning": "Mu ki awọn sisanwo ipalọlọ",
238
+ "enable_silent_payments_scanning": "Bẹrẹ awọn sisanwo ipalọlọ, titi ti o fi de opin",
239
"enabled": "Wọ́n tíwọn ti tan",
240
"enter_amount": "Tẹ̀ iye",
241
"enter_backup_password": "Tẹ̀ ọ̀rọ̀ aṣínà ti ẹ̀dà ḿbí",
@@ -296,6 +297,7 @@
297
"failed_authentication": "Ìfẹ̀rílàdí pipòfo. ${state_error}",
298
"faq": "Àwọn ìbéèrè l'a máa ń bèèrè",
299
"features": "Awọn ẹya",
300
+ "fee_rate": "Oṣuwọn owo ọya",
301
"fetching": "ń wá",
302
"fiat_api": "Ojú ètò áàpù owó tí ìjọba pàṣẹ wa lò",
303
"fiat_balance": "Fiat Iwontunws.funfun",
@@ -611,6 +613,7 @@
613
"send": "Ránṣẹ́",
614
"send_address": "${cryptoCurrency} àdírẹ́sì",
615
"send_amount": "Iye:",
616
+ "send_change_to_you": "Yipada, si ọ:",
617
"send_creating_transaction": "Ńṣe àránṣẹ́",
618
"send_error_currency": "Ó yẹ kí òǹkà dá wà nínu iye",
619
"send_error_minimum_value": "Ránṣẹ́ owó kò kéré dé 0.01",
@@ -677,6 +680,7 @@
680
"signature_invalid_error": "Ibuwọlu ko wulo fun ifiranṣẹ ti a fun",
681
"signTransaction": "Wole Idunadura",
682
"signup_for_card_accept_terms": "Ẹ f'orúkọ sílẹ̀ láti gba káàdì àti àjọrò.",
683
+ "silent_payment": "Isanwo dakẹ",
684
"silent_payments": "Awọn sisanwo ipalọlọ",
685
"silent_payments_always_scan": "Ṣeto awọn sisanwo ipalọlọ nigbagbogbo n ṣatunṣe",
686
"silent_payments_disclaimer": "Awọn adirẹsi tuntun kii ṣe awọn idanimọ tuntun. O jẹ yiyan ti idanimọ ti o wa pẹlu aami oriṣiriṣi.",
@@ -709,12 +713,13 @@
713
"switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)",
714
"symbol": "Aami",
715
"sync_all_wallets": "Muṣiṣẹpọ gbogbo awọn Woleti",
716
+ "sync_status_attempting_scan": "Igbiyanju ọlọjẹ",
717
"sync_status_attempting_sync": "Ń GBÌYÀNJÚ MÚDỌ́GBA",
718
"sync_status_connected": "TI DÁRAPỌ̀ MỌ́",
719
"sync_status_connecting": "Ń DÁRAPỌ̀ MỌ́",
720
"sync_status_failed_connect": "ÌKÀNPỌ̀ TI KÚ",
721
"sync_status_not_connected": "KÒ TI DÁRAPỌ̀ MỌ́ Ọ",
717
- "sync_status_starting_scan": "Bibẹrẹ ọlọjẹ",
722
+ "sync_status_starting_scan": "Ibẹrẹ ọlọjẹ (lati ${height})",
723
"sync_status_starting_sync": "Ń BẸ̀RẸ̀ RẸ́",
724
"sync_status_syncronized": "TI MÚDỌ́GBA",
725
"sync_status_syncronizing": "Ń MÚDỌ́GBA",
res/values/strings_zh.arb
+7
-2
@@ -232,8 +232,9 @@
232
"edit_token": "编辑令牌",
233
"electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效",
234
"email_address": "电子邮件地址",
235
+ "enable_mempool_api": "Mempool API获得准确的费用和日期",
236
"enable_replace_by_fee": "启用by-Fee替换",
236
- "enable_silent_payments_scanning": "启用无声付款扫描",
237
+ "enable_silent_payments_scanning": "开始扫描无声付款,直到达到提示",
238
"enabled": "启用",
239
"enter_amount": "输入金额",
240
"enter_backup_password": "在此处输入備用密码",
@@ -295,6 +296,7 @@
296
"failed_authentication": "身份验证失败. ${state_error}",
297
"faq": "FAQ",
298
"features": "特征",
299
+ "fee_rate": "费率",
300
"fetching": "正在获取",
301
"fiat_api": "法币API",
302
"fiat_balance": "法币余额",
@@ -610,6 +612,7 @@
612
"send": "发送",
613
"send_address": "${cryptoCurrency} 地址",
614
"send_amount": "金额:",
615
+ "send_change_to_you": "改变,向您:",
616
"send_creating_transaction": "创建交易",
617
"send_error_currency": "货币只能包含数字",
618
"send_error_minimum_value": "最小金额为0.01",
@@ -676,6 +679,7 @@
679
"signature_invalid_error": "签名对于给出的消息无效",
680
"signTransaction": "签署交易",
681
"signup_for_card_accept_terms": "注册卡并接受条款。",
682
+ "silent_payment": "无声付款",
683
"silent_payments": "无声付款",
684
"silent_payments_always_scan": "设置无声付款总是扫描",
685
"silent_payments_disclaimer": "新地址不是新的身份。这是重复使用具有不同标签的现有身份。",
@@ -708,12 +712,13 @@
712
"switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)",
713
"symbol": "象征",
714
"sync_all_wallets": "同步所有钱包",
715
+ "sync_status_attempting_scan": "尝试扫描",
716
"sync_status_attempting_sync": "嘗試同步",
717
"sync_status_connected": "已连接",
718
"sync_status_connecting": "连接中",
719
"sync_status_failed_connect": "断线",
720
"sync_status_not_connected": "未连接",
716
- "sync_status_starting_scan": "开始扫描",
721
+ "sync_status_starting_scan": "启动扫描(来自 ${height})",
722
"sync_status_starting_sync": "开始同步",
723
"sync_status_syncronized": "已同步",
724
"sync_status_syncronizing": "正在同步",
tool/configure.dart
+5
-2
@@ -116,7 +116,7 @@ import 'package:cw_bitcoin/bitcoin_address_record.dart';
116
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
117
import 'package:cw_bitcoin/litecoin_wallet_service.dart';
118
import 'package:cw_core/get_height_by_date.dart';
119
-import 'package:cw_bitcoin/script_hash.dart';
119
+import 'package:cw_core/transaction_info.dart';
120
import 'package:cw_bitcoin/bitcoin_hardware_wallet_service.dart';
121
import 'package:mobx/mobx.dart';
122
""";
@@ -211,7 +211,8 @@ abstract class Bitcoin {
211
int getEstimatedFeeWithFeeRate(Object wallet, int feeRate, int? amount,
212
{int? outputsCount, int? size});
213
int feeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size});
214
- int getHeightByDate({required DateTime date});
214
+ Future<bool> checkIfMempoolAPIIsEnabled(Object wallet);
215
+ Future<int> getHeightByDate({required DateTime date, bool? bitcoinMempoolAPIEnabled});
216
Future<void> rescan(Object wallet, {required int height, bool? doSingleScan});
217
Future<bool> getNodeIsElectrsSPEnabled(Object wallet);
218
void deleteSilentPaymentAddress(Object wallet, String address);
@@ -220,6 +221,8 @@ abstract class Bitcoin {
221
222
void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device);
223
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
224
+ List<Output> updateOutputs(PendingTransaction pendingTransaction, List<Output> outputs);
225
+ bool txIsReceivedSilentPayment(TransactionInfo txInfo);
226
}
227
""";
228