mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 20:39:51 +00:00
Merge branch 'main' into CW-519-add-tor-connection-feature-to-cake
This commit is contained in:
commit
152b458190
73 changed files with 2684 additions and 187 deletions
|
@ -266,6 +266,12 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
derivationPath: walletInfo.derivationInfo!.derivationPath!);
|
derivationPath: walletInfo.derivationInfo!.derivationPath!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close({bool shouldCleanup = false}) async {
|
||||||
|
payjoinManager.cleanupSessions();
|
||||||
|
super.close(shouldCleanup: shouldCleanup);
|
||||||
|
}
|
||||||
|
|
||||||
late final PayjoinManager payjoinManager;
|
late final PayjoinManager payjoinManager;
|
||||||
|
|
||||||
bool get isPayjoinAvailable => unspentCoinsInfo.values
|
bool get isPayjoinAvailable => unspentCoinsInfo.values
|
||||||
|
|
|
@ -59,19 +59,26 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
|
||||||
|
|
||||||
@action
|
@action
|
||||||
Future<void> initPayjoin() async {
|
Future<void> initPayjoin() async {
|
||||||
|
try {
|
||||||
await payjoinManager.initPayjoin();
|
await payjoinManager.initPayjoin();
|
||||||
currentPayjoinReceiver = await payjoinManager.initReceiver(primaryAddress);
|
currentPayjoinReceiver = await payjoinManager.getUnusedReceiver(primaryAddress);
|
||||||
payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint();
|
payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint();
|
||||||
|
|
||||||
payjoinManager.resumeSessions();
|
payjoinManager.resumeSessions();
|
||||||
|
} catch (e) {
|
||||||
|
printV(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
Future<void> newPayjoinReceiver() async {
|
Future<void> newPayjoinReceiver() async {
|
||||||
currentPayjoinReceiver = await payjoinManager.initReceiver(primaryAddress);
|
try {
|
||||||
|
currentPayjoinReceiver = await payjoinManager.getUnusedReceiver(primaryAddress);
|
||||||
payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint();
|
payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint();
|
||||||
|
|
||||||
printV("Initializing new Payjoin Receiver");
|
payjoinManager.spawnReceiver(receiver: currentPayjoinReceiver!);
|
||||||
payjoinManager.spawnNewReceiver(receiver: currentPayjoinReceiver!);
|
} catch (e) {
|
||||||
|
printV(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ class PayjoinManager {
|
||||||
}
|
}
|
||||||
final receiver = Receiver.fromJson(json: session.receiver!);
|
final receiver = Receiver.fromJson(json: session.receiver!);
|
||||||
printV("Resuming Payjoin Receiver Session ${receiver.id()}");
|
printV("Resuming Payjoin Receiver Session ${receiver.id()}");
|
||||||
return _spawnReceiver(receiver: receiver);
|
return spawnReceiver(receiver: receiver);
|
||||||
});
|
});
|
||||||
|
|
||||||
printV("Resumed ${spawnedSessions.length} Payjoin Sessions");
|
printV("Resumed ${spawnedSessions.length} Payjoin Sessions");
|
||||||
|
@ -121,15 +121,13 @@ class PayjoinManager {
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_cleanupSession(pjUri);
|
_cleanupSession(pjUri);
|
||||||
printV(e);
|
await _payjoinStorage.markSenderSessionUnrecoverable(pjUri, e.toString());
|
||||||
await _payjoinStorage.markSenderSessionUnrecoverable(pjUri);
|
completer.complete();
|
||||||
completer.completeError(e);
|
|
||||||
}
|
}
|
||||||
} else if (message is PayjoinSessionError) {
|
} else if (message is PayjoinSessionError) {
|
||||||
_cleanupSession(pjUri);
|
_cleanupSession(pjUri);
|
||||||
if (message is UnrecoverableError) {
|
if (message is UnrecoverableError) {
|
||||||
printV(message.message);
|
await _payjoinStorage.markSenderSessionUnrecoverable(pjUri, message.message);
|
||||||
await _payjoinStorage.markSenderSessionUnrecoverable(pjUri);
|
|
||||||
completer.complete();
|
completer.complete();
|
||||||
} else if (message is RecoverableError) {
|
} else if (message is RecoverableError) {
|
||||||
completer.complete();
|
completer.complete();
|
||||||
|
@ -149,9 +147,20 @@ class PayjoinManager {
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Receiver> initReceiver(String address,
|
Future<Receiver> getUnusedReceiver(String address,
|
||||||
[bool isTestnet = false]) async {
|
[bool isTestnet = false]) async {
|
||||||
try {
|
final session = _payjoinStorage.getUnusedActiveReceiverSession(_wallet.id);
|
||||||
|
|
||||||
|
if (session != null) {
|
||||||
|
await PayjoinUri.Url.fromStr(payjoinDirectoryUrl);
|
||||||
|
|
||||||
|
return Receiver.fromJson(json: session.receiver!);
|
||||||
|
}
|
||||||
|
|
||||||
|
return initReceiver(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Receiver> initReceiver(String address, [bool isTestnet = false]) async {
|
||||||
final ohttpKeys = await PayjoinUri.fetchOhttpKeys(
|
final ohttpKeys = await PayjoinUri.fetchOhttpKeys(
|
||||||
ohttpRelay: await randomOhttpRelayUrl(),
|
ohttpRelay: await randomOhttpRelayUrl(),
|
||||||
payjoinDirectory: payjoinDirectoryUrl,
|
payjoinDirectory: payjoinDirectoryUrl,
|
||||||
|
@ -165,26 +174,14 @@ class PayjoinManager {
|
||||||
);
|
);
|
||||||
final persister = PayjoinReceiverPersister.impl();
|
final persister = PayjoinReceiverPersister.impl();
|
||||||
final receiverToken = await newReceiver.persist(persister: persister);
|
final receiverToken = await newReceiver.persist(persister: persister);
|
||||||
final receiver =
|
final receiver = await Receiver.load(persister: persister, token: receiverToken);
|
||||||
await Receiver.load(persister: persister, token: receiverToken);
|
|
||||||
|
|
||||||
await _payjoinStorage.insertReceiverSession(receiver, _wallet.id);
|
await _payjoinStorage.insertReceiverSession(receiver, _wallet.id);
|
||||||
|
|
||||||
return receiver;
|
return receiver;
|
||||||
} catch (e) {
|
|
||||||
throw Exception('Error initializing Payjoin Receiver: $e');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> spawnNewReceiver({
|
Future<void> spawnReceiver({
|
||||||
required Receiver receiver,
|
|
||||||
bool isTestnet = false,
|
|
||||||
}) async {
|
|
||||||
await _payjoinStorage.insertReceiverSession(receiver, _wallet.id);
|
|
||||||
return _spawnReceiver(isTestnet: isTestnet, receiver: receiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _spawnReceiver({
|
|
||||||
required Receiver receiver,
|
required Receiver receiver,
|
||||||
bool isTestnet = false,
|
bool isTestnet = false,
|
||||||
}) async {
|
}) async {
|
||||||
|
@ -229,6 +226,10 @@ class PayjoinManager {
|
||||||
|
|
||||||
case PayjoinReceiverRequestTypes.getCandidateInputs:
|
case PayjoinReceiverRequestTypes.getCandidateInputs:
|
||||||
utxos = _wallet.getUtxoWithPrivateKeys();
|
utxos = _wallet.getUtxoWithPrivateKeys();
|
||||||
|
if (utxos.isEmpty) {
|
||||||
|
await _wallet.updateAllUnspents();
|
||||||
|
utxos = _wallet.getUtxoWithPrivateKeys();
|
||||||
|
}
|
||||||
mainToIsolateSendPort?.send({
|
mainToIsolateSendPort?.send({
|
||||||
'requestId': message['requestId'],
|
'requestId': message['requestId'],
|
||||||
'result': utxos,
|
'result': utxos,
|
||||||
|
|
|
@ -174,7 +174,7 @@ class PayjoinReceiverWorker {
|
||||||
final listUnspent =
|
final listUnspent =
|
||||||
await _sendRequest(PayjoinReceiverRequestTypes.getCandidateInputs);
|
await _sendRequest(PayjoinReceiverRequestTypes.getCandidateInputs);
|
||||||
final unspent = listUnspent as List<UtxoWithPrivateKey>;
|
final unspent = listUnspent as List<UtxoWithPrivateKey>;
|
||||||
if (unspent.isEmpty) throw Exception('No unspent outputs available');
|
if (unspent.isEmpty) throw RecoverableError('No unspent outputs available');
|
||||||
|
|
||||||
final selectedUtxo = await _inputPairFromUtxo(unspent[0]);
|
final selectedUtxo = await _inputPairFromUtxo(unspent[0]);
|
||||||
final pj6 = await pj5.contributeInputs(replacementInputs: [selectedUtxo]);
|
final pj6 = await pj5.contributeInputs(replacementInputs: [selectedUtxo]);
|
||||||
|
|
|
@ -23,6 +23,14 @@ class PayjoinStorage {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
PayjoinSession? getUnusedActiveReceiverSession(String walletId) =>
|
||||||
|
_payjoinSessionSources.values
|
||||||
|
.where((session) =>
|
||||||
|
session.walletId == walletId &&
|
||||||
|
session.status == PayjoinSessionStatus.created.name &&
|
||||||
|
!session.isSenderSession)
|
||||||
|
.firstOrNull;
|
||||||
|
|
||||||
Future<void> markReceiverSessionComplete(
|
Future<void> markReceiverSessionComplete(
|
||||||
String sessionId, String txId, String amount) async {
|
String sessionId, String txId, String amount) async {
|
||||||
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
|
final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
|
||||||
|
@ -76,10 +84,11 @@ class PayjoinStorage {
|
||||||
await session.save();
|
await session.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> markSenderSessionUnrecoverable(String pjUrl) async {
|
Future<void> markSenderSessionUnrecoverable(String pjUrl, String reason) async {
|
||||||
final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!;
|
final session = _payjoinSessionSources.get("$_senderPrefix$pjUrl")!;
|
||||||
|
|
||||||
session.status = PayjoinSessionStatus.unrecoverable.name;
|
session.status = PayjoinSessionStatus.unrecoverable.name;
|
||||||
|
session.error = reason;
|
||||||
await session.save();
|
await session.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
121
cw_ethereum/lib/deuro/deuro_savings.dart
Normal file
121
cw_ethereum/lib/deuro/deuro_savings.dart
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:crypto/crypto.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_ethereum/deuro/deuro_savings_contract.dart';
|
||||||
|
import 'package:cw_ethereum/ethereum_wallet.dart';
|
||||||
|
import 'package:cw_evm/contract/erc20.dart';
|
||||||
|
import 'package:cw_evm/evm_chain_transaction_priority.dart';
|
||||||
|
import 'package:cw_evm/pending_evm_chain_transaction.dart';
|
||||||
|
import 'package:web3dart/web3dart.dart';
|
||||||
|
|
||||||
|
const String savingsGatewayAddress =
|
||||||
|
"0x073493d73258C4BEb6542e8dd3e1b2891C972303";
|
||||||
|
|
||||||
|
const String dEuroAddress = "0xbA3f535bbCcCcA2A154b573Ca6c5A49BAAE0a3ea";
|
||||||
|
|
||||||
|
class DEuro {
|
||||||
|
final SavingsGateway _savingsGateway;
|
||||||
|
final ERC20 _dEuro;
|
||||||
|
final EthereumWallet _wallet;
|
||||||
|
|
||||||
|
DEuro(EthereumWallet wallet)
|
||||||
|
: _wallet = wallet,
|
||||||
|
_savingsGateway = _getSavingsGateway(wallet.getWeb3Client()!),
|
||||||
|
_dEuro = _getDEuroToken(wallet.getWeb3Client()!);
|
||||||
|
|
||||||
|
static SavingsGateway _getSavingsGateway(Web3Client client) => SavingsGateway(
|
||||||
|
address: EthereumAddress.fromHex(savingsGatewayAddress),
|
||||||
|
client: client,
|
||||||
|
);
|
||||||
|
|
||||||
|
static ERC20 _getDEuroToken(Web3Client client) => ERC20(
|
||||||
|
address: EthereumAddress.fromHex(dEuroAddress),
|
||||||
|
client: client,
|
||||||
|
);
|
||||||
|
|
||||||
|
final frontendCode =
|
||||||
|
Uint8List.fromList(sha256.convert(utf8.encode("wallet")).bytes);
|
||||||
|
|
||||||
|
EthereumAddress get _address =>
|
||||||
|
EthereumAddress.fromHex(_wallet.walletAddresses.primaryAddress);
|
||||||
|
|
||||||
|
Future<BigInt> get savingsBalance async =>
|
||||||
|
(await _savingsGateway.savings(accountOwner: _address)).saved;
|
||||||
|
|
||||||
|
Future<BigInt> get accruedInterest =>
|
||||||
|
_savingsGateway.accruedInterest(accountOwner: _address);
|
||||||
|
|
||||||
|
Future<BigInt> get interestRate => _savingsGateway.currentRatePPM();
|
||||||
|
|
||||||
|
Future<BigInt> get approvedBalance =>
|
||||||
|
_dEuro.allowance(_address, _savingsGateway.self.address);
|
||||||
|
|
||||||
|
Future<PendingEVMChainTransaction> depositSavings(
|
||||||
|
BigInt amount, EVMChainTransactionPriority priority) async {
|
||||||
|
final signedTransaction = await _savingsGateway.save(
|
||||||
|
(amount: amount, frontendCode: frontendCode),
|
||||||
|
credentials: _wallet.evmChainPrivateKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
final fee = await _wallet.calculateActualEstimatedFeeForCreateTransaction(
|
||||||
|
amount: amount,
|
||||||
|
contractAddress: _savingsGateway.self.address.hexEip55,
|
||||||
|
receivingAddressHex: _savingsGateway.self.address.hexEip55,
|
||||||
|
priority: priority,
|
||||||
|
data: _savingsGateway.self.abi.functions[17]
|
||||||
|
.encodeCall([amount, frontendCode]),
|
||||||
|
);
|
||||||
|
|
||||||
|
final sendTransaction =
|
||||||
|
() => _wallet.getWeb3Client()!.sendRawTransaction(signedTransaction);
|
||||||
|
|
||||||
|
return PendingEVMChainTransaction(
|
||||||
|
sendTransaction: sendTransaction,
|
||||||
|
signedTransaction: signedTransaction,
|
||||||
|
fee: BigInt.from(fee.estimatedGasFee),
|
||||||
|
amount: amount.toString(),
|
||||||
|
exponent: 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<PendingEVMChainTransaction> withdrawSavings(
|
||||||
|
BigInt amount, EVMChainTransactionPriority priority) async {
|
||||||
|
final signedTransaction = await _savingsGateway.withdraw(
|
||||||
|
(target: _address, amount: amount, frontendCode: frontendCode),
|
||||||
|
credentials: _wallet.evmChainPrivateKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
final fee = await _wallet.calculateActualEstimatedFeeForCreateTransaction(
|
||||||
|
amount: amount,
|
||||||
|
contractAddress: _savingsGateway.self.address.hexEip55,
|
||||||
|
receivingAddressHex: _savingsGateway.self.address.hexEip55,
|
||||||
|
priority: priority,
|
||||||
|
data: _savingsGateway.self.abi.functions[17]
|
||||||
|
.encodeCall([amount, frontendCode]),
|
||||||
|
);
|
||||||
|
|
||||||
|
final sendTransaction =
|
||||||
|
() => _wallet.getWeb3Client()!.sendRawTransaction(signedTransaction);
|
||||||
|
|
||||||
|
return PendingEVMChainTransaction(
|
||||||
|
sendTransaction: sendTransaction,
|
||||||
|
signedTransaction: signedTransaction,
|
||||||
|
fee: BigInt.from(fee.estimatedGasFee),
|
||||||
|
amount: amount.toString(),
|
||||||
|
exponent: 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set an infinite approval to save gas in the future
|
||||||
|
Future<PendingEVMChainTransaction> enableSavings(
|
||||||
|
EVMChainTransactionPriority priority) async =>
|
||||||
|
(await _wallet.createApprovalTransaction(
|
||||||
|
BigInt.parse(
|
||||||
|
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
|
||||||
|
radix: 16,
|
||||||
|
),
|
||||||
|
_savingsGateway.self.address.hexEip55,
|
||||||
|
CryptoCurrency.deuro,
|
||||||
|
priority,
|
||||||
|
)) as PendingEVMChainTransaction;
|
||||||
|
}
|
543
cw_ethereum/lib/deuro/deuro_savings_contract.dart
Normal file
543
cw_ethereum/lib/deuro/deuro_savings_contract.dart
Normal file
File diff suppressed because one or more lines are too long
|
@ -6,7 +6,7 @@ author: Cake Wallet
|
||||||
homepage: https://cakewallet.com
|
homepage: https://cakewallet.com
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.18.2 <3.0.0'
|
sdk: ^3.5.0
|
||||||
flutter: ">=1.17.0"
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
|
@ -101,6 +101,7 @@ abstract class EVMChainClient {
|
||||||
String? contractAddress,
|
String? contractAddress,
|
||||||
EtherAmount? gasPrice,
|
EtherAmount? gasPrice,
|
||||||
EtherAmount? maxFeePerGas,
|
EtherAmount? maxFeePerGas,
|
||||||
|
Uint8List? data,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
if (contractAddress == null) {
|
if (contractAddress == null) {
|
||||||
|
@ -124,7 +125,7 @@ abstract class EVMChainClient {
|
||||||
final gasEstimate = await _client!.estimateGas(
|
final gasEstimate = await _client!.estimateGas(
|
||||||
sender: senderAddress,
|
sender: senderAddress,
|
||||||
to: EthereumAddress.fromHex(contractAddress),
|
to: EthereumAddress.fromHex(contractAddress),
|
||||||
data: transfer.encodeCall([
|
data: data ?? transfer.encodeCall([
|
||||||
toAddress,
|
toAddress,
|
||||||
value.getInWei,
|
value.getInWei,
|
||||||
]),
|
]),
|
||||||
|
@ -137,6 +138,21 @@ abstract class EVMChainClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Uint8List getEncodedDataForApprovalTransaction({
|
||||||
|
required EthereumAddress toAddress,
|
||||||
|
required EtherAmount value,
|
||||||
|
required EthereumAddress contractAddress,
|
||||||
|
}) {
|
||||||
|
final contract = DeployedContract(ethereumContractAbi, contractAddress);
|
||||||
|
|
||||||
|
final approve = contract.function('approve');
|
||||||
|
|
||||||
|
return approve.encodeCall([
|
||||||
|
toAddress,
|
||||||
|
value.getInWei,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
Future<PendingEVMChainTransaction> signTransaction({
|
Future<PendingEVMChainTransaction> signTransaction({
|
||||||
required Credentials privateKey,
|
required Credentials privateKey,
|
||||||
required String toAddress,
|
required String toAddress,
|
||||||
|
@ -198,6 +214,50 @@ abstract class EVMChainClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<PendingEVMChainTransaction> signApprovalTransaction({
|
||||||
|
required Credentials privateKey,
|
||||||
|
required String spender,
|
||||||
|
required BigInt amount,
|
||||||
|
required BigInt gasFee,
|
||||||
|
required int estimatedGasUnits,
|
||||||
|
required int maxFeePerGas,
|
||||||
|
required EVMChainTransactionPriority priority,
|
||||||
|
required int exponent,
|
||||||
|
required String contractAddress,
|
||||||
|
}) async {
|
||||||
|
|
||||||
|
final Transaction transaction = createTransaction(
|
||||||
|
from: privateKey.address,
|
||||||
|
to: EthereumAddress.fromHex(contractAddress),
|
||||||
|
maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip),
|
||||||
|
amount: EtherAmount.zero(),
|
||||||
|
maxGas: estimatedGasUnits,
|
||||||
|
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
|
||||||
|
);
|
||||||
|
|
||||||
|
final erc20 = ERC20(
|
||||||
|
client: _client!,
|
||||||
|
address: EthereumAddress.fromHex(contractAddress),
|
||||||
|
chainId: chainId,
|
||||||
|
);
|
||||||
|
|
||||||
|
final signedTransaction = await erc20.approve(
|
||||||
|
EthereumAddress.fromHex(spender),
|
||||||
|
amount,
|
||||||
|
credentials: privateKey,
|
||||||
|
transaction: transaction,
|
||||||
|
);
|
||||||
|
|
||||||
|
return PendingEVMChainTransaction(
|
||||||
|
signedTransaction: prepareSignedTransactionForSending(signedTransaction),
|
||||||
|
amount: amount.toString(),
|
||||||
|
fee: gasFee,
|
||||||
|
sendTransaction: () => sendTransaction(signedTransaction),
|
||||||
|
exponent: exponent,
|
||||||
|
isInfiniteApproval: amount.toRadixString(16) == 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Transaction createTransaction({
|
Transaction createTransaction({
|
||||||
required EthereumAddress from,
|
required EthereumAddress from,
|
||||||
required EthereumAddress to,
|
required EthereumAddress to,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:bip32/bip32.dart' as bip32;
|
import 'package:bip32/bip32.dart' as bip32;
|
||||||
import 'package:bip39/bip39.dart' as bip39;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
|
@ -255,6 +256,7 @@ abstract class EVMChainWalletBase
|
||||||
required String? contractAddress,
|
required String? contractAddress,
|
||||||
required String receivingAddressHex,
|
required String receivingAddressHex,
|
||||||
required TransactionPriority priority,
|
required TransactionPriority priority,
|
||||||
|
Uint8List? data,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
if (priority is EVMChainTransactionPriority) {
|
if (priority is EVMChainTransactionPriority) {
|
||||||
|
@ -276,6 +278,7 @@ abstract class EVMChainWalletBase
|
||||||
gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice),
|
gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice),
|
||||||
toAddress: EthereumAddress.fromHex(receivingAddressHex),
|
toAddress: EthereumAddress.fromHex(receivingAddressHex),
|
||||||
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
|
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
|
||||||
|
data: data,
|
||||||
);
|
);
|
||||||
|
|
||||||
final totalGasFee = estimatedGas * maxFeePerGas;
|
final totalGasFee = estimatedGas * maxFeePerGas;
|
||||||
|
@ -478,6 +481,43 @@ abstract class EVMChainWalletBase
|
||||||
return pendingEVMChainTransaction;
|
return pendingEVMChainTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<PendingTransaction> createApprovalTransaction(
|
||||||
|
BigInt amount,
|
||||||
|
String spender,
|
||||||
|
CryptoCurrency token,
|
||||||
|
EVMChainTransactionPriority priority) async {
|
||||||
|
final CryptoCurrency transactionCurrency =
|
||||||
|
balance.keys.firstWhere((element) => element.title == token.title);
|
||||||
|
assert(transactionCurrency is Erc20Token);
|
||||||
|
|
||||||
|
final data = _client.getEncodedDataForApprovalTransaction(
|
||||||
|
contractAddress: EthereumAddress.fromHex(
|
||||||
|
(transactionCurrency as Erc20Token).contractAddress),
|
||||||
|
value: EtherAmount.fromBigInt(EtherUnit.wei, amount),
|
||||||
|
toAddress: EthereumAddress.fromHex(spender),
|
||||||
|
);
|
||||||
|
|
||||||
|
final gasFeesModel = await calculateActualEstimatedFeeForCreateTransaction(
|
||||||
|
amount: amount,
|
||||||
|
receivingAddressHex: spender,
|
||||||
|
priority: priority,
|
||||||
|
contractAddress: transactionCurrency.contractAddress,
|
||||||
|
data: data,
|
||||||
|
);
|
||||||
|
|
||||||
|
return _client.signApprovalTransaction(
|
||||||
|
privateKey: _evmChainPrivateKey,
|
||||||
|
spender: spender,
|
||||||
|
amount: amount,
|
||||||
|
priority: priority,
|
||||||
|
gasFee: BigInt.from(gasFeesModel.estimatedGasFee),
|
||||||
|
maxFeePerGas: gasFeesModel.maxFeePerGas,
|
||||||
|
estimatedGasUnits: gasFeesModel.estimatedGasUnits,
|
||||||
|
exponent: transactionCurrency.decimal,
|
||||||
|
contractAddress: transactionCurrency.contractAddress,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _updateTransactions() async {
|
Future<void> _updateTransactions() async {
|
||||||
try {
|
try {
|
||||||
if (_isTransactionUpdating) {
|
if (_isTransactionUpdating) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ class PendingEVMChainTransaction with PendingTransaction {
|
||||||
final BigInt fee;
|
final BigInt fee;
|
||||||
final String amount;
|
final String amount;
|
||||||
final int exponent;
|
final int exponent;
|
||||||
|
final bool isInfiniteApproval;
|
||||||
|
|
||||||
PendingEVMChainTransaction({
|
PendingEVMChainTransaction({
|
||||||
required this.sendTransaction,
|
required this.sendTransaction,
|
||||||
|
@ -18,10 +19,12 @@ class PendingEVMChainTransaction with PendingTransaction {
|
||||||
required this.fee,
|
required this.fee,
|
||||||
required this.amount,
|
required this.amount,
|
||||||
required this.exponent,
|
required this.exponent,
|
||||||
|
this.isInfiniteApproval = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get amountFormatted {
|
String get amountFormatted {
|
||||||
|
if (isInfiniteApproval) return "∞";
|
||||||
final _amount = (BigInt.parse(amount) / BigInt.from(pow(10, exponent))).toString();
|
final _amount = (BigInt.parse(amount) / BigInt.from(pow(10, exponent))).toString();
|
||||||
return _amount.substring(0, min(10, _amount.length));
|
return _amount.substring(0, min(10, _amount.length));
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/cake-tech/ledger-flutter-plus-plugins
|
url: https://github.com/cake-tech/ledger-flutter-plus-plugins
|
||||||
path: packages/ledger-ethereum
|
path: packages/ledger-ethereum
|
||||||
|
ref: f4761cd5171d4c1e2e42fd3298261650539fb2db
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
web3dart:
|
web3dart:
|
||||||
|
|
|
@ -38,9 +38,9 @@ class AddressValidator extends TextValidator {
|
||||||
'|[0-9a-zA-Z]{105}|addr1[0-9a-zA-Z]{98}';
|
'|[0-9a-zA-Z]{105}|addr1[0-9a-zA-Z]{98}';
|
||||||
case CryptoCurrency.btc:
|
case CryptoCurrency.btc:
|
||||||
pattern =
|
pattern =
|
||||||
'${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${RegExp(r'(bc|tb)1q[ac-hj-np-z02-9]{25,39}}').pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
|
'${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
|
||||||
case CryptoCurrency.ltc:
|
case CryptoCurrency.ltc:
|
||||||
pattern = '^${RegExp(r'ltc1q[ac-hj-np-z02-9]{25,39}').pattern}\$|^${MwebAddress.regex.pattern}\$';
|
pattern = '${P2wpkhAddress.regex.pattern}|${MwebAddress.regex.pattern}';
|
||||||
case CryptoCurrency.nano:
|
case CryptoCurrency.nano:
|
||||||
pattern = '[0-9a-zA-Z_]+';
|
pattern = '[0-9a-zA-Z_]+';
|
||||||
case CryptoCurrency.banano:
|
case CryptoCurrency.banano:
|
||||||
|
@ -335,10 +335,6 @@ class AddressValidator extends TextValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pattern != null) {
|
return pattern != null ? "($pattern)" : null;
|
||||||
return "$BEFORE_REGEX($pattern)$AFTER_REGEX";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,8 +73,11 @@ class WalletLoadingService {
|
||||||
return wallet;
|
return wallet;
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
await ExceptionHandler.resetLastPopupDate();
|
await ExceptionHandler.resetLastPopupDate();
|
||||||
|
final isLedgerError = await ExceptionHandler.isLedgerError(error);
|
||||||
|
if (isLedgerError) rethrow;
|
||||||
await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
||||||
|
|
||||||
|
|
||||||
// try fetching the seeds of the corrupted wallet to show it to the user
|
// try fetching the seeds of the corrupted wallet to show it to the user
|
||||||
String corruptedWalletsSeeds = "Corrupted wallets seeds (if retrievable, empty otherwise):";
|
String corruptedWalletsSeeds = "Corrupted wallets seeds (if retrievable, empty otherwise):";
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -36,6 +36,7 @@ import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart';
|
||||||
import 'package:cake_wallet/src/screens/dev/network_requests.dart';
|
import 'package:cake_wallet/src/screens/dev/network_requests.dart';
|
||||||
import 'package:cake_wallet/src/screens/dev/secure_preferences_page.dart';
|
import 'package:cake_wallet/src/screens/dev/secure_preferences_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/dev/shared_preferences_page.dart';
|
import 'package:cake_wallet/src/screens/dev/shared_preferences_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/integrations/deuro/savings_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/background_sync_page.dart';
|
import 'package:cake_wallet/src/screens/settings/background_sync_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/start_tor/start_tor_page.dart';
|
import 'package:cake_wallet/src/screens/start_tor/start_tor_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
|
import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
|
||||||
|
@ -45,6 +46,7 @@ import 'package:cake_wallet/themes/core/theme_store.dart';
|
||||||
import 'package:cake_wallet/view_model/dev/monero_background_sync.dart';
|
import 'package:cake_wallet/view_model/dev/monero_background_sync.dart';
|
||||||
import 'package:cake_wallet/view_model/dev/secure_preferences.dart';
|
import 'package:cake_wallet/view_model/dev/secure_preferences.dart';
|
||||||
import 'package:cake_wallet/view_model/dev/shared_preferences.dart';
|
import 'package:cake_wallet/view_model/dev/shared_preferences.dart';
|
||||||
|
import 'package:cake_wallet/view_model/integrations/deuro_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/link_view_model.dart';
|
import 'package:cake_wallet/view_model/link_view_model.dart';
|
||||||
import 'package:cake_wallet/tron/tron.dart';
|
import 'package:cake_wallet/tron/tron.dart';
|
||||||
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
|
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
|
||||||
|
@ -1516,5 +1518,9 @@ Future<void> setup({
|
||||||
|
|
||||||
getIt.registerFactory(() => StartTorPage(StartTorViewModel(),));
|
getIt.registerFactory(() => StartTorPage(StartTorViewModel(),));
|
||||||
|
|
||||||
|
getIt.registerFactory(() => DEuroViewModel(getIt<AppStore>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(() => DEuroSavingsPage(getIt<DEuroViewModel>()));
|
||||||
|
|
||||||
_isSetupFinished = true;
|
_isSetupFinished = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,13 +165,19 @@ class AddressResolver {
|
||||||
"zone"
|
"zone"
|
||||||
];
|
];
|
||||||
|
|
||||||
static String? extractAddressByType({required String raw, required CryptoCurrency type}) {
|
static String? extractAddressByType(
|
||||||
final addressPattern = AddressValidator.getAddressFromStringPattern(type);
|
{required String raw,
|
||||||
|
required CryptoCurrency type,
|
||||||
|
bool requireSurroundingWhitespaces = true}) {
|
||||||
|
var addressPattern = AddressValidator.getAddressFromStringPattern(type);
|
||||||
|
|
||||||
if (addressPattern == null) {
|
if (addressPattern == null) {
|
||||||
throw Exception('Unexpected token: $type for getAddressFromStringPattern');
|
throw Exception('Unexpected token: $type for getAddressFromStringPattern');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requireSurroundingWhitespaces)
|
||||||
|
addressPattern = "$BEFORE_REGEX$addressPattern$AFTER_REGEX";
|
||||||
|
|
||||||
final match = RegExp(addressPattern, multiLine: true).firstMatch(raw);
|
final match = RegExp(addressPattern, multiLine: true).firstMatch(raw);
|
||||||
return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_|ban_'),
|
return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_|ban_'),
|
||||||
(Match match) {
|
(Match match) {
|
||||||
|
|
|
@ -67,8 +67,7 @@ class CWEthereum extends Ethereum {
|
||||||
@override
|
@override
|
||||||
String getPublicKey(WalletBase wallet) {
|
String getPublicKey(WalletBase wallet) {
|
||||||
final privateKeyInUnitInt = (wallet as EthereumWallet).evmChainPrivateKey;
|
final privateKeyInUnitInt = (wallet as EthereumWallet).evmChainPrivateKey;
|
||||||
final publicKey = privateKeyInUnitInt.address.hex;
|
return privateKeyInUnitInt.address.hex;
|
||||||
return publicKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -138,29 +137,24 @@ class CWEthereum extends Ethereum {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Erc20Token> getERC20Currencies(WalletBase wallet) {
|
List<Erc20Token> getERC20Currencies(WalletBase wallet) =>
|
||||||
final ethereumWallet = wallet as EthereumWallet;
|
(wallet as EthereumWallet).erc20Currencies;
|
||||||
return ethereumWallet.erc20Currencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) async {
|
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) =>
|
||||||
await (wallet as EthereumWallet).addErc20Token(token as Erc20Token);
|
(wallet as EthereumWallet).addErc20Token(token as Erc20Token);
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) async =>
|
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) =>
|
||||||
await (wallet as EthereumWallet).deleteErc20Token(token as Erc20Token);
|
(wallet as EthereumWallet).deleteErc20Token(token as Erc20Token);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) async =>
|
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) =>
|
||||||
await (wallet as EthereumWallet).removeTokenTransactionsInHistory(token as Erc20Token);
|
(wallet as EthereumWallet).removeTokenTransactionsInHistory(token as Erc20Token);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
|
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) =>
|
||||||
final ethereumWallet = wallet as EthereumWallet;
|
(wallet as EthereumWallet).getErc20Token(contractAddress, 'eth');
|
||||||
return await ethereumWallet.getErc20Token(contractAddress, 'eth');
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
|
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
|
||||||
|
@ -177,23 +171,19 @@ class CWEthereum extends Ethereum {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void updateEtherscanUsageState(WalletBase wallet, bool isEnabled) {
|
void updateEtherscanUsageState(WalletBase wallet, bool isEnabled) =>
|
||||||
(wallet as EthereumWallet).updateScanProviderUsageState(isEnabled);
|
(wallet as EthereumWallet).updateScanProviderUsageState(isEnabled);
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Web3Client? getWeb3Client(WalletBase wallet) {
|
Web3Client? getWeb3Client(WalletBase wallet) => (wallet as EthereumWallet).getWeb3Client();
|
||||||
return (wallet as EthereumWallet).getWeb3Client();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@override
|
||||||
String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
|
String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void setLedgerConnection(
|
void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection) {
|
||||||
WalletBase wallet, ledger.LedgerConnection connection) {
|
|
||||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials)
|
((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials)
|
||||||
.setLedgerConnection(
|
.setLedgerConnection(connection, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||||
connection, wallet.walletInfo.derivationInfo?.derivationPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -209,7 +199,44 @@ class CWEthereum extends Ethereum {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> getDefaultTokenContractAddresses() {
|
List<String> getDefaultTokenContractAddresses() =>
|
||||||
return DefaultEthereumErc20Tokens().initialErc20Tokens.map((e) => e.contractAddress).toList();
|
DefaultEthereumErc20Tokens().initialErc20Tokens.map((e) => e.contractAddress).toList();
|
||||||
}
|
|
||||||
|
Future<PendingTransaction> createTokenApproval(WalletBase wallet, BigInt amount, String spender,
|
||||||
|
CryptoCurrency token, TransactionPriority priority) =>
|
||||||
|
(wallet as EVMChainWallet).createApprovalTransaction(
|
||||||
|
amount, spender, token, priority as EVMChainTransactionPriority);
|
||||||
|
|
||||||
|
// Integrations
|
||||||
|
@override
|
||||||
|
Future<BigInt> getDEuroSavingsBalance(WalletBase wallet) =>
|
||||||
|
DEuro(wallet as EthereumWallet).savingsBalance;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<BigInt> getDEuroAccruedInterest(WalletBase wallet) =>
|
||||||
|
DEuro(wallet as EthereumWallet).accruedInterest;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<BigInt> getDEuroInterestRate(WalletBase wallet) =>
|
||||||
|
DEuro(wallet as EthereumWallet).interestRate;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<BigInt> getDEuroSavingsApproved(WalletBase wallet) =>
|
||||||
|
DEuro(wallet as EthereumWallet).approvedBalance;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<PendingTransaction> addDEuroSaving(
|
||||||
|
WalletBase wallet, BigInt amount, TransactionPriority priority) =>
|
||||||
|
DEuro(wallet as EthereumWallet)
|
||||||
|
.depositSavings(amount, priority as EVMChainTransactionPriority);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<PendingTransaction> removeDEuroSaving(
|
||||||
|
WalletBase wallet, BigInt amount, TransactionPriority priority) =>
|
||||||
|
DEuro(wallet as EthereumWallet)
|
||||||
|
.withdrawSavings(amount, priority as EVMChainTransactionPriority);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<PendingTransaction> enableDEuroSaving(WalletBase wallet, TransactionPriority priority) =>
|
||||||
|
DEuro(wallet as EthereumWallet).enableSavings(priority as EVMChainTransactionPriority);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,8 +67,7 @@ class CWPolygon extends Polygon {
|
||||||
@override
|
@override
|
||||||
String getPublicKey(WalletBase wallet) {
|
String getPublicKey(WalletBase wallet) {
|
||||||
final privateKeyInUnitInt = (wallet as PolygonWallet).evmChainPrivateKey;
|
final privateKeyInUnitInt = (wallet as PolygonWallet).evmChainPrivateKey;
|
||||||
final publicKey = privateKeyInUnitInt.address.hex;
|
return privateKeyInUnitInt.address.hex;
|
||||||
return publicKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -137,28 +136,27 @@ class CWPolygon extends Polygon {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Erc20Token> getERC20Currencies(WalletBase wallet) {
|
List<Erc20Token> getERC20Currencies(WalletBase wallet) =>
|
||||||
final polygonWallet = wallet as PolygonWallet;
|
(wallet as PolygonWallet).erc20Currencies;
|
||||||
return polygonWallet.erc20Currencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) async =>
|
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) =>
|
||||||
await (wallet as PolygonWallet).addErc20Token(token as Erc20Token);
|
(wallet as PolygonWallet).addErc20Token(token as Erc20Token);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) async =>
|
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) =>
|
||||||
await (wallet as PolygonWallet).deleteErc20Token(token as Erc20Token);
|
(wallet as PolygonWallet).deleteErc20Token(token as Erc20Token);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) async =>
|
Future<void> removeTokenTransactionsInHistory(
|
||||||
await (wallet as PolygonWallet).removeTokenTransactionsInHistory(token as Erc20Token);
|
WalletBase wallet, CryptoCurrency token) =>
|
||||||
|
(wallet as PolygonWallet)
|
||||||
|
.removeTokenTransactionsInHistory(token as Erc20Token);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
|
Future<Erc20Token?> getErc20Token(
|
||||||
final polygonWallet = wallet as PolygonWallet;
|
WalletBase wallet, String contractAddress) =>
|
||||||
return await polygonWallet.getErc20Token(contractAddress, 'polygon');
|
(wallet as PolygonWallet).getErc20Token(contractAddress, 'polygon');
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
|
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
|
||||||
|
@ -176,16 +174,22 @@ class CWPolygon extends Polygon {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled) {
|
void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled) =>
|
||||||
(wallet as PolygonWallet).updateScanProviderUsageState(isEnabled);
|
(wallet as PolygonWallet).updateScanProviderUsageState(isEnabled);
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Web3Client? getWeb3Client(WalletBase wallet) {
|
Web3Client? getWeb3Client(WalletBase wallet) =>
|
||||||
return (wallet as PolygonWallet).getWeb3Client();
|
(wallet as PolygonWallet).getWeb3Client();
|
||||||
}
|
|
||||||
|
|
||||||
String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
|
@override
|
||||||
|
String getTokenAddress(CryptoCurrency asset) =>
|
||||||
|
(asset as Erc20Token).contractAddress;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<PendingTransaction> createTokenApproval(WalletBase wallet,
|
||||||
|
BigInt amount, String spender, CryptoCurrency token, TransactionPriority priority) =>
|
||||||
|
(wallet as EVMChainWallet)
|
||||||
|
.createApprovalTransaction(amount, spender, token, priority as EVMChainTransactionPriority);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void setLedgerConnection(
|
void setLedgerConnection(
|
||||||
|
@ -208,7 +212,8 @@ class CWPolygon extends Polygon {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> getDefaultTokenContractAddresses() {
|
List<String> getDefaultTokenContractAddresses() => DefaultPolygonErc20Tokens()
|
||||||
return DefaultPolygonErc20Tokens().initialPolygonErc20Tokens.map((e) => e.contractAddress).toList();
|
.initialPolygonErc20Tokens
|
||||||
}
|
.map((e) => e.contractAddress)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
|
import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
|
import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||||
import 'package:cake_wallet/store/authentication_store.dart';
|
import 'package:cake_wallet/store/authentication_store.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||||
|
@ -63,14 +64,49 @@ void startAuthenticationStateChange(
|
||||||
monero!.setGlobalLedgerConnection(ledgerVM.connection);
|
monero!.setGlobalLedgerConnection(ledgerVM.connection);
|
||||||
showPopUp<void>(
|
showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) => AlertWithOneAction(
|
builder: (context) => AlertWithOneAction(
|
||||||
alertTitle: S.of(context).proceed_on_device,
|
alertTitle: S.of(context).proceed_on_device,
|
||||||
alertContent: S.of(context).proceed_on_device_description,
|
alertContent: S.of(context).proceed_on_device_description,
|
||||||
buttonText: S.of(context).cancel,
|
buttonText: S.of(context).cancel,
|
||||||
alertBarrierDismissible: false,
|
alertBarrierDismissible: false,
|
||||||
buttonAction: () => Navigator.of(context).pop()),
|
buttonAction: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
bool tryOpening = true;
|
||||||
|
while (tryOpening) {
|
||||||
|
try {
|
||||||
await loadCurrentWallet();
|
await loadCurrentWallet();
|
||||||
|
tryOpening = false;
|
||||||
|
} on Exception catch (e) {
|
||||||
|
final errorCode = RegExp(r'0x\S*?(?= )').firstMatch(
|
||||||
|
e.toString());
|
||||||
|
|
||||||
|
final errorMessage = ledgerVM.interpretErrorCode(
|
||||||
|
errorCode?.group(0).toString().replaceAll("0x", "") ??
|
||||||
|
"");
|
||||||
|
if (errorMessage != null) {
|
||||||
|
await showPopUp<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertWithTwoActions(
|
||||||
|
alertTitle: "Ledger Error",
|
||||||
|
alertContent: errorMessage,
|
||||||
|
leftButtonText: S.of(context).try_again,
|
||||||
|
alertBarrierDismissible: false,
|
||||||
|
actionLeftButton: () => Navigator.of(context).pop(),
|
||||||
|
rightButtonText: S.of(context).cancel,
|
||||||
|
actionRightButton: () {
|
||||||
|
tryOpening = false;
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
tryOpening = false;
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getIt.get<BottomSheetService>().showNext();
|
getIt.get<BottomSheetService>().showNext();
|
||||||
await navigatorKey.currentState!
|
await navigatorKey.currentState!
|
||||||
.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
|
.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
|
||||||
|
|
|
@ -66,7 +66,7 @@ void startCurrentWalletChangeReaction(
|
||||||
|
|
||||||
final node = settingsStore.getCurrentNode(wallet.type);
|
final node = settingsStore.getCurrentNode(wallet.type);
|
||||||
|
|
||||||
startWalletSyncStatusChangeReaction(wallet, fiatConversionStore);
|
startWalletSyncStatusChangeReaction(wallet, settingsStore);
|
||||||
startCheckConnectionReaction(wallet, settingsStore);
|
startCheckConnectionReaction(wallet, settingsStore);
|
||||||
|
|
||||||
await Future.delayed(Duration.zero);
|
await Future.delayed(Duration.zero);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cw_core/transaction_history.dart';
|
import 'package:cw_core/transaction_history.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
|
@ -12,7 +14,7 @@ ReactionDisposer? _onWalletSyncStatusChangeReaction;
|
||||||
|
|
||||||
void startWalletSyncStatusChangeReaction(
|
void startWalletSyncStatusChangeReaction(
|
||||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet,
|
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet,
|
||||||
FiatConversionStore fiatConversionStore) {
|
SettingsStore settingsStore) {
|
||||||
_onWalletSyncStatusChangeReaction?.reaction.dispose();
|
_onWalletSyncStatusChangeReaction?.reaction.dispose();
|
||||||
_onWalletSyncStatusChangeReaction = reaction((_) => wallet.syncStatus, (SyncStatus status) async {
|
_onWalletSyncStatusChangeReaction = reaction((_) => wallet.syncStatus, (SyncStatus status) async {
|
||||||
try {
|
try {
|
||||||
|
@ -25,6 +27,12 @@ void startWalletSyncStatusChangeReaction(
|
||||||
if (status is SyncedSyncStatus || status is FailedSyncStatus) {
|
if (status is SyncedSyncStatus || status is FailedSyncStatus) {
|
||||||
await WakelockPlus.disable();
|
await WakelockPlus.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status is SyncedSyncStatus &&
|
||||||
|
wallet.type == WalletType.bitcoin &&
|
||||||
|
settingsStore.usePayjoin) {
|
||||||
|
bitcoin!.resumePayjoinSessions(wallet);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
printV(e.toString());
|
printV(e.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dar
|
||||||
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_external_send_page.dart';
|
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_external_send_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
|
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/faq/faq_page.dart';
|
import 'package:cake_wallet/src/screens/faq/faq_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/integrations/deuro/savings_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart';
|
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart';
|
import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart';
|
import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart';
|
||||||
|
@ -928,6 +929,11 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
builder: (_) => getIt.get<StartTorPage>(),
|
builder: (_) => getIt.get<StartTorPage>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case Routes.dEuroSavings:
|
||||||
|
return MaterialPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<DEuroSavingsPage>(),
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
builder: (_) => Scaffold(
|
builder: (_) => Scaffold(
|
||||||
|
|
|
@ -129,4 +129,6 @@ class Routes {
|
||||||
static const walletGroupExistingSeedDescriptionPage = '/wallet_group_existing_seed_description_page';
|
static const walletGroupExistingSeedDescriptionPage = '/wallet_group_existing_seed_description_page';
|
||||||
static const walletSeedVerificationPage = '/wallet_seed_verification_page';
|
static const walletSeedVerificationPage = '/wallet_seed_verification_page';
|
||||||
static const exchangeTradeExternalSendPage = '/exchange_trade_external_send_page';
|
static const exchangeTradeExternalSendPage = '/exchange_trade_external_send_page';
|
||||||
|
|
||||||
|
static const dEuroSavings = '/integration/dEuro/savings';
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,8 +165,9 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _connectToDevice(LedgerDevice device) async {
|
Future<void> _connectToDevice(LedgerDevice device) async {
|
||||||
|
final isConnected =
|
||||||
await widget.ledgerVM.connectLedger(device, widget.walletType);
|
await widget.ledgerVM.connectLedger(device, widget.walletType);
|
||||||
widget.onConnectDevice(context, widget.ledgerVM);
|
if (isConnected) widget.onConnectDevice(context, widget.ledgerVM);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getDeviceTileLeading(LedgerDeviceType deviceInfo) {
|
String _getDeviceTileLeading(LedgerDeviceType deviceInfo) {
|
||||||
|
|
|
@ -5,15 +5,16 @@ import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart';
|
import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart';
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/cake_features_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/cake_features_view_model.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class CakeFeaturesPage extends StatelessWidget {
|
class CakeFeaturesPage extends StatelessWidget {
|
||||||
CakeFeaturesPage({required this.dashboardViewModel, required this.cakeFeaturesViewModel});
|
CakeFeaturesPage(
|
||||||
|
{required this.dashboardViewModel, required this.cakeFeaturesViewModel});
|
||||||
|
|
||||||
final DashboardViewModel dashboardViewModel;
|
final DashboardViewModel dashboardViewModel;
|
||||||
final CakeFeaturesViewModel cakeFeaturesViewModel;
|
final CakeFeaturesViewModel cakeFeaturesViewModel;
|
||||||
|
@ -58,6 +59,23 @@ class CakeFeaturesPage extends StatelessWidget {
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (dashboardViewModel.type == WalletType.ethereum) ...[
|
||||||
|
DashBoardRoundedCardWidget(
|
||||||
|
isDarkTheme: dashboardViewModel.isDarkTheme,
|
||||||
|
shadowBlur: dashboardViewModel.getShadowBlur(),
|
||||||
|
shadowSpread: dashboardViewModel.getShadowSpread(),
|
||||||
|
onTap: () =>
|
||||||
|
Navigator.of(context).pushNamed(Routes.dEuroSavings),
|
||||||
|
title: S.of(context).deuro_savings,
|
||||||
|
subTitle: S.of(context).deuro_savings_subtitle,
|
||||||
|
image: Image.asset(
|
||||||
|
'assets/images/deuro_icon.png',
|
||||||
|
height: 80,
|
||||||
|
width: 80,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
DashBoardRoundedCardWidget(
|
DashBoardRoundedCardWidget(
|
||||||
isDarkTheme: dashboardViewModel.isDarkTheme,
|
isDarkTheme: dashboardViewModel.isDarkTheme,
|
||||||
shadowBlur: dashboardViewModel.getShadowBlur(),
|
shadowBlur: dashboardViewModel.getShadowBlur(),
|
||||||
|
|
197
lib/src/screens/integrations/deuro/savings_page.dart
Normal file
197
lib/src/screens/integrations/deuro/savings_page.dart
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
import 'package:cake_wallet/core/execution_state.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/integrations/deuro/widgets/interest_card_widget.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/integrations/deuro/widgets/savings_card_widget.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/integrations/deuro/widgets/savings_edit_sheet.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/gradient_background.dart';
|
||||||
|
import 'package:cake_wallet/view_model/integrations/deuro_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
|
class DEuroSavingsPage extends BasePage {
|
||||||
|
final DEuroViewModel _dEuroViewModel;
|
||||||
|
|
||||||
|
DEuroSavingsPage(this._dEuroViewModel);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get gradientBackground => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget Function(BuildContext, Widget) get rootWrapper =>
|
||||||
|
(context, scaffold) => GradientBackground(scaffold: scaffold);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => S.current.deuro_savings;
|
||||||
|
|
||||||
|
Widget trailing(BuildContext context) => MergeSemantics(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 37,
|
||||||
|
width: 37,
|
||||||
|
child: ButtonTheme(
|
||||||
|
minWidth: double.minPositive,
|
||||||
|
child: Semantics(
|
||||||
|
label: "Refresh",
|
||||||
|
child: TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
foregroundColor: Theme.of(context).colorScheme.onSurface,
|
||||||
|
overlayColor: WidgetStateColor.resolveWith(
|
||||||
|
(states) => Colors.transparent),
|
||||||
|
),
|
||||||
|
onPressed: _dEuroViewModel.reloadSavingsUserData,
|
||||||
|
child: Icon(
|
||||||
|
Icons.refresh,
|
||||||
|
color: pageIconColor(context),
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget body(BuildContext context) {
|
||||||
|
WidgetsBinding.instance
|
||||||
|
.addPostFrameCallback((_) => _setReactions(context, _dEuroViewModel));
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
width: double.infinity,
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Observer(
|
||||||
|
builder: (_) => SavingsCard(
|
||||||
|
isDarkTheme: currentTheme.isDark,
|
||||||
|
interestRate: "${_dEuroViewModel.interestRate}%",
|
||||||
|
savingsBalance: _dEuroViewModel.savingsBalance,
|
||||||
|
currency: CryptoCurrency.deuro,
|
||||||
|
onAddSavingsPressed: () => _onSavingsAdd(context),
|
||||||
|
onRemoveSavingsPressed: () => _onSavingsRemove(context),
|
||||||
|
onApproveSavingsPressed: _dEuroViewModel.prepareApproval,
|
||||||
|
isEnabled: _dEuroViewModel.isEnabled,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Observer(
|
||||||
|
builder: (_) => InterestCardWidget(
|
||||||
|
isDarkTheme: currentTheme.isDark,
|
||||||
|
title: S.of(context).deuro_savings_collect_interest,
|
||||||
|
collectedInterest: _dEuroViewModel.accruedInterest,
|
||||||
|
onCollectInterest: _dEuroViewModel.prepareCollectInterest,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onSavingsAdd(BuildContext context) async {
|
||||||
|
final amount = await Navigator.of(context).push(MaterialPageRoute<String>(
|
||||||
|
builder: (BuildContext context) => SavingEditPage(isAdding: true)));
|
||||||
|
if (amount != null) _dEuroViewModel.prepareSavingsEdit(amount, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onSavingsRemove(BuildContext context) async {
|
||||||
|
final amount = await Navigator.of(context).push(MaterialPageRoute<String>(
|
||||||
|
builder: (BuildContext context) => SavingEditPage(isAdding: false)));
|
||||||
|
if (amount != null) _dEuroViewModel.prepareSavingsEdit(amount, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _isReactionsSet = false;
|
||||||
|
|
||||||
|
void _setReactions(BuildContext context, DEuroViewModel dEuroViewModel) {
|
||||||
|
if (_isReactionsSet) return;
|
||||||
|
|
||||||
|
reaction((_) => dEuroViewModel.transaction, (PendingTransaction? tx) async {
|
||||||
|
if (tx == null) return;
|
||||||
|
final result = await showModalBottomSheet<bool>(
|
||||||
|
context: context,
|
||||||
|
isDismissible: false,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (BuildContext bottomSheetContext) => ConfirmSendingBottomSheet(
|
||||||
|
key: ValueKey('savings_page_confirm_sending_dialog_key'),
|
||||||
|
titleText: S.of(bottomSheetContext).confirm_transaction,
|
||||||
|
currentTheme: currentTheme,
|
||||||
|
walletType: WalletType.ethereum,
|
||||||
|
titleIconPath: CryptoCurrency.deuro.iconPath,
|
||||||
|
currency: CryptoCurrency.deuro,
|
||||||
|
amount: S.of(bottomSheetContext).send_amount,
|
||||||
|
amountValue: tx.amountFormatted,
|
||||||
|
fiatAmountValue: "",
|
||||||
|
fee: S.of(bottomSheetContext).send_estimated_fee,
|
||||||
|
feeValue: tx.feeFormatted,
|
||||||
|
feeFiatAmount: "",
|
||||||
|
outputs: [],
|
||||||
|
onSlideComplete: () async {
|
||||||
|
Navigator.of(bottomSheetContext).pop(true);
|
||||||
|
dEuroViewModel.commitTransaction();
|
||||||
|
},
|
||||||
|
change: tx.change,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == null) dEuroViewModel.dismissTransaction();
|
||||||
|
});
|
||||||
|
|
||||||
|
reaction((_) => dEuroViewModel.approvalTransaction, (PendingTransaction? tx) async {
|
||||||
|
if (tx == null) return;
|
||||||
|
final result = await showModalBottomSheet<bool>(
|
||||||
|
context: context,
|
||||||
|
isDismissible: false,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (BuildContext bottomSheetContext) => ConfirmSendingBottomSheet(
|
||||||
|
key: ValueKey('savings_page_confirm_approval_dialog_key'),
|
||||||
|
titleText: S.of(bottomSheetContext).approve_tokens,
|
||||||
|
currentTheme: currentTheme,
|
||||||
|
walletType: WalletType.ethereum,
|
||||||
|
titleIconPath: CryptoCurrency.deuro.iconPath,
|
||||||
|
currency: CryptoCurrency.deuro,
|
||||||
|
amount: S.of(bottomSheetContext).send_amount,
|
||||||
|
amountValue: tx.amountFormatted,
|
||||||
|
fiatAmountValue: "",
|
||||||
|
fee: S.of(bottomSheetContext).send_estimated_fee,
|
||||||
|
feeValue: tx.feeFormatted,
|
||||||
|
feeFiatAmount: "",
|
||||||
|
outputs: [],
|
||||||
|
onSlideComplete: () {
|
||||||
|
Navigator.of(bottomSheetContext).pop(true);
|
||||||
|
dEuroViewModel.commitApprovalTransaction();
|
||||||
|
},
|
||||||
|
change: tx.change,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == null) dEuroViewModel.dismissTransaction();
|
||||||
|
});
|
||||||
|
|
||||||
|
reaction((_) => dEuroViewModel.state, (ExecutionState state) async {
|
||||||
|
if (state is TransactionCommitted) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
await showModalBottomSheet<void>(
|
||||||
|
context: context,
|
||||||
|
isDismissible: false,
|
||||||
|
builder: (BuildContext bottomSheetContext) => InfoBottomSheet(
|
||||||
|
currentTheme: currentTheme,
|
||||||
|
titleText: S.of(bottomSheetContext).transaction_sent,
|
||||||
|
contentImage: 'assets/images/birthday_cake.png',
|
||||||
|
content: S.of(bottomSheetContext).deuro_tx_commited_content,
|
||||||
|
actionButtonText: S.of(bottomSheetContext).close,
|
||||||
|
actionButtonKey: ValueKey('send_page_sent_dialog_ok_button_key'),
|
||||||
|
actionButton: () => Navigator.of(bottomSheetContext).pop(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_isReactionsSet = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/integrations/deuro/widgets/savings_card_widget.dart';
|
||||||
|
import 'package:cake_wallet/themes/utils/custom_theme_colors.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class InterestCardWidget extends StatelessWidget {
|
||||||
|
InterestCardWidget({
|
||||||
|
required this.title,
|
||||||
|
required this.collectedInterest,
|
||||||
|
super.key,
|
||||||
|
required this.isDarkTheme,
|
||||||
|
required this.onCollectInterest,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final String collectedInterest;
|
||||||
|
final bool isDarkTheme;
|
||||||
|
final VoidCallback onCollectInterest;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(children: [
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
width: double.infinity,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
isDarkTheme
|
||||||
|
? CustomThemeColors.cardGradientColorPrimaryDark
|
||||||
|
: CustomThemeColors.cardGradientColorPrimaryLight,
|
||||||
|
isDarkTheme
|
||||||
|
? CustomThemeColors.cardGradientColorSecondaryDark
|
||||||
|
: CustomThemeColors.cardGradientColorSecondaryLight,
|
||||||
|
],
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SavingsCard.getAssetBalanceRow(
|
||||||
|
context,
|
||||||
|
title: title,
|
||||||
|
subtitle: collectedInterest,
|
||||||
|
currency: CryptoCurrency.deuro,
|
||||||
|
hideSymbol: true,
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
SavingsCard.getButton(
|
||||||
|
context,
|
||||||
|
label: S.of(context).deuro_collect_interest,
|
||||||
|
onPressed: onCollectInterest,
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
107
lib/src/screens/integrations/deuro/widgets/numpad.dart
Normal file
107
lib/src/screens/integrations/deuro/widgets/numpad.dart
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
class NumberPad extends StatelessWidget {
|
||||||
|
final VoidCallback? onDecimalPressed;
|
||||||
|
final VoidCallback onDeletePressed;
|
||||||
|
final void Function(int index) onNumberPressed;
|
||||||
|
final FocusNode focusNode;
|
||||||
|
|
||||||
|
const NumberPad({
|
||||||
|
super.key,
|
||||||
|
required this.onNumberPressed,
|
||||||
|
required this.onDeletePressed,
|
||||||
|
required this.focusNode,
|
||||||
|
this.onDecimalPressed,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => KeyboardListener(
|
||||||
|
focusNode: focusNode,
|
||||||
|
onKeyEvent: (keyEvent) {
|
||||||
|
if (keyEvent is KeyDownEvent) {
|
||||||
|
if (keyEvent.logicalKey.keyLabel == "Backspace") {
|
||||||
|
return onDeletePressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([".", ","].contains(keyEvent.logicalKey.keyLabel) &&
|
||||||
|
onDecimalPressed != null) {
|
||||||
|
return onDecimalPressed!();
|
||||||
|
}
|
||||||
|
|
||||||
|
int? number = int.tryParse(keyEvent.character ?? '');
|
||||||
|
if (number != null) return onNumberPressed(number);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
height: 300,
|
||||||
|
child: GridView.count(
|
||||||
|
childAspectRatio: 2,
|
||||||
|
shrinkWrap: true,
|
||||||
|
crossAxisCount: 3,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
children: List.generate(12, (index) {
|
||||||
|
if (index == 9) {
|
||||||
|
if (onDecimalPressed == null) return Container();
|
||||||
|
return InkWell(
|
||||||
|
onTap: onDecimalPressed,
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'.',
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 30,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (index == 10) {
|
||||||
|
index = 0;
|
||||||
|
} else if (index == 11) {
|
||||||
|
return MergeSemantics(
|
||||||
|
child: Container(
|
||||||
|
child: Semantics(
|
||||||
|
label: S.of(context).delete,
|
||||||
|
button: true,
|
||||||
|
onTap: onDeletePressed,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: onDeletePressed,
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor:
|
||||||
|
Colors.transparent,
|
||||||
|
shape: CircleBorder(),
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/delete_icon.png',
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InkWell(
|
||||||
|
onTap: () => onNumberPressed(index),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'$index',
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 30,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,263 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||||
|
import 'package:cake_wallet/themes/utils/custom_theme_colors.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SavingsCard extends StatelessWidget {
|
||||||
|
final bool isDarkTheme;
|
||||||
|
final bool isEnabled;
|
||||||
|
final String interestRate;
|
||||||
|
final String savingsBalance;
|
||||||
|
final CryptoCurrency currency;
|
||||||
|
final VoidCallback onAddSavingsPressed;
|
||||||
|
final VoidCallback onRemoveSavingsPressed;
|
||||||
|
final VoidCallback onApproveSavingsPressed;
|
||||||
|
|
||||||
|
const SavingsCard({
|
||||||
|
super.key,
|
||||||
|
required this.isDarkTheme,
|
||||||
|
required this.interestRate,
|
||||||
|
required this.savingsBalance,
|
||||||
|
required this.currency,
|
||||||
|
required this.onAddSavingsPressed,
|
||||||
|
required this.onRemoveSavingsPressed,
|
||||||
|
required this.onApproveSavingsPressed,
|
||||||
|
this.isEnabled = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => Container(
|
||||||
|
margin: const EdgeInsets.all(15),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
isDarkTheme
|
||||||
|
? CustomThemeColors.cardGradientColorPrimaryDark
|
||||||
|
: CustomThemeColors.cardGradientColorPrimaryLight,
|
||||||
|
isDarkTheme
|
||||||
|
? CustomThemeColors.cardGradientColorSecondaryDark
|
||||||
|
: CustomThemeColors.cardGradientColorSecondaryLight,
|
||||||
|
],
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
getAssetBalanceRow(context,
|
||||||
|
title: S.of(context).deuro_savings_balance,
|
||||||
|
subtitle: savingsBalance,
|
||||||
|
currency: currency),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Current APR',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
color:
|
||||||
|
Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
softWrap: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
interestRate,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
softWrap: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: isEnabled
|
||||||
|
? [
|
||||||
|
Expanded(
|
||||||
|
child: getButton(
|
||||||
|
context,
|
||||||
|
label: S.of(context).deuro_savings_add,
|
||||||
|
imagePath: 'assets/images/received.png',
|
||||||
|
onPressed: onAddSavingsPressed,
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: getButton(
|
||||||
|
context,
|
||||||
|
label: S.of(context).deuro_savings_remove,
|
||||||
|
imagePath: 'assets/images/upload.png',
|
||||||
|
onPressed: onRemoveSavingsPressed,
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.surface,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSecondaryContainer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
Expanded(
|
||||||
|
child: getButton(
|
||||||
|
context,
|
||||||
|
label: S.of(context).deuro_savings_set_approval,
|
||||||
|
onPressed: onApproveSavingsPressed,
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
static Widget getButton(
|
||||||
|
BuildContext context, {
|
||||||
|
required String label,
|
||||||
|
String? imagePath,
|
||||||
|
required VoidCallback onPressed,
|
||||||
|
required Color backgroundColor,
|
||||||
|
required Color color,
|
||||||
|
}) =>
|
||||||
|
Semantics(
|
||||||
|
label: label,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
side: BorderSide(
|
||||||
|
color: Theme.of(context).colorScheme.outlineVariant.withAlpha(0),
|
||||||
|
width: 0,
|
||||||
|
),
|
||||||
|
shape:
|
||||||
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
if (imagePath != null) ...[
|
||||||
|
Image.asset(
|
||||||
|
imagePath,
|
||||||
|
height: 30,
|
||||||
|
width: 30,
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
],
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
color: color,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
static Widget getAssetBalanceRow(
|
||||||
|
BuildContext context, {
|
||||||
|
required String title,
|
||||||
|
required String subtitle,
|
||||||
|
required CryptoCurrency currency,
|
||||||
|
bool hideSymbol = true,
|
||||||
|
}) =>
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 6),
|
||||||
|
AutoSizeText(
|
||||||
|
subtitle,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
fontSize: 24,
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
//width: min(MediaQuery.of(context).size.width * 0.2, 100),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
CakeImageWidget(
|
||||||
|
imageUrl: currency.iconPath,
|
||||||
|
height: 40,
|
||||||
|
width: 40,
|
||||||
|
errorWidget: Container(
|
||||||
|
height: 30.0,
|
||||||
|
width: 30.0,
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
currency.title
|
||||||
|
.substring(0, min(currency.title.length, 2)),
|
||||||
|
style:
|
||||||
|
Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!hideSymbol) ...[
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Text(
|
||||||
|
currency.title,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/integrations/deuro/widgets/numpad.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SavingEditPage extends BasePage {
|
||||||
|
final bool isAdding;
|
||||||
|
|
||||||
|
SavingEditPage({required this.isAdding});
|
||||||
|
|
||||||
|
String get title =>
|
||||||
|
isAdding ? S.current.deuro_savings_add : S.current.deuro_savings_remove;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget body(BuildContext context) => _SavingsEditBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SavingsEditBody extends StatefulWidget {
|
||||||
|
const _SavingsEditBody();
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _SavingsEditBodyState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SavingsEditBodyState extends State<_SavingsEditBody> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
WidgetsBinding.instance
|
||||||
|
.addPostFrameCallback((_) => _numpadFocusNode.requestFocus());
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_numpadFocusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
String amount = '0';
|
||||||
|
final FocusNode _numpadFocusNode = FocusNode();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => SafeArea(
|
||||||
|
child: Column(children: [
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 26, right: 26, top: 10),
|
||||||
|
child: AutoSizeText(
|
||||||
|
"${amount.toString()} dEuro",
|
||||||
|
maxLines: 1,
|
||||||
|
maxFontSize: 60,
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 60,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
NumberPad(
|
||||||
|
focusNode: _numpadFocusNode,
|
||||||
|
onNumberPressed: (i) => setState(
|
||||||
|
() => amount = amount == '0' ? i.toString() : '${amount}${i}',
|
||||||
|
),
|
||||||
|
onDeletePressed: () => setState(
|
||||||
|
() => amount = amount.length > 1
|
||||||
|
? amount.substring(0, amount.length - 1)
|
||||||
|
: '0',
|
||||||
|
),
|
||||||
|
onDecimalPressed: () =>
|
||||||
|
setState(() => amount = '${amount.replaceAll('.', '')}.'),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 34),
|
||||||
|
child: LoadingPrimaryButton(
|
||||||
|
onPressed: () => Navigator.pop(context, amount),
|
||||||
|
text: S.of(context).confirm,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
isLoading: false,
|
||||||
|
isDisabled: false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
|
@ -8,6 +8,8 @@ import 'choose_yat_address_alert.dart';
|
||||||
Future<String> extractAddressFromParsed(
|
Future<String> extractAddressFromParsed(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
ParsedAddress parsedAddress) async {
|
ParsedAddress parsedAddress) async {
|
||||||
|
if (!context.mounted) return parsedAddress.addresses.first;
|
||||||
|
|
||||||
var title = '';
|
var title = '';
|
||||||
var content = '';
|
var content = '';
|
||||||
var address = '';
|
var address = '';
|
||||||
|
@ -96,15 +98,16 @@ Future<String> extractAddressFromParsed(
|
||||||
|
|
||||||
address = await showPopUp<String?>(
|
address = await showPopUp<String?>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (context) => PopScope(
|
||||||
|
|
||||||
return WillPopScope(
|
|
||||||
child: ChooseYatAddressAlert(
|
child: ChooseYatAddressAlert(
|
||||||
alertTitle: title,
|
alertTitle: title,
|
||||||
alertContent: content,
|
alertContent: content,
|
||||||
addresses: parsedAddress.addresses),
|
addresses: parsedAddress.addresses,
|
||||||
onWillPop: () async => false);
|
),
|
||||||
}) ?? '';
|
canPop: false,
|
||||||
|
),
|
||||||
|
) ??
|
||||||
|
'';
|
||||||
|
|
||||||
if (address.isEmpty) {
|
if (address.isEmpty) {
|
||||||
return parsedAddress.name;
|
return parsedAddress.name;
|
||||||
|
@ -113,22 +116,20 @@ Future<String> extractAddressFromParsed(
|
||||||
return address;
|
return address;
|
||||||
case ParseFrom.contact:
|
case ParseFrom.contact:
|
||||||
case ParseFrom.notParsed:
|
case ParseFrom.notParsed:
|
||||||
address = parsedAddress.addresses.first;
|
return parsedAddress.addresses.first;
|
||||||
return address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await showPopUp<void>(
|
await showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (context) => AlertWithOneAction(
|
||||||
|
|
||||||
return AlertWithOneAction(
|
|
||||||
alertTitle: title,
|
alertTitle: title,
|
||||||
headerTitleText: profileName.isEmpty ? null : profileName,
|
headerTitleText: profileName.isEmpty ? null : profileName,
|
||||||
headerImageProfileUrl: profileImageUrl.isEmpty ? null : profileImageUrl,
|
headerImageProfileUrl: profileImageUrl.isEmpty ? null : profileImageUrl,
|
||||||
alertContent: content,
|
alertContent: content,
|
||||||
buttonText: S.of(context).ok,
|
buttonText: S.of(context).ok,
|
||||||
buttonAction: () => Navigator.of(context).pop());
|
buttonAction: () => Navigator.of(context).pop(),
|
||||||
});
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||||
import 'package:cake_wallet/themes/core/material_base_theme.dart';
|
|
||||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
|
|
@ -7,7 +7,7 @@ class CakeImageWidget extends StatelessWidget {
|
||||||
this.imageUrl,
|
this.imageUrl,
|
||||||
this.height,
|
this.height,
|
||||||
this.width,
|
this.width,
|
||||||
this.fit = BoxFit.cover,
|
this.fit,
|
||||||
this.loadingWidget,
|
this.loadingWidget,
|
||||||
this.errorWidget,
|
this.errorWidget,
|
||||||
this.color,
|
this.color,
|
||||||
|
@ -16,7 +16,7 @@ class CakeImageWidget extends StatelessWidget {
|
||||||
final String? imageUrl;
|
final String? imageUrl;
|
||||||
final double? height;
|
final double? height;
|
||||||
final double? width;
|
final double? width;
|
||||||
final BoxFit fit;
|
final BoxFit? fit;
|
||||||
final Widget? loadingWidget;
|
final Widget? loadingWidget;
|
||||||
final Widget? errorWidget;
|
final Widget? errorWidget;
|
||||||
final Color? color;
|
final Color? color;
|
||||||
|
@ -37,8 +37,7 @@ class CakeImageWidget extends StatelessWidget {
|
||||||
imageUrl!,
|
imageUrl!,
|
||||||
height: height,
|
height: height,
|
||||||
width: width,
|
width: width,
|
||||||
fit: fit,
|
fit: fit ?? BoxFit.contain,
|
||||||
color: color,
|
|
||||||
)
|
)
|
||||||
: Image.asset(
|
: Image.asset(
|
||||||
imageUrl!,
|
imageUrl!,
|
||||||
|
@ -53,8 +52,7 @@ class CakeImageWidget extends StatelessWidget {
|
||||||
imageUrl!,
|
imageUrl!,
|
||||||
height: height,
|
height: height,
|
||||||
width: width,
|
width: width,
|
||||||
fit: fit,
|
fit: fit ?? BoxFit.contain,
|
||||||
color: color,
|
|
||||||
placeholderBuilder: (_) {
|
placeholderBuilder: (_) {
|
||||||
return loadingWidget ?? const Center(child: CircularProgressIndicator());
|
return loadingWidget ?? const Center(child: CircularProgressIndicator());
|
||||||
},
|
},
|
||||||
|
@ -64,7 +62,7 @@ class CakeImageWidget extends StatelessWidget {
|
||||||
imageUrl!,
|
imageUrl!,
|
||||||
height: height,
|
height: height,
|
||||||
width: width,
|
width: width,
|
||||||
fit: fit,
|
fit: fit ?? BoxFit.cover,
|
||||||
color: color,
|
color: color,
|
||||||
loadingBuilder: (_, Widget child, ImageChunkEvent? progress) {
|
loadingBuilder: (_, Widget child, ImageChunkEvent? progress) {
|
||||||
if (progress == null) return child;
|
if (progress == null) return child;
|
||||||
|
|
|
@ -109,6 +109,7 @@ class DashBoardRoundedCardWidget extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Padding(padding: EdgeInsets.only(left: 10)),
|
||||||
if (image != null) image! else if (svgPicture != null) svgPicture!,
|
if (image != null) image! else if (svgPicture != null) svgPicture!,
|
||||||
if (icon != null) icon!
|
if (icon != null) icon!
|
||||||
],
|
],
|
||||||
|
|
|
@ -4,8 +4,10 @@ import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/main.dart';
|
import 'package:cake_wallet/main.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||||
import 'package:cake_wallet/store/app_store.dart';
|
import 'package:cake_wallet/store/app_store.dart';
|
||||||
|
import 'package:cake_wallet/utils/package_info.dart';
|
||||||
import 'package:cake_wallet/utils/show_bar.dart';
|
import 'package:cake_wallet/utils/show_bar.dart';
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
import 'package:cw_core/root_dir.dart';
|
import 'package:cw_core/root_dir.dart';
|
||||||
|
@ -15,7 +17,6 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_mailer/flutter_mailer.dart';
|
import 'package:flutter_mailer/flutter_mailer.dart';
|
||||||
import 'package:cake_wallet/utils/package_info.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class ExceptionHandler {
|
class ExceptionHandler {
|
||||||
|
@ -113,6 +114,8 @@ class ExceptionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> onError(FlutterErrorDetails errorDetails) async {
|
static Future<void> onError(FlutterErrorDetails errorDetails) async {
|
||||||
|
if (await onLedgerError(errorDetails)) return;
|
||||||
|
|
||||||
if (kDebugMode || kProfileMode) {
|
if (kDebugMode || kProfileMode) {
|
||||||
FlutterError.presentError(errorDetails);
|
FlutterError.presentError(errorDetails);
|
||||||
printV(errorDetails.toString());
|
printV(errorDetails.toString());
|
||||||
|
@ -183,6 +186,57 @@ class ExceptionHandler {
|
||||||
_hasError = false;
|
_hasError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const List<String> _ledgerErrors = [
|
||||||
|
'Wrong Device Status',
|
||||||
|
'PlatformException(133, Failed to write: (Unknown Error: 133), null, null)',
|
||||||
|
'PlatformException(IllegalArgument, Unknown deviceId:',
|
||||||
|
'ServiceNotSupportedException(ConnectionType.ble, Required service not supported. Write characteristic: false, Notify characteristic: false)',
|
||||||
|
'Exception: 6e01', // Wrong App
|
||||||
|
'Exception: 6d02',
|
||||||
|
'Exception: 6511',
|
||||||
|
'Exception: 6e00',
|
||||||
|
'Exception: 6985',
|
||||||
|
'Exception: 5515',
|
||||||
|
];
|
||||||
|
|
||||||
|
static bool isLedgerError(Object exception) =>
|
||||||
|
_ledgerErrors.any((element) => exception.toString().contains(element));
|
||||||
|
|
||||||
|
static Future<bool> onLedgerError(FlutterErrorDetails errorDetails) async {
|
||||||
|
if (!isLedgerError(errorDetails.exception)) return false;
|
||||||
|
|
||||||
|
String? interpretErrorCode(String errorCode) {
|
||||||
|
if (errorCode.contains("6985")) {
|
||||||
|
return S.current.ledger_error_tx_rejected_by_user;
|
||||||
|
} else if (errorCode.contains("5515")) {
|
||||||
|
return S.current.ledger_error_device_locked;
|
||||||
|
} else
|
||||||
|
if (["6e01", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
|
||||||
|
return S.current.ledger_error_wrong_app;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
printV(errorDetails.exception);
|
||||||
|
|
||||||
|
if (navigatorKey.currentContext != null) {
|
||||||
|
await showPopUp<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
builder: (context) => AlertWithOneAction(
|
||||||
|
alertTitle: "Ledger Error",
|
||||||
|
alertContent:
|
||||||
|
interpretErrorCode(errorDetails.exception.toString()) ??
|
||||||
|
S.of(context).ledger_connection_error,
|
||||||
|
buttonText: S.of(context).close,
|
||||||
|
buttonAction: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_hasError = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Ignore User related errors or system errors
|
/// Ignore User related errors or system errors
|
||||||
static bool _ignoreError(String error) =>
|
static bool _ignoreError(String error) =>
|
||||||
_ignoredErrors.any((element) => error.contains(element));
|
_ignoredErrors.any((element) => error.contains(element));
|
||||||
|
@ -227,6 +281,7 @@ class ExceptionHandler {
|
||||||
"core/auth_service.dart:64",
|
"core/auth_service.dart:64",
|
||||||
"core/key_service.dart:14",
|
"core/key_service.dart:14",
|
||||||
"core/wallet_loading_service.dart:139",
|
"core/wallet_loading_service.dart:139",
|
||||||
|
"Wrong Device Status: 0x5515 (UNKNOWN)",
|
||||||
];
|
];
|
||||||
|
|
||||||
static Future<void> _addDeviceInfo(File file) async {
|
static Future<void> _addDeviceInfo(File file) async {
|
||||||
|
|
|
@ -20,9 +20,8 @@ class PayjoinTransactionListItem extends ActionListItem {
|
||||||
String get status {
|
String get status {
|
||||||
switch (session.status) {
|
switch (session.status) {
|
||||||
case 'success':
|
case 'success':
|
||||||
if (transaction?.isPending == true)
|
if (transaction?.isPending == false) return S.current.successful;
|
||||||
return S.current.payjoin_request_awaiting_tx;
|
return S.current.payjoin_request_awaiting_tx;
|
||||||
return S.current.successful;
|
|
||||||
case 'inProgress':
|
case 'inProgress':
|
||||||
return S.current.payjoin_request_in_progress;
|
return S.current.payjoin_request_in_progress;
|
||||||
case 'unrecoverable':
|
case 'unrecoverable':
|
||||||
|
|
|
@ -96,7 +96,8 @@ abstract class LedgerViewModelBase with Store {
|
||||||
if (!Platform.isIOS) await ledgerPlusUSB.stopScanning();
|
if (!Platform.isIOS) await ledgerPlusUSB.stopScanning();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> connectLedger(sdk.LedgerDevice device, WalletType type) async {
|
Future<bool> connectLedger(sdk.LedgerDevice device, WalletType type) async {
|
||||||
|
if (_isConnecting) return false;
|
||||||
_isConnecting = true;
|
_isConnecting = true;
|
||||||
_connectingWalletType = type;
|
_connectingWalletType = type;
|
||||||
if (isConnected) {
|
if (isConnected) {
|
||||||
|
@ -110,17 +111,25 @@ abstract class LedgerViewModelBase with Store {
|
||||||
: ledgerPlusUSB;
|
: ledgerPlusUSB;
|
||||||
|
|
||||||
if (_connectionChangeSubscription == null) {
|
if (_connectionChangeSubscription == null) {
|
||||||
_connectionChangeSubscription =
|
_connectionChangeSubscription = ledger
|
||||||
ledger.deviceStateChanges.listen(_connectionChangeListener);
|
.deviceStateChanges(device.id)
|
||||||
|
.listen(_connectionChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
_connection = await ledger.connect(device);
|
_connection = await ledger.connect(device);
|
||||||
_isConnecting = false;
|
_isConnecting = false;
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
printV(e);
|
||||||
|
}
|
||||||
|
_isConnecting = false;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamSubscription<sdk.BleConnectionState>? _connectionChangeSubscription;
|
StreamSubscription<sdk.BleConnectionState>? _connectionChangeSubscription;
|
||||||
sdk.LedgerConnection? _connection;
|
sdk.LedgerConnection? _connection;
|
||||||
bool _isConnecting = true;
|
bool _isConnecting = false;
|
||||||
WalletType? _connectingWalletType;
|
WalletType? _connectingWalletType;
|
||||||
|
|
||||||
void _connectionChangeListener(sdk.BleConnectionState event) {
|
void _connectionChangeListener(sdk.BleConnectionState event) {
|
||||||
|
@ -168,17 +177,14 @@ abstract class LedgerViewModelBase with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
String? interpretErrorCode(String errorCode) {
|
String? interpretErrorCode(String errorCode) {
|
||||||
switch (errorCode) {
|
if (errorCode.contains("6985")) {
|
||||||
case "6985":
|
|
||||||
return S.current.ledger_error_tx_rejected_by_user;
|
return S.current.ledger_error_tx_rejected_by_user;
|
||||||
case "5515":
|
} else if (errorCode.contains("5515")) {
|
||||||
return S.current.ledger_error_device_locked;
|
return S.current.ledger_error_device_locked;
|
||||||
case "6d02": // UNKNOWN_APDU
|
} else
|
||||||
case "6511":
|
if (["6e01", "6a87", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
|
||||||
case "6e00":
|
|
||||||
return S.current.ledger_error_wrong_app;
|
return S.current.ledger_error_wrong_app;
|
||||||
default:
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
119
lib/view_model/integrations/deuro_view_model.dart
Normal file
119
lib/view_model/integrations/deuro_view_model.dart
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:cake_wallet/core/execution_state.dart';
|
||||||
|
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||||
|
import 'package:cake_wallet/store/app_store.dart';
|
||||||
|
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
|
||||||
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
|
part 'deuro_view_model.g.dart';
|
||||||
|
|
||||||
|
class DEuroViewModel = DEuroViewModelBase with _$DEuroViewModel;
|
||||||
|
|
||||||
|
abstract class DEuroViewModelBase with Store {
|
||||||
|
final AppStore _appStore;
|
||||||
|
|
||||||
|
DEuroViewModelBase(this._appStore) {
|
||||||
|
reloadInterestRate();
|
||||||
|
reloadSavingsUserData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String savingsBalance = '0.00';
|
||||||
|
|
||||||
|
@observable
|
||||||
|
ExecutionState state = InitialExecutionState();
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String interestRate = '0';
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String accruedInterest = '0.00';
|
||||||
|
|
||||||
|
@observable
|
||||||
|
BigInt approvedTokens = BigInt.zero;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
bool get isEnabled => approvedTokens > BigInt.zero;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
PendingTransaction? transaction = null;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
PendingTransaction? approvalTransaction = null;
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> reloadSavingsUserData() async {
|
||||||
|
final savingsBalanceRaw =
|
||||||
|
ethereum!.getDEuroSavingsBalance(_appStore.wallet!);
|
||||||
|
final accruedInterestRaw =
|
||||||
|
ethereum!.getDEuroAccruedInterest(_appStore.wallet!);
|
||||||
|
|
||||||
|
approvedTokens = await ethereum!.getDEuroSavingsApproved(_appStore.wallet!);
|
||||||
|
|
||||||
|
savingsBalance = ethereum!
|
||||||
|
.formatterEthereumAmountToDouble(amount: await savingsBalanceRaw)
|
||||||
|
.toStringAsFixed(6);
|
||||||
|
accruedInterest = ethereum!
|
||||||
|
.formatterEthereumAmountToDouble(amount: await accruedInterestRaw)
|
||||||
|
.toStringAsFixed(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> reloadInterestRate() async {
|
||||||
|
final interestRateRaw =
|
||||||
|
await ethereum!.getDEuroInterestRate(_appStore.wallet!);
|
||||||
|
|
||||||
|
interestRate = (interestRateRaw / BigInt.from(10000)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> prepareApproval() async {
|
||||||
|
final priority = _appStore.settingsStore.priority[WalletType.ethereum]!;
|
||||||
|
approvalTransaction =
|
||||||
|
await ethereum!.enableDEuroSaving(_appStore.wallet!, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> prepareSavingsEdit(String amountRaw, bool isAdding) async {
|
||||||
|
final amount = BigInt.from(num.parse(amountRaw) * pow(10, 18));
|
||||||
|
final priority = _appStore.settingsStore.priority[WalletType.ethereum]!;
|
||||||
|
transaction = await (isAdding
|
||||||
|
? ethereum!.addDEuroSaving(_appStore.wallet!, amount, priority)
|
||||||
|
: ethereum!.removeDEuroSaving(_appStore.wallet!, amount, priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> prepareCollectInterest() =>
|
||||||
|
prepareSavingsEdit(accruedInterest, false);
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> commitTransaction() async {
|
||||||
|
if (transaction != null) {
|
||||||
|
state = TransactionCommitting();
|
||||||
|
await transaction!.commit();
|
||||||
|
transaction = null;
|
||||||
|
reloadSavingsUserData();
|
||||||
|
state = TransactionCommitted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> commitApprovalTransaction() async {
|
||||||
|
if (approvalTransaction != null) {
|
||||||
|
state = TransactionCommitting();
|
||||||
|
await approvalTransaction!.commit();
|
||||||
|
approvalTransaction = null;
|
||||||
|
reloadSavingsUserData();
|
||||||
|
state = TransactionCommitted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
void dismissTransaction() {
|
||||||
|
transaction == null;
|
||||||
|
approvalTransaction = null;
|
||||||
|
state = InitialExecutionState();
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,7 +69,7 @@ abstract class PayjoinDetailsViewModelBase with Store {
|
||||||
title: S.current.error,
|
title: S.current.error,
|
||||||
value: payjoinSession.error!,
|
value: payjoinSession.error!,
|
||||||
),
|
),
|
||||||
if (payjoinSession.txId?.isNotEmpty == true)
|
if (payjoinSession.txId?.isNotEmpty == true && transactionInfo != null)
|
||||||
StandartListItem(
|
StandartListItem(
|
||||||
title: S.current.transaction_details_transaction_id,
|
title: S.current.transaction_details_transaction_id,
|
||||||
value: payjoinSession.txId!,
|
value: payjoinSession.txId!,
|
||||||
|
@ -107,9 +107,8 @@ abstract class PayjoinDetailsViewModelBase with Store {
|
||||||
String _getStatusString() {
|
String _getStatusString() {
|
||||||
switch (payjoinSession.status) {
|
switch (payjoinSession.status) {
|
||||||
case 'success':
|
case 'success':
|
||||||
if (transactionInfo?.isPending == true)
|
if (transactionInfo?.isPending == false) return S.current.successful;
|
||||||
return S.current.payjoin_request_awaiting_tx;
|
return S.current.payjoin_request_awaiting_tx;
|
||||||
return S.current.successful;
|
|
||||||
case 'inProgress':
|
case 'inProgress':
|
||||||
return S.current.payjoin_request_in_progress;
|
return S.current.payjoin_request_in_progress;
|
||||||
case 'unrecoverable':
|
case 'unrecoverable':
|
||||||
|
|
|
@ -74,7 +74,10 @@ class WalletRestoreFromQRCode {
|
||||||
static String? _extractAddressFromUrl(String rawString, WalletType type) {
|
static String? _extractAddressFromUrl(String rawString, WalletType type) {
|
||||||
try {
|
try {
|
||||||
return AddressResolver.extractAddressByType(
|
return AddressResolver.extractAddressByType(
|
||||||
raw: rawString, type: walletTypeToCryptoCurrency(type));
|
raw: rawString,
|
||||||
|
type: walletTypeToCryptoCurrency(type),
|
||||||
|
requireSurroundingWhitespaces: false,
|
||||||
|
);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,11 +80,9 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
|
||||||
|
|
||||||
availableAccounts.addAll(accounts);
|
availableAccounts.addAll(accounts);
|
||||||
_nextIndex += limit;
|
_nextIndex += limit;
|
||||||
// } on LedgerException catch (e) {
|
|
||||||
// error = ledgerViewModel.interpretErrorCode(e.errorCode.toRadixString(16));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
printV(e);
|
printV(e);
|
||||||
error = S.current.ledger_connection_error;
|
error = ledgerViewModel.interpretErrorCode(e.toString()) ?? S.current.ledger_connection_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoadingMoreAccounts = false;
|
isLoadingMoreAccounts = false;
|
||||||
|
|
|
@ -114,7 +114,7 @@ dependencies:
|
||||||
ledger_flutter_plus:
|
ledger_flutter_plus:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/vespr-wallet/ledger-flutter-plus
|
url: https://github.com/vespr-wallet/ledger-flutter-plus
|
||||||
ref: c2e341d8038f1108690ad6f80f7b4b7156aacc76
|
ref: 60817d4b20144f9da9029f5034790272795b9d38
|
||||||
hashlib: ^1.19.2
|
hashlib: ^1.19.2
|
||||||
on_chain:
|
on_chain:
|
||||||
git:
|
git:
|
||||||
|
@ -171,7 +171,7 @@ dependency_overrides:
|
||||||
ledger_flutter_plus:
|
ledger_flutter_plus:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/vespr-wallet/ledger-flutter-plus
|
url: https://github.com/vespr-wallet/ledger-flutter-plus
|
||||||
ref: c2e341d8038f1108690ad6f80f7b4b7156aacc76
|
ref: 60817d4b20144f9da9029f5034790272795b9d38
|
||||||
socks5_proxy:
|
socks5_proxy:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/LacticWhale/socks_dart.git
|
url: https://github.com/LacticWhale/socks_dart.git
|
||||||
|
@ -180,6 +180,8 @@ dependency_overrides:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/MrCyjaneK/flutter-tor_binary
|
url: https://github.com/MrCyjaneK/flutter-tor_binary
|
||||||
ref: cb811c610871a9517d47134b87c2f590c15c96c5
|
ref: cb811c610871a9517d47134b87c2f590c15c96c5
|
||||||
|
web_socket_channel: ^3.0.2
|
||||||
|
freezed_annotation: 2.4.4
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
image_path: "assets/images/app_logo.png"
|
image_path: "assets/images/app_logo.png"
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "تحديث APK",
|
"apk_update": "تحديث APK",
|
||||||
"approve": "ﺪﻤﺘﻌﻳ",
|
"approve": "ﺪﻤﺘﻌﻳ",
|
||||||
"approve_request": "الموافقة على الطلب",
|
"approve_request": "الموافقة على الطلب",
|
||||||
|
"approve_tokens": "الموافقة على الرموز",
|
||||||
"arrive_in_this_address": "سيصل ${currency} ${tag}إلى هذا العنوان",
|
"arrive_in_this_address": "سيصل ${currency} ${tag}إلى هذا العنوان",
|
||||||
"ascending": "تصاعدي",
|
"ascending": "تصاعدي",
|
||||||
"ask_each_time": "اسأل في كل مرة",
|
"ask_each_time": "اسأل في كل مرة",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "النزول",
|
"descending": "النزول",
|
||||||
"description": "ﻒﺻﻭ",
|
"description": "ﻒﺻﻭ",
|
||||||
"destination_tag": "علامة الوجهة:",
|
"destination_tag": "علامة الوجهة:",
|
||||||
|
"deuro_collect_interest": "يجمع",
|
||||||
|
"deuro_savings": "الادخار ديورو",
|
||||||
|
"deuro_savings_add": "إيداع",
|
||||||
|
"deuro_savings_balance": "توازن الادخار",
|
||||||
|
"deuro_savings_collect_interest": "جمع الاهتمام",
|
||||||
|
"deuro_savings_remove": "ينسحب",
|
||||||
|
"deuro_savings_set_approval": "تعيين الموافقة",
|
||||||
|
"deuro_savings_subtitle": "كسب ما يصل إلى 10 ٪ فائدة على مقتنيات Deuro Stablecoin",
|
||||||
|
"deuro_tx_commited_content": "قد يستغرق الأمر بضع ثوانٍ حتى يتم تأكيد المعاملة وينعكس على الشاشة",
|
||||||
"device_is_signing": "الجهاز يوقع",
|
"device_is_signing": "الجهاز يوقع",
|
||||||
"dfx_option_description": "شراء التشفير مع EUR & CHF. لعملاء البيع بالتجزئة والشركات في أوروبا",
|
"dfx_option_description": "شراء التشفير مع EUR & CHF. لعملاء البيع بالتجزئة والشركات في أوروبا",
|
||||||
"didnt_get_code": "لم تحصل على رمز؟",
|
"didnt_get_code": "لم تحصل على رمز؟",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "نوع النقل",
|
"transport_type": "نوع النقل",
|
||||||
"trongrid_history": "تاريخ ترونغريد",
|
"trongrid_history": "تاريخ ترونغريد",
|
||||||
"trusted": "موثوق به",
|
"trusted": "موثوق به",
|
||||||
|
"try_again": "حاول ثانية",
|
||||||
"tx_commit_exception_no_dust_on_change": "يتم رفض المعاملة مع هذا المبلغ. باستخدام هذه العملات المعدنية ، يمكنك إرسال ${min} دون تغيير أو ${max} الذي يعيد التغيير.",
|
"tx_commit_exception_no_dust_on_change": "يتم رفض المعاملة مع هذا المبلغ. باستخدام هذه العملات المعدنية ، يمكنك إرسال ${min} دون تغيير أو ${max} الذي يعيد التغيير.",
|
||||||
"tx_commit_failed": "فشل ارتكاب المعاملة. يرجى الاتصال بالدعم.",
|
"tx_commit_failed": "فشل ارتكاب المعاملة. يرجى الاتصال بالدعم.",
|
||||||
"tx_commit_failed_no_peers": "فشل المعاملة في البث ، يرجى المحاولة مرة أخرى في ثانية أو نحو ذلك",
|
"tx_commit_failed_no_peers": "فشل المعاملة في البث ، يرجى المحاولة مرة أخرى في ثانية أو نحو ذلك",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK ъпдейт",
|
"apk_update": "APK ъпдейт",
|
||||||
"approve": "Одобряване",
|
"approve": "Одобряване",
|
||||||
"approve_request": "Одобрете искане",
|
"approve_request": "Одобрете искане",
|
||||||
|
"approve_tokens": "Одобрете жетоните",
|
||||||
"arrive_in_this_address": "${currency} ${tag}ще отидат на този адрес",
|
"arrive_in_this_address": "${currency} ${tag}ще отидат на този адрес",
|
||||||
"ascending": "Възходящ",
|
"ascending": "Възходящ",
|
||||||
"ask_each_time": "Питайте всеки път",
|
"ask_each_time": "Питайте всеки път",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Низходящ",
|
"descending": "Низходящ",
|
||||||
"description": "Описание",
|
"description": "Описание",
|
||||||
"destination_tag": "Destination tag:",
|
"destination_tag": "Destination tag:",
|
||||||
|
"deuro_collect_interest": "Събиране",
|
||||||
|
"deuro_savings": "Спестявания на Деуро",
|
||||||
|
"deuro_savings_add": "Депозит",
|
||||||
|
"deuro_savings_balance": "Спестотен баланс",
|
||||||
|
"deuro_savings_collect_interest": "Събиране на интерес",
|
||||||
|
"deuro_savings_remove": "Оттегляне",
|
||||||
|
"deuro_savings_set_approval": "Задайте одобрение",
|
||||||
|
"deuro_savings_subtitle": "Печелете до 10% лихва за вашите Deuro Stablecoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Може да отнеме няколко секунди, за да може транзакцията да се потвърди и да бъде отразена на екрана",
|
||||||
"device_is_signing": "Устройството подписва",
|
"device_is_signing": "Устройството подписва",
|
||||||
"dfx_option_description": "Купете криптовалута с Eur & CHF. За търговски и корпоративни клиенти в Европа",
|
"dfx_option_description": "Купете криптовалута с Eur & CHF. За търговски и корпоративни клиенти в Европа",
|
||||||
"didnt_get_code": "Не получихте код?",
|
"didnt_get_code": "Не получихте код?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "Тип транспорт",
|
"transport_type": "Тип транспорт",
|
||||||
"trongrid_history": "Trongrid History",
|
"trongrid_history": "Trongrid History",
|
||||||
"trusted": "Надежден",
|
"trusted": "Надежден",
|
||||||
|
"try_again": "Опитайте отново",
|
||||||
"tx_commit_exception_no_dust_on_change": "Сделката се отхвърля с тази сума. С тези монети можете да изпратите ${min} без промяна или ${max}, която връща промяна.",
|
"tx_commit_exception_no_dust_on_change": "Сделката се отхвърля с тази сума. С тези монети можете да изпратите ${min} без промяна или ${max}, която връща промяна.",
|
||||||
"tx_commit_failed": "Компетацията на транзакцията не успя. Моля, свържете се с поддръжката.",
|
"tx_commit_failed": "Компетацията на транзакцията не успя. Моля, свържете се с поддръжката.",
|
||||||
"tx_commit_failed_no_peers": "Сделката не успя да излъчи, моля, опитайте отново след секунда или така",
|
"tx_commit_failed_no_peers": "Сделката не успя да излъчи, моля, опитайте отново след секунда или така",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "aktualizace APK",
|
"apk_update": "aktualizace APK",
|
||||||
"approve": "Schvalovat",
|
"approve": "Schvalovat",
|
||||||
"approve_request": "Schválit žádost",
|
"approve_request": "Schválit žádost",
|
||||||
|
"approve_tokens": "Schválit tokeny",
|
||||||
"arrive_in_this_address": "${currency} ${tag}přijde na tuto adresu",
|
"arrive_in_this_address": "${currency} ${tag}přijde na tuto adresu",
|
||||||
"ascending": "Vzestupné",
|
"ascending": "Vzestupné",
|
||||||
"ask_each_time": "Zeptejte se pokaždé",
|
"ask_each_time": "Zeptejte se pokaždé",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Klesající",
|
"descending": "Klesající",
|
||||||
"description": "Popis",
|
"description": "Popis",
|
||||||
"destination_tag": "Destination Tag:",
|
"destination_tag": "Destination Tag:",
|
||||||
|
"deuro_collect_interest": "Sbírat",
|
||||||
|
"deuro_savings": "dEuro úspory",
|
||||||
|
"deuro_savings_add": "Vklad",
|
||||||
|
"deuro_savings_balance": "Úspora zůstatek",
|
||||||
|
"deuro_savings_collect_interest": "Sbírat zájem",
|
||||||
|
"deuro_savings_remove": "Odstoupit",
|
||||||
|
"deuro_savings_set_approval": "Stanovit schválení",
|
||||||
|
"deuro_savings_subtitle": "Získejte až 10% úrok z vašeho Deuro Stablecoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Transakce může trvat několik sekund, aby se potvrdila a odrážela se na obrazovce",
|
||||||
"device_is_signing": "Zařízení se podpisu",
|
"device_is_signing": "Zařízení se podpisu",
|
||||||
"dfx_option_description": "Koupit krypto s EUR & CHF. Pro maloobchodní a firemní zákazníky v Evropě",
|
"dfx_option_description": "Koupit krypto s EUR & CHF. Pro maloobchodní a firemní zákazníky v Evropě",
|
||||||
"didnt_get_code": "Nepřišel Vám kód?",
|
"didnt_get_code": "Nepřišel Vám kód?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "Typ transportu",
|
"transport_type": "Typ transportu",
|
||||||
"trongrid_history": "Trongridní historie",
|
"trongrid_history": "Trongridní historie",
|
||||||
"trusted": "Důvěřovat",
|
"trusted": "Důvěřovat",
|
||||||
|
"try_again": "Zkuste to znovu",
|
||||||
"tx_commit_exception_no_dust_on_change": "Transakce je zamítnuta s touto částkou. S těmito mincemi můžete odeslat ${min} bez změny nebo ${max}, které se vrátí změna.",
|
"tx_commit_exception_no_dust_on_change": "Transakce je zamítnuta s touto částkou. S těmito mincemi můžete odeslat ${min} bez změny nebo ${max}, které se vrátí změna.",
|
||||||
"tx_commit_failed": "Transakce COMPORT selhala. Kontaktujte prosím podporu.",
|
"tx_commit_failed": "Transakce COMPORT selhala. Kontaktujte prosím podporu.",
|
||||||
"tx_commit_failed_no_peers": "Transakce se nepodařilo vysílat, zkuste to prosím znovu za vteřinu",
|
"tx_commit_failed_no_peers": "Transakce se nepodařilo vysílat, zkuste to prosím znovu za vteřinu",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK-Update",
|
"apk_update": "APK-Update",
|
||||||
"approve": "Genehmigen",
|
"approve": "Genehmigen",
|
||||||
"approve_request": "Anfrage genehmigen",
|
"approve_request": "Anfrage genehmigen",
|
||||||
|
"approve_tokens": "Token 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",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Absteigend",
|
"descending": "Absteigend",
|
||||||
"description": "Beschreibung",
|
"description": "Beschreibung",
|
||||||
"destination_tag": "Ziel-Tag:",
|
"destination_tag": "Ziel-Tag:",
|
||||||
|
"deuro_collect_interest": "Auszahlen",
|
||||||
|
"deuro_savings": "dEuro-Savings",
|
||||||
|
"deuro_savings_add": "Einzahlen",
|
||||||
|
"deuro_savings_balance": "Sparguthaben",
|
||||||
|
"deuro_savings_collect_interest": "Interesse sammeln",
|
||||||
|
"deuro_savings_remove": "Auszahlen",
|
||||||
|
"deuro_savings_set_approval": "Genehmigung festlegen",
|
||||||
|
"deuro_savings_subtitle": "Verdienen Sie bis zu 10% Zinsen für Ihre dEuro Stablecoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Es kann ein paar Sekunden dauern, bis die Transaktion bestätigt und auf dem Bildschirm angezeigt",
|
||||||
"device_is_signing": "Das Gerät unterschreibt",
|
"device_is_signing": "Das Gerät unterschreibt",
|
||||||
"dfx_option_description": "Kaufen Sie Krypto mit EUR & CHF. Für Einzelhandel und Unternehmenskunden in Europa",
|
"dfx_option_description": "Kaufen Sie Krypto mit EUR & CHF. Für Einzelhandel und Unternehmenskunden in Europa",
|
||||||
"didnt_get_code": "Kein Code?",
|
"didnt_get_code": "Kein Code?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "Transporttyp",
|
"transport_type": "Transporttyp",
|
||||||
"trongrid_history": "Trongrid-Historie",
|
"trongrid_history": "Trongrid-Historie",
|
||||||
"trusted": "Vertrauenswürdige",
|
"trusted": "Vertrauenswürdige",
|
||||||
|
"try_again": "Erneut versuchen",
|
||||||
"tx_commit_exception_no_dust_on_change": "Die Transaktion wird diesen Betrag abgelehnt. Mit diesen Münzen können Sie ${min} ohne Veränderung oder ${max} senden, die Änderungen zurückgeben.",
|
"tx_commit_exception_no_dust_on_change": "Die Transaktion wird diesen Betrag abgelehnt. Mit diesen Münzen können Sie ${min} ohne Veränderung oder ${max} senden, die Änderungen zurückgeben.",
|
||||||
"tx_commit_failed": "Transaktionsausschüsse ist fehlgeschlagen. Bitte wenden Sie sich an Support.",
|
"tx_commit_failed": "Transaktionsausschüsse ist fehlgeschlagen. Bitte wenden Sie sich an Support.",
|
||||||
"tx_commit_failed_no_peers": "Transaktion konnte nicht übertragen werden. Bitte versuchen Sie es in einer Sekunde oder so erneut",
|
"tx_commit_failed_no_peers": "Transaktion konnte nicht übertragen werden. Bitte versuchen Sie es in einer Sekunde oder so erneut",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK update",
|
"apk_update": "APK update",
|
||||||
"approve": "Approve",
|
"approve": "Approve",
|
||||||
"approve_request": "Approve Request",
|
"approve_request": "Approve Request",
|
||||||
|
"approve_tokens": "Approve tokens",
|
||||||
"arrive_in_this_address": "${currency} ${tag}will arrive in this address",
|
"arrive_in_this_address": "${currency} ${tag}will arrive in this address",
|
||||||
"ascending": "Ascending",
|
"ascending": "Ascending",
|
||||||
"ask_each_time": "Ask each time",
|
"ask_each_time": "Ask each time",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Descending",
|
"descending": "Descending",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"destination_tag": "Destination tag:",
|
"destination_tag": "Destination tag:",
|
||||||
|
"deuro_collect_interest": "Collect",
|
||||||
|
"deuro_savings": "dEuro Savings",
|
||||||
|
"deuro_savings_add": "Deposit",
|
||||||
|
"deuro_savings_balance": "Savings Balance",
|
||||||
|
"deuro_savings_collect_interest": "Collect interest",
|
||||||
|
"deuro_savings_remove": "Withdraw",
|
||||||
|
"deuro_savings_set_approval": "Set approval",
|
||||||
|
"deuro_savings_subtitle": "Earn up to 10% interest on your dEuro Stablecoin holdings",
|
||||||
|
"deuro_tx_commited_content": "It might take a couple of seconds for the transaction to confirm and be reflected on screen",
|
||||||
"device_is_signing": "Device is signing",
|
"device_is_signing": "Device is signing",
|
||||||
"dfx_option_description": "Buy crypto with EUR & CHF. For retail and corporate customers in Europe",
|
"dfx_option_description": "Buy crypto with EUR & CHF. For retail and corporate customers in Europe",
|
||||||
"didnt_get_code": "Didn't get code?",
|
"didnt_get_code": "Didn't get code?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "Transport Type",
|
"transport_type": "Transport Type",
|
||||||
"trongrid_history": "TronGrid history",
|
"trongrid_history": "TronGrid history",
|
||||||
"trusted": "Trusted",
|
"trusted": "Trusted",
|
||||||
|
"try_again": "Try again",
|
||||||
"tx_commit_exception_no_dust_on_change": "The transaction is rejected with this amount. With these coins you can send ${min} without change or ${max} that returns change.",
|
"tx_commit_exception_no_dust_on_change": "The transaction is rejected with this amount. With these coins you can send ${min} without change or ${max} that returns change.",
|
||||||
"tx_commit_failed": "Transaction commit failed. Please contact support.",
|
"tx_commit_failed": "Transaction commit failed. Please contact support.",
|
||||||
"tx_commit_failed_no_peers": "Transaction failed to broadcast, please try again in a second or so",
|
"tx_commit_failed_no_peers": "Transaction failed to broadcast, please try again in a second or so",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Actualización de APK",
|
"apk_update": "Actualización de APK",
|
||||||
"approve": "Aprobar",
|
"approve": "Aprobar",
|
||||||
"approve_request": "Aprobar la solicitud",
|
"approve_request": "Aprobar la solicitud",
|
||||||
|
"approve_tokens": "Aprobar tokens",
|
||||||
"arrive_in_this_address": "${currency} ${tag}llegará a esta dirección",
|
"arrive_in_this_address": "${currency} ${tag}llegará a esta dirección",
|
||||||
"ascending": "Ascendente",
|
"ascending": "Ascendente",
|
||||||
"ask_each_time": "Pregunta cada vez",
|
"ask_each_time": "Pregunta cada vez",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Descendente",
|
"descending": "Descendente",
|
||||||
"description": "Descripción",
|
"description": "Descripción",
|
||||||
"destination_tag": "Etiqueta de destino:",
|
"destination_tag": "Etiqueta de destino:",
|
||||||
|
"deuro_collect_interest": "Recolectar",
|
||||||
|
"deuro_savings": "ahorros de deuro",
|
||||||
|
"deuro_savings_add": "Depósito",
|
||||||
|
"deuro_savings_balance": "Saldo de ahorro",
|
||||||
|
"deuro_savings_collect_interest": "Cobrar interés",
|
||||||
|
"deuro_savings_remove": "Retirar",
|
||||||
|
"deuro_savings_set_approval": "Establecer aprobación",
|
||||||
|
"deuro_savings_subtitle": "Gane hasta un 10% de interés en sus Holdings de Deuro Stablecoin",
|
||||||
|
"deuro_tx_commited_content": "La transacción puede tardar un par de segundos en confirmar y reflejarse en la pantalla",
|
||||||
"device_is_signing": "El dispositivo está firmando",
|
"device_is_signing": "El dispositivo está firmando",
|
||||||
"dfx_option_description": "Compre cripto con EUR y CHF. Para clientes minoristas y corporativos en Europa",
|
"dfx_option_description": "Compre cripto con EUR y CHF. Para clientes minoristas y corporativos en Europa",
|
||||||
"didnt_get_code": "¿No recibiste el código?",
|
"didnt_get_code": "¿No recibiste el código?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "Tipo de transporte",
|
"transport_type": "Tipo de transporte",
|
||||||
"trongrid_history": "Historia trongrid",
|
"trongrid_history": "Historia trongrid",
|
||||||
"trusted": "de confianza",
|
"trusted": "de confianza",
|
||||||
|
"try_again": "Intentar otra vez",
|
||||||
"tx_commit_exception_no_dust_on_change": "La transacción se rechaza con esta cantidad. Con estas monedas puede enviar ${min} sin cambios o ${max} que devuelve el cambio.",
|
"tx_commit_exception_no_dust_on_change": "La transacción se rechaza con esta cantidad. Con estas monedas puede enviar ${min} sin cambios o ${max} que devuelve el cambio.",
|
||||||
"tx_commit_failed": "La confirmación de transacción falló. Ponte en contacto con el soporte.",
|
"tx_commit_failed": "La confirmación de transacción falló. Ponte en contacto con el soporte.",
|
||||||
"tx_commit_failed_no_peers": "La transacción no se transmitió, intenta nuevamente en un segundo más o menos",
|
"tx_commit_failed_no_peers": "La transacción no se transmitió, intenta nuevamente en un segundo más o menos",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Mise à jour d'APK",
|
"apk_update": "Mise à jour d'APK",
|
||||||
"approve": "Approuver",
|
"approve": "Approuver",
|
||||||
"approve_request": "Approuver la demande",
|
"approve_request": "Approuver la demande",
|
||||||
|
"approve_tokens": "Approuver les jetons",
|
||||||
"arrive_in_this_address": "${currency} ${tag}arrivera à cette adresse",
|
"arrive_in_this_address": "${currency} ${tag}arrivera à cette adresse",
|
||||||
"ascending": "Ascendant",
|
"ascending": "Ascendant",
|
||||||
"ask_each_time": "Demander à chaque fois",
|
"ask_each_time": "Demander à chaque fois",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Descendant",
|
"descending": "Descendant",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"destination_tag": "Tag de destination :",
|
"destination_tag": "Tag de destination :",
|
||||||
|
"deuro_collect_interest": "Collecter",
|
||||||
|
"deuro_savings": "Économies de deuro",
|
||||||
|
"deuro_savings_add": "Dépôt",
|
||||||
|
"deuro_savings_balance": "Solde d'épargne",
|
||||||
|
"deuro_savings_collect_interest": "Percevoir l'intérêt",
|
||||||
|
"deuro_savings_remove": "Retirer",
|
||||||
|
"deuro_savings_set_approval": "Établir l'approbation",
|
||||||
|
"deuro_savings_subtitle": "Gagnez jusqu'à 10% d'intérêt sur vos avoirs de Deuro Stablecoin",
|
||||||
|
"deuro_tx_commited_content": "Il pourrait prendre quelques secondes pour que la transaction confirme et soit reflétée à l'écran",
|
||||||
"device_is_signing": "L'appareil signale",
|
"device_is_signing": "L'appareil signale",
|
||||||
"dfx_option_description": "Achetez de la crypto avec EUR & CHF. Pour les clients de la vente au détail et des entreprises en Europe",
|
"dfx_option_description": "Achetez de la crypto avec EUR & CHF. Pour les clients de la vente au détail et des entreprises en Europe",
|
||||||
"didnt_get_code": "Vous n'avez pas reçu le code ?",
|
"didnt_get_code": "Vous n'avez pas reçu le code ?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "Type de transport",
|
"transport_type": "Type de transport",
|
||||||
"trongrid_history": "Histoire de la trongride",
|
"trongrid_history": "Histoire de la trongride",
|
||||||
"trusted": "de confiance",
|
"trusted": "de confiance",
|
||||||
|
"try_again": "Essayer à nouveau",
|
||||||
"tx_commit_exception_no_dust_on_change": "La transaction est rejetée avec ce montant. Avec ces pièces, vous pouvez envoyer ${min} sans changement ou ${max} qui renvoie le changement.",
|
"tx_commit_exception_no_dust_on_change": "La transaction est rejetée avec ce montant. Avec ces pièces, vous pouvez envoyer ${min} sans changement ou ${max} qui renvoie le changement.",
|
||||||
"tx_commit_failed": "La validation de la transaction a échoué. Veuillez contacter l'assistance.",
|
"tx_commit_failed": "La validation de la transaction a échoué. Veuillez contacter l'assistance.",
|
||||||
"tx_commit_failed_no_peers": "La transaction n'a pas été diffusée, veuillez réessayer dans une seconde environ",
|
"tx_commit_failed_no_peers": "La transaction n'a pas été diffusée, veuillez réessayer dans une seconde environ",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "apk sabunta",
|
"apk_update": "apk sabunta",
|
||||||
"approve": "Amincewa",
|
"approve": "Amincewa",
|
||||||
"approve_request": "Amince da bukata",
|
"approve_request": "Amince da bukata",
|
||||||
|
"approve_tokens": "Amince da Alamu",
|
||||||
"arrive_in_this_address": "${currency} ${tag} zai je wurin wannan adireshi",
|
"arrive_in_this_address": "${currency} ${tag} zai je wurin wannan adireshi",
|
||||||
"ascending": "Hau",
|
"ascending": "Hau",
|
||||||
"ask_each_time": "Tambaya kowane lokaci",
|
"ask_each_time": "Tambaya kowane lokaci",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Saukowa",
|
"descending": "Saukowa",
|
||||||
"description": "Bayani",
|
"description": "Bayani",
|
||||||
"destination_tag": "Tambarin makoma:",
|
"destination_tag": "Tambarin makoma:",
|
||||||
|
"deuro_collect_interest": "Tara",
|
||||||
|
"deuro_savings": "deuro tanadi",
|
||||||
|
"deuro_savings_add": "Yi ajiya",
|
||||||
|
"deuro_savings_balance": "Ma'auni",
|
||||||
|
"deuro_savings_collect_interest": "Tattara amfani da sha'awa",
|
||||||
|
"deuro_savings_remove": "Janye",
|
||||||
|
"deuro_savings_set_approval": "Saita yarda",
|
||||||
|
"deuro_savings_subtitle": "Sami har zuwa 10% sha'awa a kan Deuro Stovecoin Rike",
|
||||||
|
"deuro_tx_commited_content": "Yana iya ɗaukar wasu secondsan seconds don ma'amala don tabbatarwa kuma a nuna shi a allon",
|
||||||
"device_is_signing": "Na'urar tana shiga",
|
"device_is_signing": "Na'urar tana shiga",
|
||||||
"dfx_option_description": "Buy crypto tare da Eur & Chf. Don Retail da abokan ciniki na kamfanoni a Turai",
|
"dfx_option_description": "Buy crypto tare da Eur & Chf. Don Retail da abokan ciniki na kamfanoni a Turai",
|
||||||
"didnt_get_code": "Ba a samun code?",
|
"didnt_get_code": "Ba a samun code?",
|
||||||
|
@ -977,6 +987,7 @@
|
||||||
"transport_type": "Nau'in sufuri",
|
"transport_type": "Nau'in sufuri",
|
||||||
"trongrid_history": "Tarihin Trongrid",
|
"trongrid_history": "Tarihin Trongrid",
|
||||||
"trusted": "Amintacce",
|
"trusted": "Amintacce",
|
||||||
|
"try_again": "Gwada kuma",
|
||||||
"tx_commit_exception_no_dust_on_change": "An ƙi ma'amala da wannan adadin. Tare da waɗannan tsabar kudi Zaka iya aika ${min}, ba tare da canji ba ko ${max} wanda ya dawo canzawa.",
|
"tx_commit_exception_no_dust_on_change": "An ƙi ma'amala da wannan adadin. Tare da waɗannan tsabar kudi Zaka iya aika ${min}, ba tare da canji ba ko ${max} wanda ya dawo canzawa.",
|
||||||
"tx_commit_failed": "Ma'amala ya kasa. Da fatan za a tuntuɓi goyan baya.",
|
"tx_commit_failed": "Ma'amala ya kasa. Da fatan za a tuntuɓi goyan baya.",
|
||||||
"tx_commit_failed_no_peers": "Kasuwanci ya kasa watsa, don Allah sake gwadawa a cikin na biyu ko",
|
"tx_commit_failed_no_peers": "Kasuwanci ya kasa watsa, don Allah sake gwadawa a cikin na biyu ko",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK अद्यतन",
|
"apk_update": "APK अद्यतन",
|
||||||
"approve": "मंज़ूरी देना",
|
"approve": "मंज़ूरी देना",
|
||||||
"approve_request": "अनुरोध को स्वीकृत करें",
|
"approve_request": "अनुरोध को स्वीकृत करें",
|
||||||
|
"approve_tokens": "टोकन को मंजूरी देना",
|
||||||
"arrive_in_this_address": "${currency} ${tag}इस पते पर पहुंचेंगे",
|
"arrive_in_this_address": "${currency} ${tag}इस पते पर पहुंचेंगे",
|
||||||
"ascending": "आरोही",
|
"ascending": "आरोही",
|
||||||
"ask_each_time": "हर बार पूछें",
|
"ask_each_time": "हर बार पूछें",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "अवरोही",
|
"descending": "अवरोही",
|
||||||
"description": "विवरण",
|
"description": "विवरण",
|
||||||
"destination_tag": "गंतव्य टैग:",
|
"destination_tag": "गंतव्य टैग:",
|
||||||
|
"deuro_collect_interest": "इकट्ठा करना",
|
||||||
|
"deuro_savings": "देउरो बचत",
|
||||||
|
"deuro_savings_add": "जमा",
|
||||||
|
"deuro_savings_balance": "बचत शेष",
|
||||||
|
"deuro_savings_collect_interest": "ब्याज इकट्ठा करना",
|
||||||
|
"deuro_savings_remove": "निकालना",
|
||||||
|
"deuro_savings_set_approval": "अनुमोदन निर्धारित करना",
|
||||||
|
"deuro_savings_subtitle": "अपने Deuro Stablecoin होल्डिंग्स पर 10% ब्याज कमाएँ",
|
||||||
|
"deuro_tx_commited_content": "लेन -देन की पुष्टि करने और स्क्रीन पर प्रतिबिंबित होने के लिए कुछ सेकंड लग सकते हैं",
|
||||||
"device_is_signing": "उपकरण हस्ताक्षर कर रहा है",
|
"device_is_signing": "उपकरण हस्ताक्षर कर रहा है",
|
||||||
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
|
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
|
||||||
"didnt_get_code": "कोड नहीं मिला?",
|
"didnt_get_code": "कोड नहीं मिला?",
|
||||||
|
@ -977,6 +987,7 @@
|
||||||
"transport_type": "परिवहन प्रकार",
|
"transport_type": "परिवहन प्रकार",
|
||||||
"trongrid_history": "ट्रॉन्ग्रिड का इतिहास",
|
"trongrid_history": "ट्रॉन्ग्रिड का इतिहास",
|
||||||
"trusted": "भरोसा",
|
"trusted": "भरोसा",
|
||||||
|
"try_again": "पुनः प्रयास करें",
|
||||||
"tx_commit_exception_no_dust_on_change": "लेनदेन को इस राशि से खारिज कर दिया जाता है। इन सिक्कों के साथ आप चेंज या ${min} के बिना ${max} को भेज सकते हैं जो परिवर्तन लौटाता है।",
|
"tx_commit_exception_no_dust_on_change": "लेनदेन को इस राशि से खारिज कर दिया जाता है। इन सिक्कों के साथ आप चेंज या ${min} के बिना ${max} को भेज सकते हैं जो परिवर्तन लौटाता है।",
|
||||||
"tx_commit_failed": "लेन -देन प्रतिबद्ध विफल। कृपया संपर्क समर्थन करें।",
|
"tx_commit_failed": "लेन -देन प्रतिबद्ध विफल। कृपया संपर्क समर्थन करें।",
|
||||||
"tx_commit_failed_no_peers": "लेन -देन प्रसारित करने में विफल रहा, कृपया एक या दो सेकंड में पुनः प्रयास करें",
|
"tx_commit_failed_no_peers": "लेन -देन प्रसारित करने में विफल रहा, कृपया एक या दो सेकंड में पुनः प्रयास करें",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK ažuriranje",
|
"apk_update": "APK ažuriranje",
|
||||||
"approve": "Odobriti",
|
"approve": "Odobriti",
|
||||||
"approve_request": "Odobriti zahtjev",
|
"approve_request": "Odobriti zahtjev",
|
||||||
|
"approve_tokens": "Odobriti tokene",
|
||||||
"arrive_in_this_address": "${currency} ${tag}će stići na ovu adresu",
|
"arrive_in_this_address": "${currency} ${tag}će stići na ovu adresu",
|
||||||
"ascending": "Uzlazni",
|
"ascending": "Uzlazni",
|
||||||
"ask_each_time": "Pitajte svaki put",
|
"ask_each_time": "Pitajte svaki put",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Silazni",
|
"descending": "Silazni",
|
||||||
"description": "Opis",
|
"description": "Opis",
|
||||||
"destination_tag": "Odredišna oznaka:",
|
"destination_tag": "Odredišna oznaka:",
|
||||||
|
"deuro_collect_interest": "Prikupiti",
|
||||||
|
"deuro_savings": "deuro ušteda",
|
||||||
|
"deuro_savings_add": "Depozit",
|
||||||
|
"deuro_savings_balance": "Ravnoteža uštede",
|
||||||
|
"deuro_savings_collect_interest": "Prikupiti interes",
|
||||||
|
"deuro_savings_remove": "Povući",
|
||||||
|
"deuro_savings_set_approval": "Odrediti odobrenje",
|
||||||
|
"deuro_savings_subtitle": "Zaradite do 10% kamate na svoje Deuro Stablecoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Možda će trebati nekoliko sekundi da se transakcija potvrdi i odrazi na zaslonu",
|
||||||
"device_is_signing": "Uređaj se potpisuje",
|
"device_is_signing": "Uređaj se potpisuje",
|
||||||
"dfx_option_description": "Kupite kriptovalute s Eur & CHF. Za maloprodajne i korporativne kupce u Europi",
|
"dfx_option_description": "Kupite kriptovalute s Eur & CHF. Za maloprodajne i korporativne kupce u Europi",
|
||||||
"didnt_get_code": "Ne dobivate kod?",
|
"didnt_get_code": "Ne dobivate kod?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "Transportni tip",
|
"transport_type": "Transportni tip",
|
||||||
"trongrid_history": "Povijest Trongrida",
|
"trongrid_history": "Povijest Trongrida",
|
||||||
"trusted": "vjerovao",
|
"trusted": "vjerovao",
|
||||||
|
"try_again": "Pokušajte ponovo",
|
||||||
"tx_commit_exception_no_dust_on_change": "Transakcija se odbija s tim iznosom. Pomoću ovih kovanica možete poslati ${min} bez promjene ili ${max} koja vraća promjenu.",
|
"tx_commit_exception_no_dust_on_change": "Transakcija se odbija s tim iznosom. Pomoću ovih kovanica možete poslati ${min} bez promjene ili ${max} koja vraća promjenu.",
|
||||||
"tx_commit_failed": "Obveza transakcije nije uspjela. Molimo kontaktirajte podršku.",
|
"tx_commit_failed": "Obveza transakcije nije uspjela. Molimo kontaktirajte podršku.",
|
||||||
"tx_commit_failed_no_peers": "Transakcija nije uspjela emitirati, pokušajte ponovo u sekundi ili tako",
|
"tx_commit_failed_no_peers": "Transakcija nije uspjela emitirati, pokušajte ponovo u sekundi ili tako",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK թարմացում",
|
"apk_update": "APK թարմացում",
|
||||||
"approve": "Հաստատել",
|
"approve": "Հաստատել",
|
||||||
"approve_request": "Հաստատում է հայցը",
|
"approve_request": "Հաստատում է հայցը",
|
||||||
|
"approve_tokens": "Հաստատում է նշանները",
|
||||||
"arrive_in_this_address": "${currency} ${tag}կժամանի այս հասցեում",
|
"arrive_in_this_address": "${currency} ${tag}կժամանի այս հասցեում",
|
||||||
"ascending": "Աճող",
|
"ascending": "Աճող",
|
||||||
"ask_each_time": "Հարցնել ամեն անգամ",
|
"ask_each_time": "Հարցնել ամեն անգամ",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Նվազող",
|
"descending": "Նվազող",
|
||||||
"description": "Նկարագրություն",
|
"description": "Նկարագրություն",
|
||||||
"destination_tag": "Նպատակակետի պիտակ:",
|
"destination_tag": "Նպատակակետի պիտակ:",
|
||||||
|
"deuro_collect_interest": "Հավաքել",
|
||||||
|
"deuro_savings": "dEuro խնայողություններ",
|
||||||
|
"deuro_savings_add": "Ավանդ",
|
||||||
|
"deuro_savings_balance": "Խնայողական հավասարակշռություն",
|
||||||
|
"deuro_savings_collect_interest": "Հավաքեք հետաքրքրություն",
|
||||||
|
"deuro_savings_remove": "Հեռացնել",
|
||||||
|
"deuro_savings_set_approval": "Սահմանել հաստատում",
|
||||||
|
"deuro_savings_subtitle": "Վաստակեք մինչեւ 10% տոկոսադրույքներ ձեր Deuro Stablecoin Holdings- ի համար",
|
||||||
|
"deuro_tx_commited_content": "Գործարքի հաստատման եւ արտացոլվելու համար գործարքի համար կարող է տեւել մի քանի վայրկյան",
|
||||||
"device_is_signing": "Սարքը ստորագրում է",
|
"device_is_signing": "Սարքը ստորագրում է",
|
||||||
"dfx_option_description": "Գնեք կրիպտոարժույթ EUR և CHF: Կորպորատիվ և մանրածախ հաճախորդների համար Եվրոպայում",
|
"dfx_option_description": "Գնեք կրիպտոարժույթ EUR և CHF: Կորպորատիվ և մանրածախ հաճախորդների համար Եվրոպայում",
|
||||||
"didnt_get_code": "Չեք ստացել կոդը?",
|
"didnt_get_code": "Չեք ստացել կոդը?",
|
||||||
|
@ -973,6 +983,7 @@
|
||||||
"transport_type": "Տրանսպորտի տեսակը",
|
"transport_type": "Տրանսպորտի տեսակը",
|
||||||
"trongrid_history": "TronGrid պատմություն",
|
"trongrid_history": "TronGrid պատմություն",
|
||||||
"trusted": "Վստահելի",
|
"trusted": "Վստահելի",
|
||||||
|
"try_again": "Կրկին փորձեք",
|
||||||
"tx_commit_exception_no_dust_on_change": "Փոխանցումը մերժվել է այս գումարով: Այս արժույթներով կարող եք ուղարկել ${min} առանց փոփոխության կամ ${max} որը վերադարձնում է փոփոխությունը",
|
"tx_commit_exception_no_dust_on_change": "Փոխանցումը մերժվել է այս գումարով: Այս արժույթներով կարող եք ուղարկել ${min} առանց փոփոխության կամ ${max} որը վերադարձնում է փոփոխությունը",
|
||||||
"tx_commit_failed": "Փոխանցումը ձախողվել է: Խնդրում ենք դիմել աջակցությանը",
|
"tx_commit_failed": "Փոխանցումը ձախողվել է: Խնդրում ենք դիմել աջակցությանը",
|
||||||
"tx_commit_failed_no_peers": "Գործարքը չի հաջողվել հեռարձակել, խնդրում ենք կրկին փորձել մեկ վայրկյանում",
|
"tx_commit_failed_no_peers": "Գործարքը չի հաջողվել հեռարձակել, խնդրում ենք կրկին փորձել մեկ վայրկյանում",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Pembaruan APK",
|
"apk_update": "Pembaruan APK",
|
||||||
"approve": "Menyetujui",
|
"approve": "Menyetujui",
|
||||||
"approve_request": "Menyetujui permintaan",
|
"approve_request": "Menyetujui permintaan",
|
||||||
|
"approve_tokens": "Menyetujui token",
|
||||||
"arrive_in_this_address": "${currency} ${tag} akan tiba di alamat ini",
|
"arrive_in_this_address": "${currency} ${tag} akan tiba di alamat ini",
|
||||||
"ascending": "Naik",
|
"ascending": "Naik",
|
||||||
"ask_each_time": "Tanyakan setiap kali",
|
"ask_each_time": "Tanyakan setiap kali",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Menurun",
|
"descending": "Menurun",
|
||||||
"description": "Keterangan",
|
"description": "Keterangan",
|
||||||
"destination_tag": "Tag tujuan:",
|
"destination_tag": "Tag tujuan:",
|
||||||
|
"deuro_collect_interest": "Mengumpulkan",
|
||||||
|
"deuro_savings": "Tabungan dEuro",
|
||||||
|
"deuro_savings_add": "Deposito",
|
||||||
|
"deuro_savings_balance": "Keseimbangan tabungan",
|
||||||
|
"deuro_savings_collect_interest": "Mengumpulkan minat",
|
||||||
|
"deuro_savings_remove": "Menarik",
|
||||||
|
"deuro_savings_set_approval": "Tetapkan persetujuan",
|
||||||
|
"deuro_savings_subtitle": "Hasilkan hingga 10% bunga di Deuro Stablecoin Holdings Anda",
|
||||||
|
"deuro_tx_commited_content": "Mungkin butuh beberapa detik untuk transaksi untuk mengkonfirmasi dan direfleksikan di layar",
|
||||||
"device_is_signing": "Perangkat sedang menandatangani",
|
"device_is_signing": "Perangkat sedang menandatangani",
|
||||||
"dfx_option_description": "Beli crypto dengan EUR & CHF. Untuk pelanggan ritel dan perusahaan di Eropa",
|
"dfx_option_description": "Beli crypto dengan EUR & CHF. Untuk pelanggan ritel dan perusahaan di Eropa",
|
||||||
"didnt_get_code": "Tidak mendapatkan kode?",
|
"didnt_get_code": "Tidak mendapatkan kode?",
|
||||||
|
@ -978,6 +988,7 @@
|
||||||
"transport_type": "Jenis transportasi",
|
"transport_type": "Jenis transportasi",
|
||||||
"trongrid_history": "Sejarah Trongrid",
|
"trongrid_history": "Sejarah Trongrid",
|
||||||
"trusted": "Dipercayai",
|
"trusted": "Dipercayai",
|
||||||
|
"try_again": "Coba lagi",
|
||||||
"tx_commit_exception_no_dust_on_change": "Transaksi ditolak dengan jumlah ini. Dengan koin ini Anda dapat mengirim ${min} tanpa perubahan atau ${max} yang mengembalikan perubahan.",
|
"tx_commit_exception_no_dust_on_change": "Transaksi ditolak dengan jumlah ini. Dengan koin ini Anda dapat mengirim ${min} tanpa perubahan atau ${max} yang mengembalikan perubahan.",
|
||||||
"tx_commit_failed": "Transaksi Gagal. Silakan hubungi Dukungan.",
|
"tx_commit_failed": "Transaksi Gagal. Silakan hubungi Dukungan.",
|
||||||
"tx_commit_failed_no_peers": "Transaksi gagal untuk disiarkan, silakan coba lagi sebentar lagi",
|
"tx_commit_failed_no_peers": "Transaksi gagal untuk disiarkan, silakan coba lagi sebentar lagi",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Aggiornamento APK",
|
"apk_update": "Aggiornamento APK",
|
||||||
"approve": "Approvare",
|
"approve": "Approvare",
|
||||||
"approve_request": "Approvare la richiesta",
|
"approve_request": "Approvare la richiesta",
|
||||||
|
"approve_tokens": "Approvare i token",
|
||||||
"arrive_in_this_address": "${currency} ${tag}arriverà a questo indirizzo",
|
"arrive_in_this_address": "${currency} ${tag}arriverà a questo indirizzo",
|
||||||
"ascending": "Ascendente",
|
"ascending": "Ascendente",
|
||||||
"ask_each_time": "Chiedi ogni volta",
|
"ask_each_time": "Chiedi ogni volta",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Discendente",
|
"descending": "Discendente",
|
||||||
"description": "Descrizione",
|
"description": "Descrizione",
|
||||||
"destination_tag": "Tag destinazione:",
|
"destination_tag": "Tag destinazione:",
|
||||||
|
"deuro_collect_interest": "Raccogliere",
|
||||||
|
"deuro_savings": "Risparmio di dEuro",
|
||||||
|
"deuro_savings_add": "Depositare",
|
||||||
|
"deuro_savings_balance": "Saldo di risparmio",
|
||||||
|
"deuro_savings_collect_interest": "Raccogliere interesse",
|
||||||
|
"deuro_savings_remove": "Ritirare",
|
||||||
|
"deuro_savings_set_approval": "Impostare l'approvazione",
|
||||||
|
"deuro_savings_subtitle": "Guadagna fino al 10% di interesse su Deuro StableCoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Potrebbero essere necessari un paio di secondi per confermare la transazione ed essere riflessa sullo schermo",
|
||||||
"device_is_signing": "Il dispositivo sta firmando",
|
"device_is_signing": "Il dispositivo sta firmando",
|
||||||
"dfx_option_description": "Acquista Crypto con EUR & CHF. Per i clienti al dettaglio e aziendali in Europa",
|
"dfx_option_description": "Acquista Crypto con EUR & CHF. Per i clienti al dettaglio e aziendali in Europa",
|
||||||
"didnt_get_code": "Non hai ricevuto il codice?",
|
"didnt_get_code": "Non hai ricevuto il codice?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "Tipo di trasporto",
|
"transport_type": "Tipo di trasporto",
|
||||||
"trongrid_history": "Cronologia TronGrid",
|
"trongrid_history": "Cronologia TronGrid",
|
||||||
"trusted": "Fidato",
|
"trusted": "Fidato",
|
||||||
|
"try_again": "Riprova",
|
||||||
"tx_commit_exception_no_dust_on_change": "La transazione viene respinta con questo importo. Con queste monete è possibile inviare ${min} senza modifiche o ${max} che restituisce il cambiamento.",
|
"tx_commit_exception_no_dust_on_change": "La transazione viene respinta con questo importo. Con queste monete è possibile inviare ${min} senza modifiche o ${max} che restituisce il cambiamento.",
|
||||||
"tx_commit_failed": "Commit di transazione non riuscita. Si prega di contattare il supporto.",
|
"tx_commit_failed": "Commit di transazione non riuscita. Si prega di contattare il supporto.",
|
||||||
"tx_commit_failed_no_peers": "Errore nella trasmissione della transazione, si prega di provare nuovamente",
|
"tx_commit_failed_no_peers": "Errore nella trasmissione della transazione, si prega di provare nuovamente",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APKアップデート",
|
"apk_update": "APKアップデート",
|
||||||
"approve": "承認する",
|
"approve": "承認する",
|
||||||
"approve_request": "リクエストを承認します",
|
"approve_request": "リクエストを承認します",
|
||||||
|
"approve_tokens": "トークンを承認します",
|
||||||
"arrive_in_this_address": "${currency} ${tag}はこの住所に到着します",
|
"arrive_in_this_address": "${currency} ${tag}はこの住所に到着します",
|
||||||
"ascending": "上昇",
|
"ascending": "上昇",
|
||||||
"ask_each_time": "毎回尋ねてください",
|
"ask_each_time": "毎回尋ねてください",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "下降",
|
"descending": "下降",
|
||||||
"description": "説明",
|
"description": "説明",
|
||||||
"destination_tag": "宛先タグ:",
|
"destination_tag": "宛先タグ:",
|
||||||
|
"deuro_collect_interest": "集める",
|
||||||
|
"deuro_savings": "dEuro Savings",
|
||||||
|
"deuro_savings_add": "デポジット",
|
||||||
|
"deuro_savings_balance": "貯蓄バランス",
|
||||||
|
"deuro_savings_collect_interest": "興味を集めます",
|
||||||
|
"deuro_savings_remove": "撤回する",
|
||||||
|
"deuro_savings_set_approval": "承認を設定します",
|
||||||
|
"deuro_savings_subtitle": "Deuro Stablecoin Holdingsで最大10%の利息を稼ぐ",
|
||||||
|
"deuro_tx_commited_content": "トランザクションが確認され、画面に反映されるまでに数秒かかる場合があります",
|
||||||
"device_is_signing": "デバイスが署名しています",
|
"device_is_signing": "デバイスが署名しています",
|
||||||
"dfx_option_description": "EUR&CHFで暗号を購入します。ヨーロッパの小売および企業の顧客向け",
|
"dfx_option_description": "EUR&CHFで暗号を購入します。ヨーロッパの小売および企業の顧客向け",
|
||||||
"didnt_get_code": "コードを取得しませんか?",
|
"didnt_get_code": "コードを取得しませんか?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "輸送タイプ",
|
"transport_type": "輸送タイプ",
|
||||||
"trongrid_history": "トロンリッドの歴史",
|
"trongrid_history": "トロンリッドの歴史",
|
||||||
"trusted": "信頼できる",
|
"trusted": "信頼できる",
|
||||||
|
"try_again": "もう一度やり直してください",
|
||||||
"tx_commit_exception_no_dust_on_change": "この金額ではトランザクションは拒否されます。 これらのコインを使用すると、おつりなしの ${min} またはおつりを返す ${max} を送信できます。",
|
"tx_commit_exception_no_dust_on_change": "この金額ではトランザクションは拒否されます。 これらのコインを使用すると、おつりなしの ${min} またはおつりを返す ${max} を送信できます。",
|
||||||
"tx_commit_failed": "トランザクションコミットは失敗しました。サポートに連絡してください。",
|
"tx_commit_failed": "トランザクションコミットは失敗しました。サポートに連絡してください。",
|
||||||
"tx_commit_failed_no_peers": "トランザクションはブロードキャストに失敗しました。一瞬かそこらで再試行してください",
|
"tx_commit_failed_no_peers": "トランザクションはブロードキャストに失敗しました。一瞬かそこらで再試行してください",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK 업데이트",
|
"apk_update": "APK 업데이트",
|
||||||
"approve": "승인",
|
"approve": "승인",
|
||||||
"approve_request": "요청 승인",
|
"approve_request": "요청 승인",
|
||||||
|
"approve_tokens": "토큰을 승인합니다",
|
||||||
"arrive_in_this_address": "${currency} ${tag}이(가) 이 주소로 도착합니다",
|
"arrive_in_this_address": "${currency} ${tag}이(가) 이 주소로 도착합니다",
|
||||||
"ascending": "오름차순",
|
"ascending": "오름차순",
|
||||||
"ask_each_time": "매번 묻기",
|
"ask_each_time": "매번 묻기",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "내림차순",
|
"descending": "내림차순",
|
||||||
"description": "설명",
|
"description": "설명",
|
||||||
"destination_tag": "목적지 태그:",
|
"destination_tag": "목적지 태그:",
|
||||||
|
"deuro_collect_interest": "모으다",
|
||||||
|
"deuro_savings": "도로 저축",
|
||||||
|
"deuro_savings_add": "보증금",
|
||||||
|
"deuro_savings_balance": "저축 잔고",
|
||||||
|
"deuro_savings_collect_interest": "관심을 모으십시오",
|
||||||
|
"deuro_savings_remove": "철회하다",
|
||||||
|
"deuro_savings_set_approval": "승인을 설정하십시오",
|
||||||
|
"deuro_savings_subtitle": "Deuro Stablecoin Holdings에 최대 10%의이자를 받으십시오.",
|
||||||
|
"deuro_tx_commited_content": "트랜잭션이 확인하고 화면에 반영되는 데 몇 초가 걸릴 수 있습니다.",
|
||||||
"device_is_signing": "장치가 서명 중입니다",
|
"device_is_signing": "장치가 서명 중입니다",
|
||||||
"dfx_option_description": "EUR 및 CHF로 암호화폐 구매. 유럽의 개인 및 기업 고객 대상",
|
"dfx_option_description": "EUR 및 CHF로 암호화폐 구매. 유럽의 개인 및 기업 고객 대상",
|
||||||
"didnt_get_code": "코드를 받지 못했나요?",
|
"didnt_get_code": "코드를 받지 못했나요?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "전송 유형",
|
"transport_type": "전송 유형",
|
||||||
"trongrid_history": "TronGrid 내역",
|
"trongrid_history": "TronGrid 내역",
|
||||||
"trusted": "신뢰됨",
|
"trusted": "신뢰됨",
|
||||||
|
"try_again": "다시 시도하십시오",
|
||||||
"tx_commit_exception_no_dust_on_change": "이 금액으로는 트랜잭션이 거부됩니다. 이 코인으로는 잔돈 없이 ${min}을(를) 보내거나 잔돈이 반환되는 ${max}을(를) 보낼 수 있습니다.",
|
"tx_commit_exception_no_dust_on_change": "이 금액으로는 트랜잭션이 거부됩니다. 이 코인으로는 잔돈 없이 ${min}을(를) 보내거나 잔돈이 반환되는 ${max}을(를) 보낼 수 있습니다.",
|
||||||
"tx_commit_failed": "트랜잭션 커밋 실패. 지원팀에 문의하세요.",
|
"tx_commit_failed": "트랜잭션 커밋 실패. 지원팀에 문의하세요.",
|
||||||
"tx_commit_failed_no_peers": "트랜잭션 전파 실패. 잠시 후 다시 시도하세요.",
|
"tx_commit_failed_no_peers": "트랜잭션 전파 실패. 잠시 후 다시 시도하세요.",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK အပ်ဒိတ်",
|
"apk_update": "APK အပ်ဒိတ်",
|
||||||
"approve": "လက်မခံပါ။",
|
"approve": "လက်မခံပါ။",
|
||||||
"approve_request": "တောင်းဆိုမှုကိုအတည်ပြု",
|
"approve_request": "တောင်းဆိုမှုကိုအတည်ပြု",
|
||||||
|
"approve_tokens": "တိုကင်အတည်ပြု",
|
||||||
"arrive_in_this_address": "${currency} ${tag}ဤလိပ်စာသို့ ရောက်ရှိပါမည်။",
|
"arrive_in_this_address": "${currency} ${tag}ဤလိပ်စာသို့ ရောက်ရှိပါမည်။",
|
||||||
"ascending": "တက်",
|
"ascending": "တက်",
|
||||||
"ask_each_time": "တစ်ခုချင်းစီကိုအချိန်မေးပါ",
|
"ask_each_time": "တစ်ခုချင်းစီကိုအချိန်မေးပါ",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "ဆင်း",
|
"descending": "ဆင်း",
|
||||||
"description": "ဖော်ပြချက်",
|
"description": "ဖော်ပြချက်",
|
||||||
"destination_tag": "ခရီးဆုံးအမှတ်-",
|
"destination_tag": "ခရီးဆုံးအမှတ်-",
|
||||||
|
"deuro_collect_interest": "စုဝေး",
|
||||||
|
"deuro_savings": "dEuro ငွေစု",
|
||||||
|
"deuro_savings_add": "အပ်ငေှ",
|
||||||
|
"deuro_savings_balance": "ငွေစုချိန်ခွင်လျှာ",
|
||||||
|
"deuro_savings_collect_interest": "အကျိုးစီးပွားစုဆောင်းပါ",
|
||||||
|
"deuro_savings_remove": "ဆုတ်ခွာ",
|
||||||
|
"deuro_savings_set_approval": "အတည်ပြုချက်ကိုသတ်မှတ်ပါ",
|
||||||
|
"deuro_savings_subtitle": "သင်၏ Deuro Stabloin Holdings တွင် 10% အထိစိတ်ဝင်စားပါ",
|
||||||
|
"deuro_tx_commited_content": "၎င်းသည်ငွေပေးငွေယူကိုအတည်ပြုရန်နှင့်မျက်နှာပြင်ပေါ်တွင်ထင်ဟပ်ရန်စက္ကန့်အနည်းငယ်ကြာနိုင်သည်",
|
||||||
"device_is_signing": "ကိရိယာလက်မှတ်ထိုးနေသည်",
|
"device_is_signing": "ကိရိယာလက်မှတ်ထိုးနေသည်",
|
||||||
"dfx_option_description": "Crypto ကို EUR & CHF ဖြင့် 0 ယ်ပါ။ လက်လီရောင်းဝယ်မှုနှင့်ဥရောပရှိကော်ပိုရိတ်ဖောက်သည်များအတွက်",
|
"dfx_option_description": "Crypto ကို EUR & CHF ဖြင့် 0 ယ်ပါ။ လက်လီရောင်းဝယ်မှုနှင့်ဥရောပရှိကော်ပိုရိတ်ဖောက်သည်များအတွက်",
|
||||||
"didnt_get_code": "ကုဒ်ကို မရဘူးလား?",
|
"didnt_get_code": "ကုဒ်ကို မရဘူးလား?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "သယ်ယူပို့ဆောင်ရေးအမျိုးအစား",
|
"transport_type": "သယ်ယူပို့ဆောင်ရေးအမျိုးအစား",
|
||||||
"trongrid_history": "Trongrid သမိုင်း",
|
"trongrid_history": "Trongrid သမိုင်း",
|
||||||
"trusted": "ယုံတယ်။",
|
"trusted": "ယုံတယ်။",
|
||||||
|
"try_again": "ထပ်ကြိုးစားပါ",
|
||||||
"tx_commit_exception_no_dust_on_change": "အဆိုပါငွေပေးငွေယူကဒီပမာဏနှင့်အတူပယ်ချခံရသည်။ ဤဒင်္ဂါးပြားများနှင့်အတူပြောင်းလဲမှုကိုပြန်လည်ပြောင်းလဲခြင်းသို့မဟုတ် ${min} မပါဘဲ ${max} ပေးပို့နိုင်သည်။",
|
"tx_commit_exception_no_dust_on_change": "အဆိုပါငွေပေးငွေယူကဒီပမာဏနှင့်အတူပယ်ချခံရသည်။ ဤဒင်္ဂါးပြားများနှင့်အတူပြောင်းလဲမှုကိုပြန်လည်ပြောင်းလဲခြင်းသို့မဟုတ် ${min} မပါဘဲ ${max} ပေးပို့နိုင်သည်။",
|
||||||
"tx_commit_failed": "ငွေပေးငွေယူကျူးလွန်မှုပျက်ကွက်။ ကျေးဇူးပြုပြီးပံ့ပိုးမှုဆက်သွယ်ပါ။",
|
"tx_commit_failed": "ငွေပေးငွေယူကျူးလွန်မှုပျက်ကွက်။ ကျေးဇူးပြုပြီးပံ့ပိုးမှုဆက်သွယ်ပါ။",
|
||||||
"tx_commit_failed_no_peers": "ငွေပေးငွေယူထုတ်လွှင့်ရန်ပျက်ကွက်ပါက ကျေးဇူးပြု. ဒုတိယသို့မဟုတ်ထိုအတိုင်းထပ်မံကြိုးစားပါ",
|
"tx_commit_failed_no_peers": "ငွေပေးငွေယူထုတ်လွှင့်ရန်ပျက်ကွက်ပါက ကျေးဇူးပြု. ဒုတိယသို့မဟုတ်ထိုအတိုင်းထပ်မံကြိုးစားပါ",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK-update",
|
"apk_update": "APK-update",
|
||||||
"approve": "Goedkeuren",
|
"approve": "Goedkeuren",
|
||||||
"approve_request": "Het verzoek goedkeuren",
|
"approve_request": "Het verzoek goedkeuren",
|
||||||
|
"approve_tokens": "Tokens goedkeuren",
|
||||||
"arrive_in_this_address": "${currency} ${tag}komt aan op dit adres",
|
"arrive_in_this_address": "${currency} ${tag}komt aan op dit adres",
|
||||||
"ascending": "Stijgend",
|
"ascending": "Stijgend",
|
||||||
"ask_each_time": "Vraag het elke keer",
|
"ask_each_time": "Vraag het elke keer",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Aflopend",
|
"descending": "Aflopend",
|
||||||
"description": "Beschrijving",
|
"description": "Beschrijving",
|
||||||
"destination_tag": "Bestemmingstag:",
|
"destination_tag": "Bestemmingstag:",
|
||||||
|
"deuro_collect_interest": "Verzamelen",
|
||||||
|
"deuro_savings": "dEuro -besparingen",
|
||||||
|
"deuro_savings_add": "Borg",
|
||||||
|
"deuro_savings_balance": "Spaarbalans",
|
||||||
|
"deuro_savings_collect_interest": "Verzamel interesse",
|
||||||
|
"deuro_savings_remove": "Terugtrekken",
|
||||||
|
"deuro_savings_set_approval": "Goedkeuring instellen",
|
||||||
|
"deuro_savings_subtitle": "Verdien tot 10% rente op uw Deuro Stablecoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Het kan een paar seconden duren voordat de transactie wordt bevestigd en weerspiegeld op het scherm",
|
||||||
"device_is_signing": "Apparaat ondertekent",
|
"device_is_signing": "Apparaat ondertekent",
|
||||||
"dfx_option_description": "Koop crypto met EUR & CHF. Voor retail- en zakelijke klanten in Europa",
|
"dfx_option_description": "Koop crypto met EUR & CHF. Voor retail- en zakelijke klanten in Europa",
|
||||||
"didnt_get_code": "Geen code?",
|
"didnt_get_code": "Geen code?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "Transporttype",
|
"transport_type": "Transporttype",
|
||||||
"trongrid_history": "Trongrid geschiedenis",
|
"trongrid_history": "Trongrid geschiedenis",
|
||||||
"trusted": "vertrouwd",
|
"trusted": "vertrouwd",
|
||||||
|
"try_again": "Probeer het opnieuw",
|
||||||
"tx_commit_exception_no_dust_on_change": "De transactie wordt afgewezen met dit bedrag. Met deze munten kunt u ${min} verzenden zonder verandering of ${max} die wijziging retourneert.",
|
"tx_commit_exception_no_dust_on_change": "De transactie wordt afgewezen met dit bedrag. Met deze munten kunt u ${min} verzenden zonder verandering of ${max} die wijziging retourneert.",
|
||||||
"tx_commit_failed": "Transactiebewissing is mislukt. Neem contact op met de ondersteuning.",
|
"tx_commit_failed": "Transactiebewissing is mislukt. Neem contact op met de ondersteuning.",
|
||||||
"tx_commit_failed_no_peers": "De transactie is niet uitgezonden, probeer het opnieuw binnen een seconde of zo",
|
"tx_commit_failed_no_peers": "De transactie is niet uitgezonden, probeer het opnieuw binnen een seconde of zo",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Aktualizacja APK",
|
"apk_update": "Aktualizacja APK",
|
||||||
"approve": "Zatwierdzić",
|
"approve": "Zatwierdzić",
|
||||||
"approve_request": "Zatwierdzić żądanie",
|
"approve_request": "Zatwierdzić żądanie",
|
||||||
|
"approve_tokens": "Zatwierdzić tokeny",
|
||||||
"arrive_in_this_address": "${currency} ${tag}dotrze na ten adres",
|
"arrive_in_this_address": "${currency} ${tag}dotrze na ten adres",
|
||||||
"ascending": "Wznoszący się",
|
"ascending": "Wznoszący się",
|
||||||
"ask_each_time": "Zapytaj za każdym razem",
|
"ask_each_time": "Zapytaj za każdym razem",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Malejąco",
|
"descending": "Malejąco",
|
||||||
"description": "Opis",
|
"description": "Opis",
|
||||||
"destination_tag": "Tag docelowy:",
|
"destination_tag": "Tag docelowy:",
|
||||||
|
"deuro_collect_interest": "Zbierać",
|
||||||
|
"deuro_savings": "dEuro oszczędności",
|
||||||
|
"deuro_savings_add": "Depozyt",
|
||||||
|
"deuro_savings_balance": "Równowaga oszczędności",
|
||||||
|
"deuro_savings_collect_interest": "Zbieraj zainteresowanie",
|
||||||
|
"deuro_savings_remove": "Wycofać",
|
||||||
|
"deuro_savings_set_approval": "Ustaw zatwierdzenie",
|
||||||
|
"deuro_savings_subtitle": "Zarabiaj do 10% odsetek od Deuro Stablecoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Potwierdzenie i odbicie na ekranie może potrwać kilka sekund",
|
||||||
"device_is_signing": "Urządzenie podpisuje",
|
"device_is_signing": "Urządzenie podpisuje",
|
||||||
"dfx_option_description": "Kup krypto za EUR & CHF. Dla klientów prywatnych i korporacyjnych w Europie",
|
"dfx_option_description": "Kup krypto za EUR & CHF. Dla klientów prywatnych i korporacyjnych w Europie",
|
||||||
"didnt_get_code": "Nie dostałeś kodu?",
|
"didnt_get_code": "Nie dostałeś kodu?",
|
||||||
|
@ -974,6 +984,7 @@
|
||||||
"transport_type": "Typ transportu",
|
"transport_type": "Typ transportu",
|
||||||
"trongrid_history": "Historia Trongrida",
|
"trongrid_history": "Historia Trongrida",
|
||||||
"trusted": "Zaufany",
|
"trusted": "Zaufany",
|
||||||
|
"try_again": "Spróbuj ponownie",
|
||||||
"tx_commit_exception_no_dust_on_change": "Transakcja została odrzucana z tą kwotą. Za pomocą tych monet możesz wysłać ${min} bez reszty lub ${max}, które zwrócą resztę.",
|
"tx_commit_exception_no_dust_on_change": "Transakcja została odrzucana z tą kwotą. Za pomocą tych monet możesz wysłać ${min} bez reszty lub ${max}, które zwrócą resztę.",
|
||||||
"tx_commit_failed": "Zatwierdzenie transakcji nie powiodło się. Skontaktuj się z obsługą.",
|
"tx_commit_failed": "Zatwierdzenie transakcji nie powiodło się. Skontaktuj się z obsługą.",
|
||||||
"tx_commit_failed_no_peers": "Transakcja nie była transmitowana, spróbuj ponownie za około sekundę",
|
"tx_commit_failed_no_peers": "Transakcja nie była transmitowana, spróbuj ponownie za około sekundę",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Atualização de APK",
|
"apk_update": "Atualização de APK",
|
||||||
"approve": "Aprovar",
|
"approve": "Aprovar",
|
||||||
"approve_request": "Aprovar solicitação",
|
"approve_request": "Aprovar solicitação",
|
||||||
|
"approve_tokens": "Aprovar tokens",
|
||||||
"arrive_in_this_address": "${currency} ${tag}chegará neste endereço",
|
"arrive_in_this_address": "${currency} ${tag}chegará neste endereço",
|
||||||
"ascending": "Ascendente",
|
"ascending": "Ascendente",
|
||||||
"ask_each_time": "Pergunte cada vez",
|
"ask_each_time": "Pergunte cada vez",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "descendente",
|
"descending": "descendente",
|
||||||
"description": "Descrição",
|
"description": "Descrição",
|
||||||
"destination_tag": "Tag de destino:",
|
"destination_tag": "Tag de destino:",
|
||||||
|
"deuro_collect_interest": "Coletar",
|
||||||
|
"deuro_savings": "dEuro Savings",
|
||||||
|
"deuro_savings_add": "Depósito",
|
||||||
|
"deuro_savings_balance": "Balanço de poupança",
|
||||||
|
"deuro_savings_collect_interest": "Coletar juros",
|
||||||
|
"deuro_savings_remove": "Retirar",
|
||||||
|
"deuro_savings_set_approval": "Defina aprovação",
|
||||||
|
"deuro_savings_subtitle": "Ganhe até 10% de juros em sua Deuro Stablecoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Pode levar alguns segundos para a transação confirmar e se refletir na tela",
|
||||||
"device_is_signing": "O dispositivo está assinando",
|
"device_is_signing": "O dispositivo está assinando",
|
||||||
"dfx_option_description": "Compre criptografia com EUR & CHF. Para clientes de varejo e corporativo na Europa",
|
"dfx_option_description": "Compre criptografia com EUR & CHF. Para clientes de varejo e corporativo na Europa",
|
||||||
"didnt_get_code": "Não recebeu o código?",
|
"didnt_get_code": "Não recebeu o código?",
|
||||||
|
@ -977,6 +987,7 @@
|
||||||
"transport_type": "Tipo de transporte",
|
"transport_type": "Tipo de transporte",
|
||||||
"trongrid_history": "História de Trongrid",
|
"trongrid_history": "História de Trongrid",
|
||||||
"trusted": "confiável",
|
"trusted": "confiável",
|
||||||
|
"try_again": "Tente novamente",
|
||||||
"tx_commit_exception_no_dust_on_change": "A transação é rejeitada com esse valor. Com essas moedas, você pode enviar ${min} sem alteração ou ${max} que retorna alterações.",
|
"tx_commit_exception_no_dust_on_change": "A transação é rejeitada com esse valor. Com essas moedas, você pode enviar ${min} sem alteração ou ${max} que retorna alterações.",
|
||||||
"tx_commit_failed": "A confirmação da transação falhou. Entre em contato com o suporte.",
|
"tx_commit_failed": "A confirmação da transação falhou. Entre em contato com o suporte.",
|
||||||
"tx_commit_failed_no_peers": "A transação não foi transmitida, tente novamente em um segundo",
|
"tx_commit_failed_no_peers": "A transação não foi transmitida, tente novamente em um segundo",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Обновление APK",
|
"apk_update": "Обновление APK",
|
||||||
"approve": "Утвердить",
|
"approve": "Утвердить",
|
||||||
"approve_request": "Утвердить запрос",
|
"approve_request": "Утвердить запрос",
|
||||||
|
"approve_tokens": "Одобрить токены",
|
||||||
"arrive_in_this_address": "${currency} ${tag}придет на этот адрес",
|
"arrive_in_this_address": "${currency} ${tag}придет на этот адрес",
|
||||||
"ascending": "Восходящий",
|
"ascending": "Восходящий",
|
||||||
"ask_each_time": "Спросите каждый раз",
|
"ask_each_time": "Спросите каждый раз",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Нисходящий",
|
"descending": "Нисходящий",
|
||||||
"description": "Описание",
|
"description": "Описание",
|
||||||
"destination_tag": "Целевой тег:",
|
"destination_tag": "Целевой тег:",
|
||||||
|
"deuro_collect_interest": "Собирать",
|
||||||
|
"deuro_savings": "dEuro Savings",
|
||||||
|
"deuro_savings_add": "Депозитный",
|
||||||
|
"deuro_savings_balance": "Сберегательный баланс",
|
||||||
|
"deuro_savings_collect_interest": "Собирать интерес",
|
||||||
|
"deuro_savings_remove": "Отзывать",
|
||||||
|
"deuro_savings_set_approval": "Установить утверждение",
|
||||||
|
"deuro_savings_subtitle": "Заработайте до 10% процентов на ваших Deuro Stablecoin Holdings",
|
||||||
|
"deuro_tx_commited_content": "Чтобы подтвердить, может потребоваться пару секунд, чтобы подтвердить и быть отраженным на экране",
|
||||||
"device_is_signing": "Устройство подписывает",
|
"device_is_signing": "Устройство подписывает",
|
||||||
"dfx_option_description": "Купить крипто с Eur & CHF. Для розничных и корпоративных клиентов в Европе",
|
"dfx_option_description": "Купить крипто с Eur & CHF. Для розничных и корпоративных клиентов в Европе",
|
||||||
"didnt_get_code": "Не получить код?",
|
"didnt_get_code": "Не получить код?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "Транспортный тип",
|
"transport_type": "Транспортный тип",
|
||||||
"trongrid_history": "История Тронгрида",
|
"trongrid_history": "История Тронгрида",
|
||||||
"trusted": "доверенный",
|
"trusted": "доверенный",
|
||||||
|
"try_again": "Попробуйте еще раз",
|
||||||
"tx_commit_exception_no_dust_on_change": "Транзакция отклоняется с этой суммой. С этими монетами вы можете отправлять ${min} без изменения или ${max}, которые возвращают изменение.",
|
"tx_commit_exception_no_dust_on_change": "Транзакция отклоняется с этой суммой. С этими монетами вы можете отправлять ${min} без изменения или ${max}, которые возвращают изменение.",
|
||||||
"tx_commit_failed": "Комплект транзакции не удался. Пожалуйста, свяжитесь с поддержкой.",
|
"tx_commit_failed": "Комплект транзакции не удался. Пожалуйста, свяжитесь с поддержкой.",
|
||||||
"tx_commit_failed_no_peers": "Транзакция не смогла передать, попробуйте еще раз через секунду или около того",
|
"tx_commit_failed_no_peers": "Транзакция не смогла передать, попробуйте еще раз через секунду или около того",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "ปรับปรุง APK",
|
"apk_update": "ปรับปรุง APK",
|
||||||
"approve": "อนุมัติ",
|
"approve": "อนุมัติ",
|
||||||
"approve_request": "อนุมัติคำขอ",
|
"approve_request": "อนุมัติคำขอ",
|
||||||
|
"approve_tokens": "อนุมัติโทเค็น",
|
||||||
"arrive_in_this_address": "${currency} ${tag}จะมาถึงที่อยู่นี้",
|
"arrive_in_this_address": "${currency} ${tag}จะมาถึงที่อยู่นี้",
|
||||||
"ascending": "จากน้อยไปมาก",
|
"ascending": "จากน้อยไปมาก",
|
||||||
"ask_each_time": "ถามทุกครั้ง",
|
"ask_each_time": "ถามทุกครั้ง",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "ลงมา",
|
"descending": "ลงมา",
|
||||||
"description": "คำอธิบาย",
|
"description": "คำอธิบาย",
|
||||||
"destination_tag": "แท็กปลายทาง:",
|
"destination_tag": "แท็กปลายทาง:",
|
||||||
|
"deuro_collect_interest": "เก็บรวบรวม",
|
||||||
|
"deuro_savings": "การออมของ dEuro",
|
||||||
|
"deuro_savings_add": "เงินฝาก",
|
||||||
|
"deuro_savings_balance": "ยอดเงินออม",
|
||||||
|
"deuro_savings_collect_interest": "เก็บดอกเบี้ย",
|
||||||
|
"deuro_savings_remove": "ถอน",
|
||||||
|
"deuro_savings_set_approval": "ตั้งค่าการอนุมัติ",
|
||||||
|
"deuro_savings_subtitle": "รับดอกเบี้ยมากถึง 10% สำหรับ Deuro Stablecoin Holdings ของคุณ",
|
||||||
|
"deuro_tx_commited_content": "อาจใช้เวลาสองสามวินาทีในการทำธุรกรรมเพื่อยืนยันและสะท้อนบนหน้าจอ",
|
||||||
"device_is_signing": "อุปกรณ์กำลังลงนาม",
|
"device_is_signing": "อุปกรณ์กำลังลงนาม",
|
||||||
"dfx_option_description": "ซื้อ crypto ด้วย Eur & CHF สำหรับลูกค้ารายย่อยและลูกค้าในยุโรป",
|
"dfx_option_description": "ซื้อ crypto ด้วย Eur & CHF สำหรับลูกค้ารายย่อยและลูกค้าในยุโรป",
|
||||||
"didnt_get_code": "ไม่ได้รับรหัส?",
|
"didnt_get_code": "ไม่ได้รับรหัส?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "ประเภทการขนส่ง",
|
"transport_type": "ประเภทการขนส่ง",
|
||||||
"trongrid_history": "ประวัติศาสตร์ Trongrid",
|
"trongrid_history": "ประวัติศาสตร์ Trongrid",
|
||||||
"trusted": "มั่นคง",
|
"trusted": "มั่นคง",
|
||||||
|
"try_again": "ลองอีกครั้ง",
|
||||||
"tx_commit_exception_no_dust_on_change": "ธุรกรรมถูกปฏิเสธด้วยจำนวนเงินนี้ ด้วยเหรียญเหล่านี้คุณสามารถส่ง ${min} โดยไม่ต้องเปลี่ยนแปลงหรือ ${max} ที่ส่งคืนการเปลี่ยนแปลง",
|
"tx_commit_exception_no_dust_on_change": "ธุรกรรมถูกปฏิเสธด้วยจำนวนเงินนี้ ด้วยเหรียญเหล่านี้คุณสามารถส่ง ${min} โดยไม่ต้องเปลี่ยนแปลงหรือ ${max} ที่ส่งคืนการเปลี่ยนแปลง",
|
||||||
"tx_commit_failed": "การทำธุรกรรมล้มเหลว กรุณาติดต่อฝ่ายสนับสนุน",
|
"tx_commit_failed": "การทำธุรกรรมล้มเหลว กรุณาติดต่อฝ่ายสนับสนุน",
|
||||||
"tx_commit_failed_no_peers": "การทำธุรกรรมล้มเหลวในการออกอากาศโปรดลองอีกครั้งในวินาทีหรือมากกว่านั้น",
|
"tx_commit_failed_no_peers": "การทำธุรกรรมล้มเหลวในการออกอากาศโปรดลองอีกครั้งในวินาทีหรือมากกว่านั้น",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK update",
|
"apk_update": "APK update",
|
||||||
"approve": "Aprubahan",
|
"approve": "Aprubahan",
|
||||||
"approve_request": "Aprubahan ang kahilingan",
|
"approve_request": "Aprubahan ang kahilingan",
|
||||||
|
"approve_tokens": "Aprubahan ang mga token",
|
||||||
"arrive_in_this_address": "Ang ${currency} ${tag} ay darating sa address na ito",
|
"arrive_in_this_address": "Ang ${currency} ${tag} ay darating sa address na ito",
|
||||||
"ascending": "Umakyat",
|
"ascending": "Umakyat",
|
||||||
"ask_each_time": "Magtanong sa tuwing",
|
"ask_each_time": "Magtanong sa tuwing",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Pababang",
|
"descending": "Pababang",
|
||||||
"description": "Paglalarawan",
|
"description": "Paglalarawan",
|
||||||
"destination_tag": "Tag ng patutunguhan:",
|
"destination_tag": "Tag ng patutunguhan:",
|
||||||
|
"deuro_collect_interest": "Mangolekta",
|
||||||
|
"deuro_savings": "Pagtipid ni dEuro",
|
||||||
|
"deuro_savings_add": "Deposito",
|
||||||
|
"deuro_savings_balance": "Balanse sa pagtitipid",
|
||||||
|
"deuro_savings_collect_interest": "Mangolekta ng interes",
|
||||||
|
"deuro_savings_remove": "Umatras",
|
||||||
|
"deuro_savings_set_approval": "Itakda ang pag -apruba",
|
||||||
|
"deuro_savings_subtitle": "Kumita ng hanggang sa 10% na interes sa iyong mga hawak na Deuro StableCoin",
|
||||||
|
"deuro_tx_commited_content": "Maaaring tumagal ng ilang segundo para sa transaksyon upang kumpirmahin at maipakita sa screen",
|
||||||
"device_is_signing": "Nag -sign ang aparato",
|
"device_is_signing": "Nag -sign ang aparato",
|
||||||
"dfx_option_description": "Bumili ng crypto kasama ang EUR & CHF. Para sa mga retail customer at corporate customer sa Europe",
|
"dfx_option_description": "Bumili ng crypto kasama ang EUR & CHF. Para sa mga retail customer at corporate customer sa Europe",
|
||||||
"didnt_get_code": "Hindi nakuha ang code?",
|
"didnt_get_code": "Hindi nakuha ang code?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "Uri ng transportasyon",
|
"transport_type": "Uri ng transportasyon",
|
||||||
"trongrid_history": "Kasaysayan ng TronGrid",
|
"trongrid_history": "Kasaysayan ng TronGrid",
|
||||||
"trusted": "Pinagkakatiwalaan",
|
"trusted": "Pinagkakatiwalaan",
|
||||||
|
"try_again": "Subukang muli",
|
||||||
"tx_commit_exception_no_dust_on_change": "Ang transaksyon ay tinanggihan sa halagang ito. Sa mga barya na ito maaari kang magpadala ng ${min} nang walang sukli o ${max} na nagbabalik ng sukli.",
|
"tx_commit_exception_no_dust_on_change": "Ang transaksyon ay tinanggihan sa halagang ito. Sa mga barya na ito maaari kang magpadala ng ${min} nang walang sukli o ${max} na nagbabalik ng sukli.",
|
||||||
"tx_commit_failed": "Nabigo ang transaksyon. Mangyaring makipag-ugnay sa suporta.",
|
"tx_commit_failed": "Nabigo ang transaksyon. Mangyaring makipag-ugnay sa suporta.",
|
||||||
"tx_commit_failed_no_peers": "Nabigo ang transaksyon na mag -broadcast, mangyaring subukang muli sa isang segundo o higit pa",
|
"tx_commit_failed_no_peers": "Nabigo ang transaksyon na mag -broadcast, mangyaring subukang muli sa isang segundo o higit pa",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK güncellemesi",
|
"apk_update": "APK güncellemesi",
|
||||||
"approve": "Onaylamak",
|
"approve": "Onaylamak",
|
||||||
"approve_request": "Talebi Onaylama",
|
"approve_request": "Talebi Onaylama",
|
||||||
|
"approve_tokens": "Jetonları onaylayın",
|
||||||
"arrive_in_this_address": "${currency} ${tag}bu adrese ulaşacak",
|
"arrive_in_this_address": "${currency} ${tag}bu adrese ulaşacak",
|
||||||
"ascending": "Yükselen",
|
"ascending": "Yükselen",
|
||||||
"ask_each_time": "Her seferinde sor",
|
"ask_each_time": "Her seferinde sor",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Azalan",
|
"descending": "Azalan",
|
||||||
"description": "Tanım",
|
"description": "Tanım",
|
||||||
"destination_tag": "Hedef Etiketi:",
|
"destination_tag": "Hedef Etiketi:",
|
||||||
|
"deuro_collect_interest": "TOPLAMAK",
|
||||||
|
"deuro_savings": "dEuro Tasarruf",
|
||||||
|
"deuro_savings_add": "Yatırmak",
|
||||||
|
"deuro_savings_balance": "Tasarruf Bakiyesi",
|
||||||
|
"deuro_savings_collect_interest": "İlgi toplamak",
|
||||||
|
"deuro_savings_remove": "Geri çekilmek",
|
||||||
|
"deuro_savings_set_approval": "Onay ayarlamak",
|
||||||
|
"deuro_savings_subtitle": "Deuro StableCoin Holdings'e% 10'a kadar faiz kazanın",
|
||||||
|
"deuro_tx_commited_content": "İşlemin onaylaması ve ekrana yansıtılması birkaç saniye sürebilir",
|
||||||
"device_is_signing": "Cihaz imzalıyor",
|
"device_is_signing": "Cihaz imzalıyor",
|
||||||
"dfx_option_description": "Eur & chf ile kripto satın alın. Avrupa'daki perakende ve kurumsal müşteriler için",
|
"dfx_option_description": "Eur & chf ile kripto satın alın. Avrupa'daki perakende ve kurumsal müşteriler için",
|
||||||
"didnt_get_code": "Kod gelmedi mi?",
|
"didnt_get_code": "Kod gelmedi mi?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "Taşıma tipi",
|
"transport_type": "Taşıma tipi",
|
||||||
"trongrid_history": "Trongrid tarihi",
|
"trongrid_history": "Trongrid tarihi",
|
||||||
"trusted": "Güvenilir",
|
"trusted": "Güvenilir",
|
||||||
|
"try_again": "Tekrar deneyin",
|
||||||
"tx_commit_exception_no_dust_on_change": "İşlem bu miktarla reddedilir. Bu madeni paralarla değişiklik yapmadan ${min} veya değişikliği döndüren ${max} gönderebilirsiniz.",
|
"tx_commit_exception_no_dust_on_change": "İşlem bu miktarla reddedilir. Bu madeni paralarla değişiklik yapmadan ${min} veya değişikliği döndüren ${max} gönderebilirsiniz.",
|
||||||
"tx_commit_failed": "İşlem taahhüdü başarısız oldu. Lütfen Destek ile iletişime geçin.",
|
"tx_commit_failed": "İşlem taahhüdü başarısız oldu. Lütfen Destek ile iletişime geçin.",
|
||||||
"tx_commit_failed_no_peers": "İşlem yayın yapamadı, lütfen bir saniye içinde tekrar deneyin",
|
"tx_commit_failed_no_peers": "İşlem yayın yapamadı, lütfen bir saniye içinde tekrar deneyin",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Оновлення APK",
|
"apk_update": "Оновлення APK",
|
||||||
"approve": "Затвердити",
|
"approve": "Затвердити",
|
||||||
"approve_request": "Запитайте запит",
|
"approve_request": "Запитайте запит",
|
||||||
|
"approve_tokens": "Затвердити токени",
|
||||||
"arrive_in_this_address": "${currency} ${tag}надійде на цю адресу",
|
"arrive_in_this_address": "${currency} ${tag}надійде на цю адресу",
|
||||||
"ascending": "Висхід",
|
"ascending": "Висхід",
|
||||||
"ask_each_time": "Запитайте кожен раз",
|
"ask_each_time": "Запитайте кожен раз",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Низхідний",
|
"descending": "Низхідний",
|
||||||
"description": "опис",
|
"description": "опис",
|
||||||
"destination_tag": "Тег призначення:",
|
"destination_tag": "Тег призначення:",
|
||||||
|
"deuro_collect_interest": "Збирати",
|
||||||
|
"deuro_savings": "заощадження dEuro",
|
||||||
|
"deuro_savings_add": "Депозит",
|
||||||
|
"deuro_savings_balance": "Баланс заощаджень",
|
||||||
|
"deuro_savings_collect_interest": "Збирати інтерес",
|
||||||
|
"deuro_savings_remove": "Відступати",
|
||||||
|
"deuro_savings_set_approval": "Встановити схвалення",
|
||||||
|
"deuro_savings_subtitle": "Заробляйте до 10% відсотків на ваших Holdings Deuro StableCoin",
|
||||||
|
"deuro_tx_commited_content": "Це може знадобитися кілька секунд, щоб транзакція підтвердила та відображалася на екрані",
|
||||||
"device_is_signing": "Пристрій підписується",
|
"device_is_signing": "Пристрій підписується",
|
||||||
"dfx_option_description": "Купуйте криптовалюту з EUR & CHF. Для роздрібних та корпоративних клієнтів у Європі",
|
"dfx_option_description": "Купуйте криптовалюту з EUR & CHF. Для роздрібних та корпоративних клієнтів у Європі",
|
||||||
"didnt_get_code": "Не отримали код?",
|
"didnt_get_code": "Не отримали код?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "Транспортний тип",
|
"transport_type": "Транспортний тип",
|
||||||
"trongrid_history": "Тронгрідська історія",
|
"trongrid_history": "Тронгрідська історія",
|
||||||
"trusted": "довіряють",
|
"trusted": "довіряють",
|
||||||
|
"try_again": "Спробуйте ще раз",
|
||||||
"tx_commit_exception_no_dust_on_change": "Транзакція відхилена цією сумою. За допомогою цих монет ви можете надіслати ${min} без змін або ${max}, що повертає зміни.",
|
"tx_commit_exception_no_dust_on_change": "Транзакція відхилена цією сумою. За допомогою цих монет ви можете надіслати ${min} без змін або ${max}, що повертає зміни.",
|
||||||
"tx_commit_failed": "Транзакційна комісія не вдалося. Будь ласка, зв'яжіться з підтримкою.",
|
"tx_commit_failed": "Транзакційна комісія не вдалося. Будь ласка, зв'яжіться з підтримкою.",
|
||||||
"tx_commit_failed_no_peers": "Транзакція не вдалося транслювати, спробуйте ще раз за секунду або близько того",
|
"tx_commit_failed_no_peers": "Транзакція не вдалося транслювати, спробуйте ще раз за секунду або близько того",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK اپ ڈیٹ",
|
"apk_update": "APK اپ ڈیٹ",
|
||||||
"approve": "ﻭﺮﮐ ﺭﻮﻈﻨﻣ",
|
"approve": "ﻭﺮﮐ ﺭﻮﻈﻨﻣ",
|
||||||
"approve_request": "درخواست کو منظور کریں",
|
"approve_request": "درخواست کو منظور کریں",
|
||||||
|
"approve_tokens": "ٹوکن کو منظور کریں",
|
||||||
"arrive_in_this_address": "${currency} ${tag}اس پتے پر پہنچے گا۔",
|
"arrive_in_this_address": "${currency} ${tag}اس پتے پر پہنچے گا۔",
|
||||||
"ascending": "چڑھنے",
|
"ascending": "چڑھنے",
|
||||||
"ask_each_time": "ہر بار پوچھیں",
|
"ask_each_time": "ہر بار پوچھیں",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "اترتے ہوئے",
|
"descending": "اترتے ہوئے",
|
||||||
"description": "ﻞﯿﺼﻔﺗ",
|
"description": "ﻞﯿﺼﻔﺗ",
|
||||||
"destination_tag": "منزل کا ٹیگ:",
|
"destination_tag": "منزل کا ٹیگ:",
|
||||||
|
"deuro_collect_interest": "جمع کریں",
|
||||||
|
"deuro_savings": "ڈیورو کی بچت",
|
||||||
|
"deuro_savings_add": "جمع کروائیں",
|
||||||
|
"deuro_savings_balance": "بچت کا توازن",
|
||||||
|
"deuro_savings_collect_interest": "دلچسپی جمع کریں",
|
||||||
|
"deuro_savings_remove": "واپس لے لو",
|
||||||
|
"deuro_savings_set_approval": "منظوری طے کریں",
|
||||||
|
"deuro_savings_subtitle": "اپنے ڈیورو اسٹبل کوئن ہولڈنگز پر 10 ٪ سود حاصل کریں",
|
||||||
|
"deuro_tx_commited_content": "لین دین کی تصدیق اور اسکرین پر عکاسی کرنے میں اس میں کچھ سیکنڈ لگ سکتے ہیں",
|
||||||
"device_is_signing": "ڈیوائس پر دستخط کر رہے ہیں",
|
"device_is_signing": "ڈیوائس پر دستخط کر رہے ہیں",
|
||||||
"dfx_option_description": "یورو اور سی ایچ ایف کے ساتھ کرپٹو خریدیں۔ یورپ میں خوردہ اور کارپوریٹ صارفین کے لئے",
|
"dfx_option_description": "یورو اور سی ایچ ایف کے ساتھ کرپٹو خریدیں۔ یورپ میں خوردہ اور کارپوریٹ صارفین کے لئے",
|
||||||
"didnt_get_code": "کوڈ نہیں ملتا؟",
|
"didnt_get_code": "کوڈ نہیں ملتا؟",
|
||||||
|
@ -977,6 +987,7 @@
|
||||||
"transport_type": "ٹرانسپورٹ کی قسم",
|
"transport_type": "ٹرانسپورٹ کی قسم",
|
||||||
"trongrid_history": "ٹرانگریڈ ہسٹری",
|
"trongrid_history": "ٹرانگریڈ ہسٹری",
|
||||||
"trusted": "قابل اعتماد",
|
"trusted": "قابل اعتماد",
|
||||||
|
"try_again": "دوبارہ کوشش کریں",
|
||||||
"tx_commit_exception_no_dust_on_change": "اس رقم سے لین دین کو مسترد کردیا گیا ہے۔ ان سککوں کے ذریعہ آپ بغیر کسی تبدیلی کے ${min} یا ${max} بھیج سکتے ہیں جو لوٹتے ہیں۔",
|
"tx_commit_exception_no_dust_on_change": "اس رقم سے لین دین کو مسترد کردیا گیا ہے۔ ان سککوں کے ذریعہ آپ بغیر کسی تبدیلی کے ${min} یا ${max} بھیج سکتے ہیں جو لوٹتے ہیں۔",
|
||||||
"tx_commit_failed": "ٹرانزیکشن کمٹ ناکام ہوگیا۔ براہ کرم سپورٹ سے رابطہ کریں۔",
|
"tx_commit_failed": "ٹرانزیکشن کمٹ ناکام ہوگیا۔ براہ کرم سپورٹ سے رابطہ کریں۔",
|
||||||
"tx_commit_failed_no_peers": "ٹرانزیکشن نشر کرنے میں ناکام ، براہ کرم ایک سیکنڈ یا اس میں دوبارہ کوشش کریں",
|
"tx_commit_failed_no_peers": "ٹرانزیکشن نشر کرنے میں ناکام ، براہ کرم ایک سیکنڈ یا اس میں دوبارہ کوشش کریں",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Cập nhật APK",
|
"apk_update": "Cập nhật APK",
|
||||||
"approve": "Phê duyệt",
|
"approve": "Phê duyệt",
|
||||||
"approve_request": "Phê duyệt yêu cầu",
|
"approve_request": "Phê duyệt yêu cầu",
|
||||||
|
"approve_tokens": "Phê duyệt mã thông báo",
|
||||||
"arrive_in_this_address": "${currency} ${tag} sẽ đến địa chỉ này",
|
"arrive_in_this_address": "${currency} ${tag} sẽ đến địa chỉ này",
|
||||||
"ascending": "Tăng dần",
|
"ascending": "Tăng dần",
|
||||||
"ask_each_time": "Hỏi mỗi lần",
|
"ask_each_time": "Hỏi mỗi lần",
|
||||||
|
@ -243,6 +244,15 @@
|
||||||
"descending": "Giảm dần",
|
"descending": "Giảm dần",
|
||||||
"description": "Mô tả",
|
"description": "Mô tả",
|
||||||
"destination_tag": "Thẻ đích:",
|
"destination_tag": "Thẻ đích:",
|
||||||
|
"deuro_collect_interest": "Sưu tầm",
|
||||||
|
"deuro_savings": "Tiết kiệm dEuro",
|
||||||
|
"deuro_savings_add": "Tiền gửi",
|
||||||
|
"deuro_savings_balance": "Số dư tiết kiệm",
|
||||||
|
"deuro_savings_collect_interest": "Thu tiền lãi",
|
||||||
|
"deuro_savings_remove": "Rút",
|
||||||
|
"deuro_savings_set_approval": "Đặt phê duyệt",
|
||||||
|
"deuro_savings_subtitle": "Kiếm tới 10% tiền lãi cho Deuro Storcoin Holdings của bạn",
|
||||||
|
"deuro_tx_commited_content": "Có thể mất vài giây để giao dịch xác nhận và được phản ánh trên màn hình",
|
||||||
"device_is_signing": "Thiết bị đang ký",
|
"device_is_signing": "Thiết bị đang ký",
|
||||||
"dfx_option_description": "Mua tiền điện tử bằng EUR & CHF. Dành cho khách hàng bán lẻ và doanh nghiệp tại Châu Âu",
|
"dfx_option_description": "Mua tiền điện tử bằng EUR & CHF. Dành cho khách hàng bán lẻ và doanh nghiệp tại Châu Âu",
|
||||||
"didnt_get_code": "Không nhận được mã?",
|
"didnt_get_code": "Không nhận được mã?",
|
||||||
|
@ -972,6 +982,7 @@
|
||||||
"transport_type": "Loại vận chuyển",
|
"transport_type": "Loại vận chuyển",
|
||||||
"trongrid_history": "Lịch sử TronGrid",
|
"trongrid_history": "Lịch sử TronGrid",
|
||||||
"trusted": "Đã tin cậy",
|
"trusted": "Đã tin cậy",
|
||||||
|
"try_again": "Hãy thử lại",
|
||||||
"tx_commit_exception_no_dust_on_change": "Giao dịch bị từ chối với số tiền này. Với số tiền này bạn có thể gửi ${min} mà không cần đổi tiền lẻ hoặc ${max} trả lại tiền lẻ.",
|
"tx_commit_exception_no_dust_on_change": "Giao dịch bị từ chối với số tiền này. Với số tiền này bạn có thể gửi ${min} mà không cần đổi tiền lẻ hoặc ${max} trả lại tiền lẻ.",
|
||||||
"tx_commit_failed": "Giao dịch không thành công. Vui lòng liên hệ với hỗ trợ.",
|
"tx_commit_failed": "Giao dịch không thành công. Vui lòng liên hệ với hỗ trợ.",
|
||||||
"tx_commit_failed_no_peers": "Giao dịch không phát sóng, vui lòng thử lại trong một giây hoặc lâu hơn",
|
"tx_commit_failed_no_peers": "Giao dịch không phát sóng, vui lòng thử lại trong một giây hoặc lâu hơn",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "Àtúnse áàpù títun wà",
|
"apk_update": "Àtúnse áàpù títun wà",
|
||||||
"approve": "Fi ọwọ si",
|
"approve": "Fi ọwọ si",
|
||||||
"approve_request": "IKILỌ RẸ",
|
"approve_request": "IKILỌ RẸ",
|
||||||
|
"approve_tokens": "Ṣe fọwọsi awọn àmi",
|
||||||
"arrive_in_this_address": "${currency} ${tag} máa dé sí àdírẹ́sì yìí",
|
"arrive_in_this_address": "${currency} ${tag} máa dé sí àdírẹ́sì yìí",
|
||||||
"ascending": "Goke",
|
"ascending": "Goke",
|
||||||
"ask_each_time": "Beere lọwọ kọọkan",
|
"ask_each_time": "Beere lọwọ kọọkan",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "Sọkalẹ",
|
"descending": "Sọkalẹ",
|
||||||
"description": "Apejuwe",
|
"description": "Apejuwe",
|
||||||
"destination_tag": "Orúkọ tí ìbí tó a ránṣẹ́ sí:",
|
"destination_tag": "Orúkọ tí ìbí tó a ránṣẹ́ sí:",
|
||||||
|
"deuro_collect_interest": "Kojọ",
|
||||||
|
"deuro_savings": "dEuro Awọn ifowopamọ",
|
||||||
|
"deuro_savings_add": "Owo ifipamọ",
|
||||||
|
"deuro_savings_balance": "Iwontunws.funfun ifowopamọ",
|
||||||
|
"deuro_savings_collect_interest": "Gba iwulo",
|
||||||
|
"deuro_savings_remove": "Yọkuro",
|
||||||
|
"deuro_savings_set_approval": "Ṣeto ifọwọsi",
|
||||||
|
"deuro_savings_subtitle": "Jo'gun to 10% iwulo lori awọn idaduro Duroblockoin rẹ",
|
||||||
|
"deuro_tx_commited_content": "O le gba tọkọtaya kan ti awọn aaya fun idunadura lati jẹrisi ati ṣe afihan loju iboju",
|
||||||
"device_is_signing": "Ẹrọ n forukọsilẹ",
|
"device_is_signing": "Ẹrọ n forukọsilẹ",
|
||||||
"dfx_option_description": "Ra Crypto pẹlu EUR & CHF. Fun soobu ati awọn alabara ile-iṣẹ ni Yuroopu",
|
"dfx_option_description": "Ra Crypto pẹlu EUR & CHF. Fun soobu ati awọn alabara ile-iṣẹ ni Yuroopu",
|
||||||
"didnt_get_code": "Ko gba koodu?",
|
"didnt_get_code": "Ko gba koodu?",
|
||||||
|
@ -976,6 +986,7 @@
|
||||||
"transport_type": "Iru irinna",
|
"transport_type": "Iru irinna",
|
||||||
"trongrid_history": "Itan Trongrid",
|
"trongrid_history": "Itan Trongrid",
|
||||||
"trusted": "A ti fọkàn ẹ̀ tán",
|
"trusted": "A ti fọkàn ẹ̀ tán",
|
||||||
|
"try_again": "Gbiyanju lẹẹkansi",
|
||||||
"tx_commit_exception_no_dust_on_change": "Iṣowo naa ti kọ pẹlu iye yii. Pẹlu awọn owó wọnyi o le firanṣẹ ${min} laisi ayipada tabi ${max} ni iyipada iyipada.",
|
"tx_commit_exception_no_dust_on_change": "Iṣowo naa ti kọ pẹlu iye yii. Pẹlu awọn owó wọnyi o le firanṣẹ ${min} laisi ayipada tabi ${max} ni iyipada iyipada.",
|
||||||
"tx_commit_failed": "Idunadura iṣowo kuna. Jọwọ kan si atilẹyin.",
|
"tx_commit_failed": "Idunadura iṣowo kuna. Jọwọ kan si atilẹyin.",
|
||||||
"tx_commit_failed_no_peers": "Idunadura kuna lati wa igbohungbe, jọwọ gbiyanju lẹẹkansi ni iṣẹju keji tabi bẹẹ",
|
"tx_commit_failed_no_peers": "Idunadura kuna lati wa igbohungbe, jọwọ gbiyanju lẹẹkansi ni iṣẹju keji tabi bẹẹ",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"apk_update": "APK更新",
|
"apk_update": "APK更新",
|
||||||
"approve": "批准",
|
"approve": "批准",
|
||||||
"approve_request": "批准请求",
|
"approve_request": "批准请求",
|
||||||
|
"approve_tokens": "批准令牌",
|
||||||
"arrive_in_this_address": "${currency} ${tag}将到达此地址",
|
"arrive_in_this_address": "${currency} ${tag}将到达此地址",
|
||||||
"ascending": "上升",
|
"ascending": "上升",
|
||||||
"ask_each_time": "每次问",
|
"ask_each_time": "每次问",
|
||||||
|
@ -244,6 +245,15 @@
|
||||||
"descending": "下降",
|
"descending": "下降",
|
||||||
"description": "描述",
|
"description": "描述",
|
||||||
"destination_tag": "目标Tag:",
|
"destination_tag": "目标Tag:",
|
||||||
|
"deuro_collect_interest": "收集",
|
||||||
|
"deuro_savings": "dEuro储蓄",
|
||||||
|
"deuro_savings_add": "订金",
|
||||||
|
"deuro_savings_balance": "储蓄平衡",
|
||||||
|
"deuro_savings_collect_interest": "收集兴趣",
|
||||||
|
"deuro_savings_remove": "提取",
|
||||||
|
"deuro_savings_set_approval": "设定批准",
|
||||||
|
"deuro_savings_subtitle": "您的Deuro Stablecoin Holdings最多可赚取10%的利息",
|
||||||
|
"deuro_tx_commited_content": "交易可能需要几秒钟才能确认并在屏幕上反射",
|
||||||
"device_is_signing": "设备正在签名",
|
"device_is_signing": "设备正在签名",
|
||||||
"dfx_option_description": "用Eur&Chf购买加密货币。对于欧洲的零售和企业客户",
|
"dfx_option_description": "用Eur&Chf购买加密货币。对于欧洲的零售和企业客户",
|
||||||
"didnt_get_code": "没有获取代码?",
|
"didnt_get_code": "没有获取代码?",
|
||||||
|
@ -975,6 +985,7 @@
|
||||||
"transport_type": "运输类型",
|
"transport_type": "运输类型",
|
||||||
"trongrid_history": "Trongrid历史",
|
"trongrid_history": "Trongrid历史",
|
||||||
"trusted": "值得信赖",
|
"trusted": "值得信赖",
|
||||||
|
"try_again": "再试一次",
|
||||||
"tx_commit_exception_no_dust_on_change": "交易被此金额拒绝。使用这些硬币,您可以发送${min}无需更改或返回${max}的变化。",
|
"tx_commit_exception_no_dust_on_change": "交易被此金额拒绝。使用这些硬币,您可以发送${min}无需更改或返回${max}的变化。",
|
||||||
"tx_commit_failed": "交易承诺失败。请联系支持。",
|
"tx_commit_failed": "交易承诺失败。请联系支持。",
|
||||||
"tx_commit_failed_no_peers": "交易无法广播,请在一秒钟左右的时间内重试",
|
"tx_commit_failed_no_peers": "交易无法广播,请在一秒钟左右的时间内重试",
|
||||||
|
|
178
test/core/address_validator_test.dart
Normal file
178
test/core/address_validator_test.dart
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
import 'package:cake_wallet/core/address_validator.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('AddressValidator', () {
|
||||||
|
setUpAll(() {
|
||||||
|
S.current = S();
|
||||||
|
});
|
||||||
|
group('getPattern', () {
|
||||||
|
test('returns correct pattern for Bitcoin', () {
|
||||||
|
final pattern = AddressValidator.getPattern(CryptoCurrency.btc);
|
||||||
|
expect(pattern, isNotEmpty);
|
||||||
|
expect(pattern, contains('(bc|tb)1q'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct pattern for Ethereum', () {
|
||||||
|
final pattern = AddressValidator.getPattern(CryptoCurrency.eth);
|
||||||
|
expect(pattern, isNotEmpty);
|
||||||
|
expect(pattern, contains('0x[0-9a-zA-Z]+'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct pattern for Monero', () {
|
||||||
|
final pattern = AddressValidator.getPattern(CryptoCurrency.xmr);
|
||||||
|
expect(pattern, isNotEmpty);
|
||||||
|
expect(pattern,
|
||||||
|
contains('4[0-9a-zA-Z]{94}|8[0-9a-zA-Z]{94}|[0-9a-zA-Z]{106}'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct pattern for Litecoin', () {
|
||||||
|
final pattern = AddressValidator.getPattern(CryptoCurrency.ltc);
|
||||||
|
expect(pattern, isNotEmpty);
|
||||||
|
expect(
|
||||||
|
pattern,
|
||||||
|
contains(
|
||||||
|
'(bc|tb|ltc)1q[ac-hj-np-z02-9]{25,39}|(ltc|t)mweb1q[ac-hj-np-z02-9]{90,120}'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns empty string for unknown currency', () {
|
||||||
|
final pattern = AddressValidator.getPattern(CryptoCurrency.btcln);
|
||||||
|
expect(pattern, isNotEmpty);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('getLength', () {
|
||||||
|
test('returns correct length for Bitcoin', () {
|
||||||
|
final length = AddressValidator.getLength(CryptoCurrency.btc);
|
||||||
|
expect(length, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct length for Ethereum', () {
|
||||||
|
final length = AddressValidator.getLength(CryptoCurrency.eth);
|
||||||
|
expect(length, equals([42]));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct length for Monero', () {
|
||||||
|
final length = AddressValidator.getLength(CryptoCurrency.xmr);
|
||||||
|
expect(length, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct length for Dash', () {
|
||||||
|
final length = AddressValidator.getLength(CryptoCurrency.dash);
|
||||||
|
expect(length, equals([34]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('getAddressFromStringPattern', () {
|
||||||
|
test('returns correct pattern for Bitcoin', () {
|
||||||
|
final pattern =
|
||||||
|
AddressValidator.getAddressFromStringPattern(CryptoCurrency.btc);
|
||||||
|
expect(pattern, isNotNull);
|
||||||
|
expect(pattern, contains('(bc|tb)1q'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct pattern for Ethereum', () {
|
||||||
|
final pattern =
|
||||||
|
AddressValidator.getAddressFromStringPattern(CryptoCurrency.eth);
|
||||||
|
expect(pattern, isNotNull);
|
||||||
|
expect(pattern, contains('0x[0-9a-zA-Z]+'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct pattern for Monero', () {
|
||||||
|
final pattern =
|
||||||
|
AddressValidator.getAddressFromStringPattern(CryptoCurrency.xmr);
|
||||||
|
expect(pattern, isNotNull);
|
||||||
|
expect(pattern, contains('(4[0-9a-zA-Z]{94})'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns null for unsupported currency', () {
|
||||||
|
final pattern =
|
||||||
|
AddressValidator.getAddressFromStringPattern(CryptoCurrency.dash);
|
||||||
|
expect(pattern, isNull);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// 0.000058158099999999995 BTC
|
||||||
|
group('validation', () {
|
||||||
|
test('validates valid Bitcoin address', () {
|
||||||
|
final validator = AddressValidator(type: CryptoCurrency.btc);
|
||||||
|
expect(validator.isValid('bc1qhg4l43pmq5v5atmtlr7gnwyuxs043cvrut5hkq'),
|
||||||
|
isTrue);
|
||||||
|
expect(validator.isValid('3AD1Btx1MzYGmdpNpeujCfuvU5SsU2LX88'), isTrue);
|
||||||
|
expect(validator.isValid('1HARAhFcvz8ZQp5MhnLFeUynC4bkha3Hv8'), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rejects invalid Bitcoin address', () {
|
||||||
|
final validator = AddressValidator(type: CryptoCurrency.btc);
|
||||||
|
expect(validator.isValid('invalid_address'), isFalse);
|
||||||
|
expect(validator.isValid('bc1qhg4l43pmq5v5atmtlr7gnwyuxs043CakeWallet'),
|
||||||
|
isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('validates valid Ethereum address', () {
|
||||||
|
final validator = AddressValidator(type: CryptoCurrency.eth);
|
||||||
|
expect(validator.isValid('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'),
|
||||||
|
isTrue); // WETH contract
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rejects invalid Ethereum address', () {
|
||||||
|
final validator = AddressValidator(type: CryptoCurrency.eth);
|
||||||
|
expect(validator.isValid('invalid_address'), isFalse);
|
||||||
|
expect(validator.isValid('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc'),
|
||||||
|
isFalse); // Too short
|
||||||
|
expect(validator.isValid('C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'),
|
||||||
|
isFalse); // Missing 0x prefix
|
||||||
|
});
|
||||||
|
|
||||||
|
test('validates valid Monero address', () {
|
||||||
|
final validator = AddressValidator(type: CryptoCurrency.xmr);
|
||||||
|
expect(
|
||||||
|
validator.isValid(
|
||||||
|
'85s6zfxGAkdCN21h566R8EFDSfThxCrFiEkhw3JEtaXN2DDfahABLXTjRj385Ro7om5saGWJG7iuE6EyW5MYcoz93DLvNqh'),
|
||||||
|
isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rejects invalid Monero address', () {
|
||||||
|
final validator = AddressValidator(type: CryptoCurrency.xmr);
|
||||||
|
expect(validator.isValid('invalid_address'), isFalse);
|
||||||
|
expect(
|
||||||
|
validator.isValid(
|
||||||
|
'85s6zfxGAkdCN21h566R8EFDSfThxCrFiEkhw3JEtaXN2DDfahABLXTjRj385Ro7om5saGWJG7iuE6EyW5MYcoz93DLvNq'),
|
||||||
|
isFalse); // Too short
|
||||||
|
});
|
||||||
|
|
||||||
|
test('validates valid Litecoin address', () {
|
||||||
|
final validator = AddressValidator(type: CryptoCurrency.ltc);
|
||||||
|
expect(validator.isValid('ltc1qzvxlvlk8wsmue0np20eh3d3qxsusx9jstf8qw8'),
|
||||||
|
isTrue);
|
||||||
|
expect(
|
||||||
|
validator.isValid(
|
||||||
|
'ltcmweb1qqt9hqch2d0vfdsvt4tf27gullem2tcd57xxrvta9xwvfmwdkn4927q6d8sq6ftw7lkqdkr5g36eqn7w06edgq8tz7gy0nv5d4lhajctkzuath23a'),
|
||||||
|
isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rejects invalid Litecoin address', () {
|
||||||
|
final validator = AddressValidator(type: CryptoCurrency.ltc);
|
||||||
|
expect(validator.isValid('invalid_address'), isFalse);
|
||||||
|
expect(
|
||||||
|
validator.isValid('ltc1qzvxlvlk8wsmue0np20eh3d3qxsusxCakeWallet'),
|
||||||
|
isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('silentPaymentAddressPattern', () {
|
||||||
|
test('returns a non-empty pattern', () {
|
||||||
|
final pattern = AddressValidator.silentPaymentAddressPattern;
|
||||||
|
expect(pattern, isNotEmpty);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('mWebAddressPattern', () {
|
||||||
|
test('returns a non-empty pattern', () {
|
||||||
|
final pattern = AddressValidator.mWebAddressPattern;
|
||||||
|
expect(pattern, isNotEmpty);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
187
test/entities/parse_address_from_domain_test.dart
Normal file
187
test/entities/parse_address_from_domain_test.dart
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('AddressResolver', () {
|
||||||
|
// late MockYatService mockYatService;
|
||||||
|
// late MockWalletBase mockWallet;
|
||||||
|
// late MockSettingsStore mockSettingsStore;
|
||||||
|
// late MockBuildContext mockContext;
|
||||||
|
// late AddressResolver addressResolver;
|
||||||
|
//
|
||||||
|
// setUp(() {
|
||||||
|
// mockYatService = MockYatService();
|
||||||
|
// mockWallet = MockWalletBase();
|
||||||
|
// mockSettingsStore = MockSettingsStore();
|
||||||
|
// mockContext = MockBuildContext();
|
||||||
|
//
|
||||||
|
// when(mockWallet.type).thenReturn(WalletType.bitcoin);
|
||||||
|
// when(mockWallet.currency).thenReturn(CryptoCurrency.btc);
|
||||||
|
//
|
||||||
|
// addressResolver = AddressResolver(
|
||||||
|
// yatService: mockYatService,
|
||||||
|
// wallet: mockWallet,
|
||||||
|
// settingsStore: mockSettingsStore,
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
|
||||||
|
group('extractAddressByType', () {
|
||||||
|
test('extracts Bitcoin address correctly', () {
|
||||||
|
final raw =
|
||||||
|
'My Bitcoin address is bc1qhg4l43pmq5v5atmtlr7gnwyuxs043cvrut5hkq please use it';
|
||||||
|
final result = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw,
|
||||||
|
type: CryptoCurrency.btc,
|
||||||
|
);
|
||||||
|
expect(result, 'bc1qhg4l43pmq5v5atmtlr7gnwyuxs043cvrut5hkq');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('extracts Ethereum address correctly', () {
|
||||||
|
final raw =
|
||||||
|
'Send ETH to 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 thanks';
|
||||||
|
final result = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw,
|
||||||
|
type: CryptoCurrency.eth,
|
||||||
|
);
|
||||||
|
expect(result, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('extracts Monero address correctly', () {
|
||||||
|
final raw =
|
||||||
|
'XMR: 85s6zfxGAkdCN21h566R8EFDSfThxCrFiEkhw3JEtaXN2DDfahABLXTjRj385Ro7om5saGWJG7iuE6EyW5MYcoz93DLvNqh';
|
||||||
|
final result = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw,
|
||||||
|
type: CryptoCurrency.xmr,
|
||||||
|
);
|
||||||
|
expect(result,
|
||||||
|
'85s6zfxGAkdCN21h566R8EFDSfThxCrFiEkhw3JEtaXN2DDfahABLXTjRj385Ro7om5saGWJG7iuE6EyW5MYcoz93DLvNqh');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('extracts Bitcoin Cash address correctly', () {
|
||||||
|
final raw =
|
||||||
|
'BCH: bitcoincash:qr2z7dusk64qnq97azhg0u0hlf7qgwwfzyj92jgmqj';
|
||||||
|
final result = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw,
|
||||||
|
type: CryptoCurrency.bch,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
result, 'bitcoincash:qr2z7dusk64qnq97azhg0u0hlf7qgwwfzyj92jgmqj');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('extracts Nano address correctly', () {
|
||||||
|
final raw =
|
||||||
|
'NANO: nano_1natrium1o3z5519ifou7xii8crpxpk8y65qmkih8e8bpsjri651oza8imdd';
|
||||||
|
final result = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw,
|
||||||
|
type: CryptoCurrency.nano,
|
||||||
|
);
|
||||||
|
expect(result,
|
||||||
|
'nano_1natrium1o3z5519ifou7xii8crpxpk8y65qmkih8e8bpsjri651oza8imdd');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns null for unsupported currency', () {
|
||||||
|
final raw = 'Some text without an address';
|
||||||
|
expect(
|
||||||
|
() => AddressResolver.extractAddressByType(
|
||||||
|
raw: raw,
|
||||||
|
type: CryptoCurrency.btc,
|
||||||
|
),
|
||||||
|
returnsNormally);
|
||||||
|
|
||||||
|
final result = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw,
|
||||||
|
type: CryptoCurrency.btc,
|
||||||
|
);
|
||||||
|
expect(result, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('extracts monero address from URI', () {
|
||||||
|
final raw =
|
||||||
|
'monero_wallet:467iotZU5tvG26k2xdZWkJ7gwATFVhfbuV3yDoWx5jHoPwxEi4f5BuJQwkP6GpCb1sZvUVB7nbSkgEuW8NKrh9KKRRga5qz?spend_key=029c559cd7669f14e91fd835144916009f8697ab5ac5c7f7c06e1ff869c17b0b&view_key=afaf646edbff3d3bcee8efd3383ffe5d20c947040f74e1110b70ca0fbb0ef90d';
|
||||||
|
final result = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw,
|
||||||
|
type: CryptoCurrency.xmr,
|
||||||
|
requireSurroundingWhitespaces: false);
|
||||||
|
expect(result,
|
||||||
|
'467iotZU5tvG26k2xdZWkJ7gwATFVhfbuV3yDoWx5jHoPwxEi4f5BuJQwkP6GpCb1sZvUVB7nbSkgEuW8NKrh9KKRRga5qz');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('extracts monero address from Tweet', () {
|
||||||
|
final raw = '''
|
||||||
|
#XMR
|
||||||
|
89bH6i3ftaWSWuPJJYSQuuApWJ8xzinCEbbnAXN1Z3mGGUuAFdpBUg82R9MvJDSheJ6kW2dyMQEFUGM4tsZqRb2Q75UXqvc
|
||||||
|
|
||||||
|
#BTC Silent Payments
|
||||||
|
sp1qq0avpawwjg4l66p6lqafj0vlvm6rlhdc6qt0r6dfual835vhs3gvkq63pechaqezvn7j7uj2jucwj5k7nenpw2r86wf42xv6wqdvxuk5rggrul45
|
||||||
|
|
||||||
|
#LTC MWEB
|
||||||
|
ltcmweb1qq0at62jjucmawxp78qutn0cqwkwahcfx7fxls0r2ma5llg5w6wyy2qe20gxa3rku2658j88zg9d2j4ttpw35k0a5nrg93h5nq3wyvkcgwc3q4dgc
|
||||||
|
''';
|
||||||
|
final resultXmr = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw, type: CryptoCurrency.xmr);
|
||||||
|
expect(resultXmr,
|
||||||
|
'89bH6i3ftaWSWuPJJYSQuuApWJ8xzinCEbbnAXN1Z3mGGUuAFdpBUg82R9MvJDSheJ6kW2dyMQEFUGM4tsZqRb2Q75UXqvc');
|
||||||
|
final resultBtc = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw, type: CryptoCurrency.btc);
|
||||||
|
expect(resultBtc,
|
||||||
|
'sp1qq0avpawwjg4l66p6lqafj0vlvm6rlhdc6qt0r6dfual835vhs3gvkq63pechaqezvn7j7uj2jucwj5k7nenpw2r86wf42xv6wqdvxuk5rggrul45');
|
||||||
|
final resultLtc = AddressResolver.extractAddressByType(
|
||||||
|
raw: raw, type: CryptoCurrency.ltc);
|
||||||
|
expect(resultLtc,
|
||||||
|
'ltcmweb1qq0at62jjucmawxp78qutn0cqwkwahcfx7fxls0r2ma5llg5w6wyy2qe20gxa3rku2658j88zg9d2j4ttpw35k0a5nrg93h5nq3wyvkcgwc3q4dgc');
|
||||||
|
});
|
||||||
|
|
||||||
|
// test('throws exception for unexpected token', () {
|
||||||
|
// // Create a custom crypto currency that won't have a pattern
|
||||||
|
// final customCurrency = CryptoCurrency('CUSTOM', 'Custom');
|
||||||
|
// expect(() => AddressResolver.extractAddressByType(
|
||||||
|
// raw: 'Some text',
|
||||||
|
// type: customCurrency,
|
||||||
|
// ), throwsException);
|
||||||
|
// });
|
||||||
|
});
|
||||||
|
//
|
||||||
|
// group('isEmailFormat', () {
|
||||||
|
// test('returns true for valid email format', () {
|
||||||
|
// expect(addressResolver.isEmailFormat('user@example.com'), isTrue);
|
||||||
|
// expect(addressResolver.isEmailFormat('name.surname@domain.co.uk'), isTrue);
|
||||||
|
// expect(addressResolver.isEmailFormat('user123@subdomain.example.org'), isTrue);
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// test('returns false for invalid email format', () {
|
||||||
|
// expect(addressResolver.isEmailFormat('user@'), isFalse);
|
||||||
|
// expect(addressResolver.isEmailFormat('@domain.com'), isFalse);
|
||||||
|
// expect(addressResolver.isEmailFormat('user@domain'), isFalse);
|
||||||
|
// expect(addressResolver.isEmailFormat('user.domain.com'), isFalse);
|
||||||
|
// expect(addressResolver.isEmailFormat('user@domain@com'), isFalse);
|
||||||
|
// expect(addressResolver.isEmailFormat('bc1qhg4l43pmq5v5atmtlr7gnwyuxs043cvrut5hkq'), isFalse);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// group('resolve', () {
|
||||||
|
// test('returns ParsedAddress with original text when no resolution is possible', () async {
|
||||||
|
// final text = 'bc1qhg4l43pmq5v5atmtlr7gnwyuxs043cvrut5hkq';
|
||||||
|
// final result = await addressResolver.resolve(mockContext, text, CryptoCurrency.btc);
|
||||||
|
//
|
||||||
|
// expect(result, isA<ParsedAddress>());
|
||||||
|
// expect(result.addresses, [text]);
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // Note: More comprehensive tests for the resolve method would require
|
||||||
|
// // mocking all the external services and APIs that the method calls.
|
||||||
|
// // This would be quite extensive and would require setting up mock
|
||||||
|
// // responses for each type of address resolution.
|
||||||
|
// });
|
||||||
|
|
||||||
|
group('unstoppableDomains', () {
|
||||||
|
test('contains expected TLDs', () {
|
||||||
|
expect(AddressResolver.unstoppableDomains, contains('crypto'));
|
||||||
|
expect(AddressResolver.unstoppableDomains, contains('eth'));
|
||||||
|
expect(AddressResolver.unstoppableDomains, contains('bitcoin'));
|
||||||
|
expect(AddressResolver.unstoppableDomains, contains('x'));
|
||||||
|
expect(AddressResolver.unstoppableDomains, contains('wallet'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -670,6 +670,7 @@ import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/erc20_token.dart';
|
import 'package:cw_core/erc20_token.dart';
|
||||||
import 'package:cw_core/hardware/hardware_account_data.dart';
|
import 'package:cw_core/hardware/hardware_account_data.dart';
|
||||||
import 'package:cw_core/output_info.dart';
|
import 'package:cw_core/output_info.dart';
|
||||||
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
import 'package:cw_core/transaction_info.dart';
|
import 'package:cw_core/transaction_info.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
|
@ -697,6 +698,7 @@ import 'package:cw_ethereum/ethereum_client.dart';
|
||||||
import 'package:cw_ethereum/ethereum_wallet.dart';
|
import 'package:cw_ethereum/ethereum_wallet.dart';
|
||||||
import 'package:cw_ethereum/ethereum_wallet_service.dart';
|
import 'package:cw_ethereum/ethereum_wallet_service.dart';
|
||||||
import 'package:cw_ethereum/default_ethereum_erc20_tokens.dart';
|
import 'package:cw_ethereum/default_ethereum_erc20_tokens.dart';
|
||||||
|
import 'package:cw_ethereum/deuro/deuro_savings.dart';
|
||||||
|
|
||||||
import 'package:eth_sig_util/util/utils.dart';
|
import 'package:eth_sig_util/util/utils.dart';
|
||||||
|
|
||||||
|
@ -745,6 +747,16 @@ abstract class Ethereum {
|
||||||
Web3Client? getWeb3Client(WalletBase wallet);
|
Web3Client? getWeb3Client(WalletBase wallet);
|
||||||
String getTokenAddress(CryptoCurrency asset);
|
String getTokenAddress(CryptoCurrency asset);
|
||||||
|
|
||||||
|
Future<PendingTransaction> createTokenApproval(WalletBase wallet, BigInt amount, String spender, CryptoCurrency token, TransactionPriority priority);
|
||||||
|
|
||||||
|
Future<BigInt> getDEuroSavingsBalance(WalletBase wallet);
|
||||||
|
Future<BigInt> getDEuroAccruedInterest(WalletBase wallet);
|
||||||
|
Future<BigInt> getDEuroInterestRate(WalletBase wallet);
|
||||||
|
Future<BigInt> getDEuroSavingsApproved(WalletBase wallet);
|
||||||
|
Future<PendingTransaction> addDEuroSaving(WalletBase wallet, BigInt amount, TransactionPriority priority);
|
||||||
|
Future<PendingTransaction> removeDEuroSaving(WalletBase wallet, BigInt amount, TransactionPriority priority);
|
||||||
|
Future<PendingTransaction> enableDEuroSaving(WalletBase wallet, TransactionPriority priority);
|
||||||
|
|
||||||
void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection);
|
void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection);
|
||||||
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
|
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
|
||||||
List<String> getDefaultTokenContractAddresses();
|
List<String> getDefaultTokenContractAddresses();
|
||||||
|
@ -777,6 +789,7 @@ import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/erc20_token.dart';
|
import 'package:cw_core/erc20_token.dart';
|
||||||
import 'package:cw_core/hardware/hardware_account_data.dart';
|
import 'package:cw_core/hardware/hardware_account_data.dart';
|
||||||
import 'package:cw_core/output_info.dart';
|
import 'package:cw_core/output_info.dart';
|
||||||
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
import 'package:cw_core/transaction_info.dart';
|
import 'package:cw_core/transaction_info.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
|
@ -847,6 +860,8 @@ abstract class Polygon {
|
||||||
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token);
|
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token);
|
||||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress);
|
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress);
|
||||||
|
|
||||||
|
Future<PendingTransaction> createTokenApproval(WalletBase wallet, BigInt amount, String spender, CryptoCurrency token, TransactionPriority priority);
|
||||||
|
|
||||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
|
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
|
||||||
void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled);
|
void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled);
|
||||||
Web3Client? getWeb3Client(WalletBase wallet);
|
Web3Client? getWeb3Client(WalletBase wallet);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue