Cw 598 fixes for electrum based wallets (#1344)

* fix: address book addresses, bch builder, exchange all fee estimation, bch coin control * feat: new error framework for Electrum messages * build: cw_bitcoin.dart * feat: error improvements, localization, fix exchange amount mismatch * chore: misc comment & print [skip ci] * feat: refactor & simplify sendAll vs regular tx estimation and creation - Since there were so many conditions inside a single function to alter its behavior if sendAll or not, it is easier and more readable to have separate sendAll and estimateTx functions that behave separately * fix: wrong LTC dust * feat: fee rate confirmation * fix: wrong createTrade value when isSendAll is enabled * fix bitcoin cash address parsing [skip ci] * fix: form no amount validator, address book with multiple entries, exchange all below min error * fix: improve string, fix sending with dust inputs at the top * fix: two change outputs when re-estimating * fix: sendAll with a little dust adds fees * chore: sanity check [skip ci] * fix: if the fee is higher than estimated * Minor enhancement [skip ci] --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>

Rafael committed Mar 29, 2024 at 15:51 UTC fd9018bcc4b48b094e0ac62781ac746b744013fc
60 files changed +980 -427
cw_bitcoin/lib/bitcoin_commit_transaction_exception.dart
+6 -2
@@ -1,4 +1,8 @@
1 class BitcoinCommitTransactionException implements Exception {
2 + String errorMessage;
3 + BitcoinCommitTransactionException(this.errorMessage);
4 +
5 @override
3 - String toString() => 'Transaction commit is failed.';
4 -}
\ No newline at end of file
6 + String toString() => errorMessage;
7 +}
8 +
cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart deleted
-4
@@ -1,4 +0,0 @@
1 -class BitcoinTransactionNoInputsException implements Exception {
2 - @override
3 - String toString() => 'Not enough inputs available. Please select more under Coin Control';
4 -}
cw_bitcoin/lib/bitcoin_transaction_wrong_balance_exception.dart deleted
-10
@@ -1,10 +0,0 @@
1 -import 'package:cw_core/crypto_currency.dart';
2 -
3 -class BitcoinTransactionWrongBalanceException implements Exception {
4 - BitcoinTransactionWrongBalanceException(this.currency);
5 -
6 - final CryptoCurrency currency;
7 -
8 - @override
9 - String toString() => 'You do not have enough ${currency.title} to send this amount.';
10 -}
\ No newline at end of file
cw_bitcoin/lib/electrum.dart
+36 -24
@@ -7,10 +7,9 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
7 import 'package:cw_bitcoin/script_hash.dart';
8 import 'package:flutter/foundation.dart';
9 import 'package:rxdart/rxdart.dart';
10 -import 'package:http/http.dart' as http;
10
11 String jsonrpcparams(List<Object> params) {
13 - final _params = params?.map((val) => '"${val.toString()}"')?.join(',');
12 + final _params = params.map((val) => '"${val.toString()}"').join(',');
13 return '[$_params]';
14 }
15
@@ -34,6 +33,7 @@ class ElectrumClient {
33 : _id = 0,
34 _isConnected = false,
35 _tasks = {},
36 + _errors = {},
37 unterminatedString = '';
38
39 static const connectionTimeout = Duration(seconds: 5);
@@ -44,6 +44,7 @@ class ElectrumClient {
44 void Function(bool)? onConnectionStatusChange;
45 int _id;
46 final Map<String, SocketTask> _tasks;
47 + final Map<String, String> _errors;
48 bool _isConnected;
49 Timer? _aliveTimer;
50 String unterminatedString;
@@ -243,30 +244,20 @@ class ElectrumClient {
244 });
245
246 Future<String> broadcastTransaction(
246 - {required String transactionRaw, BasedUtxoNetwork? network}) async {
247 - if (network == BitcoinNetwork.testnet) {
248 - return http
249 - .post(Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx'),
250 - headers: <String, String>{'Content-Type': 'application/json; charset=utf-8'},
251 - body: transactionRaw)
252 - .then((http.Response response) {
253 - if (response.statusCode == 200) {
254 - return response.body;
247 + {required String transactionRaw,
248 + BasedUtxoNetwork? network,
249 + Function(int)? idCallback}) async =>
250 + call(
251 + method: 'blockchain.transaction.broadcast',
252 + params: [transactionRaw],
253 + idCallback: idCallback)
254 + .then((dynamic result) {
255 + if (result is String) {
256 + return result;
257 }
258
257 - throw Exception('Failed to broadcast transaction: ${response.body}');
259 + return '';
260 });
259 - }
260 -
261 - return call(method: 'blockchain.transaction.broadcast', params: [transactionRaw])
262 - .then((dynamic result) {
263 - if (result is String) {
264 - return result;
265 - }
266 -
267 - return '';
268 - });
269 - }
261
262 Future<Map<String, dynamic>> getMerkle({required String hash, required int height}) async =>
263 await call(method: 'blockchain.transaction.get_merkle', params: [hash, height])
@@ -371,10 +362,12 @@ class ElectrumClient {
362 }
363 }
364
374 - Future<dynamic> call({required String method, List<Object> params = const []}) async {
365 + Future<dynamic> call(
366 + {required String method, List<Object> params = const [], Function(int)? idCallback}) async {
367 final completer = Completer<dynamic>();
368 _id += 1;
369 final id = _id;
370 + idCallback?.call(id);
371 _registryTask(id, completer);
372 socket!.write(jsonrpc(method: method, id: id, params: params));
373
@@ -456,6 +449,23 @@ class ElectrumClient {
449 final id = response['id'] as String?;
450 final result = response['result'];
451
452 + try {
453 + final error = response['error'] as Map<String, dynamic>?;
454 + if (error != null) {
455 + final errorMessage = error['message'] as String?;
456 + if (errorMessage != null) {
457 + _errors[id!] = errorMessage;
458 + }
459 + }
460 + } catch (_) {}
461 +
462 + try {
463 + final error = response['error'] as String?;
464 + if (error != null) {
465 + _errors[id!] = error;
466 + }
467 + } catch (_) {}
468 +
469 if (method is String) {
470 _methodHandler(method: method, request: response);
471 return;
@@ -465,6 +475,8 @@ class ElectrumClient {
475 _finish(id, result);
476 }
477 }
478 +
479 + String getErrorMessage(int id) => _errors[id.toString()] ?? '';
480 }
481
482 // FIXME: move me
cw_bitcoin/lib/electrum_wallet.dart
+282 -93
@@ -8,10 +8,9 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
8 import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base;
9 import 'package:collection/collection.dart';
10 import 'package:cw_bitcoin/bitcoin_address_record.dart';
11 +import 'package:cw_bitcoin/bitcoin_amount_format.dart';
12 import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
12 -import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart';
13 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
14 -import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart';
14 import 'package:cw_bitcoin/bitcoin_unspent.dart';
15 import 'package:cw_bitcoin/bitcoin_wallet_keys.dart';
16 import 'package:cw_bitcoin/electrum.dart';
@@ -19,6 +18,7 @@ import 'package:cw_bitcoin/electrum_balance.dart';
18 import 'package:cw_bitcoin/electrum_transaction_history.dart';
19 import 'package:cw_bitcoin/electrum_transaction_info.dart';
20 import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
21 +import 'package:cw_bitcoin/exceptions.dart';
22 import 'package:cw_bitcoin/litecoin_network.dart';
23 import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
24 import 'package:cw_bitcoin/script_hash.dart';
@@ -188,27 +188,27 @@ abstract class ElectrumWalletBase
188 }
189 }
190
191 - Future<EstimatedTxResult> estimateTxFeeAndInputsToUse(
192 - int credentialsAmount,
193 - bool sendAll,
194 - List<BitcoinBaseAddress> outputAddresses,
195 - List<BitcoinOutput> outputs,
196 - int? feeRate,
197 - BitcoinTransactionPriority? priority,
198 - {int? inputsCount,
199 - String? memo}) async {
191 + int _getDustAmount() {
192 + return 546;
193 + }
194 +
195 + bool _isBelowDust(int amount) => amount <= _getDustAmount() && network != BitcoinNetwork.testnet;
196 +
197 + Future<EstimatedTxResult> estimateSendAllTx(
198 + List<BitcoinOutput> outputs,
199 + int feeRate, {
200 + String? memo,
201 + int credentialsAmount = 0,
202 + }) async {
203 final utxos = <UtxoWithAddress>[];
204 List<ECPrivate> privateKeys = [];
202 -
203 - var leftAmount = credentialsAmount;
204 - var allInputsAmount = 0;
205 + int allInputsAmount = 0;
206
207 for (int i = 0; i < unspentCoins.length; i++) {
208 final utx = unspentCoins[i];
209
210 if (utx.isSending) {
211 allInputsAmount += utx.value;
211 - leftAmount = leftAmount - utx.value;
212
213 final address = addressTypeFromStr(utx.address, network);
214 final privkey = generateECPrivate(
@@ -226,15 +226,12 @@ abstract class ElectrumWalletBase
226 vout: utx.vout,
227 scriptType: _getScriptType(address),
228 ),
229 - ownerDetails:
230 - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address),
229 + ownerDetails: UtxoAddressDetails(
230 + publicKey: privkey.getPublic().toHex(),
231 + address: address,
232 + ),
233 ),
234 );
233 -
234 - bool amountIsAcquired = !sendAll && leftAmount <= 0;
235 - if ((inputsCount == null && amountIsAcquired) || inputsCount == i + 1) {
236 - break;
237 - }
235 }
236 }
237
@@ -242,66 +239,218 @@ abstract class ElectrumWalletBase
239 throw BitcoinTransactionNoInputsException();
240 }
241
245 - var changeValue = allInputsAmount - credentialsAmount;
242 + int estimatedSize;
243 + if (network is BitcoinCashNetwork) {
244 + estimatedSize = ForkedTransactionBuilder.estimateTransactionSize(
245 + utxos: utxos,
246 + outputs: outputs,
247 + network: network as BitcoinCashNetwork,
248 + memo: memo,
249 + );
250 + } else {
251 + estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
252 + utxos: utxos,
253 + outputs: outputs,
254 + network: network,
255 + memo: memo,
256 + );
257 + }
258 +
259 + int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize);
260 +
261 + if (fee == 0) {
262 + throw BitcoinTransactionNoFeeException();
263 + }
264
247 - if (!sendAll) {
248 - if (changeValue > 0) {
249 - final changeAddress = await walletAddresses.getChangeAddress();
250 - final address = addressTypeFromStr(changeAddress, network);
251 - outputAddresses.add(address);
252 - outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue)));
265 + // Here, when sending all, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount left for change
266 + int amount = allInputsAmount - fee;
267 +
268 + // Attempting to send less than the dust limit
269 + if (_isBelowDust(amount)) {
270 + throw BitcoinTransactionNoDustException();
271 + }
272 +
273 + if (credentialsAmount > 0) {
274 + final amountLeftForFee = amount - credentialsAmount;
275 + if (amountLeftForFee > 0 && _isBelowDust(amountLeftForFee)) {
276 + amount -= amountLeftForFee;
277 + fee += amountLeftForFee;
278 }
279 }
280
256 - final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
281 + outputs[outputs.length - 1] =
282 + BitcoinOutput(address: outputs.last.address, value: BigInt.from(amount));
283 +
284 + return EstimatedTxResult(
285 utxos: utxos,
258 - outputs: outputs,
259 - network: network,
286 + privateKeys: privateKeys,
287 + fee: fee,
288 + amount: amount,
289 + isSendAll: true,
290 + hasChange: false,
291 memo: memo,
292 );
293 + }
294
263 - int fee = feeRate != null
264 - ? feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize)
265 - : feeAmountForPriority(priority!, 0, 0, size: estimatedSize);
295 + Future<EstimatedTxResult> estimateTxForAmount(
296 + int credentialsAmount,
297 + List<BitcoinOutput> outputs,
298 + int feeRate, {
299 + int? inputsCount,
300 + String? memo,
301 + }) async {
302 + final utxos = <UtxoWithAddress>[];
303 + List<ECPrivate> privateKeys = [];
304 + int allInputsAmount = 0;
305
267 - if (fee == 0) {
268 - throw BitcoinTransactionWrongBalanceException(currency);
269 - }
306 + int leftAmount = credentialsAmount;
307 + final sendingCoins = unspentCoins.where((utx) => utx.isSending).toList();
308
271 - var amount = credentialsAmount;
309 + for (int i = 0; i < sendingCoins.length; i++) {
310 + final utx = sendingCoins[i];
311
273 - final lastOutput = outputs.last;
274 - if (!sendAll) {
275 - if (changeValue > fee) {
276 - // Here, lastOutput is change, deduct the fee from it
277 - outputs[outputs.length - 1] =
278 - BitcoinOutput(address: lastOutput.address, value: lastOutput.value - BigInt.from(fee));
312 + allInputsAmount += utx.value;
313 + leftAmount = leftAmount - utx.value;
314 +
315 + final address = addressTypeFromStr(utx.address, network);
316 + final privkey = generateECPrivate(
317 + hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
318 + index: utx.bitcoinAddressRecord.index,
319 + network: network);
320 +
321 + privateKeys.add(privkey);
322 +
323 + utxos.add(
324 + UtxoWithAddress(
325 + utxo: BitcoinUtxo(
326 + txHash: utx.hash,
327 + value: BigInt.from(utx.value),
328 + vout: utx.vout,
329 + scriptType: _getScriptType(address),
330 + ),
331 + ownerDetails: UtxoAddressDetails(
332 + publicKey: privkey.getPublic().toHex(),
333 + address: address,
334 + ),
335 + ),
336 + );
337 +
338 + bool amountIsAcquired = leftAmount <= 0;
339 + if ((inputsCount == null && amountIsAcquired) || inputsCount == i + 1) {
340 + break;
341 }
342 + }
343 +
344 + if (utxos.isEmpty) {
345 + throw BitcoinTransactionNoInputsException();
346 + }
347 +
348 + final spendingAllCoins = sendingCoins.length == utxos.length;
349 +
350 + // How much is being spent - how much is being sent
351 + int amountLeftForChangeAndFee = allInputsAmount - credentialsAmount;
352 +
353 + if (amountLeftForChangeAndFee <= 0) {
354 + throw BitcoinTransactionWrongBalanceException();
355 + }
356 +
357 + final changeAddress = await walletAddresses.getChangeAddress();
358 + final address = addressTypeFromStr(changeAddress, network);
359 + outputs.add(BitcoinOutput(
360 + address: address,
361 + value: BigInt.from(amountLeftForChangeAndFee),
362 + ));
363 +
364 + int estimatedSize;
365 + if (network is BitcoinCashNetwork) {
366 + estimatedSize = ForkedTransactionBuilder.estimateTransactionSize(
367 + utxos: utxos,
368 + outputs: outputs,
369 + network: network as BitcoinCashNetwork,
370 + memo: memo,
371 + );
372 } else {
281 - // Here, if sendAll, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount for change
282 - amount = allInputsAmount - fee;
373 + estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
374 + utxos: utxos,
375 + outputs: outputs,
376 + network: network,
377 + memo: memo,
378 + );
379 + }
380 +
381 + int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize);
382 +
383 + if (fee == 0) {
384 + throw BitcoinTransactionNoFeeException();
385 + }
386 +
387 + int amount = credentialsAmount;
388 + final lastOutput = outputs.last;
389 + final amountLeftForChange = amountLeftForChangeAndFee - fee;
390 +
391 + if (!_isBelowDust(amountLeftForChange)) {
392 + // Here, lastOutput already is change, return the amount left without the fee to the user's address.
393 outputs[outputs.length - 1] =
284 - BitcoinOutput(address: lastOutput.address, value: BigInt.from(amount));
394 + BitcoinOutput(address: lastOutput.address, value: BigInt.from(amountLeftForChange));
395 + } else {
396 + // If has change that is lower than dust, will end up with tx rejected by network rules, so estimate again without the added change
397 + outputs.removeLast();
398 +
399 + // Still has inputs to spend before failing
400 + if (!spendingAllCoins) {
401 + return estimateTxForAmount(
402 + credentialsAmount,
403 + outputs,
404 + feeRate,
405 + inputsCount: utxos.length + 1,
406 + memo: memo,
407 + );
408 + }
409 +
410 + final estimatedSendAll = await estimateSendAllTx(
411 + outputs,
412 + feeRate,
413 + memo: memo,
414 + );
415 +
416 + if (estimatedSendAll.amount == credentialsAmount) {
417 + return estimatedSendAll;
418 + }
419 +
420 + // Estimate to user how much is needed to send to cover the fee
421 + final maxAmountWithReturningChange = allInputsAmount - _getDustAmount() - fee - 1;
422 + throw BitcoinTransactionNoDustOnChangeException(
423 + bitcoinAmountToString(amount: maxAmountWithReturningChange),
424 + bitcoinAmountToString(amount: estimatedSendAll.amount),
425 + );
426 + }
427 +
428 + // Attempting to send less than the dust limit
429 + if (_isBelowDust(amount)) {
430 + throw BitcoinTransactionNoDustException();
431 }
432
433 final totalAmount = amount + fee;
434
435 if (totalAmount > balance[currency]!.confirmed) {
290 - throw BitcoinTransactionWrongBalanceException(currency);
436 + throw BitcoinTransactionWrongBalanceException();
437 }
438
439 if (totalAmount > allInputsAmount) {
294 - if (unspentCoins.where((utx) => utx.isSending).length == utxos.length) {
295 - throw BitcoinTransactionWrongBalanceException(currency);
440 + if (spendingAllCoins) {
441 + throw BitcoinTransactionWrongBalanceException();
442 } else {
297 - if (changeValue > fee) {
298 - outputAddresses.removeLast();
443 + if (amountLeftForChangeAndFee > fee) {
444 outputs.removeLast();
445 }
446
302 - return estimateTxFeeAndInputsToUse(
303 - credentialsAmount, sendAll, outputAddresses, outputs, feeRate, priority,
304 - inputsCount: utxos.length + 1);
447 + return estimateTxForAmount(
448 + credentialsAmount,
449 + outputs,
450 + feeRate,
451 + inputsCount: utxos.length + 1,
452 + memo: memo,
453 + );
454 }
455 }
456
@@ -310,6 +459,8 @@ abstract class ElectrumWalletBase
459 privateKeys: privateKeys,
460 fee: fee,
461 amount: amount,
462 + hasChange: true,
463 + isSendAll: false,
464 memo: memo,
465 );
466 }
@@ -318,58 +469,80 @@ abstract class ElectrumWalletBase
469 Future<PendingTransaction> createTransaction(Object credentials) async {
470 try {
471 final outputs = <BitcoinOutput>[];
321 - final outputAddresses = <BitcoinBaseAddress>[];
472 final transactionCredentials = credentials as BitcoinTransactionCredentials;
473 final hasMultiDestination = transactionCredentials.outputs.length > 1;
474 final sendAll = !hasMultiDestination && transactionCredentials.outputs.first.sendAll;
475 + final memo = transactionCredentials.outputs.first.memo;
476
326 - var credentialsAmount = 0;
477 + int credentialsAmount = 0;
478
479 for (final out in transactionCredentials.outputs) {
329 - final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address;
330 - final address = addressTypeFromStr(outputAddress, network);
480 + final outputAmount = out.formattedCryptoAmount!;
481
332 - outputAddresses.add(address);
482 + if (!sendAll && _isBelowDust(outputAmount)) {
483 + throw BitcoinTransactionNoDustException();
484 + }
485
486 if (hasMultiDestination) {
335 - if (out.sendAll || out.formattedCryptoAmount! <= 0) {
336 - throw BitcoinTransactionWrongBalanceException(currency);
487 + if (out.sendAll) {
488 + throw BitcoinTransactionWrongBalanceException();
489 }
490 + }
491
339 - final outputAmount = out.formattedCryptoAmount!;
340 - credentialsAmount += outputAmount;
492 + credentialsAmount += outputAmount;
493
342 - outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount)));
494 + final address =
495 + addressTypeFromStr(out.isParsedAddress ? out.extractedAddress! : out.address, network);
496 +
497 + if (sendAll) {
498 + // The value will be changed after estimating the Tx size and deducting the fee from the total to be sent
499 + outputs.add(BitcoinOutput(address: address, value: BigInt.from(0)));
500 } else {
344 - if (!sendAll) {
345 - final outputAmount = out.formattedCryptoAmount!;
346 - credentialsAmount += outputAmount;
347 - outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount)));
348 - } else {
349 - // The value will be changed after estimating the Tx size and deducting the fee from the total
350 - outputs.add(BitcoinOutput(address: address, value: BigInt.from(0)));
351 - }
501 + outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount)));
502 }
503 }
504
355 - final estimatedTx = await estimateTxFeeAndInputsToUse(
356 - credentialsAmount,
357 - sendAll,
358 - outputAddresses,
359 - outputs,
360 - transactionCredentials.feeRate,
361 - transactionCredentials.priority,
362 - memo: transactionCredentials.outputs.first.memo,
363 - );
505 + final feeRateInt = transactionCredentials.feeRate != null
506 + ? transactionCredentials.feeRate!
507 + : feeRate(transactionCredentials.priority!);
508 +
509 + EstimatedTxResult estimatedTx;
510 + if (sendAll) {
511 + estimatedTx = await estimateSendAllTx(
512 + outputs,
513 + feeRateInt,
514 + memo: memo,
515 + credentialsAmount: credentialsAmount,
516 + );
517 + } else {
518 + estimatedTx = await estimateTxForAmount(
519 + credentialsAmount,
520 + outputs,
521 + feeRateInt,
522 + memo: memo,
523 + );
524 + }
525
365 - final txb = BitcoinTransactionBuilder(
366 - utxos: estimatedTx.utxos,
367 - outputs: outputs,
368 - fee: BigInt.from(estimatedTx.fee),
369 - network: network,
370 - memo: estimatedTx.memo,
371 - outputOrdering: BitcoinOrdering.none,
372 - );
526 + BasedBitcoinTransacationBuilder txb;
527 + if (network is BitcoinCashNetwork) {
528 + txb = ForkedTransactionBuilder(
529 + utxos: estimatedTx.utxos,
530 + outputs: outputs,
531 + fee: BigInt.from(estimatedTx.fee),
532 + network: network,
533 + memo: estimatedTx.memo,
534 + outputOrdering: BitcoinOrdering.none,
535 + );
536 + } else {
537 + txb = BitcoinTransactionBuilder(
538 + utxos: estimatedTx.utxos,
539 + outputs: outputs,
540 + fee: BigInt.from(estimatedTx.fee),
541 + network: network,
542 + memo: estimatedTx.memo,
543 + outputOrdering: BitcoinOrdering.none,
544 + );
545 + }
546
547 final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) {
548 final key = estimatedTx.privateKeys
@@ -390,7 +563,10 @@ abstract class ElectrumWalletBase
563 electrumClient: electrumClient,
564 amount: estimatedTx.amount,
565 fee: estimatedTx.fee,
393 - network: network)
566 + feeRate: feeRateInt.toString(),
567 + network: network,
568 + hasChange: estimatedTx.hasChange,
569 + isSendAll: estimatedTx.isSendAll)
570 ..addListener((transaction) async {
571 transactionHistory.addOne(transaction);
572 await updateBalance();
@@ -423,7 +599,7 @@ abstract class ElectrumWalletBase
599 }
600 }
601
426 - int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount,
602 + int feeAmountForPriority(TransactionPriority priority, int inputsCount, int outputsCount,
603 {int? size}) =>
604 feeRate(priority) * (size ?? estimatedTransactionSize(inputsCount, outputsCount));
605
@@ -908,6 +1084,8 @@ class EstimatedTxResult {
1084 required this.privateKeys,
1085 required this.fee,
1086 required this.amount,
1087 + required this.hasChange,
1088 + required this.isSendAll,
1089 this.memo,
1090 });
1091
@@ -915,10 +1093,21 @@ class EstimatedTxResult {
1093 final List<ECPrivate> privateKeys;
1094 final int fee;
1095 final int amount;
1096 + final bool hasChange;
1097 + final bool isSendAll;
1098 final String? memo;
1099 }
1100
1101 BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) {
1102 + if (network is BitcoinCashNetwork) {
1103 + if (!address.startsWith("bitcoincash:") &&
1104 + (address.startsWith("q") || address.startsWith("p"))) {
1105 + address = "bitcoincash:$address";
1106 + }
1107 +
1108 + return BitcoinCashAddress(address).baseAddress;
1109 + }
1110 +
1111 if (P2pkhAddress.regex.hasMatch(address)) {
1112 return P2pkhAddress.fromAddress(address: address, network: network);
1113 } else if (P2shAddress.regex.hasMatch(address)) {
cw_bitcoin/lib/electrum_wallet_addresses.dart
+6 -2
@@ -77,7 +77,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
77 String get address {
78 String receiveAddress;
79
80 - final typeMatchingReceiveAddresses = receiveAddresses.where(_isAddressPageTypeMatch);
80 + final typeMatchingReceiveAddresses =
81 + receiveAddresses.where(_isAddressPageTypeMatch).where((addr) => !addr.isUsed);
82
83 if ((isEnabledAutoGenerateSubaddress && receiveAddresses.isEmpty) ||
84 typeMatchingReceiveAddresses.isEmpty) {
@@ -220,8 +221,11 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
221 Future<void> updateAddressesInBox() async {
222 try {
223 addressesMap.clear();
224 + addressesMap[address] = '';
225 +
226 + allAddressesMap.clear();
227 _addresses.forEach((addressRecord) {
224 - addressesMap[addressRecord.address] = addressRecord.name;
228 + allAddressesMap[addressRecord.address] = addressRecord.name;
229 });
230 await saveAddressesInBox();
231 } catch (e) {
cw_bitcoin/lib/exceptions.dart new
+27
@@ -0,0 +1,27 @@
1 +import 'package:cw_core/crypto_currency.dart';
2 +import 'package:cw_core/exceptions.dart';
3 +
4 +class BitcoinTransactionWrongBalanceException extends TransactionWrongBalanceException {
5 + BitcoinTransactionWrongBalanceException() : super(CryptoCurrency.btc);
6 +}
7 +
8 +class BitcoinTransactionNoInputsException extends TransactionNoInputsException {}
9 +
10 +class BitcoinTransactionNoFeeException extends TransactionNoFeeException {}
11 +
12 +class BitcoinTransactionNoDustException extends TransactionNoDustException {}
13 +
14 +class BitcoinTransactionNoDustOnChangeException extends TransactionNoDustOnChangeException {
15 + BitcoinTransactionNoDustOnChangeException(super.max, super.min);
16 +}
17 +
18 +class BitcoinTransactionCommitFailed extends TransactionCommitFailed {}
19 +
20 +class BitcoinTransactionCommitFailedDustChange extends TransactionCommitFailedDustChange {}
21 +
22 +class BitcoinTransactionCommitFailedDustOutput extends TransactionCommitFailedDustOutput {}
23 +
24 +class BitcoinTransactionCommitFailedDustOutputSendAll
25 + extends TransactionCommitFailedDustOutputSendAll {}
26 +
27 +class BitcoinTransactionCommitFailedVoutNegative extends TransactionCommitFailedVoutNegative {}
cw_bitcoin/lib/pending_bitcoin_transaction.dart
+33 -4
@@ -1,4 +1,4 @@
1 -import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart';
1 +import 'package:cw_bitcoin/exceptions.dart';
2 import 'package:bitcoin_base/bitcoin_base.dart';
3 import 'package:cw_core/pending_transaction.dart';
4 import 'package:cw_bitcoin/electrum.dart';
@@ -9,7 +9,13 @@ import 'package:cw_core/wallet_type.dart';
9
10 class PendingBitcoinTransaction with PendingTransaction {
11 PendingBitcoinTransaction(this._tx, this.type,
12 - {required this.electrumClient, required this.amount, required this.fee, this.network})
12 + {required this.electrumClient,
13 + required this.amount,
14 + required this.fee,
15 + required this.feeRate,
16 + this.network,
17 + required this.hasChange,
18 + required this.isSendAll})
19 : _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
20
21 final WalletType type;
@@ -17,7 +23,10 @@ class PendingBitcoinTransaction with PendingTransaction {
23 final ElectrumClient electrumClient;
24 final int amount;
25 final int fee;
26 + final String feeRate;
27 final BasedUtxoNetwork? network;
28 + final bool hasChange;
29 + final bool isSendAll;
30
31 @override
32 String get id => _tx.txId();
@@ -38,10 +47,30 @@ class PendingBitcoinTransaction with PendingTransaction {
47
48 @override
49 Future<void> commit() async {
41 - final result = await electrumClient.broadcastTransaction(transactionRaw: hex, network: network);
50 + int? callId;
51 +
52 + final result = await electrumClient.broadcastTransaction(
53 + transactionRaw: hex, network: network, idCallback: (id) => callId = id);
54
55 if (result.isEmpty) {
44 - throw BitcoinCommitTransactionException();
56 + if (callId != null) {
57 + final error = electrumClient.getErrorMessage(callId!);
58 +
59 + if (error.contains("dust")) {
60 + if (hasChange) {
61 + throw BitcoinTransactionCommitFailedDustChange();
62 + } else if (!isSendAll) {
63 + throw BitcoinTransactionCommitFailedDustOutput();
64 + } else {
65 + throw BitcoinTransactionCommitFailedDustOutputSendAll();
66 + }
67 + }
68 +
69 + if (error.contains("bad-txns-vout-negative")) {
70 + throw BitcoinTransactionCommitFailedVoutNegative();
71 + }
72 + }
73 + throw BitcoinTransactionCommitFailed();
74 }
75
76 _listeners.forEach((listener) => listener(transactionInfo()));
cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart
-183
@@ -4,15 +4,10 @@ import 'package:bitbox/bitbox.dart' as bitbox;
4 import 'package:bitcoin_base/bitcoin_base.dart';
5 import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
6 import 'package:cw_bitcoin/bitcoin_address_record.dart';
7 -import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
8 -import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart';
7 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
10 -import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart';
11 -import 'package:cw_bitcoin/bitcoin_unspent.dart';
8 import 'package:cw_bitcoin/electrum_balance.dart';
9 import 'package:cw_bitcoin/electrum_wallet.dart';
10 import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
15 -import 'package:cw_bitcoin_cash/src/pending_bitcoin_cash_transaction.dart';
11 import 'package:cw_core/crypto_currency.dart';
12 import 'package:cw_core/transaction_priority.dart';
13 import 'package:cw_core/unspent_coins_info.dart';
@@ -130,187 +125,9 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
125 );
126 }
127
133 - @override
134 - Future<PendingBitcoinCashTransaction> createTransaction(Object credentials) async {
135 - const minAmount = 546;
136 - final transactionCredentials = credentials as BitcoinTransactionCredentials;
137 - final inputs = <BitcoinUnspent>[];
138 - final outputs = transactionCredentials.outputs;
139 - final hasMultiDestination = outputs.length > 1;
140 -
141 - var allInputsAmount = 0;
142 -
143 - final String? opReturnMemo = outputs.first.memo;
144 -
145 - if (unspentCoins.isEmpty) await updateUnspent();
146 -
147 - for (final utx in unspentCoins) {
148 - if (utx.isSending) {
149 - allInputsAmount += utx.value;
150 - inputs.add(utx);
151 - }
152 - }
153 -
154 - if (inputs.isEmpty) throw BitcoinTransactionNoInputsException();
155 -
156 - final allAmountFee = transactionCredentials.feeRate != null
157 - ? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length)
158 - : feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length);
159 -
160 - final allAmount = allInputsAmount - allAmountFee;
161 -
162 - var credentialsAmount = 0;
163 - var amount = 0;
164 - var fee = 0;
165 -
166 - if (hasMultiDestination) {
167 - if (outputs.any((item) => item.sendAll || item.formattedCryptoAmount! <= 0)) {
168 - throw BitcoinTransactionWrongBalanceException(currency);
169 - }
170 -
171 - credentialsAmount = outputs.fold(0, (acc, value) => acc + value.formattedCryptoAmount!);
172 -
173 - if (allAmount - credentialsAmount < minAmount) {
174 - throw BitcoinTransactionWrongBalanceException(currency);
175 - }
176 -
177 - amount = credentialsAmount;
178 -
179 - if (transactionCredentials.feeRate != null) {
180 - fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount,
181 - outputsCount: outputs.length + 1);
182 - } else {
183 - fee = calculateEstimatedFee(transactionCredentials.priority, amount,
184 - outputsCount: outputs.length + 1);
185 - }
186 - } else {
187 - final output = outputs.first;
188 - credentialsAmount = !output.sendAll ? output.formattedCryptoAmount! : 0;
189 -
190 - if (credentialsAmount > allAmount) {
191 - throw BitcoinTransactionWrongBalanceException(currency);
192 - }
193 -
194 - amount = output.sendAll || allAmount - credentialsAmount < minAmount
195 - ? allAmount
196 - : credentialsAmount;
197 -
198 - if (output.sendAll || amount == allAmount) {
199 - fee = allAmountFee;
200 - } else if (transactionCredentials.feeRate != null) {
201 - fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount);
202 - } else {
203 - fee = calculateEstimatedFee(transactionCredentials.priority, amount);
204 - }
205 - }
206 -
207 - if (fee == 0) {
208 - throw BitcoinTransactionWrongBalanceException(currency);
209 - }
210 -
211 - final totalAmount = amount + fee;
212 -
213 - if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) {
214 - throw BitcoinTransactionWrongBalanceException(currency);
215 - }
216 - final txb = bitbox.Bitbox.transactionBuilder(testnet: false);
217 -
218 - final changeAddress = await walletAddresses.getChangeAddress();
219 - var leftAmount = totalAmount;
220 - var totalInputAmount = 0;
221 -
222 - inputs.clear();
223 -
224 - for (final utx in unspentCoins) {
225 - if (utx.isSending) {
226 - leftAmount = leftAmount - utx.value;
227 - totalInputAmount += utx.value;
228 - inputs.add(utx);
229 -
230 - if (leftAmount <= 0) {
231 - break;
232 - }
233 - }
234 - }
235 -
236 - if (inputs.isEmpty) throw BitcoinTransactionNoInputsException();
237 -
238 - if (amount <= 0 || totalInputAmount < totalAmount) {
239 - throw BitcoinTransactionWrongBalanceException(currency);
240 - }
241 -
242 - inputs.forEach((input) {
243 - txb.addInput(input.hash, input.vout);
244 - });
245 -
246 - final String bchPrefix = "bitcoincash:";
247 -
248 - outputs.forEach((item) {
249 - final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount;
250 - String outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address;
251 -
252 - if (!outputAddress.startsWith(bchPrefix)) {
253 - outputAddress = "$bchPrefix$outputAddress";
254 - }
255 -
256 - bool isP2sh = outputAddress.startsWith("p", bchPrefix.length);
257 -
258 - if (isP2sh) {
259 - final p2sh = P2shAddress.fromAddress(
260 - address: outputAddress,
261 - network: BitcoinCashNetwork.mainnet,
262 - );
263 -
264 - txb.addOutput(Uint8List.fromList(p2sh.toScriptPubKey().toBytes()), outputAmount!);
265 - return;
266 - }
267 -
268 - txb.addOutput(outputAddress, outputAmount!);
269 - });
270 -
271 - final estimatedSize = bitbox.BitcoinCash.getByteCount(inputs.length, outputs.length + 1);
272 -
273 - var feeAmount = 0;
274 -
275 - if (transactionCredentials.feeRate != null) {
276 - feeAmount = transactionCredentials.feeRate! * estimatedSize;
277 - } else {
278 - feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize;
279 - }
280 -
281 - final changeValue = totalInputAmount - amount - feeAmount;
282 -
283 - if (changeValue > minAmount) {
284 - txb.addOutput(changeAddress, changeValue);
285 - }
286 -
287 - if (opReturnMemo != null) txb.addOutputData(opReturnMemo);
288 -
289 - for (var i = 0; i < inputs.length; i++) {
290 - final input = inputs[i];
291 - final keyPair = generateKeyPair(
292 - hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
293 - index: input.bitcoinAddressRecord.index);
294 - txb.sign(i, keyPair, input.value);
295 - }
296 -
297 - final tx = txb.build();
298 -
299 - return PendingBitcoinCashTransaction(tx, type,
300 - electrumClient: electrumClient, amount: amount, fee: fee);
301 - }
302 -
128 bitbox.ECPair generateKeyPair({required bitcoin.HDWallet hd, required int index}) =>
129 bitbox.ECPair.fromWIF(hd.derive(index).wif!);
130
306 - @override
307 - int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount,
308 - {int? size}) =>
309 - feeRate(priority) * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount);
310 -
311 - int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) =>
312 - feeRate * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount);
313 -
131 int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount, int? size}) {
132 int inputsCount = 0;
133 int totalValue = 0;
cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart
+30 -8
@@ -1,4 +1,4 @@
1 -import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart';
1 +import 'package:cw_bitcoin/exceptions.dart';
2 import 'package:bitbox/bitbox.dart' as bitbox;
3 import 'package:cw_core/pending_transaction.dart';
4 import 'package:cw_bitcoin/electrum.dart';
@@ -11,7 +11,9 @@ class PendingBitcoinCashTransaction with PendingTransaction {
11 PendingBitcoinCashTransaction(this._tx, this.type,
12 {required this.electrumClient,
13 required this.amount,
14 - required this.fee})
14 + required this.fee,
15 + required this.hasChange,
16 + required this.isSendAll})
17 : _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
18
19 final WalletType type;
@@ -19,6 +21,8 @@ class PendingBitcoinCashTransaction with PendingTransaction {
21 final ElectrumClient electrumClient;
22 final int amount;
23 final int fee;
24 + final bool hasChange;
25 + final bool isSendAll;
26
27 @override
28 String get id => _tx.getId();
@@ -36,18 +40,36 @@ class PendingBitcoinCashTransaction with PendingTransaction {
40
41 @override
42 Future<void> commit() async {
39 - final result =
40 - await electrumClient.broadcastTransaction(transactionRaw: _tx.toHex());
43 + int? callId;
44 +
45 + final result = await electrumClient.broadcastTransaction(
46 + transactionRaw: hex, idCallback: (id) => callId = id);
47
48 if (result.isEmpty) {
43 - throw BitcoinCommitTransactionException();
49 + if (callId != null) {
50 + final error = electrumClient.getErrorMessage(callId!);
51 +
52 + if (error.contains("dust")) {
53 + if (hasChange) {
54 + throw BitcoinTransactionCommitFailedDustChange();
55 + } else if (!isSendAll) {
56 + throw BitcoinTransactionCommitFailedDustOutput();
57 + } else {
58 + throw BitcoinTransactionCommitFailedDustOutputSendAll();
59 + }
60 + }
61 +
62 + if (error.contains("bad-txns-vout-negative")) {
63 + throw BitcoinTransactionCommitFailedVoutNegative();
64 + }
65 + }
66 + throw BitcoinTransactionCommitFailed();
67 }
68
46 - _listeners?.forEach((listener) => listener(transactionInfo()));
69 + _listeners.forEach((listener) => listener(transactionInfo()));
70 }
71
49 - void addListener(
50 - void Function(ElectrumTransactionInfo transaction) listener) =>
72 + void addListener(void Function(ElectrumTransactionInfo transaction) listener) =>
73 _listeners.add(listener);
74
75 ElectrumTransactionInfo transactionInfo() => ElectrumTransactionInfo(type,
cw_core/lib/exceptions.dart new
+30
@@ -0,0 +1,30 @@
1 +import 'package:cw_core/crypto_currency.dart';
2 +
3 +class TransactionWrongBalanceException implements Exception {
4 + TransactionWrongBalanceException(this.currency);
5 +
6 + final CryptoCurrency currency;
7 +}
8 +
9 +class TransactionNoInputsException implements Exception {}
10 +
11 +class TransactionNoFeeException implements Exception {}
12 +
13 +class TransactionNoDustException implements Exception {}
14 +
15 +class TransactionNoDustOnChangeException implements Exception {
16 + TransactionNoDustOnChangeException(this.max, this.min);
17 +
18 + final String max;
19 + final String min;
20 +}
21 +
22 +class TransactionCommitFailed implements Exception {}
23 +
24 +class TransactionCommitFailedDustChange implements Exception {}
25 +
26 +class TransactionCommitFailedDustOutput implements Exception {}
27 +
28 +class TransactionCommitFailedDustOutputSendAll implements Exception {}
29 +
30 +class TransactionCommitFailedVoutNegative implements Exception {}
cw_core/lib/pending_transaction.dart
+2 -1
@@ -2,8 +2,9 @@ mixin PendingTransaction {
2 String get id;
3 String get amountFormatted;
4 String get feeFormatted;
5 + String? feeRate;
6 String get hex;
7 int? get outputCount => null;
8
9 Future<void> commit();
9 -}
\ No newline at end of file
10 +}
cw_core/lib/wallet_addresses.dart
+5 -3
@@ -3,8 +3,9 @@ import 'package:cw_core/wallet_info.dart';
3
4 abstract class WalletAddresses {
5 WalletAddresses(this.walletInfo)
6 - : addressesMap = {},
7 - addressInfos = {};
6 + : addressesMap = {},
7 + allAddressesMap = {},
8 + addressInfos = {};
9
10 final WalletInfo walletInfo;
11
@@ -15,6 +16,7 @@ abstract class WalletAddresses {
16 set address(String address);
17
18 Map<String, String> addressesMap;
19 + Map<String, String> allAddressesMap;
20
21 Map<int, List<AddressInfo>> addressInfos;
22
@@ -39,5 +41,5 @@ abstract class WalletAddresses {
41 }
42 }
43
42 - bool containsAddress(String address) => addressesMap.containsKey(address);
44 + bool containsAddress(String address) => allAddressesMap.containsKey(address);
45 }
lib/bitcoin/cw_bitcoin.dart
+24 -17
@@ -86,7 +86,7 @@ class CWBitcoin extends Bitcoin {
86 extractedAddress: out.extractedAddress,
87 isParsedAddress: out.isParsedAddress,
88 formattedCryptoAmount: out.formattedCryptoAmount,
89 - memo: out.memo))
89 + memo: out.memo))
90 .toList(),
91 priority: priority as BitcoinTransactionPriority,
92 feeRate: feeRate);
@@ -123,23 +123,30 @@ class CWBitcoin extends Bitcoin {
123
124 @override
125 Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority) async {
126 - final electrumWallet = wallet as ElectrumWallet;
127 - final sk = ECPrivate.random();
128 -
129 - final p2shAddr = sk.getPublic().toP2pkhInP2sh();
130 - final p2wpkhAddr = sk.getPublic().toP2wpkhAddress();
126 try {
132 - final estimatedTx = await electrumWallet.estimateTxFeeAndInputsToUse(
133 - 0,
134 - true,
135 - // Deposit address + change address
136 - [p2shAddr, p2wpkhAddr],
137 - [
138 - BitcoinOutput(address: p2shAddr, value: BigInt.zero),
139 - BitcoinOutput(address: p2wpkhAddr, value: BigInt.zero)
140 - ],
141 - null,
142 - priority as BitcoinTransactionPriority);
127 + final sk = ECPrivate.random();
128 + final electrumWallet = wallet as ElectrumWallet;
129 +
130 + if (wallet.type == WalletType.bitcoinCash) {
131 + final p2pkhAddr = sk.getPublic().toP2pkhAddress();
132 + final estimatedTx = await electrumWallet.estimateSendAllTx(
133 + [BitcoinOutput(address: p2pkhAddr, value: BigInt.zero)],
134 + getFeeRate(wallet, priority as BitcoinCashTransactionPriority),
135 + );
136 +
137 + return estimatedTx.amount;
138 + }
139 +
140 + final p2shAddr = sk.getPublic().toP2pkhInP2sh();
141 + final estimatedTx = await electrumWallet.estimateSendAllTx(
142 + [BitcoinOutput(address: p2shAddr, value: BigInt.zero)],
143 + getFeeRate(
144 + wallet,
145 + wallet.type == WalletType.litecoin
146 + ? priority as LitecoinTransactionPriority
147 + : priority as BitcoinTransactionPriority,
148 + ),
149 + );
150
151 return estimatedTx.amount;
152 } catch (_) {
lib/core/amount_validator.dart
+4
@@ -34,6 +34,10 @@ class AmountValidator extends TextValidator {
34 late final DecimalAmountValidator decimalAmountValidator;
35
36 String? call(String? value) {
37 + if (value == null || value.isEmpty) {
38 + return S.current.error_text_amount;
39 + }
40 +
41 //* Validate for Text(length, symbols, decimals etc)
42
43 final textValidation = symbolsAmountValidator(value) ?? decimalAmountValidator(value);
lib/exchange/provider/changenow_exchange_provider.dart
+7 -2
@@ -133,7 +133,11 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
133 }
134
135 @override
136 - Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
136 + Future<Trade> createTrade({
137 + required TradeRequest request,
138 + required bool isFixedRateMode,
139 + required bool isSendAll,
140 + }) async {
141 final distributionPath = await DistributionInfo.instance.getDistributionPath();
142 final formattedAppVersion = int.tryParse(_settingsStore.appVersion.replaceAll('.', '')) ?? 0;
143 final payload = {
@@ -202,7 +206,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
206 createdAt: DateTime.now(),
207 amount: responseJSON['fromAmount']?.toString() ?? request.fromAmount,
208 state: TradeState.created,
205 - payoutAddress: payoutAddress);
209 + payoutAddress: payoutAddress,
210 + isSendAll: isSendAll);
211 }
212
213 @override
lib/exchange/provider/exchange_provider.dart
+2 -1
@@ -28,7 +28,8 @@ abstract class ExchangeProvider {
28 Future<Limits> fetchLimits(
29 {required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode});
30
31 - Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode});
31 + Future<Trade> createTrade(
32 + {required TradeRequest request, required bool isFixedRateMode, required bool isSendAll});
33
34 Future<Trade> findTradeById({required String id});
35
lib/exchange/provider/exolix_exchange_provider.dart
+7 -2
@@ -130,7 +130,11 @@ class ExolixExchangeProvider extends ExchangeProvider {
130 }
131
132 @override
133 - Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
133 + Future<Trade> createTrade({
134 + required TradeRequest request,
135 + required bool isFixedRateMode,
136 + required bool isSendAll,
137 + }) async {
138 final headers = {'Content-Type': 'application/json'};
139 final body = {
140 'coinFrom': _normalizeCurrency(request.fromCurrency),
@@ -180,7 +184,8 @@ class ExolixExchangeProvider extends ExchangeProvider {
184 createdAt: DateTime.now(),
185 amount: amount,
186 state: TradeState.created,
183 - payoutAddress: payoutAddress);
187 + payoutAddress: payoutAddress,
188 + isSendAll: isSendAll);
189 }
190
191 @override
lib/exchange/provider/sideshift_exchange_provider.dart
+6 -1
@@ -144,7 +144,11 @@ class SideShiftExchangeProvider extends ExchangeProvider {
144 }
145
146 @override
147 - Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
147 + Future<Trade> createTrade({
148 + required TradeRequest request,
149 + required bool isFixedRateMode,
150 + required bool isSendAll,
151 + }) async {
152 String url = '';
153 final body = {
154 'affiliateId': affiliateId,
@@ -197,6 +201,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
201 amount: depositAmount ?? request.fromAmount,
202 payoutAddress: settleAddress,
203 createdAt: DateTime.now(),
204 + isSendAll: isSendAll,
205 );
206 }
207
lib/exchange/provider/simpleswap_exchange_provider.dart
+6 -1
@@ -117,7 +117,11 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
117 }
118
119 @override
120 - Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
120 + Future<Trade> createTrade({
121 + required TradeRequest request,
122 + required bool isFixedRateMode,
123 + required bool isSendAll,
124 + }) async {
125 final headers = {'Content-Type': 'application/json'};
126 final params = {'api_key': apiKey};
127 final body = <String, dynamic>{
@@ -162,6 +166,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
166 amount: request.fromAmount,
167 payoutAddress: payoutAddress,
168 createdAt: DateTime.now(),
169 + isSendAll: isSendAll,
170 );
171 }
172
lib/exchange/provider/thorchain_exchange.provider.dart
+11 -4
@@ -109,7 +109,11 @@ class ThorChainExchangeProvider extends ExchangeProvider {
109 }
110
111 @override
112 - Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
112 + Future<Trade> createTrade({
113 + required TradeRequest request,
114 + required bool isFixedRateMode,
115 + required bool isSendAll,
116 + }) async {
117 String formattedToAddress = request.toAddress.startsWith('bitcoincash:')
118 ? request.toAddress.replaceFirst('bitcoincash:', '')
119 : request.toAddress;
@@ -142,7 +146,8 @@ class ThorChainExchangeProvider extends ExchangeProvider {
146 amount: request.fromAmount,
147 state: TradeState.notFound,
148 payoutAddress: request.toAddress,
145 - memo: memo);
149 + memo: memo,
150 + isSendAll: isSendAll);
151 }
152
153 @override
@@ -177,10 +182,12 @@ class ThorChainExchangeProvider extends ExchangeProvider {
182 final parts = memo?.split(':') ?? [];
183
184 final String toChain = parts.length > 1 ? parts[1].split('.')[0] : '';
180 - final String toAsset = parts.length > 1 && parts[1].split('.').length > 1 ? parts[1].split('.')[1].split('-')[0] : '';
185 + final String toAsset = parts.length > 1 && parts[1].split('.').length > 1
186 + ? parts[1].split('.')[1].split('-')[0]
187 + : '';
188
189 final formattedToChain = CryptoCurrency.fromString(toChain);
183 - final toAssetWithChain = CryptoCurrency.fromString(toAsset, walletCurrency:formattedToChain);
190 + final toAssetWithChain = CryptoCurrency.fromString(toAsset, walletCurrency: formattedToChain);
191
192 final plannedOutTxs = responseJSON['planned_out_txs'] as List<dynamic>?;
193 final isRefund = plannedOutTxs?.any((tx) => tx['refund'] == true) ?? false;
lib/exchange/provider/trocador_exchange_provider.dart
+10 -6
@@ -13,7 +13,8 @@ import 'package:http/http.dart';
13
14 class TrocadorExchangeProvider extends ExchangeProvider {
15 TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}})
16 - : _lastUsedRateId = '', _provider = [],
16 + : _lastUsedRateId = '',
17 + _provider = [],
18 super(pairList: supportedPairs(_notSupported));
19
20 bool useTorOnly;
@@ -23,7 +24,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
24 'Swapter',
25 'StealthEx',
26 'Simpleswap',
26 - 'Swapuz'
27 + 'Swapuz',
28 'ChangeNow',
29 'Changehero',
30 'FixedFloat',
@@ -144,8 +145,11 @@ class TrocadorExchangeProvider extends ExchangeProvider {
145 }
146
147 @override
147 - Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
148 -
148 + Future<Trade> createTrade({
149 + required TradeRequest request,
150 + required bool isFixedRateMode,
151 + required bool isSendAll,
152 + }) async {
153 final params = {
154 'api_key': apiKey,
155 'ticker_from': _normalizeCurrency(request.fromCurrency),
@@ -172,7 +176,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
176 params['id'] = _lastUsedRateId;
177 }
178
175 -
179 String firstAvailableProvider = '';
180
181 for (var provider in _provider) {
@@ -225,7 +228,8 @@ class TrocadorExchangeProvider extends ExchangeProvider {
228 providerName: providerName,
229 createdAt: DateTime.tryParse(date)?.toLocal(),
230 amount: responseJSON['amount_from']?.toString() ?? request.fromAmount,
228 - payoutAddress: payoutAddress);
231 + payoutAddress: payoutAddress,
232 + isSendAll: isSendAll);
233 }
234
235 @override
lib/exchange/trade.dart
+8 -3
@@ -31,6 +31,7 @@ class Trade extends HiveObject {
31 this.memo,
32 this.txId,
33 this.isRefund,
34 + this.isSendAll,
35 }) {
36 if (provider != null) providerRaw = provider.raw;
37
@@ -117,6 +118,9 @@ class Trade extends HiveObject {
118 @HiveField(20)
119 bool? isRefund;
120
121 + @HiveField(21)
122 + bool? isSendAll;
123 +
124 static Trade fromMap(Map<String, Object?> map) {
125 return Trade(
126 id: map['id'] as String,
@@ -130,8 +134,8 @@ class Trade extends HiveObject {
134 fromWalletAddress: map['from_wallet_address'] as String?,
135 memo: map['memo'] as String?,
136 txId: map['tx_id'] as String?,
133 - isRefund: map['isRefund'] as bool?
134 - );
137 + isRefund: map['isRefund'] as bool?,
138 + isSendAll: map['isSendAll'] as bool?);
139 }
140
141 Map<String, dynamic> toMap() {
@@ -146,7 +150,8 @@ class Trade extends HiveObject {
150 'from_wallet_address': fromWalletAddress,
151 'memo': memo,
152 'tx_id': txId,
149 - 'isRefund': isRefund
153 + 'isRefund': isRefund,
154 + 'isSendAll': isSendAll,
155 };
156 }
157
lib/src/screens/exchange/exchange_page.dart
+8 -2
@@ -186,7 +186,13 @@ class ExchangePage extends BasePage {
186 StandardCheckbox(
187 value: exchangeViewModel.isFixedRateMode,
188 caption: S.of(context).fixed_rate,
189 - onChanged: (value) => exchangeViewModel.isFixedRateMode = value,
189 + onChanged: (value) {
190 + if (value) {
191 + exchangeViewModel.enableFixedRateMode();
192 + } else {
193 + exchangeViewModel.isFixedRateMode = false;
194 + }
195 + },
196 ),
197 ],
198 )),
@@ -528,7 +534,7 @@ class ExchangePage extends BasePage {
534
535 _receiveAmountFocus.addListener(() {
536 if (_receiveAmountFocus.hasFocus) {
531 - exchangeViewModel.isFixedRateMode = true;
537 + exchangeViewModel.enableFixedRateMode();
538 }
539 // exchangeViewModel.changeReceiveAmount(amount: receiveAmountController.text);
540 });
lib/src/screens/exchange_trade/exchange_trade_page.dart
+1
@@ -262,6 +262,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
262 fee: S.of(popupContext).send_fee,
263 feeValue: widget.exchangeTradeViewModel.sendViewModel
264 .pendingTransaction!.feeFormatted,
265 + feeRate: widget.exchangeTradeViewModel.sendViewModel.pendingTransaction!.feeRate,
266 rightButtonText: S.of(popupContext).send,
267 leftButtonText: S.of(popupContext).cancel,
268 actionRightButton: () async {
lib/src/screens/send/send_page.dart
+1
@@ -426,6 +426,7 @@ class SendPage extends BasePage {
426 fee: isEVMCompatibleChain(sendViewModel.walletType)
427 ? S.of(_dialogContext).send_estimated_fee
428 : S.of(_dialogContext).send_fee,
429 + feeRate: sendViewModel.pendingTransaction!.feeRate,
430 feeValue: sendViewModel.pendingTransaction!.feeFormatted,
431 feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
432 outputs: sendViewModel.outputs,
lib/src/screens/send/widgets/confirm_sending_alert.dart
+39 -1
@@ -16,6 +16,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
16 required this.amountValue,
17 required this.fiatAmountValue,
18 required this.fee,
19 + this.feeRate,
20 required this.feeValue,
21 required this.feeFiatAmount,
22 required this.outputs,
@@ -36,6 +37,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
37 final String amountValue;
38 final String fiatAmountValue;
39 final String fee;
40 + final String? feeRate;
41 final String feeValue;
42 final String feeFiatAmount;
43 final List<Output> outputs;
@@ -90,6 +92,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
92 amountValue: amountValue,
93 fiatAmountValue: fiatAmountValue,
94 fee: fee,
95 + feeRate: feeRate,
96 feeValue: feeValue,
97 feeFiatAmount: feeFiatAmount,
98 outputs: outputs);
@@ -103,6 +106,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
106 required this.amountValue,
107 required this.fiatAmountValue,
108 required this.fee,
109 + this.feeRate,
110 required this.feeValue,
111 required this.feeFiatAmount,
112 required this.outputs});
@@ -113,6 +117,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
117 final String amountValue;
118 final String fiatAmountValue;
119 final String fee;
120 + final String? feeRate;
121 final String feeValue;
122 final String feeFiatAmount;
123 final List<Output> outputs;
@@ -125,6 +130,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
130 amountValue: amountValue,
131 fiatAmountValue: fiatAmountValue,
132 fee: fee,
133 + feeRate: feeRate,
134 feeValue: feeValue,
135 feeFiatAmount: feeFiatAmount,
136 outputs: outputs);
@@ -138,6 +144,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
144 required this.amountValue,
145 required this.fiatAmountValue,
146 required this.fee,
147 + this.feeRate,
148 required this.feeValue,
149 required this.feeFiatAmount,
150 required this.outputs})
@@ -153,6 +160,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
160 final String amountValue;
161 final String fiatAmountValue;
162 final String fee;
163 + final String? feeRate;
164 final String feeValue;
165 final String feeFiatAmount;
166 final List<Output> outputs;
@@ -183,7 +191,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
191
192 return Stack(alignment: Alignment.center, clipBehavior: Clip.none, children: [
193 Container(
186 - height: 200,
194 + height: feeRate != null ? 250 : 200,
195 child: SingleChildScrollView(
196 controller: controller,
197 child: Column(
@@ -311,6 +319,36 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
319 )
320 ],
321 )),
322 + if (feeRate != null && feeRate!.isNotEmpty)
323 + Padding(
324 + padding: EdgeInsets.only(top: 16),
325 + child: Row(
326 + mainAxisSize: MainAxisSize.max,
327 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
328 + crossAxisAlignment: CrossAxisAlignment.start,
329 + children: <Widget>[
330 + Text(
331 + S.current.send_estimated_fee,
332 + style: TextStyle(
333 + fontSize: 16,
334 + fontWeight: FontWeight.normal,
335 + fontFamily: 'Lato',
336 + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
337 + decoration: TextDecoration.none,
338 + ),
339 + ),
340 + Text(
341 + "$feeRate sat/byte",
342 + style: TextStyle(
343 + fontSize: 18,
344 + fontWeight: FontWeight.w600,
345 + fontFamily: 'Lato',
346 + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
347 + decoration: TextDecoration.none,
348 + ),
349 + )
350 + ],
351 + )),
352 Padding(
353 padding: EdgeInsets.only(top: 16),
354 child: Column(
lib/src/screens/unspent_coins/unspent_coins_list_page.dart
+1 -4
@@ -46,9 +46,6 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
46 itemBuilder: (_, int index) {
47 return Observer(builder: (_) {
48 final item = unspentCoinsListViewModel.items[index];
49 - final address = unspentCoinsListViewModel.wallet.type == WalletType.bitcoinCash
50 - ? bitcoinCash!.getCashAddrFormat(item.address)
51 - : item.address;
49
50 return GestureDetector(
51 onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsDetails,
@@ -56,7 +53,7 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
53 child: UnspentCoinsListItem(
54 note: item.note,
55 amount: item.amount,
59 - address: address,
56 + address: item.address,
57 isSending: item.isSending,
58 isFrozen: item.isFrozen,
59 isChange: item.isChange,
lib/view_model/contact_list/contact_list_view_model.dart
+2
@@ -46,6 +46,8 @@ abstract class ContactListViewModelBase with Store {
46 name,
47 walletTypeToCryptoCurrency(info.type),
48 ));
49 + // Only one contact address per wallet
50 + return;
51 });
52 } else if (info.address != null) {
53 walletContacts.add(WalletContact(
lib/view_model/exchange/exchange_trade_view_model.dart
+8 -3
@@ -105,6 +105,7 @@ abstract class ExchangeTradeViewModelBase with Store {
105 output.address = trade.inputAddress ?? '';
106 output.setCryptoAmount(trade.amount);
107 if (_provider is ThorChainExchangeProvider) output.memo = trade.memo;
108 + if (trade.isSendAll == true) output.sendAll = true;
109 sendViewModel.selectedCryptoCurrency = trade.from;
110 final pendingTransaction = await sendViewModel.createTransaction(provider: _provider);
111 if (_provider is ThorChainExchangeProvider) {
@@ -116,6 +117,8 @@ abstract class ExchangeTradeViewModelBase with Store {
117 @action
118 Future<void> _updateTrade() async {
119 try {
120 + final agreedAmount = tradesStore.trade!.amount;
121 + final isSendAll = tradesStore.trade!.isSendAll;
122 final updatedTrade = await _provider!.findTradeById(id: trade.id);
123
124 if (updatedTrade.createdAt == null && trade.createdAt != null)
@@ -124,6 +127,8 @@ abstract class ExchangeTradeViewModelBase with Store {
127 if (updatedTrade.amount.isEmpty) updatedTrade.amount = trade.amount;
128
129 trade = updatedTrade;
130 + trade.amount = agreedAmount;
131 + trade.isSendAll = isSendAll;
132
133 _updateItems();
134 } catch (e) {
@@ -137,9 +142,9 @@ abstract class ExchangeTradeViewModelBase with Store {
142 final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : '';
143 items.clear();
144
140 - if(trade.provider != ExchangeProviderDescription.thorChain)
141 - items.add(ExchangeTradeItem(
142 - title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true));
145 + if (trade.provider != ExchangeProviderDescription.thorChain)
146 + items.add(ExchangeTradeItem(
147 + title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true));
148
149 if (trade.extraId != null) {
150 final title = trade.from == CryptoCurrency.xrp
lib/view_model/exchange/exchange_view_model.dart
+28 -14
@@ -470,6 +470,18 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
470
471 @action
472 Future<void> createTrade() async {
473 + if (isSendAllEnabled) {
474 + await calculateDepositAllAmount();
475 + final amount = double.tryParse(depositAmount);
476 +
477 + if (limits.min != null && amount != null && amount < limits.min!) {
478 + tradeState = TradeIsCreatedFailure(
479 + title: S.current.trade_not_created,
480 + error: S.current.amount_is_below_minimum_limit(limits.min!.toString()));
481 + return;
482 + }
483 + }
484 +
485 try {
486 for (var provider in _sortedAvailableProviders.values) {
487 if (!(await provider.checkIsAvailable())) continue;
@@ -496,8 +508,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
508 else {
509 try {
510 tradeState = TradeIsCreating();
499 - final trade =
500 - await provider.createTrade(request: request, isFixedRateMode: isFixedRateMode);
511 + final trade = await provider.createTrade(
512 + request: request,
513 + isFixedRateMode: isFixedRateMode,
514 + isSendAll: isSendAllEnabled,
515 + );
516 trade.walletId = wallet.id;
517 trade.fromWalletAddress = wallet.walletAddresses.address;
518
@@ -551,25 +566,24 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
566 @action
567 void enableSendAllAmount() {
568 isSendAllEnabled = true;
569 + isFixedRateMode = false;
570 calculateDepositAllAmount();
571 }
572
573 @action
558 - Future<void> calculateDepositAllAmount() async {
559 - if (wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) {
560 - final availableBalance = wallet.balance[wallet.currency]!.available;
561 - final priority = _settingsStore.priority[wallet.type]!;
562 - final fee = wallet.calculateEstimatedFee(priority, null);
563 -
564 - if (availableBalance < fee || availableBalance == 0) return;
574 + void enableFixedRateMode() {
575 + isSendAllEnabled = false;
576 + isFixedRateMode = true;
577 + }
578
566 - final amount = availableBalance - fee;
567 - changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
568 - } else if (wallet.type == WalletType.bitcoin) {
579 + @action
580 + Future<void> calculateDepositAllAmount() async {
581 + if (wallet.type == WalletType.litecoin ||
582 + wallet.type == WalletType.bitcoin ||
583 + wallet.type == WalletType.bitcoinCash) {
584 final priority = _settingsStore.priority[wallet.type]!;
585
571 - final amount = await bitcoin!.estimateFakeSendAllTxAmount(
572 - wallet, bitcoin!.deserializeBitcoinTransactionPriority(priority.raw));
586 + final amount = await bitcoin!.estimateFakeSendAllTxAmount(wallet, priority);
587
588 changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
589 }
lib/view_model/send/send_view_model.dart
+48 -15
@@ -14,6 +14,7 @@ import 'package:cake_wallet/solana/solana.dart';
14 import 'package:cake_wallet/store/app_store.dart';
15 import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
16 import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
17 +import 'package:cw_core/exceptions.dart';
18 import 'package:cw_core/transaction_priority.dart';
19 import 'package:cake_wallet/view_model/send/output.dart';
20 import 'package:cake_wallet/view_model/send/send_template_view_model.dart';
@@ -309,9 +310,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
310 state = ExecutedSuccessfullyState();
311 return pendingTransaction;
312 } catch (e) {
312 - print('Failed with ${e.toString()}');
313 - state = FailureState(e.toString());
314 - return null;
313 + state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency));
314 }
315 }
316
@@ -353,8 +352,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
352
353 state = TransactionCommitted();
354 } catch (e) {
356 - String translatedError = translateErrorMessage(e.toString(), wallet.type, wallet.currency);
357 - state = FailureState(translatedError);
355 + state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency));
356 }
357 }
358
@@ -429,11 +427,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
427 }
428 }
429
432 - ContactRecord? newContactAddress () {
433 -
430 + ContactRecord? newContactAddress() {
431 final Set<String> contactAddresses =
435 - Set.from(contactListViewModel.contacts.map((contact) => contact.address))
436 - ..addAll(contactListViewModel.walletContacts.map((contact) => contact.address));
432 + Set.from(contactListViewModel.contacts.map((contact) => contact.address))
433 + ..addAll(contactListViewModel.walletContacts.map((contact) => contact.address));
434
435 for (var output in outputs) {
436 String address;
@@ -444,7 +441,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
441 }
442
443 if (address.isNotEmpty && !contactAddresses.contains(address)) {
447 -
444 return ContactRecord(
445 contactListViewModel.contactSource,
446 Contact(
@@ -458,22 +454,59 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
454 }
455
456 String translateErrorMessage(
461 - String error,
457 + Object error,
458 WalletType walletType,
459 CryptoCurrency currency,
460 ) {
461 + String errorMessage = error.toString();
462 +
463 if (walletType == WalletType.ethereum ||
464 walletType == WalletType.polygon ||
465 walletType == WalletType.solana ||
466 walletType == WalletType.haven) {
469 - if (error.contains('gas required exceeds allowance') ||
470 - error.contains('insufficient funds')) {
467 + if (errorMessage.contains('gas required exceeds allowance') ||
468 + errorMessage.contains('insufficient funds')) {
469 return S.current.do_not_have_enough_gas_asset(currency.toString());
470 }
471
474 - return error;
472 + return errorMessage;
473 + }
474 +
475 + if (walletType == WalletType.bitcoin ||
476 + walletType == WalletType.litecoin ||
477 + walletType == WalletType.bitcoinCash) {
478 + if (error is TransactionWrongBalanceException) {
479 + return S.current.tx_wrong_balance_exception(currency.toString());
480 + }
481 + if (error is TransactionNoInputsException) {
482 + return S.current.tx_not_enough_inputs_exception;
483 + }
484 + if (error is TransactionNoFeeException) {
485 + return S.current.tx_zero_fee_exception;
486 + }
487 + if (error is TransactionNoDustException) {
488 + return S.current.tx_no_dust_exception;
489 + }
490 + if (error is TransactionCommitFailed) {
491 + return S.current.tx_commit_failed;
492 + }
493 + if (error is TransactionCommitFailedDustChange) {
494 + return S.current.tx_rejected_dust_change;
495 + }
496 + if (error is TransactionCommitFailedDustOutput) {
497 + return S.current.tx_rejected_dust_output;
498 + }
499 + if (error is TransactionCommitFailedDustOutputSendAll) {
500 + return S.current.tx_rejected_dust_output_send_all;
501 + }
502 + if (error is TransactionCommitFailedVoutNegative) {
503 + return S.current.tx_rejected_vout_negative;
504 + }
505 + if (error is TransactionNoDustOnChangeException) {
506 + return S.current.tx_commit_exception_no_dust_on_change(error.min, error.max);
507 + }
508 }
509
477 - return error;
510 + return errorMessage;
511 }
512 }
lib/view_model/unspent_coins/unspent_coins_details_view_model.dart
+1 -3
@@ -100,7 +100,5 @@ abstract class UnspentCoinsDetailsViewModelBase with Store {
100 final WalletType _type;
101 List<TransactionDetailsListItem> items;
102
103 - String get formattedAddress => WalletType.bitcoinCash == _type
104 - ? bitcoinCash!.getCashAddrFormat(unspentCoinsItem.address)
105 - : unspentCoinsItem.address;
103 + String get formattedAddress => unspentCoinsItem.address;
104 }
res/values/strings_ar.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "لديك حساب؟",
44 "always": "دائماً",
45 "amount": "مقدار:",
46 + "amount_is_below_minimum_limit": "سيكون رصيدك بعد الرسوم أقل من الحد الأدنى للمبلغ اللازم للتبادل (${min})",
47 "amount_is_estimate": "المبلغ المستلم هو تقدير",
48 "amount_is_guaranteed": "مبلغ الاستلام مضمون",
49 "and": "و",
@@ -712,6 +713,16 @@
713 "transactions": "المعاملات",
714 "transactions_by_date": "المعاملات حسب التاريخ",
715 "trusted": "موثوق به",
716 + "tx_commit_exception_no_dust_on_change": "يتم رفض المعاملة مع هذا المبلغ. باستخدام هذه العملات المعدنية ، يمكنك إرسال ${min} دون تغيير أو ${max} الذي يعيد التغيير.",
717 + "tx_commit_failed": "فشل ارتكاب المعاملة. يرجى الاتصال بالدعم.",
718 + "tx_no_dust_exception": "يتم رفض المعاملة عن طريق إرسال مبلغ صغير جدًا. يرجى محاولة زيادة المبلغ.",
719 + "tx_not_enough_inputs_exception": "لا يكفي المدخلات المتاحة. الرجاء تحديد المزيد تحت التحكم في العملة",
720 + "tx_rejected_dust_change": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، ومبلغ التغيير المنخفض (الغبار). حاول إرسال كل أو تقليل المبلغ.",
721 + "tx_rejected_dust_output": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، وكمية الإخراج المنخفض (الغبار). يرجى زيادة المبلغ.",
722 + "tx_rejected_dust_output_send_all": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، وكمية الإخراج المنخفض (الغبار). يرجى التحقق من رصيد العملات المعدنية المحددة تحت التحكم في العملة.",
723 + "tx_rejected_vout_negative": "لا يوجد ما يكفي من الرصيد لدفع رسوم هذه الصفقة. يرجى التحقق من رصيد العملات المعدنية تحت السيطرة على العملة.",
724 + "tx_wrong_balance_exception": "ليس لديك ما يكفي من ${currency} لإرسال هذا المبلغ.",
725 + "tx_zero_fee_exception": "لا يمكن إرسال معاملة مع 0 رسوم. حاول زيادة المعدل أو التحقق من اتصالك للحصول على أحدث التقديرات.",
726 "unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ",
727 "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ",
728 "unconfirmed": "رصيد غير مؤكد",
res/values/strings_bg.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Вече имате профил?",
44 "always": "Винаги",
45 "amount": "Сума: ",
46 + "amount_is_below_minimum_limit": "Вашето салдо след такси ще бъде по -малко от минималната сума, необходима за борсата (${min})",
47 "amount_is_estimate": "Сумата за получаване е ",
48 "amount_is_guaranteed": "Сумата за получаване е гарантирана",
49 "and": "и",
@@ -712,6 +713,16 @@
713 "transactions": "Транзакции",
714 "transactions_by_date": "Транзакции по дата",
715 "trusted": "Надежден",
716 + "tx_commit_exception_no_dust_on_change": "Сделката се отхвърля с тази сума. С тези монети можете да изпратите ${min} без промяна или ${max}, която връща промяна.",
717 + "tx_commit_failed": "Компетацията на транзакцията не успя. Моля, свържете се с поддръжката.",
718 + "tx_no_dust_exception": "Сделката се отхвърля чрез изпращане на сума твърде малка. Моля, опитайте да увеличите сумата.",
719 + "tx_not_enough_inputs_exception": "Няма достатъчно налични входове. Моля, изберете повече под контрол на монети",
720 + "tx_rejected_dust_change": "Транзакция, отхвърлена от мрежови правила, ниска сума на промяна (прах). Опитайте да изпратите всички или да намалите сумата.",
721 + "tx_rejected_dust_output": "Транзакция, отхвърлена от мрежови правила, ниска стойност на изхода (прах). Моля, увеличете сумата.",
722 + "tx_rejected_dust_output_send_all": "Транзакция, отхвърлена от мрежови правила, ниска стойност на изхода (прах). Моля, проверете баланса на монетите, избрани под контрол на монети.",
723 + "tx_rejected_vout_negative": "Няма достатъчно баланс, за да платите за таксите на тази транзакция. Моля, проверете баланса на монетите под контрол на монетите.",
724 + "tx_wrong_balance_exception": "Нямате достатъчно ${currency}, за да изпратите тази сума.",
725 + "tx_zero_fee_exception": "Не може да изпраща транзакция с 0 такса. Опитайте да увеличите скоростта или да проверите връзката си за най -новите оценки.",
726 "unavailable_balance": "Неналично салдо",
727 "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.",
728 "unconfirmed": "Непотвърден баланс",
res/values/strings_cs.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Máte už účet?",
44 "always": "Vždy",
45 "amount": "Částka: ",
46 + "amount_is_below_minimum_limit": "Váš zůstatek po poplatcích by byl menší než minimální částka potřebná pro burzu (${min})",
47 "amount_is_estimate": "Částka, kterou dostanete, je jen odhad.",
48 "amount_is_guaranteed": "Částka, kterou dostanete, je konečná",
49 "and": "a",
@@ -712,6 +713,16 @@
713 "transactions": "Transakce",
714 "transactions_by_date": "Transakce podle data",
715 "trusted": "Důvěřovat",
716 + "tx_commit_exception_no_dust_on_change": "Transakce je zamítnuta s touto částkou. S těmito mincemi můžete odeslat ${min} bez změny nebo ${max}, které se vrátí změna.",
717 + "tx_commit_failed": "Transakce COMPORT selhala. Kontaktujte prosím podporu.",
718 + "tx_no_dust_exception": "Transakce je zamítnuta odesláním příliš malé. Zkuste prosím zvýšit částku.",
719 + "tx_not_enough_inputs_exception": "Není k dispozici dostatek vstupů. Vyberte prosím více pod kontrolou mincí",
720 + "tx_rejected_dust_change": "Transakce zamítnuta podle síťových pravidel, množství nízké změny (prach). Zkuste odeslat vše nebo snížit částku.",
721 + "tx_rejected_dust_output": "Transakce zamítnuta síťovými pravidly, nízkým množstvím výstupu (prach). Zvyšte prosím částku.",
722 + "tx_rejected_dust_output_send_all": "Transakce zamítnuta síťovými pravidly, nízkým množstvím výstupu (prach). Zkontrolujte prosím zůstatek mincí vybraných pod kontrolou mincí.",
723 + "tx_rejected_vout_negative": "Nedostatek zůstatek na zaplacení poplatků za tuto transakci. Zkontrolujte prosím zůstatek mincí pod kontrolou mincí.",
724 + "tx_wrong_balance_exception": "Nemáte dost ${currency} pro odeslání této částky.",
725 + "tx_zero_fee_exception": "Nelze odeslat transakci s 0 poplatkem. Zkuste zvýšit sazbu nebo zkontrolovat připojení pro nejnovější odhady.",
726 "unavailable_balance": "Nedostupný zůstatek",
727 "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.",
728 "unconfirmed": "Nepotvrzený zůstatek",
res/values/strings_de.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Sie haben bereits ein Konto?",
44 "always": "immer",
45 "amount": "Betrag: ",
46 + "amount_is_below_minimum_limit": "Ihr Saldo nach Gebühren wäre geringer als der für den Austausch benötigte Mindestbetrag (${min})",
47 "amount_is_estimate": "Der empfangene Betrag ist eine Schätzung",
48 "amount_is_guaranteed": "Der Empfangsbetrag ist garantiert",
49 "and": "Und",
@@ -713,6 +714,16 @@
714 "transactions": "Transaktionen",
715 "transactions_by_date": "Transaktionen nach Datum",
716 "trusted": "Vertrauenswürdige",
717 + "tx_commit_exception_no_dust_on_change": "Die Transaktion wird diesen Betrag abgelehnt. Mit diesen Münzen können Sie ${min} ohne Veränderung oder ${max} senden, die Änderungen zurückgeben.",
718 + "tx_commit_failed": "Transaktionsausschüsse ist fehlgeschlagen. Bitte wenden Sie sich an Support.",
719 + "tx_no_dust_exception": "Die Transaktion wird abgelehnt, indem eine Menge zu klein gesendet wird. Bitte versuchen Sie, die Menge zu erhöhen.",
720 + "tx_not_enough_inputs_exception": "Nicht genügend Eingänge verfügbar. Bitte wählen Sie mehr unter Münzkontrolle aus",
721 + "tx_rejected_dust_change": "Transaktion abgelehnt durch Netzwerkregeln, niedriger Änderungsbetrag (Staub). Versuchen Sie, alle zu senden oder die Menge zu reduzieren.",
722 + "tx_rejected_dust_output": "Transaktion durch Netzwerkregeln, niedriger Ausgangsmenge (Staub) abgelehnt. Bitte erhöhen Sie den Betrag.",
723 + "tx_rejected_dust_output_send_all": "Transaktion durch Netzwerkregeln, niedriger Ausgangsmenge (Staub) abgelehnt. Bitte überprüfen Sie den Gleichgewicht der unter Münzkontrolle ausgewählten Münzen.",
724 + "tx_rejected_vout_negative": "Nicht genug Guthaben, um die Gebühren dieser Transaktion zu bezahlen. Bitte überprüfen Sie den Restbetrag der Münzen unter Münzkontrolle.",
725 + "tx_wrong_balance_exception": "Sie haben nicht genug ${currency}, um diesen Betrag zu senden.",
726 + "tx_zero_fee_exception": "Transaktion kann nicht mit 0 Gebühren gesendet werden. Versuchen Sie, die Rate zu erhöhen oder Ihre Verbindung auf die neuesten Schätzungen zu überprüfen.",
727 "unavailable_balance": "Nicht verfügbares Guthaben",
728 "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.",
729 "unconfirmed": "Unbestätigter Saldo",
res/values/strings_en.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Already have an account?",
44 "always": "Always",
45 "amount": "Amount: ",
46 + "amount_is_below_minimum_limit": "Your balance after fees would be less than the minimum amount needed for the exchange (${min})",
47 "amount_is_estimate": "The receive amount is an estimate",
48 "amount_is_guaranteed": "The receive amount is guaranteed",
49 "and": "and",
@@ -712,6 +713,16 @@
713 "transactions": "Transactions",
714 "transactions_by_date": "Transactions by date",
715 "trusted": "Trusted",
716 + "tx_commit_exception_no_dust_on_change": "The transaction is rejected with this amount. With these coins you can send ${min} without change or ${max} that returns change.",
717 + "tx_commit_failed": "Transaction commit failed. Please contact support.",
718 + "tx_no_dust_exception": "The transaction is rejected by sending an amount too small. Please try increasing the amount.",
719 + "tx_not_enough_inputs_exception": "Not enough inputs available. Please select more under Coin Control",
720 + "tx_rejected_dust_change": "Transaction rejected by network rules, low change amount (dust). Try sending ALL or reducing the amount.",
721 + "tx_rejected_dust_output": "Transaction rejected by network rules, low output amount (dust). Please increase the amount.",
722 + "tx_rejected_dust_output_send_all": "Transaction rejected by network rules, low output amount (dust). Please check the balance of coins selected under Coin Control.",
723 + "tx_rejected_vout_negative": "Not enough balance to pay for this transaction's fees. Please check the balance of coins under Coin Control.",
724 + "tx_wrong_balance_exception": "You do not have enough ${currency} to send this amount.",
725 + "tx_zero_fee_exception": "Cannot send transaction with 0 fee. Try increasing the rate or checking your connection for latest estimates.",
726 "unavailable_balance": "Unavailable balance",
727 "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.",
728 "unconfirmed": "Unconfirmed Balance",
res/values/strings_es.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "¿Ya tienes una cuenta?",
44 "always": "siempre",
45 "amount": "Cantidad: ",
46 + "amount_is_below_minimum_limit": "Su saldo después de las tarifas sería menor que la cantidad mínima necesaria para el intercambio (${min})",
47 "amount_is_estimate": "El monto recibido es un estimado",
48 "amount_is_guaranteed": "La cantidad recibida está garantizada",
49 "and": "y",
@@ -713,6 +714,16 @@
714 "transactions": "Actas",
715 "transactions_by_date": "Transacciones por fecha",
716 "trusted": "de confianza",
717 + "tx_commit_exception_no_dust_on_change": "La transacción se rechaza con esta cantidad. Con estas monedas puede enviar ${min} sin cambios o ${max} que devuelve el cambio.",
718 + "tx_commit_failed": "La confirmación de transacción falló. Póngase en contacto con el soporte.",
719 + "tx_no_dust_exception": "La transacción se rechaza enviando una cantidad demasiado pequeña. Intente aumentar la cantidad.",
720 + "tx_not_enough_inputs_exception": "No hay suficientes entradas disponibles. Seleccione más bajo control de monedas",
721 + "tx_rejected_dust_change": "Transacción rechazada por reglas de red, bajo cambio de cambio (polvo). Intente enviar todo o reducir la cantidad.",
722 + "tx_rejected_dust_output": "Transacción rechazada por reglas de red, baja cantidad de salida (polvo). Aumente la cantidad.",
723 + "tx_rejected_dust_output_send_all": "Transacción rechazada por reglas de red, baja cantidad de salida (polvo). Verifique el saldo de monedas seleccionadas bajo control de monedas.",
724 + "tx_rejected_vout_negative": "No es suficiente saldo para pagar las tarifas de esta transacción. Verifique el saldo de monedas bajo control de monedas.",
725 + "tx_wrong_balance_exception": "No tiene suficiente ${currency} para enviar esta cantidad.",
726 + "tx_zero_fee_exception": "No se puede enviar transacciones con 0 tarifa. Intente aumentar la tasa o verificar su conexión para las últimas estimaciones.",
727 "unavailable_balance": "Saldo no disponible",
728 "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.",
729 "unconfirmed": "Saldo no confirmado",
res/values/strings_fr.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Vous avez déjà un compte ?",
44 "always": "toujours",
45 "amount": "Montant : ",
46 + "amount_is_below_minimum_limit": "Votre solde après les frais serait inférieur au montant minimum nécessaire à l'échange (${min})",
47 "amount_is_estimate": "Le montant reçu est estimé",
48 "amount_is_guaranteed": "Le montant reçu est garanti",
49 "and": "et",
@@ -712,6 +713,16 @@
713 "transactions": "Transactions",
714 "transactions_by_date": "Transactions par date",
715 "trusted": "de confiance",
716 + "tx_commit_exception_no_dust_on_change": "La transaction est rejetée avec ce montant. Avec ces pièces, vous pouvez envoyer ${min} sans changement ou ${max} qui renvoie le changement.",
717 + "tx_commit_failed": "La validation de la transaction a échoué. Veuillez contacter l'assistance.",
718 + "tx_no_dust_exception": "La transaction est rejetée en envoyant un montant trop faible. Veuillez essayer d'augmenter le montant.",
719 + "tx_not_enough_inputs_exception": "Pas assez d'entrées disponibles. Veuillez sélectionner plus sous Control Control",
720 + "tx_rejected_dust_change": "Transaction rejetée par les règles du réseau, montant de faible variation (poussière). Essayez d'envoyer tout ou de réduire le montant.",
721 + "tx_rejected_dust_output": "Transaction rejetée par les règles du réseau, faible quantité de sortie (poussière). Veuillez augmenter le montant.",
722 + "tx_rejected_dust_output_send_all": "Transaction rejetée par les règles du réseau, faible quantité de sortie (poussière). Veuillez vérifier le solde des pièces sélectionnées sous le contrôle des pièces de monnaie.",
723 + "tx_rejected_vout_negative": "Pas assez de solde pour payer les frais de cette transaction. Veuillez vérifier le solde des pièces sous le contrôle des pièces.",
724 + "tx_wrong_balance_exception": "Vous n'avez pas assez ${currency} pour envoyer ce montant.",
725 + "tx_zero_fee_exception": "Impossible d'envoyer une transaction avec 0 frais. Essayez d'augmenter le taux ou de vérifier votre connexion pour les dernières estimations.",
726 "unavailable_balance": "Solde indisponible",
727 "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.",
728 "unconfirmed": "Solde non confirmé",
res/values/strings_ha.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Kuna da asusu?",
44 "always": "Koyaushe",
45 "amount": "Adadi:",
46 + "amount_is_below_minimum_limit": "Daidaitarku bayan kudade zai zama ƙasa da mafi ƙarancin adadin da ake buƙata don musayar (${min}",
47 "amount_is_estimate": "Adadin da aka karɓa shine kimantawa",
48 "amount_is_guaranteed": "Adadin da aka karɓa yana da garanti",
49 "and": "kuma",
@@ -714,6 +715,16 @@
715 "transactions": "Ma'amaloli",
716 "transactions_by_date": "Ma'amaloli ta kwanan wata",
717 "trusted": "Amintacce",
718 + "tx_commit_exception_no_dust_on_change": "An ƙi ma'amala da wannan adadin. Tare da waɗannan tsabar kudi Zaka iya aika ${min}, ba tare da canji ba ko ${max} wanda ya dawo canzawa.",
719 + "tx_commit_failed": "Ma'amala ya kasa. Da fatan za a tuntuɓi goyan baya.",
720 + "tx_no_dust_exception": "An ƙi ma'amala ta hanyar aika adadin ƙarami. Da fatan za a gwada ƙara adadin.",
721 + "tx_not_enough_inputs_exception": "Bai isa ba hanyoyin da ake samu. Da fatan za selectiari a karkashin Kwarewar Coin",
722 + "tx_rejected_dust_change": "Ma'amala ta ƙi ta dokokin cibiyar sadarwa, ƙarancin canji (ƙura). Gwada aikawa da duka ko rage adadin.",
723 + "tx_rejected_dust_output": "Ma'adar da aka ƙi ta dokokin cibiyar sadarwa, ƙananan fitarwa (ƙura). Da fatan za a ƙara adadin.",
724 + "tx_rejected_dust_output_send_all": "Ma'adar da aka ƙi ta dokokin cibiyar sadarwa, ƙananan fitarwa (ƙura). Da fatan za a duba daidaiton tsabar kudi a ƙarƙashin ikon tsabar kudin.",
725 + "tx_rejected_vout_negative": "Bai isa daidai ba don biyan wannan kudin ma'amala. Da fatan za a duba daidaiton tsabar kudi a ƙarƙashin ikon tsabar kudin.",
726 + "tx_wrong_balance_exception": "Ba ku da isasshen ${currency} don aika wannan adadin.",
727 + "tx_zero_fee_exception": "Ba zai iya aika ma'amala da kuɗi 0 ba. Gwada ƙara ƙimar ko bincika haɗin ku don mahimmin ƙididdiga.",
728 "unavailable_balance": "Ma'aunin da ba ya samuwa",
729 "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.",
730 "unconfirmed": "Ba a tabbatar ba",
res/values/strings_hi.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "क्या आपके पास पहले से एक खाता मौजूद है?",
44 "always": "हमेशा",
45 "amount": "रकम: ",
46 + "amount_is_below_minimum_limit": "फीस के बाद आपका संतुलन विनिमय के लिए आवश्यक न्यूनतम राशि से कम होगा (${min})",
47 "amount_is_estimate": "प्राप्त राशि एक अनुमान है",
48 "amount_is_guaranteed": "प्राप्त राशि की गारंटी है",
49 "and": "और",
@@ -714,6 +715,16 @@
715 "transactions": "लेन-देन",
716 "transactions_by_date": "तारीख से लेन-देन",
717 "trusted": "भरोसा",
718 + "tx_commit_exception_no_dust_on_change": "लेनदेन को इस राशि से खारिज कर दिया जाता है। इन सिक्कों के साथ आप चेंज या ${min} के बिना ${max} को भेज सकते हैं जो परिवर्तन लौटाता है।",
719 + "tx_commit_failed": "लेन -देन प्रतिबद्ध विफल। कृपया संपर्क समर्थन करें।",
720 + "tx_no_dust_exception": "लेनदेन को बहुत छोटी राशि भेजकर अस्वीकार कर दिया जाता है। कृपया राशि बढ़ाने का प्रयास करें।",
721 + "tx_not_enough_inputs_exception": "पर्याप्त इनपुट उपलब्ध नहीं है। कृपया सिक्का नियंत्रण के तहत अधिक चुनें",
722 + "tx_rejected_dust_change": "नेटवर्क नियमों, कम परिवर्तन राशि (धूल) द्वारा खारिज किए गए लेनदेन। सभी भेजने या राशि को कम करने का प्रयास करें।",
723 + "tx_rejected_dust_output": "नेटवर्क नियमों, कम आउटपुट राशि (धूल) द्वारा खारिज किए गए लेनदेन। कृपया राशि बढ़ाएं।",
724 + "tx_rejected_dust_output_send_all": "नेटवर्क नियमों, कम आउटपुट राशि (धूल) द्वारा खारिज किए गए लेनदेन। कृपया सिक्का नियंत्रण के तहत चुने गए सिक्कों के संतुलन की जाँच करें।",
725 + "tx_rejected_vout_negative": "इस लेनदेन की फीस के लिए भुगतान करने के लिए पर्याप्त शेष राशि नहीं है। कृपया सिक्के नियंत्रण के तहत सिक्कों के संतुलन की जाँच करें।",
726 + "tx_wrong_balance_exception": "इस राशि को भेजने के लिए आपके पास पर्याप्त ${currency} नहीं है।",
727 + "tx_zero_fee_exception": "0 शुल्क के साथ लेनदेन नहीं भेज सकते। नवीनतम अनुमानों के लिए दर बढ़ाने या अपने कनेक्शन की जांच करने का प्रयास करें।",
728 "unavailable_balance": "अनुपलब्ध शेष",
729 "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।",
730 "unconfirmed": "अपुष्ट शेष राशि",
res/values/strings_hr.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Već imate račun?",
44 "always": "Uvijek",
45 "amount": "Iznos: ",
46 + "amount_is_below_minimum_limit": "Vaša bilanca nakon naknada bila bi manja od minimalnog iznosa potrebnog za razmjenu (${min})",
47 "amount_is_estimate": "Iznos koji ćete primiti je okviran",
48 "amount_is_guaranteed": "Iznos koji ćete primiti je zajamčen",
49 "and": "i",
@@ -712,6 +713,16 @@
713 "transactions": "Transakcije",
714 "transactions_by_date": "Transakcije prema datumu",
715 "trusted": "vjerovao",
716 + "tx_commit_exception_no_dust_on_change": "Transakcija se odbija s tim iznosom. Pomoću ovih kovanica možete poslati ${min} bez promjene ili ${max} koja vraća promjenu.",
717 + "tx_commit_failed": "Obveza transakcije nije uspjela. Molimo kontaktirajte podršku.",
718 + "tx_no_dust_exception": "Transakcija se odbija slanjem iznosa premalo. Pokušajte povećati iznos.",
719 + "tx_not_enough_inputs_exception": "Nema dovoljno unosa. Molimo odaberite više pod kontrolom novčića",
720 + "tx_rejected_dust_change": "Transakcija odbijena mrežnim pravilima, niska količina promjene (prašina). Pokušajte poslati sve ili smanjiti iznos.",
721 + "tx_rejected_dust_output": "Transakcija odbijena mrežnim pravilima, niska količina izlaza (prašina). Molimo povećajte iznos.",
722 + "tx_rejected_dust_output_send_all": "Transakcija odbijena mrežnim pravilima, niska količina izlaza (prašina). Molimo provjerite ravnotežu kovanica odabranih pod kontrolom novčića.",
723 + "tx_rejected_vout_negative": "Nema dovoljno salda za plaćanje naknada ove transakcije. Molimo provjerite ravnotežu kovanica pod kontrolom novčića.",
724 + "tx_wrong_balance_exception": "Nemate dovoljno ${currency} da biste poslali ovaj iznos.",
725 + "tx_zero_fee_exception": "Ne mogu poslati transakciju s 0 naknade. Pokušajte povećati stopu ili provjeriti vezu za najnovije procjene.",
726 "unavailable_balance": "Nedostupno stanje",
727 "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.",
728 "unconfirmed": "Nepotvrđeno stanje",
res/values/strings_id.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Sudah punya akun?",
44 "always": "Selalu",
45 "amount": "Jumlah: ",
46 + "amount_is_below_minimum_limit": "Saldo Anda setelah biaya akan kurang dari jumlah minimum yang dibutuhkan untuk pertukaran (${min})",
47 "amount_is_estimate": "Jumlah penerimaan diperkirakan",
48 "amount_is_guaranteed": "Jumlah penerimaan dijamin",
49 "and": "dan",
@@ -715,6 +716,16 @@
716 "transactions": "Transaksi",
717 "transactions_by_date": "Transaksi berdasarkan tanggal",
718 "trusted": "Dipercayai",
719 + "tx_commit_exception_no_dust_on_change": "Transaksi ditolak dengan jumlah ini. Dengan koin ini Anda dapat mengirim ${min} tanpa perubahan atau ${max} yang mengembalikan perubahan.",
720 + "tx_commit_failed": "Transaksi Gagal. Silakan hubungi Dukungan.",
721 + "tx_no_dust_exception": "Transaksi ditolak dengan mengirimkan jumlah yang terlalu kecil. Silakan coba tingkatkan jumlahnya.",
722 + "tx_not_enough_inputs_exception": "Tidak cukup input yang tersedia. Pilih lebih banyak lagi di bawah Kontrol Koin",
723 + "tx_rejected_dust_change": "Transaksi ditolak oleh aturan jaringan, jumlah perubahan rendah (debu). Coba kirim semua atau mengurangi jumlahnya.",
724 + "tx_rejected_dust_output": "Transaksi ditolak oleh aturan jaringan, jumlah output rendah (debu). Harap tingkatkan jumlahnya.",
725 + "tx_rejected_dust_output_send_all": "Transaksi ditolak oleh aturan jaringan, jumlah output rendah (debu). Silakan periksa saldo koin yang dipilih di bawah kontrol koin.",
726 + "tx_rejected_vout_negative": "Tidak cukup saldo untuk membayar biaya transaksi ini. Silakan periksa saldo koin di bawah kendali koin.",
727 + "tx_wrong_balance_exception": "Anda tidak memiliki cukup ${currency} untuk mengirim jumlah ini.",
728 + "tx_zero_fee_exception": "Tidak dapat mengirim transaksi dengan biaya 0. Coba tingkatkan tarif atau periksa koneksi Anda untuk perkiraan terbaru.",
729 "unavailable_balance": "Saldo tidak tersedia",
730 "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.",
731 "unconfirmed": "Saldo Belum Dikonfirmasi",
res/values/strings_it.arb
+11
@@ -43,6 +43,7 @@
43 "already_have_account": "Hai già un account?",
44 "always": "sempre",
45 "amount": "Ammontare: ",
46 + "amount_is_below_minimum_limit": "Il saldo dopo le commissioni sarebbe inferiore all'importo minimo necessario per lo scambio (${min})",
47 "amount_is_estimate": "L'ammontare da ricevere è una stima",
48 "amount_is_guaranteed": "L'ammontare da ricevere è fisso",
49 "and": "e",
@@ -714,6 +715,16 @@
715 "transactions": "Transazioni",
716 "transactions_by_date": "Transazioni per data",
717 "trusted": "di fiducia",
718 + "tx_commit_exception_no_dust_on_change": "La transazione viene respinta con questo importo. Con queste monete è possibile inviare ${min} senza modifiche o ${max} che restituisce il cambiamento.",
719 + "tx_commit_failed": "Commit di transazione non riuscita. Si prega di contattare il supporto.",
720 + "tx_no_dust_exception": "La transazione viene respinta inviando un importo troppo piccolo. Per favore, prova ad aumentare l'importo.",
721 + "tx_not_enough_inputs_exception": "Input non sufficienti disponibili. Seleziona di più sotto il controllo delle monete",
722 + "tx_rejected_dust_change": "Transazione respinta dalle regole di rete, quantità bassa variazione (polvere). Prova a inviare tutto o ridurre l'importo.",
723 + "tx_rejected_dust_output": "Transazione respinta dalle regole di rete, bassa quantità di output (polvere). Si prega di aumentare l'importo.",
724 + "tx_rejected_dust_output_send_all": "Transazione respinta dalle regole di rete, bassa quantità di output (polvere). Si prega di controllare il saldo delle monete selezionate sotto controllo delle monete.",
725 + "tx_rejected_vout_negative": "Non abbastanza saldo per pagare le commissioni di questa transazione. Si prega di controllare il saldo delle monete sotto controllo delle monete.",
726 + "tx_wrong_balance_exception": "Non hai abbastanza ${currency} per inviare questo importo.",
727 + "tx_zero_fee_exception": "Impossibile inviare transazioni con 0 tassa. Prova ad aumentare la tariffa o controlla la connessione per le ultime stime.",
728 "unavailable_balance": "Saldo non disponibile",
729 "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.",
730 "unconfirmed": "Saldo non confermato",
res/values/strings_ja.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "すでにアカウントをお持ちですか?",
44 "always": "いつも",
45 "amount": "量: ",
46 + "amount_is_below_minimum_limit": "手数料後の残高は、交換に必要な最低額(${min})よりも少なくなります",
47 "amount_is_estimate": "受け取り金額は見積もりです",
48 "amount_is_guaranteed": "受け取り金額は保証されています",
49 "and": "と",
@@ -713,6 +714,16 @@
714 "transactions": "取引",
715 "transactions_by_date": "日付ごとの取引",
716 "trusted": "信頼できる",
717 + "tx_commit_exception_no_dust_on_change": "この金額ではトランザクションは拒否されます。 これらのコインを使用すると、おつりなしの ${min} またはおつりを返す ${max} を送信できます。",
718 + "tx_commit_failed": "トランザクションコミットは失敗しました。サポートに連絡してください。",
719 + "tx_no_dust_exception": "トランザクションは、小さすぎる金額を送信することにより拒否されます。量を増やしてみてください。",
720 + "tx_not_enough_inputs_exception": "利用可能な入力が十分ではありません。コイン制御下でもっと選択してください",
721 + "tx_rejected_dust_change": "ネットワークルール、低い変更量(ほこり)によって拒否されたトランザクション。すべてを送信するか、金額を減らしてみてください。",
722 + "tx_rejected_dust_output": "ネットワークルール、低出力量(ダスト)によって拒否されたトランザクション。金額を増やしてください。",
723 + "tx_rejected_dust_output_send_all": "ネットワークルール、低出力量(ダスト)によって拒否されたトランザクション。コイン管理下で選択されたコインのバランスを確認してください。",
724 + "tx_rejected_vout_negative": "この取引の料金に支払うのに十分な残高はありません。コイン制御下のコインのバランスを確認してください。",
725 + "tx_wrong_balance_exception": "この金額を送信するのに十分な${currency}はありません。",
726 + "tx_zero_fee_exception": "0料金でトランザクションを送信できません。レートを上げて、最新の見積もりについて接続を確認してみてください。",
727 "unavailable_balance": "利用できない残高",
728 "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。",
729 "unconfirmed": "残高未確認",
@@ -790,4 +801,4 @@
801 "you_will_get": "に変換",
802 "you_will_send": "から変換",
803 "yy": "YY"
793 -}
\ No newline at end of file
804 +}
res/values/strings_ko.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "이미 계정이 있습니까?",
44 "always": "언제나",
45 "amount": "양: ",
46 + "amount_is_below_minimum_limit": "수수료 후 잔액은 Exchange (${min})에 필요한 최소 금액보다 적습니다.",
47 "amount_is_estimate": "수신 금액은 견적입니다",
48 "amount_is_guaranteed": "수령 금액이 보장됩니다.",
49 "and": "그리고",
@@ -713,6 +714,16 @@
714 "transactions": "업무",
715 "transactions_by_date": "날짜 별 거래",
716 "trusted": "신뢰할 수 있는",
717 + "tx_commit_exception_no_dust_on_change": "이 금액으로 거래가 거부되었습니다. 이 코인을 사용하면 거스름돈 없이 ${min}를 보내거나 거스름돈을 반환하는 ${max}를 보낼 수 있습니다.",
718 + "tx_commit_failed": "거래 커밋이 실패했습니다. 지원에 연락하십시오.",
719 + "tx_no_dust_exception": "너무 작은 금액을 보내면 거래가 거부됩니다. 금액을 늘리십시오.",
720 + "tx_not_enough_inputs_exception": "사용 가능한 입력이 충분하지 않습니다. 코인 컨트롤에서 더 많은 것을 선택하십시오",
721 + "tx_rejected_dust_change": "네트워크 규칙, 낮은 변경 금액 (먼지)에 의해 거부 된 거래. 전부를 보내거나 금액을 줄이십시오.",
722 + "tx_rejected_dust_output": "네트워크 규칙, 낮은 출력 금액 (먼지)에 의해 거부 된 거래. 금액을 늘리십시오.",
723 + "tx_rejected_dust_output_send_all": "네트워크 규칙, 낮은 출력 금액 (먼지)에 의해 거부 된 거래. 동전 제어에서 선택한 동전의 균형을 확인하십시오.",
724 + "tx_rejected_vout_negative": "이 거래 수수료를 지불하기에 잔액이 충분하지 않습니다. 동전 통제하에 동전의 균형을 확인하십시오.",
725 + "tx_wrong_balance_exception": "이 금액을 보내기에 충분한 ${currency}가 충분하지 않습니다.",
726 + "tx_zero_fee_exception": "0 수수료로 거래를 보낼 수 없습니다. 최신 견적에 대해서는 속도를 높이거나 연결을 확인하십시오.",
727 "unavailable_balance": "사용할 수 없는 잔액",
728 "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.",
729 "unconfirmed": "확인되지 않은 잔액",
@@ -791,4 +802,4 @@
802 "you_will_send": "다음에서 변환",
803 "YY": "YY",
804 "yy": "YY"
794 -}
\ No newline at end of file
805 +}
res/values/strings_my.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "အကောင့်ရှိပြီးသားလား?",
44 "always": "အမြဲတမ်း",
45 "amount": "ပမာဏ:",
46 + "amount_is_below_minimum_limit": "ငွေလဲလှယ်ရန်လိုအပ်သည့်အနိမ့်ဆုံးပမာဏထက်လျော့နည်းသွားပြီးသည့်နောက်ငွေလက်ကျန်ငွေပမာဏသည်ငွေလဲလှယ်မှုအတွက်လိုအပ်သည့်အနိမ့်ဆုံးပမာဏထက်နည်းသည် (${min})",
47 "amount_is_estimate": "ရရှိသည့်ပမာဏသည် ခန့်မှန်းချက်တစ်ခုဖြစ်သည်။",
48 "amount_is_guaranteed": "ရရှိသည့်ပမာဏကို အာမခံပါသည်။",
49 "and": "နှင့်",
@@ -712,6 +713,16 @@
713 "transactions": "ငွေပေးငွေယူ",
714 "transactions_by_date": "ရက်စွဲအလိုက် ငွေလွှဲမှုများ",
715 "trusted": "ယုံတယ်။",
716 + "tx_commit_exception_no_dust_on_change": "အဆိုပါငွေပေးငွေယူကဒီပမာဏနှင့်အတူပယ်ချခံရသည်။ ဤဒင်္ဂါးပြားများနှင့်အတူပြောင်းလဲမှုကိုပြန်လည်ပြောင်းလဲခြင်းသို့မဟုတ် ${min} မပါဘဲ ${max} ပေးပို့နိုင်သည်။",
717 + "tx_commit_failed": "ငွေပေးငွေယူကျူးလွန်မှုပျက်ကွက်။ ကျေးဇူးပြုပြီးပံ့ပိုးမှုဆက်သွယ်ပါ။",
718 + "tx_no_dust_exception": "ငွေပမာဏကိုသေးငယ်လွန်းသောငွေပမာဏကိုပေးပို့ခြင်းဖြင့်ပယ်ဖျက်ခြင်းကိုငြင်းပယ်သည်။ ကျေးဇူးပြုပြီးငွေပမာဏကိုတိုးမြှင့်ကြိုးစားပါ။",
719 + "tx_not_enough_inputs_exception": "အလုံအလောက်သွင်းအားစုများမလုံလောက်။ ကျေးဇူးပြုပြီးဒင်္ဂါးပြားထိန်းချုပ်မှုအောက်တွင်ပိုမိုရွေးချယ်ပါ",
720 + "tx_rejected_dust_change": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့်ပယ်ဖျက်ခြင်းသည် Network စည်းမျဉ်းစည်းကမ်းများဖြင့်ငြင်းပယ်ခြင်း, အားလုံးပေးပို့ခြင်းသို့မဟုတ်ငွေပမာဏကိုလျှော့ချကြိုးစားပါ။",
721 + "tx_rejected_dust_output": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့် ပယ်ချ. ငွေပေးချေမှုသည် output output (ဖုန်မှုန့်) ဖြင့်ပယ်ချခဲ့သည်။ ကျေးဇူးပြုပြီးငွေပမာဏကိုတိုးမြှင့်ပေးပါ။",
722 + "tx_rejected_dust_output_send_all": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့် ပယ်ချ. ငွေပေးချေမှုသည် output output (ဖုန်မှုန့်) ဖြင့်ပယ်ချခဲ့သည်။ ဒင်္ဂါးပြားထိန်းချုပ်မှုအောက်တွင်ရွေးချယ်ထားသောဒင်္ဂါးများ၏လက်ကျန်ငွေကိုစစ်ဆေးပါ။",
723 + "tx_rejected_vout_negative": "ဒီငွေပေးငွေယူရဲ့အခကြေးငွေအတွက်ပေးဆောင်ဖို့လုံလောက်တဲ့ဟန်ချက်မလုံလောက်။ ဒင်္ဂါးပြား၏လက်ကျန်ငွေလက်ကျန်ငွေကိုစစ်ဆေးပါ။",
724 + "tx_wrong_balance_exception": "ဤငွေပမာဏကိုပေးပို့ရန်သင့်တွင် ${currency} မရှိပါ။",
725 + "tx_zero_fee_exception": "0 ကြေးနှင့်အတူငွေပေးငွေယူပေးပို့လို့မရပါဘူး။ နှုန်းကိုတိုးမြှင့်ခြင်းသို့မဟုတ်နောက်ဆုံးခန့်မှန်းချက်များအတွက်သင်၏ connection ကိုစစ်ဆေးပါ။",
726 "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။",
727 "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။",
728 "unconfirmed": "အတည်မပြုနိုင်သော လက်ကျန်ငွေ",
@@ -789,4 +800,4 @@
800 "you_will_get": "သို့ပြောင်းပါ။",
801 "you_will_send": "မှပြောင်းပါ။",
802 "yy": "YY"
792 -}
\ No newline at end of file
803 +}
res/values/strings_nl.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "Heb je al een account?",
44 "always": "altijd",
45 "amount": "Bedrag: ",
46 + "amount_is_below_minimum_limit": "Uw saldo na vergoedingen zou lager zijn dan het minimale bedrag dat nodig is voor de uitwisseling (${min})",
47 "amount_is_estimate": "Het ontvangen bedrag is een schatting",
48 "amount_is_guaranteed": "Het ontvangen bedrag is gegarandeerd",
49 "and": "en",
@@ -712,6 +713,16 @@
713 "transactions": "Transacties",
714 "transactions_by_date": "Transacties op datum",
715 "trusted": "vertrouwd",
716 + "tx_commit_exception_no_dust_on_change": "De transactie wordt afgewezen met dit bedrag. Met deze munten kunt u ${min} verzenden zonder verandering of ${max} die wijziging retourneert.",
717 + "tx_commit_failed": "Transactiebewissing is mislukt. Neem contact op met de ondersteuning.",
718 + "tx_no_dust_exception": "De transactie wordt afgewezen door een te klein bedrag te verzenden. Probeer het bedrag te verhogen.",
719 + "tx_not_enough_inputs_exception": "Niet genoeg ingangen beschikbaar. Selecteer meer onder muntenbesturing",
720 + "tx_rejected_dust_change": "Transactie afgewezen door netwerkregels, laag wijzigingsbedrag (stof). Probeer alles te verzenden of het bedrag te verminderen.",
721 + "tx_rejected_dust_output": "Transactie afgewezen door netwerkregels, laag outputbedrag (stof). Verhoog het bedrag.",
722 + "tx_rejected_dust_output_send_all": "Transactie afgewezen door netwerkregels, laag outputbedrag (stof). Controleer het saldo van munten die zijn geselecteerd onder muntcontrole.",
723 + "tx_rejected_vout_negative": "Niet genoeg saldo om te betalen voor de kosten van deze transactie. Controleer het saldo van munten onder muntcontrole.",
724 + "tx_wrong_balance_exception": "Je hebt niet genoeg ${currency} om dit bedrag te verzenden.",
725 + "tx_zero_fee_exception": "Kan geen transactie verzenden met 0 kosten. Probeer het tarief te verhogen of uw verbinding te controleren op de laatste schattingen.",
726 "unavailable_balance": "Onbeschikbaar saldo",
727 "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.",
728 "unconfirmed": "Onbevestigd saldo",
@@ -790,4 +801,4 @@
801 "you_will_get": "Converteren naar",
802 "you_will_send": "Converteren van",
803 "yy": "JJ"
793 -}
\ No newline at end of file
804 +}
res/values/strings_pl.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "Masz już konto?",
44 "always": "zawsze",
45 "amount": "Ilość: ",
46 + "amount_is_below_minimum_limit": "Twoje saldo po opłatach byłoby mniejsze niż minimalna kwota potrzebna do wymiany (${min})",
47 "amount_is_estimate": "Otrzymana kwota jest wartością szacunkową",
48 "amount_is_guaranteed": "Otrzymana kwota jest gwarantowana",
49 "and": "i",
@@ -712,6 +713,16 @@
713 "transactions": "Transakcje",
714 "transactions_by_date": "Transakcje według daty",
715 "trusted": "Zaufany",
716 + "tx_commit_exception_no_dust_on_change": "Transakcja jest odrzucana z tą kwotą. Za pomocą tych monet możesz wysłać ${min} bez zmiany lub ${max}, które zwraca zmianę.",
717 + "tx_commit_failed": "Zatwierdzenie transakcji nie powiodło się. Skontaktuj się z obsługą.",
718 + "tx_no_dust_exception": "Transakcja jest odrzucana przez wysyłanie zbyt małej ilości. Spróbuj zwiększyć kwotę.",
719 + "tx_not_enough_inputs_exception": "Za mało dostępnych danych wejściowych. Wybierz więcej pod kontrolą monet",
720 + "tx_rejected_dust_change": "Transakcja odrzucona według reguł sieciowych, niska ilość zmiany (kurz). Spróbuj wysłać całość lub zmniejszyć kwotę.",
721 + "tx_rejected_dust_output": "Transakcja odrzucona według reguł sieciowych, niskiej ilości wyjściowej (pyłu). Zwiększ kwotę.",
722 + "tx_rejected_dust_output_send_all": "Transakcja odrzucona według reguł sieciowych, niskiej ilości wyjściowej (pyłu). Sprawdź saldo monet wybranych pod kontrolą monet.",
723 + "tx_rejected_vout_negative": "Za mało salda, aby zapłacić za opłaty tej transakcji. Sprawdź saldo monet pod kontrolą monet.",
724 + "tx_wrong_balance_exception": "Nie masz wystarczającej ilości ${currency}, aby wysłać tę kwotę.",
725 + "tx_zero_fee_exception": "Nie można wysłać transakcji z 0 opłatą. Spróbuj zwiększyć stawkę lub sprawdzić połączenie w poszukiwaniu najnowszych szacunków.",
726 "unavailable_balance": "Niedostępne saldo",
727 "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.",
728 "unconfirmed": "Niepotwierdzone saldo",
@@ -789,4 +800,4 @@
800 "you_will_get": "Konwertuj na",
801 "you_will_send": "Konwertuj z",
802 "yy": "RR"
792 -}
\ No newline at end of file
803 +}
res/values/strings_pt.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "Já tem uma conta?",
44 "always": "sempre",
45 "amount": "Quantia: ",
46 + "amount_is_below_minimum_limit": "Seu saldo após as taxas seria menor que o valor mínimo necessário para a troca (${min})",
47 "amount_is_estimate": "O valor a ser recebido informado acima é uma estimativa",
48 "amount_is_guaranteed": "O valor recebido é garantido",
49 "and": "e",
@@ -714,6 +715,16 @@
715 "transactions": "Transações",
716 "transactions_by_date": "Transações por data",
717 "trusted": "confiável",
718 + "tx_commit_exception_no_dust_on_change": "A transação é rejeitada com esse valor. Com essas moedas, você pode enviar ${min} sem alteração ou ${max} que retorna alterações.",
719 + "tx_commit_failed": "A confirmação da transação falhou. Entre em contato com o suporte.",
720 + "tx_no_dust_exception": "A transação é rejeitada enviando uma quantia pequena demais. Por favor, tente aumentar o valor.",
721 + "tx_not_enough_inputs_exception": "Não há entradas disponíveis. Selecione mais sob controle de moedas",
722 + "tx_rejected_dust_change": "Transação rejeitada pelas regras de rede, baixa quantidade de troco (poeira). Tente enviar tudo ou reduzir o valor.",
723 + "tx_rejected_dust_output": "Transação rejeitada por regras de rede, baixa quantidade de saída (poeira). Por favor, aumente o valor.",
724 + "tx_rejected_dust_output_send_all": "Transação rejeitada por regras de rede, baixa quantidade de saída (poeira). Por favor, verifique o saldo de moedas selecionadas sob controle de moedas.",
725 + "tx_rejected_vout_negative": "Não há saldo suficiente para pagar as taxas desta transação. Por favor, verifique o saldo de moedas sob controle de moedas.",
726 + "tx_wrong_balance_exception": "Você não tem o suficiente ${currency} para enviar esse valor.",
727 + "tx_zero_fee_exception": "Não pode enviar transação com taxa 0. Tente aumentar a taxa ou verificar sua conexão para obter as estimativas mais recentes.",
728 "unavailable_balance": "Saldo indisponível",
729 "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.",
730 "unconfirmed": "Saldo não confirmado",
@@ -792,4 +803,4 @@
803 "you_will_get": "Converter para",
804 "you_will_send": "Converter de",
805 "yy": "aa"
795 -}
\ No newline at end of file
806 +}
res/values/strings_ru.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "У вас уже есть аккаунт?",
44 "always": "всегда",
45 "amount": "Сумма: ",
46 + "amount_is_below_minimum_limit": "Ваш баланс после сборов будет меньше, чем минимальная сумма, необходимая для обмена (${min}))",
47 "amount_is_estimate": "Полученная сумма является приблизительной",
48 "amount_is_guaranteed": "Полученная сумма гарантирована",
49 "and": "и",
@@ -713,6 +714,16 @@
714 "transactions": "Транзакции",
715 "transactions_by_date": "Сортировать по дате",
716 "trusted": "доверенный",
717 + "tx_commit_exception_no_dust_on_change": "Транзакция отклоняется с этой суммой. С этими монетами вы можете отправлять ${min} без изменения или ${max}, которые возвращают изменение.",
718 + "tx_commit_failed": "Комплект транзакции не удался. Пожалуйста, свяжитесь с поддержкой.",
719 + "tx_no_dust_exception": "Транзакция отклоняется путем отправки слишком маленькой суммы. Пожалуйста, попробуйте увеличить сумму.",
720 + "tx_not_enough_inputs_exception": "Недостаточно входов доступны. Пожалуйста, выберите больше под контролем монет",
721 + "tx_rejected_dust_change": "Транзакция отклоняется в соответствии с правилами сети, низкой суммой изменений (пыль). Попробуйте отправить все или уменьшить сумму.",
722 + "tx_rejected_dust_output": "Транзакция отклоняется в соответствии с правилами сети, низкой выходной суммой (пыль). Пожалуйста, увеличьте сумму.",
723 + "tx_rejected_dust_output_send_all": "Транзакция отклоняется в соответствии с правилами сети, низкой выходной суммой (пыль). Пожалуйста, проверьте баланс монет, выбранных под контролем монет.",
724 + "tx_rejected_vout_negative": "Недостаточно баланс, чтобы оплатить плату этой транзакции. Пожалуйста, проверьте баланс монет под контролем монет.",
725 + "tx_wrong_balance_exception": "У вас не хватает ${currency}, чтобы отправить эту сумму.",
726 + "tx_zero_fee_exception": "Не может отправить транзакцию с платой 0. Попробуйте увеличить ставку или проверить соединение на наличие последних оценок.",
727 "unavailable_balance": "Недоступный баланс",
728 "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.",
729 "unconfirmed": "Неподтвержденный баланс",
@@ -790,4 +801,4 @@
801 "you_will_get": "Конвертировать в",
802 "you_will_send": "Конвертировать из",
803 "yy": "ГГ"
793 -}
\ No newline at end of file
804 +}
res/values/strings_th.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "มีบัญชีอยู่แล้ว?",
44 "always": "เสมอ",
45 "amount": "จำนวน: ",
46 + "amount_is_below_minimum_limit": "ยอดคงเหลือหลังจากค่าธรรมเนียมของคุณจะน้อยกว่าจำนวนเงินขั้นต่ำที่จำเป็นสำหรับการแลกเปลี่ยน (${min})",
47 "amount_is_estimate": "จำนวนที่จะได้รับเป็นการประมาณการ",
48 "amount_is_guaranteed": "จำนวนที่จะได้รับมีการรับประกัน",
49 "and": "และ",
@@ -712,6 +713,16 @@
713 "transactions": "ธุรกรรม",
714 "transactions_by_date": "ธุรกรรมตามวันที่",
715 "trusted": "มั่นคง",
716 + "tx_commit_exception_no_dust_on_change": "ธุรกรรมถูกปฏิเสธด้วยจำนวนเงินนี้ ด้วยเหรียญเหล่านี้คุณสามารถส่ง ${min} โดยไม่ต้องเปลี่ยนแปลงหรือ ${max} ที่ส่งคืนการเปลี่ยนแปลง",
717 + "tx_commit_failed": "การทำธุรกรรมล้มเหลว กรุณาติดต่อฝ่ายสนับสนุน",
718 + "tx_no_dust_exception": "การทำธุรกรรมถูกปฏิเสธโดยการส่งจำนวนน้อยเกินไป โปรดลองเพิ่มจำนวนเงิน",
719 + "tx_not_enough_inputs_exception": "มีอินพุตไม่เพียงพอ โปรดเลือกเพิ่มเติมภายใต้การควบคุมเหรียญ",
720 + "tx_rejected_dust_change": "ธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนการเปลี่ยนแปลงต่ำ (ฝุ่น) ลองส่งทั้งหมดหรือลดจำนวนเงิน",
721 + "tx_rejected_dust_output": "การทำธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนเอาต์พุตต่ำ (ฝุ่น) โปรดเพิ่มจำนวนเงิน",
722 + "tx_rejected_dust_output_send_all": "การทำธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนเอาต์พุตต่ำ (ฝุ่น) โปรดตรวจสอบยอดคงเหลือของเหรียญที่เลือกภายใต้การควบคุมเหรียญ",
723 + "tx_rejected_vout_negative": "ยอดคงเหลือไม่เพียงพอที่จะจ่ายสำหรับค่าธรรมเนียมการทำธุรกรรมนี้ โปรดตรวจสอบยอดคงเหลือของเหรียญภายใต้การควบคุมเหรียญ",
724 + "tx_wrong_balance_exception": "คุณมีไม่เพียงพอ ${currency} ในการส่งจำนวนนี้",
725 + "tx_zero_fee_exception": "ไม่สามารถส่งธุรกรรมด้วยค่าธรรมเนียม 0 ลองเพิ่มอัตราหรือตรวจสอบการเชื่อมต่อของคุณสำหรับการประมาณการล่าสุด",
726 "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน",
727 "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง",
728 "unconfirmed": "ยอดคงเหลือที่ไม่ได้รับการยืนยัน",
@@ -789,4 +800,4 @@
800 "you_will_get": "แปลงเป็น",
801 "you_will_send": "แปลงจาก",
802 "yy": "ปี"
792 -}
\ No newline at end of file
803 +}
res/values/strings_tl.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "Mayroon nang account?",
44 "always": "Palagi",
45 "amount": "Halaga:",
46 + "amount_is_below_minimum_limit": "Ang iyong balanse pagkatapos ng mga bayarin ay mas mababa kaysa sa minimum na halaga na kinakailangan para sa palitan (${min})",
47 "amount_is_estimate": "Ang natanggap na halaga ay isang pagtatantya",
48 "amount_is_guaranteed": "Ang natanggap na halaga ay garantisado",
49 "and": "at",
@@ -712,6 +713,16 @@
713 "transactions": "Mga Transaksyon",
714 "transactions_by_date": "Mga Transaksyon ayon sa Petsa",
715 "trusted": "Pinagkakatiwalaan",
716 + "tx_commit_exception_no_dust_on_change": "Ang transaksyon ay tinanggihan sa halagang ito. Sa mga barya na ito maaari kang magpadala ng ${min} nang walang pagbabago o ${max} na nagbabalik ng pagbabago.",
717 + "tx_commit_failed": "Nabigo ang transaksyon sa transaksyon. Mangyaring makipag -ugnay sa suporta.",
718 + "tx_no_dust_exception": "Ang transaksyon ay tinanggihan sa pamamagitan ng pagpapadala ng isang maliit na maliit. Mangyaring subukang dagdagan ang halaga.",
719 + "tx_not_enough_inputs_exception": "Hindi sapat na magagamit ang mga input. Mangyaring pumili ng higit pa sa ilalim ng control ng barya",
720 + "tx_rejected_dust_change": "Ang transaksyon na tinanggihan ng mga patakaran sa network, mababang halaga ng pagbabago (alikabok). Subukang ipadala ang lahat o bawasan ang halaga.",
721 + "tx_rejected_dust_output": "Ang transaksyon na tinanggihan ng mga patakaran sa network, mababang halaga ng output (alikabok). Mangyaring dagdagan ang halaga.",
722 + "tx_rejected_dust_output_send_all": "Ang transaksyon na tinanggihan ng mga patakaran sa network, mababang halaga ng output (alikabok). Mangyaring suriin ang balanse ng mga barya na napili sa ilalim ng kontrol ng barya.",
723 + "tx_rejected_vout_negative": "Hindi sapat na balanse upang magbayad para sa mga bayarin ng transaksyon na ito. Mangyaring suriin ang balanse ng mga barya sa ilalim ng kontrol ng barya.",
724 + "tx_wrong_balance_exception": "Wala kang sapat na ${currency} upang maipadala ang halagang ito.",
725 + "tx_zero_fee_exception": "Hindi maaaring magpadala ng transaksyon na may 0 bayad. Subukan ang pagtaas ng rate o pagsuri sa iyong koneksyon para sa pinakabagong mga pagtatantya.",
726 "unavailable_balance": "Hindi available na balanse",
727 "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.",
728 "unconfirmed": "Hindi nakumpirma na balanse",
@@ -789,4 +800,4 @@
800 "you_will_get": "Mag -convert sa",
801 "you_will_send": "I -convert mula sa",
802 "yy": "YY"
792 -}
\ No newline at end of file
803 +}
res/values/strings_tr.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "Zaten bir hesabınız var mı?",
44 "always": "Her Zaman",
45 "amount": "Miktar: ",
46 + "amount_is_below_minimum_limit": "Ücretlerden sonra bakiyeniz, değişim için gereken minimum miktardan daha az olur (${min})",
47 "amount_is_estimate": "Alacağınız tutar tahminidir",
48 "amount_is_guaranteed": "Alacağınız tutar garantilidir",
49 "and": "ve",
@@ -712,6 +713,16 @@
713 "transactions": "İşlemler",
714 "transactions_by_date": "Tarihe göre transferler",
715 "trusted": "Güvenilir",
716 + "tx_commit_exception_no_dust_on_change": "İşlem bu miktarla reddedilir. Bu madeni paralarla değişiklik yapmadan ${min} veya değişikliği döndüren ${max} gönderebilirsiniz.",
717 + "tx_commit_failed": "İşlem taahhüdü başarısız oldu. Lütfen Destek ile iletişime geçin.",
718 + "tx_no_dust_exception": "İşlem, çok küçük bir miktar gönderilerek reddedilir. Lütfen miktarı artırmayı deneyin.",
719 + "tx_not_enough_inputs_exception": "Yeterli giriş yok. Lütfen madeni para kontrolü altında daha fazlasını seçin",
720 + "tx_rejected_dust_change": "Ağ kurallarına göre reddedilen işlem, düşük değişim miktarı (toz). Tümünü göndermeyi veya miktarı azaltmayı deneyin.",
721 + "tx_rejected_dust_output": "Ağ kurallarına göre reddedilen işlem, düşük çıktı miktarı (toz). Lütfen miktarı artırın.",
722 + "tx_rejected_dust_output_send_all": "Ağ kurallarına göre reddedilen işlem, düşük çıktı miktarı (toz). Lütfen madeni para kontrolü altında seçilen madeni para dengesini kontrol edin.",
723 + "tx_rejected_vout_negative": "Bu işlem ücretleri için ödeme yapmak için yeterli bakiye yok. Lütfen madeni para kontrolü altındaki madeni para dengesini kontrol edin.",
724 + "tx_wrong_balance_exception": "Bu miktarı göndermek için yeterli ${currency} yok.",
725 + "tx_zero_fee_exception": "0 ücret ile işlem gönderilemez. En son tahminler için oranı artırmayı veya bağlantınızı kontrol etmeyi deneyin.",
726 "unavailable_balance": "Kullanılamayan bakiye",
727 "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.",
728 "unconfirmed": "Onaylanmamış Bakiye",
@@ -789,4 +800,4 @@
800 "you_will_get": "Biçimine dönüştür:",
801 "you_will_send": "Biçiminden dönüştür:",
802 "yy": "YY"
792 -}
\ No newline at end of file
803 +}
res/values/strings_uk.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "Вже є обліковий запис?",
44 "always": "Завжди",
45 "amount": "Сума: ",
46 + "amount_is_below_minimum_limit": "Ваш баланс після зборів буде меншим, ніж мінімальна сума, необхідна для обміну (${min})",
47 "amount_is_estimate": "Отримана сума є приблизною",
48 "amount_is_guaranteed": "Отримана сума є гарантованою",
49 "and": "і",
@@ -713,6 +714,16 @@
714 "transactions": "Транзакції",
715 "transactions_by_date": "Сортувати по даті",
716 "trusted": "довіряють",
717 + "tx_commit_exception_no_dust_on_change": "Транзакція відхилена цією сумою. За допомогою цих монет ви можете надіслати ${min} без змін або ${max}, що повертає зміни.",
718 + "tx_commit_failed": "Транзакційна комісія не вдалося. Будь ласка, зв'яжіться з підтримкою.",
719 + "tx_no_dust_exception": "Угода відхиляється, відправивши суму занадто мала. Будь ласка, спробуйте збільшити суму.",
720 + "tx_not_enough_inputs_exception": "Недостатньо доступних входів. Виберіть більше під контролем монети",
721 + "tx_rejected_dust_change": "Транзакція відхилена за допомогою мережевих правил, низька кількість змін (пил). Спробуйте надіслати все або зменшити суму.",
722 + "tx_rejected_dust_output": "Транзакція відхилена за допомогою мережевих правил, низька кількість вихідної кількості (пил). Будь ласка, збільшуйте суму.",
723 + "tx_rejected_dust_output_send_all": "Транзакція відхилена за допомогою мережевих правил, низька кількість вихідної кількості (пил). Будь ласка, перевірте баланс монет, вибраних під контролем монет.",
724 + "tx_rejected_vout_negative": "Недостатньо балансу, щоб оплатити плату за цю транзакцію. Будь ласка, перевірте баланс монет під контролем монет.",
725 + "tx_wrong_balance_exception": "У вас недостатньо ${currency}, щоб надіслати цю суму.",
726 + "tx_zero_fee_exception": "Не вдається відправити транзакцію з 0 платежами. Спробуйте збільшити ставку або перевірити з'єднання на останні оцінки.",
727 "unavailable_balance": "Недоступний баланс",
728 "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.",
729 "unconfirmed": "Непідтверджений баланс",
@@ -790,4 +801,4 @@
801 "you_will_get": "Конвертувати в",
802 "you_will_send": "Конвертувати з",
803 "yy": "YY"
793 -}
\ No newline at end of file
804 +}
res/values/strings_ur.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "پہلے سے ہی اکاؤنٹ ہے؟",
44 "always": "ہمیشہ",
45 "amount": "رقم کی رقم:",
46 + "amount_is_below_minimum_limit": "فیس کے بعد آپ کا توازن تبادلہ کے لئے درکار کم سے کم رقم سے کم ہوگا (${min}",
47 "amount_is_estimate": "وصول شدہ رقم ایک تخمینہ ہے۔",
48 "amount_is_guaranteed": "وصول شدہ رقم کی ضمانت ہے۔",
49 "and": "اور",
@@ -714,6 +715,16 @@
715 "transactions": "لین دین",
716 "transactions_by_date": "تاریخ کے لحاظ سے لین دین",
717 "trusted": "قابل اعتماد",
718 + "tx_commit_exception_no_dust_on_change": "اس رقم سے لین دین کو مسترد کردیا گیا ہے۔ ان سککوں کے ذریعہ آپ بغیر کسی تبدیلی کے ${min} یا ${max} بھیج سکتے ہیں جو لوٹتے ہیں۔",
719 + "tx_commit_failed": "ٹرانزیکشن کمٹ ناکام ہوگیا۔ براہ کرم سپورٹ سے رابطہ کریں۔",
720 + "tx_no_dust_exception": "لین دین کو بہت چھوٹی رقم بھیج کر مسترد کردیا جاتا ہے۔ براہ کرم رقم میں اضافہ کرنے کی کوشش کریں۔",
721 + "tx_not_enough_inputs_exception": "کافی ان پٹ دستیاب نہیں ہے۔ براہ کرم سکے کے کنٹرول میں مزید منتخب کریں",
722 + "tx_rejected_dust_change": "نیٹ ورک کے قواعد ، کم تبدیلی کی رقم (دھول) کے ذریعہ لین دین کو مسترد کردیا گیا۔ سب کو بھیجنے یا رقم کو کم کرنے کی کوشش کریں۔",
723 + "tx_rejected_dust_output": "لین دین کو نیٹ ورک کے قواعد ، کم آؤٹ پٹ رقم (دھول) کے ذریعہ مسترد کردیا گیا۔ براہ کرم رقم میں اضافہ کریں۔",
724 + "tx_rejected_dust_output_send_all": "لین دین کو نیٹ ورک کے قواعد ، کم آؤٹ پٹ رقم (دھول) کے ذریعہ مسترد کردیا گیا۔ براہ کرم سکے کے کنٹرول میں منتخب کردہ سکے کا توازن چیک کریں۔",
725 + "tx_rejected_vout_negative": "اس لین دین کی فیسوں کی ادائیگی کے لئے کافی توازن نہیں ہے۔ براہ کرم سکے کے کنٹرول میں سکے کا توازن چیک کریں۔",
726 + "tx_wrong_balance_exception": "آپ کے پاس یہ رقم بھیجنے کے لئے کافی ${currency} نہیں ہے۔",
727 + "tx_zero_fee_exception": "0 فیس کے ساتھ لین دین نہیں بھیج سکتا۔ شرح کو بڑھانے یا تازہ ترین تخمینے کے ل your اپنے کنکشن کی جانچ پڑتال کرنے کی کوشش کریں۔",
728 "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ",
729 "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ",
730 "unconfirmed": "غیر تصدیق شدہ بیلنس",
@@ -791,4 +802,4 @@
802 "you_will_get": "میں تبدیل کریں۔",
803 "you_will_send": "سے تبدیل کریں۔",
804 "yy": "YY"
794 -}
\ No newline at end of file
805 +}
res/values/strings_yo.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "Ṣé ẹ ti ní àkáǹtì?",
44 "always": "Ní gbogbo àwọn ìgbà",
45 "amount": "Iye: ",
46 + "amount_is_below_minimum_limit": "Iwontunws.funfun rẹ lẹhin awọn idiyele yoo kere ju iye ti o kere ju nilo fun paṣipaarọ (${min}",
47 "amount_is_estimate": "Ìdíyelé ni iye tó ń bọ̀",
48 "amount_is_guaranteed": "ó di dandan pé owó á wọlé",
49 "and": "àti",
@@ -713,6 +714,16 @@
714 "transactions": "Àwọn àránṣẹ́",
715 "transactions_by_date": "Àwọn àránṣẹ́ t'á ti fi aago ṣa",
716 "trusted": "A ti fọkàn ẹ̀ tán",
717 + "tx_commit_exception_no_dust_on_change": "Iṣowo naa ti kọ pẹlu iye yii. Pẹlu awọn owó wọnyi o le firanṣẹ ${min} laisi ayipada tabi ${max} ni iyipada iyipada.",
718 + "tx_commit_failed": "Idunadura iṣowo kuna. Jọwọ kan si atilẹyin.",
719 + "tx_no_dust_exception": "Iṣowo naa ni kọ nipa fifiranṣẹ iye ti o kere ju. Jọwọ gbiyanju pọ si iye naa.",
720 + "tx_not_enough_inputs_exception": "Ko to awọn titẹsi to. Jọwọ yan diẹ sii labẹ iṣakoso owo",
721 + "tx_rejected_dust_change": "Idunadura kọ nipasẹ awọn ofin nẹtiwọọki, iye iyipada kekere (eruku). Gbiyanju lati firanṣẹ gbogbo rẹ tabi dinku iye.",
722 + "tx_rejected_dust_output": "Idunadura kọ nipasẹ awọn ofin nẹtiwọọki, iye ti o wuwe kekere (eruku). Jọwọ mu iye naa pọ si.",
723 + "tx_rejected_dust_output_send_all": "Idunadura kọ nipasẹ awọn ofin nẹtiwọọki, iye ti o wuwe kekere (eruku). Jọwọ ṣayẹwo dọgbadọgba ti awọn owo ti a yan labẹ iṣakoso owo.",
724 + "tx_rejected_vout_negative": "Iwontunws.funfun ti o to lati sanwo fun awọn idiyele iṣowo yii. Jọwọ ṣayẹwo iwọntunwọnsi ti awọn owo labẹ iṣakoso owo.",
725 + "tx_wrong_balance_exception": "O ko ni to ${currency} lati firanṣẹ iye yii.",
726 + "tx_zero_fee_exception": "Ko le firanṣẹ idunadura pẹlu ọya 0. Gbiyanju jijẹ oṣuwọn tabi ṣayẹwo asopọ rẹ fun awọn iṣiro tuntun.",
727 "unavailable_balance": "Iwontunwonsi ti ko si",
728 "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.",
729 "unconfirmed": "A kò tí ì jẹ́rìí ẹ̀",
@@ -790,4 +801,4 @@
801 "you_will_get": "Ṣe pàṣípààrọ̀ sí",
802 "you_will_send": "Ṣe pàṣípààrọ̀ láti",
803 "yy": "Ọd"
793 -}
\ No newline at end of file
804 +}
res/values/strings_zh.arb
+12 -1
@@ -43,6 +43,7 @@
43 "already_have_account": "已经有账号了?",
44 "always": "总是",
45 "amount": "金额: ",
46 + "amount_is_below_minimum_limit": "您的余额费用将小于交易所所需的最低金额(${min})",
47 "amount_is_estimate": "收款金额为估算值",
48 "amount_is_guaranteed": "保证收到的金额",
49 "and": "和",
@@ -712,6 +713,16 @@
713 "transactions": "交易情况",
714 "transactions_by_date": "按日期交易",
715 "trusted": "值得信赖",
716 + "tx_commit_exception_no_dust_on_change": "交易被此金额拒绝。使用这些硬币,您可以发送${min}无需更改或返回${max}的变化。",
717 + "tx_commit_failed": "交易承诺失败。请联系支持。",
718 + "tx_no_dust_exception": "通过发送太小的金额来拒绝交易。请尝试增加金额。",
719 + "tx_not_enough_inputs_exception": "没有足够的输入。请在硬币控制下选择更多",
720 + "tx_rejected_dust_change": "交易被网络规则拒绝,较低的变化数量(灰尘)。尝试发送全部或减少金额。",
721 + "tx_rejected_dust_output": "交易被网络规则,低输出量(灰尘)拒绝。请增加金额。",
722 + "tx_rejected_dust_output_send_all": "交易被网络规则,低输出量(灰尘)拒绝。请检查在硬币控制下选择的硬币的余额。",
723 + "tx_rejected_vout_negative": "没有足够的余额来支付此交易费用。请检查硬币控制下的硬币余额。",
724 + "tx_wrong_balance_exception": "您没有足够的${currency}来发送此金额。",
725 + "tx_zero_fee_exception": "无法以0费用发送交易。尝试提高速率或检查连接以获取最新估计。",
726 "unavailable_balance": "不可用余额",
727 "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。",
728 "unconfirmed": "未确认余额",
@@ -789,4 +800,4 @@
800 "you_will_get": "转换到",
801 "you_will_send": "转换自",
802 "yy": "YY"
792 -}
\ No newline at end of file
803 +}
tool/configure.dart
+1
@@ -69,6 +69,7 @@ import 'package:cw_core/transaction_priority.dart';
69 import 'package:cw_core/output_info.dart';
70 import 'package:cw_core/unspent_coins_info.dart';
71 import 'package:cw_core/wallet_service.dart';
72 +import 'package:cw_core/wallet_type.dart';
73 import 'package:cake_wallet/view_model/send/output.dart';
74 import 'package:hive/hive.dart';
75 import 'package:bitcoin_base/bitcoin_base.dart';""";