Merge remote-tracking branch 'origin/main' into CW-453-bitcoin-silent-payments

This commit is contained in:
Rafael Saes 2023-12-13 16:28:13 -03:00
commit 8627698416
62 changed files with 389 additions and 301 deletions

View file

@ -119,6 +119,7 @@ jobs:
cd /opt/android/cake_wallet
touch lib/.secrets.g.dart
touch cw_ethereum/lib/.secrets.g.dart
touch cw_polygon/lib/.secrets.g.dart
echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart
echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart
echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart
@ -146,13 +147,13 @@ jobs:
echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart
echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart
echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart
echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart
echo "const exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
echo "const robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart
echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart
echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart
echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart
- name: Rename app
run: echo -e "id=com.cakewallet.test\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties

View file

@ -1,6 +1,6 @@
-
uri: polygon-rpc.com
-
uri: polygon-bor.publicnode.com
-
uri: polygon-rpc.com
-
uri: polygon.llamarpc.com

View file

@ -4,7 +4,10 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_core/balance.dart';
class ElectrumBalance extends Balance {
const ElectrumBalance({required this.confirmed, required this.unconfirmed, required this.frozen})
const ElectrumBalance(
{required this.confirmed,
required this.unconfirmed,
required this.frozen})
: super(confirmed, unconfirmed);
static ElectrumBalance? fromJSON(String? jsonSource) {
@ -25,16 +28,19 @@ class ElectrumBalance extends Balance {
final int frozen;
@override
String get formattedAvailableBalance => bitcoinAmountToString(amount: confirmed - frozen);
String get formattedAvailableBalance =>
bitcoinAmountToString(amount: confirmed - unconfirmed.abs() - frozen);
@override
String get formattedAdditionalBalance => bitcoinAmountToString(amount: unconfirmed);
String get formattedAdditionalBalance =>
bitcoinAmountToString(amount: unconfirmed);
String get formattedFrozenBalance {
@override
String get formattedUnAvailableBalance {
final frozenFormatted = bitcoinAmountToString(amount: frozen);
return frozenFormatted == '0.0' ? '' : frozenFormatted;
}
String toJSON() =>
json.encode({'confirmed': confirmed, 'unconfirmed': unconfirmed, 'frozen': frozen});
String toJSON() => json.encode(
{'confirmed': confirmed, 'unconfirmed': unconfirmed, 'frozen': frozen});
}

View file

@ -87,7 +87,7 @@ abstract class ElectrumWalletBase
bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0");
static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
inputsCount * 146 + outputsCounts * 33 + 8;
inputsCount * 68 + outputsCounts * 34 + 10;
final bitcoin.HDWallet hd;
final String mnemonic;

View file

@ -93,6 +93,8 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
CryptoCurrency.dydx,
CryptoCurrency.steth,
CryptoCurrency.banano,
CryptoCurrency.usdtPoly,
CryptoCurrency.usdcEPoly,
];
static const havenCurrencies = [
@ -202,6 +204,8 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
static const dydx = CryptoCurrency(title: 'DYDX', tag: 'ETH', fullName: 'dYdX', raw: 84, name: 'dydx', iconPath: 'assets/images/dydx_icon.png', decimals: 18);
static const steth = CryptoCurrency(title: 'STETH', tag: 'ETH', fullName: 'Lido Staked Ethereum', raw: 85, name: 'steth', iconPath: 'assets/images/steth_icon.png', decimals: 18);
static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29);
static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POLY', fullName: 'Tether USD (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/images/usdt_icon.png', decimals: 6);
static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POLY', fullName: 'USD Coin (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/images/usdc_icon.png', decimals: 6);
static final Map<int, CryptoCurrency> _rawCurrencyMap =

View file

@ -18,6 +18,8 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin {
bool _enabled;
@HiveField(5)
final String? iconPath;
@HiveField(6)
final String? tag;
bool get enabled => _enabled;
@ -30,30 +32,31 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin {
required this.decimal,
bool enabled = true,
this.iconPath,
this.tag,
}) : _enabled = enabled,
super(
name: symbol.toLowerCase(),
title: symbol.toUpperCase(),
fullName: name,
tag: "ETH",
iconPath: iconPath,
decimals: decimal
);
name: symbol.toLowerCase(),
title: symbol.toUpperCase(),
fullName: name,
tag: tag,
iconPath: iconPath,
decimals: decimal);
Erc20Token.copyWith(Erc20Token other, String? icon)
Erc20Token.copyWith(Erc20Token other, String? icon, String? tag)
: this.name = other.name,
this.symbol = other.symbol,
this.contractAddress = other.contractAddress,
this.decimal = other.decimal,
this._enabled = other.enabled,
this.tag = tag,
this.iconPath = icon,
super(
name: other.name,
title: other.symbol.toUpperCase(),
fullName: other.name,
tag: "ETH",
tag: tag,
iconPath: icon,
decimals: other.decimal
decimals: other.decimal,
);
static const typeId = ERC20_TOKEN_TYPE_ID;
@ -61,7 +64,8 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin {
static const polygonBoxName = ' PolygonErc20Tokens';
@override
bool operator ==(other) => (other is Erc20Token && other.contractAddress == contractAddress) ||
bool operator ==(other) =>
(other is Erc20Token && other.contractAddress == contractAddress) ||
(other is CryptoCurrency && other.title == title);
@override

View file

@ -214,7 +214,7 @@ class Node extends HiveObject with Keyable {
}
Future<bool> requestNodeWithProxy() async {
if (!isValidProxyAddress/* && !Tor.instance.enabled*/) {
if (!isValidProxyAddress /* && !Tor.instance.enabled*/) {
return false;
}

View file

@ -293,17 +293,13 @@ class DefaultErc20Tokens {
];
List<Erc20Token> get initialErc20Tokens => _defaultTokens.map((token) {
String? iconPath;
try {
iconPath = CryptoCurrency.all
.firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase())
.iconPath;
} catch (_) {}
String? iconPath;
try {
iconPath = CryptoCurrency.all
.firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase())
.iconPath;
} catch (_) {}
if (iconPath != null) {
return Erc20Token.copyWith(token, iconPath);
}
return token;
}).toList();
return Erc20Token.copyWith(token, iconPath, 'ETH');
}).toList();
}

View file

@ -78,19 +78,18 @@ class EthereumClient {
currency == CryptoCurrency.maticpoly ||
contractAddress != null);
bool _isEVMCompatibleChain = currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly;
bool _isEVMCompatibleChain =
currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly;
final price = _client!.getGasPrice();
final Transaction transaction = Transaction(
final Transaction transaction = createTransaction(
from: privateKey.address,
to: EthereumAddress.fromHex(toAddress),
maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip),
value: _isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(),
amount: _isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(),
);
final chainId = _getChainIdForCurrency(currency);
final signedTransaction =
await _client!.signTransaction(privateKey, transaction, chainId: chainId);
@ -124,18 +123,27 @@ class EthereumClient {
);
}
int _getChainIdForCurrency(CryptoCurrency currency) {
switch (currency) {
case CryptoCurrency.maticpoly:
return 137;
case CryptoCurrency.eth:
default:
return 1;
}
int get chainId => 1;
Transaction createTransaction({
required EthereumAddress from,
required EthereumAddress to,
required EtherAmount amount,
EtherAmount? maxPriorityFeePerGas,
}) {
return Transaction(
from: from,
to: to,
maxPriorityFeePerGas: maxPriorityFeePerGas,
value: amount,
);
}
Future<String> sendTransaction(Uint8List signedTransaction) async =>
await _client!.sendRawTransaction(prependTransactionType(0x02, signedTransaction));
await _client!.sendRawTransaction(prepareSignedTransactionForSending(signedTransaction));
Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) =>
prependTransactionType(0x02, signedTransaction);
Future getTransactionDetails(String transactionHash) async {
// Wait for the transaction receipt to become available

View file

@ -14,7 +14,7 @@ import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_ethereum/default_erc20_tokens.dart';
import 'package:cw_ethereum/default_ethereum_erc20_tokens.dart';
import 'package:cw_ethereum/erc20_balance.dart';
import 'package:cw_ethereum/ethereum_client.dart';
import 'package:cw_ethereum/ethereum_exceptions.dart';
@ -429,6 +429,7 @@ abstract class EthereumWalletBase
contractAddress: token.contractAddress,
decimal: token.decimal,
enabled: token.enabled,
tag: token.tag ?? "ETH",
iconPath: iconPath,
);
@ -492,7 +493,7 @@ abstract class EthereumWalletBase
_transactionsUpdateTimer!.cancel();
}
_transactionsUpdateTimer = Timer.periodic(Duration(seconds: 10), (_) {
_transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 10), (_) {
_updateTransactions();
_updateBalance();
});
@ -508,7 +509,7 @@ abstract class EthereumWalletBase
}
@override
String signMessage(String message, {String? address = null}) =>
String signMessage(String message, {String? address}) =>
bytesToHex(_ethPrivateKey.signPersonalMessageToUint8List(ascii.encode(message)));
Web3Client? getWeb3Client() => _client.getWeb3Client();

