Merge branch 'main' into CW-1103-Token-Validation-Issues

This commit is contained in:
Omar Hatem 2025-06-19 05:52:05 +03:00 committed by GitHub
commit 4418a3d542
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 2034 additions and 63 deletions

View 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;
}

File diff suppressed because one or more lines are too long

View file

@ -6,7 +6,7 @@ author: Cake Wallet
homepage: https://cakewallet.com
environment:
sdk: '>=2.18.2 <3.0.0'
sdk: ^3.5.0
flutter: ">=1.17.0"
dependencies:

View file

@ -101,6 +101,7 @@ abstract class EVMChainClient {
String? contractAddress,
EtherAmount? gasPrice,
EtherAmount? maxFeePerGas,
Uint8List? data,
}) async {
try {
if (contractAddress == null) {
@ -124,7 +125,7 @@ abstract class EVMChainClient {
final gasEstimate = await _client!.estimateGas(
sender: senderAddress,
to: EthereumAddress.fromHex(contractAddress),
data: transfer.encodeCall([
data: data ?? transfer.encodeCall([
toAddress,
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({
required Credentials privateKey,
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({
required EthereumAddress from,
required EthereumAddress to,

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:bip32/bip32.dart' as bip32;
import 'package:bip39/bip39.dart' as bip39;
@ -265,6 +266,7 @@ abstract class EVMChainWalletBase
required String? contractAddress,
required String receivingAddressHex,
required TransactionPriority priority,
Uint8List? data,
}) async {
try {
if (priority is EVMChainTransactionPriority) {
@ -286,6 +288,7 @@ abstract class EVMChainWalletBase
gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice),
toAddress: EthereumAddress.fromHex(receivingAddressHex),
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
data: data,
);
final totalGasFee = estimatedGas * maxFeePerGas;
@ -488,6 +491,43 @@ abstract class EVMChainWalletBase
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 {
try {
if (_isTransactionUpdating) {

View file

@ -11,6 +11,7 @@ class PendingEVMChainTransaction with PendingTransaction {
final BigInt fee;
final String amount;
final int exponent;
final bool isInfiniteApproval;
PendingEVMChainTransaction({
required this.sendTransaction,
@ -18,10 +19,12 @@ class PendingEVMChainTransaction with PendingTransaction {
required this.fee,
required this.amount,
required this.exponent,
this.isInfiniteApproval = false,
});
@override
String get amountFormatted {
if (isInfiniteApproval) return "";
final _amount = (BigInt.parse(amount) / BigInt.from(pow(10, exponent))).toString();
return _amount.substring(0, min(10, _amount.length));
}

View file

@ -35,6 +35,7 @@ import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart';
import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.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/integrations/deuro/savings_page.dart';
import 'package:cake_wallet/src/screens/settings/background_sync_page.dart';
import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
import 'package:cake_wallet/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart';
@ -43,6 +44,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/secure_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/tron/tron.dart';
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
@ -1511,5 +1513,9 @@ Future<void> setup({
getIt.registerFactory(() => DevBackgroundSyncLogsPage(getIt.get<BackgroundSyncLogsViewModel>()));
getIt.registerFactory(() => DEuroViewModel(getIt<AppStore>()));
getIt.registerFactory(() => DEuroSavingsPage(getIt<DEuroViewModel>()));
_isSetupFinished = true;
}

View file

@ -67,8 +67,7 @@ class CWEthereum extends Ethereum {
@override
String getPublicKey(WalletBase wallet) {
final privateKeyInUnitInt = (wallet as EthereumWallet).evmChainPrivateKey;
final publicKey = privateKeyInUnitInt.address.hex;
return publicKey;
return privateKeyInUnitInt.address.hex;
}
@override
@ -138,29 +137,24 @@ class CWEthereum extends Ethereum {
}
@override
List<Erc20Token> getERC20Currencies(WalletBase wallet) {
final ethereumWallet = wallet as EthereumWallet;
return ethereumWallet.erc20Currencies;
}
List<Erc20Token> getERC20Currencies(WalletBase wallet) =>
(wallet as EthereumWallet).erc20Currencies;
@override
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) async {
await (wallet as EthereumWallet).addErc20Token(token as Erc20Token);
}
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) =>
(wallet as EthereumWallet).addErc20Token(token as Erc20Token);
@override
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) async =>
await (wallet as EthereumWallet).deleteErc20Token(token as Erc20Token);
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) =>
(wallet as EthereumWallet).deleteErc20Token(token as Erc20Token);
@override
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) async =>
await (wallet as EthereumWallet).removeTokenTransactionsInHistory(token as Erc20Token);
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) =>
(wallet as EthereumWallet).removeTokenTransactionsInHistory(token as Erc20Token);
@override
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
final ethereumWallet = wallet as EthereumWallet;
return await ethereumWallet.getErc20Token(contractAddress, 'eth');
}
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) =>
(wallet as EthereumWallet).getErc20Token(contractAddress, 'eth');
@override
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
@ -177,23 +171,19 @@ class CWEthereum extends Ethereum {
}
@override
void updateEtherscanUsageState(WalletBase wallet, bool isEnabled) {
void updateEtherscanUsageState(WalletBase wallet, bool isEnabled) =>
(wallet as EthereumWallet).updateScanProviderUsageState(isEnabled);
}
@override
Web3Client? getWeb3Client(WalletBase wallet) {
return (wallet as EthereumWallet).getWeb3Client();
}
Web3Client? getWeb3Client(WalletBase wallet) => (wallet as EthereumWallet).getWeb3Client();
@override
String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
@override
void setLedgerConnection(
WalletBase wallet, ledger.LedgerConnection connection) {
void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection) {
((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials)
.setLedgerConnection(
connection, wallet.walletInfo.derivationInfo?.derivationPath);
.setLedgerConnection(connection, wallet.walletInfo.derivationInfo?.derivationPath);
}
@override
@ -219,4 +209,42 @@ class CWEthereum extends Ethereum {
final ethereumWallet = wallet as EthereumWallet;
return ethereumWallet.erc20Currencies.any((element) => element.contractAddress.toLowerCase() == contractAddress.toLowerCase());
}
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);
}

View file

@ -67,8 +67,7 @@ class CWPolygon extends Polygon {
@override
String getPublicKey(WalletBase wallet) {
final privateKeyInUnitInt = (wallet as PolygonWallet).evmChainPrivateKey;
final publicKey = privateKeyInUnitInt.address.hex;
return publicKey;
return privateKeyInUnitInt.address.hex;
}
@override
@ -137,28 +136,27 @@ class CWPolygon extends Polygon {
}
@override
List<Erc20Token> getERC20Currencies(WalletBase wallet) {
final polygonWallet = wallet as PolygonWallet;
return polygonWallet.erc20Currencies;
}
List<Erc20Token> getERC20Currencies(WalletBase wallet) =>
(wallet as PolygonWallet).erc20Currencies;
@override
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) async =>
await (wallet as PolygonWallet).addErc20Token(token as Erc20Token);
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) =>
(wallet as PolygonWallet).addErc20Token(token as Erc20Token);
@override
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) async =>
await (wallet as PolygonWallet).deleteErc20Token(token as Erc20Token);
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) =>
(wallet as PolygonWallet).deleteErc20Token(token as Erc20Token);
@override
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) async =>
await (wallet as PolygonWallet).removeTokenTransactionsInHistory(token as Erc20Token);
Future<void> removeTokenTransactionsInHistory(
WalletBase wallet, CryptoCurrency token) =>
(wallet as PolygonWallet)
.removeTokenTransactionsInHistory(token as Erc20Token);
@override
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
final polygonWallet = wallet as PolygonWallet;
return await polygonWallet.getErc20Token(contractAddress, 'polygon');
}
Future<Erc20Token?> getErc20Token(
WalletBase wallet, String contractAddress) =>
(wallet as PolygonWallet).getErc20Token(contractAddress, 'polygon');
@override
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
@ -176,16 +174,22 @@ class CWPolygon extends Polygon {
}
@override
void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled) {
void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled) =>
(wallet as PolygonWallet).updateScanProviderUsageState(isEnabled);
}
@override
Web3Client? getWeb3Client(WalletBase wallet) {
return (wallet as PolygonWallet).getWeb3Client();
}
Web3Client? getWeb3Client(WalletBase wallet) =>
(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
void setLedgerConnection(
@ -208,9 +212,10 @@ class CWPolygon extends Polygon {
}
@override
List<String> getDefaultTokenContractAddresses() {
return DefaultPolygonErc20Tokens().initialPolygonErc20Tokens.map((e) => e.contractAddress).toList();
}
List<String> getDefaultTokenContractAddresses() => DefaultPolygonErc20Tokens()
.initialPolygonErc20Tokens
.map((e) => e.contractAddress)
.toList();
@override
bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress) {

View file

@ -48,6 +48,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_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/nano/nano_change_rep_page.dart';
import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart';
@ -920,6 +921,11 @@ Route<dynamic> createRoute(RouteSettings settings) {
builder: (_) => getIt.get<DevSecurePreferencesPage>(),
);
case Routes.dEuroSavings:
return MaterialPageRoute<void>(
builder: (_) => getIt.get<DEuroSavingsPage>(),
);
default:
return MaterialPageRoute<void>(
builder: (_) => Scaffold(

View file

@ -127,4 +127,6 @@ class Routes {
static const walletGroupExistingSeedDescriptionPage = '/wallet_group_existing_seed_description_page';
static const walletSeedVerificationPage = '/wallet_seed_verification_page';
static const exchangeTradeExternalSendPage = '/exchange_trade_external_send_page';
static const dEuroSavings = '/integration/dEuro/savings';
}

View file

@ -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/dashboard_card_widget.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:cw_core/utils/print_verbose.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:url_launcher/url_launcher.dart';
class CakeFeaturesPage extends StatelessWidget {
CakeFeaturesPage({required this.dashboardViewModel, required this.cakeFeaturesViewModel});
CakeFeaturesPage(
{required this.dashboardViewModel, required this.cakeFeaturesViewModel});
final DashboardViewModel dashboardViewModel;
final CakeFeaturesViewModel cakeFeaturesViewModel;
@ -58,6 +59,23 @@ class CakeFeaturesPage extends StatelessWidget {
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(
isDarkTheme: dashboardViewModel.isDarkTheme,
shadowBlur: dashboardViewModel.getShadowBlur(),

View 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;
}
}

View file

@ -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,
),
],
),
),
),
]);
}
}

