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>
This commit is contained in:
Rafael 2024-03-29 15:51:34 -03:00 committed by GitHub
parent 78685b74f0
commit fd9018bcc4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
60 changed files with 984 additions and 431 deletions

View file

@ -1,4 +1,8 @@
class BitcoinCommitTransactionException implements Exception {
String errorMessage;
BitcoinCommitTransactionException(this.errorMessage);
@override
String toString() => 'Transaction commit is failed.';
String toString() => errorMessage;
}

View file

@ -1,4 +0,0 @@
class BitcoinTransactionNoInputsException implements Exception {
@override
String toString() => 'Not enough inputs available. Please select more under Coin Control';
}

View file

@ -1,10 +0,0 @@
import 'package:cw_core/crypto_currency.dart';
class BitcoinTransactionWrongBalanceException implements Exception {
BitcoinTransactionWrongBalanceException(this.currency);
final CryptoCurrency currency;
@override
String toString() => 'You do not have enough ${currency.title} to send this amount.';
}

View file

@ -7,10 +7,9 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_bitcoin/script_hash.dart';
import 'package:flutter/foundation.dart';
import 'package:rxdart/rxdart.dart';
import 'package:http/http.dart' as http;
String jsonrpcparams(List<Object> params) {
final _params = params?.map((val) => '"${val.toString()}"')?.join(',');
final _params = params.map((val) => '"${val.toString()}"').join(',');
return '[$_params]';
}
@ -34,6 +33,7 @@ class ElectrumClient {
: _id = 0,
_isConnected = false,
_tasks = {},
_errors = {},
unterminatedString = '';
static const connectionTimeout = Duration(seconds: 5);
@ -44,6 +44,7 @@ class ElectrumClient {
void Function(bool)? onConnectionStatusChange;
int _id;
final Map<String, SocketTask> _tasks;
final Map<String, String> _errors;
bool _isConnected;
Timer? _aliveTimer;
String unterminatedString;
@ -243,30 +244,20 @@ class ElectrumClient {
});
Future<String> broadcastTransaction(
{required String transactionRaw, BasedUtxoNetwork? network}) async {
if (network == BitcoinNetwork.testnet) {
return http
.post(Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx'),
headers: <String, String>{'Content-Type': 'application/json; charset=utf-8'},
body: transactionRaw)
.then((http.Response response) {
if (response.statusCode == 200) {
return response.body;
{required String transactionRaw,
BasedUtxoNetwork? network,
Function(int)? idCallback}) async =>
call(
method: 'blockchain.transaction.broadcast',
params: [transactionRaw],
idCallback: idCallback)
.then((dynamic result) {
if (result is String) {
return result;
}
throw Exception('Failed to broadcast transaction: ${response.body}');
return '';
});
}
return call(method: 'blockchain.transaction.broadcast', params: [transactionRaw])
.then((dynamic result) {
if (result is String) {
return result;
}
return '';
});
}
Future<Map<String, dynamic>> getMerkle({required String hash, required int height}) async =>
await call(method: 'blockchain.transaction.get_merkle', params: [hash, height])
@ -371,10 +362,12 @@ class ElectrumClient {
}
}
Future<dynamic> call({required String method, List<Object> params = const []}) async {
Future<dynamic> call(
{required String method, List<Object> params = const [], Function(int)? idCallback}) async {
final completer = Completer<dynamic>();
_id += 1;
final id = _id;
idCallback?.call(id);
_registryTask(id, completer);
socket!.write(jsonrpc(method: method, id: id, params: params));
@ -456,6 +449,23 @@ class ElectrumClient {
final id = response['id'] as String?;
final result = response['result'];
try {
final error = response['error'] as Map<String, dynamic>?;
if (error != null) {
final errorMessage = error['message'] as String?;
if (errorMessage != null) {
_errors[id!] = errorMessage;
}
}
} catch (_) {}
try {
final error = response['error'] as String?;
if (error != null) {
_errors[id!] = error;
}
} catch (_) {}
if (method is String) {
_methodHandler(method: method, request: response);
return;
@ -465,6 +475,8 @@ class ElectrumClient {
_finish(id, result);
}
}
String getErrorMessage(int id) => _errors[id.toString()] ?? '';
}
// FIXME: move me

View file

@ -8,10 +8,9 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base;
import 'package:collection/collection.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart';
import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart';
import 'package:cw_bitcoin/bitcoin_unspent.dart';
import 'package:cw_bitcoin/bitcoin_wallet_keys.dart';
import 'package:cw_bitcoin/electrum.dart';
@ -19,6 +18,7 @@ import 'package:cw_bitcoin/electrum_balance.dart';
import 'package:cw_bitcoin/electrum_transaction_history.dart';
import 'package:cw_bitcoin/electrum_transaction_info.dart';
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
import 'package:cw_bitcoin/exceptions.dart';
import 'package:cw_bitcoin/litecoin_network.dart';
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
import 'package:cw_bitcoin/script_hash.dart';
@ -188,27 +188,27 @@ abstract class ElectrumWalletBase
}
}
Future<EstimatedTxResult> estimateTxFeeAndInputsToUse(
int credentialsAmount,
bool sendAll,
List<BitcoinBaseAddress> outputAddresses,
List<BitcoinOutput> outputs,
int? feeRate,
BitcoinTransactionPriority? priority,
{int? inputsCount,
String? memo}) async {
int _getDustAmount() {
return 546;
}
bool _isBelowDust(int amount) => amount <= _getDustAmount() && network != BitcoinNetwork.testnet;
Future<EstimatedTxResult> estimateSendAllTx(
List<BitcoinOutput> outputs,
int feeRate, {
String? memo,
int credentialsAmount = 0,
}) async {
final utxos = <UtxoWithAddress>[];
List<ECPrivate> privateKeys = [];
var leftAmount = credentialsAmount;
var allInputsAmount = 0;
int allInputsAmount = 0;
for (int i = 0; i < unspentCoins.length; i++) {
final utx = unspentCoins[i];
if (utx.isSending) {
allInputsAmount += utx.value;
leftAmount = leftAmount - utx.value;
final address = addressTypeFromStr(utx.address, network);
final privkey = generateECPrivate(
@ -226,15 +226,12 @@ abstract class ElectrumWalletBase
vout: utx.vout,
scriptType: _getScriptType(address),
),
ownerDetails:
UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address),
ownerDetails: UtxoAddressDetails(
publicKey: privkey.getPublic().toHex(),
address: address,
),
),
);
bool amountIsAcquired = !sendAll && leftAmount <= 0;
if ((inputsCount == null && amountIsAcquired) || inputsCount == i + 1) {
break;
}
}
}
@ -242,66 +239,218 @@ abstract class ElectrumWalletBase
throw BitcoinTransactionNoInputsException();
}
var changeValue = allInputsAmount - credentialsAmount;
if (!sendAll) {
if (changeValue > 0) {
final changeAddress = await walletAddresses.getChangeAddress();
final address = addressTypeFromStr(changeAddress, network);
outputAddresses.add(address);
outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue)));
}
int estimatedSize;
if (network is BitcoinCashNetwork) {
estimatedSize = ForkedTransactionBuilder.estimateTransactionSize(
utxos: utxos,
outputs: outputs,
network: network as BitcoinCashNetwork,
memo: memo,
);
} else {
estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
utxos: utxos,
outputs: outputs,
network: network,
memo: memo,
);
}
final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
utxos: utxos,
outputs: outputs,
network: network,
memo: memo,
);
int fee = feeRate != null
? feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize)
: feeAmountForPriority(priority!, 0, 0, size: estimatedSize);
int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize);
if (fee == 0) {
throw BitcoinTransactionWrongBalanceException(currency);
throw BitcoinTransactionNoFeeException();
}
var amount = credentialsAmount;
// 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
int amount = allInputsAmount - fee;
final lastOutput = outputs.last;
if (!sendAll) {
if (changeValue > fee) {
// Here, lastOutput is change, deduct the fee from it
outputs[outputs.length - 1] =
BitcoinOutput(address: lastOutput.address, value: lastOutput.value - BigInt.from(fee));
// Attempting to send less than the dust limit
if (_isBelowDust(amount)) {
throw BitcoinTransactionNoDustException();
}
if (credentialsAmount > 0) {
final amountLeftForFee = amount - credentialsAmount;
if (amountLeftForFee > 0 && _isBelowDust(amountLeftForFee)) {
amount -= amountLeftForFee;
fee += amountLeftForFee;
}
}
outputs[outputs.length - 1] =
BitcoinOutput(address: outputs.last.address, value: BigInt.from(amount));
return EstimatedTxResult(
utxos: utxos,
privateKeys: privateKeys,
fee: fee,
amount: amount,
isSendAll: true,
hasChange: false,
memo: memo,
);
}
Future<EstimatedTxResult> estimateTxForAmount(
int credentialsAmount,
List<BitcoinOutput> outputs,
int feeRate, {
int? inputsCount,
String? memo,
}) async {
final utxos = <UtxoWithAddress>[];
List<ECPrivate> privateKeys = [];
int allInputsAmount = 0;
int leftAmount = credentialsAmount;
final sendingCoins = unspentCoins.where((utx) => utx.isSending).toList();
for (int i = 0; i < sendingCoins.length; i++) {
final utx = sendingCoins[i];
allInputsAmount += utx.value;
leftAmount = leftAmount - utx.value;
final address = addressTypeFromStr(utx.address, network);
final privkey = generateECPrivate(
hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
index: utx.bitcoinAddressRecord.index,
network: network);
privateKeys.add(privkey);
utxos.add(
UtxoWithAddress(
utxo: BitcoinUtxo(
txHash: utx.hash,
value: BigInt.from(utx.value),
vout: utx.vout,
scriptType: _getScriptType(address),
),
ownerDetails: UtxoAddressDetails(
publicKey: privkey.getPublic().toHex(),
address: address,
),
),
);
bool amountIsAcquired = leftAmount <= 0;
if ((inputsCount == null && amountIsAcquired) || inputsCount == i + 1) {
break;
}
}
if (utxos.isEmpty) {
throw BitcoinTransactionNoInputsException();
}
final spendingAllCoins = sendingCoins.length == utxos.length;
// How much is being spent - how much is being sent
int amountLeftForChangeAndFee = allInputsAmount - credentialsAmount;
if (amountLeftForChangeAndFee <= 0) {
throw BitcoinTransactionWrongBalanceException();
}
final changeAddress = await walletAddresses.getChangeAddress();
final address = addressTypeFromStr(changeAddress, network);
outputs.add(BitcoinOutput(
address: address,
value: BigInt.from(amountLeftForChangeAndFee),
));
int estimatedSize;
if (network is BitcoinCashNetwork) {
estimatedSize = ForkedTransactionBuilder.estimateTransactionSize(
utxos: utxos,
outputs: outputs,
network: network as BitcoinCashNetwork,
memo: memo,
);
} else {
// Here, if sendAll, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount for change
amount = allInputsAmount - fee;
estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
utxos: utxos,
outputs: outputs,
network: network,
memo: memo,
);
}
int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize);
if (fee == 0) {
throw BitcoinTransactionNoFeeException();
}
int amount = credentialsAmount;
final lastOutput = outputs.last;
final amountLeftForChange = amountLeftForChangeAndFee - fee;
if (!_isBelowDust(amountLeftForChange)) {
// Here, lastOutput already is change, return the amount left without the fee to the user's address.
outputs[outputs.length - 1] =
BitcoinOutput(address: lastOutput.address, value: BigInt.from(amount));
BitcoinOutput(address: lastOutput.address, value: BigInt.from(amountLeftForChange));
} else {
// If has change that is lower than dust, will end up with tx rejected by network rules, so estimate again without the added change
outputs.removeLast();
// Still has inputs to spend before failing
if (!spendingAllCoins) {
return estimateTxForAmount(
credentialsAmount,
outputs,
feeRate,
inputsCount: utxos.length + 1,
memo: memo,
);
}
final estimatedSendAll = await estimateSendAllTx(
outputs,
feeRate,
memo: memo,
);
if (estimatedSendAll.amount == credentialsAmount) {
return estimatedSendAll;
}
// Estimate to user how much is needed to send to cover the fee
final maxAmountWithReturningChange = allInputsAmount - _getDustAmount() - fee - 1;
throw BitcoinTransactionNoDustOnChangeException(
bitcoinAmountToString(amount: maxAmountWithReturningChange),
bitcoinAmountToString(amount: estimatedSendAll.amount),
);
}
// Attempting to send less than the dust limit
if (_isBelowDust(amount)) {
throw BitcoinTransactionNoDustException();
}
final totalAmount = amount + fee;
if (totalAmount > balance[currency]!.confirmed) {
throw BitcoinTransactionWrongBalanceException(currency);
throw BitcoinTransactionWrongBalanceException();
}
if (totalAmount > allInputsAmount) {
if (unspentCoins.where((utx) => utx.isSending).length == utxos.length) {
throw BitcoinTransactionWrongBalanceException(currency);
if (spendingAllCoins) {
throw BitcoinTransactionWrongBalanceException();
} else {
if (changeValue > fee) {
outputAddresses.removeLast();
if (amountLeftForChangeAndFee > fee) {
outputs.removeLast();
}
return estimateTxFeeAndInputsToUse(
credentialsAmount, sendAll, outputAddresses, outputs, feeRate, priority,
inputsCount: utxos.length + 1);
return estimateTxForAmount(
credentialsAmount,
outputs,
feeRate,
inputsCount: utxos.length + 1,
memo: memo,
);
}
}
@ -310,6 +459,8 @@ abstract class ElectrumWalletBase
privateKeys: privateKeys,
fee: fee,
amount: amount,
hasChange: true,
isSendAll: false,
memo: memo,
);
}
@ -318,58 +469,80 @@ abstract class ElectrumWalletBase
Future<PendingTransaction> createTransaction(Object credentials) async {
try {
final outputs = <BitcoinOutput>[];
final outputAddresses = <BitcoinBaseAddress>[];
final transactionCredentials = credentials as BitcoinTransactionCredentials;
final hasMultiDestination = transactionCredentials.outputs.length > 1;
final sendAll = !hasMultiDestination && transactionCredentials.outputs.first.sendAll;
final memo = transactionCredentials.outputs.first.memo;
var credentialsAmount = 0;
int credentialsAmount = 0;
for (final out in transactionCredentials.outputs) {
final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address;
final address = addressTypeFromStr(outputAddress, network);
final outputAmount = out.formattedCryptoAmount!;
outputAddresses.add(address);
if (!sendAll && _isBelowDust(outputAmount)) {
throw BitcoinTransactionNoDustException();
}
if (hasMultiDestination) {
if (out.sendAll || out.formattedCryptoAmount! <= 0) {
throw BitcoinTransactionWrongBalanceException(currency);
if (out.sendAll) {
throw BitcoinTransactionWrongBalanceException();
}
}
final outputAmount = out.formattedCryptoAmount!;
credentialsAmount += outputAmount;
credentialsAmount += outputAmount;
outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount)));
final address =
addressTypeFromStr(out.isParsedAddress ? out.extractedAddress! : out.address, network);
if (sendAll) {
// The value will be changed after estimating the Tx size and deducting the fee from the total to be sent
outputs.add(BitcoinOutput(address: address, value: BigInt.from(0)));
} else {
if (!sendAll) {
final outputAmount = out.formattedCryptoAmount!;
credentialsAmount += outputAmount;
outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount)));
} else {
// The value will be changed after estimating the Tx size and deducting the fee from the total
outputs.add(BitcoinOutput(address: address, value: BigInt.from(0)));
}
outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount)));
}
}
final estimatedTx = await estimateTxFeeAndInputsToUse(
credentialsAmount,
sendAll,
outputAddresses,
outputs,
transactionCredentials.feeRate,
transactionCredentials.priority,
memo: transactionCredentials.outputs.first.memo,
);
final feeRateInt = transactionCredentials.feeRate != null
? transactionCredentials.feeRate!
: feeRate(transactionCredentials.priority!);
final txb = BitcoinTransactionBuilder(
utxos: estimatedTx.utxos,
outputs: outputs,
fee: BigInt.from(estimatedTx.fee),
network: network,
memo: estimatedTx.memo,
outputOrdering: BitcoinOrdering.none,
);
EstimatedTxResult estimatedTx;
if (sendAll) {
estimatedTx = await estimateSendAllTx(
outputs,
feeRateInt,
memo: memo,
credentialsAmount: credentialsAmount,
);
} else {
estimatedTx = await estimateTxForAmount(
credentialsAmount,
outputs,
feeRateInt,
memo: memo,
);
}
BasedBitcoinTransacationBuilder txb;
if (network is BitcoinCashNetwork) {
txb = ForkedTransactionBuilder(
utxos: estimatedTx.utxos,
outputs: outputs,
fee: BigInt.from(estimatedTx.fee),
network: network,
memo: estimatedTx.memo,
outputOrdering: BitcoinOrdering.none,
);
} else {
txb = BitcoinTransactionBuilder(
utxos: estimatedTx.utxos,
outputs: outputs,
fee: BigInt.from(estimatedTx.fee),
network: network,
memo: estimatedTx.memo,
outputOrdering: BitcoinOrdering.none,
);
}
final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) {
final key = estimatedTx.privateKeys
@ -390,7 +563,10 @@ abstract class ElectrumWalletBase
electrumClient: electrumClient,
amount: estimatedTx.amount,
fee: estimatedTx.fee,
network: network)
feeRate: feeRateInt.toString(),
network: network,
hasChange: estimatedTx.hasChange,
isSendAll: estimatedTx.isSendAll)
..addListener((transaction) async {
transactionHistory.addOne(transaction);
await updateBalance();
@ -423,7 +599,7 @@ abstract class ElectrumWalletBase
}
}
int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount,
int feeAmountForPriority(TransactionPriority priority, int inputsCount, int outputsCount,
{int? size}) =>
feeRate(priority) * (size ?? estimatedTransactionSize(inputsCount, outputsCount));
@ -908,6 +1084,8 @@ class EstimatedTxResult {
required this.privateKeys,
required this.fee,
required this.amount,
required this.hasChange,
required this.isSendAll,
this.memo,
});
@ -915,10 +1093,21 @@ class EstimatedTxResult {
final List<ECPrivate> privateKeys;
final int fee;
final int amount;
final bool hasChange;
final bool isSendAll;
final String? memo;
}
BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) {
if (network is BitcoinCashNetwork) {
if (!address.startsWith("bitcoincash:") &&
(address.startsWith("q") || address.startsWith("p"))) {
address = "bitcoincash:$address";
}
return BitcoinCashAddress(address).baseAddress;
}
if (P2pkhAddress.regex.hasMatch(address)) {
return P2pkhAddress.fromAddress(address: address, network: network);
} else if (P2shAddress.regex.hasMatch(address)) {

View file

@ -77,7 +77,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
String get address {
String receiveAddress;
final typeMatchingReceiveAddresses = receiveAddresses.where(_isAddressPageTypeMatch);
final typeMatchingReceiveAddresses =
receiveAddresses.where(_isAddressPageTypeMatch).where((addr) => !addr.isUsed);
if ((isEnabledAutoGenerateSubaddress && receiveAddresses.isEmpty) ||
typeMatchingReceiveAddresses.isEmpty) {
@ -220,8 +221,11 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
Future<void> updateAddressesInBox() async {
try {
addressesMap.clear();
addressesMap[address] = '';
allAddressesMap.clear();
_addresses.forEach((addressRecord) {
addressesMap[addressRecord.address] = addressRecord.name;
allAddressesMap[addressRecord.address] = addressRecord.name;
});
await saveAddressesInBox();
} catch (e) {

View file

@ -0,0 +1,27 @@
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/exceptions.dart';
class BitcoinTransactionWrongBalanceException extends TransactionWrongBalanceException {
BitcoinTransactionWrongBalanceException() : super(CryptoCurrency.btc);
}
class BitcoinTransactionNoInputsException extends TransactionNoInputsException {}
class BitcoinTransactionNoFeeException extends TransactionNoFeeException {}
class BitcoinTransactionNoDustException extends TransactionNoDustException {}
class BitcoinTransactionNoDustOnChangeException extends TransactionNoDustOnChangeException {
BitcoinTransactionNoDustOnChangeException(super.max, super.min);
}
class BitcoinTransactionCommitFailed extends TransactionCommitFailed {}
class BitcoinTransactionCommitFailedDustChange extends TransactionCommitFailedDustChange {}
class BitcoinTransactionCommitFailedDustOutput extends TransactionCommitFailedDustOutput {}
class BitcoinTransactionCommitFailedDustOutputSendAll
extends TransactionCommitFailedDustOutputSendAll {}
class BitcoinTransactionCommitFailedVoutNegative extends TransactionCommitFailedVoutNegative {}

View file

@ -1,4 +1,4 @@
import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart';
import 'package:cw_bitcoin/exceptions.dart';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_bitcoin/electrum.dart';
@ -9,7 +9,13 @@ import 'package:cw_core/wallet_type.dart';
class PendingBitcoinTransaction with PendingTransaction {
PendingBitcoinTransaction(this._tx, this.type,
{required this.electrumClient, required this.amount, required this.fee, this.network})
{required this.electrumClient,
required this.amount,
required this.fee,
required this.feeRate,
this.network,
required this.hasChange,
required this.isSendAll})
: _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
final WalletType type;
@ -17,7 +23,10 @@ class PendingBitcoinTransaction with PendingTransaction {
final ElectrumClient electrumClient;
final int amount;
final int fee;
final String feeRate;
final BasedUtxoNetwork? network;
final bool hasChange;
final bool isSendAll;
@override
String get id => _tx.txId();
@ -38,10 +47,30 @@ class PendingBitcoinTransaction with PendingTransaction {
@override
Future<void> commit() async {
final result = await electrumClient.broadcastTransaction(transactionRaw: hex, network: network);
int? callId;
final result = await electrumClient.broadcastTransaction(
transactionRaw: hex, network: network, idCallback: (id) => callId = id);
if (result.isEmpty) {
throw BitcoinCommitTransactionException();
if (callId != null) {
final error = electrumClient.getErrorMessage(callId!);
if (error.contains("dust")) {
if (hasChange) {
throw BitcoinTransactionCommitFailedDustChange();
} else if (!isSendAll) {
throw BitcoinTransactionCommitFailedDustOutput();
} else {
throw BitcoinTransactionCommitFailedDustOutputSendAll();
}
}
if (error.contains("bad-txns-vout-negative")) {
throw BitcoinTransactionCommitFailedVoutNegative();
}
}
throw BitcoinTransactionCommitFailed();
}
_listeners.forEach((listener) => listener(transactionInfo()));

View file

@ -4,15 +4,10 @@ import 'package:bitbox/bitbox.dart' as bitbox;
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
import 'package:cw_bitcoin/bitcoin_address_record.dart';
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart';
import 'package:cw_bitcoin/bitcoin_unspent.dart';
import 'package:cw_bitcoin/electrum_balance.dart';
import 'package:cw_bitcoin/electrum_wallet.dart';
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
import 'package:cw_bitcoin_cash/src/pending_bitcoin_cash_transaction.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coins_info.dart';
@ -130,187 +125,9 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
);
}
@override
Future<PendingBitcoinCashTransaction> createTransaction(Object credentials) async {
const minAmount = 546;
final transactionCredentials = credentials as BitcoinTransactionCredentials;
final inputs = <BitcoinUnspent>[];
final outputs = transactionCredentials.outputs;
final hasMultiDestination = outputs.length > 1;
var allInputsAmount = 0;
final String? opReturnMemo = outputs.first.memo;
if (unspentCoins.isEmpty) await updateUnspent();
for (final utx in unspentCoins) {
if (utx.isSending) {
allInputsAmount += utx.value;
inputs.add(utx);
}
}
if (inputs.isEmpty) throw BitcoinTransactionNoInputsException();
final allAmountFee = transactionCredentials.feeRate != null
? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length)
: feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length);
final allAmount = allInputsAmount - allAmountFee;
var credentialsAmount = 0;
var amount = 0;
var fee = 0;
if (hasMultiDestination) {
if (outputs.any((item) => item.sendAll || item.formattedCryptoAmount! <= 0)) {
throw BitcoinTransactionWrongBalanceException(currency);
}
credentialsAmount = outputs.fold(0, (acc, value) => acc + value.formattedCryptoAmount!);
if (allAmount - credentialsAmount < minAmount) {
throw BitcoinTransactionWrongBalanceException(currency);
}
amount = credentialsAmount;
if (transactionCredentials.feeRate != null) {
fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount,
outputsCount: outputs.length + 1);
} else {
fee = calculateEstimatedFee(transactionCredentials.priority, amount,
outputsCount: outputs.length + 1);
}
} else {
final output = outputs.first;
credentialsAmount = !output.sendAll ? output.formattedCryptoAmount! : 0;
if (credentialsAmount > allAmount) {
throw BitcoinTransactionWrongBalanceException(currency);
}
amount = output.sendAll || allAmount - credentialsAmount < minAmount
? allAmount
: credentialsAmount;
if (output.sendAll || amount == allAmount) {
fee = allAmountFee;
} else if (transactionCredentials.feeRate != null) {
fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount);
} else {
fee = calculateEstimatedFee(transactionCredentials.priority, amount);
}
}
if (fee == 0) {
throw BitcoinTransactionWrongBalanceException(currency);
}
final totalAmount = amount + fee;
if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) {
throw BitcoinTransactionWrongBalanceException(currency);
}
final txb = bitbox.Bitbox.transactionBuilder(testnet: false);
final changeAddress = await walletAddresses.getChangeAddress();
var leftAmount = totalAmount;
var totalInputAmount = 0;
inputs.clear();
for (final utx in unspentCoins) {
if (utx.isSending) {
leftAmount = leftAmount - utx.value;
totalInputAmount += utx.value;
inputs.add(utx);
if (leftAmount <= 0) {
break;
}
}
}
if (inputs.isEmpty) throw BitcoinTransactionNoInputsException();
if (amount <= 0 || totalInputAmount < totalAmount) {
throw BitcoinTransactionWrongBalanceException(currency);
}
inputs.forEach((input) {
txb.addInput(input.hash, input.vout);
});
final String bchPrefix = "bitcoincash:";
outputs.forEach((item) {
final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount;
String outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address;
if (!outputAddress.startsWith(bchPrefix)) {
outputAddress = "$bchPrefix$outputAddress";
}
bool isP2sh = outputAddress.startsWith("p", bchPrefix.length);
if (isP2sh) {
final p2sh = P2shAddress.fromAddress(
address: outputAddress,
network: BitcoinCashNetwork.mainnet,
);
txb.addOutput(Uint8List.fromList(p2sh.toScriptPubKey().toBytes()), outputAmount!);
return;
}
txb.addOutput(outputAddress, outputAmount!);
});
final estimatedSize = bitbox.BitcoinCash.getByteCount(inputs.length, outputs.length + 1);
var feeAmount = 0;
if (transactionCredentials.feeRate != null) {
feeAmount = transactionCredentials.feeRate! * estimatedSize;
} else {
feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize;
}
final changeValue = totalInputAmount - amount - feeAmount;
if (changeValue > minAmount) {
txb.addOutput(changeAddress, changeValue);
}
if (opReturnMemo != null) txb.addOutputData(opReturnMemo);
for (var i = 0; i < inputs.length; i++) {
final input = inputs[i];
final keyPair = generateKeyPair(
hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
index: input.bitcoinAddressRecord.index);
txb.sign(i, keyPair, input.value);
}
final tx = txb.build();
return PendingBitcoinCashTransaction(tx, type,
electrumClient: electrumClient, amount: amount, fee: fee);
}
bitbox.ECPair generateKeyPair({required bitcoin.HDWallet hd, required int index}) =>
bitbox.ECPair.fromWIF(hd.derive(index).wif!);
@override
int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount,
{int? size}) =>
feeRate(priority) * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount);
int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) =>
feeRate * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount);
int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount, int? size}) {
int inputsCount = 0;
int totalValue = 0;

View file

@ -1,4 +1,4 @@
import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart';
import 'package:cw_bitcoin/exceptions.dart';
import 'package:bitbox/bitbox.dart' as bitbox;
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_bitcoin/electrum.dart';
@ -11,7 +11,9 @@ class PendingBitcoinCashTransaction with PendingTransaction {
PendingBitcoinCashTransaction(this._tx, this.type,
{required this.electrumClient,
required this.amount,
required this.fee})
required this.fee,
required this.hasChange,
required this.isSendAll})
: _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
final WalletType type;
@ -19,6 +21,8 @@ class PendingBitcoinCashTransaction with PendingTransaction {
final ElectrumClient electrumClient;
final int amount;
final int fee;
final bool hasChange;
final bool isSendAll;
@override
String get id => _tx.getId();
@ -36,18 +40,36 @@ class PendingBitcoinCashTransaction with PendingTransaction {
@override
Future<void> commit() async {
final result =
await electrumClient.broadcastTransaction(transactionRaw: _tx.toHex());
int? callId;
final result = await electrumClient.broadcastTransaction(
transactionRaw: hex, idCallback: (id) => callId = id);
if (result.isEmpty) {
throw BitcoinCommitTransactionException();
if (callId != null) {
final error = electrumClient.getErrorMessage(callId!);
if (error.contains("dust")) {
if (hasChange) {
throw BitcoinTransactionCommitFailedDustChange();
} else if (!isSendAll) {
throw BitcoinTransactionCommitFailedDustOutput();
} else {
throw BitcoinTransactionCommitFailedDustOutputSendAll();
}
}
if (error.contains("bad-txns-vout-negative")) {
throw BitcoinTransactionCommitFailedVoutNegative();
}
}
throw BitcoinTransactionCommitFailed();
}
_listeners?.forEach((listener) => listener(transactionInfo()));
_listeners.forEach((listener) => listener(transactionInfo()));
}
void addListener(
void Function(ElectrumTransactionInfo transaction) listener) =>
void addListener(void Function(ElectrumTransactionInfo transaction) listener) =>
_listeners.add(listener);
ElectrumTransactionInfo transactionInfo() => ElectrumTransactionInfo(type,

View file

@ -0,0 +1,30 @@
import 'package:cw_core/crypto_currency.dart';
class TransactionWrongBalanceException implements Exception {
TransactionWrongBalanceException(this.currency);
final CryptoCurrency currency;
}
class TransactionNoInputsException implements Exception {}
class TransactionNoFeeException implements Exception {}
class TransactionNoDustException implements Exception {}
class TransactionNoDustOnChangeException implements Exception {
TransactionNoDustOnChangeException(this.max, this.min);
final String max;
final String min;
}
class TransactionCommitFailed implements Exception {}
class TransactionCommitFailedDustChange implements Exception {}
class TransactionCommitFailedDustOutput implements Exception {}
class TransactionCommitFailedDustOutputSendAll implements Exception {}
class TransactionCommitFailedVoutNegative implements Exception {}

View file

@ -2,6 +2,7 @@ mixin PendingTransaction {
String get id;
String get amountFormatted;
String get feeFormatted;
String? feeRate;
String get hex;
int? get outputCount => null;

View file

@ -3,8 +3,9 @@ import 'package:cw_core/wallet_info.dart';
abstract class WalletAddresses {
WalletAddresses(this.walletInfo)
: addressesMap = {},
addressInfos = {};
: addressesMap = {},
allAddressesMap = {},
addressInfos = {};
final WalletInfo walletInfo;
@ -15,6 +16,7 @@ abstract class WalletAddresses {
set address(String address);
Map<String, String> addressesMap;
Map<String, String> allAddressesMap;
Map<int, List<AddressInfo>> addressInfos;
@ -39,5 +41,5 @@ abstract class WalletAddresses {
}
}
bool containsAddress(String address) => addressesMap.containsKey(address);
bool containsAddress(String address) => allAddressesMap.containsKey(address);
}

View file

@ -86,7 +86,7 @@ class CWBitcoin extends Bitcoin {
extractedAddress: out.extractedAddress,
isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount,
memo: out.memo))
memo: out.memo))
.toList(),
priority: priority as BitcoinTransactionPriority,
feeRate: feeRate);
@ -123,23 +123,30 @@ class CWBitcoin extends Bitcoin {
@override
Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority) async {
final electrumWallet = wallet as ElectrumWallet;
final sk = ECPrivate.random();
final p2shAddr = sk.getPublic().toP2pkhInP2sh();
final p2wpkhAddr = sk.getPublic().toP2wpkhAddress();
try {
final estimatedTx = await electrumWallet.estimateTxFeeAndInputsToUse(
0,
true,
// Deposit address + change address
[p2shAddr, p2wpkhAddr],
[
BitcoinOutput(address: p2shAddr, value: BigInt.zero),
BitcoinOutput(address: p2wpkhAddr, value: BigInt.zero)
],
null,
priority as BitcoinTransactionPriority);
final sk = ECPrivate.random();
final electrumWallet = wallet as ElectrumWallet;
if (wallet.type == WalletType.bitcoinCash) {
final p2pkhAddr = sk.getPublic().toP2pkhAddress();
final estimatedTx = await electrumWallet.estimateSendAllTx(
[BitcoinOutput(address: p2pkhAddr, value: BigInt.zero)],
getFeeRate(wallet, priority as BitcoinCashTransactionPriority),
);
return estimatedTx.amount;
}
final p2shAddr = sk.getPublic().toP2pkhInP2sh();
final estimatedTx = await electrumWallet.estimateSendAllTx(
[BitcoinOutput(address: p2shAddr, value: BigInt.zero)],
getFeeRate(
wallet,
wallet.type == WalletType.litecoin
? priority as LitecoinTransactionPriority
: priority as BitcoinTransactionPriority,
),
);
return estimatedTx.amount;
} catch (_) {

View file

@ -34,6 +34,10 @@ class AmountValidator extends TextValidator {
late final DecimalAmountValidator decimalAmountValidator;
String? call(String? value) {
if (value == null || value.isEmpty) {
return S.current.error_text_amount;
}
//* Validate for Text(length, symbols, decimals etc)
final textValidation = symbolsAmountValidator(value) ?? decimalAmountValidator(value);

View file

@ -133,7 +133,11 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
Future<Trade> createTrade({
required TradeRequest request,
required bool isFixedRateMode,
required bool isSendAll,
}) async {
final distributionPath = await DistributionInfo.instance.getDistributionPath();
final formattedAppVersion = int.tryParse(_settingsStore.appVersion.replaceAll('.', '')) ?? 0;
final payload = {
@ -202,7 +206,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
createdAt: DateTime.now(),
amount: responseJSON['fromAmount']?.toString() ?? request.fromAmount,
state: TradeState.created,
payoutAddress: payoutAddress);
payoutAddress: payoutAddress,
isSendAll: isSendAll);
}
@override

View file

@ -28,7 +28,8 @@ abstract class ExchangeProvider {
Future<Limits> fetchLimits(
{required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode});
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode});
Future<Trade> createTrade(
{required TradeRequest request, required bool isFixedRateMode, required bool isSendAll});
Future<Trade> findTradeById({required String id});

View file

@ -130,7 +130,11 @@ class ExolixExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
Future<Trade> createTrade({
required TradeRequest request,
required bool isFixedRateMode,
required bool isSendAll,
}) async {
final headers = {'Content-Type': 'application/json'};
final body = {
'coinFrom': _normalizeCurrency(request.fromCurrency),
@ -180,7 +184,8 @@ class ExolixExchangeProvider extends ExchangeProvider {
createdAt: DateTime.now(),
amount: amount,
state: TradeState.created,
payoutAddress: payoutAddress);
payoutAddress: payoutAddress,
isSendAll: isSendAll);
}
@override

View file

@ -144,7 +144,11 @@ class SideShiftExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
Future<Trade> createTrade({
required TradeRequest request,
required bool isFixedRateMode,
required bool isSendAll,
}) async {
String url = '';
final body = {
'affiliateId': affiliateId,
@ -197,6 +201,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
amount: depositAmount ?? request.fromAmount,
payoutAddress: settleAddress,
createdAt: DateTime.now(),
isSendAll: isSendAll,
);
}

View file

@ -117,7 +117,11 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
Future<Trade> createTrade({
required TradeRequest request,
required bool isFixedRateMode,
required bool isSendAll,
}) async {
final headers = {'Content-Type': 'application/json'};
final params = {'api_key': apiKey};
final body = <String, dynamic>{
@ -162,6 +166,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
amount: request.fromAmount,
payoutAddress: payoutAddress,
createdAt: DateTime.now(),
isSendAll: isSendAll,
);
}

View file

@ -109,7 +109,11 @@ class ThorChainExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
Future<Trade> createTrade({
required TradeRequest request,
required bool isFixedRateMode,
required bool isSendAll,
}) async {
String formattedToAddress = request.toAddress.startsWith('bitcoincash:')
? request.toAddress.replaceFirst('bitcoincash:', '')
: request.toAddress;
@ -142,7 +146,8 @@ class ThorChainExchangeProvider extends ExchangeProvider {
amount: request.fromAmount,
state: TradeState.notFound,
payoutAddress: request.toAddress,
memo: memo);
memo: memo,
isSendAll: isSendAll);
}
@override
@ -177,10 +182,12 @@ class ThorChainExchangeProvider extends ExchangeProvider {
final parts = memo?.split(':') ?? [];
final String toChain = parts.length > 1 ? parts[1].split('.')[0] : '';
final String toAsset = parts.length > 1 && parts[1].split('.').length > 1 ? parts[1].split('.')[1].split('-')[0] : '';
final String toAsset = parts.length > 1 && parts[1].split('.').length > 1
? parts[1].split('.')[1].split('-')[0]
: '';
final formattedToChain = CryptoCurrency.fromString(toChain);
final toAssetWithChain = CryptoCurrency.fromString(toAsset, walletCurrency:formattedToChain);
final toAssetWithChain = CryptoCurrency.fromString(toAsset, walletCurrency: formattedToChain);
final plannedOutTxs = responseJSON['planned_out_txs'] as List<dynamic>?;
final isRefund = plannedOutTxs?.any((tx) => tx['refund'] == true) ?? false;

View file

@ -13,7 +13,8 @@ import 'package:http/http.dart';
class TrocadorExchangeProvider extends ExchangeProvider {
TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}})
: _lastUsedRateId = '', _provider = [],
: _lastUsedRateId = '',
_provider = [],
super(pairList: supportedPairs(_notSupported));
bool useTorOnly;
@ -23,7 +24,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
'Swapter',
'StealthEx',
'Simpleswap',
'Swapuz'
'Swapuz',
'ChangeNow',
'Changehero',
'FixedFloat',
@ -144,8 +145,11 @@ class TrocadorExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
Future<Trade> createTrade({
required TradeRequest request,
required bool isFixedRateMode,
required bool isSendAll,
}) async {
final params = {
'api_key': apiKey,
'ticker_from': _normalizeCurrency(request.fromCurrency),
@ -172,7 +176,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
params['id'] = _lastUsedRateId;
}
String firstAvailableProvider = '';
for (var provider in _provider) {
@ -225,7 +228,8 @@ class TrocadorExchangeProvider extends ExchangeProvider {
providerName: providerName,
createdAt: DateTime.tryParse(date)?.toLocal(),
amount: responseJSON['amount_from']?.toString() ?? request.fromAmount,
payoutAddress: payoutAddress);
payoutAddress: payoutAddress,
isSendAll: isSendAll);
}
@override