View file

@ -29,7 +29,7 @@ class DefaultPolygonErc20Tokens {
symbol: "USDC.e",
contractAddress: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
decimal: 6,
enabled: false,
enabled: true,
),
Erc20Token(
name: "Avalanche Token",
@ -73,14 +73,10 @@ class DefaultPolygonErc20Tokens {
try {
iconPath = CryptoCurrency.all
.firstWhere((element) =>
element.title.toUpperCase() == token.symbol.toUpperCase())
element.title.toUpperCase() == token.symbol.split(".").first.toUpperCase())
.iconPath;
} catch (_) {}
if (iconPath != null) {
return Erc20Token.copyWith(token, iconPath);
}
return token;
return Erc20Token.copyWith(token, iconPath, 'POLY');
}).toList();
}

View file

@ -3,8 +3,30 @@ import 'dart:convert';
import 'package:cw_ethereum/ethereum_client.dart';
import 'package:cw_polygon/polygon_transaction_model.dart';
import 'package:cw_ethereum/.secrets.g.dart' as secrets;
import 'package:flutter/foundation.dart';
import 'package:web3dart/web3dart.dart';
class PolygonClient extends EthereumClient {
@override
Transaction createTransaction({
required EthereumAddress from,
required EthereumAddress to,
required EtherAmount amount,
EtherAmount? maxPriorityFeePerGas,
}) {
return Transaction(
from: from,
to: to,
value: amount,
);
}
@override
Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) => signedTransaction;
@override
int get chainId => 137;
@override
Future<List<PolygonTransactionModel>> fetchTransactions(String address,
{String? contractAddress}) async {
@ -27,7 +49,6 @@ class PolygonClient extends EthereumClient {
return [];
} catch (e) {
print(e);
return [];
}
}

View file