View 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,
),
),
);
}),
),
),
);
}

View file

@ -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,
),
),
]
],
),
),
),
],
);
}

View file

@ -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,
),
)
]),
);
}

View file

@ -109,6 +109,7 @@ class DashBoardRoundedCardWidget extends StatelessWidget {
],
),
),
Padding(padding: EdgeInsets.only(left: 10)),
if (image != null) image! else if (svgPicture != null) svgPicture!,
if (icon != null) icon!
],

View 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();
}
}

View file

@ -56,6 +56,7 @@
"apk_update": "تحديث APK",
"approve": "ﺪﻤﺘﻌﻳ",
"approve_request": "الموافقة على الطلب",
"approve_tokens": "الموافقة على الرموز",
"arrive_in_this_address": "سيصل ${currency} ${tag}إلى هذا العنوان",
"ascending": "تصاعدي",
"ask_each_time": "اسأل في كل مرة",
@ -244,6 +245,15 @@
"descending": "النزول",
"description": "ﻒﺻﻭ",
"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": "الجهاز يوقع",
"dfx_option_description": "شراء التشفير مع EUR & CHF. لعملاء البيع بالتجزئة والشركات في أوروبا",
"didnt_get_code": "لم تحصل على رمز؟",

View file

@ -56,6 +56,7 @@
"apk_update": "APK ъпдейт",
"approve": "Одобряване",
"approve_request": "Одобрете искане",
"approve_tokens": "Одобрете жетоните",
"arrive_in_this_address": "${currency} ${tag}ще отидат на този адрес",
"ascending": "Възходящ",
"ask_each_time": "Питайте всеки път",
@ -244,6 +245,15 @@
"descending": "Низходящ",
"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 Holdings",
"deuro_tx_commited_content": "Може да отнеме няколко секунди, за да може транзакцията да се потвърди и да бъде отразена на екрана",
"device_is_signing": "Устройството подписва",
"dfx_option_description": "Купете криптовалута с Eur & CHF. За търговски и корпоративни клиенти в Европа",
"didnt_get_code": "Не получихте код?",

