mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-03-23 23:58:48 +00:00
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into CW-565-sign-messages
This commit is contained in:
commit
10ad96d4da
73 changed files with 574 additions and 275 deletions
|
@ -37,7 +37,7 @@ class BitcoinTransactionPriority extends TransactionPriority {
|
||||||
|
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case BitcoinTransactionPriority.slow:
|
case BitcoinTransactionPriority.slow:
|
||||||
label = 'Slow ~24hrs'; // '${S.current.transaction_priority_slow} ~24hrs';
|
label = 'Slow ~24hrs+'; // '${S.current.transaction_priority_slow} ~24hrs';
|
||||||
break;
|
break;
|
||||||
case BitcoinTransactionPriority.medium:
|
case BitcoinTransactionPriority.medium:
|
||||||
label = 'Medium'; // S.current.transaction_priority_medium;
|
label = 'Medium'; // S.current.transaction_priority_medium;
|
||||||
|
|
|
@ -212,10 +212,14 @@ abstract class ElectrumWalletBase
|
||||||
List<ECPrivate> privateKeys = [];
|
List<ECPrivate> privateKeys = [];
|
||||||
int allInputsAmount = 0;
|
int allInputsAmount = 0;
|
||||||
|
|
||||||
|
bool spendsUnconfirmedTX = false;
|
||||||
|
|
||||||
for (int i = 0; i < unspentCoins.length; i++) {
|
for (int i = 0; i < unspentCoins.length; i++) {
|
||||||
final utx = unspentCoins[i];
|
final utx = unspentCoins[i];
|
||||||
|
|
||||||
if (utx.isSending) {
|
if (utx.isSending && !utx.isFrozen) {
|
||||||
|
if (!spendsUnconfirmedTX) spendsUnconfirmedTX = utx.confirmations == 0;
|
||||||
|
|
||||||
allInputsAmount += utx.value;
|
allInputsAmount += utx.value;
|
||||||
|
|
||||||
final address = addressTypeFromStr(utx.address, network);
|
final address = addressTypeFromStr(utx.address, network);
|
||||||
|
@ -273,6 +277,10 @@ abstract class ElectrumWalletBase
|
||||||
// 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
|
// 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;
|
int amount = allInputsAmount - fee;
|
||||||
|
|
||||||
|
if (amount <= 0) {
|
||||||
|
throw BitcoinTransactionWrongBalanceException();
|
||||||
|
}
|
||||||
|
|
||||||
// Attempting to send less than the dust limit
|
// Attempting to send less than the dust limit
|
||||||
if (_isBelowDust(amount)) {
|
if (_isBelowDust(amount)) {
|
||||||
throw BitcoinTransactionNoDustException();
|
throw BitcoinTransactionNoDustException();
|
||||||
|
@ -297,6 +305,7 @@ abstract class ElectrumWalletBase
|
||||||
isSendAll: true,
|
isSendAll: true,
|
||||||
hasChange: false,
|
hasChange: false,
|
||||||
memo: memo,
|
memo: memo,
|
||||||
|
spendsUnconfirmedTX: spendsUnconfirmedTX,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,17 +315,25 @@ abstract class ElectrumWalletBase
|
||||||
int feeRate, {
|
int feeRate, {
|
||||||
int? inputsCount,
|
int? inputsCount,
|
||||||
String? memo,
|
String? memo,
|
||||||
|
bool? useUnconfirmed,
|
||||||
}) async {
|
}) async {
|
||||||
final utxos = <UtxoWithAddress>[];
|
final utxos = <UtxoWithAddress>[];
|
||||||
List<ECPrivate> privateKeys = [];
|
List<ECPrivate> privateKeys = [];
|
||||||
int allInputsAmount = 0;
|
int allInputsAmount = 0;
|
||||||
|
bool spendsUnconfirmedTX = false;
|
||||||
|
|
||||||
int leftAmount = credentialsAmount;
|
int leftAmount = credentialsAmount;
|
||||||
final sendingCoins = unspentCoins.where((utx) => utx.isSending).toList();
|
final sendingCoins = unspentCoins.where((utx) => utx.isSending && !utx.isFrozen).toList();
|
||||||
|
final unconfirmedCoins = sendingCoins.where((utx) => utx.confirmations == 0).toList();
|
||||||
|
|
||||||
for (int i = 0; i < sendingCoins.length; i++) {
|
for (int i = 0; i < sendingCoins.length; i++) {
|
||||||
final utx = sendingCoins[i];
|
final utx = sendingCoins[i];
|
||||||
|
|
||||||
|
final isUncormirmed = utx.confirmations == 0;
|
||||||
|
if (useUnconfirmed != true && isUncormirmed) continue;
|
||||||
|
|
||||||
|
if (!spendsUnconfirmedTX) spendsUnconfirmedTX = isUncormirmed;
|
||||||
|
|
||||||
allInputsAmount += utx.value;
|
allInputsAmount += utx.value;
|
||||||
leftAmount = leftAmount - utx.value;
|
leftAmount = leftAmount - utx.value;
|
||||||
|
|
||||||
|
@ -354,11 +371,23 @@ abstract class ElectrumWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
final spendingAllCoins = sendingCoins.length == utxos.length;
|
final spendingAllCoins = sendingCoins.length == utxos.length;
|
||||||
|
final spendingAllConfirmedCoins =
|
||||||
|
!spendsUnconfirmedTX && utxos.length == sendingCoins.length - unconfirmedCoins.length;
|
||||||
|
|
||||||
// How much is being spent - how much is being sent
|
// How much is being spent - how much is being sent
|
||||||
int amountLeftForChangeAndFee = allInputsAmount - credentialsAmount;
|
int amountLeftForChangeAndFee = allInputsAmount - credentialsAmount;
|
||||||
|
|
||||||
if (amountLeftForChangeAndFee <= 0) {
|
if (amountLeftForChangeAndFee <= 0) {
|
||||||
|
if (!spendingAllCoins) {
|
||||||
|
return estimateTxForAmount(
|
||||||
|
credentialsAmount,
|
||||||
|
outputs,
|
||||||
|
feeRate,
|
||||||
|
inputsCount: utxos.length + 1,
|
||||||
|
memo: memo,
|
||||||
|
useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins,
|
||||||
|
);
|
||||||
|
}
|
||||||
throw BitcoinTransactionWrongBalanceException();
|
throw BitcoinTransactionWrongBalanceException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,6 +441,7 @@ abstract class ElectrumWalletBase
|
||||||
feeRate,
|
feeRate,
|
||||||
inputsCount: utxos.length + 1,
|
inputsCount: utxos.length + 1,
|
||||||
memo: memo,
|
memo: memo,
|
||||||
|
useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,6 +488,7 @@ abstract class ElectrumWalletBase
|
||||||
feeRate,
|
feeRate,
|
||||||
inputsCount: utxos.length + 1,
|
inputsCount: utxos.length + 1,
|
||||||
memo: memo,
|
memo: memo,
|
||||||
|
useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,6 +501,7 @@ abstract class ElectrumWalletBase
|
||||||
hasChange: true,
|
hasChange: true,
|
||||||
isSendAll: false,
|
isSendAll: false,
|
||||||
memo: memo,
|
memo: memo,
|
||||||
|
spendsUnconfirmedTX: spendsUnconfirmedTX,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +572,7 @@ abstract class ElectrumWalletBase
|
||||||
network: network,
|
network: network,
|
||||||
memo: estimatedTx.memo,
|
memo: estimatedTx.memo,
|
||||||
outputOrdering: BitcoinOrdering.none,
|
outputOrdering: BitcoinOrdering.none,
|
||||||
enableRBF: true,
|
enableRBF: !estimatedTx.spendsUnconfirmedTX,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
txb = BitcoinTransactionBuilder(
|
txb = BitcoinTransactionBuilder(
|
||||||
|
@ -550,7 +582,7 @@ abstract class ElectrumWalletBase
|
||||||
network: network,
|
network: network,
|
||||||
memo: estimatedTx.memo,
|
memo: estimatedTx.memo,
|
||||||
outputOrdering: BitcoinOrdering.none,
|
outputOrdering: BitcoinOrdering.none,
|
||||||
enableRBF: true,
|
enableRBF: !estimatedTx.spendsUnconfirmedTX,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,6 +762,7 @@ abstract class ElectrumWalletBase
|
||||||
final tx = await fetchTransactionInfo(
|
final tx = await fetchTransactionInfo(
|
||||||
hash: coin.hash, height: 0, myAddresses: addressesSet);
|
hash: coin.hash, height: 0, myAddresses: addressesSet);
|
||||||
coin.isChange = tx?.direction == TransactionDirection.outgoing;
|
coin.isChange = tx?.direction == TransactionDirection.outgoing;
|
||||||
|
coin.confirmations = tx?.confirmations;
|
||||||
updatedUnspentCoins.add(coin);
|
updatedUnspentCoins.add(coin);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}))));
|
}))));
|
||||||
|
@ -754,6 +787,7 @@ abstract class ElectrumWalletBase
|
||||||
coin.isFrozen = coinInfo.isFrozen;
|
coin.isFrozen = coinInfo.isFrozen;
|
||||||
coin.isSending = coinInfo.isSending;
|
coin.isSending = coinInfo.isSending;
|
||||||
coin.note = coinInfo.note;
|
coin.note = coinInfo.note;
|
||||||
|
coin.bitcoinAddressRecord.balance += coinInfo.value;
|
||||||
} else {
|
} else {
|
||||||
_addCoinInfo(coin);
|
_addCoinInfo(coin);
|
||||||
}
|
}
|
||||||
|
@ -1046,9 +1080,11 @@ abstract class ElectrumWalletBase
|
||||||
|
|
||||||
return Future.wait(addressesByType.map((addressRecord) async {
|
return Future.wait(addressesByType.map((addressRecord) async {
|
||||||
final history = await _fetchAddressHistory(addressRecord, addressesSet, currentHeight);
|
final history = await _fetchAddressHistory(addressRecord, addressesSet, currentHeight);
|
||||||
|
final balance = await electrumClient.getBalance(addressRecord.scriptHash!);
|
||||||
|
|
||||||
if (history.isNotEmpty) {
|
if (history.isNotEmpty) {
|
||||||
addressRecord.txCount = history.length;
|
addressRecord.txCount = history.length;
|
||||||
|
addressRecord.balance = balance['confirmed'] as int? ?? 0;
|
||||||
historiesWithDetails.addAll(history);
|
historiesWithDetails.addAll(history);
|
||||||
|
|
||||||
final matchedAddresses =
|
final matchedAddresses =
|
||||||
|
@ -1341,6 +1377,7 @@ class EstimatedTxResult {
|
||||||
required this.hasChange,
|
required this.hasChange,
|
||||||
required this.isSendAll,
|
required this.isSendAll,
|
||||||
this.memo,
|
this.memo,
|
||||||
|
required this.spendsUnconfirmedTX,
|
||||||
});
|
});
|
||||||
|
|
||||||
final List<UtxoWithAddress> utxos;
|
final List<UtxoWithAddress> utxos;
|
||||||
|
@ -1350,6 +1387,7 @@ class EstimatedTxResult {
|
||||||
final bool hasChange;
|
final bool hasChange;
|
||||||
final bool isSendAll;
|
final bool isSendAll;
|
||||||
final String? memo;
|
final String? memo;
|
||||||
|
final bool spendsUnconfirmedTX;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) {
|
BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) {
|
||||||
|
|
|
@ -15,7 +15,9 @@ class BitcoinTransactionNoDustOnChangeException extends TransactionNoDustOnChang
|
||||||
BitcoinTransactionNoDustOnChangeException(super.max, super.min);
|
BitcoinTransactionNoDustOnChangeException(super.max, super.min);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BitcoinTransactionCommitFailed extends TransactionCommitFailed {}
|
class BitcoinTransactionCommitFailed extends TransactionCommitFailed {
|
||||||
|
BitcoinTransactionCommitFailed({super.errorMessage});
|
||||||
|
}
|
||||||
|
|
||||||
class BitcoinTransactionCommitFailedDustChange extends TransactionCommitFailedDustChange {}
|
class BitcoinTransactionCommitFailedDustChange extends TransactionCommitFailedDustChange {}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,9 @@ class PendingBitcoinTransaction with PendingTransaction {
|
||||||
if (error.contains("bad-txns-vout-negative")) {
|
if (error.contains("bad-txns-vout-negative")) {
|
||||||
throw BitcoinTransactionCommitFailedVoutNegative();
|
throw BitcoinTransactionCommitFailedVoutNegative();
|
||||||
}
|
}
|
||||||
|
throw BitcoinTransactionCommitFailed(errorMessage: error);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw BitcoinTransactionCommitFailed();
|
throw BitcoinTransactionCommitFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: args
|
name: args
|
||||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.2"
|
version: "2.5.0"
|
||||||
asn1lib:
|
asn1lib:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -153,10 +153,10 @@ packages:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: build_runner
|
name: build_runner
|
||||||
sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21"
|
sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.8"
|
version: "2.4.9"
|
||||||
build_runner_core:
|
build_runner_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -177,10 +177,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: built_value
|
name: built_value
|
||||||
sha256: a3ec2e0f967bc47f69f95009bb93db936288d61d5343b9436e378b28a2f830c6
|
sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.9.0"
|
version: "8.9.2"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -309,10 +309,10 @@ packages:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_mobx
|
name: flutter_mobx
|
||||||
sha256: "4a5d062ff85ed3759f4aac6410ff0ffae32e324b2e71ca722ae1b37b32e865f4"
|
sha256: "859fbf452fa9c2519d2700b125dd7fb14c508bbdd7fb65e26ca8ff6c92280e2e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0+2"
|
version: "2.2.1+1"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -322,10 +322,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: frontend_server_client
|
name: frontend_server_client
|
||||||
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
|
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.0"
|
version: "4.0.0"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -490,10 +490,10 @@ packages:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: mobx
|
name: mobx
|
||||||
sha256: "74ee54012dc7c1b3276eaa960a600a7418ef5f9997565deb8fca1fd88fb36b78"
|
sha256: "63920b27b32ad1910adfe767ab1750e4c212e8923232a1f891597b362074ea5e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0+1"
|
version: "2.3.3+2"
|
||||||
mobx_codegen:
|
mobx_codegen:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
@ -594,10 +594,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: pointycastle
|
name: pointycastle
|
||||||
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
|
sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.7.4"
|
version: "3.8.0"
|
||||||
pool:
|
pool:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -610,10 +610,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: provider
|
name: provider
|
||||||
sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096"
|
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.1"
|
version: "6.1.2"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -787,6 +787,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.4-beta"
|
||||||
web_socket_channel:
|
web_socket_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -62,7 +62,9 @@ class PendingBitcoinCashTransaction with PendingTransaction {
|
||||||
if (error.contains("bad-txns-vout-negative")) {
|
if (error.contains("bad-txns-vout-negative")) {
|
||||||
throw BitcoinTransactionCommitFailedVoutNegative();
|
throw BitcoinTransactionCommitFailedVoutNegative();
|
||||||
}
|
}
|
||||||
|
throw BitcoinTransactionCommitFailed(errorMessage: error);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw BitcoinTransactionCommitFailed();
|
throw BitcoinTransactionCommitFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,11 @@ class TransactionNoDustOnChangeException implements Exception {
|
||||||
final String min;
|
final String min;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TransactionCommitFailed implements Exception {}
|
class TransactionCommitFailed implements Exception {
|
||||||
|
final String? errorMessage;
|
||||||
|
|
||||||
|
TransactionCommitFailed({this.errorMessage});
|
||||||
|
}
|
||||||
|
|
||||||
class TransactionCommitFailedDustChange implements Exception {}
|
class TransactionCommitFailedDustChange implements Exception {}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import 'package:http/io_client.dart' as ioc;
|
||||||
|
|
||||||
part 'node.g.dart';
|
part 'node.g.dart';
|
||||||
|
|
||||||
Uri createUriFromElectrumAddress(String address) => Uri.tryParse('tcp://$address')!;
|
Uri createUriFromElectrumAddress(String address, String path) => Uri.tryParse('tcp://$address$path')!;
|
||||||
|
|
||||||
@HiveType(typeId: Node.typeId)
|
@HiveType(typeId: Node.typeId)
|
||||||
class Node extends HiveObject with Keyable {
|
class Node extends HiveObject with Keyable {
|
||||||
|
@ -83,7 +83,7 @@ class Node extends HiveObject with Keyable {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return createUriFromElectrumAddress(uriRaw);
|
return createUriFromElectrumAddress(uriRaw, path ?? '');
|
||||||
case WalletType.nano:
|
case WalletType.nano:
|
||||||
case WalletType.banano:
|
case WalletType.banano:
|
||||||
if (isSSL) {
|
if (isSSL) {
|
||||||
|
@ -94,7 +94,7 @@ class Node extends HiveObject with Keyable {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
case WalletType.polygon:
|
case WalletType.polygon:
|
||||||
case WalletType.solana:
|
case WalletType.solana:
|
||||||
return Uri.https(uriRaw, '');
|
return Uri.https(uriRaw, path ?? '');
|
||||||
default:
|
default:
|
||||||
throw Exception('Unexpected type ${type.toString()} for Node uri');
|
throw Exception('Unexpected type ${type.toString()} for Node uri');
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Unspent {
|
||||||
bool isChange;
|
bool isChange;
|
||||||
bool isSending;
|
bool isSending;
|
||||||
bool isFrozen;
|
bool isFrozen;
|
||||||
|
int? confirmations;
|
||||||
String note;
|
String note;
|
||||||
|
|
||||||
bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc');
|
bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc');
|
||||||
|
|
|
@ -149,10 +149,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.1"
|
version: "1.17.2"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -343,18 +343,18 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.15"
|
version: "0.12.16"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.5.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -564,10 +564,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.10.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -612,10 +612,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.1"
|
version: "0.6.0"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -641,13 +641,21 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: "direct overridden"
|
||||||
description:
|
description:
|
||||||
name: watcher
|
name: watcher
|
||||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.4-beta"
|
||||||
web_socket_channel:
|
web_socket_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -681,5 +689,5 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.0.0 <4.0.0"
|
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||||
flutter: ">=3.10.0"
|
flutter: ">=3.10.0"
|
||||||
|
|
|
@ -234,14 +234,17 @@ abstract class EVMChainClient {
|
||||||
|
|
||||||
final decodedResponse = jsonDecode(response.body)[0] as Map<String, dynamic>;
|
final decodedResponse = jsonDecode(response.body)[0] as Map<String, dynamic>;
|
||||||
|
|
||||||
|
|
||||||
|
final symbol = (decodedResponse['symbol'] ?? '') as String;
|
||||||
|
String filteredSymbol = symbol.replaceFirst(RegExp('^\\\$'), '');
|
||||||
|
|
||||||
final name = decodedResponse['name'] ?? '';
|
final name = decodedResponse['name'] ?? '';
|
||||||
final symbol = decodedResponse['symbol'] ?? '';
|
|
||||||
final decimal = decodedResponse['decimals'] ?? '0';
|
final decimal = decodedResponse['decimals'] ?? '0';
|
||||||
final iconPath = decodedResponse['logo'] ?? '';
|
final iconPath = decodedResponse['logo'] ?? '';
|
||||||
|
|
||||||
return Erc20Token(
|
return Erc20Token(
|
||||||
name: name,
|
name: name,
|
||||||
symbol: symbol,
|
symbol: filteredSymbol,
|
||||||
contractAddress: contractAddress,
|
contractAddress: contractAddress,
|
||||||
decimal: int.tryParse(decimal) ?? 0,
|
decimal: int.tryParse(decimal) ?? 0,
|
||||||
iconPath: iconPath,
|
iconPath: iconPath,
|
||||||
|
|
|
@ -470,9 +470,15 @@ abstract class EVMChainWalletBase
|
||||||
await token.delete();
|
await token.delete();
|
||||||
|
|
||||||
balance.remove(token);
|
balance.remove(token);
|
||||||
|
await _removeTokenTransactionsInHistory(token);
|
||||||
_updateBalance();
|
_updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _removeTokenTransactionsInHistory(Erc20Token token) async {
|
||||||
|
transactionHistory.transactions.removeWhere((key, value) => value.tokenSymbol == token.title);
|
||||||
|
await transactionHistory.save();
|
||||||
|
}
|
||||||
|
|
||||||
Future<Erc20Token?> getErc20Token(String contractAddress, String chainName) async =>
|
Future<Erc20Token?> getErc20Token(String contractAddress, String chainName) async =>
|
||||||
await _client.getErc20Token(contractAddress, chainName);
|
await _client.getErc20Token(contractAddress, chainName);
|
||||||
|
|
||||||
|
|
|
@ -69,10 +69,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_daemon
|
name: build_daemon
|
||||||
sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf"
|
sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "4.0.0"
|
||||||
build_resolvers:
|
build_resolvers:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
@ -85,10 +85,10 @@ packages:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: build_runner
|
name: build_runner
|
||||||
sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727
|
sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.3"
|
version: "2.4.9"
|
||||||
build_runner_core:
|
build_runner_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -149,10 +149,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.1"
|
version: "1.17.2"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -350,18 +350,18 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.15"
|
version: "0.12.16"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.5.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -563,10 +563,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.10.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -611,10 +611,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.1"
|
version: "0.6.0"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -640,13 +640,21 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: "direct overridden"
|
||||||
description:
|
description:
|
||||||
name: watcher
|
name: watcher
|
||||||
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
|
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.1.0"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.4-beta"
|
||||||
web_socket_channel:
|
web_socket_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -680,5 +688,5 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.1"
|
version: "3.1.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.0.0 <4.0.0"
|
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||||
flutter: ">=3.7.0"
|
flutter: ">=3.7.0"
|
||||||
|
|
|
@ -53,10 +53,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.1"
|
version: "1.17.2"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -213,18 +213,18 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.15"
|
version: "0.12.16"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.5.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -354,10 +354,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.10.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -394,10 +394,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.1"
|
version: "0.6.0"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -414,6 +414,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.4-beta"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -431,5 +439,5 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0+3"
|
version: "0.2.0+3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.0.6 <4.0.0"
|
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||||
flutter: ">=3.7.0"
|
flutter: ">=3.7.0"
|
||||||
|
|
|
@ -69,10 +69,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_daemon
|
name: build_daemon
|
||||||
sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf"
|
sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "4.0.0"
|
||||||
build_resolvers:
|
build_resolvers:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
@ -85,10 +85,10 @@ packages:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: build_runner
|
name: build_runner
|
||||||
sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727
|
sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.3"
|
version: "2.4.9"
|
||||||
build_runner_core:
|
build_runner_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -149,10 +149,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.1"
|
version: "1.17.2"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -366,18 +366,18 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.15"
|
version: "0.12.16"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.5.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -587,10 +587,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.10.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -635,10 +635,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.1"
|
version: "0.6.0"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -664,13 +664,21 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: "direct overridden"
|
||||||
description:
|
description:
|
||||||
name: watcher
|
name: watcher
|
||||||
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
|
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.1.0"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.4-beta"
|
||||||
web_socket_channel:
|
web_socket_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -704,5 +712,5 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.1"
|
version: "3.1.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.0.6 <4.0.0"
|
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||||
flutter: ">=3.7.0"
|
flutter: ">=3.7.0"
|
||||||
|
|
|
@ -34,10 +34,7 @@ class SolanaTransactionInfo extends TransactionInfo {
|
||||||
@override
|
@override
|
||||||
String amountFormatted() {
|
String amountFormatted() {
|
||||||
String stringBalance = solAmount.toString();
|
String stringBalance = solAmount.toString();
|
||||||
|
|
||||||
if (stringBalance.toString().length >= 6) {
|
|
||||||
stringBalance = stringBalance.substring(0, 6);
|
|
||||||
}
|
|
||||||
return '$stringBalance $tokenSymbol';
|
return '$stringBalance $tokenSymbol';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,17 @@ abstract class SolanaWalletBase
|
||||||
String? get seed => _mnemonic;
|
String? get seed => _mnemonic;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get privateKey => HEX.encode(_keyPairData!.bytes);
|
String get privateKey {
|
||||||
|
final privateKeyBytes = _keyPairData!.bytes;
|
||||||
|
|
||||||
|
final publicKeyBytes = _keyPairData!.publicKey.bytes;
|
||||||
|
|
||||||
|
final encodedBytes = privateKeyBytes + publicKeyBytes;
|
||||||
|
|
||||||
|
final privateKey = base58encode(encodedBytes);
|
||||||
|
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
final boxName = "${walletInfo.name.replaceAll(" ", "_")}_${SPLToken.boxName}";
|
final boxName = "${walletInfo.name.replaceAll(" ", "_")}_${SPLToken.boxName}";
|
||||||
|
@ -138,8 +148,8 @@ abstract class SolanaWalletBase
|
||||||
assert(mnemonic != null || privateKey != null);
|
assert(mnemonic != null || privateKey != null);
|
||||||
|
|
||||||
if (privateKey != null) {
|
if (privateKey != null) {
|
||||||
final privateKeyBytes = HEX.decode(privateKey);
|
final privateKeyBytes = base58decode(privateKey);
|
||||||
return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes);
|
return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes.take(32).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Wallet.fromMnemonic(mnemonic!, account: 0, change: 0);
|
return Wallet.fromMnemonic(mnemonic!, account: 0, change: 0);
|
||||||
|
@ -265,32 +275,12 @@ abstract class SolanaWalletBase
|
||||||
|
|
||||||
final transactions = await _client.fetchTransactions(address);
|
final transactions = await _client.fetchTransactions(address);
|
||||||
|
|
||||||
final Map<String, SolanaTransactionInfo> result = {};
|
await _addTransactionsToTransactionHistory(transactions);
|
||||||
|
|
||||||
for (var transactionModel in transactions) {
|
|
||||||
result[transactionModel.id] = SolanaTransactionInfo(
|
|
||||||
id: transactionModel.id,
|
|
||||||
to: transactionModel.to,
|
|
||||||
from: transactionModel.from,
|
|
||||||
blockTime: transactionModel.blockTime,
|
|
||||||
direction: transactionModel.isOutgoingTx
|
|
||||||
? TransactionDirection.outgoing
|
|
||||||
: TransactionDirection.incoming,
|
|
||||||
solAmount: transactionModel.amount,
|
|
||||||
isPending: false,
|
|
||||||
txFee: transactionModel.fee,
|
|
||||||
tokenSymbol: transactionModel.tokenSymbol,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionHistory.addMany(result);
|
|
||||||
|
|
||||||
await transactionHistory.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches the SPL Tokens transactions linked to the token account Public Key
|
/// Fetches the SPL Tokens transactions linked to the token account Public Key
|
||||||
Future<void> _updateSPLTokenTransactions() async {
|
Future<void> _updateSPLTokenTransactions() async {
|
||||||
List<SolanaTransactionModel> splTokenTransactions = [];
|
// List<SolanaTransactionModel> splTokenTransactions = [];
|
||||||
|
|
||||||
// Make a copy of keys to avoid concurrent modification
|
// Make a copy of keys to avoid concurrent modification
|
||||||
var tokenKeys = List<CryptoCurrency>.from(balance.keys);
|
var tokenKeys = List<CryptoCurrency>.from(balance.keys);
|
||||||
|
@ -304,13 +294,20 @@ abstract class SolanaWalletBase
|
||||||
_walletKeyPair!,
|
_walletKeyPair!,
|
||||||
);
|
);
|
||||||
|
|
||||||
splTokenTransactions.addAll(tokenTxs);
|
// splTokenTransactions.addAll(tokenTxs);
|
||||||
|
await _addTransactionsToTransactionHistory(tokenTxs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// await _addTransactionsToTransactionHistory(splTokenTransactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _addTransactionsToTransactionHistory(
|
||||||
|
List<SolanaTransactionModel> transactions,
|
||||||
|
) async {
|
||||||
final Map<String, SolanaTransactionInfo> result = {};
|
final Map<String, SolanaTransactionInfo> result = {};
|
||||||
|
|
||||||
for (var transactionModel in splTokenTransactions) {
|
for (var transactionModel in transactions) {
|
||||||
result[transactionModel.id] = SolanaTransactionInfo(
|
result[transactionModel.id] = SolanaTransactionInfo(
|
||||||
id: transactionModel.id,
|
id: transactionModel.id,
|
||||||
to: transactionModel.to,
|
to: transactionModel.to,
|
||||||
|
@ -452,12 +449,23 @@ abstract class SolanaWalletBase
|
||||||
await token.delete();
|
await token.delete();
|
||||||
|
|
||||||
balance.remove(token);
|
balance.remove(token);
|
||||||
|
await _removeTokenTransactionsInHistory(token);
|
||||||
_updateBalance();
|
_updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _removeTokenTransactionsInHistory(SPLToken token) async {
|
||||||
|
transactionHistory.transactions.removeWhere((key, value) => value.tokenSymbol == token.title);
|
||||||
|
await transactionHistory.save();
|
||||||
|
}
|
||||||
|
|
||||||
Future<SPLToken?> getSPLToken(String mintAddress) async {
|
Future<SPLToken?> getSPLToken(String mintAddress) async {
|
||||||
// Convert SPL token mint address to public key
|
// Convert SPL token mint address to public key
|
||||||
final mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress);
|
final Ed25519HDPublicKey mintPublicKey;
|
||||||
|
try {
|
||||||
|
mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress);
|
||||||
|
} catch (_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch token's metadata account
|
// Fetch token's metadata account
|
||||||
try {
|
try {
|
||||||
|
@ -472,10 +480,12 @@ abstract class SolanaWalletBase
|
||||||
iconPath = await _client.getIconImageFromTokenUri(token.uri);
|
iconPath = await _client.getIconImageFromTokenUri(token.uri);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
|
String filteredTokenSymbol = token.symbol.replaceFirst(RegExp('^\\\$'), '');
|
||||||
|
|
||||||
return SPLToken.fromMetadata(
|
return SPLToken.fromMetadata(
|
||||||
name: token.name,
|
name: token.name,
|
||||||
mint: token.mint,
|
mint: token.mint,
|
||||||
symbol: token.symbol,
|
symbol: filteredTokenSymbol,
|
||||||
mintAddress: mintAddress,
|
mintAddress: mintAddress,
|
||||||
iconPath: iconPath,
|
iconPath: iconPath,
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,7 +19,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin {
|
||||||
@HiveField(3)
|
@HiveField(3)
|
||||||
final int decimal;
|
final int decimal;
|
||||||
|
|
||||||
@HiveField(4, defaultValue: false)
|
@HiveField(4, defaultValue: true)
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
|
|
||||||
@HiveField(5)
|
@HiveField(5)
|
||||||
|
@ -39,7 +39,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin {
|
||||||
required this.mint,
|
required this.mint,
|
||||||
this.iconPath,
|
this.iconPath,
|
||||||
this.tag = 'SOL',
|
this.tag = 'SOL',
|
||||||
bool enabled = false,
|
bool enabled = true,
|
||||||
}) : _enabled = enabled,
|
}) : _enabled = enabled,
|
||||||
super(
|
super(
|
||||||
name: mint.toLowerCase(),
|
name: mint.toLowerCase(),
|
||||||
|
|
|
@ -282,13 +282,20 @@ class CWBitcoin extends Bitcoin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int getFeeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount,
|
int getEstimatedFeeWithFeeRate(Object wallet, int feeRate, int? amount,
|
||||||
{int? size}) {
|
{int? outputsCount, int? size}) {
|
||||||
final bitcoinWallet = wallet as ElectrumWallet;
|
final bitcoinWallet = wallet as ElectrumWallet;
|
||||||
return bitcoinWallet.feeAmountWithFeeRate(
|
return bitcoinWallet.calculateEstimatedFeeWithFeeRate(
|
||||||
feeRate,
|
feeRate,
|
||||||
inputsCount,
|
amount,
|
||||||
outputsCount,
|
outputsCount: outputsCount,
|
||||||
|
size: size,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int getMaxCustomFeeRate(Object wallet) {
|
||||||
|
final bitcoinWallet = wallet as ElectrumWallet;
|
||||||
|
return (bitcoinWallet.feeRate(BitcoinTransactionPriority.fast) * 1.1).round();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,12 @@ class DFXBuyProvider extends BuyProvider {
|
||||||
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
: super(wallet: wallet, isTestEnvironment: isTestEnvironment);
|
||||||
|
|
||||||
static const _baseUrl = 'api.dfx.swiss';
|
static const _baseUrl = 'api.dfx.swiss';
|
||||||
static const _authPath = '/v1/auth/signMessage';
|
// static const _signMessagePath = '/v1/auth/signMessage';
|
||||||
static const _signUpPath = '/v1/auth/signUp';
|
static const _authPath = '/v1/auth';
|
||||||
static const _signInPath = '/v1/auth/signIn';
|
|
||||||
static const walletName = 'CakeWallet';
|
static const walletName = 'CakeWallet';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => 'DFX Connect';
|
String get title => 'DFX.swiss';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get providerDescription => S.current.dfx_option_description;
|
String get providerDescription => S.current.dfx_option_description;
|
||||||
|
@ -73,21 +72,25 @@ class DFXBuyProvider extends BuyProvider {
|
||||||
String get walletAddress =>
|
String get walletAddress =>
|
||||||
wallet.walletAddresses.primaryAddress ?? wallet.walletAddresses.address;
|
wallet.walletAddresses.primaryAddress ?? wallet.walletAddresses.address;
|
||||||
|
|
||||||
Future<String> getSignMessage() async {
|
Future<String> getSignMessage() async =>
|
||||||
final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress});
|
"By_signing_this_message,_you_confirm_that_you_are_the_sole_owner_of_the_provided_Blockchain_address._Your_ID:_$walletAddress";
|
||||||
|
|
||||||
var response = await http.get(uri, headers: {'accept': 'application/json'});
|
// // Lets keep this just in case, but we can avoid this API Call
|
||||||
|
// Future<String> getSignMessage() async {
|
||||||
|
// final uri = Uri.https(_baseUrl, _signMessagePath, {'address': walletAddress});
|
||||||
|
//
|
||||||
|
// final response = await http.get(uri, headers: {'accept': 'application/json'});
|
||||||
|
//
|
||||||
|
// if (response.statusCode == 200) {
|
||||||
|
// final responseBody = jsonDecode(response.body);
|
||||||
|
// return responseBody['message'] as String;
|
||||||
|
// } else {
|
||||||
|
// throw Exception(
|
||||||
|
// 'Failed to get sign message. Status: ${response.statusCode} ${response.body}');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
Future<String> auth() async {
|
||||||
final responseBody = jsonDecode(response.body);
|
|
||||||
return responseBody['message'] as String;
|
|
||||||
} else {
|
|
||||||
throw Exception(
|
|
||||||
'Failed to get sign message. Status: ${response.statusCode} ${response.body}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> signUp() async {
|
|
||||||
final signMessage = await getSignature(await getSignMessage());
|
final signMessage = await getSignature(await getSignMessage());
|
||||||
|
|
||||||
final requestBody = jsonEncode({
|
final requestBody = jsonEncode({
|
||||||
|
@ -96,7 +99,7 @@ class DFXBuyProvider extends BuyProvider {
|
||||||
'signature': signMessage,
|
'signature': signMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
final uri = Uri.https(_baseUrl, _signUpPath);
|
final uri = Uri.https(_baseUrl, _authPath);
|
||||||
var response = await http.post(
|
var response = await http.post(
|
||||||
uri,
|
uri,
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
@ -115,33 +118,6 @@ class DFXBuyProvider extends BuyProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> signIn() async {
|
|
||||||
final signMessage = await getSignature(await getSignMessage());
|
|
||||||
|
|
||||||
final requestBody = jsonEncode({
|
|
||||||
'address': walletAddress,
|
|
||||||
'signature': signMessage,
|
|
||||||
});
|
|
||||||
|
|
||||||
final uri = Uri.https(_baseUrl, _signInPath);
|
|
||||||
var response = await http.post(
|
|
||||||
uri,
|
|
||||||
headers: {'Content-Type': 'application/json'},
|
|
||||||
body: requestBody,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.statusCode == 201) {
|
|
||||||
final responseBody = jsonDecode(response.body);
|
|
||||||
return responseBody['accessToken'] as String;
|
|
||||||
} else if (response.statusCode == 403) {
|
|
||||||
final responseBody = jsonDecode(response.body);
|
|
||||||
final message = responseBody['message'] ?? 'Service unavailable in your country';
|
|
||||||
throw Exception(message);
|
|
||||||
} else {
|
|
||||||
throw Exception('Failed to sign in. Status: ${response.statusCode} ${response.body}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> getSignature(String message) async {
|
Future<String> getSignature(String message) async {
|
||||||
switch (wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
|
@ -151,7 +127,7 @@ class DFXBuyProvider extends BuyProvider {
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return wallet.signMessage(message, address: walletAddress);
|
return await wallet.signMessage(message, address: walletAddress);
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
throw Exception("WalletType is not available for DFX ${wallet.type}");
|
||||||
}
|
}
|
||||||
|
@ -164,17 +140,7 @@ class DFXBuyProvider extends BuyProvider {
|
||||||
final blockchain = this.blockchain;
|
final blockchain = this.blockchain;
|
||||||
final actionType = isBuyAction == true ? '/buy' : '/sell';
|
final actionType = isBuyAction == true ? '/buy' : '/sell';
|
||||||
|
|
||||||
String accessToken;
|
final accessToken = await auth();
|
||||||
|
|
||||||
try {
|
|
||||||
accessToken = await signUp();
|
|
||||||
} on Exception catch (e) {
|
|
||||||
if (e.toString().contains('409')) {
|
|
||||||
accessToken = await signIn();
|
|
||||||
} else {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final uri = Uri.https('services.dfx.swiss', actionType, {
|
final uri = Uri.https('services.dfx.swiss', actionType, {
|
||||||
'session': accessToken,
|
'session': accessToken,
|
||||||
|
@ -198,7 +164,7 @@ class DFXBuyProvider extends BuyProvider {
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertWithOneAction(
|
return AlertWithOneAction(
|
||||||
alertTitle: "DFX Connect",
|
alertTitle: "DFX.swiss",
|
||||||
alertContent: S.of(context).buy_provider_unavailable + ': $e',
|
alertContent: S.of(context).buy_provider_unavailable + ': $e',
|
||||||
buttonText: S.of(context).ok,
|
buttonText: S.of(context).ok,
|
||||||
buttonAction: () => Navigator.of(context).pop());
|
buttonAction: () => Navigator.of(context).pop());
|
||||||
|
|
9
lib/core/create_trade_result.dart
Normal file
9
lib/core/create_trade_result.dart
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
class CreateTradeResult {
|
||||||
|
bool result;
|
||||||
|
String? errorMessage;
|
||||||
|
|
||||||
|
CreateTradeResult({
|
||||||
|
required this.result,
|
||||||
|
this.errorMessage,
|
||||||
|
});
|
||||||
|
}
|
|
@ -11,5 +11,9 @@ class NodeAddressValidator extends TextValidator {
|
||||||
|
|
||||||
class NodePathValidator extends TextValidator {
|
class NodePathValidator extends TextValidator {
|
||||||
NodePathValidator()
|
NodePathValidator()
|
||||||
: super(errorMessage: S.current.error_text_node_address, pattern: '^([/0-9a-zA-Z.\-]+)?\$');
|
: super(
|
||||||
|
errorMessage: S.current.error_text_node_address,
|
||||||
|
pattern: '^([/0-9a-zA-Z.\-]+)?\$',
|
||||||
|
isAutovalidate: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,28 @@
|
||||||
import 'package:cake_wallet/core/generate_wallet_password.dart';
|
import 'package:cake_wallet/core/generate_wallet_password.dart';
|
||||||
import 'package:cake_wallet/core/key_service.dart';
|
import 'package:cake_wallet/core/key_service.dart';
|
||||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||||
|
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||||
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_service.dart';
|
import 'package:cw_core/wallet_service.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class WalletLoadingService {
|
class WalletLoadingService {
|
||||||
WalletLoadingService(
|
WalletLoadingService(this.sharedPreferences, this.keyService, this.walletServiceFactory);
|
||||||
this.sharedPreferences, this.keyService, this.walletServiceFactory);
|
|
||||||
|
|
||||||
final SharedPreferences sharedPreferences;
|
final SharedPreferences sharedPreferences;
|
||||||
final KeyService keyService;
|
final KeyService keyService;
|
||||||
final WalletService Function(WalletType type) walletServiceFactory;
|
final WalletService Function(WalletType type) walletServiceFactory;
|
||||||
|
|
||||||
Future<void> renameWallet(
|
Future<void> renameWallet(WalletType type, String name, String newName) async {
|
||||||
WalletType type, String name, String newName) async {
|
|
||||||
final walletService = walletServiceFactory.call(type);
|
final walletService = walletServiceFactory.call(type);
|
||||||
final password = await keyService.getWalletPassword(walletName: name);
|
final password = await keyService.getWalletPassword(walletName: name);
|
||||||
|
|
||||||
// Save the current wallet's password to the new wallet name's key
|
// Save the current wallet's password to the new wallet name's key
|
||||||
await keyService.saveWalletPassword(
|
await keyService.saveWalletPassword(walletName: newName, password: password);
|
||||||
walletName: newName, password: password);
|
|
||||||
// Delete previous wallet name from keyService to keep only new wallet's name
|
// Delete previous wallet name from keyService to keep only new wallet's name
|
||||||
// otherwise keeps duplicate (old and new names)
|
// otherwise keeps duplicate (old and new names)
|
||||||
await keyService.deleteWalletPassword(walletName: name);
|
await keyService.deleteWalletPassword(walletName: name);
|
||||||
|
@ -38,15 +39,43 @@ class WalletLoadingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<WalletBase> load(WalletType type, String name) async {
|
Future<WalletBase> load(WalletType type, String name) async {
|
||||||
final walletService = walletServiceFactory.call(type);
|
try {
|
||||||
final password = await keyService.getWalletPassword(walletName: name);
|
final walletService = walletServiceFactory.call(type);
|
||||||
final wallet = await walletService.openWallet(name, password);
|
final password = await keyService.getWalletPassword(walletName: name);
|
||||||
|
final wallet = await walletService.openWallet(name, password);
|
||||||
|
|
||||||
if (type == WalletType.monero) {
|
if (type == WalletType.monero) {
|
||||||
await updateMoneroWalletPassword(wallet);
|
await updateMoneroWalletPassword(wallet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wallet;
|
||||||
|
} catch (error, stack) {
|
||||||
|
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
||||||
|
|
||||||
|
// try opening another wallet that is not corrupted to give user access to the app
|
||||||
|
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||||
|
|
||||||
|
for (var walletInfo in walletInfoSource.values) {
|
||||||
|
try {
|
||||||
|
final walletService = walletServiceFactory.call(walletInfo.type);
|
||||||
|
final password = await keyService.getWalletPassword(walletName: walletInfo.name);
|
||||||
|
final wallet = await walletService.openWallet(walletInfo.name, password);
|
||||||
|
|
||||||
|
if (walletInfo.type == WalletType.monero) {
|
||||||
|
await updateMoneroWalletPassword(wallet);
|
||||||
|
}
|
||||||
|
|
||||||
|
await sharedPreferences.setString(PreferencesKey.currentWalletName, wallet.name);
|
||||||
|
await sharedPreferences.setInt(
|
||||||
|
PreferencesKey.currentWalletType, serializeToInt(wallet.type));
|
||||||
|
|
||||||
|
return wallet;
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if all user's wallets are corrupted throw exception
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wallet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateMoneroWalletPassword(WalletBase wallet) async {
|
Future<void> updateMoneroWalletPassword(WalletBase wallet) async {
|
||||||
|
@ -61,11 +90,9 @@ class WalletLoadingService {
|
||||||
// Save new generated password with backup key for case where
|
// Save new generated password with backup key for case where
|
||||||
// wallet will change password, but it will fail to update in secure storage
|
// wallet will change password, but it will fail to update in secure storage
|
||||||
final bakWalletName = '#__${wallet.name}_bak__#';
|
final bakWalletName = '#__${wallet.name}_bak__#';
|
||||||
await keyService.saveWalletPassword(
|
await keyService.saveWalletPassword(walletName: bakWalletName, password: password);
|
||||||
walletName: bakWalletName, password: password);
|
|
||||||
await wallet.changePassword(password);
|
await wallet.changePassword(password);
|
||||||
await keyService.saveWalletPassword(
|
await keyService.saveWalletPassword(walletName: wallet.name, password: password);
|
||||||
walletName: wallet.name, password: password);
|
|
||||||
isPasswordUpdated = true;
|
isPasswordUpdated = true;
|
||||||
await sharedPreferences.setBool(key, isPasswordUpdated);
|
await sharedPreferences.setBool(key, isPasswordUpdated);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,4 +25,4 @@ class BiometricAuth {
|
||||||
|
|
||||||
return canAuthenticate;
|
return canAuthenticate;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,8 @@ String calculateFiatAmount({double? price, String? cryptoAmount}) {
|
||||||
return '0.00';
|
return '0.00';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cryptoAmount = cryptoAmount.replaceAll(',', '.');
|
||||||
|
|
||||||
final _amount = double.parse(cryptoAmount);
|
final _amount = double.parse(cryptoAmount);
|
||||||
final _result = price * _amount;
|
final _result = price * _amount;
|
||||||
final result = _result < 0 ? _result * -1 : _result;
|
final result = _result < 0 ? _result * -1 : _result;
|
||||||
|
|
|
@ -22,7 +22,7 @@ extension ProviderTypeName on ProviderType {
|
||||||
case ProviderType.robinhood:
|
case ProviderType.robinhood:
|
||||||
return 'Robinhood Connect';
|
return 'Robinhood Connect';
|
||||||
case ProviderType.dfx:
|
case ProviderType.dfx:
|
||||||
return 'DFX Connect';
|
return 'DFX.swiss';
|
||||||
case ProviderType.onramper:
|
case ProviderType.onramper:
|
||||||
return 'Onramper';
|
return 'Onramper';
|
||||||
case ProviderType.moonpay:
|
case ProviderType.moonpay:
|
||||||
|
|
|
@ -142,8 +142,10 @@ class CWEthereum extends Ethereum {
|
||||||
}
|
}
|
||||||
|
|
||||||
wallet as EthereumWallet;
|
wallet as EthereumWallet;
|
||||||
return wallet.erc20Currencies
|
|
||||||
.firstWhere((element) => transaction.tokenSymbol == element.symbol);
|
return wallet.erc20Currencies.firstWhere(
|
||||||
|
(element) => transaction.tokenSymbol == element.symbol,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -140,8 +140,10 @@ class CWPolygon extends Polygon {
|
||||||
}
|
}
|
||||||
|
|
||||||
wallet as PolygonWallet;
|
wallet as PolygonWallet;
|
||||||
|
|
||||||
return wallet.erc20Currencies.firstWhere(
|
return wallet.erc20Currencies.firstWhere(
|
||||||
(element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase());
|
(element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -110,8 +110,10 @@ class CWSolana extends Solana {
|
||||||
}
|
}
|
||||||
|
|
||||||
wallet as SolanaWallet;
|
wallet as SolanaWallet;
|
||||||
return wallet.splTokenCurrencies
|
|
||||||
.firstWhere((element) => transaction.tokenSymbol == element.symbol);
|
return wallet.splTokenCurrencies.firstWhere(
|
||||||
|
(element) => transaction.tokenSymbol == element.symbol,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -96,18 +96,20 @@ class NodeForm extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 10.0),
|
SizedBox(height: 10.0),
|
||||||
Row(
|
if (nodeViewModel.hasPathSupport) ...[
|
||||||
children: <Widget>[
|
Row(
|
||||||
Expanded(
|
children: <Widget>[
|
||||||
child: BaseTextFormField(
|
Expanded(
|
||||||
controller: _pathController,
|
child: BaseTextFormField(
|
||||||
hintText: "/path",
|
controller: _pathController,
|
||||||
validator: NodePathValidator(),
|
hintText: "/path",
|
||||||
),
|
validator: NodePathValidator(),
|
||||||
)
|
),
|
||||||
],
|
)
|
||||||
),
|
],
|
||||||
SizedBox(height: 10.0),
|
),
|
||||||
|
SizedBox(height: 10.0),
|
||||||
|
],
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
|
|
|
@ -100,7 +100,7 @@ class SendPage extends BasePage {
|
||||||
AppBarStyle get appBarStyle => AppBarStyle.transparent;
|
AppBarStyle get appBarStyle => AppBarStyle.transparent;
|
||||||
|
|
||||||
double _sendCardHeight(BuildContext context) {
|
double _sendCardHeight(BuildContext context) {
|
||||||
double initialHeight = 450;
|
double initialHeight = 480;
|
||||||
if (sendViewModel.hasCoinControl) {
|
if (sendViewModel.hasCoinControl) {
|
||||||
initialHeight += 35;
|
initialHeight += 35;
|
||||||
}
|
}
|
||||||
|
|
|
@ -675,6 +675,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||||
final selectedItem = items.indexOf(sendViewModel.transactionPriority);
|
final selectedItem = items.indexOf(sendViewModel.transactionPriority);
|
||||||
final customItemIndex = sendViewModel.getCustomPriorityIndex(items);
|
final customItemIndex = sendViewModel.getCustomPriorityIndex(items);
|
||||||
final isBitcoinWallet = sendViewModel.walletType == WalletType.bitcoin;
|
final isBitcoinWallet = sendViewModel.walletType == WalletType.bitcoin;
|
||||||
|
final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
|
||||||
double? customFeeRate = isBitcoinWallet ? sendViewModel.customBitcoinFeeRate.toDouble() : null;
|
double? customFeeRate = isBitcoinWallet ? sendViewModel.customBitcoinFeeRate.toDouble() : null;
|
||||||
|
|
||||||
await showPopUp<void>(
|
await showPopUp<void>(
|
||||||
|
@ -689,6 +690,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||||
sendViewModel.displayFeeRate(priority, customFeeRate?.round()),
|
sendViewModel.displayFeeRate(priority, customFeeRate?.round()),
|
||||||
selectedAtIndex: selectedIdx,
|
selectedAtIndex: selectedIdx,
|
||||||
customItemIndex: customItemIndex,
|
customItemIndex: customItemIndex,
|
||||||
|
maxValue: maxCustomFeeRate,
|
||||||
title: S.of(context).please_select,
|
title: S.of(context).please_select,
|
||||||
headerEnabled: !isBitcoinWallet,
|
headerEnabled: !isBitcoinWallet,
|
||||||
closeOnItemSelected: !isBitcoinWallet,
|
closeOnItemSelected: !isBitcoinWallet,
|
||||||
|
|
|
@ -37,6 +37,7 @@ class OtherSettingsPage extends BasePage {
|
||||||
customItemIndex: _otherSettingsViewModel.customPriorityItemIndex,
|
customItemIndex: _otherSettingsViewModel.customPriorityItemIndex,
|
||||||
onItemSelected: _otherSettingsViewModel.onDisplayBitcoinPrioritySelected,
|
onItemSelected: _otherSettingsViewModel.onDisplayBitcoinPrioritySelected,
|
||||||
customValue: _otherSettingsViewModel.customBitcoinFeeRate,
|
customValue: _otherSettingsViewModel.customBitcoinFeeRate,
|
||||||
|
maxValue: _otherSettingsViewModel.maxCustomFeeRate?.toDouble(),
|
||||||
) :
|
) :
|
||||||
SettingsPickerCell(
|
SettingsPickerCell(
|
||||||
title: S.current.settings_fee_priority,
|
title: S.current.settings_fee_priority,
|
||||||
|
|
|
@ -15,6 +15,7 @@ class SettingsPriorityPickerCell<ItemType> extends StandardListRow {
|
||||||
this.isGridView = false,
|
this.isGridView = false,
|
||||||
this.matchingCriteria,
|
this.matchingCriteria,
|
||||||
this.customValue,
|
this.customValue,
|
||||||
|
this.maxValue,
|
||||||
this.customItemIndex,
|
this.customItemIndex,
|
||||||
this.onItemSelected})
|
this.onItemSelected})
|
||||||
: super(
|
: super(
|
||||||
|
@ -34,6 +35,7 @@ class SettingsPriorityPickerCell<ItemType> extends StandardListRow {
|
||||||
displayItem: (ItemType item) => displayItem!(item, sliderValue.round()),
|
displayItem: (ItemType item) => displayItem!(item, sliderValue.round()),
|
||||||
selectedAtIndex: selectedAtIndex,
|
selectedAtIndex: selectedAtIndex,
|
||||||
customItemIndex: customItemIndex,
|
customItemIndex: customItemIndex,
|
||||||
|
maxValue: maxValue,
|
||||||
headerEnabled: false,
|
headerEnabled: false,
|
||||||
closeOnItemSelected: false,
|
closeOnItemSelected: false,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
@ -61,6 +63,7 @@ class SettingsPriorityPickerCell<ItemType> extends StandardListRow {
|
||||||
final bool isGridView;
|
final bool isGridView;
|
||||||
final bool Function(ItemType, String)? matchingCriteria;
|
final bool Function(ItemType, String)? matchingCriteria;
|
||||||
double? customValue;
|
double? customValue;
|
||||||
|
double? maxValue;
|
||||||
int? customItemIndex;
|
int? customItemIndex;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -10,6 +10,7 @@ class StandardPickerListItem<T> extends TransactionDetailsListItem {
|
||||||
required this.onItemSelected,
|
required this.onItemSelected,
|
||||||
required this.selectedIdx,
|
required this.selectedIdx,
|
||||||
required this.customItemIndex,
|
required this.customItemIndex,
|
||||||
|
this.maxValue,
|
||||||
required this.customValue})
|
required this.customValue})
|
||||||
: super(title: title, value: value);
|
: super(title: title, value: value);
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ class StandardPickerListItem<T> extends TransactionDetailsListItem {
|
||||||
final Function(double) onSliderChanged;
|
final Function(double) onSliderChanged;
|
||||||
final Function(T) onItemSelected;
|
final Function(T) onItemSelected;
|
||||||
final int selectedIdx;
|
final int selectedIdx;
|
||||||
|
final double? maxValue;
|
||||||
final int customItemIndex;
|
final int customItemIndex;
|
||||||
double customValue;
|
double customValue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ class RBFDetailsPage extends BasePage {
|
||||||
selectedIdx: item.selectedIdx,
|
selectedIdx: item.selectedIdx,
|
||||||
customItemIndex: item.customItemIndex,
|
customItemIndex: item.customItemIndex,
|
||||||
customValue: item.customValue,
|
customValue: item.customValue,
|
||||||
|
maxValue: item.maxValue,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,21 @@ class Picker<Item> extends StatefulWidget {
|
||||||
this.headerEnabled = true,
|
this.headerEnabled = true,
|
||||||
this.closeOnItemSelected = true,
|
this.closeOnItemSelected = true,
|
||||||
this.sliderValue,
|
this.sliderValue,
|
||||||
|
this.minValue,
|
||||||
|
this.maxValue,
|
||||||
this.customItemIndex,
|
this.customItemIndex,
|
||||||
this.isWrapped = true,
|
this.isWrapped = true,
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
this.onSliderChanged,
|
this.onSliderChanged,
|
||||||
this.matchingCriteria,
|
this.matchingCriteria,
|
||||||
}) : assert(hintText == null ||
|
}) : assert(hintText == null || matchingCriteria != null) {
|
||||||
matchingCriteria !=
|
// make sure that if the search field is enabled then there is a searching criteria provided
|
||||||
null); // make sure that if the search field is enabled then there is a searching criteria provided
|
if (sliderValue != null && maxValue != null) {
|
||||||
|
if (sliderValue! > maxValue!) {
|
||||||
|
sliderValue = maxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final int selectedAtIndex;
|
final int selectedAtIndex;
|
||||||
final List<Item> items;
|
final List<Item> items;
|
||||||
|
@ -49,12 +56,14 @@ class Picker<Item> extends StatefulWidget {
|
||||||
final String? hintText;
|
final String? hintText;
|
||||||
final bool headerEnabled;
|
final bool headerEnabled;
|
||||||
final bool closeOnItemSelected;
|
final bool closeOnItemSelected;
|
||||||
final double? sliderValue;
|
double? sliderValue;
|
||||||
|
final double? minValue;
|
||||||
final int? customItemIndex;
|
final int? customItemIndex;
|
||||||
final bool isWrapped;
|
final bool isWrapped;
|
||||||
final Color? borderColor;
|
final Color? borderColor;
|
||||||
final Function(double)? onSliderChanged;
|
final Function(double)? onSliderChanged;
|
||||||
final bool Function(Item, String)? matchingCriteria;
|
final bool Function(Item, String)? matchingCriteria;
|
||||||
|
final double? maxValue;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_PickerState<Item> createState() => _PickerState<Item>(items, images, onItemSelected);
|
_PickerState<Item> createState() => _PickerState<Item>(items, images, onItemSelected);
|
||||||
|
@ -138,7 +147,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
containerHeight = height * 0.75;
|
containerHeight = height * 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
final content = Column (
|
final content = Column(
|
||||||
children: [
|
children: [
|
||||||
if (widget.title?.isNotEmpty ?? false)
|
if (widget.title?.isNotEmpty ?? false)
|
||||||
Container(
|
Container(
|
||||||
|
@ -211,8 +220,9 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
fontFamily: 'Lato',
|
fontFamily: 'Lato',
|
||||||
decoration: TextDecoration.none,
|
decoration: TextDecoration.none,
|
||||||
color:
|
color: Theme.of(context)
|
||||||
Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
.extension<CakeTextTheme>()!
|
||||||
|
.titleColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -491,8 +501,8 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
child: Slider(
|
child: Slider(
|
||||||
value: widget.sliderValue ?? 1,
|
value: widget.sliderValue ?? 1,
|
||||||
onChanged: isActivated ? widget.onSliderChanged : null,
|
onChanged: isActivated ? widget.onSliderChanged : null,
|
||||||
min: 1,
|
min: widget.minValue ?? 1,
|
||||||
max: 100,
|
max: widget.maxValue ?? 100,
|
||||||
divisions: 100,
|
divisions: 100,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -15,6 +15,7 @@ class StandardPickerList<T> extends StatefulWidget {
|
||||||
required this.selectedIdx,
|
required this.selectedIdx,
|
||||||
required this.customItemIndex,
|
required this.customItemIndex,
|
||||||
required this.customValue,
|
required this.customValue,
|
||||||
|
this.maxValue,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
|
@ -26,6 +27,7 @@ class StandardPickerList<T> extends StatefulWidget {
|
||||||
final String value;
|
final String value;
|
||||||
final int selectedIdx;
|
final int selectedIdx;
|
||||||
final double customValue;
|
final double customValue;
|
||||||
|
final double? maxValue;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_StandardPickerListState<T> createState() => _StandardPickerListState<T>();
|
_StandardPickerListState<T> createState() => _StandardPickerListState<T>();
|
||||||
|
@ -59,6 +61,7 @@ class _StandardPickerListState<T> extends State<StandardPickerList<T>> {
|
||||||
displayItem: adaptedDisplayItem,
|
displayItem: adaptedDisplayItem,
|
||||||
selectedAtIndex: selectedIdx,
|
selectedAtIndex: selectedIdx,
|
||||||
customItemIndex: widget.customItemIndex,
|
customItemIndex: widget.customItemIndex,
|
||||||
|
maxValue: widget.maxValue,
|
||||||
headerEnabled: false,
|
headerEnabled: false,
|
||||||
closeOnItemSelected: false,
|
closeOnItemSelected: false,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
|
|
@ -173,4 +173,4 @@ class ValidatableAnnotatedEditableTextState extends EditableTextState {
|
||||||
|
|
||||||
return TextSpan(style: widget.style, text: text);
|
return TextSpan(style: widget.style, text: text);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -124,4 +124,4 @@ abstract class AuthViewModelBase with Store {
|
||||||
_authService.saveLastAuthTime();
|
_authService.saveLastAuthTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,8 +3,20 @@ import 'dart:collection';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
import 'package:cake_wallet/core/create_trade_result.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/sync_status.dart';
|
||||||
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
|
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||||
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
|
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
|
||||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||||
|
@ -33,14 +45,6 @@ import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cake_wallet/store/templates/exchange_template_store.dart';
|
import 'package:cake_wallet/store/templates/exchange_template_store.dart';
|
||||||
import 'package:cake_wallet/utils/feature_flag.dart';
|
import 'package:cake_wallet/utils/feature_flag.dart';
|
||||||
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
|
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
|
||||||
import 'package:cw_core/sync_status.dart';
|
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
|
||||||
import 'package:cw_core/wallet_type.dart';
|
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
import 'package:mobx/mobx.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
part 'exchange_view_model.g.dart';
|
part 'exchange_view_model.g.dart';
|
||||||
|
|
||||||
|
@ -516,10 +520,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
trade.walletId = wallet.id;
|
trade.walletId = wallet.id;
|
||||||
trade.fromWalletAddress = wallet.walletAddresses.address;
|
trade.fromWalletAddress = wallet.walletAddresses.address;
|
||||||
|
|
||||||
if (!isCanCreateTrade(trade)) {
|
final canCreateTrade = await isCanCreateTrade(trade);
|
||||||
|
if (!canCreateTrade.result) {
|
||||||
tradeState = TradeIsCreatedFailure(
|
tradeState = TradeIsCreatedFailure(
|
||||||
title: S.current.trade_not_created,
|
title: S.current.trade_not_created,
|
||||||
error: S.current.thorchain_taproot_address_not_supported);
|
error: canCreateTrade.errorMessage ?? '',
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,16 +782,100 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
|
|
||||||
int get receiveMaxDigits => receiveCurrency.decimals;
|
int get receiveMaxDigits => receiveCurrency.decimals;
|
||||||
|
|
||||||
bool isCanCreateTrade(Trade trade) {
|
Future<CreateTradeResult> isCanCreateTrade(Trade trade) async {
|
||||||
if (trade.provider == ExchangeProviderDescription.thorChain) {
|
if (trade.provider == ExchangeProviderDescription.thorChain) {
|
||||||
final payoutAddress = trade.payoutAddress ?? '';
|
final payoutAddress = trade.payoutAddress ?? '';
|
||||||
final fromWalletAddress = trade.fromWalletAddress ?? '';
|
final fromWalletAddress = trade.fromWalletAddress ?? '';
|
||||||
final tapRootPattern = RegExp(P2trAddress.regex.pattern);
|
final tapRootPattern = RegExp(P2trAddress.regex.pattern);
|
||||||
|
|
||||||
if (tapRootPattern.hasMatch(payoutAddress) || tapRootPattern.hasMatch(fromWalletAddress)) {
|
if (tapRootPattern.hasMatch(payoutAddress) || tapRootPattern.hasMatch(fromWalletAddress)) {
|
||||||
return false;
|
return CreateTradeResult(
|
||||||
|
result: false,
|
||||||
|
errorMessage: S.current.thorchain_taproot_address_not_supported,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final currenciesToCheckPattern = RegExp('0x[0-9a-zA-Z]');
|
||||||
|
|
||||||
|
// Perform checks for payOutAddress
|
||||||
|
final isPayOutAddressAccordingToPattern = currenciesToCheckPattern.hasMatch(payoutAddress);
|
||||||
|
|
||||||
|
if (isPayOutAddressAccordingToPattern) {
|
||||||
|
final isPayOutAddressEOA = await _isExternallyOwnedAccountAddress(payoutAddress);
|
||||||
|
|
||||||
|
return CreateTradeResult(
|
||||||
|
result: isPayOutAddressEOA,
|
||||||
|
errorMessage:
|
||||||
|
!isPayOutAddressEOA ? S.current.thorchain_contract_address_not_supported : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform checks for fromWalletAddress
|
||||||
|
final isFromWalletAddressAddressAccordingToPattern =
|
||||||
|
currenciesToCheckPattern.hasMatch(fromWalletAddress);
|
||||||
|
|
||||||
|
if (isFromWalletAddressAddressAccordingToPattern) {
|
||||||
|
final isFromWalletAddressEOA = await _isExternallyOwnedAccountAddress(fromWalletAddress);
|
||||||
|
|
||||||
|
return CreateTradeResult(
|
||||||
|
result: isFromWalletAddressEOA,
|
||||||
|
errorMessage:
|
||||||
|
!isFromWalletAddressEOA ? S.current.thorchain_contract_address_not_supported : null,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return CreateTradeResult(result: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _normalizeReceiveCurrency(CryptoCurrency receiveCurrency) {
|
||||||
|
switch (receiveCurrency) {
|
||||||
|
case CryptoCurrency.eth:
|
||||||
|
return 'eth';
|
||||||
|
case CryptoCurrency.maticpoly:
|
||||||
|
return 'polygon';
|
||||||
|
default:
|
||||||
|
return receiveCurrency.tag ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _isExternallyOwnedAccountAddress(String receivingAddress) async {
|
||||||
|
final normalizedReceiveCurrency = _normalizeReceiveCurrency(receiveCurrency);
|
||||||
|
|
||||||
|
final isEOAAddress = !(await _isContractAddress(normalizedReceiveCurrency, receivingAddress));
|
||||||
|
return isEOAAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _isContractAddress(String chainName, String contractAddress) async {
|
||||||
|
final httpClient = http.Client();
|
||||||
|
|
||||||
|
final uri = Uri.https(
|
||||||
|
'deep-index.moralis.io',
|
||||||
|
'/api/v2.2/erc20/metadata',
|
||||||
|
{
|
||||||
|
"chain": chainName,
|
||||||
|
"addresses": contractAddress,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await httpClient.get(
|
||||||
|
uri,
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"X-API-Key": secrets.moralisApiKey,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final decodedResponse = jsonDecode(response.body)[0] as Map<String, dynamic>;
|
||||||
|
|
||||||
|
final name = decodedResponse['name'] as String?;
|
||||||
|
|
||||||
|
bool isContractAddress = name!.isNotEmpty;
|
||||||
|
|
||||||
|
return isContractAddress;
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,24 @@ abstract class NodeCreateOrEditViewModelBase with Store {
|
||||||
|
|
||||||
bool get hasTestnetSupport => _walletType == WalletType.bitcoin;
|
bool get hasTestnetSupport => _walletType == WalletType.bitcoin;
|
||||||
|
|
||||||
|
bool get hasPathSupport {
|
||||||
|
switch (_walletType) {
|
||||||
|
case WalletType.ethereum:
|
||||||
|
case WalletType.polygon:
|
||||||
|
case WalletType.solana:
|
||||||
|
case WalletType.banano:
|
||||||
|
case WalletType.nano:
|
||||||
|
return true;
|
||||||
|
case WalletType.none:
|
||||||
|
case WalletType.monero:
|
||||||
|
case WalletType.haven:
|
||||||
|
case WalletType.litecoin:
|
||||||
|
case WalletType.bitcoinCash:
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String get uri {
|
String get uri {
|
||||||
var uri = address;
|
var uri = address;
|
||||||
|
|
||||||
|
@ -217,7 +235,6 @@ abstract class NodeCreateOrEditViewModelBase with Store {
|
||||||
final port = uri.port.toString();
|
final port = uri.port.toString();
|
||||||
final path = uri.path;
|
final path = uri.path;
|
||||||
|
|
||||||
|
|
||||||
setAddress(ipAddress);
|
setAddress(ipAddress);
|
||||||
setPath(path);
|
setPath(path);
|
||||||
setPassword(rpcPassword);
|
setPassword(rpcPassword);
|
||||||
|
|
|
@ -126,8 +126,8 @@ abstract class OutputBase with Store {
|
||||||
|
|
||||||
if (_wallet.type == WalletType.bitcoin) {
|
if (_wallet.type == WalletType.bitcoin) {
|
||||||
if (_settingsStore.priority[_wallet.type] == bitcoin!.getBitcoinTransactionPriorityCustom()) {
|
if (_settingsStore.priority[_wallet.type] == bitcoin!.getBitcoinTransactionPriorityCustom()) {
|
||||||
fee = bitcoin!.getFeeAmountWithFeeRate(
|
fee = bitcoin!.getEstimatedFeeWithFeeRate(_wallet,
|
||||||
_settingsStore.customBitcoinFeeRate, formattedCryptoAmount, 1, 1);
|
_settingsStore.customBitcoinFeeRate,formattedCryptoAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitcoin!.formatterBitcoinAmountToDouble(amount: fee);
|
return bitcoin!.formatterBitcoinAmountToDouble(amount: fee);
|
||||||
|
|
|
@ -166,6 +166,13 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int? get maxCustomFeeRate {
|
||||||
|
if (wallet.type == WalletType.bitcoin) {
|
||||||
|
return bitcoin!.getMaxCustomFeeRate(wallet);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate;
|
int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate;
|
||||||
|
|
||||||
|
@ -324,14 +331,16 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
Future<PendingTransaction?> createTransaction({ExchangeProvider? provider}) async {
|
Future<PendingTransaction?> createTransaction({ExchangeProvider? provider}) async {
|
||||||
try {
|
try {
|
||||||
state = IsExecutingState();
|
state = IsExecutingState();
|
||||||
|
|
||||||
pendingTransaction = await wallet.createTransaction(_credentials());
|
pendingTransaction = await wallet.createTransaction(_credentials());
|
||||||
if (provider is ThorChainExchangeProvider) {
|
if (provider is ThorChainExchangeProvider) {
|
||||||
final outputCount = pendingTransaction?.outputCount ?? 0;
|
final outputCount = pendingTransaction?.outputCount ?? 0;
|
||||||
if (outputCount > 10) {
|
if (outputCount > 10) {
|
||||||
throw Exception("ThorChain does not support more than 10 outputs");
|
throw Exception("THORChain does not support more than 10 outputs");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_hasTaprootInput(pendingTransaction)) {
|
if (_hasTaprootInput(pendingTransaction)) {
|
||||||
throw Exception("ThorChain does not support Taproot addresses");
|
throw Exception("THORChain does not support Taproot addresses");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = ExecutedSuccessfullyState();
|
state = ExecutedSuccessfullyState();
|
||||||
|
@ -553,7 +562,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
return S.current.tx_no_dust_exception;
|
return S.current.tx_no_dust_exception;
|
||||||
}
|
}
|
||||||
if (error is TransactionCommitFailed) {
|
if (error is TransactionCommitFailed) {
|
||||||
return S.current.tx_commit_failed;
|
return "${S.current.tx_commit_failed}${error.errorMessage != null ? "\n\n${error.errorMessage}" : ""}";
|
||||||
}
|
}
|
||||||
if (error is TransactionCommitFailedDustChange) {
|
if (error is TransactionCommitFailedDustChange) {
|
||||||
return S.current.tx_rejected_dust_change;
|
return S.current.tx_rejected_dust_change;
|
||||||
|
|
|
@ -140,6 +140,13 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||||
return customItem != null ? priorities.indexOf(customItem) : null;
|
return customItem != null ? priorities.indexOf(customItem) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int? get maxCustomFeeRate {
|
||||||
|
if (_wallet.type == WalletType.bitcoin) {
|
||||||
|
return bitcoin!.getMaxCustomFeeRate(_wallet);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
ProviderType onBuyProviderTypeSelected(ProviderType buyProviderType) =>
|
ProviderType onBuyProviderTypeSelected(ProviderType buyProviderType) =>
|
||||||
_settingsStore.defaultBuyProviders[walletType] = buyProviderType;
|
_settingsStore.defaultBuyProviders[walletType] = buyProviderType;
|
||||||
|
|
|
@ -348,12 +348,14 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||||
final customItem = priorities.firstWhereOrNull(
|
final customItem = priorities.firstWhereOrNull(
|
||||||
(element) => element == sendViewModel.bitcoinTransactionPriorityCustom);
|
(element) => element == sendViewModel.bitcoinTransactionPriorityCustom);
|
||||||
final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null;
|
final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null;
|
||||||
|
final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
|
||||||
|
|
||||||
RBFListItems.add(StandardPickerListItem(
|
RBFListItems.add(StandardPickerListItem(
|
||||||
title: S.current.estimated_new_fee,
|
title: S.current.estimated_new_fee,
|
||||||
value: bitcoin!.formatterBitcoinAmountToString(amount: newFee) + ' ${walletTypeToCryptoCurrency(wallet.type)}',
|
value: bitcoin!.formatterBitcoinAmountToString(amount: newFee) + ' ${walletTypeToCryptoCurrency(wallet.type)}',
|
||||||
items: priorityForWalletType(wallet.type),
|
items: priorityForWalletType(wallet.type),
|
||||||
customValue: settingsStore.customBitcoinFeeRate.toDouble(),
|
customValue: settingsStore.customBitcoinFeeRate.toDouble(),
|
||||||
|
maxValue: maxCustomFeeRate,
|
||||||
selectedIdx: selectedItem,
|
selectedIdx: selectedItem,
|
||||||
customItemIndex: customItemIndex ?? 0,
|
customItemIndex: customItemIndex ?? 0,
|
||||||
displayItem: (dynamic priority, double sliderValue) =>
|
displayItem: (dynamic priority, double sliderValue) =>
|
||||||
|
@ -388,16 +390,12 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||||
|
|
||||||
String setNewFee({double? value, required TransactionPriority priority}) {
|
String setNewFee({double? value, required TransactionPriority priority}) {
|
||||||
newFee = priority == bitcoin!.getBitcoinTransactionPriorityCustom() && value != null
|
newFee = priority == bitcoin!.getBitcoinTransactionPriorityCustom() && value != null
|
||||||
? bitcoin!.getFeeAmountWithFeeRate(
|
? bitcoin!.getEstimatedFeeWithFeeRate(wallet, value.round(), transactionInfo.amount)
|
||||||
wallet,
|
|
||||||
value.round(),
|
|
||||||
transactionInfo.inputAddresses?.length ?? 1,
|
|
||||||
transactionInfo.outputAddresses?.length ?? 1)
|
|
||||||
: bitcoin!.getFeeAmountForPriority(
|
: bitcoin!.getFeeAmountForPriority(
|
||||||
wallet,
|
wallet,
|
||||||
priority,
|
priority,
|
||||||
transactionInfo.inputAddresses?.length ?? 1,
|
transactionInfo.inputAddresses?.length ?? 1,
|
||||||
transactionInfo.outputAddresses?.length ?? 1);
|
transactionInfo.outputAddresses?.length ?? 1);
|
||||||
|
|
||||||
return bitcoin!.formatterBitcoinAmountToString(amount: newFee);
|
return bitcoin!.formatterBitcoinAmountToString(amount: newFee);
|
||||||
}
|
}
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "اسم القالب",
|
"template_name": "اسم القالب",
|
||||||
"third_intro_content": "يعيش Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة على وجه الأرض بـ Yat!",
|
"third_intro_content": "يعيش Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة على وجه الأرض بـ Yat!",
|
||||||
"third_intro_title": "يتماشي Yat بلطف مع الآخرين",
|
"third_intro_title": "يتماشي Yat بلطف مع الآخرين",
|
||||||
|
"thorchain_contract_address_not_supported": "لا يدعم Thorchain الإرسال إلى عنوان العقد",
|
||||||
"thorchain_taproot_address_not_supported": "لا يدعم مزود Thorchain عناوين Taproot. يرجى تغيير العنوان أو تحديد مزود مختلف.",
|
"thorchain_taproot_address_not_supported": "لا يدعم مزود Thorchain عناوين Taproot. يرجى تغيير العنوان أو تحديد مزود مختلف.",
|
||||||
"time": "${minutes}د ${seconds}س",
|
"time": "${minutes}د ${seconds}س",
|
||||||
"tip": "بقشيش:",
|
"tip": "بقشيش:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "Име на шаблон",
|
"template_name": "Име на шаблон",
|
||||||
"third_intro_content": "Yats също живее извън Cake Wallet. Всеки адрес на портфейл може да бъде заменен с Yat!",
|
"third_intro_content": "Yats също живее извън Cake Wallet. Всеки адрес на портфейл може да бъде заменен с Yat!",
|
||||||
"third_intro_title": "Yat добре се сработва с други",
|
"third_intro_title": "Yat добре се сработва с други",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain не подкрепя изпращането до адрес на договор",
|
||||||
"thorchain_taproot_address_not_supported": "Доставчикът на Thorchain не поддържа адреси на TapRoot. Моля, променете адреса или изберете друг доставчик.",
|
"thorchain_taproot_address_not_supported": "Доставчикът на Thorchain не поддържа адреси на TapRoot. Моля, променете адреса или изберете друг доставчик.",
|
||||||
"time": "${minutes} мин ${seconds} сек",
|
"time": "${minutes} мин ${seconds} сек",
|
||||||
"tip": "Tip:",
|
"tip": "Tip:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "Název šablony",
|
"template_name": "Název šablony",
|
||||||
"third_intro_content": "Yat existuje i mimo Cake Wallet. Jakákoliv adresa peněženky na světě může být nahrazena Yatem!",
|
"third_intro_content": "Yat existuje i mimo Cake Wallet. Jakákoliv adresa peněženky na světě může být nahrazena Yatem!",
|
||||||
"third_intro_title": "Yat dobře spolupracuje s ostatními",
|
"third_intro_title": "Yat dobře spolupracuje s ostatními",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain nepodporuje odeslání na adresu smlouvy",
|
||||||
"thorchain_taproot_address_not_supported": "Poskytovatel Thorchain nepodporuje adresy Taproot. Změňte adresu nebo vyberte jiného poskytovatele.",
|
"thorchain_taproot_address_not_supported": "Poskytovatel Thorchain nepodporuje adresy Taproot. Změňte adresu nebo vyberte jiného poskytovatele.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Spropitné:",
|
"tip": "Spropitné:",
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
"anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.",
|
"anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.",
|
||||||
"apk_update": "APK-Update",
|
"apk_update": "APK-Update",
|
||||||
"approve": "Genehmigen",
|
"approve": "Genehmigen",
|
||||||
"arrive_in_this_address": "${currency} ${tag}wird an dieser Adresse ankommen",
|
"arrive_in_this_address": "${currency} ${tag} wird an dieser Adresse ankommen",
|
||||||
"ascending": "Aufsteigend",
|
"ascending": "Aufsteigend",
|
||||||
"ask_each_time": "Jedes Mal fragen",
|
"ask_each_time": "Jedes Mal fragen",
|
||||||
"auth_store_ban_timeout": "ban_timeout",
|
"auth_store_ban_timeout": "ban_timeout",
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
"buy_provider_unavailable": "Anbieter derzeit nicht verfügbar.",
|
"buy_provider_unavailable": "Anbieter derzeit nicht verfügbar.",
|
||||||
"buy_with": "Kaufen mit",
|
"buy_with": "Kaufen mit",
|
||||||
"by_cake_pay": "von Cake Pay",
|
"by_cake_pay": "von Cake Pay",
|
||||||
"cake_2fa_preset": "Kuchen 2FA-Voreinstellung",
|
"cake_2fa_preset": "Cake 2FA-Voreinstellung",
|
||||||
"cake_dark_theme": "Cake Dark Thema",
|
"cake_dark_theme": "Cake Dark Thema",
|
||||||
"cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!",
|
"cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!",
|
||||||
"cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.",
|
"cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.",
|
||||||
|
@ -120,7 +120,7 @@
|
||||||
"change_wallet_alert_title": "Aktuelle Wallet ändern",
|
"change_wallet_alert_title": "Aktuelle Wallet ändern",
|
||||||
"choose_account": "Konto auswählen",
|
"choose_account": "Konto auswählen",
|
||||||
"choose_address": "\n\nBitte wählen Sie die Adresse:",
|
"choose_address": "\n\nBitte wählen Sie die Adresse:",
|
||||||
"choose_derivation": "Wählen Sie Brieftaschenableitung",
|
"choose_derivation": "Wählen Sie Wallet-Ableitung",
|
||||||
"choose_from_available_options": "Wähle aus verfügbaren Optionen:",
|
"choose_from_available_options": "Wähle aus verfügbaren Optionen:",
|
||||||
"choose_one": "Wähle ein",
|
"choose_one": "Wähle ein",
|
||||||
"choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus",
|
"choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus",
|
||||||
|
@ -199,7 +199,7 @@
|
||||||
"disable_fiat": "Fiat deaktivieren",
|
"disable_fiat": "Fiat deaktivieren",
|
||||||
"disable_sell": "Verkaufsaktion deaktivieren",
|
"disable_sell": "Verkaufsaktion deaktivieren",
|
||||||
"disableBatteryOptimization": "Batterieoptimierung deaktivieren",
|
"disableBatteryOptimization": "Batterieoptimierung deaktivieren",
|
||||||
"disableBatteryOptimizationDescription": "Möchten Sie die Batterieoptimierung deaktivieren, um die Hintergrundsynchronisierung freier und reibungsloser zu gestalten?",
|
"disableBatteryOptimizationDescription": "Möchten Sie die Batterieoptimierung deaktivieren, um die Hintergrundsynchronisierung reibungsloser zu gestalten?",
|
||||||
"disabled": "Deaktiviert",
|
"disabled": "Deaktiviert",
|
||||||
"discount": "${value} % sparen",
|
"discount": "${value} % sparen",
|
||||||
"display_settings": "Anzeigeeinstellungen",
|
"display_settings": "Anzeigeeinstellungen",
|
||||||
|
@ -460,8 +460,8 @@
|
||||||
"reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?",
|
"reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?",
|
||||||
"reconnection": "Neu verbinden",
|
"reconnection": "Neu verbinden",
|
||||||
"red_dark_theme": "Red Dark Thema",
|
"red_dark_theme": "Red Dark Thema",
|
||||||
"red_light_theme": "Rotlichtthema",
|
"red_light_theme": "Red Light Thema",
|
||||||
"redeemed": "Versilbert",
|
"redeemed": "Eingelöst",
|
||||||
"refund_address": "Rückerstattungsadresse",
|
"refund_address": "Rückerstattungsadresse",
|
||||||
"reject": "Ablehnen",
|
"reject": "Ablehnen",
|
||||||
"remaining": "Rest",
|
"remaining": "Rest",
|
||||||
|
@ -533,7 +533,7 @@
|
||||||
"seed_alert_title": "Achtung",
|
"seed_alert_title": "Achtung",
|
||||||
"seed_alert_yes": "Ja, habe ich",
|
"seed_alert_yes": "Ja, habe ich",
|
||||||
"seed_choose": "Seed-Sprache auswählen",
|
"seed_choose": "Seed-Sprache auswählen",
|
||||||
"seed_hex_form": "Brieftaschensamen (Sechskantform)",
|
"seed_hex_form": "Seed (Hexformat)",
|
||||||
"seed_key": "Seed-Schlüssel",
|
"seed_key": "Seed-Schlüssel",
|
||||||
"seed_language": "Seed-Sprache",
|
"seed_language": "Seed-Sprache",
|
||||||
"seed_language_chinese": "Chinesisch",
|
"seed_language_chinese": "Chinesisch",
|
||||||
|
@ -585,7 +585,7 @@
|
||||||
"send_your_wallet": "Ihre Wallet",
|
"send_your_wallet": "Ihre Wallet",
|
||||||
"sending": "Senden",
|
"sending": "Senden",
|
||||||
"sent": "Versendet",
|
"sent": "Versendet",
|
||||||
"service_health_disabled": "Service Health Bulletin ist behindert",
|
"service_health_disabled": "Service Health Bulletin ist deaktiviert",
|
||||||
"service_health_disabled_message": "Dies ist die Seite \"Service Health Bulletin\", können Sie diese Seite unter Einstellungen -> Privatsphäre aktivieren",
|
"service_health_disabled_message": "Dies ist die Seite \"Service Health Bulletin\", können Sie diese Seite unter Einstellungen -> Privatsphäre aktivieren",
|
||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
"settings_all": "ALLE",
|
"settings_all": "ALLE",
|
||||||
|
@ -668,6 +668,7 @@
|
||||||
"template_name": "Vorlagenname",
|
"template_name": "Vorlagenname",
|
||||||
"third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!",
|
"third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!",
|
||||||
"third_intro_title": "Yat spielt gut mit anderen",
|
"third_intro_title": "Yat spielt gut mit anderen",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain unterstützt das Senden an eine Vertragsadresse nicht",
|
||||||
"thorchain_taproot_address_not_supported": "Der Thorchain -Anbieter unterstützt keine Taproot -Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.",
|
"thorchain_taproot_address_not_supported": "Der Thorchain -Anbieter unterstützt keine Taproot -Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Hinweis:",
|
"tip": "Hinweis:",
|
||||||
|
@ -829,4 +830,4 @@
|
||||||
"you_will_get": "Konvertieren zu",
|
"you_will_get": "Konvertieren zu",
|
||||||
"you_will_send": "Konvertieren von",
|
"you_will_send": "Konvertieren von",
|
||||||
"yy": "YY"
|
"yy": "YY"
|
||||||
}
|
}
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "Template Name",
|
"template_name": "Template Name",
|
||||||
"third_intro_content": "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!",
|
"third_intro_content": "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!",
|
||||||
"third_intro_title": "Yat plays nicely with others",
|
"third_intro_title": "Yat plays nicely with others",
|
||||||
|
"thorchain_contract_address_not_supported": "THORChain does not support sending to a contract address",
|
||||||
"thorchain_taproot_address_not_supported": "The ThorChain provider does not support Taproot addresses. Please change the address or select a different provider.",
|
"thorchain_taproot_address_not_supported": "The ThorChain provider does not support Taproot addresses. Please change the address or select a different provider.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Tip:",
|
"tip": "Tip:",
|
||||||
|
|
|
@ -668,6 +668,7 @@
|
||||||
"template_name": "Nombre de la plantilla",
|
"template_name": "Nombre de la plantilla",
|
||||||
"third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!",
|
"third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!",
|
||||||
"third_intro_title": "Yat juega muy bien con otras",
|
"third_intro_title": "Yat juega muy bien con otras",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain no admite enviar a una dirección de contrato",
|
||||||
"thorchain_taproot_address_not_supported": "El proveedor de Thorchain no admite las direcciones de Taproot. Cambie la dirección o seleccione un proveedor diferente.",
|
"thorchain_taproot_address_not_supported": "El proveedor de Thorchain no admite las direcciones de Taproot. Cambie la dirección o seleccione un proveedor diferente.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Consejo:",
|
"tip": "Consejo:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "Nom du modèle",
|
"template_name": "Nom du modèle",
|
||||||
"third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !",
|
"third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !",
|
||||||
"third_intro_title": "Yat est universel",
|
"third_intro_title": "Yat est universel",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain ne prend pas en charge l'envoi à une adresse de contrat",
|
||||||
"thorchain_taproot_address_not_supported": "Le fournisseur de Thorchain ne prend pas en charge les adresses de tapoot. Veuillez modifier l'adresse ou sélectionner un autre fournisseur.",
|
"thorchain_taproot_address_not_supported": "Le fournisseur de Thorchain ne prend pas en charge les adresses de tapoot. Veuillez modifier l'adresse ou sélectionner un autre fournisseur.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Pourboire :",
|
"tip": "Pourboire :",
|
||||||
|
|
|
@ -669,6 +669,7 @@
|
||||||
"template_name": "Sunan Samfura",
|
"template_name": "Sunan Samfura",
|
||||||
"third_intro_content": "Yats suna zaune a wajen Kek Wallet, kuma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!",
|
"third_intro_content": "Yats suna zaune a wajen Kek Wallet, kuma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!",
|
||||||
"third_intro_title": "Yat yana wasa da kyau tare da wasu",
|
"third_intro_title": "Yat yana wasa da kyau tare da wasu",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain baya goyon bayan aika zuwa adireshin kwangila",
|
||||||
"thorchain_taproot_address_not_supported": "Mai ba da tallafi na ThorChain baya goyan bayan adreshin taproot. Da fatan za a canza adireshin ko zaɓi mai bayarwa daban.",
|
"thorchain_taproot_address_not_supported": "Mai ba da tallafi na ThorChain baya goyan bayan adreshin taproot. Da fatan za a canza adireshin ko zaɓi mai bayarwa daban.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Tukwici:",
|
"tip": "Tukwici:",
|
||||||
|
|
|
@ -669,6 +669,7 @@
|
||||||
"template_name": "टेम्पलेट नाम",
|
"template_name": "टेम्पलेट नाम",
|
||||||
"third_intro_content": "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!",
|
"third_intro_content": "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!",
|
||||||
"third_intro_title": "Yat दूसरों के साथ अच्छा खेलता है",
|
"third_intro_title": "Yat दूसरों के साथ अच्छा खेलता है",
|
||||||
|
"thorchain_contract_address_not_supported": "थोरचेन एक अनुबंध पते पर भेजने का समर्थन नहीं करता है",
|
||||||
"thorchain_taproot_address_not_supported": "थोरचेन प्रदाता टैपरोट पते का समर्थन नहीं करता है। कृपया पता बदलें या एक अलग प्रदाता का चयन करें।",
|
"thorchain_taproot_address_not_supported": "थोरचेन प्रदाता टैपरोट पते का समर्थन नहीं करता है। कृपया पता बदलें या एक अलग प्रदाता का चयन करें।",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "टिप:",
|
"tip": "टिप:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "Naziv predloška",
|
"template_name": "Naziv predloška",
|
||||||
"third_intro_content": "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!",
|
"third_intro_content": "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!",
|
||||||
"third_intro_title": "Yat se lijepo igra s drugima",
|
"third_intro_title": "Yat se lijepo igra s drugima",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain ne podržava slanje na adresu ugovora",
|
||||||
"thorchain_taproot_address_not_supported": "Thorchain pružatelj ne podržava Taproot adrese. Promijenite adresu ili odaberite drugog davatelja usluga.",
|
"thorchain_taproot_address_not_supported": "Thorchain pružatelj ne podržava Taproot adrese. Promijenite adresu ili odaberite drugog davatelja usluga.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Savjet:",
|
"tip": "Savjet:",
|
||||||
|
|
|
@ -670,6 +670,7 @@
|
||||||
"template_name": "Nama Templat",
|
"template_name": "Nama Templat",
|
||||||
"third_intro_content": "Yats hidup di luar Cake Wallet juga. Setiap alamat dompet di dunia dapat diganti dengan Yat!",
|
"third_intro_content": "Yats hidup di luar Cake Wallet juga. Setiap alamat dompet di dunia dapat diganti dengan Yat!",
|
||||||
"third_intro_title": "Yat bermain baik dengan yang lain",
|
"third_intro_title": "Yat bermain baik dengan yang lain",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain tidak mendukung pengiriman ke alamat kontrak",
|
||||||
"thorchain_taproot_address_not_supported": "Penyedia Thorchain tidak mendukung alamat Taproot. Harap ubah alamatnya atau pilih penyedia yang berbeda.",
|
"thorchain_taproot_address_not_supported": "Penyedia Thorchain tidak mendukung alamat Taproot. Harap ubah alamatnya atau pilih penyedia yang berbeda.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Tip:",
|
"tip": "Tip:",
|
||||||
|
|
|
@ -669,6 +669,7 @@
|
||||||
"template_name": "Nome modello",
|
"template_name": "Nome modello",
|
||||||
"third_intro_content": "Yat può funzionare anche fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con uno Yat!",
|
"third_intro_content": "Yat può funzionare anche fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con uno Yat!",
|
||||||
"third_intro_title": "Yat gioca bene con gli altri",
|
"third_intro_title": "Yat gioca bene con gli altri",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain non supporta l'invio a un indirizzo contrattuale",
|
||||||
"thorchain_taproot_address_not_supported": "Il provider di Thorchain non supporta gli indirizzi di TapRoot. Si prega di modificare l'indirizzo o selezionare un fornitore diverso.",
|
"thorchain_taproot_address_not_supported": "Il provider di Thorchain non supporta gli indirizzi di TapRoot. Si prega di modificare l'indirizzo o selezionare un fornitore diverso.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Suggerimento:",
|
"tip": "Suggerimento:",
|
||||||
|
|
|
@ -668,6 +668,7 @@
|
||||||
"template_name": "テンプレート名",
|
"template_name": "テンプレート名",
|
||||||
"third_intro_content": "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!",
|
"third_intro_content": "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!",
|
||||||
"third_intro_title": "Yatは他の人とうまく遊ぶ",
|
"third_intro_title": "Yatは他の人とうまく遊ぶ",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchainは、契約アドレスへの送信をサポートしていません",
|
||||||
"thorchain_taproot_address_not_supported": "Thorchainプロバイダーは、TapRootアドレスをサポートしていません。アドレスを変更するか、別のプロバイダーを選択してください。",
|
"thorchain_taproot_address_not_supported": "Thorchainプロバイダーは、TapRootアドレスをサポートしていません。アドレスを変更するか、別のプロバイダーを選択してください。",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "ヒント: ",
|
"tip": "ヒント: ",
|
||||||
|
|
|
@ -668,6 +668,7 @@
|
||||||
"template_name": "템플릿 이름",
|
"template_name": "템플릿 이름",
|
||||||
"third_intro_content": "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!",
|
"third_intro_content": "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!",
|
||||||
"third_intro_title": "Yat는 다른 사람들과 잘 놉니다.",
|
"third_intro_title": "Yat는 다른 사람들과 잘 놉니다.",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain은 계약 주소로 보내는 것을 지원하지 않습니다",
|
||||||
"thorchain_taproot_address_not_supported": "Thorchain 제공 업체는 Taproot 주소를 지원하지 않습니다. 주소를 변경하거나 다른 공급자를 선택하십시오.",
|
"thorchain_taproot_address_not_supported": "Thorchain 제공 업체는 Taproot 주소를 지원하지 않습니다. 주소를 변경하거나 다른 공급자를 선택하십시오.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "팁:",
|
"tip": "팁:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "နမူနာပုံစံ",
|
"template_name": "နမူနာပုံစံ",
|
||||||
"third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင် နေထိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့်ပိုက်ဆံအိတ်လိပ်စာကို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။",
|
"third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင် နေထိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့်ပိုက်ဆံအိတ်လိပ်စာကို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။",
|
||||||
"third_intro_title": "Yat သည် အခြားသူများနှင့် ကောင်းစွာကစားသည်။",
|
"third_intro_title": "Yat သည် အခြားသူများနှင့် ကောင်းစွာကစားသည်။",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain သည်စာချုပ်လိပ်စာသို့ပို့ခြင်းမပြုပါ",
|
||||||
"thorchain_taproot_address_not_supported": "Thorchain Provider သည် Taproot လိပ်စာများကိုမထောက်ခံပါ။ ကျေးဇူးပြု. လိပ်စာကိုပြောင်းပါသို့မဟုတ်အခြားပံ့ပိုးပေးသူကိုရွေးချယ်ပါ။",
|
"thorchain_taproot_address_not_supported": "Thorchain Provider သည် Taproot လိပ်စာများကိုမထောက်ခံပါ။ ကျေးဇူးပြု. လိပ်စာကိုပြောင်းပါသို့မဟုတ်အခြားပံ့ပိုးပေးသူကိုရွေးချယ်ပါ။",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "အကြံပြုချက်-",
|
"tip": "အကြံပြုချက်-",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "Sjabloonnaam",
|
"template_name": "Sjabloonnaam",
|
||||||
"third_intro_content": "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!",
|
"third_intro_content": "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!",
|
||||||
"third_intro_title": "Yat speelt leuk met anderen",
|
"third_intro_title": "Yat speelt leuk met anderen",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain ondersteunt het verzenden niet naar een contractadres",
|
||||||
"thorchain_taproot_address_not_supported": "De Thorchain -provider ondersteunt geen Taprooot -adressen. Wijzig het adres of selecteer een andere provider.",
|
"thorchain_taproot_address_not_supported": "De Thorchain -provider ondersteunt geen Taprooot -adressen. Wijzig het adres of selecteer een andere provider.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Tip:",
|
"tip": "Tip:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "Nazwa szablonu",
|
"template_name": "Nazwa szablonu",
|
||||||
"third_intro_content": "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!",
|
"third_intro_content": "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!",
|
||||||
"third_intro_title": "Yat ładnie bawi się z innymi",
|
"third_intro_title": "Yat ładnie bawi się z innymi",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain nie wspiera wysyłania na adres umowy",
|
||||||
"thorchain_taproot_address_not_supported": "Dostawca Thorchain nie obsługuje adresów TAPROOT. Zmień adres lub wybierz innego dostawcę.",
|
"thorchain_taproot_address_not_supported": "Dostawca Thorchain nie obsługuje adresów TAPROOT. Zmień adres lub wybierz innego dostawcę.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "wskazówka:",
|
"tip": "wskazówka:",
|
||||||
|
|
|
@ -669,6 +669,7 @@
|
||||||
"template_name": "Nome do modelo",
|
"template_name": "Nome do modelo",
|
||||||
"third_intro_content": "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!",
|
"third_intro_content": "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!",
|
||||||
"third_intro_title": "Yat joga bem com os outros",
|
"third_intro_title": "Yat joga bem com os outros",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain não suporta o envio para um endereço de contrato",
|
||||||
"thorchain_taproot_address_not_supported": "O provedor de Thorchain não suporta endereços de raiz de Tap. Altere o endereço ou selecione um provedor diferente.",
|
"thorchain_taproot_address_not_supported": "O provedor de Thorchain não suporta endereços de raiz de Tap. Altere o endereço ou selecione um provedor diferente.",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "Dica:",
|
"tip": "Dica:",
|
||||||
|
|
|
@ -668,6 +668,7 @@
|
||||||
"template_name": "Имя Шаблона",
|
"template_name": "Имя Шаблона",
|
||||||
"third_intro_content": "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!",
|
"third_intro_content": "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!",
|
||||||
"third_intro_title": "Yat хорошо взаимодействует с другими",
|
"third_intro_title": "Yat хорошо взаимодействует с другими",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain не поддерживает отправку на адрес контракта",
|
||||||
"thorchain_taproot_address_not_supported": "Поставщик Thorchain не поддерживает адреса taproot. Пожалуйста, измените адрес или выберите другого поставщика.",
|
"thorchain_taproot_address_not_supported": "Поставщик Thorchain не поддерживает адреса taproot. Пожалуйста, измените адрес или выберите другого поставщика.",
|
||||||
"time": "${minutes}мин ${seconds}сек",
|
"time": "${minutes}мин ${seconds}сек",
|
||||||
"tip": "Совет:",
|
"tip": "Совет:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "ชื่อแม่แบบ",
|
"template_name": "ชื่อแม่แบบ",
|
||||||
"third_intro_content": "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!",
|
"third_intro_content": "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!",
|
||||||
"third_intro_title": "Yat ปฏิบัติตนอย่างดีกับผู้อื่น",
|
"third_intro_title": "Yat ปฏิบัติตนอย่างดีกับผู้อื่น",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain ไม่สนับสนุนการส่งไปยังที่อยู่สัญญา",
|
||||||
"thorchain_taproot_address_not_supported": "ผู้ให้บริการ Thorchain ไม่รองรับที่อยู่ taproot โปรดเปลี่ยนที่อยู่หรือเลือกผู้ให้บริการอื่น",
|
"thorchain_taproot_address_not_supported": "ผู้ให้บริการ Thorchain ไม่รองรับที่อยู่ taproot โปรดเปลี่ยนที่อยู่หรือเลือกผู้ให้บริการอื่น",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "เพิ่มค่าตอบแทน:",
|
"tip": "เพิ่มค่าตอบแทน:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "Pangalan ng Template",
|
"template_name": "Pangalan ng Template",
|
||||||
"third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!",
|
"third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!",
|
||||||
"third_intro_title": "Si Yat ay mahusay na gumaganap sa iba",
|
"third_intro_title": "Si Yat ay mahusay na gumaganap sa iba",
|
||||||
|
"thorchain_contract_address_not_supported": "Hindi sinusuportahan ng Thorchain ang pagpapadala sa isang address ng kontrata",
|
||||||
"thorchain_taproot_address_not_supported": "Ang Tagabigay ng Thorchain ay hindi sumusuporta sa mga address ng taproot. Mangyaring baguhin ang address o pumili ng ibang provider.",
|
"thorchain_taproot_address_not_supported": "Ang Tagabigay ng Thorchain ay hindi sumusuporta sa mga address ng taproot. Mangyaring baguhin ang address o pumili ng ibang provider.",
|
||||||
"time": "${minutes} m ${seconds} s",
|
"time": "${minutes} m ${seconds} s",
|
||||||
"tip": "Tip:",
|
"tip": "Tip:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "şablon adı",
|
"template_name": "şablon adı",
|
||||||
"third_intro_content": "Yat'lar Cake Wallet'ın dışında da çalışabilir. Dünya üzerindeki herhangi bir cüzdan adresi Yat ile değiştirilebilir!",
|
"third_intro_content": "Yat'lar Cake Wallet'ın dışında da çalışabilir. Dünya üzerindeki herhangi bir cüzdan adresi Yat ile değiştirilebilir!",
|
||||||
"third_intro_title": "Yat diğerleriyle iyi çalışır",
|
"third_intro_title": "Yat diğerleriyle iyi çalışır",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain bir sözleşme adresine göndermeyi desteklemiyor",
|
||||||
"thorchain_taproot_address_not_supported": "Thorchain sağlayıcısı Taproot adreslerini desteklemiyor. Lütfen adresi değiştirin veya farklı bir sağlayıcı seçin.",
|
"thorchain_taproot_address_not_supported": "Thorchain sağlayıcısı Taproot adreslerini desteklemiyor. Lütfen adresi değiştirin veya farklı bir sağlayıcı seçin.",
|
||||||
"time": "${minutes}d ${seconds}s",
|
"time": "${minutes}d ${seconds}s",
|
||||||
"tip": "Bahşiş:",
|
"tip": "Bahşiş:",
|
||||||
|
|
|
@ -668,6 +668,7 @@
|
||||||
"template_name": "Назва шаблону",
|
"template_name": "Назва шаблону",
|
||||||
"third_intro_content": "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!",
|
"third_intro_content": "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!",
|
||||||
"third_intro_title": "Yat добре взаємодіє з іншими",
|
"third_intro_title": "Yat добре взаємодіє з іншими",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain не підтримує надсилання на адресу контракту",
|
||||||
"thorchain_taproot_address_not_supported": "Постачальник Thorchain не підтримує адреси Taproot. Будь ласка, змініть адресу або виберіть іншого постачальника.",
|
"thorchain_taproot_address_not_supported": "Постачальник Thorchain не підтримує адреси Taproot. Будь ласка, змініть адресу або виберіть іншого постачальника.",
|
||||||
"time": "${minutes}хв ${seconds}сек",
|
"time": "${minutes}хв ${seconds}сек",
|
||||||
"tip": "Порада:",
|
"tip": "Порада:",
|
||||||
|
|
|
@ -669,6 +669,7 @@
|
||||||
"template_name": "ٹیمپلیٹ کا نام",
|
"template_name": "ٹیمپلیٹ کا نام",
|
||||||
"third_intro_content": "Yats بھی Cake والیٹ سے باہر رہتے ہیں۔ زمین پر کسی بھی بٹوے کے پتے کو Yat سے تبدیل کیا جا سکتا ہے!",
|
"third_intro_content": "Yats بھی Cake والیٹ سے باہر رہتے ہیں۔ زمین پر کسی بھی بٹوے کے پتے کو Yat سے تبدیل کیا جا سکتا ہے!",
|
||||||
"third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح کھیلتا ہے۔",
|
"third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح کھیلتا ہے۔",
|
||||||
|
"thorchain_contract_address_not_supported": "تھورچین معاہدے کے پتے بھیجنے کی حمایت نہیں کرتا ہے",
|
||||||
"thorchain_taproot_address_not_supported": "تھورچین فراہم کنندہ ٹیپروٹ پتے کی حمایت نہیں کرتا ہے۔ براہ کرم پتہ تبدیل کریں یا ایک مختلف فراہم کنندہ کو منتخب کریں۔",
|
"thorchain_taproot_address_not_supported": "تھورچین فراہم کنندہ ٹیپروٹ پتے کی حمایت نہیں کرتا ہے۔ براہ کرم پتہ تبدیل کریں یا ایک مختلف فراہم کنندہ کو منتخب کریں۔",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "ٹپ:",
|
"tip": "ٹپ:",
|
||||||
|
|
|
@ -668,6 +668,7 @@
|
||||||
"template_name": "Orukọ Awoṣe",
|
"template_name": "Orukọ Awoṣe",
|
||||||
"third_intro_content": "A sì lè lo Yats níta Cake Wallet. A lè rọ́pò Àdírẹ́sì kankan àpamọ́wọ́ fún Yat!",
|
"third_intro_content": "A sì lè lo Yats níta Cake Wallet. A lè rọ́pò Àdírẹ́sì kankan àpamọ́wọ́ fún Yat!",
|
||||||
"third_intro_title": "Àlàáfíà ni Yat àti àwọn ìmíìn jọ wà",
|
"third_intro_title": "Àlàáfíà ni Yat àti àwọn ìmíìn jọ wà",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain ko ṣe atilẹyin fifiranṣẹ si adirẹsi adehun kan",
|
||||||
"thorchain_taproot_address_not_supported": "Olupese Trockchain ko ṣe atilẹyin awọn adirẹsi Taproot. Jọwọ yi adirẹsi pada tabi yan olupese ti o yatọ.",
|
"thorchain_taproot_address_not_supported": "Olupese Trockchain ko ṣe atilẹyin awọn adirẹsi Taproot. Jọwọ yi adirẹsi pada tabi yan olupese ti o yatọ.",
|
||||||
"time": "${minutes}ìṣj ${seconds}ìṣs",
|
"time": "${minutes}ìṣj ${seconds}ìṣs",
|
||||||
"tip": "Owó àfikún:",
|
"tip": "Owó àfikún:",
|
||||||
|
|
|
@ -667,6 +667,7 @@
|
||||||
"template_name": "模板名称",
|
"template_name": "模板名称",
|
||||||
"third_intro_content": "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!",
|
"third_intro_content": "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!",
|
||||||
"third_intro_title": "Yat 和別人玩得很好",
|
"third_intro_title": "Yat 和別人玩得很好",
|
||||||
|
"thorchain_contract_address_not_supported": "Thorchain不支持发送到合同地址",
|
||||||
"thorchain_taproot_address_not_supported": "Thorchain提供商不支持Taproot地址。请更改地址或选择其他提供商。",
|
"thorchain_taproot_address_not_supported": "Thorchain提供商不支持Taproot地址。请更改地址或选择其他提供商。",
|
||||||
"time": "${minutes}m ${seconds}s",
|
"time": "${minutes}m ${seconds}s",
|
||||||
"tip": "提示:",
|
"tip": "提示:",
|
||||||
|
|
|
@ -158,7 +158,8 @@ abstract class Bitcoin {
|
||||||
Future<bool> canReplaceByFee(Object wallet, String transactionHash);
|
Future<bool> canReplaceByFee(Object wallet, String transactionHash);
|
||||||
Future<bool> isChangeSufficientForFee(Object wallet, String txId, String newFee);
|
Future<bool> isChangeSufficientForFee(Object wallet, String txId, String newFee);
|
||||||
int getFeeAmountForPriority(Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, {int? size});
|
int getFeeAmountForPriority(Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, {int? size});
|
||||||
int getFeeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size});
|
int getEstimatedFeeWithFeeRate(Object wallet, int feeRate, int? amount, {int? outputsCount, int? size});
|
||||||
|
int getMaxCustomFeeRate(Object wallet);
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
@ -1057,7 +1058,8 @@ Future<void> generatePubspec(
|
||||||
final inputFile = File(pubspecOutputPath);
|
final inputFile = File(pubspecOutputPath);
|
||||||
final inputText = await inputFile.readAsString();
|
final inputText = await inputFile.readAsString();
|
||||||
final inputLines = inputText.split('\n');
|
final inputLines = inputText.split('\n');
|
||||||
final dependenciesIndex = inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:'));
|
final dependenciesIndex =
|
||||||
|
inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:'));
|
||||||
var output = cwCore;
|
var output = cwCore;
|
||||||
|
|
||||||
if (hasMonero) {
|
if (hasMonero) {
|
||||||
|
|
Loading…
Reference in a new issue