@ -16,10 +16,9 @@ import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_ethereum/erc20_balance.dart';
import 'package:cw_ethereum/ethereum_formatter.dart';
import 'package:cw_ethereum/ethereum_transaction_model.dart';
import 'package:cw_ethereum/file.dart';
import 'package:cw_core/erc20_token.dart';
import 'package:cw_polygon/default_erc20_tokens.dart';
import 'package:cw_polygon/default_polygon_erc20_tokens.dart';
import 'package:cw_polygon/polygon_client.dart';
import 'package:cw_polygon/polygon_exceptions.dart';
import 'package:cw_polygon/polygon_formatter.dart';
@ -42,28 +41,26 @@ part 'polygon_wallet.g.dart';
class PolygonWallet = PolygonWalletBase with _$PolygonWallet;
abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
PolygonTransactionHistory, PolygonTransactionInfo> with Store {
abstract class PolygonWalletBase
extends WalletBase<ERC20Balance, PolygonTransactionHistory, PolygonTransactionInfo> with Store {
PolygonWalletBase({
required WalletInfo walletInfo,
String? mnemonic,
String? privateKey,
required String password,
ERC20Balance? initialBalance,
}) : syncStatus = NotConnectedSyncStatus(),
}) : syncStatus = const NotConnectedSyncStatus(),
_password = password,
_mnemonic = mnemonic,
_hexPrivateKey = privateKey,
_isTransactionUpdating = false,
_client = PolygonClient(),
walletAddresses = PolygonWalletAddresses(walletInfo),
balance = ObservableMap<CryptoCurrency, ERC20Balance>.of({
CryptoCurrency.maticpoly: initialBalance ?? ERC20Balance(BigInt.zero)
}),
balance = ObservableMap<CryptoCurrency, ERC20Balance>.of(
{CryptoCurrency.maticpoly: initialBalance ?? ERC20Balance(BigInt.zero)}),
super(walletInfo) {
this.walletInfo = walletInfo;
transactionHistory =
PolygonTransactionHistory(walletInfo: walletInfo, password: password);
transactionHistory = PolygonTransactionHistory(walletInfo: walletInfo, password: password);
if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) {
CakeHive.registerAdapter(Erc20TokenAdapter());
@ -80,9 +77,9 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
late final EthPrivateKey _polygonPrivateKey;
EthPrivateKey get polygonPrivateKey => _polygonPrivateKey;
late final PolygonClient _client;
late PolygonClient _client;
EthPrivateKey get polygonPrivateKey => _polygonPrivateKey;
int? _gasPrice;
int? _estimatedGas;
@ -102,11 +99,11 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
@observable
late ObservableMap<CryptoCurrency, ERC20Balance> balance;
Completer<SharedPreferences> _sharedPrefs = Completer();
final Completer<SharedPreferences> _sharedPrefs = Completer();
Future<void> init() async {
polygonErc20TokensBox =
await CakeHive.openBox<Erc20Token>(Erc20Token.polygonBoxName);
polygonErc20TokensBox = await CakeHive.openBox<Erc20Token>(
"${walletInfo.name.replaceAll(" ", "_")}_${Erc20Token.polygonBoxName}");
await walletAddresses.init();
await transactionHistory.init();
_polygonPrivateKey = await getPrivateKey(
@ -122,8 +119,7 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
try {
if (priority is PolygonTransactionPriority) {
final priorityFee =
EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt();
final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt();
return (_gasPrice! + priorityFee) * (_estimatedGas ?? 0);
}
@ -168,33 +164,29 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
@override
Future<PendingTransaction> createTransaction(Object credentials) async {
final _credentials = credentials as PolygonTransactionCredentials;
final outputs = _credentials.outputs;
final credentials0 = credentials as PolygonTransactionCredentials;
final outputs = credentials0.outputs;
final hasMultiDestination = outputs.length > 1;
final CryptoCurrency transactionCurrency = balance.keys
.firstWhere((element) => element.title == _credentials.currency.title);
final CryptoCurrency transactionCurrency =
balance.keys.firstWhere((element) => element.title == credentials0.currency.title);
final _erc20Balance = balance[transactionCurrency]!;
final erc20Balance = balance[transactionCurrency]!;
BigInt totalAmount = BigInt.zero;
int exponent =
transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18;
int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18;
num amountToPolygonMultiplier = pow(10, exponent);
// so far this can not be made with Polygon as Polygon does not support multiple recipients
if (hasMultiDestination) {
if (outputs.any(
(item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) {
if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) {
throw PolygonTransactionCreationException(transactionCurrency);
}
final totalOriginalAmount = PolygonFormatter.parsePolygonAmountToDouble(
outputs.fold(
0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)));
totalAmount =
BigInt.from(totalOriginalAmount * amountToPolygonMultiplier);
outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)));
totalAmount = BigInt.from(totalOriginalAmount * amountToPolygonMultiplier);
if (_erc20Balance.balance < totalAmount) {
if (erc20Balance.balance < totalAmount) {
throw PolygonTransactionCreationException(transactionCurrency);
}
} else {
@ -203,35 +195,33 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
// then no need to subtract the fees from the amount if send all
final BigInt allAmount;
if (transactionCurrency is Erc20Token) {
allAmount = _erc20Balance.balance;
allAmount = erc20Balance.balance;
} else {
allAmount = _erc20Balance.balance -
BigInt.from(calculateEstimatedFee(_credentials.priority!, null));
allAmount =
erc20Balance.balance - BigInt.from(calculateEstimatedFee(credentials0.priority!, null));
}
final totalOriginalAmount = EthereumFormatter.parseEthereumAmountToDouble(
output.formattedCryptoAmount ?? 0);
totalAmount = output.sendAll
? allAmount
: BigInt.from(totalOriginalAmount * amountToPolygonMultiplier);
final totalOriginalAmount =
EthereumFormatter.parseEthereumAmountToDouble(output.formattedCryptoAmount ?? 0);
totalAmount =
output.sendAll ? allAmount : BigInt.from(totalOriginalAmount * amountToPolygonMultiplier);
if (_erc20Balance.balance < totalAmount) {
if (erc20Balance.balance < totalAmount) {
throw PolygonTransactionCreationException(transactionCurrency);
}
}
final pendingPolygonTransaction = await _client.signTransaction(
privateKey: _polygonPrivateKey,
toAddress: _credentials.outputs.first.isParsedAddress
? _credentials.outputs.first.extractedAddress!
: _credentials.outputs.first.address,
toAddress: credentials0.outputs.first.isParsedAddress
? credentials0.outputs.first.extractedAddress!
: credentials0.outputs.first.address,
amount: totalAmount.toString(),
gas: _estimatedGas!,
priority: _credentials.priority!,
priority: credentials0.priority!,
currency: transactionCurrency,
exponent: exponent,
contractAddress: transactionCurrency is Erc20Token
? transactionCurrency.contractAddress
: null,
contractAddress:
transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null,
);
return pendingPolygonTransaction;
@ -262,15 +252,16 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
final address = _polygonPrivateKey.address.hex;
final transactions = await _client.fetchTransactions(address);
final List<Future<List<PolygonTransactionModel>>> polygonErc20TokensTransactions =
[];
final List<Future<List<PolygonTransactionModel>>> polygonErc20TokensTransactions = [];
for (var token in balance.keys) {
if (token is Erc20Token) {
polygonErc20TokensTransactions.add(_client.fetchTransactions(
address,
contractAddress: token.contractAddress,
) as Future<List<PolygonTransactionModel>>);
polygonErc20TokensTransactions.add(
_client.fetchTransactions(
address,
contractAddress: token.contractAddress,
),
);
}
}
@ -294,8 +285,7 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
isPending: false,
date: transactionModel.date,
confirmations: transactionModel.confirmations,
ethFee:
BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice,
ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice,
exponent: transactionModel.tokenDecimal ?? 18,
tokenSymbol: transactionModel.tokenSymbol ?? "MATIC",
to: transactionModel.to,
@ -337,8 +327,8 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
_gasPrice = await _client.getGasUnitPrice();
_estimatedGas = await _client.getEstimatedGas();
Timer.periodic(const Duration(minutes: 1),
(timer) async => _gasPrice = await _client.getGasUnitPrice());
Timer.periodic(
const Duration(minutes: 1), (timer) async => _gasPrice = await _client.getGasUnitPrice());
Timer.periodic(const Duration(seconds: 10),
(timer) async => _estimatedGas = await _client.getEstimatedGas());
@ -348,8 +338,7 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
}
}
Future<String> makePath() async =>
pathForWallet(name: walletInfo.name, type: walletInfo.type);
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
String toJSON() => json.encode({
'mnemonic': _mnemonic,
@ -367,8 +356,7 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
final data = json.decode(jsonSource) as Map;
final mnemonic = data['mnemonic'] as String?;
final privateKey = data['private_key'] as String?;
final balance = ERC20Balance.fromJSON(data['balance'] as String) ??
ERC20Balance(BigInt.zero);
final balance = ERC20Balance.fromJSON(data['balance'] as String) ?? ERC20Balance(BigInt.zero);
return PolygonWallet(
walletInfo: walletInfo,
@ -418,14 +406,14 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
final root = bip32.BIP32.fromSeed(seed);
const _hdPathPolygon = "m/44'/60'/0'/0";
const hdPathPolygon = "m/44'/60'/0'/0";
const index = 0;
final addressAtIndex = root.derivePath("$_hdPathPolygon/$index");
final addressAtIndex = root.derivePath("$hdPathPolygon/$index");
return EthPrivateKey.fromHex(
HEX.encode(addressAtIndex.privateKey as List<int>));
return EthPrivateKey.fromHex(HEX.encode(addressAtIndex.privateKey as List<int>));
}
@override
Future<void>? updateBalance() async => await _updateBalance();
List<Erc20Token> get erc20Currencies => polygonErc20TokensBox.values.toList();
@ -434,29 +422,29 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
String? iconPath;
try {
iconPath = CryptoCurrency.all
.firstWhere((element) =>
element.title.toUpperCase() == token.symbol.toUpperCase())
.firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase())
.iconPath;
} catch (_) {}
final _token = Erc20Token(
final token0 = Erc20Token(
name: token.name,
symbol: token.symbol,
contractAddress: token.contractAddress,
decimal: token.decimal,
enabled: token.enabled,
tag: token.tag ?? "POLY",
iconPath: iconPath,
);
await polygonErc20TokensBox.put(_token.contractAddress, _token);
await polygonErc20TokensBox.put(token0.contractAddress, token0);
if (_token.enabled) {
balance[_token] = await _client.fetchERC20Balances(
if (token0.enabled) {
balance[token0] = await _client.fetchERC20Balances(
_polygonPrivateKey.address,
_token.contractAddress,
token0.contractAddress,
);
} else {
balance.remove(_token);
balance.remove(token0);
}
}
@ -476,8 +464,7 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
}
void addInitialTokens() {
final initialErc20Tokens =
DefaultPolygonErc20Tokens().initialPolygonErc20Tokens;
final initialErc20Tokens = DefaultPolygonErc20Tokens().initialPolygonErc20Tokens;
for (var token in initialErc20Tokens) {
polygonErc20TokensBox.put(token.contractAddress, token);
@ -486,26 +473,20 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
@override
Future<void> renameWalletFiles(String newWalletName) async {
final currentWalletPath =
await pathForWallet(name: walletInfo.name, type: type);
final currentWalletPath = await pathForWallet(name: walletInfo.name, type: type);
final currentWalletFile = File(currentWalletPath);
final currentDirPath =
await pathForWalletDir(name: walletInfo.name, type: type);
final currentTransactionsFile =
File('$currentDirPath/$transactionsHistoryFileName');
final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: type);
final currentTransactionsFile = File('$currentDirPath/$transactionsHistoryFileName');
// Copies current wallet files into new wallet name's dir and files
if (currentWalletFile.existsSync()) {
final newWalletPath =
await pathForWallet(name: newWalletName, type: type);
final newWalletPath = await pathForWallet(name: newWalletName, type: type);
await currentWalletFile.copy(newWalletPath);
}
if (currentTransactionsFile.existsSync()) {
final newDirPath =
await pathForWalletDir(name: newWalletName, type: type);
await currentTransactionsFile
.copy('$newDirPath/$transactionsHistoryFileName');
final newDirPath = await pathForWalletDir(name: newWalletName, type: type);
await currentTransactionsFile.copy('$newDirPath/$transactionsHistoryFileName');
}
// Delete old name's dir and files
@ -517,7 +498,7 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
_transactionsUpdateTimer!.cancel();
}
_transactionsUpdateTimer = Timer.periodic(Duration(seconds: 10), (_) {
_transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 10), (_) {
_updateTransactions();
_updateBalance();
});
@ -533,8 +514,8 @@ abstract class PolygonWalletBase extends WalletBase<ERC20Balance,
}
@override
String signMessage(String message, {String? address = null}) => bytesToHex(
_polygonPrivateKey.signPersonalMessageToUint8List(ascii.encode(message)));
String signMessage(String message, {String? address}) =>
bytesToHex(_polygonPrivateKey.signPersonalMessageToUint8List(ascii.encode(message)));
Web3Client? getWeb3Client() => _client.getWeb3Client();
}

View file

@ -32,6 +32,8 @@ class AddressValidator extends TextValidator {
return '[0-9a-zA-Z_]';
case CryptoCurrency.usdc:
case CryptoCurrency.usdcpoly:
case CryptoCurrency.usdtPoly:
case CryptoCurrency.usdcEPoly:
case CryptoCurrency.ape:
case CryptoCurrency.avaxc:
case CryptoCurrency.eth:
@ -141,6 +143,8 @@ class AddressValidator extends TextValidator {
return [42];
case CryptoCurrency.eth:
case CryptoCurrency.usdcpoly:
case CryptoCurrency.usdtPoly:
case CryptoCurrency.usdcEPoly:
case CryptoCurrency.mana:
case CryptoCurrency.matic:
case CryptoCurrency.maticpoly:

View file

@ -285,10 +285,12 @@ class EvmChainServiceImpl implements ChainService {
}
String _convertToReadable(Map<String, dynamic> data) {
final tokenName = getTokenNameBasedOnWalletType(appStore.wallet!.type);
String gas = int.parse((data['gas'] as String).substring(2), radix: 16).toString();
String value = data['value'] != null
? (int.parse((data['value'] as String).substring(2), radix: 16) / 1e18).toString() + ' ETH'
: '0 ETH';
? (int.parse((data['value'] as String).substring(2), radix: 16) / 1e18).toString() +
' $tokenName'
: '0 $tokenName';
String from = data['from'] as String;
String to = data['to'] as String;

View file

@ -19,7 +19,6 @@ import 'package:cake_wallet/ionia/ionia_anypay.dart';
import 'package:cake_wallet/ionia/ionia_gift_card.dart';
import 'package:cake_wallet/ionia/ionia_tip.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart';
import 'package:cake_wallet/src/screens/buy/buy_options_page.dart';
@ -756,13 +755,7 @@ Future<void> setup({
return PowNodeListViewModel(_powNodeSource, appStore);
});
getIt.registerFactory(() {
final wallet = getIt.get<AppStore>().wallet;
return ConnectionSyncPage(
getIt.get<DashboardViewModel>(),
isEVMCompatibleChain(wallet!.type) ? getIt.get<Web3WalletService>() : null,
);
});
getIt.registerFactory(() => ConnectionSyncPage(getIt.get<DashboardViewModel>()));
getIt.registerFactory(
() => SecurityBackupPage(getIt.get<SecuritySettingsViewModel>(), getIt.get<AuthService>()));

View file

@ -1,6 +1,5 @@
import 'dart:io' show Directory, File, Platform;
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/entities/encrypt.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cake_wallet/entities/secret_store_key.dart';
@ -190,7 +189,6 @@ Future<void> defaultSettingsMigration(
case 25:
await rewriteSecureStoragePin(secureStorage: secureStorage);
break;
default:
break;
}

View file

@ -85,8 +85,7 @@ Future<List<Node>> loadDefaultEthereumNodes() async {
}
Future<List<Node>> loadBitcoinCashElectrumServerList() async {
final serverListRaw =
await rootBundle.loadString('assets/bitcoin_cash_electrum_server_list.yml');
final serverListRaw = await rootBundle.loadString('assets/bitcoin_cash_electrum_server_list.yml');
final loadedServerList = loadYaml(serverListRaw) as YamlList;
final serverList = <Node>[];
@ -141,6 +140,7 @@ Future<List<Node>> loadDefaultPolygonNodes() async {
for (final raw in loadedNodes) {
if (raw is Map) {
final node = Node.fromMap(Map<String, Object>.from(raw));
node.type = WalletType.polygon;
nodes.add(node);
}
@ -159,7 +159,6 @@ Future<void> resetToDefault(Box<Node> nodeSource) async {
final nanoNodes = await loadDefaultNanoNodes();
final polygonNodes = await loadDefaultPolygonNodes();
final nodes = moneroNodes +
bitcoinElectrumServerList +
litecoinElectrumServerList +
@ -178,4 +177,4 @@ Future<void> resetPowToDefault(Box<Node> powNodeSource) async {
final nodes = nanoPowNodes;
await powNodeSource.clear();
await powNodeSource.addAll(nodes);
}
}

View file

@ -159,8 +159,8 @@ class SideShiftExchangeProvider extends ExchangeProvider {
url = apiBaseUrl + orderPath + '/fixed';
} else {
url = apiBaseUrl + orderPath + '/variable';
body["depositCoin"] = request.fromCurrency.title.toLowerCase();
body["settleCoin"] = request.toCurrency.title.toLowerCase();
body["depositCoin"] = _normalizeCurrency(request.fromCurrency);
body["settleCoin"] = _normalizeCurrency(request.toCurrency);
body["settleNetwork"] = _networkFor(request.toCurrency);
body["depositNetwork"] = _networkFor(request.fromCurrency);
}
@ -248,8 +248,8 @@ class SideShiftExchangeProvider extends ExchangeProvider {
final url = apiBaseUrl + quotePath;
final headers = {'Content-Type': 'application/json'};
final body = {
'depositCoin': request.fromCurrency.title.toLowerCase(),
'settleCoin': request.toCurrency.title.toLowerCase(),
'depositCoin': _normalizeCurrency(request.fromCurrency),
'settleCoin': _normalizeCurrency(request.toCurrency),
'affiliateId': affiliateId,
'settleAmount': request.toAmount,
'settleNetwork': _networkFor(request.toCurrency),
@ -274,6 +274,15 @@ class SideShiftExchangeProvider extends ExchangeProvider {
return responseJSON['id'] as String;
}
String _normalizeCurrency(CryptoCurrency currency) {
switch (currency) {
case CryptoCurrency.usdcEPoly:
return 'usdc';
default:
return currency.title.toLowerCase();
}
}
String _networkFor(CryptoCurrency currency) =>
currency.tag != null ? _normalizeTag(currency.tag!) : 'mainnet';

View file

@ -222,6 +222,10 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
return 'usdttrc20';
case CryptoCurrency.usdcpoly:
return 'usdcpoly';
case CryptoCurrency.usdtPoly:
return 'usdtpoly';
case CryptoCurrency.usdcEPoly:
return 'usdcepoly';
case CryptoCurrency.usdcsol:
return 'usdcspl';
case CryptoCurrency.matic:

View file

@ -271,6 +271,8 @@ class TrocadorExchangeProvider extends ExchangeProvider {
case CryptoCurrency.maticpoly:
return 'Mainnet';
case CryptoCurrency.usdcpoly:
case CryptoCurrency.usdtPoly:
case CryptoCurrency.usdcEPoly:
return 'MATIC';
case CryptoCurrency.zec:
return 'Mainnet';
@ -283,6 +285,8 @@ class TrocadorExchangeProvider extends ExchangeProvider {
switch (currency) {
case CryptoCurrency.zec:
return 'zec';
case CryptoCurrency.usdcEPoly:
return 'usdce';
default:
return currency.title.toLowerCase();
}

View file

@ -44,3 +44,14 @@ String getChainNameBasedOnWalletType(WalletType walletType) {
return '';
}
}
String getTokenNameBasedOnWalletType(WalletType walletType) {
switch (walletType) {
case WalletType.ethereum:
return 'ETH';
case WalletType.polygon:
return 'MATIC';
default:
return '';
}
}

View file

@ -135,6 +135,7 @@ class ContactListPage extends BasePage {
await showBar<void>(context, S.of(context).copied_to_clipboard);
}
},
behavior: HitTestBehavior.opaque,
child: Container(
padding: const EdgeInsets.only(top: 16, bottom: 16, right: 24),
child: Row(

View file

@ -191,7 +191,10 @@ class _DashboardPageView extends BasePage {
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context).indicatorColor,
dotColor: Theme.of(context)
.extension<DashboardPageTheme>()!
.indicatorDotTheme
.indicatorColor,
activeDotColor: Theme.of(context)
.extension<DashboardPageTheme>()!
.indicatorDotTheme

View file

@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
import 'package:cake_wallet/themes/extensions/address_theme.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
import 'package:cake_wallet/themes/extensions/picker_theme.dart';
import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart';
@ -91,7 +92,7 @@ class HomeSettingsPage extends BasePage {
fillColor: Theme.of(context).cardColor,
child: Icon(
Icons.add,
color: Theme.of(context).dialogTheme.backgroundColor,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
size: 22.0,
),
padding: EdgeInsets.all(12),

View file

@ -18,6 +18,7 @@ class HomeScreenAccountWidget extends StatelessWidget {
context: context,
builder: (_) => getIt.get<MoneroAccountListPage>());
},
behavior: HitTestBehavior.opaque,
child: Container(
height: 100.0,
child: Row(

View file

@ -176,7 +176,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
);
launchUri = null;
} else {
_nonETHWalletErrorToast(S.current.switchToETHWallet);
_nonETHWalletErrorToast(S.current.switchToEVMCompatibleWallet);
}
}
@ -206,7 +206,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
String? _getRouteToGo() {
if (isWalletConnectLink) {
if (isEVMCompatibleChain(widget.appStore.wallet!.type)) {
_nonETHWalletErrorToast(S.current.switchToETHWallet);
_nonETHWalletErrorToast(S.current.switchToEVMCompatibleWallet);
return null;
}
return Routes.walletConnectConnectionsListing;

View file

@ -1,4 +1,3 @@
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
@ -18,12 +17,11 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
class ConnectionSyncPage extends BasePage {
ConnectionSyncPage(this.dashboardViewModel, this.web3walletService);
ConnectionSyncPage(this.dashboardViewModel);
@override
String get title => S.current.connection_sync;
final Web3WalletService? web3walletService;
final DashboardViewModel dashboardViewModel;
@override

View file

@ -76,7 +76,7 @@ class DisplaySettingsPage extends BasePage {
},
),
if (responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile)
SettingsThemeChoicesCell(_displaySettingsViewModel),
Semantics(label: S.current.color_theme, child: SettingsThemeChoicesCell(_displaySettingsViewModel)),
],
),
);

View file

@ -31,42 +31,43 @@ class SettingsChoicesCell extends StatelessWidget {
),
const SizedBox(height: 24),
Center(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Theme.of(context).extension<AddressTheme>()!.actionButtonColor,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: choicesListItem.items.map((dynamic e) {
final isSelected = choicesListItem.selectedItem == e;
return GestureDetector(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Theme.of(context).extension<AddressTheme>()!.actionButtonColor,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: choicesListItem.items.map((dynamic e) {
final isSelected = choicesListItem.selectedItem == e;
return Expanded(
child: GestureDetector(
onTap: () {
choicesListItem.onItemSelected.call(e);
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 8),
padding: EdgeInsets.symmetric(vertical: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: isSelected
? Theme.of(context).primaryColor
: null,
),
child: Text(
choicesListItem.displayItem.call(e),
style: TextStyle(
color: isSelected
? Colors.white
: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
fontWeight: isSelected ? FontWeight.w700 : FontWeight.normal,
child: Center(
child: Text(
choicesListItem.displayItem.call(e),
style: TextStyle(
color: isSelected
? Colors.white
: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
fontWeight: isSelected ? FontWeight.w700 : FontWeight.normal,
),
),
),
),
);
}).toList(),
),
),
);
}).toList(),
),
),
),

View file

@ -54,57 +54,61 @@ class SettingsThemeChoicesCell extends StatelessWidget {
return Padding(
padding: EdgeInsets.all(5),
child: GestureDetector(
onTap: () {
_displaySettingsViewModel.setTheme(e);
},
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(cellRadius),
border: isSelected
? Border.all(
color: Theme.of(context).primaryColor)
: null,
color: Theme.of(context)
.extension<CakeTextTheme>()!
.secondaryTextColor
.withOpacity(
currentTheme.brightness == Brightness.light
? 0.1
: 0.3),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.symmetric(
horizontal: cellWidth, vertical: cellHeight),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(cellRadius),
bottomLeft: Radius.circular(cellRadius)),
color: e.themeData.primaryColor,
child: Semantics(
label: e.toString(),
selected: isSelected,
child: GestureDetector(
onTap: () {
_displaySettingsViewModel.setTheme(e);
},
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(cellRadius),
border: isSelected
? Border.all(
color: Theme.of(context).primaryColor)
: null,
color: Theme.of(context)
.extension<CakeTextTheme>()!
.secondaryTextColor
.withOpacity(
currentTheme.brightness == Brightness.light
? 0.1
: 0.3),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.symmetric(
horizontal: cellWidth, vertical: cellHeight),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(cellRadius),
bottomLeft: Radius.circular(cellRadius)),
color: e.themeData.primaryColor,
),
),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: cellWidth, vertical: cellHeight),
decoration: BoxDecoration(
color: e.themeData.colorScheme.background,
Container(
padding: EdgeInsets.symmetric(
horizontal: cellWidth, vertical: cellHeight),
decoration: BoxDecoration(
color: e.themeData.colorScheme.background,
),
),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: cellWidth, vertical: cellHeight),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(cellRadius),
bottomRight: Radius.circular(cellRadius)),
color: e.themeData.cardColor,
Container(
padding: EdgeInsets.symmetric(
horizontal: cellWidth, vertical: cellHeight),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(cellRadius),
bottomRight: Radius.circular(cellRadius)),
color: e.themeData.cardColor,
),
),
),
],
],
),
),
),
),

View file

@ -14,25 +14,29 @@ class StandardSwitch extends StatefulWidget {
class StandardSwitchState extends State<StandardSwitch> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onTaped,
child: AnimatedContainer(
padding: EdgeInsets.only(left: 2.0, right: 2.0),
alignment: widget.value ? Alignment.centerRight : Alignment.centerLeft,
duration: Duration(milliseconds: 250),
width: 50,
height: 28,
decoration: BoxDecoration(
color: widget.value
? Theme.of(context).primaryColor
: Theme.of(context).disabledColor,
borderRadius: BorderRadius.all(Radius.circular(14.0))),
child: Container(
width: 24.0,
height: 24.0,
return Semantics(
toggled: widget.value,
child: GestureDetector(
onTap: widget.onTaped,
child: AnimatedContainer(
padding: EdgeInsets.only(left: 2.0, right: 2.0),
alignment: widget.value ? Alignment.centerRight : Alignment.centerLeft,
duration: Duration(milliseconds: 250),
width: 50,
height: 28,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle),
color: widget.value
? Theme.of(context).primaryColor
: Theme.of(context).disabledColor,
borderRadius: BorderRadius.all(Radius.circular(14.0))),
child: Container(
width: 24.0,
height: 24.0,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle),
),
),
),
);

View file