View file

@ -56,6 +56,7 @@
"apk_update": "aktualizace APK",
"approve": "Schvalovat",
"approve_request": "Schválit žádost",
"approve_tokens": "Schválit tokeny",
"arrive_in_this_address": "${currency} ${tag}přijde na tuto adresu",
"ascending": "Vzestupné",
"ask_each_time": "Zeptejte se pokaždé",
@ -244,6 +245,15 @@
"descending": "Klesající",
"description": "Popis",
"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",
"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?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK-Update",
"approve": "Genehmigen",
"approve_request": "Anfrage genehmigen",
"approve_tokens": "Token genehmigen",
"arrive_in_this_address": "${currency} ${tag} wird an dieser Adresse ankommen",
"ascending": "Aufsteigend",
"ask_each_time": "Jedes Mal fragen",
@ -244,6 +245,15 @@
"descending": "Absteigend",
"description": "Beschreibung",
"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",
"dfx_option_description": "Kaufen Sie Krypto mit EUR & CHF. Für Einzelhandel und Unternehmenskunden in Europa",
"didnt_get_code": "Kein Code?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK update",
"approve": "Approve",
"approve_request": "Approve Request",
"approve_tokens": "Approve tokens",
"arrive_in_this_address": "${currency} ${tag}will arrive in this address",
"ascending": "Ascending",
"ask_each_time": "Ask each time",
@ -244,6 +245,15 @@
"descending": "Descending",
"description": "Description",
"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",
"dfx_option_description": "Buy crypto with EUR & CHF. For retail and corporate customers in Europe",
"didnt_get_code": "Didn't get code?",