View file

@ -31,6 +31,7 @@ class Trade extends HiveObject {
this.memo,
this.txId,
this.isRefund,
this.isSendAll,
}) {
if (provider != null) providerRaw = provider.raw;
@ -117,6 +118,9 @@ class Trade extends HiveObject {
@HiveField(20)
bool? isRefund;
@HiveField(21)
bool? isSendAll;
static Trade fromMap(Map<String, Object?> map) {
return Trade(
id: map['id'] as String,
@ -130,8 +134,8 @@ class Trade extends HiveObject {
fromWalletAddress: map['from_wallet_address'] as String?,
memo: map['memo'] as String?,
txId: map['tx_id'] as String?,
isRefund: map['isRefund'] as bool?
);
isRefund: map['isRefund'] as bool?,
isSendAll: map['isSendAll'] as bool?);
}
Map<String, dynamic> toMap() {
@ -146,7 +150,8 @@ class Trade extends HiveObject {
'from_wallet_address': fromWalletAddress,
'memo': memo,
'tx_id': txId,
'isRefund': isRefund
'isRefund': isRefund,
'isSendAll': isSendAll,
};
}

View file

@ -186,7 +186,13 @@ class ExchangePage extends BasePage {
StandardCheckbox(
value: exchangeViewModel.isFixedRateMode,
caption: S.of(context).fixed_rate,
onChanged: (value) => exchangeViewModel.isFixedRateMode = value,
onChanged: (value) {
if (value) {
exchangeViewModel.enableFixedRateMode();
} else {
exchangeViewModel.isFixedRateMode = false;
}
},
),
],
)),
@ -528,7 +534,7 @@ class ExchangePage extends BasePage {
_receiveAmountFocus.addListener(() {
if (_receiveAmountFocus.hasFocus) {
exchangeViewModel.isFixedRateMode = true;
exchangeViewModel.enableFixedRateMode();
}
// exchangeViewModel.changeReceiveAmount(amount: receiveAmountController.text);
});

View file

@ -262,6 +262,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
fee: S.of(popupContext).send_fee,
feeValue: widget.exchangeTradeViewModel.sendViewModel
.pendingTransaction!.feeFormatted,
feeRate: widget.exchangeTradeViewModel.sendViewModel.pendingTransaction!.feeRate,
rightButtonText: S.of(popupContext).send,
leftButtonText: S.of(popupContext).cancel,
actionRightButton: () async {

View file

@ -426,6 +426,7 @@ class SendPage extends BasePage {
fee: isEVMCompatibleChain(sendViewModel.walletType)
? S.of(_dialogContext).send_estimated_fee
: S.of(_dialogContext).send_fee,
feeRate: sendViewModel.pendingTransaction!.feeRate,
feeValue: sendViewModel.pendingTransaction!.feeFormatted,
feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
outputs: sendViewModel.outputs,

View file

@ -16,6 +16,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
required this.amountValue,
required this.fiatAmountValue,
required this.fee,
this.feeRate,
required this.feeValue,
required this.feeFiatAmount,
required this.outputs,
@ -36,6 +37,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
final String amountValue;
final String fiatAmountValue;
final String fee;
final String? feeRate;
final String feeValue;
final String feeFiatAmount;
final List<Output> outputs;
@ -90,6 +92,7 @@ class ConfirmSendingAlert extends BaseAlertDialog {
amountValue: amountValue,
fiatAmountValue: fiatAmountValue,
fee: fee,
feeRate: feeRate,
feeValue: feeValue,
feeFiatAmount: feeFiatAmount,
outputs: outputs);
@ -103,6 +106,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
required this.amountValue,
required this.fiatAmountValue,
required this.fee,
this.feeRate,
required this.feeValue,
required this.feeFiatAmount,
required this.outputs});
@ -113,6 +117,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
final String amountValue;
final String fiatAmountValue;
final String fee;
final String? feeRate;
final String feeValue;
final String feeFiatAmount;
final List<Output> outputs;
@ -125,6 +130,7 @@ class ConfirmSendingAlertContent extends StatefulWidget {
amountValue: amountValue,
fiatAmountValue: fiatAmountValue,
fee: fee,
feeRate: feeRate,
feeValue: feeValue,
feeFiatAmount: feeFiatAmount,
outputs: outputs);
@ -138,6 +144,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
required this.amountValue,
required this.fiatAmountValue,
required this.fee,
this.feeRate,
required this.feeValue,
required this.feeFiatAmount,
required this.outputs})
@ -153,6 +160,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
final String amountValue;
final String fiatAmountValue;
final String fee;
final String? feeRate;
final String feeValue;
final String feeFiatAmount;
final List<Output> outputs;
@ -183,7 +191,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
return Stack(alignment: Alignment.center, clipBehavior: Clip.none, children: [
Container(
height: 200,
height: feeRate != null ? 250 : 200,
child: SingleChildScrollView(
controller: controller,
child: Column(
@ -311,6 +319,36 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
)
],
)),
if (feeRate != null && feeRate!.isNotEmpty)
Padding(
padding: EdgeInsets.only(top: 16),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
S.current.send_estimated_fee,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
fontFamily: 'Lato',
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
decoration: TextDecoration.none,
),
),
Text(
"$feeRate sat/byte",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
fontFamily: 'Lato',
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
decoration: TextDecoration.none,
),
)
],
)),
Padding(
padding: EdgeInsets.only(top: 16),
child: Column(

View file

@ -46,9 +46,6 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
itemBuilder: (_, int index) {
return Observer(builder: (_) {
final item = unspentCoinsListViewModel.items[index];
final address = unspentCoinsListViewModel.wallet.type == WalletType.bitcoinCash
? bitcoinCash!.getCashAddrFormat(item.address)
: item.address;
return GestureDetector(
onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsDetails,
@ -56,7 +53,7 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
child: UnspentCoinsListItem(
note: item.note,
amount: item.amount,
address: address,
address: item.address,
isSending: item.isSending,
isFrozen: item.isFrozen,
isChange: item.isChange,

View file

@ -46,6 +46,8 @@ abstract class ContactListViewModelBase with Store {
name,
walletTypeToCryptoCurrency(info.type),
));
// Only one contact address per wallet
return;
});
} else if (info.address != null) {
walletContacts.add(WalletContact(

View file

@ -105,6 +105,7 @@ abstract class ExchangeTradeViewModelBase with Store {
output.address = trade.inputAddress ?? '';
output.setCryptoAmount(trade.amount);
if (_provider is ThorChainExchangeProvider) output.memo = trade.memo;
if (trade.isSendAll == true) output.sendAll = true;
sendViewModel.selectedCryptoCurrency = trade.from;
final pendingTransaction = await sendViewModel.createTransaction(provider: _provider);
if (_provider is ThorChainExchangeProvider) {
@ -116,6 +117,8 @@ abstract class ExchangeTradeViewModelBase with Store {
@action
Future<void> _updateTrade() async {
try {
final agreedAmount = tradesStore.trade!.amount;
final isSendAll = tradesStore.trade!.isSendAll;
final updatedTrade = await _provider!.findTradeById(id: trade.id);
if (updatedTrade.createdAt == null && trade.createdAt != null)
@ -124,6 +127,8 @@ abstract class ExchangeTradeViewModelBase with Store {
if (updatedTrade.amount.isEmpty) updatedTrade.amount = trade.amount;
trade = updatedTrade;
trade.amount = agreedAmount;
trade.isSendAll = isSendAll;
_updateItems();
} catch (e) {
@ -137,9 +142,9 @@ abstract class ExchangeTradeViewModelBase with Store {
final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : '';
items.clear();
if(trade.provider != ExchangeProviderDescription.thorChain)
items.add(ExchangeTradeItem(
title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true));
if (trade.provider != ExchangeProviderDescription.thorChain)
items.add(ExchangeTradeItem(
title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true));
if (trade.extraId != null) {
final title = trade.from == CryptoCurrency.xrp

View file

@ -470,6 +470,18 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
@action
Future<void> createTrade() async {
if (isSendAllEnabled) {
await calculateDepositAllAmount();
final amount = double.tryParse(depositAmount);
if (limits.min != null && amount != null && amount < limits.min!) {
tradeState = TradeIsCreatedFailure(
title: S.current.trade_not_created,
error: S.current.amount_is_below_minimum_limit(limits.min!.toString()));
return;
}
}
try {
for (var provider in _sortedAvailableProviders.values) {
if (!(await provider.checkIsAvailable())) continue;
@ -496,8 +508,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
else {
try {
tradeState = TradeIsCreating();
final trade =
await provider.createTrade(request: request, isFixedRateMode: isFixedRateMode);
final trade = await provider.createTrade(
request: request,
isFixedRateMode: isFixedRateMode,
isSendAll: isSendAllEnabled,
);
trade.walletId = wallet.id;
trade.fromWalletAddress = wallet.walletAddresses.address;
@ -551,25 +566,24 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
@action
void enableSendAllAmount() {
isSendAllEnabled = true;
isFixedRateMode = false;
calculateDepositAllAmount();
}
@action
void enableFixedRateMode() {
isSendAllEnabled = false;
isFixedRateMode = true;
}
@action
Future<void> calculateDepositAllAmount() async {
if (wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) {
final availableBalance = wallet.balance[wallet.currency]!.available;
final priority = _settingsStore.priority[wallet.type]!;
final fee = wallet.calculateEstimatedFee(priority, null);
if (availableBalance < fee || availableBalance == 0) return;
final amount = availableBalance - fee;
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
} else if (wallet.type == WalletType.bitcoin) {
if (wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.bitcoinCash) {
final priority = _settingsStore.priority[wallet.type]!;
final amount = await bitcoin!.estimateFakeSendAllTxAmount(
wallet, bitcoin!.deserializeBitcoinTransactionPriority(priority.raw));
final amount = await bitcoin!.estimateFakeSendAllTxAmount(wallet, priority);
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
}

View file

@ -14,6 +14,7 @@ import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
import 'package:cw_core/exceptions.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:cake_wallet/view_model/send/send_template_view_model.dart';
@ -309,9 +310,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
state = ExecutedSuccessfullyState();
return pendingTransaction;
} catch (e) {
print('Failed with ${e.toString()}');
state = FailureState(e.toString());
return null;
state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency));
}
}
@ -353,8 +352,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
state = TransactionCommitted();
} catch (e) {
String translatedError = translateErrorMessage(e.toString(), wallet.type, wallet.currency);
state = FailureState(translatedError);
state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency));
}
}
@ -429,11 +427,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
}
ContactRecord? newContactAddress () {
ContactRecord? newContactAddress() {
final Set<String> contactAddresses =
Set.from(contactListViewModel.contacts.map((contact) => contact.address))
..addAll(contactListViewModel.walletContacts.map((contact) => contact.address));
Set.from(contactListViewModel.contacts.map((contact) => contact.address))
..addAll(contactListViewModel.walletContacts.map((contact) => contact.address));
for (var output in outputs) {
String address;
@ -444,7 +441,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
if (address.isNotEmpty && !contactAddresses.contains(address)) {
return ContactRecord(
contactListViewModel.contactSource,
Contact(
@ -458,22 +454,59 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
String translateErrorMessage(
String error,
Object error,
WalletType walletType,
CryptoCurrency currency,
) {
String errorMessage = error.toString();
if (walletType == WalletType.ethereum ||
walletType == WalletType.polygon ||
walletType == WalletType.solana ||
walletType == WalletType.haven) {
if (error.contains('gas required exceeds allowance') ||
error.contains('insufficient funds')) {
if (errorMessage.contains('gas required exceeds allowance') ||
errorMessage.contains('insufficient funds')) {
return S.current.do_not_have_enough_gas_asset(currency.toString());
}
return error;
return errorMessage;
}
return error;
if (walletType == WalletType.bitcoin ||
walletType == WalletType.litecoin ||
walletType == WalletType.bitcoinCash) {
if (error is TransactionWrongBalanceException) {
return S.current.tx_wrong_balance_exception(currency.toString());
}
if (error is TransactionNoInputsException) {
return S.current.tx_not_enough_inputs_exception;
}
if (error is TransactionNoFeeException) {
return S.current.tx_zero_fee_exception;
}
if (error is TransactionNoDustException) {
return S.current.tx_no_dust_exception;
}
if (error is TransactionCommitFailed) {
return S.current.tx_commit_failed;
}
if (error is TransactionCommitFailedDustChange) {
return S.current.tx_rejected_dust_change;
}
if (error is TransactionCommitFailedDustOutput) {
return S.current.tx_rejected_dust_output;
}
if (error is TransactionCommitFailedDustOutputSendAll) {
return S.current.tx_rejected_dust_output_send_all;
}
if (error is TransactionCommitFailedVoutNegative) {
return S.current.tx_rejected_vout_negative;
}
if (error is TransactionNoDustOnChangeException) {
return S.current.tx_commit_exception_no_dust_on_change(error.min, error.max);
}
}
return errorMessage;
}
}

View file

@ -100,7 +100,5 @@ abstract class UnspentCoinsDetailsViewModelBase with Store {
final WalletType _type;
List<TransactionDetailsListItem> items;
String get formattedAddress => WalletType.bitcoinCash == _type
? bitcoinCash!.getCashAddrFormat(unspentCoinsItem.address)
: unspentCoinsItem.address;
String get formattedAddress => unspentCoinsItem.address;
}

View file

@ -43,6 +43,7 @@
"already_have_account": "لديك حساب؟",
"always": "دائماً",
"amount": "مقدار:",
"amount_is_below_minimum_limit": "سيكون رصيدك بعد الرسوم أقل من الحد الأدنى للمبلغ اللازم للتبادل (${min})",
"amount_is_estimate": "المبلغ المستلم هو تقدير",
"amount_is_guaranteed": "مبلغ الاستلام مضمون",
"and": "و",
@ -712,6 +713,16 @@
"transactions": "المعاملات",
"transactions_by_date": "المعاملات حسب التاريخ",
"trusted": "موثوق به",
"tx_commit_exception_no_dust_on_change": "يتم رفض المعاملة مع هذا المبلغ. باستخدام هذه العملات المعدنية ، يمكنك إرسال ${min} دون تغيير أو ${max} الذي يعيد التغيير.",
"tx_commit_failed": "فشل ارتكاب المعاملة. يرجى الاتصال بالدعم.",
"tx_no_dust_exception": "يتم رفض المعاملة عن طريق إرسال مبلغ صغير جدًا. يرجى محاولة زيادة المبلغ.",
"tx_not_enough_inputs_exception": "لا يكفي المدخلات المتاحة. الرجاء تحديد المزيد تحت التحكم في العملة",
"tx_rejected_dust_change": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، ومبلغ التغيير المنخفض (الغبار). حاول إرسال كل أو تقليل المبلغ.",
"tx_rejected_dust_output": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، وكمية الإخراج المنخفض (الغبار). يرجى زيادة المبلغ.",
"tx_rejected_dust_output_send_all": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، وكمية الإخراج المنخفض (الغبار). يرجى التحقق من رصيد العملات المعدنية المحددة تحت التحكم في العملة.",
"tx_rejected_vout_negative": "لا يوجد ما يكفي من الرصيد لدفع رسوم هذه الصفقة. يرجى التحقق من رصيد العملات المعدنية تحت السيطرة على العملة.",
"tx_wrong_balance_exception": "ليس لديك ما يكفي من ${currency} لإرسال هذا المبلغ.",
"tx_zero_fee_exception": "لا يمكن إرسال معاملة مع 0 رسوم. حاول زيادة المعدل أو التحقق من اتصالك للحصول على أحدث التقديرات.",
"unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ",
"unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ",
"unconfirmed": "رصيد غير مؤكد",

View file

@ -43,6 +43,7 @@
"already_have_account": "Вече имате профил?",
"always": "Винаги",
"amount": "Сума: ",
"amount_is_below_minimum_limit": "Вашето салдо след такси ще бъде по -малко от минималната сума, необходима за борсата (${min})",
"amount_is_estimate": "Сумата за получаване е ",
"amount_is_guaranteed": "Сумата за получаване е гарантирана",
"and": "и",
@ -712,6 +713,16 @@
"transactions": "Транзакции",
"transactions_by_date": "Транзакции по дата",
"trusted": "Надежден",
"tx_commit_exception_no_dust_on_change": "Сделката се отхвърля с тази сума. С тези монети можете да изпратите ${min} без промяна или ${max}, която връща промяна.",
"tx_commit_failed": "Компетацията на транзакцията не успя. Моля, свържете се с поддръжката.",
"tx_no_dust_exception": "Сделката се отхвърля чрез изпращане на сума твърде малка. Моля, опитайте да увеличите сумата.",
"tx_not_enough_inputs_exception": "Няма достатъчно налични входове. Моля, изберете повече под контрол на монети",
"tx_rejected_dust_change": "Транзакция, отхвърлена от мрежови правила, ниска сума на промяна (прах). Опитайте да изпратите всички или да намалите сумата.",
"tx_rejected_dust_output": "Транзакция, отхвърлена от мрежови правила, ниска стойност на изхода (прах). Моля, увеличете сумата.",
"tx_rejected_dust_output_send_all": "Транзакция, отхвърлена от мрежови правила, ниска стойност на изхода (прах). Моля, проверете баланса на монетите, избрани под контрол на монети.",
"tx_rejected_vout_negative": "Няма достатъчно баланс, за да платите за таксите на тази транзакция. Моля, проверете баланса на монетите под контрол на монетите.",
"tx_wrong_balance_exception": "Нямате достатъчно ${currency}, за да изпратите тази сума.",
"tx_zero_fee_exception": "Не може да изпраща транзакция с 0 такса. Опитайте да увеличите скоростта или да проверите връзката си за най -новите оценки.",
"unavailable_balance": "Неналично салдо",
"unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.",
"unconfirmed": "Непотвърден баланс",

View file

@ -43,6 +43,7 @@
"already_have_account": "Máte už účet?",
"always": "Vždy",
"amount": "Částka: ",
"amount_is_below_minimum_limit": "Váš zůstatek po poplatcích by byl menší než minimální částka potřebná pro burzu (${min})",
"amount_is_estimate": "Částka, kterou dostanete, je jen odhad.",
"amount_is_guaranteed": "Částka, kterou dostanete, je konečná",
"and": "a",
@ -712,6 +713,16 @@
"transactions": "Transakce",
"transactions_by_date": "Transakce podle data",
"trusted": "Důvěřovat",
"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.",
"tx_commit_failed": "Transakce COMPORT selhala. Kontaktujte prosím podporu.",
"tx_no_dust_exception": "Transakce je zamítnuta odesláním příliš malé. Zkuste prosím zvýšit částku.",
"tx_not_enough_inputs_exception": "Není k dispozici dostatek vstupů. Vyberte prosím více pod kontrolou mincí",
"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.",
"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.",
"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í.",
"tx_rejected_vout_negative": "Nedostatek zůstatek na zaplacení poplatků za tuto transakci. Zkontrolujte prosím zůstatek mincí pod kontrolou mincí.",
"tx_wrong_balance_exception": "Nemáte dost ${currency} pro odeslání této částky.",
"tx_zero_fee_exception": "Nelze odeslat transakci s 0 poplatkem. Zkuste zvýšit sazbu nebo zkontrolovat připojení pro nejnovější odhady.",
"unavailable_balance": "Nedostupný zůstatek",
"unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.",
"unconfirmed": "Nepotvrzený zůstatek",

View file

@ -43,6 +43,7 @@
"already_have_account": "Sie haben bereits ein Konto?",
"always": "immer",
"amount": "Betrag: ",
"amount_is_below_minimum_limit": "Ihr Saldo nach Gebühren wäre geringer als der für den Austausch benötigte Mindestbetrag (${min})",
"amount_is_estimate": "Der empfangene Betrag ist eine Schätzung",
"amount_is_guaranteed": "Der Empfangsbetrag ist garantiert",
"and": "Und",
@ -713,6 +714,16 @@
"transactions": "Transaktionen",
"transactions_by_date": "Transaktionen nach Datum",
"trusted": "Vertrauenswürdige",
"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.",
"tx_commit_failed": "Transaktionsausschüsse ist fehlgeschlagen. Bitte wenden Sie sich an Support.",
"tx_no_dust_exception": "Die Transaktion wird abgelehnt, indem eine Menge zu klein gesendet wird. Bitte versuchen Sie, die Menge zu erhöhen.",
"tx_not_enough_inputs_exception": "Nicht genügend Eingänge verfügbar. Bitte wählen Sie mehr unter Münzkontrolle aus",
"tx_rejected_dust_change": "Transaktion abgelehnt durch Netzwerkregeln, niedriger Änderungsbetrag (Staub). Versuchen Sie, alle zu senden oder die Menge zu reduzieren.",
"tx_rejected_dust_output": "Transaktion durch Netzwerkregeln, niedriger Ausgangsmenge (Staub) abgelehnt. Bitte erhöhen Sie den Betrag.",
"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.",
"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.",
"tx_wrong_balance_exception": "Sie haben nicht genug ${currency}, um diesen Betrag zu senden.",
"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.",
"unavailable_balance": "Nicht verfügbares Guthaben",
"unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.",
"unconfirmed": "Unbestätigter Saldo",

View file

@ -43,6 +43,7 @@
"already_have_account": "Already have an account?",
"always": "Always",
"amount": "Amount: ",
"amount_is_below_minimum_limit": "Your balance after fees would be less than the minimum amount needed for the exchange (${min})",
"amount_is_estimate": "The receive amount is an estimate",
"amount_is_guaranteed": "The receive amount is guaranteed",
"and": "and",
@ -712,6 +713,16 @@
"transactions": "Transactions",
"transactions_by_date": "Transactions by date",
"trusted": "Trusted",
"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.",
"tx_commit_failed": "Transaction commit failed. Please contact support.",
"tx_no_dust_exception": "The transaction is rejected by sending an amount too small. Please try increasing the amount.",
"tx_not_enough_inputs_exception": "Not enough inputs available. Please select more under Coin Control",
"tx_rejected_dust_change": "Transaction rejected by network rules, low change amount (dust). Try sending ALL or reducing the amount.",
"tx_rejected_dust_output": "Transaction rejected by network rules, low output amount (dust). Please increase the amount.",
"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.",
"tx_rejected_vout_negative": "Not enough balance to pay for this transaction's fees. Please check the balance of coins under Coin Control.",
"tx_wrong_balance_exception": "You do not have enough ${currency} to send this amount.",
"tx_zero_fee_exception": "Cannot send transaction with 0 fee. Try increasing the rate or checking your connection for latest estimates.",
"unavailable_balance": "Unavailable balance",
"unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.",
"unconfirmed": "Unconfirmed Balance",

View file

@ -43,6 +43,7 @@
"already_have_account": "¿Ya tienes una cuenta?",
"always": "siempre",
"amount": "Cantidad: ",
"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})",
"amount_is_estimate": "El monto recibido es un estimado",
"amount_is_guaranteed": "La cantidad recibida está garantizada",
"and": "y",
@ -713,6 +714,16 @@
"transactions": "Actas",
"transactions_by_date": "Transacciones por fecha",
"trusted": "de confianza",
"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.",
"tx_commit_failed": "La confirmación de transacción falló. Póngase en contacto con el soporte.",
"tx_no_dust_exception": "La transacción se rechaza enviando una cantidad demasiado pequeña. Intente aumentar la cantidad.",
"tx_not_enough_inputs_exception": "No hay suficientes entradas disponibles. Seleccione más bajo control de monedas",
"tx_rejected_dust_change": "Transacción rechazada por reglas de red, bajo cambio de cambio (polvo). Intente enviar todo o reducir la cantidad.",
"tx_rejected_dust_output": "Transacción rechazada por reglas de red, baja cantidad de salida (polvo). Aumente la cantidad.",
"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.",
"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.",
"tx_wrong_balance_exception": "No tiene suficiente ${currency} para enviar esta cantidad.",
"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.",
"unavailable_balance": "Saldo no disponible",
"unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.",
"unconfirmed": "Saldo no confirmado",

View file

@ -43,6 +43,7 @@
"already_have_account": "Vous avez déjà un compte ?",
"always": "toujours",
"amount": "Montant : ",
"amount_is_below_minimum_limit": "Votre solde après les frais serait inférieur au montant minimum nécessaire à l'échange (${min})",
"amount_is_estimate": "Le montant reçu est estimé",
"amount_is_guaranteed": "Le montant reçu est garanti",
"and": "et",
@ -712,6 +713,16 @@
"transactions": "Transactions",
"transactions_by_date": "Transactions par date",
"trusted": "de confiance",
"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.",
"tx_commit_failed": "La validation de la transaction a échoué. Veuillez contacter l'assistance.",
"tx_no_dust_exception": "La transaction est rejetée en envoyant un montant trop faible. Veuillez essayer d'augmenter le montant.",
"tx_not_enough_inputs_exception": "Pas assez d'entrées disponibles. Veuillez sélectionner plus sous Control Control",
"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.",
"tx_rejected_dust_output": "Transaction rejetée par les règles du réseau, faible quantité de sortie (poussière). Veuillez augmenter le montant.",
"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.",
"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.",
"tx_wrong_balance_exception": "Vous n'avez pas assez ${currency} pour envoyer ce montant.",
"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.",
"unavailable_balance": "Solde indisponible",
"unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.",
"unconfirmed": "Solde non confirmé",

View file

@ -43,6 +43,7 @@
"already_have_account": "Kuna da asusu?",
"always": "Koyaushe",
"amount": "Adadi:",
"amount_is_below_minimum_limit": "Daidaitarku bayan kudade zai zama ƙasa da mafi ƙarancin adadin da ake buƙata don musayar (${min}",
"amount_is_estimate": "Adadin da aka karɓa shine kimantawa",
"amount_is_guaranteed": "Adadin da aka karɓa yana da garanti",
"and": "kuma",
@ -714,6 +715,16 @@
"transactions": "Ma'amaloli",
"transactions_by_date": "Ma'amaloli ta kwanan wata",
"trusted": "Amintacce",
"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.",
"tx_commit_failed": "Ma'amala ya kasa. Da fatan za a tuntuɓi goyan baya.",
"tx_no_dust_exception": "An ƙi ma'amala ta hanyar aika adadin ƙarami. Da fatan za a gwada ƙara adadin.",
"tx_not_enough_inputs_exception": "Bai isa ba hanyoyin da ake samu. Da fatan za selectiari a karkashin Kwarewar Coin",
"tx_rejected_dust_change": "Ma'amala ta ƙi ta dokokin cibiyar sadarwa, ƙarancin canji (ƙura). Gwada aikawa da duka ko rage adadin.",
"tx_rejected_dust_output": "Ma'adar da aka ƙi ta dokokin cibiyar sadarwa, ƙananan fitarwa (ƙura). Da fatan za a ƙara adadin.",
"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.",
"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.",
"tx_wrong_balance_exception": "Ba ku da isasshen ${currency} don aika wannan adadin.",
"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.",
"unavailable_balance": "Ma'aunin da ba ya samuwa",
"unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.",
"unconfirmed": "Ba a tabbatar ba",

View file

@ -43,6 +43,7 @@
"already_have_account": "क्या आपके पास पहले से एक खाता मौजूद है?",
"always": "हमेशा",
"amount": "रकम: ",
"amount_is_below_minimum_limit": "फीस के बाद आपका संतुलन विनिमय के लिए आवश्यक न्यूनतम राशि से कम होगा (${min})",
"amount_is_estimate": "प्राप्त राशि एक अनुमान है",
"amount_is_guaranteed": "प्राप्त राशि की गारंटी है",
"and": "और",
@ -714,6 +715,16 @@
"transactions": "लेन-देन",
"transactions_by_date": "तारीख से लेन-देन",
"trusted": "भरोसा",
"tx_commit_exception_no_dust_on_change": "लेनदेन को इस राशि से खारिज कर दिया जाता है। इन सिक्कों के साथ आप चेंज या ${min} के बिना ${max} को भेज सकते हैं जो परिवर्तन लौटाता है।",
"tx_commit_failed": "लेन -देन प्रतिबद्ध विफल। कृपया संपर्क समर्थन करें।",
"tx_no_dust_exception": "लेनदेन को बहुत छोटी राशि भेजकर अस्वीकार कर दिया जाता है। कृपया राशि बढ़ाने का प्रयास करें।",
"tx_not_enough_inputs_exception": "पर्याप्त इनपुट उपलब्ध नहीं है। कृपया सिक्का नियंत्रण के तहत अधिक चुनें",
"tx_rejected_dust_change": "नेटवर्क नियमों, कम परिवर्तन राशि (धूल) द्वारा खारिज किए गए लेनदेन। सभी भेजने या राशि को कम करने का प्रयास करें।",
"tx_rejected_dust_output": "नेटवर्क नियमों, कम आउटपुट राशि (धूल) द्वारा खारिज किए गए लेनदेन। कृपया राशि बढ़ाएं।",
"tx_rejected_dust_output_send_all": "नेटवर्क नियमों, कम आउटपुट राशि (धूल) द्वारा खारिज किए गए लेनदेन। कृपया सिक्का नियंत्रण के तहत चुने गए सिक्कों के संतुलन की जाँच करें।",
"tx_rejected_vout_negative": "इस लेनदेन की फीस के लिए भुगतान करने के लिए पर्याप्त शेष राशि नहीं है। कृपया सिक्के नियंत्रण के तहत सिक्कों के संतुलन की जाँच करें।",
"tx_wrong_balance_exception": "इस राशि को भेजने के लिए आपके पास पर्याप्त ${currency} नहीं है।",
"tx_zero_fee_exception": "0 शुल्क के साथ लेनदेन नहीं भेज सकते। नवीनतम अनुमानों के लिए दर बढ़ाने या अपने कनेक्शन की जांच करने का प्रयास करें।",
"unavailable_balance": "अनुपलब्ध शेष",
"unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।",
"unconfirmed": "अपुष्ट शेष राशि",

View file

@ -43,6 +43,7 @@
"already_have_account": "Već imate račun?",
"always": "Uvijek",
"amount": "Iznos: ",
"amount_is_below_minimum_limit": "Vaša bilanca nakon naknada bila bi manja od minimalnog iznosa potrebnog za razmjenu (${min})",
"amount_is_estimate": "Iznos koji ćete primiti je okviran",
"amount_is_guaranteed": "Iznos koji ćete primiti je zajamčen",
"and": "i",
@ -712,6 +713,16 @@
"transactions": "Transakcije",
"transactions_by_date": "Transakcije prema datumu",
"trusted": "vjerovao",
"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.",
"tx_commit_failed": "Obveza transakcije nije uspjela. Molimo kontaktirajte podršku.",
"tx_no_dust_exception": "Transakcija se odbija slanjem iznosa premalo. Pokušajte povećati iznos.",
"tx_not_enough_inputs_exception": "Nema dovoljno unosa. Molimo odaberite više pod kontrolom novčića",
"tx_rejected_dust_change": "Transakcija odbijena mrežnim pravilima, niska količina promjene (prašina). Pokušajte poslati sve ili smanjiti iznos.",
"tx_rejected_dust_output": "Transakcija odbijena mrežnim pravilima, niska količina izlaza (prašina). Molimo povećajte iznos.",
"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.",
"tx_rejected_vout_negative": "Nema dovoljno salda za plaćanje naknada ove transakcije. Molimo provjerite ravnotežu kovanica pod kontrolom novčića.",
"tx_wrong_balance_exception": "Nemate dovoljno ${currency} da biste poslali ovaj iznos.",
"tx_zero_fee_exception": "Ne mogu poslati transakciju s 0 naknade. Pokušajte povećati stopu ili provjeriti vezu za najnovije procjene.",
"unavailable_balance": "Nedostupno stanje",
"unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.",
"unconfirmed": "Nepotvrđeno stanje",

View file

@ -43,6 +43,7 @@
"already_have_account": "Sudah punya akun?",
"always": "Selalu",
"amount": "Jumlah: ",
"amount_is_below_minimum_limit": "Saldo Anda setelah biaya akan kurang dari jumlah minimum yang dibutuhkan untuk pertukaran (${min})",
"amount_is_estimate": "Jumlah penerimaan diperkirakan",
"amount_is_guaranteed": "Jumlah penerimaan dijamin",
"and": "dan",
@ -715,6 +716,16 @@
"transactions": "Transaksi",
"transactions_by_date": "Transaksi berdasarkan tanggal",
"trusted": "Dipercayai",
"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.",
"tx_commit_failed": "Transaksi Gagal. Silakan hubungi Dukungan.",
"tx_no_dust_exception": "Transaksi ditolak dengan mengirimkan jumlah yang terlalu kecil. Silakan coba tingkatkan jumlahnya.",
"tx_not_enough_inputs_exception": "Tidak cukup input yang tersedia. Pilih lebih banyak lagi di bawah Kontrol Koin",
"tx_rejected_dust_change": "Transaksi ditolak oleh aturan jaringan, jumlah perubahan rendah (debu). Coba kirim semua atau mengurangi jumlahnya.",
"tx_rejected_dust_output": "Transaksi ditolak oleh aturan jaringan, jumlah output rendah (debu). Harap tingkatkan jumlahnya.",
"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.",
"tx_rejected_vout_negative": "Tidak cukup saldo untuk membayar biaya transaksi ini. Silakan periksa saldo koin di bawah kendali koin.",
"tx_wrong_balance_exception": "Anda tidak memiliki cukup ${currency} untuk mengirim jumlah ini.",
"tx_zero_fee_exception": "Tidak dapat mengirim transaksi dengan biaya 0. Coba tingkatkan tarif atau periksa koneksi Anda untuk perkiraan terbaru.",
"unavailable_balance": "Saldo tidak tersedia",
"unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.",
"unconfirmed": "Saldo Belum Dikonfirmasi",

View file

@ -43,6 +43,7 @@
"already_have_account": "Hai già un account?",
"always": "sempre",
"amount": "Ammontare: ",
"amount_is_below_minimum_limit": "Il saldo dopo le commissioni sarebbe inferiore all'importo minimo necessario per lo scambio (${min})",
"amount_is_estimate": "L'ammontare da ricevere è una stima",
"amount_is_guaranteed": "L'ammontare da ricevere è fisso",
"and": "e",
@ -714,6 +715,16 @@
"transactions": "Transazioni",
"transactions_by_date": "Transazioni per data",
"trusted": "di fiducia",
"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.",
"tx_commit_failed": "Commit di transazione non riuscita. Si prega di contattare il supporto.",
"tx_no_dust_exception": "La transazione viene respinta inviando un importo troppo piccolo. Per favore, prova ad aumentare l'importo.",
"tx_not_enough_inputs_exception": "Input non sufficienti disponibili. Seleziona di più sotto il controllo delle monete",
"tx_rejected_dust_change": "Transazione respinta dalle regole di rete, quantità bassa variazione (polvere). Prova a inviare tutto o ridurre l'importo.",
"tx_rejected_dust_output": "Transazione respinta dalle regole di rete, bassa quantità di output (polvere). Si prega di aumentare l'importo.",
"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.",
"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.",
"tx_wrong_balance_exception": "Non hai abbastanza ${currency} per inviare questo importo.",
"tx_zero_fee_exception": "Impossibile inviare transazioni con 0 tassa. Prova ad aumentare la tariffa o controlla la connessione per le ultime stime.",
"unavailable_balance": "Saldo non disponibile",
"unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.",
"unconfirmed": "Saldo non confermato",

View file

@ -43,6 +43,7 @@
"already_have_account": "すでにアカウントをお持ちですか?",
"always": "いつも",
"amount": "量: ",
"amount_is_below_minimum_limit": "手数料後の残高は、交換に必要な最低額(${min})よりも少なくなります",
"amount_is_estimate": "受け取り金額は見積もりです",
"amount_is_guaranteed": "受け取り金額は保証されています",
"and": "と",
@ -713,6 +714,16 @@
"transactions": "取引",
"transactions_by_date": "日付ごとの取引",
"trusted": "信頼できる",
"tx_commit_exception_no_dust_on_change": "この金額ではトランザクションは拒否されます。 これらのコインを使用すると、おつりなしの ${min} またはおつりを返す ${max} を送信できます。",
"tx_commit_failed": "トランザクションコミットは失敗しました。サポートに連絡してください。",
"tx_no_dust_exception": "トランザクションは、小さすぎる金額を送信することにより拒否されます。量を増やしてみてください。",
"tx_not_enough_inputs_exception": "利用可能な入力が十分ではありません。コイン制御下でもっと選択してください",
"tx_rejected_dust_change": "ネットワークルール、低い変更量(ほこり)によって拒否されたトランザクション。すべてを送信するか、金額を減らしてみてください。",
"tx_rejected_dust_output": "ネットワークルール、低出力量(ダスト)によって拒否されたトランザクション。金額を増やしてください。",
"tx_rejected_dust_output_send_all": "ネットワークルール、低出力量(ダスト)によって拒否されたトランザクション。コイン管理下で選択されたコインのバランスを確認してください。",
"tx_rejected_vout_negative": "この取引の料金に支払うのに十分な残高はありません。コイン制御下のコインのバランスを確認してください。",
"tx_wrong_balance_exception": "この金額を送信するのに十分な${currency}はありません。",
"tx_zero_fee_exception": "0料金でトランザクションを送信できません。レートを上げて、最新の見積もりについて接続を確認してみてください。",
"unavailable_balance": "利用できない残高",
"unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。",
"unconfirmed": "残高未確認",

View file

@ -43,6 +43,7 @@
"already_have_account": "이미 계정이 있습니까?",
"always": "언제나",
"amount": "양: ",
"amount_is_below_minimum_limit": "수수료 후 잔액은 Exchange (${min})에 필요한 최소 금액보다 적습니다.",
"amount_is_estimate": "수신 금액은 견적입니다",
"amount_is_guaranteed": "수령 금액이 보장됩니다.",
"and": "그리고",
@ -713,6 +714,16 @@
"transactions": "업무",
"transactions_by_date": "날짜 별 거래",
"trusted": "신뢰할 수 있는",
"tx_commit_exception_no_dust_on_change": "이 금액으로 거래가 거부되었습니다. 이 코인을 사용하면 거스름돈 없이 ${min}를 보내거나 거스름돈을 반환하는 ${max}를 보낼 수 있습니다.",
"tx_commit_failed": "거래 커밋이 실패했습니다. 지원에 연락하십시오.",
"tx_no_dust_exception": "너무 작은 금액을 보내면 거래가 거부됩니다. 금액을 늘리십시오.",
"tx_not_enough_inputs_exception": "사용 가능한 입력이 충분하지 않습니다. 코인 컨트롤에서 더 많은 것을 선택하십시오",
"tx_rejected_dust_change": "네트워크 규칙, 낮은 변경 금액 (먼지)에 의해 거부 된 거래. 전부를 보내거나 금액을 줄이십시오.",
"tx_rejected_dust_output": "네트워크 규칙, 낮은 출력 금액 (먼지)에 의해 거부 된 거래. 금액을 늘리십시오.",
"tx_rejected_dust_output_send_all": "네트워크 규칙, 낮은 출력 금액 (먼지)에 의해 거부 된 거래. 동전 제어에서 선택한 동전의 균형을 확인하십시오.",
"tx_rejected_vout_negative": "이 거래 수수료를 지불하기에 잔액이 충분하지 않습니다. 동전 통제하에 동전의 균형을 확인하십시오.",
"tx_wrong_balance_exception": "이 금액을 보내기에 충분한 ${currency}가 충분하지 않습니다.",
"tx_zero_fee_exception": "0 수수료로 거래를 보낼 수 없습니다. 최신 견적에 대해서는 속도를 높이거나 연결을 확인하십시오.",
"unavailable_balance": "사용할 수 없는 잔액",
"unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.",
"unconfirmed": "확인되지 않은 잔액",

View file

@ -43,6 +43,7 @@
"already_have_account": "အကောင့်ရှိပြီးသားလား?",
"always": "အမြဲတမ်း",
"amount": "ပမာဏ:",
"amount_is_below_minimum_limit": "ငွေလဲလှယ်ရန်လိုအပ်သည့်အနိမ့်ဆုံးပမာဏထက်လျော့နည်းသွားပြီးသည့်နောက်ငွေလက်ကျန်ငွေပမာဏသည်ငွေလဲလှယ်မှုအတွက်လိုအပ်သည့်အနိမ့်ဆုံးပမာဏထက်နည်းသည် (${min})",
"amount_is_estimate": "ရရှိသည့်ပမာဏသည် ခန့်မှန်းချက်တစ်ခုဖြစ်သည်။",
"amount_is_guaranteed": "ရရှိသည့်ပမာဏကို အာမခံပါသည်။",
"and": "နှင့်",
@ -712,6 +713,16 @@
"transactions": "ငွေပေးငွေယူ",
"transactions_by_date": "ရက်စွဲအလိုက် ငွေလွှဲမှုများ",
"trusted": "ယုံတယ်။",
"tx_commit_exception_no_dust_on_change": "အဆိုပါငွေပေးငွေယူကဒီပမာဏနှင့်အတူပယ်ချခံရသည်။ ဤဒင်္ဂါးပြားများနှင့်အတူပြောင်းလဲမှုကိုပြန်လည်ပြောင်းလဲခြင်းသို့မဟုတ် ${min} မပါဘဲ ${max} ပေးပို့နိုင်သည်။",
"tx_commit_failed": "ငွေပေးငွေယူကျူးလွန်မှုပျက်ကွက်။ ကျေးဇူးပြုပြီးပံ့ပိုးမှုဆက်သွယ်ပါ။",
"tx_no_dust_exception": "ငွေပမာဏကိုသေးငယ်လွန်းသောငွေပမာဏကိုပေးပို့ခြင်းဖြင့်ပယ်ဖျက်ခြင်းကိုငြင်းပယ်သည်။ ကျေးဇူးပြုပြီးငွေပမာဏကိုတိုးမြှင့်ကြိုးစားပါ။",
"tx_not_enough_inputs_exception": "အလုံအလောက်သွင်းအားစုများမလုံလောက်။ ကျေးဇူးပြုပြီးဒင်္ဂါးပြားထိန်းချုပ်မှုအောက်တွင်ပိုမိုရွေးချယ်ပါ",
"tx_rejected_dust_change": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့်ပယ်ဖျက်ခြင်းသည် Network စည်းမျဉ်းစည်းကမ်းများဖြင့်ငြင်းပယ်ခြင်း, အားလုံးပေးပို့ခြင်းသို့မဟုတ်ငွေပမာဏကိုလျှော့ချကြိုးစားပါ။",
"tx_rejected_dust_output": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့် ပယ်ချ. ငွေပေးချေမှုသည် output output (ဖုန်မှုန့်) ဖြင့်ပယ်ချခဲ့သည်။ ကျေးဇူးပြုပြီးငွေပမာဏကိုတိုးမြှင့်ပေးပါ။",
"tx_rejected_dust_output_send_all": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့် ပယ်ချ. ငွေပေးချေမှုသည် output output (ဖုန်မှုန့်) ဖြင့်ပယ်ချခဲ့သည်။ ဒင်္ဂါးပြားထိန်းချုပ်မှုအောက်တွင်ရွေးချယ်ထားသောဒင်္ဂါးများ၏လက်ကျန်ငွေကိုစစ်ဆေးပါ။",
"tx_rejected_vout_negative": "ဒီငွေပေးငွေယူရဲ့အခကြေးငွေအတွက်ပေးဆောင်ဖို့လုံလောက်တဲ့ဟန်ချက်မလုံလောက်။ ဒင်္ဂါးပြား၏လက်ကျန်ငွေလက်ကျန်ငွေကိုစစ်ဆေးပါ။",
"tx_wrong_balance_exception": "ဤငွေပမာဏကိုပေးပို့ရန်သင့်တွင် ${currency} မရှိပါ။",
"tx_zero_fee_exception": "0 ကြေးနှင့်အတူငွေပေးငွေယူပေးပို့လို့မရပါဘူး။ နှုန်းကိုတိုးမြှင့်ခြင်းသို့မဟုတ်နောက်ဆုံးခန့်မှန်းချက်များအတွက်သင်၏ connection ကိုစစ်ဆေးပါ။",
"unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။",
"unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။",
"unconfirmed": "အတည်မပြုနိုင်သော လက်ကျန်ငွေ",

View file

@ -43,6 +43,7 @@
"already_have_account": "Heb je al een account?",
"always": "altijd",
"amount": "Bedrag: ",
"amount_is_below_minimum_limit": "Uw saldo na vergoedingen zou lager zijn dan het minimale bedrag dat nodig is voor de uitwisseling (${min})",
"amount_is_estimate": "Het ontvangen bedrag is een schatting",
"amount_is_guaranteed": "Het ontvangen bedrag is gegarandeerd",
"and": "en",
@ -712,6 +713,16 @@
"transactions": "Transacties",
"transactions_by_date": "Transacties op datum",
"trusted": "vertrouwd",
"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.",
"tx_commit_failed": "Transactiebewissing is mislukt. Neem contact op met de ondersteuning.",
"tx_no_dust_exception": "De transactie wordt afgewezen door een te klein bedrag te verzenden. Probeer het bedrag te verhogen.",
"tx_not_enough_inputs_exception": "Niet genoeg ingangen beschikbaar. Selecteer meer onder muntenbesturing",
"tx_rejected_dust_change": "Transactie afgewezen door netwerkregels, laag wijzigingsbedrag (stof). Probeer alles te verzenden of het bedrag te verminderen.",
"tx_rejected_dust_output": "Transactie afgewezen door netwerkregels, laag outputbedrag (stof). Verhoog het bedrag.",
"tx_rejected_dust_output_send_all": "Transactie afgewezen door netwerkregels, laag outputbedrag (stof). Controleer het saldo van munten die zijn geselecteerd onder muntcontrole.",
"tx_rejected_vout_negative": "Niet genoeg saldo om te betalen voor de kosten van deze transactie. Controleer het saldo van munten onder muntcontrole.",
"tx_wrong_balance_exception": "Je hebt niet genoeg ${currency} om dit bedrag te verzenden.",
"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.",
"unavailable_balance": "Onbeschikbaar saldo",
"unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.",
"unconfirmed": "Onbevestigd saldo",

View file

@ -43,6 +43,7 @@
"already_have_account": "Masz już konto?",
"always": "zawsze",
"amount": "Ilość: ",
"amount_is_below_minimum_limit": "Twoje saldo po opłatach byłoby mniejsze niż minimalna kwota potrzebna do wymiany (${min})",
"amount_is_estimate": "Otrzymana kwota jest wartością szacunkową",
"amount_is_guaranteed": "Otrzymana kwota jest gwarantowana",
"and": "i",
@ -712,6 +713,16 @@
"transactions": "Transakcje",
"transactions_by_date": "Transakcje według daty",
"trusted": "Zaufany",
"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ę.",
"tx_commit_failed": "Zatwierdzenie transakcji nie powiodło się. Skontaktuj się z obsługą.",
"tx_no_dust_exception": "Transakcja jest odrzucana przez wysyłanie zbyt małej ilości. Spróbuj zwiększyć kwotę.",
"tx_not_enough_inputs_exception": "Za mało dostępnych danych wejściowych. Wybierz więcej pod kontrolą monet",
"tx_rejected_dust_change": "Transakcja odrzucona według reguł sieciowych, niska ilość zmiany (kurz). Spróbuj wysłać całość lub zmniejszyć kwotę.",
"tx_rejected_dust_output": "Transakcja odrzucona według reguł sieciowych, niskiej ilości wyjściowej (pyłu). Zwiększ kwotę.",
"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.",
"tx_rejected_vout_negative": "Za mało salda, aby zapłacić za opłaty tej transakcji. Sprawdź saldo monet pod kontrolą monet.",
"tx_wrong_balance_exception": "Nie masz wystarczającej ilości ${currency}, aby wysłać tę kwotę.",
"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.",
"unavailable_balance": "Niedostępne saldo",
"unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.",
"unconfirmed": "Niepotwierdzone saldo",

View file

@ -43,6 +43,7 @@
"already_have_account": "Já tem uma conta?",
"always": "sempre",
"amount": "Quantia: ",
"amount_is_below_minimum_limit": "Seu saldo após as taxas seria menor que o valor mínimo necessário para a troca (${min})",
"amount_is_estimate": "O valor a ser recebido informado acima é uma estimativa",
"amount_is_guaranteed": "O valor recebido é garantido",
"and": "e",
@ -714,6 +715,16 @@
"transactions": "Transações",
"transactions_by_date": "Transações por data",
"trusted": "confiável",
"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.",
"tx_commit_failed": "A confirmação da transação falhou. Entre em contato com o suporte.",
"tx_no_dust_exception": "A transação é rejeitada enviando uma quantia pequena demais. Por favor, tente aumentar o valor.",
"tx_not_enough_inputs_exception": "Não há entradas disponíveis. Selecione mais sob controle de moedas",
"tx_rejected_dust_change": "Transação rejeitada pelas regras de rede, baixa quantidade de troco (poeira). Tente enviar tudo ou reduzir o valor.",
"tx_rejected_dust_output": "Transação rejeitada por regras de rede, baixa quantidade de saída (poeira). Por favor, aumente o valor.",
"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.",
"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.",
"tx_wrong_balance_exception": "Você não tem o suficiente ${currency} para enviar esse valor.",
"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.",
"unavailable_balance": "Saldo indisponível",
"unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.",
"unconfirmed": "Saldo não confirmado",

View file

@ -43,6 +43,7 @@
"already_have_account": "У вас уже есть аккаунт?",
"always": "всегда",
"amount": "Сумма: ",
"amount_is_below_minimum_limit": "Ваш баланс после сборов будет меньше, чем минимальная сумма, необходимая для обмена (${min}))",
"amount_is_estimate": "Полученная сумма является приблизительной",
"amount_is_guaranteed": "Полученная сумма гарантирована",
"and": "и",
@ -713,6 +714,16 @@
"transactions": "Транзакции",
"transactions_by_date": "Сортировать по дате",
"trusted": "доверенный",
"tx_commit_exception_no_dust_on_change": "Транзакция отклоняется с этой суммой. С этими монетами вы можете отправлять ${min} без изменения или ${max}, которые возвращают изменение.",
"tx_commit_failed": "Комплект транзакции не удался. Пожалуйста, свяжитесь с поддержкой.",
"tx_no_dust_exception": "Транзакция отклоняется путем отправки слишком маленькой суммы. Пожалуйста, попробуйте увеличить сумму.",
"tx_not_enough_inputs_exception": "Недостаточно входов доступны. Пожалуйста, выберите больше под контролем монет",
"tx_rejected_dust_change": "Транзакция отклоняется в соответствии с правилами сети, низкой суммой изменений (пыль). Попробуйте отправить все или уменьшить сумму.",
"tx_rejected_dust_output": "Транзакция отклоняется в соответствии с правилами сети, низкой выходной суммой (пыль). Пожалуйста, увеличьте сумму.",
"tx_rejected_dust_output_send_all": "Транзакция отклоняется в соответствии с правилами сети, низкой выходной суммой (пыль). Пожалуйста, проверьте баланс монет, выбранных под контролем монет.",
"tx_rejected_vout_negative": "Недостаточно баланс, чтобы оплатить плату этой транзакции. Пожалуйста, проверьте баланс монет под контролем монет.",
"tx_wrong_balance_exception": "У вас не хватает ${currency}, чтобы отправить эту сумму.",
"tx_zero_fee_exception": "Не может отправить транзакцию с платой 0. Попробуйте увеличить ставку или проверить соединение на наличие последних оценок.",
"unavailable_balance": "Недоступный баланс",
"unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.",
"unconfirmed": "Неподтвержденный баланс",

View file

@ -43,6 +43,7 @@
"already_have_account": "มีบัญชีอยู่แล้ว?",
"always": "เสมอ",
"amount": "จำนวน: ",
"amount_is_below_minimum_limit": "ยอดคงเหลือหลังจากค่าธรรมเนียมของคุณจะน้อยกว่าจำนวนเงินขั้นต่ำที่จำเป็นสำหรับการแลกเปลี่ยน (${min})",
"amount_is_estimate": "จำนวนที่จะได้รับเป็นการประมาณการ",
"amount_is_guaranteed": "จำนวนที่จะได้รับมีการรับประกัน",
"and": "และ",
@ -712,6 +713,16 @@
"transactions": "ธุรกรรม",
"transactions_by_date": "ธุรกรรมตามวันที่",
"trusted": "มั่นคง",
"tx_commit_exception_no_dust_on_change": "ธุรกรรมถูกปฏิเสธด้วยจำนวนเงินนี้ ด้วยเหรียญเหล่านี้คุณสามารถส่ง ${min} โดยไม่ต้องเปลี่ยนแปลงหรือ ${max} ที่ส่งคืนการเปลี่ยนแปลง",
"tx_commit_failed": "การทำธุรกรรมล้มเหลว กรุณาติดต่อฝ่ายสนับสนุน",
"tx_no_dust_exception": "การทำธุรกรรมถูกปฏิเสธโดยการส่งจำนวนน้อยเกินไป โปรดลองเพิ่มจำนวนเงิน",
"tx_not_enough_inputs_exception": "มีอินพุตไม่เพียงพอ โปรดเลือกเพิ่มเติมภายใต้การควบคุมเหรียญ",
"tx_rejected_dust_change": "ธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนการเปลี่ยนแปลงต่ำ (ฝุ่น) ลองส่งทั้งหมดหรือลดจำนวนเงิน",
"tx_rejected_dust_output": "การทำธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนเอาต์พุตต่ำ (ฝุ่น) โปรดเพิ่มจำนวนเงิน",
"tx_rejected_dust_output_send_all": "การทำธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนเอาต์พุตต่ำ (ฝุ่น) โปรดตรวจสอบยอดคงเหลือของเหรียญที่เลือกภายใต้การควบคุมเหรียญ",
"tx_rejected_vout_negative": "ยอดคงเหลือไม่เพียงพอที่จะจ่ายสำหรับค่าธรรมเนียมการทำธุรกรรมนี้ โปรดตรวจสอบยอดคงเหลือของเหรียญภายใต้การควบคุมเหรียญ",
"tx_wrong_balance_exception": "คุณมีไม่เพียงพอ ${currency} ในการส่งจำนวนนี้",
"tx_zero_fee_exception": "ไม่สามารถส่งธุรกรรมด้วยค่าธรรมเนียม 0 ลองเพิ่มอัตราหรือตรวจสอบการเชื่อมต่อของคุณสำหรับการประมาณการล่าสุด",
"unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน",
"unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง",
"unconfirmed": "ยอดคงเหลือที่ไม่ได้รับการยืนยัน",

View file

@ -43,6 +43,7 @@
"already_have_account": "Mayroon nang account?",
"always": "Palagi",
"amount": "Halaga:",
"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})",
"amount_is_estimate": "Ang natanggap na halaga ay isang pagtatantya",
"amount_is_guaranteed": "Ang natanggap na halaga ay garantisado",
"and": "at",
@ -712,6 +713,16 @@
"transactions": "Mga Transaksyon",
"transactions_by_date": "Mga Transaksyon ayon sa Petsa",
"trusted": "Pinagkakatiwalaan",
"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.",
"tx_commit_failed": "Nabigo ang transaksyon sa transaksyon. Mangyaring makipag -ugnay sa suporta.",
"tx_no_dust_exception": "Ang transaksyon ay tinanggihan sa pamamagitan ng pagpapadala ng isang maliit na maliit. Mangyaring subukang dagdagan ang halaga.",
"tx_not_enough_inputs_exception": "Hindi sapat na magagamit ang mga input. Mangyaring pumili ng higit pa sa ilalim ng control ng barya",
"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.",
"tx_rejected_dust_output": "Ang transaksyon na tinanggihan ng mga patakaran sa network, mababang halaga ng output (alikabok). Mangyaring dagdagan ang halaga.",
"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.",
"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.",
"tx_wrong_balance_exception": "Wala kang sapat na ${currency} upang maipadala ang halagang ito.",
"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.",
"unavailable_balance": "Hindi available na balanse",
"unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.",
"unconfirmed": "Hindi nakumpirma na balanse",

View file

@ -43,6 +43,7 @@
"already_have_account": "Zaten bir hesabınız var mı?",
"always": "Her Zaman",
"amount": "Miktar: ",
"amount_is_below_minimum_limit": "Ücretlerden sonra bakiyeniz, değişim için gereken minimum miktardan daha az olur (${min})",
"amount_is_estimate": "Alacağınız tutar tahminidir",
"amount_is_guaranteed": "Alacağınız tutar garantilidir",
"and": "ve",
@ -712,6 +713,16 @@
"transactions": "İşlemler",
"transactions_by_date": "Tarihe göre transferler",
"trusted": "Güvenilir",
"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.",
"tx_commit_failed": "İşlem taahhüdü başarısız oldu. Lütfen Destek ile iletişime geçin.",
"tx_no_dust_exception": "İşlem, çok küçük bir miktar gönderilerek reddedilir. Lütfen miktarı artırmayı deneyin.",
"tx_not_enough_inputs_exception": "Yeterli giriş yok. Lütfen madeni para kontrolü altında daha fazlasını seçin",
"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.",
"tx_rejected_dust_output": "Ağ kurallarına göre reddedilen işlem, düşük çıktı miktarı (toz). Lütfen miktarı artırın.",
"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.",
"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.",
"tx_wrong_balance_exception": "Bu miktarı göndermek için yeterli ${currency} yok.",
"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.",
"unavailable_balance": "Kullanılamayan bakiye",
"unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.",
"unconfirmed": "Onaylanmamış Bakiye",

View file

@ -43,6 +43,7 @@
"already_have_account": "Вже є обліковий запис?",
"always": "Завжди",
"amount": "Сума: ",
"amount_is_below_minimum_limit": "Ваш баланс після зборів буде меншим, ніж мінімальна сума, необхідна для обміну (${min})",
"amount_is_estimate": "Отримана сума є приблизною",
"amount_is_guaranteed": "Отримана сума є гарантованою",
"and": "і",
@ -713,6 +714,16 @@
"transactions": "Транзакції",
"transactions_by_date": "Сортувати по даті",
"trusted": "довіряють",
"tx_commit_exception_no_dust_on_change": "Транзакція відхилена цією сумою. За допомогою цих монет ви можете надіслати ${min} без змін або ${max}, що повертає зміни.",
"tx_commit_failed": "Транзакційна комісія не вдалося. Будь ласка, зв'яжіться з підтримкою.",
"tx_no_dust_exception": "Угода відхиляється, відправивши суму занадто мала. Будь ласка, спробуйте збільшити суму.",
"tx_not_enough_inputs_exception": "Недостатньо доступних входів. Виберіть більше під контролем монети",
"tx_rejected_dust_change": "Транзакція відхилена за допомогою мережевих правил, низька кількість змін (пил). Спробуйте надіслати все або зменшити суму.",
"tx_rejected_dust_output": "Транзакція відхилена за допомогою мережевих правил, низька кількість вихідної кількості (пил). Будь ласка, збільшуйте суму.",
"tx_rejected_dust_output_send_all": "Транзакція відхилена за допомогою мережевих правил, низька кількість вихідної кількості (пил). Будь ласка, перевірте баланс монет, вибраних під контролем монет.",
"tx_rejected_vout_negative": "Недостатньо балансу, щоб оплатити плату за цю транзакцію. Будь ласка, перевірте баланс монет під контролем монет.",
"tx_wrong_balance_exception": "У вас недостатньо ${currency}, щоб надіслати цю суму.",
"tx_zero_fee_exception": "Не вдається відправити транзакцію з 0 платежами. Спробуйте збільшити ставку або перевірити з'єднання на останні оцінки.",
"unavailable_balance": "Недоступний баланс",
"unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.",
"unconfirmed": "Непідтверджений баланс",

View file

@ -43,6 +43,7 @@
"already_have_account": "پہلے سے ہی اکاؤنٹ ہے؟",
"always": "ہمیشہ",
"amount": "رقم کی رقم:",
"amount_is_below_minimum_limit": "فیس کے بعد آپ کا توازن تبادلہ کے لئے درکار کم سے کم رقم سے کم ہوگا (${min}",
"amount_is_estimate": "وصول شدہ رقم ایک تخمینہ ہے۔",
"amount_is_guaranteed": "وصول شدہ رقم کی ضمانت ہے۔",
"and": "اور",
@ -714,6 +715,16 @@
"transactions": "لین دین",
"transactions_by_date": "تاریخ کے لحاظ سے لین دین",
"trusted": "قابل اعتماد",
"tx_commit_exception_no_dust_on_change": "اس رقم سے لین دین کو مسترد کردیا گیا ہے۔ ان سککوں کے ذریعہ آپ بغیر کسی تبدیلی کے ${min} یا ${max} بھیج سکتے ہیں جو لوٹتے ہیں۔",
"tx_commit_failed": "ٹرانزیکشن کمٹ ناکام ہوگیا۔ براہ کرم سپورٹ سے رابطہ کریں۔",
"tx_no_dust_exception": "لین دین کو بہت چھوٹی رقم بھیج کر مسترد کردیا جاتا ہے۔ براہ کرم رقم میں اضافہ کرنے کی کوشش کریں۔",
"tx_not_enough_inputs_exception": "کافی ان پٹ دستیاب نہیں ہے۔ براہ کرم سکے کے کنٹرول میں مزید منتخب کریں",
"tx_rejected_dust_change": "نیٹ ورک کے قواعد ، کم تبدیلی کی رقم (دھول) کے ذریعہ لین دین کو مسترد کردیا گیا۔ سب کو بھیجنے یا رقم کو کم کرنے کی کوشش کریں۔",
"tx_rejected_dust_output": "لین دین کو نیٹ ورک کے قواعد ، کم آؤٹ پٹ رقم (دھول) کے ذریعہ مسترد کردیا گیا۔ براہ کرم رقم میں اضافہ کریں۔",
"tx_rejected_dust_output_send_all": "لین دین کو نیٹ ورک کے قواعد ، کم آؤٹ پٹ رقم (دھول) کے ذریعہ مسترد کردیا گیا۔ براہ کرم سکے کے کنٹرول میں منتخب کردہ سکے کا توازن چیک کریں۔",
"tx_rejected_vout_negative": "اس لین دین کی فیسوں کی ادائیگی کے لئے کافی توازن نہیں ہے۔ براہ کرم سکے کے کنٹرول میں سکے کا توازن چیک کریں۔",
"tx_wrong_balance_exception": "آپ کے پاس یہ رقم بھیجنے کے لئے کافی ${currency} نہیں ہے۔",
"tx_zero_fee_exception": "0 فیس کے ساتھ لین دین نہیں بھیج سکتا۔ شرح کو بڑھانے یا تازہ ترین تخمینے کے ل your اپنے کنکشن کی جانچ پڑتال کرنے کی کوشش کریں۔",
"unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ",
"unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ",
"unconfirmed": "غیر تصدیق شدہ بیلنس",

View file

@ -43,6 +43,7 @@
"already_have_account": "Ṣé ẹ ti ní àkáǹtì?",
"always": "Ní gbogbo àwọn ìgbà",
"amount": "Iye: ",
"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}",
"amount_is_estimate": "Ìdíyelé ni iye tó ń bọ̀",
"amount_is_guaranteed": "ó di dandan pé owó á wọlé",
"and": "àti",
@ -713,6 +714,16 @@
"transactions": "Àwọn àránṣẹ́",
"transactions_by_date": "Àwọn àránṣẹ́ t'á ti fi aago ṣa",
"trusted": "A ti fọkàn ẹ̀ tán",
"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.",
"tx_commit_failed": "Idunadura iṣowo kuna. Jọwọ kan si atilẹyin.",
"tx_no_dust_exception": "Iṣowo naa ni kọ nipa fifiranṣẹ iye ti o kere ju. Jọwọ gbiyanju pọ si iye naa.",
"tx_not_enough_inputs_exception": "Ko to awọn titẹsi to. Jọwọ yan diẹ sii labẹ iṣakoso owo",
"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.",
"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.",
"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.",
"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.",
"tx_wrong_balance_exception": "O ko ni to ${currency} lati firanṣẹ iye yii.",
"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.",
"unavailable_balance": "Iwontunwonsi ti ko si",
"unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.",
"unconfirmed": "A kò tí ì jẹ́rìí ẹ̀",

View file

@ -43,6 +43,7 @@
"already_have_account": "已经有账号了?",
"always": "总是",
"amount": "金额: ",
"amount_is_below_minimum_limit": "您的余额费用将小于交易所所需的最低金额(${min}",
"amount_is_estimate": "收款金额为估算值",
"amount_is_guaranteed": "保证收到的金额",
"and": "和",
@ -712,6 +713,16 @@
"transactions": "交易情况",
"transactions_by_date": "按日期交易",
"trusted": "值得信赖",
"tx_commit_exception_no_dust_on_change": "交易被此金额拒绝。使用这些硬币,您可以发送${min}无需更改或返回${max}的变化。",
"tx_commit_failed": "交易承诺失败。请联系支持。",
"tx_no_dust_exception": "通过发送太小的金额来拒绝交易。请尝试增加金额。",
"tx_not_enough_inputs_exception": "没有足够的输入。请在硬币控制下选择更多",
"tx_rejected_dust_change": "交易被网络规则拒绝,较低的变化数量(灰尘)。尝试发送全部或减少金额。",
"tx_rejected_dust_output": "交易被网络规则,低输出量(灰尘)拒绝。请增加金额。",
"tx_rejected_dust_output_send_all": "交易被网络规则,低输出量(灰尘)拒绝。请检查在硬币控制下选择的硬币的余额。",
"tx_rejected_vout_negative": "没有足够的余额来支付此交易费用。请检查硬币控制下的硬币余额。",
"tx_wrong_balance_exception": "您没有足够的${currency}来发送此金额。",
"tx_zero_fee_exception": "无法以0费用发送交易。尝试提高速率或检查连接以获取最新估计。",
"unavailable_balance": "不可用余额",
"unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。",
"unconfirmed": "未确认余额",

View file

@ -69,6 +69,7 @@ import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/output_info.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:hive/hive.dart';
import 'package:bitcoin_base/bitcoin_base.dart';""";