@ -91,6 +91,9 @@ abstract class ContactListViewModelBase with Store {
walletContacts.where((element) => _isValidForCurrency(element)).toList();
bool _isValidForCurrency(ContactBase element) {
return _currency == null || element.type == _currency || element.type.title == _currency!.tag;
return _currency == null ||
element.type == _currency ||
element.type.title == _currency!.tag ||
element.type.tag == _currency!.tag;
}
}

View file

@ -757,5 +757,6 @@
"primary_silent_address": "العنوان الصامت الأساسي",
"dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ",
"polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ",
"wallet_seed_legacy": "بذرة محفظة قديمة"
"wallet_seed_legacy": "بذرة محفظة قديمة",
"switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ"
}

View file

@ -753,5 +753,6 @@
"primary_silent_address": "Първичен безшумен адрес",
"dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа",
"polygonscan_history": "История на PolygonScan",
"wallet_seed_legacy": "Наследено портфейл семе"
"wallet_seed_legacy": "Наследено портфейл семе",
"switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)"
}

View file

@ -753,5 +753,6 @@
"primary_silent_address": "Primární tichá adresa",
"dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě",
"polygonscan_history": "Historie PolygonScan",
"wallet_seed_legacy": "Starší semeno peněženky"
"wallet_seed_legacy": "Starší semeno peněženky",
"switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)"
}

View file

@ -761,5 +761,6 @@
"primary_silent_address": "Primäre stille Adresse",
"dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa",
"polygonscan_history": "PolygonScan-Verlauf",
"wallet_seed_legacy": "Legacy Wallet Seed"
"wallet_seed_legacy": "Legacy Wallet Seed",
"switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)"
}

View file

@ -762,5 +762,6 @@
"primary_silent_address": "Primary Silent Address",
"dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe",
"polygonscan_history": "PolygonScan history",
"wallet_seed_legacy": "Legacy wallet seed"
"wallet_seed_legacy": "Legacy wallet seed",
"switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)"
}

View file

@ -752,6 +752,7 @@
"seedtype_polyseed": "Polieta (16 palabras)",
"seed_language_czech": "checo",
"seed_language_korean": "coreano",
"seed_language_chinese_traditional": "Chino (tradicional)",
"dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa",
"seed_language_chinese_traditional": "Chino (tradicional)",
"mainnet": "Red",
@ -761,5 +762,6 @@
"bitcoin_legacy": "Legado de bitcoin",
"primary_silent_address": "Dirección silenciosa primaria",
"polygonscan_history": "Historial de PolygonScan",
"wallet_seed_legacy": "Semilla de billetera heredada"
}
"wallet_seed_legacy": "Semilla de billetera heredada",
"switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)"
}