View file

@ -56,6 +56,7 @@
"apk_update": "Actualización de APK",
"approve": "Aprobar",
"approve_request": "Aprobar la solicitud",
"approve_tokens": "Aprobar tokens",
"arrive_in_this_address": "${currency} ${tag}llegará a esta dirección",
"ascending": "Ascendente",
"ask_each_time": "Pregunta cada vez",
@ -244,6 +245,15 @@
"descending": "Descendente",
"description": "Descripción",
"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",
"dfx_option_description": "Compre cripto con EUR y CHF. Para clientes minoristas y corporativos en Europa",
"didnt_get_code": "¿No recibiste el código?",

View file

@ -56,6 +56,7 @@
"apk_update": "Mise à jour d'APK",
"approve": "Approuver",
"approve_request": "Approuver la demande",
"approve_tokens": "Approuver les jetons",
"arrive_in_this_address": "${currency} ${tag}arrivera à cette adresse",
"ascending": "Ascendant",
"ask_each_time": "Demander à chaque fois",
@ -244,6 +245,15 @@
"descending": "Descendant",
"description": "Description",
"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",
"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 ?",

View file

@ -56,6 +56,7 @@
"apk_update": "apk sabunta",
"approve": "Amincewa",
"approve_request": "Amince da bukata",
"approve_tokens": "Amince da Alamu",
"arrive_in_this_address": "${currency} ${tag} zai je wurin wannan adireshi",
"ascending": "Hau",
"ask_each_time": "Tambaya kowane lokaci",
@ -244,6 +245,15 @@
"descending": "Saukowa",
"description": "Bayani",
"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",
"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?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK अद्यतन",
"approve": "मंज़ूरी देना",
"approve_request": "अनुरोध को स्वीकृत करें",
"approve_tokens": "टोकन को मंजूरी देना",
"arrive_in_this_address": "${currency} ${tag}इस पते पर पहुंचेंगे",
"ascending": "आरोही",
"ask_each_time": "हर बार पूछें",
@ -244,6 +245,15 @@
"descending": "अवरोही",
"description": "विवरण",
"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": "उपकरण हस्ताक्षर कर रहा है",
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
"didnt_get_code": "कोड नहीं मिला?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK ažuriranje",
"approve": "Odobriti",
"approve_request": "Odobriti zahtjev",
"approve_tokens": "Odobriti tokene",
"arrive_in_this_address": "${currency} ${tag}će stići na ovu adresu",
"ascending": "Uzlazni",
"ask_each_time": "Pitajte svaki put",
@ -244,6 +245,15 @@
"descending": "Silazni",
"description": "Opis",
"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",
"dfx_option_description": "Kupite kriptovalute s Eur & CHF. Za maloprodajne i korporativne kupce u Europi",
"didnt_get_code": "Ne dobivate kod?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK թարմացում",
"approve": "Հաստատել",
"approve_request": "Հաստատում է հայցը",
"approve_tokens": "Հաստատում է նշանները",
"arrive_in_this_address": "${currency} ${tag}կժամանի այս հասցեում",
"ascending": "Աճող",
"ask_each_time": "Հարցնել ամեն անգամ",
@ -244,6 +245,15 @@
"descending": "Նվազող",
"description": "Նկարագրություն",
"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": "Սարքը ստորագրում է",
"dfx_option_description": "Գնեք կրիպտոարժույթ EUR և CHF: Կորպորատիվ և մանրածախ հաճախորդների համար Եվրոպայում",
"didnt_get_code": "Չեք ստացել կոդը?",

View file

@ -56,6 +56,7 @@
"apk_update": "Pembaruan APK",
"approve": "Menyetujui",
"approve_request": "Menyetujui permintaan",
"approve_tokens": "Menyetujui token",
"arrive_in_this_address": "${currency} ${tag} akan tiba di alamat ini",
"ascending": "Naik",
"ask_each_time": "Tanyakan setiap kali",
@ -244,6 +245,15 @@
"descending": "Menurun",
"description": "Keterangan",
"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",
"dfx_option_description": "Beli crypto dengan EUR & CHF. Untuk pelanggan ritel dan perusahaan di Eropa",
"didnt_get_code": "Tidak mendapatkan kode?",

View file

@ -56,6 +56,7 @@
"apk_update": "Aggiornamento APK",
"approve": "Approvare",
"approve_request": "Approvare la richiesta",
"approve_tokens": "Approvare i token",
"arrive_in_this_address": "${currency} ${tag}arriverà a questo indirizzo",
"ascending": "Ascendente",
"ask_each_time": "Chiedi ogni volta",
@ -244,6 +245,15 @@
"descending": "Discendente",
"description": "Descrizione",
"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",
"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?",

View file

@ -56,6 +56,7 @@
"apk_update": "APKアップデート",
"approve": "承認する",
"approve_request": "リクエストを承認します",
"approve_tokens": "トークンを承認します",
"arrive_in_this_address": "${currency} ${tag}はこの住所に到着します",
"ascending": "上昇",
"ask_each_time": "毎回尋ねてください",
@ -244,6 +245,15 @@
"descending": "下降",
"description": "説明",
"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": "デバイスが署名しています",
"dfx_option_description": "EURCHFで暗号を購入します。ヨーロッパの小売および企業の顧客向け",
"didnt_get_code": "コードを取得しませんか?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK 업데이트",
"approve": "승인",
"approve_request": "요청 승인",
"approve_tokens": "토큰을 승인합니다",
"arrive_in_this_address": "${currency} ${tag}이(가) 이 주소로 도착합니다",
"ascending": "오름차순",
"ask_each_time": "매번 묻기",
@ -244,6 +245,15 @@
"descending": "내림차순",
"description": "설명",
"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": "장치가 서명 중입니다",
"dfx_option_description": "EUR 및 CHF로 암호화폐 구매. 유럽의 개인 및 기업 고객 대상",
"didnt_get_code": "코드를 받지 못했나요?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK အပ်ဒိတ်",
"approve": "လက်မခံပါ။",
"approve_request": "တောင်းဆိုမှုကိုအတည်ပြု",
"approve_tokens": "တိုကင်အတည်ပြု",
"arrive_in_this_address": "${currency} ${tag}ဤလိပ်စာသို့ ရောက်ရှိပါမည်။",
"ascending": "တက်",
"ask_each_time": "တစ်ခုချင်းစီကိုအချိန်မေးပါ",
@ -244,6 +245,15 @@
"descending": "ဆင်း",
"description": "ဖော်ပြချက်",
"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": "ကိရိယာလက်မှတ်ထိုးနေသည်",
"dfx_option_description": "Crypto ကို EUR & CHF ဖြင့် 0 ယ်ပါ။ လက်လီရောင်းဝယ်မှုနှင့်ဥရောပရှိကော်ပိုရိတ်ဖောက်သည်များအတွက်",
"didnt_get_code": "ကုဒ်ကို မရဘူးလား?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK-update",
"approve": "Goedkeuren",
"approve_request": "Het verzoek goedkeuren",
"approve_tokens": "Tokens goedkeuren",
"arrive_in_this_address": "${currency} ${tag}komt aan op dit adres",
"ascending": "Stijgend",
"ask_each_time": "Vraag het elke keer",
@ -244,6 +245,15 @@
"descending": "Aflopend",
"description": "Beschrijving",
"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",
"dfx_option_description": "Koop crypto met EUR & CHF. Voor retail- en zakelijke klanten in Europa",
"didnt_get_code": "Geen code?",

View file

@ -56,6 +56,7 @@
"apk_update": "Aktualizacja APK",
"approve": "Zatwierdzić",
"approve_request": "Zatwierdzić żądanie",
"approve_tokens": "Zatwierdzić tokeny",
"arrive_in_this_address": "${currency} ${tag}dotrze na ten adres",
"ascending": "Wznoszący się",
"ask_each_time": "Zapytaj za każdym razem",
@ -244,6 +245,15 @@
"descending": "Malejąco",
"description": "Opis",
"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",
"dfx_option_description": "Kup krypto za EUR & CHF. Dla klientów prywatnych i korporacyjnych w Europie",
"didnt_get_code": "Nie dostałeś kodu?",

View file

@ -56,6 +56,7 @@
"apk_update": "Atualização de APK",
"approve": "Aprovar",
"approve_request": "Aprovar solicitação",
"approve_tokens": "Aprovar tokens",
"arrive_in_this_address": "${currency} ${tag}chegará neste endereço",
"ascending": "Ascendente",
"ask_each_time": "Pergunte cada vez",
@ -244,6 +245,15 @@
"descending": "descendente",
"description": "Descrição",
"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",
"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?",

View file

@ -56,6 +56,7 @@
"apk_update": "Обновление APK",
"approve": "Утвердить",
"approve_request": "Утвердить запрос",
"approve_tokens": "Одобрить токены",
"arrive_in_this_address": "${currency} ${tag}придет на этот адрес",
"ascending": "Восходящий",
"ask_each_time": "Спросите каждый раз",
@ -244,6 +245,15 @@
"descending": "Нисходящий",
"description": "Описание",
"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": "Устройство подписывает",
"dfx_option_description": "Купить крипто с Eur & CHF. Для розничных и корпоративных клиентов в Европе",
"didnt_get_code": "Не получить код?",

View file

@ -56,6 +56,7 @@
"apk_update": "ปรับปรุง APK",
"approve": "อนุมัติ",
"approve_request": "อนุมัติคำขอ",
"approve_tokens": "อนุมัติโทเค็น",
"arrive_in_this_address": "${currency} ${tag}จะมาถึงที่อยู่นี้",
"ascending": "จากน้อยไปมาก",
"ask_each_time": "ถามทุกครั้ง",
@ -244,6 +245,15 @@
"descending": "ลงมา",
"description": "คำอธิบาย",
"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": "อุปกรณ์กำลังลงนาม",
"dfx_option_description": "ซื้อ crypto ด้วย Eur & CHF สำหรับลูกค้ารายย่อยและลูกค้าในยุโรป",
"didnt_get_code": "ไม่ได้รับรหัส?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK update",
"approve": "Aprubahan",
"approve_request": "Aprubahan ang kahilingan",
"approve_tokens": "Aprubahan ang mga token",
"arrive_in_this_address": "Ang ${currency} ${tag} ay darating sa address na ito",
"ascending": "Umakyat",
"ask_each_time": "Magtanong sa tuwing",
@ -244,6 +245,15 @@
"descending": "Pababang",
"description": "Paglalarawan",
"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",
"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?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK güncellemesi",
"approve": "Onaylamak",
"approve_request": "Talebi Onaylama",
"approve_tokens": "Jetonları onaylayın",
"arrive_in_this_address": "${currency} ${tag}bu adrese ulaşacak",
"ascending": "Yükselen",
"ask_each_time": "Her seferinde sor",
@ -244,6 +245,15 @@
"descending": "Azalan",
"description": "Tanım",
"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",
"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?",

View file

@ -56,6 +56,7 @@
"apk_update": "Оновлення APK",
"approve": "Затвердити",
"approve_request": "Запитайте запит",
"approve_tokens": "Затвердити токени",
"arrive_in_this_address": "${currency} ${tag}надійде на цю адресу",
"ascending": "Висхід",
"ask_each_time": "Запитайте кожен раз",
@ -244,6 +245,15 @@
"descending": "Низхідний",
"description": "опис",
"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": "Пристрій підписується",
"dfx_option_description": "Купуйте криптовалюту з EUR & CHF. Для роздрібних та корпоративних клієнтів у Європі",
"didnt_get_code": "Не отримали код?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK اپ ڈیٹ",
"approve": "ﻭﺮﮐ ﺭﻮﻈﻨﻣ",
"approve_request": "درخواست کو منظور کریں",
"approve_tokens": "ٹوکن کو منظور کریں",
"arrive_in_this_address": "${currency} ${tag}اس پتے پر پہنچے گا۔",
"ascending": "چڑھنے",
"ask_each_time": "ہر بار پوچھیں",
@ -244,6 +245,15 @@
"descending": "اترتے ہوئے",
"description": "ﻞﯿﺼﻔﺗ",
"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": "ڈیوائس پر دستخط کر رہے ہیں",
"dfx_option_description": "یورو اور سی ایچ ایف کے ساتھ کرپٹو خریدیں۔ یورپ میں خوردہ اور کارپوریٹ صارفین کے لئے",
"didnt_get_code": "کوڈ نہیں ملتا؟",

View file

@ -56,6 +56,7 @@
"apk_update": "Cập nhật APK",
"approve": "Phê duyệt",
"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",
"ascending": "Tăng dần",
"ask_each_time": "Hỏi mỗi lần",
@ -243,6 +244,15 @@
"descending": "Giảm dần",
"description": "Mô tả",
"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ý",
"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ã?",

View file

@ -56,6 +56,7 @@
"apk_update": "Àtúnse áàpù títun wà",
"approve": "Fi ọwọ si",
"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ìí",
"ascending": "Goke",
"ask_each_time": "Beere lọwọ kọọkan",
@ -244,6 +245,15 @@
"descending": "Sọkalẹ",
"description": "Apejuwe",
"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ẹ",
"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?",

View file

@ -56,6 +56,7 @@
"apk_update": "APK更新",
"approve": "批准",
"approve_request": "批准请求",
"approve_tokens": "批准令牌",
"arrive_in_this_address": "${currency} ${tag}将到达此地址",
"ascending": "上升",
"ask_each_time": "每次问",
@ -244,6 +245,15 @@
"descending": "下降",
"description": "描述",
"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": "设备正在签名",
"dfx_option_description": "用EurChf购买加密货币。对于欧洲的零售和企业客户",
"didnt_get_code": "没有获取代码?",

View file

@ -670,6 +670,7 @@ import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/erc20_token.dart';
import 'package:cw_core/hardware/hardware_account_data.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_priority.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_service.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';
@ -745,6 +747,16 @@ abstract class Ethereum {
Web3Client? getWeb3Client(WalletBase wallet);
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);
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
List<String> getDefaultTokenContractAddresses();
@ -778,6 +790,7 @@ import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/erc20_token.dart';
import 'package:cw_core/hardware/hardware_account_data.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_priority.dart';
import 'package:cw_core/wallet_base.dart';
@ -848,6 +861,8 @@ abstract class Polygon {
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token);
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);
void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled);
Web3Client? getWeb3Client(WalletBase wallet);