View file

@ -761,5 +761,6 @@
"primary_silent_address": "Adresse silencieuse primaire",
"dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe",
"polygonscan_history": "Historique de PolygonScan",
"wallet_seed_legacy": "Graine de portefeuille hérité"
"wallet_seed_legacy": "Graine de portefeuille hérité",
"switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)"
}

View file

@ -739,5 +739,6 @@
"primary_silent_address": "Adireshin Silent na farko",
"dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai",
"polygonscan_history": "PolygonScan tarihin kowane zamani",
"wallet_seed_legacy": "Tallarin walat walat"
"wallet_seed_legacy": "Tallarin walat walat",
"switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)"
}

View file

@ -761,5 +761,6 @@
"primary_silent_address": "प्राथमिक मूक पता",
"dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए",
"polygonscan_history": "पॉलीगॉनस्कैन इतिहास",
"wallet_seed_legacy": "विरासत बटुए बीज"
"wallet_seed_legacy": "विरासत बटुए बीज",
"switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)"
}

View file

@ -750,6 +750,7 @@
"seedtype_polyseed": "Poliseed (16 riječi)",
"seed_language_czech": "češki",
"seed_language_korean": "korejski",
"seed_language_chinese_traditional": "Kinesko (tradicionalno)",
"dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi",
"seed_language_chinese_traditional": "Kinesko (tradicionalno)",
"mainnet": "Mainnet",
@ -759,5 +760,6 @@
"bitcoin_legacy": "Nasljeđe bitcoina",
"primary_silent_address": "Primarna tiha adresa",
"polygonscan_history": "Povijest PolygonScan",
"wallet_seed_legacy": "Sjeme naslijeđenog novčanika"
}
"wallet_seed_legacy": "Sjeme naslijeđenog novčanika",
"switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)"
}

View file

@ -740,6 +740,7 @@
"seedtype_polyseed": "Polyseed (16 kata)",
"seed_language_czech": "Ceko",
"seed_language_korean": "Korea",
"seed_language_chinese_traditional": "Cina (tradisional)",
"dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa",
"seed_language_chinese_traditional": "Cina (tradisional)",
"mainnet": "Mainnet",
@ -749,5 +750,6 @@
"bitcoin_legacy": "Bitcoin Legacy",
"primary_silent_address": "Alamat diam primer",
"polygonscan_history": "Sejarah PolygonScan",
"wallet_seed_legacy": "Biji dompet warisan"
}
"wallet_seed_legacy": "Biji dompet warisan",
"switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)"
}

View file

@ -761,5 +761,6 @@
"primary_silent_address": "Indirizzo silenzioso primario",
"dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa",
"polygonscan_history": "Cronologia PolygonScan",
"wallet_seed_legacy": "Seme di portafoglio legacy"
"wallet_seed_legacy": "Seme di portafoglio legacy",
"switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)"
}

View file

@ -761,5 +761,6 @@
"primary_silent_address": "主なサイレントアドレス",
"dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け",
"polygonscan_history": "ポリゴンスキャン履歴",
"wallet_seed_legacy": "レガシーウォレットシード"
"wallet_seed_legacy": "レガシーウォレットシード",
"switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)"
}

View file

@ -759,5 +759,6 @@
"primary_silent_address": "기본 조용한 주소",
"dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용",
"polygonscan_history": "다각형 스캔 기록",
"wallet_seed_legacy": "레거시 지갑 시드"
"wallet_seed_legacy": "레거시 지갑 시드",
"switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)"
}

View file

@ -759,5 +759,6 @@
"primary_silent_address": "မူလအသံတိတ်လိပ်စာ",
"dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်",
"polygonscan_history": "PolygonScan မှတ်တမ်း",
"wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့"
"wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့",
"switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)"
}

View file

@ -752,6 +752,7 @@
"seedtype_polyseed": "Polyseed (16 woorden)",
"seed_language_czech": "Tsjechisch",
"seed_language_korean": "Koreaans",
"seed_language_chinese_traditional": "Chinese (traditionele)",
"dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa",
"seed_language_chinese_traditional": "Chinese (traditionele)",
"mainnet": "Maimet",
@ -761,5 +762,6 @@
"bitcoin_legacy": "Bitcoin Legacy",
"primary_silent_address": "Primair stil adres",
"polygonscan_history": "PolygonScan-geschiedenis",
"wallet_seed_legacy": "Legacy portemonnee zaad"
}
"wallet_seed_legacy": "Legacy portemonnee zaad",
"switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)"
}

View file

@ -761,5 +761,6 @@
"primary_silent_address": "Podstawowy cichy adres",
"dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie",
"polygonscan_history": "Historia PolygonScan",
"wallet_seed_legacy": "Dziedziczne ziarno portfela"
"wallet_seed_legacy": "Dziedziczne ziarno portfela",
"switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)"
}

View file

@ -760,5 +760,6 @@
"primary_silent_address": "Endereço silencioso primário",
"dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa",
"polygonscan_history": "História do PolygonScan",
"wallet_seed_legacy": "Semente de carteira herdada"
"wallet_seed_legacy": "Semente de carteira herdada",
"switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)"
}

View file

@ -761,5 +761,6 @@
"primary_silent_address": "Основной тихий адрес",
"dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе",
"polygonscan_history": "История PolygonScan",
"wallet_seed_legacy": "Наследие семя кошелька"
"wallet_seed_legacy": "Наследие семя кошелька",
"switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)."
}

View file

@ -759,5 +759,6 @@
"primary_silent_address": "ที่อยู่เงียบหลัก",
"dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป",
"polygonscan_history": "ประวัติ PolygonScan",
"wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก"
"wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก",
"switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)"
}

View file

@ -755,5 +755,6 @@
"primary_silent_address": "Pangunahing tahimik na address",
"dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe",
"polygonscan_history": "Kasaysayan ng PolygonScan",
"wallet_seed_legacy": "Legacy wallet seed"
"wallet_seed_legacy": "Legacy wallet seed",
"switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)"
}

View file

@ -759,5 +759,6 @@
"primary_silent_address": "Birincil sessiz adres",
"dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için",
"polygonscan_history": "PolygonScan geçmişi",
"wallet_seed_legacy": "Eski cüzdan tohumu"
"wallet_seed_legacy": "Eski cüzdan tohumu",
"switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)"
}

View file

@ -761,5 +761,6 @@
"bitcoin_legacy": "Bitcoin Legacy",
"primary_silent_address": "Первинна мовчазна адреса",
"polygonscan_history": "Історія PolygonScan",
"wallet_seed_legacy": "Спадець насіння гаманця"
}
"wallet_seed_legacy": "Спадець насіння гаманця",
"switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)"
}

View file

@ -753,5 +753,6 @@
"primary_silent_address": "بنیادی خاموش پتہ",
"dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ",
"polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ",
"wallet_seed_legacy": "میراثی پرس کا بیج"
"wallet_seed_legacy": "میراثی پرس کا بیج",
"switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ "
}

View file

@ -755,5 +755,6 @@
"primary_silent_address": "Adirẹsi ipalọlọ akọkọ",
"dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu",
"polygonscan_history": "PolygonScan itan",
"wallet_seed_legacy": "Irugbin akole"
"wallet_seed_legacy": "Irugbin akole",
"switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)"
}

View file

@ -760,5 +760,6 @@
"primary_silent_address": "主要无声地址",
"dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户",
"polygonscan_history": "多边形扫描历史",
"wallet_seed_legacy": "旧的钱包种子"
"wallet_seed_legacy": "旧的钱包种子",
"switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试以太坊、Polygon"
}

View file

@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in
CONFIG_ARGS="--monero"
;;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash"
CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash"
;;
$HAVEN)
CONFIG_ARGS="--haven"

View file

@ -28,7 +28,7 @@ case $APP_IOS_TYPE in
CONFIG_ARGS="--monero"
;;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash"
CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash"
;;
$HAVEN)

View file

@ -23,7 +23,7 @@ CONFIG_ARGS=""
case $APP_MACOS_TYPE in
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --nano --bitcoinCash";; #--haven
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash";; #--haven
esac
cp -rf pubspec_description.yaml pubspec.yaml