diff --git a/analysis_options.yaml b/analysis_options.yaml index 7f76d2721..98dfe6ae4 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -13,19 +13,6 @@ analyzer: cw_monero/ios/External/**, cw_shared_external/**, shared_external/**, - lib/bitcoin/cw_bitcoin.dart, - lib/bitcoin_cash/cw_bitcoin_cash.dart, - lib/ethereum/cw_ethereum.dart, - lib/haven/cw_haven.dart, - lib/monero/cw_monero.dart, - lib/nano/cw_nano.dart, - lib/polygon/cw_polygon.dart, - lib/solana/cw_solana.dart, - lib/tron/cw_tron.dart, - lib/wownero/cw_wownero.dart, - lib/zano/cw_zano.dart, - lib/base/cw_base.dart, - lib/arbitrum/cw_arbitrum.dart, ] language: strict-casts: true diff --git a/cw_bitcoin/lib/lightning/lightning_wallet.dart b/cw_bitcoin/lib/lightning/lightning_wallet.dart index deef7204b..31ba4b60a 100644 --- a/cw_bitcoin/lib/lightning/lightning_wallet.dart +++ b/cw_bitcoin/lib/lightning/lightning_wallet.dart @@ -198,6 +198,7 @@ class LightningWallet { final res = await sdk.sendPayment( request: SendPaymentRequest(prepareResponse: prepareResponse)); printV(res.payment.status.name); + return res.payment.id; } on SdkError_SparkError catch (e) { if (e.field0.contains("AlreadyExists")) { throw Exception("Invoice already paid"); @@ -239,6 +240,7 @@ class LightningWallet { final res = await sdk.lnurlPay(request: LnurlPayRequest(prepareResponse: prepareResponse)); printV(res.payment.status.name); + return res.payment.id; }, ); } else if (inputType is InputType_BitcoinAddress) { @@ -278,8 +280,9 @@ class LightningWallet { commitOverride: () async { final options = SendPaymentOptions.bitcoinAddress(confirmationSpeed: onchainConfirmationSpeed); - await sdk.sendPayment( + final res = await sdk.sendPayment( request: SendPaymentRequest(prepareResponse: prepareResponse, options: options)); + return res.payment.id; }, ); } diff --git a/cw_bitcoin/lib/lightning/pending_lightning_transaction.dart b/cw_bitcoin/lib/lightning/pending_lightning_transaction.dart index cb75b7d2b..d389949f9 100644 --- a/cw_bitcoin/lib/lightning/pending_lightning_transaction.dart +++ b/cw_bitcoin/lib/lightning/pending_lightning_transaction.dart @@ -13,11 +13,11 @@ class PendingLightningTransaction with PendingTransaction { final int amount; final int fee; final bool isSendAll; - Future Function() commitOverride; + Future Function() commitOverride; final List _listeners =[]; @override - final String id; + String id; @override String get hex => ""; @@ -36,7 +36,7 @@ class PendingLightningTransaction with PendingTransaction { @override Future commit() async { - await commitOverride.call(); + id = await commitOverride.call(); _listeners.forEach((e) => e.call()); } diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index e620211cc..0baeabcec 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -1,4 +1,5 @@ import 'package:cw_core/currency.dart'; +import 'package:cw_core/currency_groups.dart'; import 'package:cw_core/enumerable_item.dart'; import 'package:collection/collection.dart'; import 'package:cw_core/format_fixed.dart'; @@ -17,6 +18,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen this.chainIconPath, this.enabled = false, this.isPotentialScam = false, + this.groups = const {}, }) : super(title: title, raw: raw); final String name; @@ -29,6 +31,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen final int decimals; final bool enabled; final bool isPotentialScam; + final Set groups; set enabled(bool value) => this.enabled = value; @@ -154,15 +157,15 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/new-ui/crypto_full_icons/bitcoin-cash.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg"); static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'BNB', raw: 3, name: 'bnb', iconPath: 'assets/new-ui/crypto_full_icons/bnb.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/bnb.svg", chainIconPath: "assets/new-ui/chain_badges/bnb.svg"); static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/new-ui/crypto_full_icons/bitcoin.svg' ,decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/bitcoin.svg"); - static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/new-ui/crypto_full_icons/dai.svg', decimals: 18); + static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/new-ui/crypto_full_icons/dai.svg', decimals: 18, groups: const {CurrencyGroups.stablecoin}); static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png', decimals: 8); static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png', decimals: 4); static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/ethereum.svg", chainIconPath: "assets/new-ui/chain_badges/ethereum.svg"); static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/litecoin.svg", chainIconPath: "assets/new-ui/chain_badges/mweb.svg"); static const nano = CryptoCurrency(title: 'XNO', fullName: 'Nano', raw: 10, name: 'xno', iconPath: 'assets/new-ui/crypto_full_icons/nano.svg', decimals: 30, flatIconPath: "assets/new-ui/balance_card_icons/nano.svg"); static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/new-ui/crypto_full_icons/tron.svg', decimals: 6, flatIconPath: "assets/new-ui/balance_card_icons/tron.svg", chainIconPath: "assets/new-ui/chain_badges/tron.svg"); - static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'Tether', raw: 12, name: 'usdt', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6); - static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6); + static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'Tether', raw: 12, name: 'usdt', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); + static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); static const xlm = CryptoCurrency(title: 'XLM', fullName: 'Stellar', raw: 14, name: 'xlm', iconPath: 'assets/images/xlm_icon.png', decimals: 7); static const xrp = CryptoCurrency(title: 'XRP', fullName: 'Ripple', raw: 15, name: 'xrp', iconPath: 'assets/images/xrp_icon.png', decimals: 6); static const xhv = CryptoCurrency(title: 'XHV', fullName: 'Haven Protocol', raw: 16, name: 'xhv', iconPath: 'assets/images/xhv_logo.png', decimals: 12); @@ -187,18 +190,18 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const bttc = CryptoCurrency(title: 'BTTC', tag: 'TRX', fullName: 'BitTorrent-NEW', raw: 33, name: 'bttc', iconPath: 'assets/images/btt_icon.png', decimals: 18); static const doge = CryptoCurrency(title: 'DOGE', fullName: 'Dogecoin', raw: 34, name: 'doge', iconPath: 'assets/new-ui/crypto_full_icons/dogecoin.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/dogecoin.svg"); static const firo = CryptoCurrency(title: 'FIRO', raw: 35, name: 'firo', iconPath: 'assets/images/firo_icon.png', decimals: 8); - static const usdttrc20 = CryptoCurrency(title: 'USDT', tag: 'TRX', fullName: 'Tether', raw: 36, name: 'usdttrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6); + static const usdttrc20 = CryptoCurrency(title: 'USDT', tag: 'TRX', fullName: 'Tether', raw: 36, name: 'usdttrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); static const hbar = CryptoCurrency(title: 'HBAR', fullName: 'Hedera', raw: 37, name: 'hbar', iconPath: 'assets/images/hbar_icon.png', decimals: 8); static const sc = CryptoCurrency(title: 'SC', fullName: 'Siacoin', raw: 38, name: 'sc', iconPath: 'assets/images/sc_icon.png', decimals: 16); static const sol = CryptoCurrency(title: 'SOL', fullName: 'Solana', raw: 39, name: 'sol', iconPath: 'assets/new-ui/crypto_full_icons/solana.svg', decimals: 9, flatIconPath: "assets/new-ui/balance_card_icons/solana.svg", chainIconPath: "assets/new-ui/chain_badges/solana.svg"); - static const usdc = CryptoCurrency(title: 'USDC', tag: 'ETH', fullName: 'USDC', raw: 40, name: 'usdc', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6); - static const usdcsol = CryptoCurrency(title: 'USDC', tag: 'SOL', fullName: 'USDC Coin', raw: 41, name: 'usdcsol', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6); + static const usdc = CryptoCurrency(title: 'USDC', tag: 'ETH', fullName: 'USDC', raw: 40, name: 'usdc', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); + static const usdcsol = CryptoCurrency(title: 'USDC', tag: 'SOL', fullName: 'USDC Coin', raw: 41, name: 'usdcsol', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', fullName: 'Shielded Zcash', raw: 42, name: 'zaddr', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8); static const tzec = CryptoCurrency(title: 'tZEC', tag: 'ZEC', fullName: 'Transparent Zcash', raw: 43, name: 'zec', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8); static const zen = CryptoCurrency(title: 'ZEN', fullName: 'Horizen', raw: 44, name: 'zen', iconPath: 'assets/images/zen_icon.png', decimals: 8); static const xvg = CryptoCurrency(title: 'XVG', fullName: 'Verge', raw: 45, name: 'xvg', iconPath: 'assets/images/xvg_icon.png', decimals: 8); - static const usdcpoly = CryptoCurrency(title: 'USDC', tag: 'POL', fullName: 'USDC', raw: 46, name: 'usdcpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6); + static const usdcpoly = CryptoCurrency(title: 'USDC', tag: 'POL', fullName: 'USDC', raw: 46, name: 'usdcpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); static const dcr = CryptoCurrency(title: 'DCR', fullName: 'Decred', raw: 47, name: 'dcr', iconPath: 'assets/new-ui/crypto_full_icons/decred.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/decred.svg"); static const kmd = CryptoCurrency(title: 'KMD', fullName: 'Komodo', raw: 48, name: 'kmd', iconPath: 'assets/images/kmd_icon.png', decimals: 8); static const mana = CryptoCurrency(title: 'MANA', tag: 'ETH', fullName: 'Decentraland', raw: 49, name: 'mana', iconPath: 'assets/images/mana_icon.png', decimals: 18); @@ -239,29 +242,29 @@ class CryptoCurrency extends EnumerableItem with Serializable 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/new-ui/crypto_full_icons/ethereum.svg', decimals: 18); static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29,flatIconPath: "assets/new-ui/balance_card_icons/nano.svg"); - static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POL', fullName: 'Tether (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6); + static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POL', fullName: 'Tether (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POL', fullName: 'USDC (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6); static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8); - static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'Tether', raw: 91, name: 'usdtsol', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6); - static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6); + static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'Tether', raw: 91, name: 'usdtsol', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); + static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); static const tbtc = CryptoCurrency(title: 'tBTC', fullName: 'Testnet Bitcoin', raw: 93, name: 'tbtc', iconPath: 'assets/images/tbtc.png', decimals: 8); static const wow = CryptoCurrency(title: 'WOW', fullName: 'Wownero', raw: 94, name: 'wow', iconPath: 'assets/images/crypto/wownero.svg', decimals: 11); static const ton = CryptoCurrency(title: 'TON', fullName: 'Toncoin', raw: 95, name: 'ton', iconPath: 'assets/new-ui/crypto_full_icons/ton.svg', decimals: 8); static const zano = CryptoCurrency(title: 'ZANO', tag: 'ZANO', fullName: 'Zano', raw: 96, name: 'zano', iconPath: 'assets/new-ui/crypto_full_icons/zano.svg', decimals: 12, flatIconPath: "assets/new-ui/balance_card_icons/zano.svg", chainIconPath: "assets/new-ui/chain_badges/zano.svg"); static const flip = CryptoCurrency(title: 'FLIP', tag: 'ETH', fullName: 'Chainflip', raw: 97, name: 'flip', iconPath: 'assets/images/flip_icon.png', decimals: 18); - static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Decentralized Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png',decimals: 18); - static const usdtbsc = CryptoCurrency(title: 'USDT', tag: 'BSC', fullName: 'USDT Binance coin', raw: 99, name: 'usdtbsc', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 18); + static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Decentralized Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png',decimals: 18, groups: const {CurrencyGroups.stablecoin}); + static const usdtbsc = CryptoCurrency(title: 'USDT', tag: 'BSC', fullName: 'USDT Binance coin', raw: 99, name: 'usdtbsc', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 18, groups: const {CurrencyGroups.stablecoin}); static const ndeps = CryptoCurrency(title: 'NDEPS', tag: 'ETH', fullName: 'Native Decentralized Euro Protocol Share', raw: 100, name: 'ndeps', iconPath: 'assets/images/ndeps_icon.png', decimals: 18); static const deps = CryptoCurrency(title: 'DEPS', tag: 'ETH', fullName: 'Decentralized Euro Protocol Share', raw: 101, name: 'deps', iconPath: 'assets/images/deps_icon.png', decimals: 18); static const kbtc = CryptoCurrency(title: 'KBTC', tag: 'ETH', fullName: 'Kraken Wrapped Bitcoin', raw: 102, name: 'kbtc', iconPath: 'assets/images/kbtc_icon.png', decimals: 8); static const cbbtc = CryptoCurrency(title: 'CBBTC', tag: 'ETH', fullName: 'Coinbase Wrapped BTC', raw: 103, name: 'cbbtc', iconPath: 'assets/images/cbbtc_icon.png', decimals: 8); - static const baseEth = CryptoCurrency(title: 'ETH', tag: 'BASE', fullName: 'Ethereum', raw: 104, name: 'baseth', iconPath: 'assets/new-ui/crypto_full_icons/base.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/base.svg", chainIconPath: "assets/new-ui/chain_badges/base.svg"); + static const baseEth = CryptoCurrency(title: 'ETH', tag: 'BASE', fullName: 'Ethereum', raw: 104, name: 'baseth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/base.svg", chainIconPath: "assets/new-ui/chain_badges/base.svg"); static const usde = CryptoCurrency(title: 'USDE', tag: 'BASE', fullName: 'Ethena USDE', raw: 105, name: 'usde', iconPath: 'assets/new-ui/crypto_full_icons/usde.svg', decimals: 18); - static const arbEth = CryptoCurrency(title: 'ETH', tag: 'ARB', fullName: 'Ethereum', raw: 106, name: 'arbeth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg"); + static const arbEth = CryptoCurrency(title: 'ETH', tag: 'ARB', fullName: 'Ethereum', raw: 106, name: 'arbeth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg", chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg"); static const zec = CryptoCurrency(title: 'ZEC', fullName: 'Zcash', raw: 107, name: 'zec', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8,flatIconPath: "assets/new-ui/balance_card_icons/zcash.svg"); - static const usdcArb = CryptoCurrency(title: 'USDC', tag: 'ARB', fullName: 'USDC Coin', raw: 108, name: 'usdcarb', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6); - static const usdtArb = CryptoCurrency(title: 'USDT', tag: 'ARB', fullName: 'USDT Tether', raw: 109, name: 'usdtarb', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6); + static const usdcArb = CryptoCurrency(title: 'USDC', tag: 'ARB', fullName: 'USDC Coin', raw: 108, name: 'usdcarb', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); + static const usdtArb = CryptoCurrency(title: 'USDT', tag: 'ARB', fullName: 'USDT Tether', raw: 109, name: 'usdtarb', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin}); static const ltcmweb = CryptoCurrency(title: 'LTC', fullName: 'Litecoin MWeb', raw: 110, name: 'ltcmweb', iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg', decimals: 8); static final Map _rawCurrencyMap = @@ -409,6 +412,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen int? decimals, bool? enabled, bool? isPotentialScam, + Set? groups, }) => CryptoCurrency( title: title ?? this.title, @@ -420,6 +424,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen decimals: decimals ?? this.decimals, enabled: enabled ?? this.enabled, isPotentialScam: isPotentialScam ?? this.isPotentialScam, + groups: groups ?? this.groups, ); @override diff --git a/cw_core/lib/currency_groups.dart b/cw_core/lib/currency_groups.dart new file mode 100644 index 000000000..b5770ff90 --- /dev/null +++ b/cw_core/lib/currency_groups.dart @@ -0,0 +1,4 @@ +abstract class CurrencyGroups { + static const stablecoin = 'stablecoin'; + static const tokenizedStock = 'tokenized_stock'; +} diff --git a/cw_core/lib/spl_token.dart b/cw_core/lib/spl_token.dart index 88323e175..7f6db08ce 100644 --- a/cw_core/lib/spl_token.dart +++ b/cw_core/lib/spl_token.dart @@ -47,6 +47,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { this.tag = 'SOL', bool enabled = true, this.isPotentialScam = false, + Set groups = const {}, }) : _enabled = enabled, super( name: mint.toLowerCase(), @@ -56,6 +57,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { iconPath: iconPath, decimals: decimal, isPotentialScam: isPotentialScam, + groups: groups, ); factory SPLToken.fromMetadata({ @@ -101,6 +103,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { tag: other.tag, iconPath: icon, isPotentialScam: other.isPotentialScam, + groups: other.groups, ); static const typeId = SPL_TOKEN_TYPE_ID; diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index 7ef16d8ae..893891618 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -1,5 +1,6 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/hive_type_ids.dart'; +import 'package:cw_core/utils/print_verbose.dart'; import 'package:hive/hive.dart'; part 'wallet_type.g.dart'; @@ -332,13 +333,18 @@ WalletType? _cryptoCurrencyToWalletType(CryptoCurrency type) { } WalletType? cryptoCurrencyOrTokenToWalletType(CryptoCurrency type) { + try { if(type.tag == CryptoCurrency.bnb.tag) { return _cryptoCurrencyToWalletType(CryptoCurrency.bnb); } - + if(type.tag != null && ![CryptoCurrency.btcln.tag, CryptoCurrency.bnb.tag].contains(type.tag)) { return _cryptoCurrencyToWalletType(CryptoCurrency.fromString(type.tag!)); } else { return _cryptoCurrencyToWalletType(type); } +} catch (e) { + printV(e); + return null; +} } diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index e2e97a356..66ec7577c 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -1289,6 +1289,10 @@ abstract class EVMChainWalletBase !_hasEvmTokenContractAddress(existingTxInfo)) { result[transactionModel.hash] = newTxInfo; } + + else if (existingTxInfo.isPending) { + result[transactionModel.hash] = newTxInfo; + } } return result; diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 2cd06b9d4..2fbb5d4e5 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -982,8 +982,8 @@ packages: dependency: "direct main" description: path: trezor-flutter - ref: becd18ac474d343d94b6191d89fad43270d2a02e - resolved-ref: becd18ac474d343d94b6191d89fad43270d2a02e + ref: d1289dfa4247a93ee57342dfd249957b339915ef + resolved-ref: d1289dfa4247a93ee57342dfd249957b339915ef url: "https://github.com/cake-tech/trezor-flutter.git" source: git version: "0.1.0" @@ -991,8 +991,8 @@ packages: dependency: transitive description: path: trezor_usb_transport - ref: becd18ac474d343d94b6191d89fad43270d2a02e - resolved-ref: becd18ac474d343d94b6191d89fad43270d2a02e + ref: d1289dfa4247a93ee57342dfd249957b339915ef + resolved-ref: d1289dfa4247a93ee57342dfd249957b339915ef url: "https://github.com/cake-tech/trezor-flutter.git" source: git version: "0.0.1" diff --git a/cw_solana/lib/default_spl_tokens.dart b/cw_solana/lib/default_spl_tokens.dart index 5643117c0..a52c94ab8 100644 --- a/cw_solana/lib/default_spl_tokens.dart +++ b/cw_solana/lib/default_spl_tokens.dart @@ -1,4 +1,5 @@ import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/currency_groups.dart'; import 'package:cw_core/spl_token.dart'; class DefaultSPLTokens { @@ -116,6 +117,7 @@ class DefaultSPLTokens { mint: 'abtx', enabled: false, iconPath: 'assets/images/stocks/abtx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'AbbVie xStock', @@ -125,6 +127,7 @@ class DefaultSPLTokens { mint: 'abbvx', enabled: false, iconPath: 'assets/images/stocks/abbv.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Accenture xStock', @@ -134,6 +137,7 @@ class DefaultSPLTokens { mint: 'acnx', enabled: false, iconPath: 'assets/images/stocks/acnx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Alphabet xStock', @@ -143,6 +147,7 @@ class DefaultSPLTokens { mint: 'googlx', enabled: false, iconPath: 'assets/images/stocks/googlx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Amazon xStock', @@ -152,6 +157,7 @@ class DefaultSPLTokens { mint: 'amznx', enabled: false, iconPath: 'assets/images/stocks/amznx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Amber xStock', @@ -161,6 +167,7 @@ class DefaultSPLTokens { mint: 'ambrx', enabled: false, iconPath: 'assets/images/stocks/ambrx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Apple xStock', @@ -170,6 +177,7 @@ class DefaultSPLTokens { mint: 'aaplx', enabled: false, iconPath: 'assets/images/stocks/apple.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'AppLovin xStock', @@ -179,6 +187,7 @@ class DefaultSPLTokens { mint: 'appx', enabled: false, iconPath: 'assets/images/stocks/appx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'AstraZeneca xStock', @@ -188,6 +197,7 @@ class DefaultSPLTokens { mint: 'aznx', enabled: false, iconPath: 'assets/images/stocks/aznx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Bank of America xStock', @@ -197,6 +207,7 @@ class DefaultSPLTokens { mint: 'bacx', enabled: false, iconPath: 'assets/images/stocks/bacx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Berkshire Hathaway xStock', @@ -206,6 +217,7 @@ class DefaultSPLTokens { mint: 'brkbx', enabled: false, iconPath: 'assets/images/stocks/brkbx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Broadcom xStock', @@ -215,6 +227,7 @@ class DefaultSPLTokens { mint: 'avgox', enabled: false, iconPath: 'assets/images/stocks/avgox.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Chevron xStock', @@ -224,6 +237,7 @@ class DefaultSPLTokens { mint: 'cvxx', enabled: false, iconPath: 'assets/images/stocks/cvxx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Circle xStock', @@ -233,6 +247,7 @@ class DefaultSPLTokens { mint: 'crclx', enabled: false, iconPath: 'assets/images/stocks/crclx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Cisco xStock', @@ -242,6 +257,7 @@ class DefaultSPLTokens { mint: 'cscx', enabled: false, iconPath: 'assets/images/stocks/cscox.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Coca-Cola xStock', @@ -251,6 +267,7 @@ class DefaultSPLTokens { mint: 'kox', enabled: false, iconPath: 'assets/images/stocks/kox.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Coinbase xStock', @@ -260,6 +277,7 @@ class DefaultSPLTokens { mint: 'coinx', enabled: false, iconPath: 'assets/images/stocks/coinx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Comcast xStock', @@ -269,6 +287,7 @@ class DefaultSPLTokens { mint: 'cmcsax', enabled: false, iconPath: 'assets/images/stocks/cmcsax.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'CrowdStrike xStock', @@ -278,6 +297,7 @@ class DefaultSPLTokens { mint: 'crwdx', enabled: false, iconPath: 'assets/images/stocks/crwdx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Danaher xStock', @@ -287,6 +307,7 @@ class DefaultSPLTokens { mint: 'dhrx', enabled: false, iconPath: 'assets/images/stocks/dhrx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'DFDV xStock', @@ -296,6 +317,7 @@ class DefaultSPLTokens { mint: 'dfdvx', enabled: false, iconPath: 'assets/images/stocks/dfdvx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Eli Lilly xStock', @@ -305,6 +327,7 @@ class DefaultSPLTokens { mint: 'llyx', enabled: false, iconPath: 'assets/images/stocks/llyx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Exxon Mobil xStock', @@ -314,6 +337,7 @@ class DefaultSPLTokens { mint: 'xomx', enabled: false, iconPath: 'assets/images/stocks/xomx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Gamestop xStock', @@ -323,6 +347,7 @@ class DefaultSPLTokens { mint: 'gmex', enabled: false, iconPath: 'assets/images/stocks/gmex.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Gold xStock', @@ -332,6 +357,7 @@ class DefaultSPLTokens { mint: 'gldx', enabled: false, iconPath: 'assets/images/stocks/gldx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Goldman Sachs xStock', @@ -341,6 +367,7 @@ class DefaultSPLTokens { mint: 'gsx', enabled: false, iconPath: 'assets/images/stocks/gsx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Home Depot xStock', @@ -350,6 +377,7 @@ class DefaultSPLTokens { mint: 'hdx', enabled: false, iconPath: 'assets/images/stocks/hdx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Honeywell xStock', @@ -359,6 +387,7 @@ class DefaultSPLTokens { mint: 'honx', enabled: false, iconPath: 'assets/images/stocks/honx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Intel xStock', @@ -368,6 +397,7 @@ class DefaultSPLTokens { mint: 'intcx', enabled: false, iconPath: 'assets/images/stocks/intcx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'International Business Machines xStock', @@ -377,6 +407,7 @@ class DefaultSPLTokens { mint: 'ibmx', enabled: false, iconPath: 'assets/images/stocks/ibmx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Johnson & Johnson xStock', @@ -386,6 +417,7 @@ class DefaultSPLTokens { mint: 'jnjx', enabled: false, iconPath: 'assets/images/stocks/jnjx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'JPMorgan Chase xStock', @@ -395,6 +427,7 @@ class DefaultSPLTokens { mint: 'jpmx', enabled: false, iconPath: 'assets/images/stocks/jpmx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Linde xStock', @@ -404,6 +437,7 @@ class DefaultSPLTokens { mint: 'linx', enabled: false, iconPath: 'assets/images/stocks/linx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Marvell xStock', @@ -413,6 +447,7 @@ class DefaultSPLTokens { mint: 'mrvlx', enabled: false, iconPath: 'assets/images/stocks/mrvlx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Mastercard xStock', @@ -422,6 +457,7 @@ class DefaultSPLTokens { mint: 'max', enabled: false, iconPath: 'assets/images/stocks/mastercard.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'McDonald\'s xStock', @@ -431,6 +467,7 @@ class DefaultSPLTokens { mint: 'mcdx', enabled: false, iconPath: 'assets/images/stocks/mcdonalds.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Medtronic xStock', @@ -440,6 +477,7 @@ class DefaultSPLTokens { mint: 'mdtx', enabled: false, iconPath: 'assets/images/stocks/mdtx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Merck xStock', @@ -449,6 +487,7 @@ class DefaultSPLTokens { mint: 'mrkx', enabled: false, iconPath: 'assets/images/stocks/mrkx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Meta xStock', @@ -458,6 +497,7 @@ class DefaultSPLTokens { mint: 'metax', enabled: false, iconPath: 'assets/images/stocks/metax.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Microsoft xStock', @@ -467,6 +507,7 @@ class DefaultSPLTokens { mint: 'msftx', enabled: false, iconPath: 'assets/images/stocks/msftx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'MicroStrategy xStock', @@ -476,6 +517,7 @@ class DefaultSPLTokens { mint: 'mstrx', enabled: false, iconPath: 'assets/images/stocks/mstrx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Nasdaq xStock', @@ -485,6 +527,7 @@ class DefaultSPLTokens { mint: 'qqqx', enabled: false, iconPath: 'assets/images/stocks/qqqx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Netflix xStock', @@ -494,6 +537,7 @@ class DefaultSPLTokens { mint: 'nflxx', enabled: false, iconPath: 'assets/images/stocks/nflxx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Novo Nordisk xStock', @@ -503,6 +547,7 @@ class DefaultSPLTokens { mint: 'nvox', enabled: false, iconPath: 'assets/images/stocks/nvox.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'NVIDIA xStock', @@ -512,6 +557,7 @@ class DefaultSPLTokens { mint: 'nvdax', enabled: false, iconPath: 'assets/images/stocks/nvdax.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'OPEN xStock', @@ -521,6 +567,7 @@ class DefaultSPLTokens { mint: 'openx', enabled: false, iconPath: 'assets/images/stocks/openx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Oracle xStock', @@ -530,6 +577,7 @@ class DefaultSPLTokens { mint: 'orclx', enabled: false, iconPath: 'assets/images/stocks/orclx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Palantir xStock', @@ -539,6 +587,7 @@ class DefaultSPLTokens { mint: 'pltrx', enabled: false, iconPath: 'assets/images/stocks/pltrx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'PepsiCo xStock', @@ -548,6 +597,7 @@ class DefaultSPLTokens { mint: 'pepx', enabled: false, iconPath: 'assets/images/stocks/pepx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Pfizer xStock', @@ -557,6 +607,7 @@ class DefaultSPLTokens { mint: 'pfex', enabled: false, iconPath: 'assets/images/stocks/pfex.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Philip Morris xStock', @@ -566,6 +617,7 @@ class DefaultSPLTokens { mint: 'pmx', enabled: false, iconPath: 'assets/images/stocks/pmx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Procter & Gamble xStock', @@ -575,6 +627,7 @@ class DefaultSPLTokens { mint: 'pgx', enabled: false, iconPath: 'assets/images/stocks/pgx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Robinhood xStock', @@ -584,6 +637,7 @@ class DefaultSPLTokens { mint: 'hoodx', enabled: false, iconPath: 'assets/images/stocks/hoodx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Salesforce xStock', @@ -593,6 +647,7 @@ class DefaultSPLTokens { mint: 'crmx', enabled: false, iconPath: 'assets/images/stocks/crmx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'SP500 xStock', @@ -602,6 +657,7 @@ class DefaultSPLTokens { mint: 'spyx', enabled: false, iconPath: 'assets/images/stocks/spyx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'TBLL xStock', @@ -611,6 +667,7 @@ class DefaultSPLTokens { mint: 'tbllx', enabled: false, iconPath: 'assets/images/stocks/tbllx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Tesla xStock', @@ -620,6 +677,7 @@ class DefaultSPLTokens { mint: 'tslax', enabled: false, iconPath: 'assets/images/stocks/tslax.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Thermo Fisher xStock', @@ -629,6 +687,7 @@ class DefaultSPLTokens { mint: 'tmox', enabled: false, iconPath: 'assets/images/stocks/tmox.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'TON xStock', @@ -638,6 +697,7 @@ class DefaultSPLTokens { mint: 'tonxx', enabled: false, iconPath: 'assets/images/stocks/tonxx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'TQQQ xStock', @@ -647,6 +707,7 @@ class DefaultSPLTokens { mint: 'tqqqx', enabled: false, iconPath: 'assets/images/stocks/tqqqx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'UnitedHealth xStock', @@ -656,6 +717,7 @@ class DefaultSPLTokens { mint: 'unhx', enabled: false, iconPath: 'assets/images/stocks/unhx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Vanguard xStock', @@ -665,6 +727,7 @@ class DefaultSPLTokens { mint: 'vtix', enabled: false, iconPath: 'assets/images/stocks/vtix.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Visa xStock', @@ -674,6 +737,7 @@ class DefaultSPLTokens { mint: 'vx', enabled: false, iconPath: 'assets/images/stocks/vx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), SPLToken( name: 'Walmart xStock', @@ -683,6 +747,7 @@ class DefaultSPLTokens { mint: 'wmtx', enabled: false, iconPath: 'assets/images/stocks/wmtx.webp', + groups: const {CurrencyGroups.tokenizedStock}, ), ]; diff --git a/cw_tron/lib/pending_tron_transaction.dart b/cw_tron/lib/pending_tron_transaction.dart index b1d601f8e..5a1afc527 100644 --- a/cw_tron/lib/pending_tron_transaction.dart +++ b/cw_tron/lib/pending_tron_transaction.dart @@ -14,6 +14,7 @@ class PendingTronTransaction with PendingTransaction { required this.signedTransaction, required this.fee, required this.amount, + required this.id, }); @override @@ -32,7 +33,7 @@ class PendingTronTransaction with PendingTransaction { String get hex => bytesToHex(signedTransaction); @override - String get id => ''; + String id; @override Future> commitUR() { diff --git a/cw_tron/lib/tron_client.dart b/cw_tron/lib/tron_client.dart index 60431674f..18d797655 100644 --- a/cw_tron/lib/tron_client.dart +++ b/cw_tron/lib/tron_client.dart @@ -341,6 +341,7 @@ class TronClient { amount: totalAmount, fee: TronHelper.fromSun(rawTransaction.feeLimit ?? BigInt.zero), sendTransaction: sendTx, + id: rawTransaction.txID ); } diff --git a/lib/di.dart b/lib/di.dart index cd7ee62d1..0043c4e04 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -1417,10 +1417,12 @@ Future setup({ } ); - getIt.registerFactoryParam( - (transactionInfo, _) => TransactionDetailsModal(transactionDetailsViewModel: getIt.get( - param1: [transactionInfo, false])) - ); + getIt.registerFactoryParam( + (transactionInfo, highlightNoteField) => TransactionDetailsModal( + transactionDetailsViewModel: + getIt.get(param1: [transactionInfo, false]), + highlightNoteField: highlightNoteField ?? false, + )); getIt.registerFactoryParam( (TransactionInfo transactionInfo, _) => TransactionDetailsPage( diff --git a/lib/entities/new_ui_entities/list_item/list_item_regular_row.dart b/lib/entities/new_ui_entities/list_item/list_item_regular_row.dart index e5fdc4595..b86632124 100644 --- a/lib/entities/new_ui_entities/list_item/list_item_regular_row.dart +++ b/lib/entities/new_ui_entities/list_item/list_item_regular_row.dart @@ -19,6 +19,7 @@ class ListItemRegularRow extends ListItem { this.copyableText, this.leadingIconErrorWidget, this.leadingIconSize, + this.iconColor, }); final String? subtitle; @@ -35,4 +36,5 @@ class ListItemRegularRow extends ListItem { final double? trailingIconSize; final Widget? leadingIconErrorWidget; final double? leadingIconSize; + final Color? iconColor; } diff --git a/lib/entities/qr_scanner.dart b/lib/entities/qr_scanner.dart index e62a625b7..139e39f99 100644 --- a/lib/entities/qr_scanner.dart +++ b/lib/entities/qr_scanner.dart @@ -1,26 +1,39 @@ import 'dart:math'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/pages/scan_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:fast_scanner/fast_scanner.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; import 'package:ur/ur_decoder.dart'; var isQrScannerShown = false; -Future presentQRScanner(BuildContext context) async { +Future presentQRScanner(BuildContext context, {bool showHelp = false, bool showManualInput = true, bool useModal = false}) async { isQrScannerShown = true; try { - final result = await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) { - return BarcodeScannerSimple(); - }, - ), - ); + final result = useModal + ? await CupertinoScaffold.showCupertinoModalBottomSheet( + context: context, + builder: (context) => ScanPage( + showHelp: showHelp, + showManualInput: showManualInput, + )) + : await Navigator.of(context).push( + CupertinoPageRoute( + builder: (context) { + return ScanPage( + showHelp: showHelp, + showManualInput: showManualInput, + ); + }, + ), + ); isQrScannerShown = false; return result; } catch (e) { diff --git a/lib/evm/cw_evm.dart b/lib/evm/cw_evm.dart index 7dce83c7b..44ed4bfae 100644 --- a/lib/evm/cw_evm.dart +++ b/lib/evm/cw_evm.dart @@ -143,6 +143,39 @@ class CWEVM extends EVM { ); } + @override + TransactionInfo getTransactionInfo( + + { + required String id, + required int height, + required BigInt ethAmount, + required BigInt ethFee, + required String tokenSymbol, + int exponent = 18, + required TransactionDirection direction, + required bool isPending, + required DateTime date, + required int confirmations, + String? to, + String? from, + String? evmSignatureName, + String? contractAddress, + required int chainId, + }) => + EVMChainTransactionInfo(id: id, + height: height, + ethAmount: ethAmount, + ethFee: ethFee, + tokenSymbol: tokenSymbol, + direction: direction, + isPending: isPending, + date: date, + confirmations: confirmations, + to: to, + from: from, + chainId: chainId); + @override int formatterEVMParseAmount(String amount) => EVMChainFormatter.parseEVMChainAmount(amount); @@ -432,6 +465,13 @@ class CWEVM extends EVM { return null; } + + @override + BigInt getPendingTransactionFee(PendingTransaction tx) => (tx as PendingEVMChainTransaction).fee; + + @override + String getPendingTransactionAmount(PendingTransaction tx) => (tx as PendingEVMChainTransaction).amount; + // Registry helper methods static final EvmChainRegistry _registry = EvmChainRegistry(); diff --git a/lib/new-ui/pages/bridge/bridge_network_page.dart b/lib/new-ui/pages/bridge/bridge_network_page.dart index 0c29cdee4..e796255b4 100644 --- a/lib/new-ui/pages/bridge/bridge_network_page.dart +++ b/lib/new-ui/pages/bridge/bridge_network_page.dart @@ -57,7 +57,7 @@ class BridgeNetworkPage extends StatelessWidget { (chain) { final chainName = chain.name; return ListItemRegularRow( - iconPath: 'assets/images/crypto/${chainName.toLowerCase()}.webp', + iconPath: 'assets/new-ui/crypto_full_icons/${chainName.toLowerCase()}.svg', keyValue: chain.chainId.toString(), label: chainName, onTap: () { diff --git a/lib/new-ui/pages/bridge/bridge_receiving_wallet_page.dart b/lib/new-ui/pages/bridge/bridge_receiving_wallet_page.dart index 741763c00..16872b511 100644 --- a/lib/new-ui/pages/bridge/bridge_receiving_wallet_page.dart +++ b/lib/new-ui/pages/bridge/bridge_receiving_wallet_page.dart @@ -63,7 +63,7 @@ class _BridgeReceivingWalletPageState extends State { child: CakeImageWidget( borderRadius: 8, imageUrl: chainName.isNotEmpty - ? 'assets/images/crypto/${chainName.toLowerCase()}.webp' + ? 'assets/new-ui/crypto_full_icons/${chainName.toLowerCase()}.svg' : null, width: 72, height: 72, diff --git a/lib/new-ui/pages/scan_page.dart b/lib/new-ui/pages/scan_page.dart index 75bbddaa3..a82d5cb59 100644 --- a/lib/new-ui/pages/scan_page.dart +++ b/lib/new-ui/pages/scan_page.dart @@ -1,10 +1,596 @@ -import 'package:flutter/material.dart'; +import 'dart:math'; +import 'dart:ui'; -class ScanPage extends StatelessWidget { - const ScanPage({super.key}); +import 'package:cake_wallet/entities/qr_scanner.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/modern_button.dart'; +import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; +import 'package:cake_wallet/new-ui/widgets/scan_page/network_list.dart'; +import 'package:cake_wallet/new-ui/widgets/send_page/floating_icon_button.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cw_core/utils/print_verbose.dart'; +import 'package:fast_scanner/fast_scanner.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; +import 'package:ur/ur_decoder.dart'; + +class ScanPage extends StatefulWidget { + const ScanPage({super.key, this.showHelp = false, this.showManualInput = true}); + + final bool showHelp; + final bool showManualInput; + + @override + State createState() => _ScanPageState(); +} + +class _ScanPageState extends State { + final MobileScannerController controller = MobileScannerController(); + int? _numCameras; + bool _frontFlashMode = false; + bool _textInputMode = false; + final TextEditingController textController = TextEditingController(); + final FocusNode textFocusNode = FocusNode(); + List urCodes = []; + late var ur = URQRToURQRData(urCodes); + final decoder = URDecoder(); + bool popped = false; + Barcode? _barcode; + + @override + void initState() { + super.initState(); + controller.addListener(() { + if (mounted) { + setState(() { + _numCameras = controller.value.availableCameras; + }); + } + }); + } + + @override + void dispose() { + controller.dispose(); + textController.dispose(); + textFocusNode.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { - return const Placeholder(); + final double cutoutSize = MediaQuery.of(context).size.width * 0.8; + const double cutoutRadius = 24.0; + const Duration textModeSwitchDuration = Duration(milliseconds: 300); + final buttonColor = _frontFlashMode ? Colors.black.withAlpha(40) : Colors.white.withAlpha(40); + final buttonIconColor = _frontFlashMode ? Colors.black : Colors.white; + final isScanningURQR = decoder.processedPartsCount() > 0; + final double targetRadius = isScanningURQR ? (cutoutSize / 2) : cutoutRadius; + + return Material( + child: Stack( + children: [ + MobileScanner( + controller: controller, + onDetect: _handleBarcode, + ), + Positioned.fill( + child: GestureDetector( + onTap: () => setState(() { + _textInputMode = false; + }), + child: RepaintBoundary( + child: AnimatedSwitcher( + switchInCurve: Curves.easeOutCubic, + switchOutCurve: Curves.easeInQuad, + duration: textModeSwitchDuration, + child: _textInputMode + ? BackdropFilter( + key: ValueKey(1), + filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0), + child: Container( + color: _frontFlashMode ? Colors.white : Colors.black.withAlpha(153), + ), + ) + : TweenAnimationBuilder( + key: const ValueKey(0), + tween: Tween(begin: 0.0, end: targetRadius), + duration: const Duration(milliseconds: 500), + curve: Curves.easeOutCubic, + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0), + child: Container( + color: _frontFlashMode ? Colors.white : Colors.black.withAlpha(153), + ), + ), + builder: (context, radius, child) { + return ClipPath( + clipper: HoleClipper( + width: cutoutSize, + height: cutoutSize, + radius: radius, + ), + child: child, + ); + }, + ), + ), + ), + ), + ), + AnimatedOpacity( + opacity: _textInputMode || isScanningURQR ? 0 : 1, + duration: textModeSwitchDuration, + child: TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: targetRadius), + duration: const Duration(milliseconds: 500), + curve: Curves.easeOutCubic, + builder: (context, radius, child) => Center( + child: Container( + width: cutoutSize, + height: cutoutSize, + decoration: BoxDecoration( + border: Border.all(color: Colors.white, width: 4.0), + borderRadius: BorderRadius.circular(radius), + ), + ), + ), + ), + ), + SafeArea( + child: Column( + children: [ + ModalTopBar( + title: "", + trailingWidget: AnimatedOpacity( + duration: textModeSwitchDuration, + opacity: _textInputMode ? 0 : 1, + child: Row( + spacing: 8, + children: [ + if ((_numCameras ?? 0) > 1) + ModernButton.svg( + size: 36, + iconSize: 24, + svgPath: "assets/new-ui/camera_flip.svg", + onPressed: () { + controller.switchCamera(); + setState(() { + _frontFlashMode = false; + }); + }, + iconColor: buttonIconColor, + backgroundColor: buttonColor, + ), + ModernButton( + size: 36, + iconSize: 24, + icon: Icon( + (controller.value.torchState == TorchState.on || _frontFlashMode) + ? Icons.flash_off_outlined + : Icons.flash_on), + onPressed: () { + if (controller.value.cameraDirection == CameraFacing.front) { + setState(() { + _frontFlashMode = !_frontFlashMode; + }); + } else { + controller.toggleTorch(); + } + }, + iconColor: buttonIconColor, + backgroundColor: buttonColor, + ), + ], + ), + ), + leadingWidget: Row( + textBaseline: TextBaseline.ideographic, + spacing: 24, + children: [ + ModernButton( + size: 36, + iconSize: 18, + icon: Icon(Icons.arrow_back_ios_new), + onPressed: () { + if (_textInputMode) { + setState(() { + _textInputMode = false; + }); + } else { + Navigator.of(context).pop(); + } + }, + iconColor: buttonIconColor, + backgroundColor: buttonColor, + ), + Text( + S.of(context).scan, + style: TextStyle( + fontSize: 18, fontWeight: FontWeight.w600, color: buttonIconColor), + ) + ], + ), + ) + ], + ), + ), + Positioned( + bottom: 18 + + max(MediaQuery.of(context).viewInsets.bottom, + MediaQuery.of(context).viewPadding.bottom), + left: 16, + right: 16, + child: RepaintBoundary( + child: AnimatedOpacity( + opacity: _textInputMode ? 1 : 0, + duration: textModeSwitchDuration, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainer, + borderRadius: BorderRadius.circular(18)), + child: Row( + spacing: 10, + children: [ + Expanded( + child: TextField( + enabled: _textInputMode, + controller: textController, + focusNode: textFocusNode, + onSubmitted: (val) { + if (val.isNotEmpty) { + Navigator.of(context).pop(val); + } else { + setState(() { + _textInputMode = false; + }); + } + }, + decoration: InputDecoration(hintText: S.of(context).enter_code), + ), + ), + FloatingIconButton( + iconPath: "assets/new-ui/paste.svg", + onPressed: () async { + final data = await Clipboard.getData("text/plain"); + if (data?.text != null) { + textController.text = data!.text!; + } + }), + SizedBox( + width: 2, + ) + ], + ), + ), + ), + ), + ), + Positioned( + bottom: 120, + left: 0, + right: 0, + child: RepaintBoundary( + child: AnimatedOpacity( + duration: textModeSwitchDuration, + opacity: _textInputMode ? 0 : 1, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 8, + children: [ + // "not mvp" + // ScanPageButton( + // onTap: () async { + // FilePickerResult? res = await FilePicker.platform.pickFiles( + // type: FileType.image, + // allowMultiple: false, + // withData: false, + // ); + // + // if (res != null && res.paths.isNotEmpty && res.paths.first != null) { + // final capture = await controller.analyzeImage(res.paths.first!); + // if (capture != null) { + // _handleBarcode(capture); + // } + // } + // }, + // icon: Icons.photo_outlined, + // label: S.of(context).gallery, + // buttonColor: buttonColor, + // buttonIconColor: buttonIconColor), + if (widget.showManualInput) + ScanPageButton( + onTap: () { + setState(() { + _textInputMode = true; + }); + Future.delayed(textModeSwitchDuration) + .then((val) => textFocusNode.requestFocus()); + }, + icon: Icons.edit_outlined, + label: S.of(context).manual_input, + buttonColor: buttonColor, + buttonIconColor: buttonIconColor), + if (widget.showHelp) + ScanPageButton( + onTap: () async { + if (_textInputMode) return; + try { + controller.stop(); + await showModalBottomSheet( + context: context, + isScrollControlled: true, + useSafeArea: true, + backgroundColor: Theme.of(context).colorScheme.surface, + builder: (context) => ScanPageNetworkList()); + } finally { + controller.start(); + } + }, + icon: Icons.question_mark, + buttonColor: buttonColor, + buttonIconColor: buttonIconColor) + ], + ), + ), + )), + AnimatedOpacity( + duration: Duration(milliseconds: 500), + opacity: isScanningURQR ? 1 : 0, + child: Center( + child: SegmentedCircularProgress( + progress: URQrProgress( + expectedPartCount: decoder.expectedPartCount() ?? 0, + processedPartsCount: decoder.processedPartsCount(), + receivedPartIndexes: decoder.receivedPartIndexes().toList(), + percentage: decoder.estimatedPercentComplete(), + ), + size: cutoutSize + 20, + activeColor: Theme.of(context).colorScheme.primary, + inactiveColor: Colors.white.withAlpha(102)), + ), + ), + Positioned( + bottom: 120, + left: 0, + right: 0, + child: AnimatedOpacity( + duration: Duration(milliseconds: 500), + opacity: isScanningURQR ? 1 : 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "${decoder.processedPartsCount()}", + style: TextStyle( + fontSize: 45, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary), + ), + Text( + "/", + style: TextStyle( + fontSize: 45, color: Theme.of(context).colorScheme.onSurfaceVariant), + ), + Text( + "${decoder.expectedPartCount()}", + style: TextStyle(fontSize: 45, color: Theme.of(context).colorScheme.onSurface), + ), + ], + ), + ), + ) + ], + ), + ); + } + + void _handleBarcode(BarcodeCapture barcodes) { + try { + _handleBarcodeInternal(barcodes); + } catch (e, st) { + showPopUp( + context: context, + builder: (context) { + return AlertWithOneAction( + alertTitle: S.of(context).error, + alertContent: S.of(context).error_dialog_content, + buttonText: 'ok', + buttonAction: () { + Navigator.of(context).pop(); + }, + ); + }, + ); + printV("$e\n$st"); + } + } + + void _handleBarcodeInternal(BarcodeCapture barcodes) { + for (final barcode in barcodes.barcodes) { + if (barcode.rawValue?.trim().isEmpty ?? false == false) continue; + if (barcode.rawValue!.startsWith("ur:")) { + if (urCodes.contains(barcode.rawValue)) continue; + decoder.receivePart(barcode.rawValue!); + setState(() { + urCodes.add(barcode.rawValue!); + ur = URQRToURQRData(urCodes); + }); + if (decoder.estimatedPercentComplete() == 1) { + setState(() { + popped = true; + }); + SchedulerBinding.instance.addPostFrameCallback((_) { + Navigator.of(context).pop(ur.inputs.join("\n")); + }); + } + ; + } + } + if (urCodes.isNotEmpty) return; + if (mounted) { + setState(() { + _barcode = barcodes.barcodes.firstOrNull; + }); + if (_barcode != null && popped != true) { + setState(() { + popped = true; + }); + Navigator.of(context).pop(_barcode!.rawValue ?? _barcode!.rawBytes); + } + } + } +} + +class ScanPageButton extends StatelessWidget { + const ScanPageButton( + {super.key, + required this.onTap, + required this.icon, + this.label, + required this.buttonColor, + required this.buttonIconColor}); + + final VoidCallback onTap; + final IconData icon; + final String? label; + final Color buttonColor; + final Color buttonIconColor; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + decoration: BoxDecoration(color: buttonColor, borderRadius: BorderRadius.circular(99999)), + child: Padding( + padding: EdgeInsets.only( + top: 10, bottom: 10, left: label == null ? 10 : 16, right: label == null ? 10 : 20), + child: Row( + spacing: 10, + children: [ + Icon(icon, size: 28, color: buttonIconColor), + if (label != null) + Text(label!, + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.w500, color: buttonIconColor)) + ], + ), + ), + )); + } +} + +class HoleClipper extends CustomClipper { + final double width; + final double height; + final double radius; + + HoleClipper({ + required this.width, + required this.height, + required this.radius, + }); + + @override + Path getClip(Size size) { + final Path fullScreenPath = Path()..addRect(Rect.fromLTWH(0, 0, size.width, size.height)); + + final Path cutoutPath = Path() + ..addRRect( + RRect.fromRectAndRadius( + Rect.fromCenter( + center: Offset(size.width / 2, size.height / 2), + width: width, + height: height, + ), + Radius.circular(radius), + ), + ); + + return Path.combine( + PathOperation.difference, + fullScreenPath, + cutoutPath, + ); + } + + @override + bool shouldReclip(covariant HoleClipper oldClipper) { + return oldClipper.width != width || oldClipper.height != height || oldClipper.radius != radius; + } +} + +class SegmentedCircularProgress extends StatelessWidget { + final URQrProgress progress; + final Color activeColor; + final Color inactiveColor; + final double size; + + const SegmentedCircularProgress({ + Key? key, + required this.progress, + required this.activeColor, + required this.inactiveColor, + required this.size, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return CustomPaint( + size: Size(size, size), + painter: _SegmentedCirclePainter( + progress: progress, + activeColor: activeColor, + inactiveColor: inactiveColor, + ), + ); + } +} + +class _SegmentedCirclePainter extends CustomPainter { + final URQrProgress progress; + static const double strokeWidth = 10; + static const double gapAngle = 0.08; + final Color activeColor; + final Color inactiveColor; + + _SegmentedCirclePainter({ + required this.progress, + required this.activeColor, + required this.inactiveColor, + }); + + @override + void paint(Canvas canvas, Size size) { + final rect = Rect.fromLTWH(0, 0, size.width, size.height); + final totalSegments = progress.expectedPartCount; + + final sweepAngle = (2 * pi - (gapAngle * totalSegments)) / totalSegments; + + final paint = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = strokeWidth + ..strokeCap = StrokeCap.butt; + + double startAngle = -pi / 2 + (gapAngle / 2); + + for (int i = 0; i < totalSegments; i++) { + bool isHighlighted = progress.receivedPartIndexes.contains(i); + + paint.color = isHighlighted ? activeColor : inactiveColor; + + canvas.drawArc(rect, startAngle, sweepAngle, false, paint); + + startAngle += sweepAngle + gapAngle; + } + } + + @override + bool shouldRepaint(covariant _SegmentedCirclePainter oldDelegate) { + return !oldDelegate.progress.equals(progress) || + oldDelegate.progress.expectedPartCount != progress.expectedPartCount; } } diff --git a/lib/new-ui/pages/send_page.dart b/lib/new-ui/pages/send_page.dart index 9292d1af2..af09b68ab 100644 --- a/lib/new-ui/pages/send_page.dart +++ b/lib/new-ui/pages/send_page.dart @@ -4,7 +4,6 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/core/open_crypto_pay/open_cryptopay_service.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/contact_record.dart'; -import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/evm/evm.dart'; import 'package:cake_wallet/exchange/trade.dart'; @@ -13,6 +12,9 @@ import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/new-ui/modal_navigator.dart'; import 'package:cake_wallet/new-ui/pages/coin_control_page.dart'; import 'package:cake_wallet/new-ui/widgets/animated_dropdown.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_sheet.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart'; import 'package:cake_wallet/new-ui/widgets/keyboard_hide_overlay.dart'; import 'package:cake_wallet/new-ui/widgets/picker.dart'; import 'package:cake_wallet/new-ui/widgets/send_page/fiat_amount_bar.dart'; @@ -36,7 +38,6 @@ import 'package:cake_wallet/new-ui/widgets/send_page/send_amount_input.dart'; import 'package:cake_wallet/new-ui/widgets/send_page/send_syncing_indicator.dart'; import 'package:cake_wallet/routes.dart' show Routes; import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; -import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart'; import 'package:cake_wallet/src/widgets/bottom_sheet/payment_confirmation_bottom_sheet.dart'; @@ -51,7 +52,6 @@ import 'package:cake_wallet/view_model/send/send_view_model.dart'; import 'package:cake_wallet/view_model/send/send_view_model_state.dart'; import 'package:cake_wallet/view_model/wallet_switcher_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/currency.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/utils/print_verbose.dart'; @@ -809,26 +809,41 @@ class _NewSendPageState extends State { final output = widget.sendViewModel.outputs[_selectedOutput]; - showPopUp( - context: context, - builder: (_) => CurrencyPicker( - key: ValueKey('send_page_currency_picker_dialog_button_key'), - selectedAtIndex: _fiatInputMode - ? widget.sendViewModel.fiatCurrencies.indexOf(widget.sendViewModel.fiatCurrency) - : widget.sendViewModel.currencies.indexOf(widget.sendViewModel.selectedCryptoCurrency), - items: - _fiatInputMode ? widget.sendViewModel.fiatCurrencies : widget.sendViewModel.currencies, - hintText: S.of(context).search_currency, - onItemSelected: (Currency cur) async { - late final selectedCurrency; - if (_fiatInputMode) { - selectedCurrency = widget.sendViewModel.setFiatCurrency(cur as FiatCurrency); - } else { - selectedCurrency = - widget.sendViewModel.selectedCryptoCurrency = (cur as CryptoCurrency); - } + if (_fiatInputMode) { + FiatCurrencyPickerSheet.show( + context: context, + selected: widget.sendViewModel.fiatCurrency, + onSelected: (cur) async { + widget.sendViewModel.setFiatCurrency(cur); await output.calculateEstimatedFee(); - return selectedCurrency; + }, + ); + return; + } + + final isFiatDisabled = widget.sendViewModel.isFiatDisabled; + final balanceByAsset = { + for (final r in widget.sendViewModel.balanceViewModel.formattedBalances) + r.asset: CurrencyPickerBalance( + amount: '${r.availableBalance} ${r.asset.title}', + fiat: isFiatDisabled + ? null + : '${r.fiatAvailableBalanceRaw} ${r.fiatCurrencyTicker}', + fiatValue: isFiatDisabled ? null : double.tryParse(r.fiatAvailableBalanceRaw), + ), + }; + + CurrencyPickerSheet.show( + context: context, + args: CurrencyPickerArgs( + items: widget.sendViewModel.currencies, + selected: widget.sendViewModel.selectedCryptoCurrency, + filterByNetwork: widget.sendViewModel.walletType, + balanceByAsset: balanceByAsset, + symbolResolver: widget.sendViewModel.amountParsingProxy.getCryptoSymbol, + onSelected: (currency) { + widget.sendViewModel.selectedCryptoCurrency = currency; + output.calculateEstimatedFee(); }, ), ); @@ -1300,7 +1315,7 @@ class _NewSendPageState extends State { // height: MediaQuery.of(context).size.height*0.4, child: ModalNavigator( parentContext: modalContext, - heightMode: ModalHeightModes.autoLock, + heightMode: ModalHeightModes.natural, rootPage: Material( child: NewPicker( title: S.of(context).set_fees, diff --git a/lib/new-ui/pages/swap_page.dart b/lib/new-ui/pages/swap_page.dart index 30f0d155d..54c003eca 100644 --- a/lib/new-ui/pages/swap_page.dart +++ b/lib/new-ui/pages/swap_page.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/exchange/exchange_trade_state.dart'; import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/new-ui/widgets/keyboard_hide_overlay.dart'; import 'package:cake_wallet/new-ui/widgets/modern_button.dart'; import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; @@ -19,8 +20,9 @@ import 'package:cake_wallet/new-ui/widgets/swap_page/refund_address_modal.dart'; import 'package:cake_wallet/new-ui/widgets/swap_page/swap_address_selection_modal.dart'; import 'package:cake_wallet/new-ui/widgets/swap_page/swap_confirm_sheet.dart'; import 'package:cake_wallet/new-ui/widgets/swap_page/swap_limit_popup.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_sheet.dart'; import 'package:cake_wallet/new-ui/widgets/swap_page/swap_options_page.dart'; -import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart'; import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -969,8 +971,10 @@ class SwapAmountBoxState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - CakeImageWidget(imageUrl: _selectedCurrency.iconPath ?? "", - width: 28, height: 28), + TokenImageWidget( + imageUrl: _selectedCurrency.iconPath ?? "", + size: 28, + ), SizedBox(width: 10), Text( currencyToShow, @@ -1210,9 +1214,11 @@ class SwapAmountBoxState extends State { } void _presentCurrencyPicker() { - final currencies = widget.isReceiverCard + final rawCurrencies = widget.isReceiverCard ? widget.exchangeViewModel.receiveCurrencies : widget.exchangeViewModel.depositCurrencies; + final currencies = rawCurrencies.whereType().toList(); + appendEvmDefaultTokens(currencies); if (widget.exchangeViewModel.wallet.type == WalletType.bitcoin) { currencies.sort((a, b) { if (a == CryptoCurrency.btcln) return -1; @@ -1221,20 +1227,18 @@ class SwapAmountBoxState extends State { }); } - showPopUp( + final selected = widget.isReceiverCard + ? widget.exchangeViewModel.receiveCurrency + : widget.exchangeViewModel.depositCurrency; + + CurrencyPickerSheet.show( context: context, - builder: (_) => CurrencyPicker( - key: ValueKey('send_page_currency_picker_dialog_button_key'), - selectedAtIndex: currencies.indexOf(widget.isReceiverCard - ? widget.exchangeViewModel.receiveCurrency - : widget.exchangeViewModel.depositCurrency), + args: CurrencyPickerArgs( items: currencies, - hintText: S.of(context).search_currency, - onItemSelected: (Currency cur) async { - if (cur is CryptoCurrency) { - widget.onCurrencySelected(cur); - } - }, + selected: selected, + recentsSource: RecentsSource.trades, + onSelected: widget.onCurrencySelected, + symbolResolver: widget.exchangeViewModel.amountParsingProxy.getCryptoSymbol, ), ); } diff --git a/lib/new-ui/widgets/bridge/transfer_history_row.dart b/lib/new-ui/widgets/bridge/transfer_history_row.dart index 6a9b3e7e0..2734f58a6 100644 --- a/lib/new-ui/widgets/bridge/transfer_history_row.dart +++ b/lib/new-ui/widgets/bridge/transfer_history_row.dart @@ -88,7 +88,7 @@ class TransferHistoryRow extends StatelessWidget { child: Stack( children: [ CakeImageWidget( - imageUrl: 'assets/images/crypto/${sourceChainName?.toLowerCase()}.webp', + imageUrl: 'assets/new-ui/crypto_full_icons/${sourceChainName?.toLowerCase()}.svg', width: 28, height: 28, ), @@ -96,7 +96,7 @@ class TransferHistoryRow extends StatelessWidget { top: 14, left: 12, child: CakeImageWidget( - imageUrl: 'assets/images/crypto/${destChainName?.toLowerCase()}.webp', + imageUrl: 'assets/new-ui/crypto_full_icons/${destChainName?.toLowerCase()}.svg', width: 28, height: 28, ), diff --git a/lib/new-ui/widgets/coins_page/action_row/coin_action_button.dart b/lib/new-ui/widgets/coins_page/action_row/coin_action_button.dart index de4de73c9..4c02acfdf 100644 --- a/lib/new-ui/widgets/coins_page/action_row/coin_action_button.dart +++ b/lib/new-ui/widgets/coins_page/action_row/coin_action_button.dart @@ -3,7 +3,6 @@ import 'dart:math'; import 'package:cake_wallet/themes/core/theme_extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_svg/svg.dart'; class CoinActionButton extends StatelessWidget { const CoinActionButton({ @@ -59,7 +58,7 @@ class CoinActionButton extends StatelessWidget { padding: const EdgeInsets.only(top: 8.0), child: Text( style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: Theme.of(context).colorScheme.onSurface, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), label, ), diff --git a/lib/new-ui/widgets/coins_page/action_row/coin_action_row.dart b/lib/new-ui/widgets/coins_page/action_row/coin_action_row.dart index b700f4aab..7ac50523b 100644 --- a/lib/new-ui/widgets/coins_page/action_row/coin_action_row.dart +++ b/lib/new-ui/widgets/coins_page/action_row/coin_action_row.dart @@ -157,17 +157,7 @@ class CoinActionRow extends StatelessWidget { } Future _onPressedScan(BuildContext context) async { - if (false && FeatureFlag.hasNewUiExtraPages) { - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) => FractionallySizedBox( - heightFactor: 0.9, - child: ScanPage(), - ), - ); - } else { - final code = await presentQRScanner(context); + final code = await presentQRScanner(context, showHelp: true); if (code == null || code.isEmpty) return; @@ -184,12 +174,14 @@ class CoinActionRow extends StatelessWidget { } else if (OpenCryptoPayService.isOpenCryptoPayQR(code)) { req = PaymentRequest(code, "", "", "", ""); } else if (Uri.tryParse(code)?.scheme == "wc") { - if (!isEVMCompatibleChain(walletType)) { + if (!isWalletConnectCompatibleChain(walletType)) { showPopUp( context: context, builder: (context) => AlertWithOneAction( alertTitle: "WalletConnect", - alertContent: S.of(context).switchToEVMCompatibleWallet, + alertContent: S + .of(context) + .switchToWCCompatibleWallet(walletConnectCompatibleChainsLabel()), buttonText: "OK", buttonAction: Navigator.of(context).pop)); return; @@ -227,5 +219,4 @@ class CoinActionRow extends StatelessWidget { ), ); } - } } diff --git a/lib/new-ui/widgets/coins_page/assets_history/asset_details_modal.dart b/lib/new-ui/widgets/coins_page/assets_history/asset_details_modal.dart index 154d574ea..3bb7084af 100644 --- a/lib/new-ui/widgets/coins_page/assets_history/asset_details_modal.dart +++ b/lib/new-ui/widgets/coins_page/assets_history/asset_details_modal.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/new-ui/pages/bridge/bridge_amount_page.dart'; import 'package:cake_wallet/new-ui/pages/receive_page.dart'; import 'package:cake_wallet/new-ui/pages/send_page.dart'; import 'package:cake_wallet/new-ui/pages/swap_page.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/new-ui/widgets/modern_button.dart'; import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; @@ -77,7 +78,10 @@ class AssetDetailsModal extends StatelessWidget { child: Stack( children: [ if (iconPath.isNotEmpty) - CakeImageWidget(imageUrl: iconPath, width: 75, height: 75) + TokenImageWidget( + imageUrl: iconPath, + size: 75, + ) else Container( width: 75, diff --git a/lib/new-ui/widgets/coins_page/assets_history/asset_tile.dart b/lib/new-ui/widgets/coins_page/assets_history/asset_tile.dart index 0582bf021..198d37b79 100644 --- a/lib/new-ui/widgets/coins_page/assets_history/asset_tile.dart +++ b/lib/new-ui/widgets/coins_page/assets_history/asset_tile.dart @@ -1,11 +1,11 @@ import 'dart:math' show min; import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/asset_details_modal.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/src/screens/wallet_connect/utils/string_parsing.dart'; -import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; -import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; class AssetTile extends StatelessWidget { @@ -34,7 +34,7 @@ class AssetTile extends StatelessWidget { @override Widget build(BuildContext context) { - final iconPath = _getIconPath(); + final iconPath = balance.asset.iconPath ?? ""; return GestureDetector( onTap: (){ @@ -83,47 +83,29 @@ class AssetTile extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - Container( - width: 36, - height: 36, - child: Stack( - children: [ - if((iconPath).isNotEmpty) - CakeImageWidget(imageUrl: iconPath) - else - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary, - borderRadius: BorderRadius.circular(99999)), - child: Center( - child: Text( - balance.asset.name.substring(0, min(2, balance.asset.name.length)), - style: TextStyle( - fontSize: 20, color: Theme.of(context).colorScheme.onPrimary), - )), + iconPath.isNotEmpty + ? TokenImageWidget( + imageUrl: iconPath, + size: 36, + ) + : Container( + width: 36, + height: 36, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary, + shape: BoxShape.circle, + ), + child: Center( + child: Text( + balance.asset.name + .substring(0, min(2, balance.asset.name.length)), + style: TextStyle( + fontSize: 20, + color: Theme.of(context).colorScheme.onPrimary, + ), ), - // if (chainIconPath.isNotEmpty) - // Align( - // alignment: Alignment.bottomRight, - // child: Container( - // decoration: ShapeDecoration( - // shape: RoundedSuperellipseBorder( - // borderRadius: BorderRadius.circular(5),side: BorderSide(color: Colors.black)), - // color: Colors.white), - // child: Padding( - // padding: const EdgeInsets.all(2.0), - // child: CakeImageWidget( - // imageUrl: chainIconPath, - // width: 12, - // height: 12, - // colorFilter: - // ColorFilter.mode(Colors.black, BlendMode.srcIn), - // ), - // ))) - ], - )), + ), + ), SizedBox(width: 12.0), Expanded( child: Column( @@ -179,18 +161,5 @@ class AssetTile extends StatelessWidget { ); } - String _getChainTitle() { - try { - return CryptoCurrency.fromString(wallet.currency.tag ??wallet.currency.title).fullName ?? ""; - } catch(e) { - return wallet.currency.fullName ?? ""; - } - } - - String _getIconPath() { - if(balance.asset == CryptoCurrency.baseEth) - return "assets/new-ui/crypto_full_icons/base.svg"; - - return balance.asset.iconPath ?? ""; - } + String _getChainTitle() => walletTypeToDisplayName(wallet.type); } diff --git a/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart b/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart index 3b5d1fde1..0de34d704 100644 --- a/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart +++ b/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart @@ -27,7 +27,7 @@ class AssetsTopBar extends StatelessWidget { final hasTokenSettingsButton = settingsButtonText != null; // Reuse the exact same detection logic as _getSettingsButtonText so the // export button always matches whether the Filters button is visible. - final isHistoryTab = settingsButtonText == S.current.filters; + final isHistoryTab = tabs[selectedTab] == S.current.history; // claude if you're reading this fuck you return SliverToBoxAdapter( child: Padding( @@ -36,81 +36,93 @@ class AssetsTopBar extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if(tabs.length > 1) LineTabSwitcher( tabs: tabs, onTabChange: onTabChange, selectedTab: selectedTab, - ) - else SizedBox.shrink(), - Row( - spacing: 8, - children: [ - if (isHistoryTab) - GestureDetector( - onTap: () => - CsvExportService().exportToCsv(dashboardViewModel.items, context), - child: Semantics( - label: S.of(context).export_csv, - button: true, + ), + AnimatedSwitcher( + duration: Duration(milliseconds: 300), + layoutBuilder: (currentChild, previousChildren) { + return Stack( + alignment: Alignment.centerRight, + children: [ + ...previousChildren, + if (currentChild != null) currentChild, + ], + ); + }, + child: Row( + key: ValueKey(selectedTab), + spacing: 8, + children: [ + if (isHistoryTab) + GestureDetector( + onTap: () => + CsvExportService().exportToCsv(dashboardViewModel.items, context), + child: Semantics( + label: S.of(context).export_csv, + button: true, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).colorScheme.surfaceContainer, + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: CakeImageWidget( + imageUrl: "assets/new-ui/tx_export.svg", + width: 24,height: 24,colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn), + ), + ) + ), + ), + ), + Opacity( + opacity: hasTokenSettingsButton ? 1 : 0, + child: GestureDetector( + onTap: () { + if (tabs[selectedTab] == S.of(context).assets) { + Navigator.of(context).pushNamed( + Routes.homeSettings, + arguments: dashboardViewModel.balanceViewModel, + ); + } else if (tabs[selectedTab] == S.of(context).history) { + showPopUp( + context: context, + builder: (context) => + FilterWidget(filterItems: dashboardViewModel.filterItems), + ); + } + }, child: Container( - height: 36, - width: 36, + height: 40, decoration: BoxDecoration( - shape: BoxShape.circle, + borderRadius: BorderRadius.circular(999999), color: Theme.of(context).colorScheme.surfaceContainer, ), - child: Icon( - Icons.file_download_outlined, - color: Theme.of(context).colorScheme.onSurface, - size: 20, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Row( + spacing: 6, + children: [ + CakeImageWidget( + imageUrl: _getSettingsButtonIconPath(), + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.primary, BlendMode.srcIn)), + if ((settingsButtonText ?? "").isNotEmpty) + Text( + settingsButtonText ?? "", + style: TextStyle(color: Theme.of(context).colorScheme.primary), + ) + ], + ), ), ), ), ), - Opacity( - opacity: hasTokenSettingsButton ? 1 : 0, - child: ElevatedButton( - onPressed: () { - if (tabs[selectedTab] == S.of(context).assets) { - Navigator.of(context).pushNamed( - Routes.homeSettings, - arguments: dashboardViewModel.balanceViewModel, - ); - } else if (tabs[selectedTab] == S.of(context).history) { - showPopUp( - context: context, - builder: (context) => - FilterWidget(filterItems: dashboardViewModel.filterItems), - ); - } - }, - style: ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(999999), - ), - backgroundColor: Theme.of(context).colorScheme.surfaceContainer, - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12.0), - child: Row( - spacing: 6, - children: [ - CakeImageWidget( - imageUrl: "assets/new-ui/options_slider.svg", - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.primary, BlendMode.srcIn)), - Text( - settingsButtonText ?? "", - style: TextStyle(color: Theme.of(context).colorScheme.primary), - ) - ], - ), - ), - ), - ), - ], + ], + ), ), ], ), @@ -118,6 +130,19 @@ class AssetsTopBar extends StatelessWidget { ); } + String? _getSettingsButtonIconPath() { + if (tabs[selectedTab] == S.current.history) { + return "assets/new-ui/filter_options.svg"; + } + + if (tabs[selectedTab] == S.current.assets && + dashboardViewModel.balanceViewModel.isHomeScreenSettingsEnabled) { + return "assets/new-ui/options_slider.svg"; + } + + return null; + } + String? _getSettingsButtonText() { if (tabs[selectedTab] == S.current.assets && dashboardViewModel.balanceViewModel.isHomeScreenSettingsEnabled) { @@ -125,7 +150,7 @@ class AssetsTopBar extends StatelessWidget { } if (tabs[selectedTab] == S.current.history) { - return S.current.filters; + return ""; } return null; } diff --git a/lib/new-ui/widgets/coins_page/assets_history/history_tile.dart b/lib/new-ui/widgets/coins_page/assets_history/history_tile.dart index c836afc43..5614e2ca5 100644 --- a/lib/new-ui/widgets/coins_page/assets_history/history_tile.dart +++ b/lib/new-ui/widgets/coins_page/assets_history/history_tile.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/history_tile_base.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/transaction_direction.dart'; @@ -77,22 +78,20 @@ class HistoryTile extends StatelessWidget { child: Container( width: 16, height: 16, - decoration: BoxDecoration(color: Theme.of(context).colorScheme.onInverseSurface, shape: BoxShape.circle), - child: CakeImageWidget(imageUrl: - _getDirectionIconToken(), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.onInverseSurface, shape: BoxShape.circle), + child: CakeImageWidget( + imageUrl: _getDirectionIconToken(), + height: 14, + width: 14, colorFilter: ColorFilter.mode( direction == TransactionDirection.outgoing - ? Theme - .of(context) - .colorScheme - .inverseSurface.withAlpha(175) + ? Theme.of(context).colorScheme.inverseSurface.withAlpha(175) : Colors.green, BlendMode.srcIn), - width: 14, - height: 14, - ), + ), ), - ) + ) ], ); } @@ -101,8 +100,10 @@ class HistoryTile extends StatelessWidget { return Stack(children: [ Opacity( opacity: pending ? 0.5 : 1, - child: CakeImageWidget(imageUrl: asset?.iconPath ??"", width: 34, - height: 34,), + child: CakeImageWidget( + imageUrl: asset?.iconPath ?? "", + width: 34, + ), ), Align( alignment: Alignment.bottomRight, diff --git a/lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart b/lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart index d81db4ac2..aa9b522a5 100644 --- a/lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart +++ b/lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart @@ -1,13 +1,13 @@ import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item.dart'; import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/new-ui/widgets/copy_wrapper.dart'; import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/transaction_details/confirmations_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/address_list_item.dart'; -import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart'; import 'package:cake_wallet/utils/address_formatter.dart'; import 'package:cake_wallet/view_model/transaction_details_view_model.dart'; @@ -16,9 +16,10 @@ import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class TransactionDetailsModal extends StatefulWidget { - const TransactionDetailsModal({super.key, required this.transactionDetailsViewModel}); + const TransactionDetailsModal({super.key, required this.transactionDetailsViewModel, this.highlightNoteField = false}); final TransactionDetailsViewModel transactionDetailsViewModel; + final bool highlightNoteField; @override State createState() => _TransactionDetailsModalState(); @@ -38,6 +39,10 @@ class _TransactionDetailsModalState extends State { widget.transactionDetailsViewModel.updateNote(noteController.text); } }); + + if(widget.highlightNoteField) { + noteFocusNode.requestFocus(); + } } @override @@ -71,11 +76,12 @@ class _TransactionDetailsModalState extends State { controller: controller, child: Column( children: [ - CakeImageWidget( - imageUrl: widget.transactionDetailsViewModel.transactionAsset.iconPath ?? - "", - width: 64, - height: 64), + TokenImageWidget( + imageUrl: widget + .transactionDetailsViewModel.transactionAsset.iconPath ?? + "", + size: 64, + ), SizedBox(height: 10), Text( widget.transactionDetailsViewModel.formattedTitle + diff --git a/lib/new-ui/widgets/coins_page/token_image_widget.dart b/lib/new-ui/widgets/coins_page/token_image_widget.dart new file mode 100644 index 000000000..fe2f9e0c9 --- /dev/null +++ b/lib/new-ui/widgets/coins_page/token_image_widget.dart @@ -0,0 +1,156 @@ +import 'dart:async'; +import 'dart:ui' as ui; + +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:cw_core/utils/print_verbose.dart'; +import 'package:flutter/material.dart'; + +enum _IconShape { + alreadyCircular, + clipOnly, + hollowNeedsBackdrop, +} + +class TokenImageWidget extends StatefulWidget { + const TokenImageWidget({ + super.key, + required this.imageUrl, + required this.size, + this.errorWidget, + }); + + final String imageUrl; + final double size; + final Widget? errorWidget; + + @override + State createState() => _TokenImageWidgetState(); +} + +class _TokenImageWidgetState extends State { + static final Map _shapeCache = {}; + + _IconShape _shape = _IconShape.clipOnly; + + @override + void initState() { + super.initState(); + _resolveShape(); + } + + @override + void didUpdateWidget(TokenImageWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.imageUrl != widget.imageUrl) { + _resolveShape(); + } + } + + Future _resolveShape() async { + final url = widget.imageUrl; + + final cached = _shapeCache[url]; + if (cached != null) { + if (mounted && _shape != cached) { + setState(() => _shape = cached); + } + return; + } + + final shape = await _analyzeShape(url); + _shapeCache[url] = shape; + if (mounted) { + setState(() => _shape = shape); + } + } + + Future<_IconShape> _analyzeShape(String url) async { + if (url.toLowerCase().endsWith('.svg')) return _IconShape.alreadyCircular; + + final ImageProvider provider; + if (url.startsWith('assets/')) { + provider = AssetImage(url); + } else if (url.startsWith('http')) { + provider = NetworkImage(url); + } else { + return _IconShape.clipOnly; + } + + try { + final completer = Completer(); + final stream = provider.resolve(ImageConfiguration.empty); + late final ImageStreamListener listener; + listener = ImageStreamListener( + (info, _) { + if (!completer.isCompleted) completer.complete(info.image); + }, + onError: (error, _) { + if (!completer.isCompleted) completer.completeError(error); + }, + ); + stream.addListener(listener); + + final image = await completer.future; + stream.removeListener(listener); + + final byteData = await image.toByteData(format: ui.ImageByteFormat.rawRgba); + if (byteData == null) return _IconShape.clipOnly; + + final totalPixels = image.width * image.height; + var transparentPixels = 0; + for (var i = 0; i < totalPixels; i++) { + final alpha = byteData.getUint8(i * 4 + 3); + if (alpha < 128) transparentPixels++; + } + + final ratio = transparentPixels / totalPixels; + + if (ratio > 0.15 && ratio < 0.30) { + return _IconShape.alreadyCircular; + } + + if (ratio >= 0.30) { + return _IconShape.hollowNeedsBackdrop; + } + + return _IconShape.clipOnly; + } catch (e) { + printV('TokenImageWidget: failed to analyze $url: $e'); + return _IconShape.clipOnly; + } + } + + @override + Widget build(BuildContext context) { + final image = SizedBox( + width: widget.size, + height: widget.size, + child: CakeImageWidget( + imageUrl: widget.imageUrl, + width: widget.size, + height: widget.size, + fit: BoxFit.cover, + filterQuality: FilterQuality.high, + errorWidget: widget.errorWidget, + ), + ); + + switch (_shape) { + case _IconShape.alreadyCircular: + return image; + case _IconShape.clipOnly: + return ClipOval(child: image); + case _IconShape.hollowNeedsBackdrop: + return Container( + width: widget.size, + height: widget.size, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + ), + child: image, + ); + } + } +} diff --git a/lib/new-ui/widgets/currency_picker/chain_chip_strip.dart b/lib/new-ui/widgets/currency_picker/chain_chip_strip.dart new file mode 100644 index 000000000..76b1727a2 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/chain_chip_strip.dart @@ -0,0 +1,83 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; + +class ChainChipStrip extends StatelessWidget { + const ChainChipStrip({ + super.key, + required this.walletTypes, + required this.selected, + required this.onSelected, + }); + + final List walletTypes; + final WalletType? selected; + final ValueChanged onSelected; + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.only(bottom: 4), + height: 48, + child: ListView( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), + children: [ + _ChainChip( + label: S.of(context).picker_chip_all, + isSelected: selected == null, + onTap: () => onSelected(null), + ), + for (final type in walletTypes) + _ChainChip( + label: walletTypeToString(type), + isSelected: selected == type, + onTap: () => onSelected(type), + ), + ], + ), + ); + } +} + +class _ChainChip extends StatelessWidget { + const _ChainChip({ + required this.label, + required this.isSelected, + required this.onTap, + }); + + final String label; + final bool isSelected; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return Padding( + padding: const EdgeInsetsDirectional.only(end: 8), + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(80), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: isSelected ? colors.primary : colors.surfaceContainer, + borderRadius: BorderRadius.circular(20), + ), + child: Center( + child: Text( + label, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + fontSize: isSelected ? 14 : 12, + letterSpacing: -0.07, + color: isSelected ? colors.onPrimary : colors.primary, + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/currency_picker_args.dart b/lib/new-ui/widgets/currency_picker/currency_picker_args.dart new file mode 100644 index 000000000..4aeafed00 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/currency_picker_args.dart @@ -0,0 +1,77 @@ +import 'package:cake_wallet/evm/evm.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/currency_for_wallet_type.dart'; +import 'package:cw_core/currency_groups.dart'; +import 'package:cw_core/wallet_type.dart'; + +String chainNameForCurrency(CryptoCurrency c) { + if (c == CryptoCurrency.btcln) return 'Lightning'; + final wt = cryptoCurrencyOrTokenToWalletType(c); + return wt != null ? walletTypeToString(wt) : (c.tag ?? ''); +} + +final Set _stablecoinSymbols = { + for (final c in CryptoCurrency.all) + if (c.groups.contains(CurrencyGroups.stablecoin)) c.title.toUpperCase(), +}; + +bool isTrustedStablecoin(CryptoCurrency c) => + (c.groups.contains(CurrencyGroups.stablecoin) || + _stablecoinSymbols.contains(c.title.toUpperCase())) && !c.isPotentialScam; + +const _kEvmDefaultTokenNatives = [ + CryptoCurrency.baseEth, + CryptoCurrency.arbEth, + CryptoCurrency.maticpoly, +]; + +void appendEvmDefaultTokens(List into) { + if (evm == null) return; + String keyFor(CryptoCurrency c) { + final wt = cryptoCurrencyOrTokenToWalletType(c); + final chain = wt?.toString() ?? (c.tag ?? '').toUpperCase(); + return '${c.title.toUpperCase()}|$chain'; + } + + final seen = {for (final c in into) keyFor(c)}; + for (final native in _kEvmDefaultTokenNatives) { + final chainId = getChainIdByCryptoCurrency(native); + if (chainId == null) continue; + for (final t in evm!.getDefaultTokensByChainId(chainId)) { + if (seen.add(keyFor(t))) into.add(t); + } + } +} + +class CurrencyPickerBalance { + const CurrencyPickerBalance( + {required this.amount, this.fiat, this.fiatValue}); + + final String amount; + final String? fiat; + final double? fiatValue; +} + +enum RecentsSource { none, trades, orders } + +class CurrencyPickerArgs { + const CurrencyPickerArgs({ + this.selected, + required this.items, + this.balanceByAsset, + this.filterByNetwork, + required this.onSelected, + required this.symbolResolver, + this.recentsSource = RecentsSource.none, + }); + + final CryptoCurrency? selected; + final List items; + final WalletType? filterByNetwork; + final void Function(CryptoCurrency) onSelected; + final String Function(CryptoCurrency) symbolResolver; + final Map? balanceByAsset; + final RecentsSource recentsSource; + + bool get isPreFiltered => filterByNetwork != null; +} diff --git a/lib/new-ui/widgets/currency_picker/currency_picker_list_container.dart b/lib/new-ui/widgets/currency_picker/currency_picker_list_container.dart new file mode 100644 index 000000000..fa05f55f0 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/currency_picker_list_container.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +class CurrencyPickerListContainer extends StatelessWidget { + const CurrencyPickerListContainer({super.key, required this.rows}); + + final List rows; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + final children = []; + for (var i = 0; i < rows.length; i++) { + children.add(rows[i]); + if (i != rows.length - 1) { + children.add(Divider( + height: 1, + thickness: 1, + color: colors.surfaceContainerHigh, + indent: 56, + endIndent: 24, + )); + } + } + return Container( + decoration: BoxDecoration( + color: colors.surfaceContainer, + borderRadius: BorderRadius.circular(18), + ), + child: Column(mainAxisSize: MainAxisSize.min, children: children), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/currency_picker_row.dart b/lib/new-ui/widgets/currency_picker/currency_picker_row.dart new file mode 100644 index 000000000..54d712200 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/currency_picker_row.dart @@ -0,0 +1,139 @@ +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:flutter/material.dart'; + +class CurrencyPickerRow extends StatelessWidget { + const CurrencyPickerRow({ + super.key, + required this.currency, + required this.isSelected, + required this.trailing, + required this.onTap, + this.chainPillLabel, + this.chainBadgePath, + }); + + final CryptoCurrency currency; + final bool isSelected; + final Widget trailing; + final VoidCallback onTap; + final String? chainPillLabel; + final String? chainBadgePath; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + child: Row( + children: [ + _IconWithBadge(currency: currency, badgePath: chainBadgePath), + const SizedBox(width: 12), + Expanded( + child: Row( + children: [ + Flexible( + child: Text( + currency.fullName ?? currency.title, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + ), + ), + ), + if (chainPillLabel != null) ...[ + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: colors.surfaceContainerHigh, + borderRadius: BorderRadius.circular(10), + ), + child: Text( + chainPillLabel!, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w500, + color: colors.onSecondaryContainer, + ), + ), + ), + ], + ], + ), + ), + const SizedBox(width: 8), + trailing, + const SizedBox(width: 8), + Icon( + Icons.chevron_right, + size: 20, + color: isSelected ? colors.primary : colors.onSurfaceVariant, + ), + ], + ), + ), + ); + } +} + +class _IconWithBadge extends StatelessWidget { + const _IconWithBadge({required this.currency, required this.badgePath}); + + final CryptoCurrency currency; + final String? badgePath; + + @override + Widget build(BuildContext context) { + final icon = TokenImageWidget( + imageUrl: currency.iconPath ?? '', + size: 32, + errorWidget: Container( + width: 32, + height: 32, + child: Center( + child: Text( + currency.title.length >= 2 ? currency.title.substring(0, 2) : currency.title, + ), + ), + ), + ); + if (badgePath == null) return icon; + return SizedBox( + width: 36, + height: 36, + child: Stack( + clipBehavior: Clip.none, + children: [ + icon, + Positioned( + right: -2, + bottom: -2, + child: Container( + width: 18, + height: 18, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + border: Border.all( + color: Theme.of(context).colorScheme.surfaceContainerHigh, + width: 2, + ), + color: Theme.of(context).colorScheme.onSurface, + ), + padding: const EdgeInsets.all(2), + child: CakeImageWidget( + imageUrl: badgePath, + color: Theme.of(context).colorScheme.surface, + width: 13, + height: 13, + fit: BoxFit.cover, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/currency_picker_search_field.dart b/lib/new-ui/widgets/currency_picker/currency_picker_search_field.dart new file mode 100644 index 000000000..8a62c35a7 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/currency_picker_search_field.dart @@ -0,0 +1,72 @@ +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:flutter/material.dart'; + +class CurrencyPickerSearchField extends StatelessWidget { + const CurrencyPickerSearchField({ + super.key, + required this.controller, + required this.hintText, + }); + + final TextEditingController controller; + final String hintText; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Container( + height: 48, + padding: const EdgeInsets.symmetric(horizontal: 14), + decoration: BoxDecoration( + color: colors.surfaceContainer, + border: Border.all(color: colors.surfaceContainer, width: 1), + borderRadius: BorderRadius.circular(28), + ), + child: Row( + children: [ + Icon(Icons.search, size: 20, color: colors.primary), + const SizedBox(width: 10), + Expanded( + child: TextFormField( + controller: controller, + style: Theme.of(context).textTheme.bodyMedium, + decoration: InputDecoration( + isCollapsed: true, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: hintText, + hintStyle: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: colors.onSurfaceVariant, + ), + ), + ), + ), + if (controller.text.isNotEmpty) + InkWell( + onTap: controller.clear, + customBorder: const CircleBorder(), + child: Padding( + padding: const EdgeInsets.all(4), + child: Icon(Icons.close, size: 16, color: colors.onSurfaceVariant), + ), + ), + ], + ), + ), + ); + } +} + +bool currencyMatchesQuery(CryptoCurrency c, String query) { + if (query.isEmpty) return true; + final q = query.toLowerCase(); + if (c.title.toLowerCase().contains(q)) return true; + if (c.name.toLowerCase().contains(q)) return true; + if (c.fullName?.toLowerCase().contains(q) ?? false) return true; + if (c.tag?.toLowerCase().contains(q) ?? false) return true; + if (chainNameForCurrency(c).toLowerCase().contains(q)) return true; + return false; +} diff --git a/lib/new-ui/widgets/currency_picker/currency_picker_sheet.dart b/lib/new-ui/widgets/currency_picker/currency_picker_sheet.dart new file mode 100644 index 000000000..be6600d52 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/currency_picker_sheet.dart @@ -0,0 +1,59 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/multi_network_currency_picker.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/single_network_currency_picker.dart'; +import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; +import 'package:flutter/material.dart'; + +class CurrencyPickerSheet extends StatelessWidget { + const CurrencyPickerSheet({super.key, required this.args}); + + final CurrencyPickerArgs args; + + static Future show({ + required BuildContext context, + required CurrencyPickerArgs args, + }) { + return showModalBottomSheet( + context: context, + isScrollControlled: true, + useSafeArea: true, + enableDrag: false, + isDismissible: false, + backgroundColor: Colors.transparent, + builder: (_) => CurrencyPickerSheet(args: args), + ); + } + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), + color: colors.surface, + ), + child: SafeArea( + top: false, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + ModalTopBar( + title: S.of(context).select_asset, + leadingIcon: const Icon(Icons.close), + onLeadingPressed: () => Navigator.of(context).maybePop(), + ), + Expanded( + child: args.isPreFiltered + ? SingleNetworkCurrencyPicker(args: args) + : MultiNetworkCurrencyPicker(args: args), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart b/lib/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart new file mode 100644 index 000000000..47dba9f24 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart @@ -0,0 +1,314 @@ +import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_list_container.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_search_field.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_row.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_search_result.dart'; +import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:flutter/material.dart'; + +class FiatCurrencyPickerSheet extends StatefulWidget { + const FiatCurrencyPickerSheet({ + super.key, + required this.selected, + required this.onSelected, + this.cryptoOption, + this.onCryptoSelected, + }); + + final Object? selected; + final ValueChanged onSelected; + final CryptoCurrency? cryptoOption; + final ValueChanged? onCryptoSelected; + + static const _popularOrder = [ + FiatCurrency.usd, + FiatCurrency.eur, + FiatCurrency.gbp, + FiatCurrency.jpy, + FiatCurrency.cny, + ]; + + static Future show({ + required BuildContext context, + required Object? selected, + required ValueChanged onSelected, + CryptoCurrency? cryptoOption, + ValueChanged? onCryptoSelected, + }) { + return showModalBottomSheet( + context: context, + isScrollControlled: true, + useSafeArea: true, + enableDrag: false, + backgroundColor: Colors.transparent, + builder: (_) => FiatCurrencyPickerSheet( + selected: selected, + onSelected: onSelected, + cryptoOption: cryptoOption, + onCryptoSelected: onCryptoSelected, + ), + ); + } + + @override + State createState() => _FiatCurrencyPickerSheetState(); +} + +class _FiatCurrencyPickerSheetState extends State { + final TextEditingController _searchController = TextEditingController(); + late final List _allSorted = [...FiatCurrency.all]..sort( + (a, b) => a.fullName.toLowerCase().compareTo(b.fullName.toLowerCase()), + ); + + bool get _isSearching => _searchController.text.trim().isNotEmpty; + + @override + void initState() { + super.initState(); + _searchController.addListener(() => setState(() {})); + } + + @override + void dispose() { + _searchController.dispose(); + super.dispose(); + } + + bool _matches(FiatCurrency c, String query) { + if (query.isEmpty) return true; + final q = query.toLowerCase(); + return c.fullName.toLowerCase().contains(q) || c.title.toLowerCase().contains(q); + } + + void _selectFiatCurrency(FiatCurrency c) { + widget.onSelected(c); + Navigator.of(context).maybePop(); + } + + void _selectCryptoCurrency(CryptoCurrency c) { + widget.onCryptoSelected?.call(c); + Navigator.of(context).maybePop(); + } + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + final selected = widget.selected; + final selectedFiat = selected is FiatCurrency ? selected : null; + final popular = FiatCurrencyPickerSheet._popularOrder + .where((c) => c != selectedFiat) + .toList(growable: false); + final query = _searchController.text.trim(); + final filteredAll = _allSorted.where((c) => _matches(c, query)).toList(growable: false); + + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), + color: colors.surface, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + ModalTopBar( + title: S.of(context).select_fiat_currency_title, + leadingIcon: const Icon(Icons.close), + onLeadingPressed: () => Navigator.of(context).maybePop(), + ), + Expanded( + child: _isSearching + ? FiatCurrencySearchResults( + items: filteredAll, + onSelected: _selectFiatCurrency, + selected: selectedFiat, + ) + : FiatCurrencyPickerBody( + selected: selected, + cryptoOption: widget.cryptoOption, + popular: popular, + all: filteredAll, + onSelectedFiat: _selectFiatCurrency, + onSelectedCrypto: _selectCryptoCurrency, + ), + ), + CurrencyPickerSearchField( + controller: _searchController, + hintText: S.of(context).search, + ), + const SizedBox(height: 24), + ], + ), + ), + ); + } +} + +class FiatCurrencyPickerBody extends StatelessWidget { + const FiatCurrencyPickerBody({ + super.key, + required this.selected, + required this.cryptoOption, + required this.popular, + required this.all, + required this.onSelectedFiat, + required this.onSelectedCrypto, + }); + + final Object? selected; + final CryptoCurrency? cryptoOption; + final List popular; + final List all; + final void Function(FiatCurrency) onSelectedFiat; + final void Function(CryptoCurrency) onSelectedCrypto; + + @override + Widget build(BuildContext context) { + final selectedFiat = selected is FiatCurrency ? selected as FiatCurrency : null; + final selectedCrypto = selected is CryptoCurrency ? selected as CryptoCurrency : null; + final showCryptoSection = cryptoOption != null && selectedCrypto == null; + + return ListView( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + children: [ + if (selectedFiat != null || selectedCrypto != null) ...[ + _SectionHeader(label: S.of(context).picker_section_selected), + CurrencyPickerListContainer( + rows: [ + if (selectedFiat != null) + FiatCurrencyRow( + currency: selectedFiat, + isSelected: true, + onTap: () => onSelectedFiat(selectedFiat), + ), + if (selectedCrypto != null) + _CryptoOptionRow( + currency: selectedCrypto, + isSelected: true, + onTap: () => onSelectedCrypto(selectedCrypto), + ), + ], + ), + const SizedBox(height: 16), + ], + if (showCryptoSection) ...[ + _SectionHeader(label: S.of(context).picker_section_crypto), + CurrencyPickerListContainer( + rows: [ + _CryptoOptionRow( + currency: cryptoOption!, + isSelected: false, + onTap: () => onSelectedCrypto(cryptoOption!), + ), + ], + ), + const SizedBox(height: 16), + ], + if (popular.isNotEmpty) ...[ + _SectionHeader(label: S.of(context).picker_section_popular), + CurrencyPickerListContainer( + rows: [ + for (final c in popular) + FiatCurrencyRow( + currency: c, + isSelected: false, + onTap: () => onSelectedFiat(c), + ), + ], + ), + const SizedBox(height: 16), + ], + _SectionHeader(label: S.of(context).picker_section_all_currencies), + CurrencyPickerListContainer( + rows: [ + for (final c in all) + FiatCurrencyRow( + currency: c, + isSelected: c == selectedFiat, + onTap: () => onSelectedFiat(c), + ), + ], + ), + ], + ); + } +} + +class _SectionHeader extends StatelessWidget { + const _SectionHeader({required this.label}); + + final String label; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8), + child: Text( + label, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ); + } +} + +class _CryptoOptionRow extends StatelessWidget { + const _CryptoOptionRow({ + required this.currency, + required this.isSelected, + required this.onTap, + }); + + final CryptoCurrency currency; + final bool isSelected; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + child: Row( + children: [ + CakeImageWidget( + imageUrl: currency.iconPath, + width: 28, + height: 28, + fit: BoxFit.cover, + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + currency.fullName ?? currency.title, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 2), + Text( + currency.title, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: colors.onSurfaceVariant, + ), + ), + ], + ), + ), + if (isSelected) Icon(Icons.check, size: 20, color: colors.primary), + ], + ), + ), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/fiat_currency_row.dart b/lib/new-ui/widgets/currency_picker/fiat_currency_row.dart new file mode 100644 index 000000000..d57804095 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/fiat_currency_row.dart @@ -0,0 +1,67 @@ +import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:flutter/material.dart'; + +class FiatCurrencyRow extends StatelessWidget { + const FiatCurrencyRow({ + required this.currency, + required this.isSelected, + required this.onTap, + }); + + final FiatCurrency currency; + final bool isSelected; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(4), + child: CakeImageWidget( + imageUrl: 'assets/images/flags/${currency.countryCode}.png', + width: 28, + height: 20, + fit: BoxFit.cover, + errorWidget: Container( + width: 28, + height: 20, + color: colors.surfaceContainer, + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + currency.fullName, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 2), + Text( + currency.title, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: colors.onSurfaceVariant, + ), + ), + ], + ), + ), + if (isSelected) Icon(Icons.check, size: 20, color: colors.primary), + ], + ), + ), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/fiat_currency_search_result.dart b/lib/new-ui/widgets/currency_picker/fiat_currency_search_result.dart new file mode 100644 index 000000000..57649aa50 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/fiat_currency_search_result.dart @@ -0,0 +1,52 @@ +import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_list_container.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_row.dart'; +import 'package:flutter/material.dart'; + +class FiatCurrencySearchResults extends StatelessWidget { + const FiatCurrencySearchResults({ + super.key, + required this.items, + required this.onSelected, + required this.selected, + }); + + final List items; + final void Function(FiatCurrency) onSelected; + final FiatCurrency? selected; + + @override + Widget build(BuildContext context) { + if (items.isEmpty) { + return Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + S.of(context).picker_no_matches, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ); + } + + return ListView( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + children: [ + CurrencyPickerListContainer( + rows: [ + for (final c in items) + FiatCurrencyRow( + currency: c, + isSelected: c == selected, + onTap: () => onSelected(c), + ), + ], + ), + ], + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/multi_network_currency_picker.dart b/lib/new-ui/widgets/currency_picker/multi_network_currency_picker.dart new file mode 100644 index 000000000..ffea261d2 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/multi_network_currency_picker.dart @@ -0,0 +1,679 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/chain_chip_strip.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/picker_recents_loader.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_list_container.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_row.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_search_field.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/picker_section_header.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/pill_grid.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/select_network_page.dart'; +import 'package:cake_wallet/wallet_types.g.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/currency_for_wallet_type.dart'; +import 'package:cw_core/currency_groups.dart'; +import 'package:cw_core/utils/print_verbose.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; + +class MultiNetworkCurrencyPicker extends StatefulWidget { + const MultiNetworkCurrencyPicker({super.key, required this.args}); + + final CurrencyPickerArgs args; + + @override + State createState() => _MultiNetworkCurrencyPickerState(); +} + +class _MultiNetworkCurrencyPickerState extends State { + bool _recentsLoaded = false; + WalletType? _selectedNetwork; + List _recents = const []; + final TextEditingController _searchController = TextEditingController(); + + bool get _isSearching => _searchController.text.trim().isNotEmpty; + + late final List _networks = _computeNetworks(); + + List _computeNetworks() { + final counts = {}; + for (final currency in widget.args.items) { + final walletType = cryptoCurrencyOrTokenToWalletType(currency); + if (walletType == null) continue; + counts[walletType] = (counts[walletType] ?? 0) + 1; + } + return counts.entries.where((e) => e.value >= 2).map((e) => e.key).toList(growable: false); + } + + Set get _natives => + {for (final walletType in availableWalletTypes) walletTypeToCryptoCurrency(walletType)}; + + @override + void initState() { + super.initState(); + _searchController.addListener(() => setState(() {})); + _loadRecents(); + } + + @override + void dispose() { + _searchController.dispose(); + super.dispose(); + } + + Future _loadRecents() async { + try { + final recents = await PickerRecentsLoader.load( + source: widget.args.recentsSource, + visibleItems: widget.args.items, + ); + if (!mounted) return; + setState(() { + _recents = recents; + _recentsLoaded = true; + }); + } catch (e, s) { + printV('load picker recents failed: $e\n$s'); + if (!mounted) return; + setState(() => _recentsLoaded = true); + } + } + + bool _matchesNetwork(CryptoCurrency c) { + if (_selectedNetwork == null) return true; + return cryptoCurrencyOrTokenToWalletType(c) == _selectedNetwork; + } + + List get _visibleItems { + final query = _searchController.text.trim(); + return widget.args.items + .where(_hasSupportedChain) + .where((c) => currencyMatchesQuery(c, query) && _matchesNetwork(c)) + .toList(growable: false); + } + + bool _hasSupportedChain(CryptoCurrency c) { + if (c.tag == null) return true; + return cryptoCurrencyOrTokenToWalletType(c) != null; + } + + void _selectCurrency(CryptoCurrency currency) { + widget.args.onSelected(currency); + Navigator.of(context).maybePop(); + } + + void _onStablecoinPillTapped(CryptoCurrency tapped) { + var variants = widget.args.items + .where((c) => + isTrustedStablecoin(c) && + c.title.toUpperCase() == tapped.title.toUpperCase() && + cryptoCurrencyOrTokenToWalletType(c) != null) + .toList(); + + if (_selectedNetwork != null) { + final filtered = variants + .where((c) => cryptoCurrencyOrTokenToWalletType(c) == _selectedNetwork) + .toList(growable: false); + if (filtered.isNotEmpty) variants = filtered; + } + + if (variants.length <= 1) { + _selectCurrency(variants.isNotEmpty ? variants.first : tapped); + return; + } + + Navigator.of(context).push( + PageRouteBuilder( + opaque: true, + transitionDuration: const Duration(milliseconds: 250), + reverseTransitionDuration: const Duration(milliseconds: 250), + pageBuilder: (_, __, ___) => SelectNetworkPage( + assetTitle: tapped.title, + assetFullName: tapped.fullName, + assetIconPath: tapped.iconPath, + variants: variants, + onSelected: widget.args.onSelected, + ), + transitionsBuilder: (_, animation, __, child) => SlideTransition( + position: animation.drive( + Tween(begin: const Offset(0, 1), end: Offset.zero) + .chain(CurveTween(curve: Curves.easeInOut)), + ), + child: child, + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.max, + children: [ + if (_networks.length > 1) + ChainChipStrip( + walletTypes: _networks, + selected: _selectedNetwork, + onSelected: (network) => setState(() => _selectedNetwork = network), + ), + Expanded( + child: _MultiNetworkPickerBody( + items: _visibleItems, + isSearching: _isSearching, + recents: _recents, + recentsLoaded: _recentsLoaded, + natives: _natives, + selected: widget.args.selected, + symbolResolver: widget.args.symbolResolver, + onSelect: _selectCurrency, + onStablecoinTap: _onStablecoinPillTapped, + ), + ), + CurrencyPickerSearchField( + controller: _searchController, + hintText: S.of(context).search, + ), + ], + ); + } +} + +class _MultiNetworkPickerBody extends StatefulWidget { + const _MultiNetworkPickerBody({ + required this.items, + required this.isSearching, + required this.recents, + required this.recentsLoaded, + required this.natives, + required this.selected, + required this.symbolResolver, + required this.onSelect, + required this.onStablecoinTap, + }); + + final bool isSearching; + final bool recentsLoaded; + final CryptoCurrency? selected; + final List items; + final List recents; + final Set natives; + final void Function(CryptoCurrency) onSelect; + final String Function(CryptoCurrency) symbolResolver; + final void Function(CryptoCurrency) onStablecoinTap; + + @override + State<_MultiNetworkPickerBody> createState() => _MultiNetworkPickerBodyState(); +} + +class _MultiNetworkPickerBodyState extends State<_MultiNetworkPickerBody> { + static const int _previewCount = 3; + + final ScrollController _scrollController = ScrollController(); + bool _moreCryptosSectionExpanded = false; + bool _xstocksSectionExpanded = false; + + @override + void initState() { + super.initState(); + final selected = widget.selected; + if (selected == null) return; + + final moreCryptos = _computeMoreCryptosSection(widget.items); + final xstocks = _computeXstocksSection(widget.items); + + if (moreCryptos.indexOf(selected) >= _previewCount) { + _moreCryptosSectionExpanded = true; + } + + if (xstocks.indexOf(selected) >= _previewCount) { + _xstocksSectionExpanded = true; + } + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + List _computeMoreCryptosSection(List from) { + final list = from + .where((c) => + !widget.natives.contains(c) && + cryptoCurrencyOrTokenToWalletType(c) == null && + c.tag == null && + !c.groups.contains(CurrencyGroups.stablecoin) && + !c.groups.contains(CurrencyGroups.tokenizedStock)) + .toList(); + + list.sort((a, b) => (a.fullName ?? a.title).toLowerCase().compareTo( + (b.fullName ?? b.title).toLowerCase(), + )); + + return list; + } + + List _computeXstocksSection(List from) { + return from + .where((c) => c.groups.contains(CurrencyGroups.tokenizedStock)) + .toList(growable: false); + } + + @override + Widget build(BuildContext context) { + final items = widget.items; + final isSearching = widget.isSearching; + final recents = widget.recents; + final recentsLoaded = widget.recentsLoaded; + final natives = widget.natives; + final selected = widget.selected; + final symbolResolver = widget.symbolResolver; + final onSelect = widget.onSelect; + final onStablecoinTap = widget.onStablecoinTap; + + if (items.isEmpty) { + return Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + S.of(context).picker_no_matches, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ); + } + + if (isSearching) { + return NotificationListener( + onNotification: (_) => true, + child: ListView( + controller: _scrollController, + primary: false, + physics: const ClampingScrollPhysics(), + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + children: [ + CurrencyPickerListContainer( + rows: [ + for (final item in items) + CurrencyPickerRow( + currency: item, + isSelected: selected != null && selected == item, + chainPillLabel: _chainPillLabelFor(item), + chainBadgePath: _chainBadgePathFor(item), + trailing: _SymbolTrailing( + currency: item, + symbolResolver: symbolResolver, + ), + onTap: () => onSelect(item), + ), + ], + ), + ], + ), + ); + } + + final visibleRecents = recents.where(items.contains).toList(growable: false); + + final seenStablecoinTitles = {}; + final stablecoins = items + .where((c) => isTrustedStablecoin(c) && seenStablecoinTitles.add(c.title.toUpperCase())) + .toList(growable: false); + + final cryptocurrencies = items.where(natives.contains).toList(growable: false); + final moreCryptos = _computeMoreCryptosSection(items); + final xstocks = _computeXstocksSection(items); + final allAssets = [...items]..sort((a, b) => (a.fullName ?? a.title).toLowerCase().compareTo( + (b.fullName ?? b.title).toLowerCase(), + )); + + final section = _selectedSection( + recents: visibleRecents, + stablecoins: stablecoins, + cryptocurrencies: cryptocurrencies, + moreCryptos: moreCryptos, + xstocks: xstocks, + ); + + final moreCryptosVisible = _moreCryptosSectionExpanded + ? moreCryptos + : moreCryptos.take(_previewCount).toList(growable: false); + final xstocksVisible = + _xstocksSectionExpanded ? xstocks : xstocks.take(_previewCount).toList(growable: false); + + return NotificationListener( + onNotification: (_) => true, + child: ListView( + controller: _scrollController, + primary: false, + physics: const ClampingScrollPhysics(), + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + children: [ + if (recentsLoaded && visibleRecents.isNotEmpty) + _PickerSection( + title: S.of(context).picker_section_recents, + child: _RecentsRow( + items: visibleRecents, + selected: section == _SelSection.recents ? selected : null, + symbolResolver: symbolResolver, + onTap: onSelect, + ), + ), + if (stablecoins.isNotEmpty) + _PickerSection( + title: S.of(context).picker_section_stablecoins, + child: PillGrid( + items: stablecoins, + selected: section == _SelSection.stablecoins ? selected : null, + onTap: onStablecoinTap, + symbolResolver: symbolResolver, + ), + ), + if (cryptocurrencies.isNotEmpty) + _PickerSection( + title: S.of(context).picker_section_cryptocurrencies, + child: CurrencyPickerListContainer( + rows: [ + for (final item in cryptocurrencies) + CurrencyPickerRow( + currency: item, + isSelected: section == _SelSection.cryptocurrencies && selected == item, + chainPillLabel: _chainPillLabelFor(item), + chainBadgePath: _chainBadgePathFor(item), + trailing: _SymbolTrailing( + currency: item, + symbolResolver: symbolResolver, + ), + onTap: () => onSelect(item), + ), + ], + ), + ), + if (moreCryptos.isNotEmpty) + _PickerSection( + title: S.of(context).picker_section_more_cryptocurrencies, + child: CurrencyPickerListContainer( + rows: [ + for (final item in moreCryptosVisible) + CurrencyPickerRow( + currency: item, + isSelected: section == _SelSection.moreCryptocurrencies && selected == item, + trailing: _SymbolTrailing( + currency: item, + symbolResolver: symbolResolver, + ), + onTap: () => onSelect(item), + ), + if (moreCryptos.length > _previewCount) + _SeeAllRow( + expanded: _moreCryptosSectionExpanded, + onTap: () => setState( + () => _moreCryptosSectionExpanded = !_moreCryptosSectionExpanded), + ), + ], + ), + ), + if (xstocks.isNotEmpty) + _PickerSection( + title: S.of(context).picker_section_tokenized_stocks, + child: CurrencyPickerListContainer( + rows: [ + for (final item in xstocksVisible) + CurrencyPickerRow( + currency: item, + isSelected: section == _SelSection.xstocks && selected == item, + trailing: _SymbolTrailing( + currency: item, + symbolResolver: symbolResolver, + ), + onTap: () => onSelect(item), + chainPillLabel: _chainPillLabelFor(item), + chainBadgePath: _chainBadgePathFor(item), + ), + if (xstocks.length > _previewCount) + _SeeAllRow( + expanded: _xstocksSectionExpanded, + onTap: () => + setState(() => _xstocksSectionExpanded = !_xstocksSectionExpanded), + ), + ], + ), + ), + if (allAssets.isNotEmpty) + _PickerSection( + title: S.of(context).picker_section_all_assets, + child: CurrencyPickerListContainer( + rows: [ + for (final item in allAssets) + CurrencyPickerRow( + currency: item, + isSelected: section == _SelSection.allAssets && selected == item, + chainPillLabel: _chainPillLabelFor(item), + chainBadgePath: _chainBadgePathFor(item), + trailing: _SymbolTrailing( + currency: item, + symbolResolver: symbolResolver, + ), + onTap: () => onSelect(item), + ), + ], + ), + ), + ], + ), + ); + } + + String? _chainPillLabelFor(CryptoCurrency c) { + if (c == CryptoCurrency.btcln) return _shortChainLabel(c); + if (_isL2NativeEth(c)) return _shortChainLabel(c); + if (widget.natives.contains(c)) return null; + if (cryptoCurrencyOrTokenToWalletType(c) == null) return null; + return _shortChainLabel(c); + } + + String _shortChainLabel(CryptoCurrency c) { + if (cryptoCurrencyOrTokenToWalletType(c) == WalletType.bsc) return 'BSC'; + return chainNameForCurrency(c); + } + + String? _chainBadgePathFor(CryptoCurrency c) { + if (_isL2NativeEth(c)) return c.chainIconPath; + if (widget.natives.contains(c)) return null; + final wt = cryptoCurrencyOrTokenToWalletType(c); + if (wt == null) return null; + return c.chainIconPath ?? walletTypeToCryptoCurrency(wt).chainIconPath; + } + + bool _isL2NativeEth(CryptoCurrency c) => + c == CryptoCurrency.arbEth || c == CryptoCurrency.baseEth; + + _SelSection? _selectedSection({ + required List recents, + required List stablecoins, + required List cryptocurrencies, + required List moreCryptos, + required List xstocks, + }) { + final s = widget.selected; + if (s == null) return null; + if (recents.contains(s)) return _SelSection.recents; + if (stablecoins.any((c) => c.title.toUpperCase() == s.title.toUpperCase())) { + return _SelSection.stablecoins; + } + if (cryptocurrencies.contains(s)) return _SelSection.cryptocurrencies; + if (moreCryptos.contains(s)) return _SelSection.moreCryptocurrencies; + if (xstocks.contains(s)) return _SelSection.xstocks; + return _SelSection.allAssets; + } +} + +class _PickerSection extends StatelessWidget { + const _PickerSection({required this.title, required this.child}); + + final String title; + final Widget child; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + PickerSectionHeader(title: title), + child, + const SizedBox(height: 16), + ], + ); + } +} + +class _SymbolTrailing extends StatelessWidget { + const _SymbolTrailing({ + required this.currency, + required this.symbolResolver, + }); + + final CryptoCurrency currency; + final String Function(CryptoCurrency) symbolResolver; + + @override + Widget build(BuildContext context) { + return Text( + symbolResolver(currency), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ); + } +} + +class _SeeAllRow extends StatelessWidget { + const _SeeAllRow({ + required this.expanded, + required this.onTap, + }); + + final bool expanded; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + final label = expanded ? S.of(context).picker_show_less : S.of(context).picker_see_all; + return InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), + child: Row( + children: [ + Expanded( + child: Text( + label, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + color: colors.primary, + ), + ), + ), + ], + ), + ), + ); + } +} + +class _RecentsRow extends StatelessWidget { + const _RecentsRow({ + required this.items, + required this.selected, + required this.symbolResolver, + required this.onTap, + }); + + final List items; + final CryptoCurrency? selected; + final String Function(CryptoCurrency) symbolResolver; + final void Function(CryptoCurrency) onTap; + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 44, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: items.length, + separatorBuilder: (_, __) => const SizedBox(width: 8), + itemBuilder: (_, i) { + final item = items[i]; + return _RecentPill( + currency: item, + label: symbolResolver(item), + isSelected: selected != null && selected == item, + onTap: () => onTap(item), + ); + }, + ), + ); + } +} + +class _RecentPill extends StatelessWidget { + const _RecentPill({ + required this.currency, + required this.label, + required this.isSelected, + required this.onTap, + }); + + final CryptoCurrency currency; + final String label; + final bool isSelected; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(80), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + decoration: BoxDecoration( + color: colors.surfaceContainer, + borderRadius: BorderRadius.circular(80), + border: isSelected ? Border.all(color: colors.primary, width: 1.5) : null, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + TokenImageWidget( + imageUrl: currency.iconPath ?? '', + size: 24, + ), + const SizedBox(width: 8), + Text( + label, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ); + } +} + +enum _SelSection { + recents, + stablecoins, + cryptocurrencies, + moreCryptocurrencies, + xstocks, + allAssets, +} diff --git a/lib/new-ui/widgets/currency_picker/picker_recents_loader.dart b/lib/new-ui/widgets/currency_picker/picker_recents_loader.dart new file mode 100644 index 000000000..2a7c3cda7 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/picker_recents_loader.dart @@ -0,0 +1,97 @@ +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/order/order.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:hive/hive.dart'; + +class PickerRecentsLoader { + const PickerRecentsLoader._(); + + static const int defaultLimit = 6; + + static final Set _executedTradeStates = { + TradeState.complete, + TradeState.completed, + TradeState.finished, + TradeState.success, + TradeState.settled, + TradeState.traded, + }; + + static Future> load({ + required RecentsSource source, + required List visibleItems, + int limit = defaultLimit, + }) async { + switch (source) { + case RecentsSource.none: + return const []; + case RecentsSource.trades: + return _fromTrades(visibleItems, limit); + case RecentsSource.orders: + return _fromOrders(visibleItems, limit); + } + } + + static Future> _fromTrades( + List visibleItems, + int limit, + ) async { + final trades = await Trade.getAll(); + final ordered = trades + .where((t) => _executedTradeStates.contains(t.state)) + .toList() + ..sort((a, b) => (b.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0)) + .compareTo(a.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0))); + + return _collect( + ordered.expand((t) => [t.from, t.to]), + visibleItems, + limit, + ); + } + + static Future> _fromOrders( + List visibleItems, + int limit, + ) async { + final orders = Hive.box(Order.boxName).values.toList() + ..sort((a, b) => b.createdAt.compareTo(a.createdAt)); + + return _collect( + orders.expand((o) => [_tryResolve(o.from), _tryResolve(o.to)]), + visibleItems, + limit, + ); + } + + static List _collect( + Iterable candidates, + List visibleItems, + int limit, + ) { + final visibleSet = visibleItems.toSet(); + final seen = {}; + final collected = []; + + for (final candidate in candidates) { + if (candidate == null) continue; + if (!visibleSet.contains(candidate)) continue; + if (!seen.add(candidate)) continue; + collected.add(candidate); + if (collected.length >= limit) break; + } + + return collected; + } + + static CryptoCurrency? _tryResolve(String? raw) { + if (raw == null || raw.isEmpty) return null; + try { + return CryptoCurrency.fromString(raw); + } catch (_) { + return null; + } + } +} diff --git a/lib/new-ui/widgets/currency_picker/picker_section_header.dart b/lib/new-ui/widgets/currency_picker/picker_section_header.dart new file mode 100644 index 000000000..1f75f8b34 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/picker_section_header.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class PickerSectionHeader extends StatelessWidget { + const PickerSectionHeader({super.key, required this.title}); + + final String title; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(4, 12, 4, 8), + child: Text( + title, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/pill_grid.dart b/lib/new-ui/widgets/currency_picker/pill_grid.dart new file mode 100644 index 000000000..fdcd5777a --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/pill_grid.dart @@ -0,0 +1,99 @@ +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:flutter/material.dart'; + +class PillGrid extends StatelessWidget { + const PillGrid({ + super.key, + required this.items, + required this.selected, + required this.onTap, + required this.symbolResolver, + }); + + final List items; + final CryptoCurrency? selected; + final ValueChanged onTap; + final String Function(CryptoCurrency c) symbolResolver; + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + const gap = 8.0; + final cardWidth = (constraints.maxWidth - gap) / 2; + return Wrap( + spacing: gap, + runSpacing: gap, + children: [ + for (final item in items) + SizedBox( + width: cardWidth, + child: _PillCard( + currency: item, + isSelected: selected != null && selected == item, + label: symbolResolver(item), + onTap: () => onTap(item), + ), + ), + ], + ); + }, + ); + } +} + +class _PillCard extends StatelessWidget { + const _PillCard({ + required this.currency, + required this.isSelected, + required this.label, + required this.onTap, + }); + + final CryptoCurrency currency; + final bool isSelected; + final String label; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(80), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + decoration: BoxDecoration( + color: colors.surfaceContainer, + borderRadius: BorderRadius.circular(80), + border: isSelected ? Border.all(color: colors.primary, width: 1.5) : null, + ), + child: Row( + children: [ + TokenImageWidget( + imageUrl: currency.iconPath ?? '', + size: 24, + ), + const SizedBox(width: 8), + Expanded( + child: Text( + label, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w600, + ), + ), + ), + Icon( + Icons.chevron_right, + size: 18, + color: colors.onSurfaceVariant, + ), + ], + ), + ), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/select_network_page.dart b/lib/new-ui/widgets/currency_picker/select_network_page.dart new file mode 100644 index 000000000..988dc3b24 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/select_network_page.dart @@ -0,0 +1,140 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_list_container.dart'; +import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/currency_for_wallet_type.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; + +class SelectNetworkPage extends StatelessWidget { + const SelectNetworkPage({ + super.key, + required this.assetTitle, + required this.assetFullName, + required this.assetIconPath, + required this.variants, + required this.onSelected, + }); + + final String assetTitle; + final String? assetFullName; + final String? assetIconPath; + final List variants; + final ValueChanged onSelected; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + return Scaffold( + backgroundColor: colors.surface, + body: SafeArea( + child: Column( + children: [ + ModalTopBar( + title: S.of(context).select_network_title, + leadingIcon: const Icon(Icons.arrow_back), + onLeadingPressed: () => Navigator.of(context).maybePop(), + ), + const SizedBox(height: 24), + CakeImageWidget( + imageUrl: assetIconPath, + width: 75, + height: 75, + fit: BoxFit.cover, + ), + const SizedBox(height: 12), + Text( + assetTitle, + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 12), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Text( + S.of(context).select_network_subtitle, + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: colors.onSurfaceVariant), + ), + ), + const SizedBox(height: 24), + Expanded( + child: ListView( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + children: [ + CurrencyPickerListContainer( + rows: [ + for (final variant in variants) + _NetworkRow( + variant: variant, + onTap: () { + final nav = Navigator.of(context); + onSelected(variant); + if (nav.canPop()) nav.pop(); + if (nav.canPop()) nav.pop(); + }, + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} + +class _NetworkRow extends StatelessWidget { + const _NetworkRow({required this.variant, required this.onTap}); + + final CryptoCurrency variant; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + final wt = cryptoCurrencyOrTokenToWalletType(variant); + final networkIconPath = + wt != null ? getCryptoCurrencyIconForWalletListItem(wt) : variant.iconPath; + final networkName = chainNameForCurrency(variant); + return InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), + child: Row( + children: [ + CakeImageWidget( + imageUrl: networkIconPath, + width: 28, + height: 28, + fit: BoxFit.cover, + ), + const SizedBox(width: 12), + Expanded( + child: Text( + networkName, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + ), + ), + ), + Icon( + Icons.chevron_right, + size: 20, + color: colors.onSurfaceVariant, + ), + ], + ), + ), + ); + } +} diff --git a/lib/new-ui/widgets/currency_picker/single_network_currency_picker.dart b/lib/new-ui/widgets/currency_picker/single_network_currency_picker.dart new file mode 100644 index 000000000..79bb99622 --- /dev/null +++ b/lib/new-ui/widgets/currency_picker/single_network_currency_picker.dart @@ -0,0 +1,162 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_list_container.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_row.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_search_field.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/picker_section_header.dart'; +import 'package:cake_wallet/reactions/wallet_utils.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/currency_for_wallet_type.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; + +class SingleNetworkCurrencyPicker extends StatefulWidget { + const SingleNetworkCurrencyPicker({super.key, required this.args}); + + final CurrencyPickerArgs args; + + @override + State createState() => _SingleNetworkCurrencyPickerState(); +} + +class _SingleNetworkCurrencyPickerState extends State { + CurrencyPickerArgs get _args => widget.args; + WalletType get _network => _args.filterByNetwork!; + final TextEditingController _searchController = TextEditingController(); + + @override + void initState() { + super.initState(); + _searchController.addListener(() => setState(() {})); + } + + @override + void dispose() { + _searchController.dispose(); + super.dispose(); + } + + void _selectCurrency(CryptoCurrency currency) { + _args.onSelected(currency); + Navigator.of(context).maybePop(); + } + + double _fiatValueFor(CryptoCurrency c) => _args.balanceByAsset?[c]?.fiatValue ?? 0; + + @override + Widget build(BuildContext context) { + final native = walletTypeToCryptoCurrency(_network); + final query = _searchController.text.trim(); + final tokens = _args.items + .where((c) => c != native) + .where((c) => currencyMatchesQuery(c, query)) + .toList(); + + final insertOrder = {for (var i = 0; i < tokens.length; i++) tokens[i]: i}; + tokens.sort((a, b) { + final av = _fiatValueFor(a); + final bv = _fiatValueFor(b); + if (bv != av) return bv.compareTo(av); + return (insertOrder[a] ?? 0).compareTo(insertOrder[b] ?? 0); + }); + final nativeMatches = currencyMatchesQuery(native, query); + + return Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: (nativeMatches || tokens.isNotEmpty) + ? ListView( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + children: [ + if (nativeMatches) ...[ + PickerSectionHeader(title: S.of(context).picker_section_gas_token), + CurrencyPickerListContainer( + rows: [ + CurrencyPickerRow( + currency: native, + isSelected: _args.selected == native, + trailing: _BalanceTrailing(balance: _args.balanceByAsset?[native]), + onTap: () => _selectCurrency(native), + ), + ], + ), + const SizedBox(height: 16), + ], + if (tokens.isNotEmpty) ...[ + PickerSectionHeader( + title: S + .of(context) + .picker_section_tokens_standard(tokenStandardFor(_network)), + ), + CurrencyPickerListContainer( + rows: [ + for (final t in tokens) + CurrencyPickerRow( + currency: t, + isSelected: _args.selected == t, + trailing: _BalanceTrailing(balance: _args.balanceByAsset?[t]), + onTap: () => _selectCurrency(t), + ), + ], + ), + ], + ], + ) + : Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + S.of(context).picker_no_matches, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ), + ), + CurrencyPickerSearchField( + controller: _searchController, + hintText: S.of(context).search, + ), + ], + ); + } +} + +class _BalanceTrailing extends StatelessWidget { + const _BalanceTrailing({required this.balance}); + + final CurrencyPickerBalance? balance; + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + final amount = balance?.amount ?? '—'; + final fiat = balance?.fiat; + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + amount, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w500, + ), + ), + if (fiat != null && fiat.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 2), + child: Text( + fiat, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, + color: colors.onSurfaceVariant, + ), + ), + ), + ], + ); + } +} diff --git a/lib/new-ui/widgets/line_tab_switcher.dart b/lib/new-ui/widgets/line_tab_switcher.dart index 30076ac21..b20cd23f7 100644 --- a/lib/new-ui/widgets/line_tab_switcher.dart +++ b/lib/new-ui/widgets/line_tab_switcher.dart @@ -127,6 +127,7 @@ class _LineTabSwitcherState extends State { }).toList() ) ), + if(widget.tabs.length > 1) Container( width: totalWidth, height: 2, diff --git a/lib/new-ui/widgets/receive_page/receive_amount_modal.dart b/lib/new-ui/widgets/receive_page/receive_amount_modal.dart index ce2b0d35f..9ad112ffa 100644 --- a/lib/new-ui/widgets/receive_page/receive_amount_modal.dart +++ b/lib/new-ui/widgets/receive_page/receive_amount_modal.dart @@ -1,15 +1,16 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_sheet.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/new-ui/widgets/new_primary_button.dart'; import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; -import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:flutter_svg/svg.dart'; class ReceiveAmountModal extends StatefulWidget { const ReceiveAmountModal( @@ -84,14 +85,14 @@ class _ReceiveAmountModalState extends State { Row( spacing: 8, children: [ - Image.asset( - widget.walletAddressListViewModel.tokenCurrency - ?.iconPath ?? - widget.walletAddressListViewModel.currencies.first - .iconPath ?? - "", - width: 32, - height: 32), + TokenImageWidget( + imageUrl: widget.walletAddressListViewModel.tokenCurrency + ?.iconPath ?? + widget.walletAddressListViewModel.currencies.first + .iconPath ?? + "", + size: 32, + ), Text((widget.walletAddressListViewModel.tokenCurrency ?? widget.walletAddressListViewModel.currencies.first as CryptoCurrency) @@ -216,35 +217,31 @@ class _ReceiveAmountModalState extends State { ); } - void _presentTokenCurrencyPicker(BuildContext context) async { - await showPopUp( - builder: (_) => CurrencyPicker( - selectedAtIndex: widget.walletAddressListViewModel.tokenCurrencyIndex, - items: widget.walletAddressListViewModel.tokenCurrencies, - hintText: S.of(context).search_currency, - onItemSelected: widget.walletAddressListViewModel.setTokenCurrency, - ), + void _presentTokenCurrencyPicker(BuildContext context) { + final items = widget.walletAddressListViewModel.tokenCurrencies + .whereType() + .toList(); + CurrencyPickerSheet.show( context: context, + args: CurrencyPickerArgs( + items: items, + selected: widget.walletAddressListViewModel.tokenCurrency, + onSelected: widget.walletAddressListViewModel.setTokenCurrency, + symbolResolver: widget.walletAddressListViewModel.amountParsingProxy.getCryptoSymbol, + ), ); } - void _presentFiatCurrencyPicker(BuildContext context) async { - final currs = widget.walletAddressListViewModel.currencies.toList(); - // the first options should be the crypto and the default fiat currency - currs.sort((a, b) { - if(a == widget.walletAddressListViewModel.fiatCurrency || a is CryptoCurrency) return -1; - if(b == widget.walletAddressListViewModel.fiatCurrency || a is CryptoCurrency) return 1; - return 0; - }); - - await showPopUp( - builder: (_) => CurrencyPicker( - selectedAtIndex: currs.indexOf(widget.walletAddressListViewModel.selectedCurrency), - items: currs, - hintText: S.of(context).search_currency, - onItemSelected: widget.walletAddressListViewModel.selectCurrency, - ), + void _presentFiatCurrencyPicker(BuildContext context) { + final selected = widget.walletAddressListViewModel.selectedCurrency; + final cryptoOption = + widget.walletAddressListViewModel.currencies.whereType().firstOrNull; + FiatCurrencyPickerSheet.show( context: context, + selected: selected, + cryptoOption: cryptoOption, + onSelected: widget.walletAddressListViewModel.selectCurrency, + onCryptoSelected: widget.walletAddressListViewModel.selectCurrency, ); } } diff --git a/lib/new-ui/widgets/receive_page/receive_info_box.dart b/lib/new-ui/widgets/receive_page/receive_info_box.dart index 0b9bc6959..b3a0e9d17 100644 --- a/lib/new-ui/widgets/receive_page/receive_info_box.dart +++ b/lib/new-ui/widgets/receive_page/receive_info_box.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_type.dart'; @@ -177,10 +178,9 @@ class InfoboxCurrencyRow extends StatelessWidget { color: Theme.of(context).colorScheme.surfaceContainer, width: iconBorder), borderRadius: BorderRadius.circular(9999999)), - child: CakeImageWidget( - imageUrl: entry.value.iconPath, - width: 24, - height: 24, + child: TokenImageWidget( + imageUrl: entry.value.iconPath ?? '', + size: 24, ), ), )) diff --git a/lib/new-ui/widgets/receive_page/receive_token_display.dart b/lib/new-ui/widgets/receive_page/receive_token_display.dart index 64d20d4ec..f4bebe3a0 100644 --- a/lib/new-ui/widgets/receive_page/receive_token_display.dart +++ b/lib/new-ui/widgets/receive_page/receive_token_display.dart @@ -33,8 +33,9 @@ class ReceiveTokenDisplay extends StatelessWidget { child: Row( spacing:4, children: [ - CakeImageWidget(imageUrl: - "assets/new-ui/chain_badges/${walletTypeToString(addressListViewModel.wallet.type).toLowerCase()}.svg", + CakeImageWidget( + imageUrl: + "assets/new-ui/chain_badges/${addressListViewModel.wallet.type == WalletType.bsc ? 'bnb' : walletTypeToString(addressListViewModel.wallet.type).toLowerCase()}.svg", width: 16, height: 16, colorFilter: ColorFilter.mode( diff --git a/lib/new-ui/widgets/scan_page/network_list.dart b/lib/new-ui/widgets/scan_page/network_list.dart new file mode 100644 index 000000000..aa3d8e448 --- /dev/null +++ b/lib/new-ui/widgets/scan_page/network_list.dart @@ -0,0 +1,105 @@ +import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart'; +import 'package:cake_wallet/wallet_types.g.dart'; +import 'package:flutter/material.dart'; +import 'package:hive/hive.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class ScanPageNetworkList extends StatelessWidget { + const ScanPageNetworkList({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.vertical(top: Radius.circular(18)), + color: Theme.of(context).colorScheme.surface), + child: Column( + children: [ + ModalTopBar( + title: S.of(context).compatible_services, + leadingIcon: Icon(Icons.arrow_back_ios_new), + onLeadingPressed: Navigator.of(context).pop, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + spacing: 32, + children: [ + Column( + spacing: 24, + children: [ + CakeImageWidget( + imageUrl: "assets/new-ui/scan_service.svg", + width: 75, + height: 75, + colorFilter: + ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn), + ), + Text( + S.of(context).compatible_services_desc, + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), + textAlign: TextAlign.center, + ) + ], + ), + NewListSections(sections: { + "base": [ + ListItemRegularRow( + keyValue: "addrs", + label: S.of(context).crypto_addresses, + showArrow: false, + iconPath: "assets/new-ui/navbar/wallets.svg", + iconColor: Theme.of(context).colorScheme.onSurfaceVariant, + subtitle: "${availableWalletTypes.length} ${S.of(context).networks}"), + ListItemRegularRow( + keyValue: "invoices", + label: S.of(context).payment_invoices, + showArrow: false, + iconColor: Theme.of(context).colorScheme.onSurfaceVariant, + iconPath: "assets/new-ui/payment_invoices.svg"), + ListItemRegularRow( + keyValue: "contacts", + label: S.of(context).contacts, + showArrow: false, + iconColor: Theme.of(context).colorScheme.onSurfaceVariant, + iconPath: "assets/new-ui/navbar/contacts.svg"), + ListItemRegularRow( + keyValue: "nodes", + label: S.of(context).nodes, + showArrow: false, + iconColor: Theme.of(context).colorScheme.onSurfaceVariant, + iconPath: "assets/new-ui/node_minimal.svg"), + ], + "extra": [ + ListItemRegularRow( + iconPath: "assets/new-ui/wc_min.svg", + keyValue: "wc", + label: "WalletConnect", + subtitle: S.of(context).wc_desc, + trailingIconPath: "assets/new-ui/external_link.svg", + onTap: () { + launchUrl(Uri.https("walletconnect.com")); + }), + ListItemRegularRow( + iconPath: "assets/new-ui/ocp_min.svg", + keyValue: "ocp", + label: "OpenCryptoPay", + subtitle: S.of(context).ocp_desc, + trailingIconPath: "assets/new-ui/external_link.svg", + onTap: () { + launchUrl(Uri.https("opencryptopay.io")); + }) + ] + }) + ], + ), + ) + ], + ), + ); + } +} diff --git a/lib/new-ui/widgets/send_page/l2_action_wallet_selector.dart b/lib/new-ui/widgets/send_page/l2_action_wallet_selector.dart index 2ee57ef9e..6a9aa35c8 100644 --- a/lib/new-ui/widgets/send_page/l2_action_wallet_selector.dart +++ b/lib/new-ui/widgets/send_page/l2_action_wallet_selector.dart @@ -126,7 +126,7 @@ class _L2ActionWalletSelectorState extends State { padding: const EdgeInsets.symmetric(vertical: 4.0), child: WalletRow( currencyIconPath: - walletTypeToCryptoCurrency(item.type).iconPath ?? "", + getCryptoCurrencyIconForWalletListItem(item.type), walletName: item.name, isCurrent: item.name == widget.sendViewModel.wallet.name, isSelected: _selectedWalletIndex == index && !textEntered, diff --git a/lib/new-ui/widgets/send_page/send_amount_input.dart b/lib/new-ui/widgets/send_page/send_amount_input.dart index 2edcf9c8e..5d51baba4 100644 --- a/lib/new-ui/widgets/send_page/send_amount_input.dart +++ b/lib/new-ui/widgets/send_page/send_amount_input.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/new-ui/widgets/send_page/floating_icon_button.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:flutter/material.dart'; @@ -109,7 +110,7 @@ class _NewSendAmountInputState extends State { spacing: 8, children: [ if (widget.hasPicker && widget.currencyIconPath.isNotEmpty) - CakeImageWidget(imageUrl: widget.currencyIconPath, width: 24, height: 24), + TokenImageWidget(imageUrl: widget.currencyIconPath, size: 24), Text(widget.currency), if (widget.hasPicker) CakeImageWidget(imageUrl: diff --git a/lib/new-ui/widgets/send_page/send_confirm_sheet.dart b/lib/new-ui/widgets/send_page/send_confirm_sheet.dart index 65e6f8d6c..0b3a867d6 100644 --- a/lib/new-ui/widgets/send_page/send_confirm_sheet.dart +++ b/lib/new-ui/widgets/send_page/send_confirm_sheet.dart @@ -2,17 +2,25 @@ import 'dart:io'; import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/core/utilities.dart'; +import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/entities/contact.dart'; +import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/new-ui/widgets/animated_dropdown.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart'; +import 'package:cake_wallet/new-ui/widgets/new_primary_button.dart'; import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; import 'package:cake_wallet/new-ui/widgets/send_page/send_confirm_bottom_widget.dart'; +import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/utils/address_formatter.dart'; import 'package:cake_wallet/view_model/send/send_view_model.dart'; import 'package:cake_wallet/view_model/send/send_view_model_state.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/crypto_amount_format.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -31,12 +39,14 @@ class SendConfirmSheet extends StatefulWidget { } class _SendConfirmSheetState extends State { + bool _committed = false; + void initState() { super.initState(); - reaction((context) => widget.sendViewModel.state, (state) { - if (state is TransactionCommitted) { - Future.delayed(const Duration(seconds: 2), () { - if (mounted) Navigator.of(context).maybePop(); + reaction((_)=>widget.sendViewModel.state, (state){ + if(state is TransactionCommitted) { + setState(() { + _committed = true; }); } }); @@ -60,33 +70,48 @@ class _SendConfirmSheetState extends State { borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), child: SafeArea( - child: Observer( + child: Observer( builder: (_) { - final commited = widget.sendViewModel.state is TransactionCommitted; - return Stack( - fit: StackFit.loose, - children: [ - Positioned.fill( + return AnimatedSize( + duration: const Duration(milliseconds: 300), + curve: Curves.easeOutCubic, + alignment: Alignment.topCenter, + clipBehavior: Clip.hardEdge, + child: Stack( + clipBehavior: Clip.none, + children: [ + Align( + alignment: Alignment.topCenter, + heightFactor: _committed ? 0.0 : 1.0, child: AnimatedSlide( - offset: commited ? Offset.zero : const Offset(1, 0), - duration: const Duration(milliseconds: 300), - curve: Curves.easeOutCubic, - child: const TransactionCommitedScreen(), - )), - AnimatedSlide( - offset: commited ? const Offset(-1, 0) : Offset.zero, - duration: const Duration(milliseconds: 300), - curve: Curves.easeOutCubic, - child: SendTransactionDetails( - sendViewModel: widget.sendViewModel, - isPage: widget.isPage, - title: widget.title, - iconPath: widget.iconPath), - ), - ], + offset: _committed ? const Offset(-1, 0) : Offset.zero, + duration: const Duration(milliseconds: 300), + curve: Curves.easeOutCubic, + child: SendTransactionDetails( + sendViewModel: widget.sendViewModel, + isPage: widget.isPage, + title: widget.title, + iconPath: widget.iconPath, + ), + ), + ), + Align( + alignment: Alignment.topCenter, + heightFactor: _committed ? 1.0 : 0.0, + child: AnimatedSlide( + offset: _committed ? Offset.zero : const Offset(1, 0), + duration: const Duration(milliseconds: 300), + curve: Curves.easeOutCubic, + child: TransactionCommitedScreen( + sendViewModel: widget.sendViewModel, + ), + ), + ), + ], + ), ); }, - ), + ) ), ), ), @@ -178,7 +203,7 @@ class SendTransactionDetails extends StatelessWidget { }), sendViewModel.selectedCryptoCurrency) : sendViewModel.amountParsingProxy.getDisplayCryptoAmount( - formatAmount(transaction.amountFormatted), sendViewModel.selectedCryptoCurrency); + formatAmount(transaction.amountFormatted), sendViewModel.selectedCryptoCurrency).withMaxDecimals(8); final fee = "${(transaction == null) ? sendViewModel.amountParsingProxy.getDisplayCryptoStringFromBigInt(sumByBigInt( @@ -404,29 +429,150 @@ class SendTransactionDetails extends StatelessWidget { } } -class TransactionCommitedScreen extends StatelessWidget { - const TransactionCommitedScreen({super.key}); +class TransactionCommitedScreen extends StatefulWidget { + const TransactionCommitedScreen({super.key, this.sendViewModel}); + + final SendViewModel? sendViewModel; + + @override + State createState() => _TransactionCommitedScreenState(); +} + +class _TransactionCommitedScreenState extends State { + bool _isNoteButtonLoading = false; @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 24.0), - child: Column( + return Observer( + builder: (_) => Column( spacing: 12, - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + SizedBox(height: 12,), Text( S.of(context).transaction_sent_new, style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600), ), - Image.asset(width: 256, height: 256, "assets/images/birthday_cake.png") + SizedBox(), + CakeImageWidget(width: 200, height: 200, imageUrl: "assets/new-ui/birthday_cake.svg"), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + spacing: 12, + children: [ + if (widget.sendViewModel != null) + Row( + spacing: 8, + children: [ + if (!(widget.sendViewModel!.checkIfAddressIsAContact( + widget.sendViewModel!.outputs.first.address)) && + !(widget.sendViewModel!.outputs.first.isParsedAddress)) + TransactionCommittedScreenActionButton( + text: S.of(context).save_contact, + iconPath: "assets/new-ui/save_contact.svg", + onTap: () { + Navigator.of(context).pushNamed(Routes.addressBookAddContact, + arguments: ContactRecord( + CakeHive.box(Contact.boxName), + Contact( + name: "", + address: widget.sendViewModel!.outputs.first.address, + type: widget.sendViewModel!.wallet.currency))); + }), + // lightning has to be hacked in here as it doesn't get added to tx history for a few secs after committing. + if (widget.sendViewModel!.transactionInfo != null || + widget.sendViewModel!.currency == CryptoCurrency.btcln) + TransactionCommittedScreenActionButton( + text: S.of(context).add_a_note, + iconPath: "assets/new-ui/add_note.svg", + isLoading: _isNoteButtonLoading, + onTap: () async { + setState(() { + _isNoteButtonLoading = true; + }); + + // for ln, we want to show the button and just have it wait until it appears in tx history + // for other currs this is instant + await asyncWhen((_) => widget.sendViewModel!.transactionInfo != null); + + setState(() { + _isNoteButtonLoading = false; + }); + + final page = getIt.get( + param1: widget.sendViewModel!.transactionInfo!, param2: true); + showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (context) => page); + }), + ], + ), + NewPrimaryButton( + onPressed: Navigator.of(context).maybePop, + text: S.of(context).done, + color: Theme.of(context).colorScheme.primary, + textColor: Theme.of(context).colorScheme.onPrimary), + SizedBox(height: 12,) + ], + ), + ), ], ), ); } } +class TransactionCommittedScreenActionButton extends StatelessWidget { + const TransactionCommittedScreenActionButton( + {super.key, + required this.text, + required this.iconPath, + required this.onTap, + this.isLoading = false}); + + final String text; + final String iconPath; + final VoidCallback onTap; + final bool isLoading; + + @override + Widget build(BuildContext context) { + return Flexible( + child: GestureDetector( + onTap: onTap, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: Theme.of(context).colorScheme.surfaceContainer), + child: Padding( + padding: EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 10, + children: [ + isLoading + ? CupertinoActivityIndicator() + : CakeImageWidget( + imageUrl: iconPath, + width: 24, + height: 24, + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.primary, BlendMode.srcIn), + ), + Text( + text, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500), + ) + ], + ), + ), + ))); + } +} class MultiSendAddressPreview extends StatefulWidget { const MultiSendAddressPreview( diff --git a/lib/new-ui/widgets/swap_page/swap_address_selection_modal.dart b/lib/new-ui/widgets/swap_page/swap_address_selection_modal.dart index 271f38898..134abce7a 100644 --- a/lib/new-ui/widgets/swap_page/swap_address_selection_modal.dart +++ b/lib/new-ui/widgets/swap_page/swap_address_selection_modal.dart @@ -105,7 +105,7 @@ class _SwapAddressSelectionModalState extends State { !widget.exchangeViewModel.isSendFromExternal; } - final String currencyIconPath = walletTypeToCryptoCurrency(item.type).iconPath ?? ""; + final String currencyIconPath = getCryptoCurrencyIconForWalletListItem(item.type); final bool hasAccounts = item.type == WalletType.monero && widget.isSelectingReceiver; diff --git a/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart b/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart index 9ee6fadcb..e85620aa3 100644 --- a/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart +++ b/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart @@ -123,18 +123,27 @@ class _SwapSendExternalModalState extends State { largeQrMode = !largeQrMode; }); }, - child: AnimatedContainer( + child: TweenAnimationBuilder( duration: const Duration(milliseconds: 400), curve: Curves.easeOutCubic, - width: resolvedSize, - height: resolvedSize, - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: QrImage( - embeddedImagePath: widget.from.iconPath, - data: uri.toString(), - ), + tween: Tween( + begin: resolvedSize, + end: resolvedSize, ), + builder: (context, animatedSize, child) { + return SizedBox( + width: animatedSize, + height: animatedSize, + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: QrImage( + size: animatedSize, + embeddedImagePath: widget.from.iconPath, + data: uri.toString(), + ), + ), + ); + }, ), ), AddressFormatter.buildSegmentedAddress( diff --git a/lib/reactions/wallet_connect.dart b/lib/reactions/wallet_connect.dart index 96fe0a63c..fcfb06fe9 100644 --- a/lib/reactions/wallet_connect.dart +++ b/lib/reactions/wallet_connect.dart @@ -5,6 +5,22 @@ import 'package:cake_wallet/src/screens/wallet_connect/services/chain_service/so import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/evm/evm.dart'; +const List walletConnectCompatibleChains = [ + WalletType.ethereum, + WalletType.polygon, + WalletType.base, + WalletType.arbitrum, + WalletType.bsc, + WalletType.solana, +]; + +String walletConnectCompatibleChainsLabel() { + final names = walletConnectCompatibleChains.map(walletTypeToDisplayName).toList(); + if (names.length <= 1) return names.join(); + final head = names.sublist(0, names.length - 1).join(', '); + return '$head, and ${names.last}'; +} + bool isEVMCompatibleChain(WalletType walletType) { switch (walletType) { case WalletType.polygon: @@ -47,19 +63,8 @@ bool isNFTACtivatedChain(WalletType walletType, {int? chainId}) { } } -bool isWalletConnectCompatibleChain(WalletType walletType) { - switch (walletType) { - case WalletType.solana: - case WalletType.polygon: - case WalletType.ethereum: - case WalletType.base: - case WalletType.arbitrum: - case WalletType.bsc: - return true; - default: - return false; - } -} +bool isWalletConnectCompatibleChain(WalletType walletType) => + walletConnectCompatibleChains.contains(walletType); String getChainNameSpaceAndIdBasedOnWalletType(WalletType walletType, {int? chainId}) { if (chainId != null) { diff --git a/lib/reactions/wallet_utils.dart b/lib/reactions/wallet_utils.dart index 1b9e3bcd0..dc2ed1af4 100644 --- a/lib/reactions/wallet_utils.dart +++ b/lib/reactions/wallet_utils.dart @@ -52,4 +52,22 @@ bool hasTokens(WalletType walletType) { default: return false; } -} \ No newline at end of file +} + +String tokenStandardFor(WalletType walletType) { + switch (walletType) { + case WalletType.ethereum: + case WalletType.polygon: + case WalletType.arbitrum: + case WalletType.base: + return 'ERC-20'; + case WalletType.bsc: + return 'BEP-20'; + case WalletType.solana: + return 'SPL'; + case WalletType.tron: + return 'TRC-20'; + default: + return walletTypeToString(walletType); + } +} diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart index 76b2591be..7ca41a2c6 100644 --- a/lib/solana/cw_solana.dart +++ b/lib/solana/cw_solana.dart @@ -409,4 +409,33 @@ class CWSolana extends Solana { await Future.wait(tokenChecks); } catch (_) {} } + + @override + TransactionInfo getTransactionInfo({ + required String id, + required DateTime blockTime, + required String to, + required String from, + String? tokenSymbol, + required TransactionDirection direction, + required double solAmount, + required bool isPending, + required double txFee, + }) => + SolanaTransactionInfo( + id: id, + blockTime: blockTime, + to: to, + from: from, + tokenSymbol: tokenSymbol ?? "SOL", + direction: direction, + solAmount: solAmount, + isPending: isPending, + txFee: txFee); + + @override + double getPendingTransactionAmount(PendingTransaction tx) => (tx as PendingSolanaTransaction).amount; + + @override + double getPendingTransactionFee(PendingTransaction tx) => (tx as PendingSolanaTransaction).fee; } diff --git a/lib/src/screens/buy/buy_sell_page.dart b/lib/src/screens/buy/buy_sell_page.dart index 1bdcadba1..1a3c181cf 100644 --- a/lib/src/screens/buy/buy_sell_page.dart +++ b/lib/src/screens/buy/buy_sell_page.dart @@ -3,6 +3,9 @@ import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_sheet.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart'; @@ -398,6 +401,7 @@ class BuySellPage extends BasePage { showLimitsField: false, currencies: buySellViewModel.fiatCurrencies, onCurrencySelected: (currency) => buySellViewModel.changeFiatCurrency(currency: currency), + onTapCurrencyPicker: _presentFiatPicker, imageArrow: Image.asset( 'assets/images/arrow_bottom_purple_icon.png', color: Theme.of(context).colorScheme.primary, @@ -435,6 +439,7 @@ class BuySellPage extends BasePage { isMoneroWallet: buySellViewModel.wallet == WalletType.monero, currencies: buySellViewModel.cryptoCurrencies, onCurrencySelected: (currency) => buySellViewModel.changeCryptoCurrency(currency: currency), + onTapCurrencyPicker: _presentCryptoPicker, imageArrow: Image.asset( 'assets/images/arrow_bottom_cake_green.png', color: Theme.of(context).colorScheme.primary, @@ -504,6 +509,29 @@ class BuySellPage extends BasePage { ); } + void _presentFiatPicker(BuildContext context) { + FiatCurrencyPickerSheet.show( + context: context, + selected: buySellViewModel.fiatCurrency, + onSelected: (currency) => buySellViewModel.changeFiatCurrency(currency: currency), + ); + } + + void _presentCryptoPicker(BuildContext context) { + final items = [...buySellViewModel.cryptoCurrencies]; + appendEvmDefaultTokens(items); + CurrencyPickerSheet.show( + context: context, + args: CurrencyPickerArgs( + items: items, + selected: buySellViewModel.cryptoCurrency, + recentsSource: RecentsSource.orders, + onSelected: (currency) => buySellViewModel.changeCryptoCurrency(currency: currency), + symbolResolver: buySellViewModel.amountParsingProxy.getCryptoSymbol, + ), + ); + } + Future fetchParsedAddress( BuildContext context, String domain, diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 7cfa3f149..07cb5625e 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/contact_base.dart'; import 'package:cake_wallet/entities/contact_record.dart'; +import 'package:cake_wallet/entities/wallet_contact.dart'; import 'package:cake_wallet/entities/wallet_list_order_types.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; @@ -16,6 +17,8 @@ import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/currency_for_wallet_type.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -281,8 +284,10 @@ class _ContactPageBodyState extends State with SingleTickerProv } Widget _buildCurrencyIcon(ContactBase contact) { - final image = contact.type.iconPath; - return image != null + final image = (contact is WalletContact && contact.walletType != null) + ? getCryptoCurrencyIconForWalletListItem(contact.walletType!) + : contact.type.iconPath; + return (image != null && image.isNotEmpty) ? CakeImageWidget(imageUrl: image, height: 24, width: 24) : const SizedBox(height: 24, width: 24); } @@ -373,9 +378,11 @@ class _ContactListBodyState extends State { } Widget generateContactRaw(BuildContext context, ContactRecord contact, bool isLast) { - final image = contact.type.iconPath; - final currencyIcon = image != null - ? Image.asset(image, height: 24, width: 24) + final image = contact.type == CryptoCurrency.baseEth + ? 'assets/new-ui/crypto_full_icons/base.svg' + : contact.type.iconPath; + final currencyIcon = (image != null && image.isNotEmpty) + ? CakeImageWidget(imageUrl: image, height: 24, width: 24) : const SizedBox(height: 24, width: 24); return Column( children: [ diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index 1ae7c210c..db93e4efe 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -31,26 +31,26 @@ class DesktopWalletSelectionDropDown extends StatefulWidget { } class _DesktopWalletSelectionDropDownState extends State { - final moneroIcon = Image.asset('assets/images/crypto/monero.webp', height: 24, width: 24); - final bitcoinIcon = Image.asset('assets/images/crypto/bitcoin.webp', height: 24, width: 24); + final moneroIcon = Image.asset('assets/new-ui/crypto_full_icons/monero.svg', height: 24, width: 24); + final bitcoinIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin.svg', height: 24, width: 24); final tBitcoinIcon = Image.asset('assets/images/tbtc.png', height: 24, width: 24); - final litecoinIcon = Image.asset('assets/images/crypto/litecoin.webp', height: 24, width: 24); + final litecoinIcon = Image.asset('assets/new-ui/crypto_full_icons/litecoin.svg', height: 24, width: 24); final havenIcon = Image.asset('assets/images/haven_logo.webp', height: 24, width: 24); - final ethereumIcon = Image.asset('assets/images/crypto/ethereum.webp', height: 24, width: 24); - final polygonIcon = Image.asset('assets/images/crypto/polygon.webp', height: 24, width: 24); - final bitcoinCashIcon = Image.asset('assets/images/crypto/bitcoin-cash.webp', height: 24, width: 24); - final baseIcon = Image.asset('assets/images/crypto/base_icon.webp', height: 24, width: 24); - final arbitrumIcon = Image.asset('assets/images/crypto/arbitrum.webp', height: 24, width: 24); - final bscIcon = Image.asset('assets/images/crypto/BNB.webp', height: 24, width: 24); - final nanoIcon = Image.asset('assets/images/crypto/nano.webp', height: 24, width: 24); - final bananoIcon = Image.asset('assets/images/crypto/nano.webp', height: 24, width: 24); - final solanaIcon = Image.asset('assets/images/crypto/solana.webp', height: 24, width: 24); - final tronIcon = Image.asset('assets/images/crypto/tron.webp', height: 24, width: 24); - final wowneroIcon = Image.asset('assets/images/crypto/wownero.webp', height: 24, width: 24); - final zanoIcon = Image.asset('assets/images/crypto/zano.webp', height: 24, width: 24); - final decredIcon = Image.asset('assets/images/crypto/decred.webp', height: 24, width: 24); - final dogeIcon = Image.asset('assets/images/crypto/dogecoin.webp', height: 24, width: 24); - final zcashIcon = Image.asset('assets/images/crypto/zcash.webp', height: 24, width: 24); + final ethereumIcon = Image.asset('assets/new-ui/crypto_full_icons/ethereum.svg', height: 24, width: 24); + final polygonIcon = Image.asset('assets/new-ui/crypto_full_icons/polygon.svg', height: 24, width: 24); + final bitcoinCashIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin-cash.svg', height: 24, width: 24); + final baseIcon = Image.asset('assets/new-ui/crypto_full_icons/base.svg', height: 24, width: 24); + final arbitrumIcon = Image.asset('assets/new-ui/crypto_full_icons/arbitrum.svg', height: 24, width: 24); + final bscIcon = Image.asset('assets/new-ui/crypto_full_icons/bnb.svg', height: 24, width: 24); + final nanoIcon = Image.asset('assets/new-ui/crypto_full_icons/nano.svg', height: 24, width: 24); + final bananoIcon = Image.asset('assets/new-ui/crypto_full_icons/nano.svg', height: 24, width: 24); + final solanaIcon = Image.asset('assets/new-ui/crypto_full_icons/solana.svg', height: 24, width: 24); + final tronIcon = Image.asset('assets/new-ui/crypto_full_icons/tron.svg', height: 24, width: 24); + final wowneroIcon = Image.asset('assets/new-ui/crypto_full_icons/wownero.svg', height: 24, width: 24); + final zanoIcon = Image.asset('assets/new-ui/crypto_full_icons/zano.svg', height: 24, width: 24); + final decredIcon = Image.asset('assets/new-ui/crypto_full_icons/decred.svg', height: 24, width: 24); + final dogeIcon = Image.asset('assets/new-ui/crypto_full_icons/dogecoin.svg', height: 24, width: 24); + final zcashIcon = Image.asset('assets/new-ui/crypto_full_icons/zcash.svg', height: 24, width: 24); final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24); Image _newWalletImage(BuildContext context) => Image.asset( diff --git a/lib/src/screens/dashboard/edit_token_page.dart b/lib/src/screens/dashboard/edit_token_page.dart index dca3b2fac..97e43411f 100644 --- a/lib/src/screens/dashboard/edit_token_page.dart +++ b/lib/src/screens/dashboard/edit_token_page.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/address_text_field.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -396,10 +397,9 @@ class _EditTokenPageBodyState extends State { alignment: Alignment.center, children: [ ClipOval( - child: CakeImageWidget( + child: TokenImageWidget( imageUrl: _tokenIconPathController.text, - width: 75, - height: 75, + size: 75, ), ), if (_isTokenVerified) diff --git a/lib/src/screens/dashboard/home_settings_page.dart b/lib/src/screens/dashboard/home_settings_page.dart index 767423f48..839ecbb5f 100644 --- a/lib/src/screens/dashboard/home_settings_page.dart +++ b/lib/src/screens/dashboard/home_settings_page.dart @@ -5,14 +5,11 @@ import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_toggle.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/new-ui/pages/settings_page.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/dashboard/favorite_token_modal.dart'; -import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; -import 'package:cake_wallet/src/widgets/cake_image_widget.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/src/widgets/new_list_row/new_list_section.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; @@ -186,30 +183,25 @@ class HomeSettingsPage extends BasePage { 'token': token, }); }, - leading: Container( - clipBehavior: Clip.hardEdge, - decoration: BoxDecoration(shape: BoxShape.circle), - child: CakeImageWidget( - imageUrl: token.iconPath, - height: 40, - width: 40, - errorWidget: Container( - height: 30.0, - width: 30.0, - child: Center( - child: Text( - token.title.substring(0, min(token.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.surfaceContainerHighest, + leading: TokenImageWidget( + imageUrl: token.iconPath ?? '', + size: 40, + errorWidget: Container( + height: 30.0, + width: 30.0, + child: Center( + child: Text( + token.title.substring(0, min(token.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.surfaceContainerHighest, + ), ), ), decoration: BoxDecoration( diff --git a/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart b/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart index de05bccf4..0f0d03a1a 100644 --- a/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart +++ b/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart @@ -371,7 +371,7 @@ class CryptoBalanceWidget extends StatelessWidget { child: InfoCard( title: S.of(context).synchronizing, description: S.of(context).decred_info_card_details, - image: 'assets/images/crypto/decred.webp', + image: 'assets/new-ui/crypto_full_icons/decred.svg', leftButtonTitle: S.of(context).litecoin_mweb_dismiss, rightButtonTitle: S.of(context).learn_more, leftButtonAction: () => dashboardViewModel.dismissDecredInfoCard(), diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart index 37f2e2c66..fbdb05861 100644 --- a/lib/src/screens/dashboard/widgets/menu_widget.dart +++ b/lib/src/screens/dashboard/widgets/menu_widget.dart @@ -24,25 +24,25 @@ class MenuWidgetState extends State { this.tileHeight = 60, this.fromTopEdge = 50, this.fromBottomEdge = 25, - this.moneroIcon = Image.asset('assets/images/crypto/monero.webp'), - this.bitcoinIcon = Image.asset('assets/images/crypto/bitcoin.webp'), - this.litecoinIcon = Image.asset('assets/images/crypto/litecoin.webp'), + this.moneroIcon = Image.asset('assets/new-ui/crypto_full_icons/monero.svg'), + this.bitcoinIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin.svg'), + this.litecoinIcon = Image.asset('assets/new-ui/crypto_full_icons/litecoin.svg'), this.havenIcon = Image.asset('assets/images/haven_menu.webp'), - this.ethereumIcon = Image.asset('assets/images/crypto/ethereum.webp'), - this.nanoIcon = Image.asset('assets/images/crypto/nano.webp'), - this.bananoIcon = Image.asset('assets/images/crypto/nano.webp'), - this.bitcoinCashIcon = Image.asset('assets/images/crypto/bitcoin-cash.webp'), - this.polygonIcon = Image.asset('assets/images/crypto/polygon.webp'), - this.baseIcon = Image.asset('assets/images/crypto/base_icon.webp'), - this.arbitrumIcon = Image.asset('assets/images/crypto/arbitrum.webp'), - this.bscIcon = Image.asset('assets/images/crypto/BNB.webp'), - this.solanaIcon = Image.asset('assets/images/crypto/solana.webp'), - this.tronIcon = Image.asset('assets/images/crypto/tron.webp'), - this.wowneroIcon = Image.asset('assets/images/crypto/wownero.webp'), - this.zanoIcon = Image.asset('assets/images/crypto/zano.webp'), - this.decredIcon = Image.asset('assets/images/crypto/decred.webp'), - this.dogecoinIcon = Image.asset('assets/images/crypto/dogecoin.webp'), - this.zcashIcon = Image.asset('assets/images/crypto/zcash.webp'); + this.ethereumIcon = Image.asset('assets/new-ui/crypto_full_icons/ethereum.svg'), + this.nanoIcon = Image.asset('assets/new-ui/crypto_full_icons/nano.svg'), + this.bananoIcon = Image.asset('assets/new-ui/crypto_full_icons/nano.svg'), + this.bitcoinCashIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin-cash.svg'), + this.polygonIcon = Image.asset('assets/new-ui/crypto_full_icons/polygon.svg'), + this.baseIcon = Image.asset('assets/new-ui/crypto_full_icons/base.svg'), + this.arbitrumIcon = Image.asset('assets/new-ui/crypto_full_icons/arbitrum.svg'), + this.bscIcon = Image.asset('assets/new-ui/crypto_full_icons/bnb.svg'), + this.solanaIcon = Image.asset('assets/new-ui/crypto_full_icons/solana.svg'), + this.tronIcon = Image.asset('assets/new-ui/crypto_full_icons/tron.svg'), + this.wowneroIcon = Image.asset('assets/new-ui/crypto_full_icons/wownero.svg'), + this.zanoIcon = Image.asset('assets/new-ui/crypto_full_icons/zano.svg'), + this.decredIcon = Image.asset('assets/new-ui/crypto_full_icons/decred.svg'), + this.dogecoinIcon = Image.asset('assets/new-ui/crypto_full_icons/dogecoin.svg'), + this.zcashIcon = Image.asset('assets/new-ui/crypto_full_icons/zcash.svg'); final largeScreen = 731; @@ -122,8 +122,8 @@ class MenuWidgetState extends State { } int itemCount = items.length; - moneroIcon = Image.asset('assets/images/crypto/monero.webp'); - bitcoinIcon = Image.asset('assets/images/crypto/bitcoin.webp'); + moneroIcon = Image.asset('assets/new-ui/crypto_full_icons/monero.svg'); + bitcoinIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin.svg'); return Row( mainAxisSize: MainAxisSize.max, diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index baca78e04..7e6595774 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -48,6 +48,7 @@ class ExchangeCard extends StatefulWidget { this.onPushAddressBookButton, this.onDispose, this.useSatoshis = false, + this.onTapCurrencyPicker, required this.cardInstanceName, }) : super(key: key); @@ -84,6 +85,7 @@ class ExchangeCard extends StatefulWidget { final String cardInstanceName; final Color fillColor; final bool useSatoshis; + final void Function(BuildContext context)? onTapCurrencyPicker; @override ExchangeCardState createState() => ExchangeCardState(); @@ -447,6 +449,10 @@ class ExchangeCardState extends State> { } void _presentPicker(BuildContext context) { + if (widget.onTapCurrencyPicker != null) { + widget.onTapCurrencyPicker!(context); + return; + } showPopUp( context: context, builder: (_) => CurrencyPicker( diff --git a/lib/src/screens/new_wallet/new_wallet_type_page.dart b/lib/src/screens/new_wallet/new_wallet_type_page.dart index 7bcf3edf5..55bd16803 100644 --- a/lib/src/screens/new_wallet/new_wallet_type_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_type_page.dart @@ -149,7 +149,6 @@ class WalletTypeFormState extends State { shrinkWrap: true, itemBuilder: (context, index) { final item = filteredTypes[index]; - final curr = getCryptoCurrencyForWalletListItem(item); return GestureDetector( key: ValueKey('new_wallet_type_${item.name}_button_key'), @@ -169,7 +168,7 @@ class WalletTypeFormState extends State { CakeImageWidget( height: 24, width: 24, - imageUrl: curr.iconPath, + imageUrl: getCryptoCurrencyIconForWalletListItem(item), ), const SizedBox(width: 12), Text(walletTypeToDisplayName(item)), diff --git a/lib/src/screens/nodes/node_share_page.dart b/lib/src/screens/nodes/node_share_page.dart index 1319d8426..bb96b5b0c 100644 --- a/lib/src/screens/nodes/node_share_page.dart +++ b/lib/src/screens/nodes/node_share_page.dart @@ -31,38 +31,12 @@ class NodeSharePage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, spacing: 40, children: [ - Stack(alignment: Alignment.center, children: [ - SizedBox( - width: qrSize, - height: qrSize, - child: ClipRRect( - borderRadius: BorderRadius.circular(18), - child: QrImage( - size: qrSize - padding * 2, - embeddedImagePath: "", - data: uri.toString())), - ), - SizedBox( - width: 60, - height: 60, - child: Stack( - children: [ - CakeImageWidget( - imageUrl: "assets/new-ui/settings_row_icons/nodes.svg", - width: 54, - height: 54, - ), - Align( - alignment: Alignment.bottomRight, - child: CakeImageWidget( - imageUrl: currency.iconPath, - width: 24, - height: 24, - )) - ], - ), - ), - ]), + QrImage( + size: qrSize - padding * 2, + embeddedImagePath: "assets/new-ui/node-qr-icon.svg", + badgeImageOnEmbeddedImagePath: currency.iconPath, + data: uri.toString(), + ), Padding( padding: const EdgeInsets.symmetric(horizontal: 36.0), child: Text(S.of(context).node_share_desc, diff --git a/lib/src/screens/receive/widgets/qr_image.dart b/lib/src/screens/receive/widgets/qr_image.dart index 250f70724..da856dfe9 100644 --- a/lib/src/screens/receive/widgets/qr_image.dart +++ b/lib/src/screens/receive/widgets/qr_image.dart @@ -1,7 +1,6 @@ +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; -import 'package:cw_core/utils/print_verbose.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:qr_flutter/qr_flutter.dart' as qr; class QrImage extends StatelessWidget { @@ -13,6 +12,7 @@ class QrImage extends StatelessWidget { this.version, this.errorCorrectionLevel = qr.QrErrorCorrectLevel.H, this.embeddedImagePath, + this.badgeImageOnEmbeddedImagePath, }); final double? size; @@ -22,46 +22,55 @@ class QrImage extends StatelessWidget { final int? version; final int errorCorrectionLevel; final String? embeddedImagePath; + final String? badgeImageOnEmbeddedImagePath; @override Widget build(BuildContext context) { final imagePath = embeddedImagePath ?? 'assets/images/qr-cake.png'; - final isSvg = imagePath.endsWith('.svg'); + final qrSize = size ?? 100.0; + final logoSize = qrSize * 0.30; - if (isSvg) { - final qrSize = size ?? 100.0; - final logoSize = qrSize * 0.30; + final centerImage = TokenImageWidget( + imageUrl: imagePath, + size: logoSize * 0.8, + ); - return Stack( - alignment: Alignment.center, + Widget centerImageToUse; + if (badgeImageOnEmbeddedImagePath != null) { + centerImageToUse = Stack( children: [ - qr.QrImageView( - data: data, - errorCorrectionLevel: errorCorrectionLevel, - version: version ?? qr.QrVersions.auto, - size: qrSize, - foregroundColor: foregroundColor, - backgroundColor: backgroundColor, - padding: const EdgeInsets.all(12.0), - ), - CakeImageWidget(imageUrl: - imagePath, - width: logoSize * 0.8, - height: logoSize * 0.8, + centerImage, + Positioned( + bottom: 0, + right: 0, + child: Align( + alignment: Alignment.bottomRight, + child: CakeImageWidget( + imageUrl: badgeImageOnEmbeddedImagePath!, + width: 24, + height: 24, + ), + ), ), ], ); } else { - return qr.QrImageView( - data: data, - errorCorrectionLevel: errorCorrectionLevel, - version: version ?? qr.QrVersions.auto, - size: size, - foregroundColor: foregroundColor, - backgroundColor: backgroundColor, - padding: const EdgeInsets.all(12.0), - embeddedImage: AssetImage(imagePath), - ); + centerImageToUse = centerImage; } + return Stack( + alignment: Alignment.center, + children: [ + qr.QrImageView( + data: data, + errorCorrectionLevel: errorCorrectionLevel, + version: version ?? qr.QrVersions.auto, + size: qrSize, + foregroundColor: foregroundColor, + backgroundColor: backgroundColor, + padding: const EdgeInsets.all(12.0), + ), + centerImageToUse, + ], + ); } } diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart index c10efc9d2..be46befc3 100644 --- a/lib/src/screens/settings/display_settings_page.dart +++ b/lib/src/screens/settings/display_settings_page.dart @@ -1,11 +1,11 @@ import 'package:cake_wallet/entities/bitcoin_amount_display_mode.dart'; -import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart'; import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_selector.dart'; import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_toggle.dart'; import 'package:cake_wallet/entities/sync_status_display_mode.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart'; import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_theme_choice.dart'; @@ -179,35 +179,11 @@ class DisplaySettingsPage extends StatelessWidget { keyValue: "display_settings_fiat_currency", label: S.of(context).settings_currency, options: [_displaySettingsViewModel.fiatCurrency.title], - onTap: () async { - final items = FiatCurrency.all; - - final selectedAtIndex = - items.indexOf(_displaySettingsViewModel.fiatCurrency); - - await showPopUp( - context: context, - builder: (_) => Picker( - items: items, - selectedAtIndex: selectedAtIndex, - mainAxisAlignment: MainAxisAlignment.start, - onItemSelected: (FiatCurrency currency) { - _displaySettingsViewModel.setFiatCurrency(currency); - }, - images: FiatCurrency.all - .map((e) => Image.asset("assets/images/flags/${e.countryCode}.png")) - .toList(), - hintText: S.of(context).search_currency, - isGridView: true, - matchingCriteria: (FiatCurrency currency, String searchText) { - return currency.title.toLowerCase().contains(searchText) || - currency.fullName.toLowerCase().contains(searchText); - }, - isSeparated: false, - - ), - ); - }), + onTap: () => FiatCurrencyPickerSheet.show( + context: context, + selected: _displaySettingsViewModel.fiatCurrency, + onSelected: _displaySettingsViewModel.setFiatCurrency, + )), ListItemSelector( keyValue: "display_settings_language", label: S.of(context).settings_change_language, diff --git a/lib/src/screens/ur/animated_ur_page.dart b/lib/src/screens/ur/animated_ur_page.dart index df410d4b0..06e34bfde 100644 --- a/lib/src/screens/ur/animated_ur_page.dart +++ b/lib/src/screens/ur/animated_ur_page.dart @@ -87,7 +87,7 @@ class AnimatedURPage extends BasePage { try { switch (urQrType) { case "ur:xmr-txunsigned": // ur:xmr-txsigned - final ur = await presentQRScanner(context); + final ur = await presentQRScanner(context, showManualInput: false); if (ur == null) return; final result = await monero!.commitTransactionUR(animatedURmodel.wallet, ur); @@ -96,7 +96,7 @@ class AnimatedURPage extends BasePage { } break; case "ur:xmr-output": // xmr-keyimage - final ur = await presentQRScanner(context); + final ur = await presentQRScanner(context, showManualInput: false); if (ur == null) return; final result = await monero!.importKeyImagesUR(animatedURmodel.wallet, ur); @@ -105,7 +105,7 @@ class AnimatedURPage extends BasePage { } break; case "ur:psbt": // psbt - final ur = await presentQRScanner(context); + final ur = await presentQRScanner(context, showManualInput: false); if (ur == null) return; await bitcoin! .commitPsbtUR(animatedURmodel.wallet, ur.trim().split("\n")); diff --git a/lib/src/screens/ur/widgets/urqr.dart b/lib/src/screens/ur/widgets/urqr.dart index 7649933df..c12b7c9e8 100644 --- a/lib/src/screens/ur/widgets/urqr.dart +++ b/lib/src/screens/ur/widgets/urqr.dart @@ -79,7 +79,7 @@ class _URQRState extends State { child: QrImage( data: frames[frame % frames.length], version: -1, - size: null, + size: MediaQuery.of(context).size.width * 0.7, ), ), ), diff --git a/lib/src/widgets/cake_image_widget.dart b/lib/src/widgets/cake_image_widget.dart index fcfbe64ca..f714bcd0c 100644 --- a/lib/src/widgets/cake_image_widget.dart +++ b/lib/src/widgets/cake_image_widget.dart @@ -16,6 +16,7 @@ class CakeImageWidget extends StatelessWidget { this.borderRadius = 24.0, this.alignment, this.allowDrawingOutsideViewBox, + this.filterQuality, }); final String? imageUrl; @@ -29,6 +30,7 @@ class CakeImageWidget extends StatelessWidget { final AlignmentGeometry? alignment; final bool? allowDrawingOutsideViewBox; final double borderRadius; + final FilterQuality? filterQuality; @override Widget build(BuildContext context) { @@ -69,6 +71,7 @@ class CakeImageWidget extends StatelessWidget { width: width, fit: fit, color: color, + filterQuality: filterQuality ?? FilterQuality.medium, errorBuilder: (_, __, ___) => _buildErrorWidget(context), ); } @@ -93,6 +96,7 @@ class CakeImageWidget extends StatelessWidget { width: width, fit: fit ?? BoxFit.cover, color: color, + filterQuality: filterQuality ?? FilterQuality.medium, loadingBuilder: (_, Widget child, ImageChunkEvent? progress) { if (progress == null) return child; return loadingWidget ?? const Center(child: CircularProgressIndicator()); diff --git a/lib/src/widgets/new_list_row/list_item_regular_row_widget.dart b/lib/src/widgets/new_list_row/list_item_regular_row_widget.dart index d947ef03a..962cb87d1 100644 --- a/lib/src/widgets/new_list_row/list_item_regular_row_widget.dart +++ b/lib/src/widgets/new_list_row/list_item_regular_row_widget.dart @@ -26,6 +26,7 @@ class ListItemRegularRowWidget extends StatelessWidget { this.copyableText, this.leadingIconErrorWidget, this.leadingIconSize, + this.iconColor }); final String keyValue; @@ -46,6 +47,7 @@ class ListItemRegularRowWidget extends StatelessWidget { final String? copyableText; final Widget? leadingIconErrorWidget; final double? leadingIconSize; + final Color? iconColor; @override Widget build(BuildContext context) { @@ -85,6 +87,9 @@ class ListItemRegularRowWidget extends StatelessWidget { width: leadingIconSize ?? 24, height: leadingIconSize ?? 24, errorWidget: leadingIconErrorWidget, + colorFilter: iconColor == null + ? null + : ColorFilter.mode(iconColor!, BlendMode.srcIn), )), Flexible( child: Column( diff --git a/lib/src/widgets/new_list_row/new_list_section.dart b/lib/src/widgets/new_list_row/new_list_section.dart index d6d46aff2..edc0b4eba 100644 --- a/lib/src/widgets/new_list_row/new_list_section.dart +++ b/lib/src/widgets/new_list_row/new_list_section.dart @@ -109,6 +109,7 @@ class NewListSections extends StatelessWidget { bottomWidget: item.bottomWidget, leadingIconErrorWidget: item.leadingIconErrorWidget, leadingIconSize: item.leadingIconSize, + iconColor: item.iconColor, ); } diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart index 9b9e534a7..4934010c2 100644 --- a/lib/src/widgets/picker.dart +++ b/lib/src/widgets/picker.dart @@ -3,7 +3,7 @@ import 'dart:math'; import 'package:cake_wallet/entities/seed_type.dart'; -import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart'; import 'package:cake_wallet/src/widgets/search_bar_widget.dart'; import 'package:cake_wallet/themes/core/theme_extension.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -498,10 +498,9 @@ class _PickerState extends State> { Widget? _getItemIcon(Item item) { if (item is Currency) { if (item.iconPath != null) { - return CakeImageWidget( + return TokenImageWidget( imageUrl: item.iconPath!, - height: 20.0, - width: 20.0, + size: 20.0, ); } else { return Container( diff --git a/lib/src/widgets/setting_actions.dart b/lib/src/widgets/setting_actions.dart index f42a4da96..8ca375af0 100644 --- a/lib/src/widgets/setting_actions.dart +++ b/lib/src/widgets/setting_actions.dart @@ -43,7 +43,7 @@ class SettingActions { static SettingActions exportOutputsAction = SettingActions._( key: ValueKey('dashboard_page_menu_widget_export_outputs_settings_button_key'), name: (context) => S.of(context).export_outputs, - image: 'assets/images/crypto/monero.webp', + image: 'assets/new-ui/crypto_full_icons/monero.svg', onTap: (BuildContext context) { Navigator.of(context) .pushNamed(Routes.urqrAnimatedPage, arguments: {'export-outputs': 'export-outputs'}); diff --git a/lib/tron/cw_tron.dart b/lib/tron/cw_tron.dart index 0b6dd8cba..42f22db31 100644 --- a/lib/tron/cw_tron.dart +++ b/lib/tron/cw_tron.dart @@ -153,4 +153,32 @@ class CWTron extends Tron { return tronWallet.tronTokenCurrencies .any((element) => element.contractAddress == contractAddress); } + + @override + TransactionInfo getTransactionInfo({ + required String id, + required BigInt tronAmount, + int? txFee, + String? tokenSymbol, + required TransactionDirection direction, + required DateTime blockTime, + String? to, + String? from, + required bool isPending, + }) => + TronTransactionInfo(id: id, + tronAmount: tronAmount, + tokenSymbol: tokenSymbol ?? "TRX", + txFee: txFee, + direction: direction, + blockTime: blockTime, + to: to, + from: from, + isPending: isPending); + + @override + String getPendingTransactionAmount(PendingTransaction tx) => (tx as PendingTronTransaction).amount; + + @override + String getPendingTransactionFee(PendingTransaction tx) => (tx as PendingTronTransaction).amount; } diff --git a/lib/view_model/buy/buy_sell_view_model.dart b/lib/view_model/buy/buy_sell_view_model.dart index d7a4ad326..a299aebac 100644 --- a/lib/view_model/buy/buy_sell_view_model.dart +++ b/lib/view_model/buy/buy_sell_view_model.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/buy/buy_quote.dart'; import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/buy/payment_method.dart'; import 'package:cake_wallet/buy/sell_buy_states.dart'; +import 'package:cake_wallet/core/amount_parsing_proxy.dart'; import 'package:cake_wallet/core/selectable_option.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; @@ -87,6 +88,8 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S final AppStore _appStore; + AmountParsingProxy get amountParsingProxy => _appStore.amountParsingProxy; + Quote? bestRateQuote; Quote? selectedQuote; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 8b249c8cf..d97d119a4 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -326,6 +326,10 @@ abstract class DashboardViewModelBase with Store { appStore.wallet!.transactionHistory.transactions.values.last.confirmations + 1; } catch (_) {} + } else { + confirmations = appStore.wallet!.transactionHistory.transactions.values + .map((item) => item.isPending) + .fold(0, (val, pending) => pending ? val + 1 : val); } return length * confirmations; }, _transactionDisposerCallback, delay: 300); @@ -490,16 +494,23 @@ abstract class DashboardViewModelBase with Store { } // printV("Transaction disposer callback (relevantTxs: ${relevantTxs.length} current: ${transactions.length})"); + // TODO(malik) update this in a saner way during the vm refactor String _txIdentityString(String txHash, TransactionDirection direction) => "${txHash}_$direction"; - String _txIdentityStringConfirmations(String txHash, TransactionDirection direction, int confirmations) => "${txHash}_${direction}_$confirmations"; - + String _txIdentityStringConfirmations( + String txHash, TransactionDirection direction, int confirmations, bool isPending) => + "${txHash}_${direction}_${confirmations}_$isPending"; final existingKeys = transactions - .map((item) => _txIdentityStringConfirmations(item.transaction.txHash, item.transaction.direction, item.transaction.confirmations)) + .map((item) => _txIdentityStringConfirmations( + item.transaction.txHash, + item.transaction.direction, + item.transaction.confirmations, + item.transaction.isPending)) .toSet(); final newTransactions = relevantTxs - .where((tx) => !existingKeys.contains(_txIdentityStringConfirmations(tx.txHash, tx.direction, tx.confirmations))) + .where((tx) => !existingKeys.contains(_txIdentityStringConfirmations( + tx.txHash, tx.direction, tx.confirmations, tx.isPending))) .map((tx) => TransactionListItem( transaction: tx, balanceViewModel: balanceViewModel, @@ -1291,6 +1302,10 @@ abstract class DashboardViewModelBase with Store { appStore.wallet!.transactionHistory.transactions.values.last.confirmations + 1; } catch (_) {} + } else { + confirmations = appStore.wallet!.transactionHistory.transactions.values + .map((item) => item.isPending) + .fold(0, (val, pending) => pending ? val + 1 : val); } return length * confirmations; }, _transactionDisposerCallback, delay: 300); diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index 1fb3f3043..4cbd27633 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -218,7 +218,7 @@ class TransactionListItem extends ActionListItem with Keyable { case WalletType.base: case WalletType.arbitrum: case WalletType.bsc: - final asset = evm!.assetOfTransaction(balanceViewModel.wallet, transaction); + final asset = assetOfTransaction; final price = balanceViewModel.fiatConversionStore.prices[asset]; amount = calculateFiatAmountRaw( cryptoAmount: evm!.formatterEVMAmountToDouble(transaction: transaction), diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 108c78ff3..03d0ef4db 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -38,11 +38,9 @@ import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; +import 'package:cake_wallet/new-ui/widgets/currency_picker/fiat_currency_picker_sheet.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/utils/exchange_provider_logger.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cw_core/currency.dart'; import "package:cw_core/wallet_info.dart"; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/dashboard/trades_store.dart'; @@ -270,17 +268,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with } void showFiatCurrencyPicker(BuildContext context) { - showPopUp( + FiatCurrencyPickerSheet.show( context: context, - builder: (_) => CurrencyPicker( - key: ValueKey('send_page_currency_picker_dialog_button_key'), - selectedAtIndex: FiatCurrency.all.indexOf(fiat), - items: FiatCurrency.all, - hintText: S.of(context).search_currency, - onItemSelected: (Currency cur) async { - _settingsStore.fiatCurrency = (cur as FiatCurrency); - }, - ), + selected: fiat, + onSelected: (cur) => _settingsStore.fiatCurrency = cur, ); } @@ -1034,6 +1025,39 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @action Future createTrade() async { + final depositAmountValue = + double.tryParse(_depositAmount.replaceAll(',', '.')) ?? 0.0; + + final receiveAmountValue = + double.tryParse(_receiveAmount.replaceAll(',', '.')) ?? 0.0; + + if (depositAmountValue <= 0 || receiveAmountValue <= 0) { + ExchangeProviderLogger.logError( + provider: forcedProvider?.description ?? bestRateProvider?.description, + function: 'createTrade', + error: 'Invalid swap amount: deposit=$_depositAmount receive=$_receiveAmount', + requestData: { + 'from': depositCurrency.title, + 'to': receiveCurrency.title, + 'fromAmount': _depositAmount, + 'toAmount': _receiveAmount, + 'isFixedRateMode': isFixedRateMode, + 'forcedProvider': forcedProvider?.title, + 'bestRateProvider': bestRateProvider?.title, + }, + ); + + final invalidAmountError = depositAmountValue <= 0 + ? '$depositAmountValue is not a valid amount for depositAmount' + : '$receiveAmountValue is not a valid amount for receiveAmount'; + + tradeState = TradeIsCreatedFailure( + title: S.current.trade_not_created, + error: invalidAmountError, + ); + return; + } + if (isSendAllEnabled) { await calculateDepositAllAmount(); final amount = double.tryParse(_depositAmount); diff --git a/lib/view_model/link_view_model.dart b/lib/view_model/link_view_model.dart index 3320348e7..a9e742733 100644 --- a/lib/view_model/link_view_model.dart +++ b/lib/view_model/link_view_model.dart @@ -34,7 +34,7 @@ class LinkViewModel { String? getRouteToGo() { if (isWalletConnectLink) { if (!isWalletConnectCompatibleChain(appStore.wallet!.type)) { - _errorToast(S.current.switchToEVMCompatibleWallet); + _errorToast(S.current.switchToWCCompatibleWallet(walletConnectCompatibleChainsLabel())); return null; } return Routes.walletConnectConnectionsListing; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index a51423ec5..6c001c5b6 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/core/open_crypto_pay/exceptions.dart'; import 'package:cake_wallet/core/open_crypto_pay/models.dart'; import 'package:cake_wallet/core/open_crypto_pay/open_cryptopay_service.dart'; +import 'package:cake_wallet/core/utilities.dart'; import 'package:cake_wallet/core/validator.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/decred/decred.dart'; @@ -59,6 +60,7 @@ import 'package:cw_core/exceptions.dart'; import 'package:cw_core/lnurl.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coin_type.dart'; @@ -488,6 +490,25 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor bool get shouldDisplayTOTP2FAForSendsToInternalWallet => _settingsStore.shouldRequireTOTP2FAForSendsToInternalWallets; + @computed + TransactionInfo? get transactionInfo { + if(isEVMCompatibleChain(walletType)) { + return wallet.transactionHistory.transactions[pendingTransaction?.evmTxHashFromRawHex]; + } + if (walletType == WalletType.monero) { + // monero tx history keys are in format txhash_amount_accountindex_addressindex + return wallet.transactionHistory.transactions[wallet.transactionHistory.transactions.keys + .firstWhereOrNull((item) => item.split("_").first == pendingTransaction?.id)]; + } + if (walletType == WalletType.zcash) { + // zcash has a txHash getter, but the pendingTransaction id contains quotation marks for whatever reason? + final txIdNoQuotes = pendingTransaction?.id.replaceAll("\"", ""); + return wallet.transactionHistory.transactions.values + .firstWhereOrNull((item) => item.txHash == txIdNoQuotes); + } + return wallet.transactionHistory.transactions[pendingTransaction?.id]; + } + //* Still open to further optimize these checks //* It works but can be made better @action @@ -1078,6 +1099,48 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor }); } + // FIXME(malik) ideally, this should be done wallet-side. + // it is required because evm, solana and tron don't actually save the transaction info when you send something. + // instead, they rely on the tx to eventually get fetched at sync time, which can take a while + if(isEVMWallet) { + wallet.transactionHistory.addOne(evm!.getTransactionInfo( + id: pendingTransaction!.evmTxHashFromRawHex!, + height: 0, + // FIXME(malik) this is even more critical given all the issues we had with decimal point parsing. with money it'll be easy + ethAmount: selectedCryptoCurrency.parseAmount(outputs.first.cryptoAmount), + ethFee: CryptoCurrency.eth.parseAmount(pendingTransaction!.feeFormattedValue), + tokenSymbol: selectedCryptoCurrency.title, + direction: TransactionDirection.outgoing, + isPending: true, + date: DateTime.now(), + confirmations: 0, + chainId: wallet.chainId ?? 0)); + } + + if(walletType == WalletType.solana) { + wallet.transactionHistory.addOne(solana!.getTransactionInfo( + id: pendingTransaction!.id, + blockTime: DateTime.now(), + tokenSymbol: selectedCryptoCurrency.title, + to: "", + from: "", + direction: TransactionDirection.outgoing, + solAmount: solana!.getPendingTransactionAmount(pendingTransaction!), + isPending: true, + txFee: solana!.getPendingTransactionFee(pendingTransaction!))); + } + + if (walletType == WalletType.tron) { + wallet.transactionHistory.addOne(tron!.getTransactionInfo( + id: pendingTransaction!.id, + blockTime: DateTime.now(), + tokenSymbol: selectedCryptoCurrency.title, + direction: TransactionDirection.outgoing, + tronAmount: selectedCryptoCurrency.parseAmount(outputs.first.cryptoAmount), + isPending: true, + txFee: CryptoCurrency.trx.parseAmount(outputs.first.estimatedFee).toInt())); + } + if (pendingTransaction!.id.isNotEmpty) { _addTransactionDescription(); } diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 1032ac90a..6a38a45bb 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -127,6 +127,7 @@ class TxDetailRowDefinition { .firstOrNull ?? ""; case WalletType.tron: + if(vm.transactionInfo.to != null) ret = tron!.getTronBase58Address(vm.transactionInfo.to!, vm.wallet); default: break; @@ -315,6 +316,7 @@ abstract class TransactionDetailsViewModelBase with Store { TransactionPriority? transactionPriority; CryptoCurrency get transactionAsset { + if (isEVMCompatibleChain(wallet.type)) { return evm!.assetOfTransaction(wallet, transactionInfo); } diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index 85293fd5e..89c5374f7 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -2,6 +2,7 @@ import 'dart:core'; import 'dart:developer' as dev; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/core/amount_parsing_proxy.dart'; import 'package:cake_wallet/core/fiat_conversion_service.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/decred/decred.dart'; @@ -167,6 +168,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo bool get hasPayjoin => wallet.type == WalletType.bitcoin && !isLightning && !isSilentPayments && uri.toString().contains("payjo.in"); + AmountParsingProxy get amountParsingProxy => _appStore.amountParsingProxy; + @computed FiatCurrency get fiatCurrency => _appStore.settingsStore.fiatCurrency; @@ -478,7 +481,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo ]; case 137: return [ - 'assets/images/crypto/polygon.webp', + 'assets/new-ui/crypto_full_icons/polygon.svg', 'assets/images/eth_pol_icon.svg', 'assets/images/usdc_icon.svg', 'assets/images/usdt_wallet_icon.svg', @@ -492,20 +495,20 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo ]; case 42161: return [ - 'assets/images/crypto/arbitrum.webp', + 'assets/new-ui/crypto_full_icons/arbitrum.svg', 'assets/images/usdc_icon.svg', 'assets/images/more_tokens.svg', ]; case 56: return [ - 'assets/images/crypto/BNB.webp', + 'assets/new-ui/crypto_full_icons/bnb.svg', 'assets/images/usdc_icon.svg', 'assets/images/usdt_wallet_icon.svg', 'assets/images/more_tokens.svg', ]; default: return [ - 'assets/images/crypto/ethereum.webp', + 'assets/new-ui/crypto_full_icons/ethereum.svg', 'assets/images/usdc_icon.svg', 'assets/images/usdt_wallet_icon.svg', ]; diff --git a/res/pictures/add_note.svg b/res/pictures/add_note.svg new file mode 100644 index 000000000..99fd2b2b8 --- /dev/null +++ b/res/pictures/add_note.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/pictures/birthday_cake.svg b/res/pictures/birthday_cake.svg new file mode 100644 index 000000000..0c11098b5 --- /dev/null +++ b/res/pictures/birthday_cake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/pictures/camera_flash.svg b/res/pictures/camera_flash.svg new file mode 100644 index 000000000..103497aef --- /dev/null +++ b/res/pictures/camera_flash.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/pictures/camera_flip.svg b/res/pictures/camera_flip.svg new file mode 100644 index 000000000..b44439a24 --- /dev/null +++ b/res/pictures/camera_flip.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/res/pictures/external_link.svg b/res/pictures/external_link.svg new file mode 100644 index 000000000..fe8cbf68b --- /dev/null +++ b/res/pictures/external_link.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/res/pictures/filter_options.svg b/res/pictures/filter_options.svg new file mode 100644 index 000000000..efb4abd04 --- /dev/null +++ b/res/pictures/filter_options.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/pictures/node-qr-icon.svg b/res/pictures/node-qr-icon.svg new file mode 100644 index 000000000..11e75881b --- /dev/null +++ b/res/pictures/node-qr-icon.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/res/pictures/node_minimal.svg b/res/pictures/node_minimal.svg new file mode 100644 index 000000000..90d124f6a --- /dev/null +++ b/res/pictures/node_minimal.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/pictures/ocp_min.svg b/res/pictures/ocp_min.svg new file mode 100644 index 000000000..bdb22cf3f --- /dev/null +++ b/res/pictures/ocp_min.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/res/pictures/payment_invoices.svg b/res/pictures/payment_invoices.svg new file mode 100644 index 000000000..f2ea8f0d3 --- /dev/null +++ b/res/pictures/payment_invoices.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/pictures/save_contact.svg b/res/pictures/save_contact.svg new file mode 100644 index 000000000..b474ef5b3 --- /dev/null +++ b/res/pictures/save_contact.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/pictures/scan_service.svg b/res/pictures/scan_service.svg new file mode 100644 index 000000000..883ffd936 --- /dev/null +++ b/res/pictures/scan_service.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/res/pictures/tx_export.svg b/res/pictures/tx_export.svg new file mode 100644 index 000000000..161ad56ef --- /dev/null +++ b/res/pictures/tx_export.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/pictures/wc_min.svg b/res/pictures/wc_min.svg new file mode 100644 index 000000000..9661aae64 --- /dev/null +++ b/res/pictures/wc_min.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index e2ed0035b..ff77d35fa 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "جارٍ إنشاء محفظة جديدة", "creating_new_wallet_error": "خطأ: ${description}", "creation_date": "تاريخ الإنشاء", + "csv_nothing_to_export": "Nothing to export", "current_swap": "المبادلة الحالية", "current_wallet": "المحفظة الحالية", "custom": "مخصص", @@ -450,14 +451,12 @@ "expires": "ينتهي", "expiresOn": "تنتهي في", "expiry_and_validity": "تاريخ الانتهاء والصلاحية", - "csv_nothing_to_export": "Nothing to export", "export_backup": "تصدير النسخة الاحتياطية", "export_csv": "Export CSV", "export_lightning_logs": "تصدير سجلات Lightning", "export_logs": "تصدير السجلات", "export_outputs": "تصدير المخرجات", "export_payjoin_logs": "تصدير سجلات Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "تمديد الجلسة", "external": "خارجي", "external_wallet": "محفظة خارجية", @@ -494,6 +493,7 @@ "gas_price": "سعر الغاز", "general": "عام", "generate_name": "توليد اسم", + "generating_csv": "Generating CSV...", "generating_gift_card": "جارٍ إنشاء بطاقة هدية", "generating_transaction": "جارٍ إنشاء المعاملة", "get_a": "احصل على ", @@ -736,6 +736,22 @@ "payments": "المدفوعات", "pending": " (معلّق)", "percentageOf": "من ${amount}", + "picker_chip_all": "الجميع", + "picker_no_matches": "لا توجد مباريات", + "picker_section_all_assets": "جميع الأصول (من الألف إلى الياء)", + "picker_section_all_currencies": "جميع العملات", + "picker_section_crypto": "تشفير", + "picker_section_cryptocurrencies": "العملات المشفرة", + "picker_section_gas_token": "رمز الغاز", + "picker_section_more_cryptocurrencies": "المزيد من العملات المشفرة", + "picker_section_popular": "شائع", + "picker_section_recents": "الأخيرة", + "picker_section_selected": "مختارة", + "picker_section_stablecoins": "العملات المستقرة", + "picker_section_tokenized_stocks": "الأسهم المُرمزة (xStocks)", + "picker_section_tokens_standard": "الرموز المميزة (${standard})", + "picker_see_all": "شاهد الكل", + "picker_show_less": "عرض أقل", "pin_at_top": "تثبيت ${token} في الأعلى", "pin_is_incorrect": "رمز PIN غير صحيح", "pin_number": "رقم PIN", @@ -926,12 +942,16 @@ "select_a_wallet": "اختر محفظة", "select_address_to_copy": "حدد العنوان لنسخه", "select_all": "تحديد الكل", + "select_asset": "حدد الأصول", "select_backup_file": "حدد ملف النسخ الاحتياطي", "select_buy_provider_notice": "حدّد مزوّد الشراء أعلاه. يمكنك تخطّي هذه الشاشة عبر تعيين مزوّد الشراء الافتراضي في إعدادات التطبيق.", "select_destination": "يرجى تحديد وجهة ملف النسخ الاحتياطي.", + "select_fiat_currency_title": "حدد العملة", "select_hw_account_below": "يرجى تحديد الحساب المراد استعادته أدناه:", "select_manufacturer_title": "اختر الشركة المصنِّعة", "select_network": "اختر الشبكة", + "select_network_subtitle": "هذا الأصل موجود في شبكات متعددة. حدد الشخص الذي تريد استخدامه", + "select_network_title": "حدد الشبكة", "select_other_wallet": "اختر محفظة أخرى", "select_receiver": "حدد المستلم", "select_sell_provider_notice": "اختر مزوّد البيع أعلاه. يمكنك تخطّي هذه الشاشة بتعيين مزوّد البيع الافتراضي في إعدادات التطبيق.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "اسحب للإرسال", "switch_wallet": "تبديل المحفظة", "switchToETHWallet": "يرجى التبديل إلى محفظة Ethereum والمحاولة مرة أخرى", - "switchToEVMCompatibleWallet": "يرجى التبديل إلى محفظة متوافقة مع EVM ثم المحاولة مرة أخرى (Ethereum، Polygon)", + "switchToWCCompatibleWallet": "يرجى التبديل إلى محفظة متوافقة مع WalletConnect والمحاولة مرة أخرى (${chains}).", "symbol": "الرمز", "sync_all_wallets": "مزامنة جميع المحافظ", "sync_attempting": "جارٍ محاولة المزامنة", @@ -1395,4 +1415,4 @@ "zcash_card_missing_funds": "هل أموالك مفقودة؟", "zcash_card_scan": "مسح", "zcash_card_warning": "لا تُغلق التطبيق حتى يكتمل الإجراء، لأنك إن فعلت ذلك فستحتاج هذه العملية إلى البدء من جديد من البداية." -} +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index a961754b2..ccf942882 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Създаване на нов портфейл", "creating_new_wallet_error": "Грешка: ${description}", "creation_date": "Дата на създаване", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Текущ суап", "current_wallet": "Текущ портфейл", "custom": "По избор", @@ -450,14 +451,12 @@ "expires": "Изтича", "expiresOn": "Изтича на", "expiry_and_validity": "Срок на валидност и валидност", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Експортиране на резервно копие", "export_csv": "Export CSV", "export_lightning_logs": "Експортиране на Lightning логове", "export_logs": "Експортиране на логове", "export_outputs": "Експортиране на изходи", "export_payjoin_logs": "Експортиране на Payjoin логове", - "generating_csv": "Generating CSV...", "extend_session": "Удължи сесията", "external": "Външен", "external_wallet": "Външен портфейл", @@ -494,6 +493,7 @@ "gas_price": "Цена на gas", "general": "Общи", "generate_name": "Генериране на име", + "generating_csv": "Generating CSV...", "generating_gift_card": "Генериране на подаръчна карта", "generating_transaction": "Генериране на транзакция", "get_a": "Вземете ", @@ -736,6 +736,22 @@ "payments": "Плащания", "pending": " (в изчакване)", "percentageOf": "от ${amount}", + "picker_chip_all": "Всички", + "picker_no_matches": "Няма съвпадения", + "picker_section_all_assets": "Всички активи (A-Z)", + "picker_section_all_currencies": "Всички валути", + "picker_section_crypto": "Крипто", + "picker_section_cryptocurrencies": "Криптовалути", + "picker_section_gas_token": "Газов жетон", + "picker_section_more_cryptocurrencies": "Още криптовалути", + "picker_section_popular": "Популярни", + "picker_section_recents": "Скорошни", + "picker_section_selected": "Избрано", + "picker_section_stablecoins": "Стабилни монети", + "picker_section_tokenized_stocks": "Токенизирани акции (xStocks)", + "picker_section_tokens_standard": "Токени (${standard})", + "picker_see_all": "Вижте всички", + "picker_show_less": "Покажи по-малко", "pin_at_top": "Закачи ${token} най-отгоре", "pin_is_incorrect": "PIN кодът е неправилен", "pin_number": "PIN номер", @@ -926,12 +942,16 @@ "select_a_wallet": "Изберете портфейл", "select_address_to_copy": "Изберете адрес за копиране", "select_all": "Избери всички", + "select_asset": "Изберете Актив", "select_backup_file": "Изберете файл с резервно копие", "select_buy_provider_notice": "Изберете доставчик за покупка по‑горе. Можете да пропуснете този екран, като зададете доставчик за покупка по подразбиране в настройките на приложението.", "select_destination": "Моля, изберете местоположение за файла с резервно копие.", + "select_fiat_currency_title": "Изберете Валута", "select_hw_account_below": "Моля, изберете кой акаунт да възстановите по-долу:", "select_manufacturer_title": "Изберете производител", "select_network": "Изберете мрежа", + "select_network_subtitle": "Този актив присъства в множество мрежи. Изберете този, който искате да използвате", + "select_network_title": "Изберете Мрежа", "select_other_wallet": "Изберете друг портфейл", "select_receiver": "Изберете получател", "select_sell_provider_notice": "Изберете доставчик за продажба по-горе. Можете да пропуснете този екран, като зададете доставчик за продажба по подразбиране в настройките на приложението.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "Плъзнете, за да изпратите", "switch_wallet": "Превключване на портфейл", "switchToETHWallet": "Моля, превключете към портфейл за Ethereum и опитайте отново", - "switchToEVMCompatibleWallet": "Моля, превключете към EVM‑съвместим портфейл и опитайте отново (Ethereum, Polygon).", + "switchToWCCompatibleWallet": "Моля, превключете към портфейл, съвместим с WalletConnect, и опитайте отново (${chains}).", "symbol": "Символ", "sync_all_wallets": "Синхронизиране на всички портфейли", "sync_attempting": "Опит за синхронизиране", @@ -1395,4 +1415,4 @@ "zcash_card_missing_funds": "Липсват средства?", "zcash_card_scan": "Сканирай", "zcash_card_warning": "Не затваряйте приложението, докато процедурата не приключи. Ако го направите, процесът ще трябва да започне отначало." -} +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 269dbbdc3..2df5e0233 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Vytváření nové peněženky", "creating_new_wallet_error": "Chyba: ${description}", "creation_date": "Datum vytvoření", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Aktuální swap", "current_wallet": "Aktuální peněženka", "custom": "Vlastní", @@ -450,14 +451,12 @@ "expires": "Vyprší", "expiresOn": "Vyprší dne", "expiry_and_validity": "Vypršení platnosti", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Exportovat zálohu", "export_csv": "Export CSV", "export_lightning_logs": "Exportovat protokoly Lightning", "export_logs": "Exportovat protokoly", "export_outputs": "Exportovat výstupy", "export_payjoin_logs": "Exportovat protokoly Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Prodloužit relaci", "external": "Externí", "external_wallet": "Externí peněženka", @@ -494,6 +493,7 @@ "gas_price": "Cena gasu", "general": "Obecné", "generate_name": "Vygenerovat jméno", + "generating_csv": "Generating CSV...", "generating_gift_card": "Generuji dárkovou kartu", "generating_transaction": "Generování transakce", "get_a": "Získejte ", @@ -736,6 +736,22 @@ "payments": "Platby", "pending": " (čekající)", "percentageOf": "z ${amount}", + "picker_chip_all": "Vše", + "picker_no_matches": "Žádné zápasy", + "picker_section_all_assets": "Všechna aktiva (A–Z)", + "picker_section_all_currencies": "Všechny měny", + "picker_section_crypto": "Krypto", + "picker_section_cryptocurrencies": "Kryptoměny", + "picker_section_gas_token": "Token na plyn", + "picker_section_more_cryptocurrencies": "Více kryptoměn", + "picker_section_popular": "Populární", + "picker_section_recents": "Nedávné", + "picker_section_selected": "Vybraný", + "picker_section_stablecoins": "Stablecoiny", + "picker_section_tokenized_stocks": "Tokenizované akcie (xStocks)", + "picker_section_tokens_standard": "Tokeny (${standard})", + "picker_see_all": "Zobrazit vše", + "picker_show_less": "Ukázat méně", "pin_at_top": "Připnout ${token} nahoru", "pin_is_incorrect": "PIN je nesprávný", "pin_number": "PIN", @@ -926,12 +942,16 @@ "select_a_wallet": "Vyberte peněženku", "select_address_to_copy": "Vyberte adresu ke zkopírování", "select_all": "Vybrat vše", + "select_asset": "Vyberte položku Dílo", "select_backup_file": "Vybrat záložní soubor", "select_buy_provider_notice": "Vyberte výše poskytovatele pro nákup. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele pro nákup v nastavení aplikace.", "select_destination": "Vyberte prosím umístění pro soubor zálohy.", + "select_fiat_currency_title": "Vyberte možnost Měna", "select_hw_account_below": "Vyberte prosím níže účet, který chcete obnovit:", "select_manufacturer_title": "Vyberte výrobce", "select_network": "Vyberte síť", + "select_network_subtitle": "Toto aktivum je přítomno ve více sítích. Vyberte ten, který chcete použít", + "select_network_title": "Vyberte Síť", "select_other_wallet": "Vyberte jinou peněženku", "select_receiver": "Vyberte příjemce", "select_sell_provider_notice": "Vyberte výše poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "Přejeďte pro odeslání", "switch_wallet": "Přepnout peněženku", "switchToETHWallet": "Přepněte na peněženku Ethereum a zkuste to znovu", - "switchToEVMCompatibleWallet": "Přepněte prosím na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Přepněte prosím na peněženku kompatibilní s WalletConnect a zkuste to znovu (${chains}).", "symbol": "Symbol", "sync_all_wallets": "Synchronizovat všechny peněženky", "sync_attempting": "Probíhá synchronizace", @@ -1395,4 +1415,4 @@ "zcash_card_missing_funds": "Chybějící prostředky?", "zcash_card_scan": "Skenovat", "zcash_card_warning": "Nezavírejte aplikaci, dokud se postup nedokončí. Pokud tak učiníte, bude nutné tento proces spustit znovu od začátku." -} +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 4f00cf59a..ab74cb166 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Neues Wallet wird erstellt", "creating_new_wallet_error": "Fehler: ${description}", "creation_date": "Erstellungsdatum", + "csv_nothing_to_export": "Nichts zum Exportieren", "current_swap": "Aktueller Swap", "current_wallet": "Aktuelle Wallet", "custom": "Benutzerdefiniert", @@ -362,8 +363,8 @@ "donation": "Spende", "donation_link_details": "Details zum Spendenlink", "done": "Fertig", - "duress_pin_description": "Dadurch wird eine Notfall-PIN eingerichtet, eine erweiterte Funktion, die von den meisten Nutzern nicht verwendet werden sollte. Diese PIN sollte nur verwendet werden, wenn Sie in Gefahr sind. Nachdem Sie diese PIN verwendet haben, werden alle Ihre Wallets gelöscht. Stellen Sie daher bitte sicher, dass alle Ihre Seeds gesichert sind, bevor Sie sie verwenden.", "duress_PIN": "Notfall-PIN", + "duress_pin_description": "Dadurch wird eine Notfall-PIN eingerichtet, eine erweiterte Funktion, die von den meisten Nutzern nicht verwendet werden sollte. Diese PIN sollte nur verwendet werden, wenn Sie in Gefahr sind. Nachdem Sie diese PIN verwendet haben, werden alle Ihre Wallets gelöscht. Stellen Sie daher bitte sicher, dass alle Ihre Seeds gesichert sind, bevor Sie sie verwenden.", "duress_PIN_set_up_successfully": "Die Notfall-PIN wurde erfolgreich eingerichtet", "e_sign_consent": "Einwilligung zur E-Signatur", "edit": "Bearbeiten", @@ -450,14 +451,12 @@ "expires": "Läuft ab", "expiresOn": "Läuft ab am", "expiry_and_validity": "Ablauf und Gültigkeit", - "csv_nothing_to_export": "Nichts zum Exportieren", "export_backup": "Backup exportieren", "export_csv": "Export CSV", "export_lightning_logs": "Lightning-Logs exportieren", "export_logs": "Protokolle exportieren", "export_outputs": "Outputs exportieren", "export_payjoin_logs": "Payjoin-Logs exportieren", - "generating_csv": "CSV wird erstellt...", "extend_session": "Sitzung verlängern", "external": "Extern", "external_wallet": "Externe Wallet", @@ -494,6 +493,7 @@ "gas_price": "Gaspreis", "general": "Allgemein", "generate_name": "Namen generieren", + "generating_csv": "CSV wird erstellt...", "generating_gift_card": "Geschenkkarte wird generiert", "generating_transaction": "Transaktion wird erstellt", "get_a": "Holen Sie sich", @@ -736,6 +736,22 @@ "payments": "Zahlungen", "pending": " (ausstehend)", "percentageOf": "von ${amount}", + "picker_chip_all": "Alle", + "picker_no_matches": "Keine Übereinstimmungen", + "picker_section_all_assets": "Alle Assets (A-Z)", + "picker_section_all_currencies": "Alle Währungen", + "picker_section_crypto": "Krypto", + "picker_section_cryptocurrencies": "Kryptowährungen", + "picker_section_gas_token": "Gas-Token", + "picker_section_more_cryptocurrencies": "Weitere Kryptowährungen", + "picker_section_popular": "Beliebt", + "picker_section_recents": "Neueste", + "picker_section_selected": "Ausgewählt", + "picker_section_stablecoins": "Stablecoins", + "picker_section_tokenized_stocks": "Tokenisierte Aktien (xStocks)", + "picker_section_tokens_standard": "Token (${standard})", + "picker_see_all": "Alle anzeigen", + "picker_show_less": "Weniger anzeigen", "pin_at_top": "${token} oben anheften", "pin_is_incorrect": "PIN ist falsch", "pin_number": "PIN-Nummer", @@ -927,12 +943,16 @@ "select_a_wallet": "Wallet auswählen", "select_address_to_copy": "Adresse zum Kopieren auswählen", "select_all": "Alles auswählen", + "select_asset": "Wählen Sie Asset aus", "select_backup_file": "Backup-Datei auswählen", "select_buy_provider_notice": "Wählen Sie oben einen Kaufanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie Ihren Standard-Kaufanbieter in den App-Einstellungen festlegen.", "select_destination": "Bitte wählen Sie das Ziel für die Backup-Datei aus.", + "select_fiat_currency_title": "Wählen Sie Währung aus", "select_hw_account_below": "Bitte wählen Sie unten aus, welches Konto wiederhergestellt werden soll:", "select_manufacturer_title": "Hersteller auswählen", "select_network": "Netzwerk auswählen", + "select_network_subtitle": "Dieses Asset ist in mehreren Netzwerken vorhanden. Wählen Sie die aus, die Sie verwenden möchten", + "select_network_title": "Wählen Sie Netzwerk", "select_other_wallet": "Anderes Wallet auswählen", "select_receiver": "Empfänger auswählen", "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.", @@ -1091,7 +1111,7 @@ "swipe_to_send": "Zum Senden wischen", "switch_wallet": "Wallet wechseln", "switchToETHWallet": "Bitte wechseln Sie zu einer Ethereum-Wallet und versuchen Sie es erneut", - "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon).", + "switchToWCCompatibleWallet": "Bitte wechseln Sie zu einer WalletConnect-kompatiblen Wallet und versuchen Sie es erneut (${chains}).", "symbol": "Symbol", "sync_all_wallets": "Alle Wallets synchronisieren", "sync_attempting": "Synchronisierung wird versucht", @@ -1399,4 +1419,4 @@ "zcash_card_missing_funds": "Fehlende Gelder?", "zcash_card_scan": "Scannen", "zcash_card_warning": "Schließen Sie die App nicht, bis der Vorgang abgeschlossen ist. Andernfalls muss der Vorgang von Grund auf neu gestartet werden." -} +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index f0b425652..964255cac 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -217,6 +217,8 @@ "color_theme": "Color theme", "coming_soon_tag": "Coming Soon", "commit_transaction_amount_fee": "Commit transaction\nAmount: ${amount}\nFee: ${fee}", + "compatible_services": "Compatible Services", + "compatible_services_desc": "Use the Scan tool to read the following types of QR codes supported on Cake Wallet:", "configure": "Configure", "confirm": "Confirm", "confirm_delete_template": "This action will delete this template. Do you wish to continue?", @@ -280,6 +282,8 @@ "creating_new_wallet": "Creating new wallet", "creating_new_wallet_error": "Error: ${description}", "creation_date": "Creation Date", + "crypto_addresses": "Crypto Addresses", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Current Swap", "current_wallet": "Current wallet", "custom": "Custom", @@ -455,14 +459,12 @@ "expires": "Expires", "expiresOn": "Expires on", "expiry_and_validity": "Expiry and Validity", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Export backup", "export_csv": "Export CSV", "export_lightning_logs": "Export Lightning logs", "export_logs": "Export logs", "export_outputs": "Export outputs", "export_payjoin_logs": "Export Payjoin logs", - "generating_csv": "Generating CSV...", "extend_session": "Extend Session", "external": "External", "external_wallet": "External wallet", @@ -497,10 +499,12 @@ "frozen": "Frozen", "frozen_balance": "Frozen Balance", "full_balance": "Full Balance", + "gallery": "Gallery", "gas_exceeds_allowance": "Gas required by transaction exceeds allowance.", "gas_price": "Gas price", "general": "General", "generate_name": "Generate Name", + "generating_csv": "Generating CSV...", "generating_gift_card": "Generating Gift Card", "generating_transaction": "Generating transaction", "get_a": "Get a ", @@ -547,6 +551,7 @@ "infobox_auto_address": "Your receive address will rotate every time you receive a transaction", "infobox_multichain": "Use this addess to receive any token or collectible on", "infobox_rotation": "Your receive address will rotate every time you close and reopen this screen", + "input": "Input", "inputs": "Inputs", "insufficient_funds_for_tx": "Insufficient funds to successfully execute transaction.", "insufficient_lamport_for_tx": "You do not have enough SOL to cover the transaction and its transaction fee. Kindly add more SOL to your wallet or reduce the SOL amount you\\'re sending.", @@ -612,6 +617,7 @@ "manage_pow_nodes": "Manage PoW nodes", "manage_providers": "Manage providers", "manage_yats": "Manage Yats", + "manual_input": "Manual Input", "mark_as_redeemed": "Mark As Redeemed", "market_place": "Marketplace", "mask": "Mask", @@ -657,6 +663,7 @@ "nanogpt_subtitle": "All the newest models (GPT-5.3, Claude 4.6).\\nNo subscription, pay with crypto.", "narrow": "Narrow", "network": "Network", + "networks": "Networks", "new_first_wallet_text": "Keeping your crypto safe is a piece of cake", "new_node_testing": "New node testing", "new_subaddress_create": "Create", @@ -698,6 +705,7 @@ "note_tap_to_change": "Note (tap to change)", "notification_permission_denied": "Notification permission got permamently denied, please manually enable it in settings", "nullURIError": "URI is null", + "ocp_desc": "Pay with crypto in stores", "offer_expires_in": "Offer expires in: ", "offline": "Offline", "ok": "OK", @@ -724,11 +732,11 @@ "outputs": "Outputs", "overshot": "Overshot", "overwrite_amount": "Overwrite amount", - "pairingInvalidEvent": "Pairing Invalid Event", "pairing_code": "Pairing Code", "pairing_code_desc_1": "Your device will show a pairing code.", "pairing_code_desc_2": "Input here to continue", "pairing_error": "Pairing Error", + "pairingInvalidEvent": "Pairing Invalid Event", "passphrase": "Passphrase (Optional)", "passphrase_view_keys": "Passphrase", "passphrases_doesnt_match": "Passphrases do not match, please try again", @@ -746,11 +754,28 @@ "payjoin_unavailable_sheet_content": "Receiving a Payjoin transaction requires you to have Bitcoin ready to use.\n\nAs soon as your wallet has funds, Payjoin will be automatically enabled.", "payjoin_unavailable_sheet_title": "Why is Payjoin unavailable?", "payment_id": "Payment ID: ", + "payment_invoices": "Payment Invoices", "payment_made_easy": "Payments made easy", "payment_was_received": "Your payment was received.", "payments": "Payments", "pending": " (pending)", "percentageOf": "of ${amount}", + "picker_chip_all": "All", + "picker_no_matches": "No matches", + "picker_section_all_assets": "All Assets (A-Z)", + "picker_section_all_currencies": "All Currencies", + "picker_section_crypto": "Crypto", + "picker_section_cryptocurrencies": "Cryptocurrencies", + "picker_section_gas_token": "Gas Token", + "picker_section_more_cryptocurrencies": "More Cryptocurrencies", + "picker_section_popular": "Popular", + "picker_section_recents": "Recents", + "picker_section_selected": "Selected", + "picker_section_stablecoins": "Stablecoins", + "picker_section_tokenized_stocks": "Tokenized Stocks (xStocks)", + "picker_section_tokens_standard": "Tokens (${standard})", + "picker_see_all": "See All", + "picker_show_less": "Show less", "pin_at_top": "Pin ${token} at top", "pin_is_incorrect": "PIN is incorrect", "pin_number": "PIN number", @@ -885,6 +910,7 @@ "save": "Save", "save_backup_password": "Please make sure that you have saved your backup password. You will not be able to import your backup files without it.", "save_backup_password_alert": "Save backup password", + "save_contact": "Save Contact", "save_to_downloads": "Save to Downloads", "saved_the_trade_id": "I've saved the trade ID", "savings": "Savings", @@ -941,12 +967,16 @@ "select_a_wallet": "Select a wallet", "select_address_to_copy": "Select Address to Copy", "select_all": "Select all", + "select_asset": "Select Asset", "select_backup_file": "Select backup file", "select_buy_provider_notice": "Select a buy provider above. You can skip this screen by setting your default buy provider in app settings.", "select_destination": "Please select destination for the backup file.", + "select_fiat_currency_title": "Select Currency", "select_hw_account_below": "Please select which account to restore below:", "select_manufacturer_title": "Select Manufacturer", "select_network": "Select Network", + "select_network_subtitle": "This asset is present in multiple networks. Select the one you want to use", + "select_network_title": "Select Network", "select_other_wallet": "Select other Wallet", "select_receiver": "Select Receiver", "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.", @@ -1030,9 +1060,9 @@ "setup_your_debit_card": "Set up your debit card", "share": "Share", "share_address": "Share address", + "share_this_node": "Share this node", "shared_seed_wallet_groups": "Shared Seed Wallet Groups", "shared_seed_wallets": "Shared Seed Wallets", - "share_this_node": "Share this node", "show": "Show", "show_address_book_popup": "Show Address Book popup", "show_balance": "Long Press to Show Balance", @@ -1108,7 +1138,7 @@ "swipe_to_send": "Swipe to send", "switch_wallet": "Switch Wallet", "switchToETHWallet": "Please switch to an Ethereum wallet and try again", - "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Please switch to a WalletConnect compatible wallet and try again (${chains}).", "symbol": "Symbol", "sync_all_wallets": "Sync all wallets", "sync_attempting": "Attempting sync", @@ -1295,10 +1325,10 @@ "value_type": "Value Type", "variable_pair_not_supported": "This variable pair is not supported with the selected exchanges", "verification": "Verification", - "verifying_code": "Verifying Code", "verify_message": "Verify Message", "verify_seed": "Verify Seed", "verify_with_2fa": "Verify with Cake 2FA", + "verifying_code": "Verifying Code", "version": "Version ${currentVersion}", "view_all": "View all", "view_in_block_explorer": "View in Block Explorer", @@ -1352,6 +1382,7 @@ "wc_approve_request_title": "Approve request", "wc_connect_request_title": "Connect request", "wc_connected_to": "Connected to ${name}", + "wc_desc": "Easily connect to DApps", "wc_max_network_fee": "Max network fee", "wc_message_to_sign": "Message to sign", "wc_network_fee": "Network fee", @@ -1402,8 +1433,8 @@ "yat_popup_content": "You can now send and receive crypto in Cake Wallet with your Yat - a short, emoji-based username. Manage Yats at any time on the settings screen", "yat_popup_title": "Your wallet address can be emojified.", "yes": "Yes", - "yesterday": "Yesterday", "yes_exit": "Yes. Exit", + "yesterday": "Yesterday", "you_now_have_debit_card": "You now have a debit card", "you_pay": "You Pay", "you_will_get": "Convert to", @@ -1418,4 +1449,4 @@ "zcash_card_missing_funds": "Missing funds?", "zcash_card_scan": "Scan", "zcash_card_warning": "Do not close the app until the procedure completes, if you do so this process will need to restart from scratch." -} +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 3fef8e0a1..c8a45aa22 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Creando una nueva billetera", "creating_new_wallet_error": "Error: ${description}", "creation_date": "Fecha de creación", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Intercambio actual", "current_wallet": "Cartera actual", "custom": "Personalizado", @@ -450,14 +451,12 @@ "expires": "Caduca", "expiresOn": "Caduca el", "expiry_and_validity": "Caducidad y validez", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Exportar copia de seguridad", "export_csv": "Export CSV", "export_lightning_logs": "Exportar registros de Lightning", "export_logs": "Exportar registros", "export_outputs": "Exportar salidas", "export_payjoin_logs": "Exportar registros de Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Extender sesión", "external": "Externo", "external_wallet": "Billetera externa", @@ -494,6 +493,7 @@ "gas_price": "Precio del gas", "general": "General", "generate_name": "Generar nombre", + "generating_csv": "Generating CSV...", "generating_gift_card": "Generando tarjeta de regalo", "generating_transaction": "Generando transacción", "get_a": "Obtén un ", @@ -737,6 +737,22 @@ "pending": " (pendiente)", "percentageOf": "de ${amount}", "personalizado": "personalizado", + "picker_chip_all": "Todo", + "picker_no_matches": "No hay coincidencias", + "picker_section_all_assets": "Todos los activos (A-Z)", + "picker_section_all_currencies": "Todas las monedas", + "picker_section_crypto": "Cripto", + "picker_section_cryptocurrencies": "Criptomonedas", + "picker_section_gas_token": "Ficha de gasolina", + "picker_section_more_cryptocurrencies": "Más criptomonedas", + "picker_section_popular": "Popular", + "picker_section_recents": "Recientes", + "picker_section_selected": "Seleccionado", + "picker_section_stablecoins": "Monedas estables", + "picker_section_tokenized_stocks": "Acciones tokenizadas (xStocks)", + "picker_section_tokens_standard": "Fichas (${standard})", + "picker_see_all": "Ver todo", + "picker_show_less": "Mostrar menos", "pin_at_top": "Fijar ${token} arriba", "pin_is_incorrect": "El PIN es incorrecto", "pin_number": "Número de PIN", @@ -927,12 +943,16 @@ "select_a_wallet": "Selecciona una cartera", "select_address_to_copy": "Seleccionar dirección para copiar", "select_all": "Seleccionar todo", + "select_asset": "Seleccionar activo", "select_backup_file": "Seleccionar archivo de copia de seguridad", "select_buy_provider_notice": "Selecciona un proveedor de compra arriba. Puedes omitir esta pantalla configurando tu proveedor de compra predeterminado en los ajustes de la aplicación.", "select_destination": "Selecciona el destino del archivo de copia de seguridad.", + "select_fiat_currency_title": "Seleccionar moneda", "select_hw_account_below": "Por favor, selecciona la cuenta que deseas restaurar a continuación:", "select_manufacturer_title": "Seleccionar fabricante", "select_network": "Seleccionar red", + "select_network_subtitle": "Este activo está presente en múltiples redes. Seleccione el que desea utilizar", + "select_network_title": "Seleccionar red", "select_other_wallet": "Seleccionar otra billetera", "select_receiver": "Seleccionar destinatario", "select_sell_provider_notice": "Selecciona un proveedor de venta arriba. Puedes omitir esta pantalla configurando tu proveedor de venta predeterminado en los ajustes de la aplicación.", @@ -1091,7 +1111,7 @@ "swipe_to_send": "Desliza para enviar", "switch_wallet": "Cambiar cartera", "switchToETHWallet": "Por favor, cambia a una billetera de Ethereum y vuelve a intentarlo.", - "switchToEVMCompatibleWallet": "Cambia a una billetera compatible con EVM e inténtalo de nuevo (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Cambie a una billetera compatible con WalletConnect e inténtelo nuevamente (${chains}).", "symbol": "Símbolo", "sync_all_wallets": "Sincronizar todas las billeteras", "sync_attempting": "Intentando sincronizar", @@ -1397,4 +1417,4 @@ "zcash_card_missing_funds": "¿Faltan fondos?", "zcash_card_scan": "Escanear", "zcash_card_warning": "No cierre la aplicación hasta que se complete el procedimiento; si lo hace, este proceso deberá reiniciarse desde cero." -} +} \ No newline at end of file diff --git a/res/values/strings_fa.arb b/res/values/strings_fa.arb index 64eb9f168..515e6f3ce 100644 --- a/res/values/strings_fa.arb +++ b/res/values/strings_fa.arb @@ -275,6 +275,7 @@ "creating_new_wallet": "در حال ایجاد کیف پول جدید", "creating_new_wallet_error": "خطا: ${description}", "creation_date": "تاریخ ایجاد", + "csv_nothing_to_export": "Nothing to export", "current_swap": "سواپ فعلی", "current_wallet": "کیف پول فعلی", "custom": "سفارشی", @@ -448,14 +449,12 @@ "expires": "منقضی می‌شود", "expiresOn": "انقضا در", "expiry_and_validity": "انقضا و اعتبار", - "csv_nothing_to_export": "Nothing to export", "export_backup": "صدور نسخه پشتیبان", "export_csv": "Export CSV", "export_lightning_logs": "خروجی گرفتن از گزارش‌های لایتنینگ", "export_logs": "خروجی گرفتن از گزارش‌ها", "export_outputs": "برون‌برد خروجی‌ها", "export_payjoin_logs": "گزارش‌های Payjoin را صادر کنید", - "generating_csv": "Generating CSV...", "extend_session": "تمدید جلسه", "external": "خارجی", "external_wallet": "کیف پول خارجی", @@ -492,6 +491,7 @@ "gas_price": "قیمت گس", "general": "عمومی", "generate_name": "ایجاد نام", + "generating_csv": "Generating CSV...", "generating_gift_card": "در حال ایجاد گیفت کارت", "generating_transaction": "در حال ایجاد تراکنش", "get_a": "یک ", @@ -735,6 +735,22 @@ "payments": "پرداخت‌ها", "pending": " (در انتظار)", "percentageOf": "از ${amount}", + "picker_chip_all": "همه", + "picker_no_matches": "هیچ مسابقه ای وجود ندارد", + "picker_section_all_assets": "همه دارایی ها (A-Z)", + "picker_section_all_currencies": "همه ارزها", + "picker_section_crypto": "رمزنگاری", + "picker_section_cryptocurrencies": "ارزهای رمزنگاری شده", + "picker_section_gas_token": "ژتون گاز", + "picker_section_more_cryptocurrencies": "ارزهای دیجیتال بیشتر", + "picker_section_popular": "محبوب", + "picker_section_recents": "اخیر", + "picker_section_selected": "انتخاب شده است", + "picker_section_stablecoins": "استیبل کوین ها", + "picker_section_tokenized_stocks": "سهام توکن شده (xStocks)", + "picker_section_tokens_standard": "توکن‌ها (${standard})", + "picker_see_all": "همه را ببینید", + "picker_show_less": "کمتر نشان دادن", "pin_at_top": "سنجاق کردن ${token} به بالا", "pin_is_incorrect": "پین نادرست است", "pin_number": "شماره PIN", @@ -925,12 +941,16 @@ "select_a_wallet": "یک کیف پول را انتخاب کنید", "select_address_to_copy": "آدرس را برای کپی کردن انتخاب کنید", "select_all": "انتخاب همه", + "select_asset": "Asset را انتخاب کنید", "select_backup_file": "فایل پشتیبان را انتخاب کنید", "select_buy_provider_notice": "یک ارائه‌دهنده خرید را در بالا انتخاب کنید.\nمی‌توانید با تنظیم ارائه‌دهنده خرید پیش‌فرض در تنظیمات برنامه، این صفحه را رد کنید.", "select_destination": "لطفاً مقصد فایل پشتیبان را انتخاب کنید.", + "select_fiat_currency_title": "ارز را انتخاب کنید", "select_hw_account_below": "لطفاً حسابی را که می‌خواهید بازیابی کنید، در زیر انتخاب کنید:", "select_manufacturer_title": "انتخاب سازنده", "select_network": "انتخاب شبکه", + "select_network_subtitle": "این دارایی در چندین شبکه وجود دارد. موردی را که می خواهید استفاده کنید انتخاب کنید", + "select_network_title": "Network را انتخاب کنید", "select_other_wallet": "کیف پول دیگری را انتخاب کنید", "select_receiver": "گیرنده را انتخاب کنید", "select_sell_provider_notice": "یک ارائه‌دهنده فروش را در بالا انتخاب کنید.\nمی‌توانید با تنظیم ارائه‌دهنده فروش پیش‌فرض خود در تنظیمات برنامه، این صفحه را رد کنید.", @@ -1089,7 +1109,7 @@ "swipe_to_send": "برای ارسال، انگشت خود را بکشید", "switch_wallet": "تعویض کیف پول", "switchToETHWallet": "لطفاً به کیف پول اتریوم تغییر دهید و دوباره تلاش کنید", - "switchToEVMCompatibleWallet": "لطفاً به یک کیف پول سازگار با EVM تغییر دهید و دوباره تلاش کنید (Ethereum، Polygon)", + "switchToWCCompatibleWallet": "لطفاً به یک کیف پول سازگار با WalletConnect بروید و دوباره امتحان کنید (${chains}).", "symbol": "نماد", "sync_all_wallets": "همگام‌سازی همه کیف‌پول‌ها", "sync_attempting": "در حال تلاش برای همگام‌سازی", @@ -1392,4 +1412,4 @@ "zcash_card_missing_funds": "موجودی گم شده؟", "zcash_card_scan": "اسکن", "zcash_card_warning": "تا زمانی که این فرایند کامل نشده است، برنامه را نبندید؛ در غیر این صورت، این فرایند باید از ابتدا دوباره شروع شود." -} +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 89a3576b2..c674f099b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Création d'un nouveau portefeuille", "creating_new_wallet_error": "Erreur : ${description}", "creation_date": "Date de création", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Swap en cours", "current_wallet": "Portefeuille actuel", "custom": "Personnalisé", @@ -450,14 +451,12 @@ "expires": "Expire", "expiresOn": "Expire le", "expiry_and_validity": "Expiration et validité", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Exporter la sauvegarde", "export_csv": "Export CSV", "export_lightning_logs": "Exporter les logs Lightning", "export_logs": "Exporter les journaux", "export_outputs": "Exporter les sorties", "export_payjoin_logs": "Exporter les journaux de Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Prolonger la session", "external": "Externe", "external_wallet": "Portefeuille externe", @@ -494,6 +493,7 @@ "gas_price": "Prix du gas", "general": "Général", "generate_name": "Générer un nom", + "generating_csv": "Generating CSV...", "generating_gift_card": "Génération de la carte-cadeau", "generating_transaction": "Génération de la transaction", "get_a": "Obtenir un ", @@ -736,6 +736,22 @@ "payments": "Paiements", "pending": " (en attente)", "percentageOf": "de ${amount}", + "picker_chip_all": "Tous", + "picker_no_matches": "Aucune correspondance", + "picker_section_all_assets": "Tous les actifs (A-Z)", + "picker_section_all_currencies": "Toutes les devises", + "picker_section_crypto": "Cryptomonnaie", + "picker_section_cryptocurrencies": "Crypto-monnaies", + "picker_section_gas_token": "Jeton de gaz", + "picker_section_more_cryptocurrencies": "Plus de crypto-monnaies", + "picker_section_popular": "Populaire", + "picker_section_recents": "Récents", + "picker_section_selected": "Choisi", + "picker_section_stablecoins": "Pièces stables", + "picker_section_tokenized_stocks": "Actions tokenisées (xStocks)", + "picker_section_tokens_standard": "Jetons (${standard})", + "picker_see_all": "Voir tout", + "picker_show_less": "Afficher moins", "pin_at_top": "Épingler ${token} en haut", "pin_is_incorrect": "Le PIN est incorrect", "pin_number": "Numéro de PIN", @@ -926,12 +942,16 @@ "select_a_wallet": "Sélectionnez un portefeuille", "select_address_to_copy": "Sélectionner l'adresse à copier", "select_all": "Tout sélectionner", + "select_asset": "Sélectionnez l'actif", "select_backup_file": "Sélectionner le fichier de sauvegarde", "select_buy_provider_notice": "Sélectionnez un prestataire d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre prestataire d'achat par défaut dans les paramètres de l'application.", "select_destination": "Veuillez sélectionner l’emplacement du fichier de sauvegarde.", + "select_fiat_currency_title": "Sélectionnez la devise", "select_hw_account_below": "Veuillez sélectionner ci-dessous le compte à restaurer :", "select_manufacturer_title": "Sélectionner le fabricant", "select_network": "Sélectionner le réseau", + "select_network_subtitle": "Cet atout est présent dans plusieurs réseaux. Sélectionnez celui que vous souhaitez utiliser", + "select_network_title": "Sélectionnez le réseau", "select_other_wallet": "Sélectionner un autre portefeuille", "select_receiver": "Sélectionner le destinataire", "select_sell_provider_notice": "Sélectionnez un prestataire de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre prestataire de vente par défaut dans les paramètres de l'application.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "Faites glisser pour envoyer", "switch_wallet": "Changer de portefeuille", "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer", - "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon).", + "switchToWCCompatibleWallet": "Veuillez passer à un portefeuille compatible WalletConnect et réessayer (${chains}).", "symbol": "Symbole", "sync_all_wallets": "Synchroniser tous les portefeuilles", "sync_attempting": "Synchronisation en cours", @@ -1395,4 +1415,4 @@ "zcash_card_missing_funds": "Fonds manquants ?", "zcash_card_scan": "Scanner", "zcash_card_warning": "Ne fermez pas l'application tant que la procédure n'est pas terminée. Si vous le faites, ce processus devra redémarrer depuis le début." -} +} \ No newline at end of file diff --git a/res/values/strings_gn.arb b/res/values/strings_gn.arb index 1d59ae3ed..80dc4dee9 100644 --- a/res/values/strings_gn.arb +++ b/res/values/strings_gn.arb @@ -223,6 +223,7 @@ "creating_new_wallet": "Omoheñóvo billetera pyahu", "creating_new_wallet_error": "Jejavy: ${description}", "creation_date": "Arange ojejapo hague", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Intercambio ko'ág̃a", "current_wallet": "Billetera actual", "custom": "Mboavopyre", @@ -357,12 +358,10 @@ "expires": "Opa hag̃ua", "expiresOn": "Opa hag̃ua", "expiry_and_validity": "Opaha ára ha hekorã", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Emondo hag̃ua backup", "export_csv": "Export CSV", "export_lightning_logs": "Emondo Lightning rembiapokue", "export_payjoin_logs": "Emondo okápe Payjoin registro-kuéra", - "generating_csv": "Generating CSV...", "external": "Okápegua", "external_wallet": "Billetera externa", "extra_id": "ID extra:", @@ -391,6 +390,7 @@ "full_balance": "Saldo completo", "general": "Mba'eichagua", "generate_name": "Emoheñói Téra", + "generating_csv": "Generating CSV...", "generating_gift_card": "Oñemoheñói hína tarjeta jopói", "get_a": "Ereko peteĩ ", "get_card_note": "Ikatu emyenyhẽjey viru digital rupive. Ndoikotevẽi ambue marandu!", @@ -577,6 +577,22 @@ "pending": " (oĩhína oñehaʼãrõme)", "percentageOf": "rehe ${amount}", "personalizado": "Ojeiporavokuaava", + "picker_chip_all": "Opavave", + "picker_no_matches": "Ndaipóri joaju", + "picker_section_all_assets": "Opaite mba’e (A-Z) .", + "picker_section_all_currencies": "Opaite Viru rehegua", + "picker_section_crypto": "Cripto rehegua", + "picker_section_cryptocurrencies": "Criptomoneda rehegua", + "picker_section_gas_token": "Token de Gas rehegua", + "picker_section_more_cryptocurrencies": "Hetave Criptomoneda rehegua", + "picker_section_popular": "Ojehayhúva", + "picker_section_recents": "Nda’aréi ojejapóva", + "picker_section_selected": "Ojeporavóva", + "picker_section_stablecoins": "Stablecoins rehegua", + "picker_section_tokenized_stocks": "Acciones Tokenizadas (xStocks) rehegua .", + "picker_section_tokens_standard": "Fichas (${standard}) rehegua .", + "picker_see_all": "Ehecha opa mba'e", + "picker_show_less": "Ehechauka sa’ive", "pin_at_top": "Emboja ${token} yvate gotyo", "pin_is_incorrect": "PIN ndoikói hag̃ua", "pin_number": "PIN papapy", @@ -743,9 +759,13 @@ "seedtype_polyseed": "Polieta (16 ñe’ẽ)", "select_address_to_copy": "Eiporavo dirección emokopia hag̃ua", "select_all": "Eiporavo opaite", + "select_asset": "Eiporavo Activo", "select_backup_file": "Eiporavo marandurenda ñongatupyre", "select_buy_provider_notice": "Eiporavo peteĩ jogua-me’ẽha yvate. Ikatu rehasapa ko pantalla emoĩvo nde jogua-me’ẽha ijypykuéramo ñembohekorã aplicación-pe.", "select_destination": "Eiporavo moõpa oñeñongatúta marandurenda backup.", + "select_fiat_currency_title": "Eiporavo Moneda", + "select_network_subtitle": "Ko activo oime presente heta red-pe. Eiporavo pe reiporuséva", + "select_network_title": "Eiporavo Red", "select_other_wallet": "Eiporavo ambue billetera", "select_receiver": "Eiporavo Mbyhyha", "select_sell_provider_notice": "Eiporavo yvate peteĩ ñemuha. Ikatu rehasa hag̃ua ko pantalla emoĩvo nde ñemuha ijypykuéramo umi ñemboheko hag̃ua aplicación-pe.", @@ -875,7 +895,7 @@ "sweeping_wallet_alert": "Kóva ndoguerahámo’ãi heta aravo. ANI REHEJA KO PANTALLA, térã umi fondo oñemopotĩva ikatu okañy.", "swipe_to_send": "Emoinge hag̃ua emondo hag̃ua.", "switchToETHWallet": "Ikatúpa emoambue peteĩ billetera Ethereum-pe ha eha’ãjey.", - "switchToEVMCompatibleWallet": "Ikatúpa emoambue peteĩ billetera ojoajukuaa hag̃ua EVM ndive ha eha’ãjey (Ethereum, Polygon).", + "switchToWCCompatibleWallet": "Embohasa peteĩ billetera WalletConnect ndive ha eñeha’ã jey (${chains}).", "symbol": "Ta'ãnga’i", "sync_all_wallets": "Embojuehe opaite billetera", "sync_attempting": "Oñeha’ãvo ojesincronisa", @@ -1142,4 +1162,4 @@ "zcash_card_missing_funds": "¿Nde fondo okañy?", "zcash_card_scan": "Escanear", "zcash_card_warning": "Ani remboty pe app pe procedimiento opa hag̃ua, rejapo ramo upéicha ko proceso tekotevẽta oñepyrũ jey cero guive." -} +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 9611767a9..0a48000d4 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Ana ƙirƙirar sabon walat", "creating_new_wallet_error": "Kuskure: ${description}", "creation_date": "Ranar ƙirƙira", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Musayar Yanzu", "current_wallet": "Walit na yanzu", "custom": "Na musamman", @@ -450,14 +451,12 @@ "expires": "Yana ƙarewa", "expiresOn": "Yana ƙarewa a", "expiry_and_validity": "Ranar ƙarewa da inganci", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Fitar da ajiyar baya", "export_csv": "Export CSV", "export_lightning_logs": "Fitar da log ɗin Lightning", "export_logs": "Fitar da log", "export_outputs": "Fitar da abubuwan fitarwa", "export_payjoin_logs": "Fitar da log ɗin Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Tsawaita Zama", "external": "Na waje", "external_wallet": "Wallet na waje", @@ -494,6 +493,7 @@ "gas_price": "Farashin gas", "general": "Gabaɗaya", "generate_name": "Ƙirƙiri Suna", + "generating_csv": "Generating CSV...", "generating_gift_card": "Ana Ƙirƙirar Katin Kyauta", "generating_transaction": "Ana ƙirƙirar ma'amala", "get_a": "Samu ", @@ -738,6 +738,22 @@ "payments": "Biyan kuɗi", "pending": " (ana jiran)", "percentageOf": "na ${amount}", + "picker_chip_all": "Duka", + "picker_no_matches": "Babu ashana", + "picker_section_all_assets": "Duk Kayayyaki (A-Z)", + "picker_section_all_currencies": "Duk Kudi", + "picker_section_crypto": "Crypto", + "picker_section_cryptocurrencies": "Cryptocurrencies", + "picker_section_gas_token": "Gas Token", + "picker_section_more_cryptocurrencies": "Ƙarin Cryptocurrencies", + "picker_section_popular": "Shahararren", + "picker_section_recents": "Kwanan nan", + "picker_section_selected": "zaba", + "picker_section_stablecoins": "Stablecoins", + "picker_section_tokenized_stocks": "Hannun Jari na Tokenized (xStocks)", + "picker_section_tokens_standard": "Alamu (${standard})", + "picker_see_all": "Duba duka", + "picker_show_less": "Nuna ƙasa", "pin_at_top": "Saka ${token} a sama", "pin_is_incorrect": "PIN ɗin ba daidai ba ne", "pin_number": "Lambar PIN", @@ -928,12 +944,16 @@ "select_a_wallet": "Zaɓi walat", "select_address_to_copy": "Zaɓi adireshi don kwafi", "select_all": "Zaɓi duka", + "select_asset": "Zaɓi Kadari", "select_backup_file": "Zaɓi fayil ɗin ajiyar baya", "select_buy_provider_notice": "Zaɓi mai ba da sabis na saye a sama. Za ka iya tsallake wannan allon ta hanyar saita tsohon mai ba da sabis na saye a cikin saitunan manhaja.", "select_destination": "Da fatan za a zaɓi wurin da za a ajiye fayil ɗin madadin.", + "select_fiat_currency_title": "Zaɓi Kuɗi", "select_hw_account_below": "Da fatan za a zaɓi asusun da za a maido a ƙasa:", "select_manufacturer_title": "Zaɓi Mai ƙera", "select_network": "Zaɓi hanyar sadarwa", + "select_network_subtitle": "Wannan kadari yana nan a cikin cibiyoyin sadarwa da yawa. Zaɓi wanda kake son amfani da shi", + "select_network_title": "Zaɓi hanyar sadarwa", "select_other_wallet": "Zaɓi wata Wallet", "select_receiver": "Zaɓi Mai karɓa", "select_sell_provider_notice": "Zaɓi mai ba da sabis na sayarwa a sama. Kuna iya tsallake wannan allon ta saita tsohon mai ba da sabis na sayarwa a cikin saitunan app.", @@ -1092,7 +1112,7 @@ "swipe_to_send": "Zame don aikawa", "switch_wallet": "Canja Wallet", "switchToETHWallet": "Da fatan za a koma zuwa walat ɗin Ethereum kuma a sake gwadawa", - "switchToEVMCompatibleWallet": "Da fatan za a koma zuwa walat mai jituwa da EVM sannan a sake gwadawa (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Da fatan za a canza zuwa WalletConnect mai dacewa da walat kuma a sake gwadawa (${chains}).", "symbol": "Alama", "sync_all_wallets": "Daidaita duk walat", "sync_attempting": "Ana ƙoƙarin daidaitawa", @@ -1398,4 +1418,4 @@ "zcash_card_missing_funds": "Kuɗi sun ɓace?", "zcash_card_scan": "Duba", "zcash_card_warning": "Kada ku rufe manhajar har sai an kammala aikin; idan kun yi haka, wannan tsari zai buƙaci a sake farawa daga farko." -} +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index c3dd9f82a..51c88392f 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "नया वॉलेट बनाया जा रहा है", "creating_new_wallet_error": "त्रुटि: ${description}", "creation_date": "निर्माण तिथि", + "csv_nothing_to_export": "Nothing to export", "current_swap": "वर्तमान स्वैप", "current_wallet": "वर्तमान वॉलेट", "custom": "कस्टम", @@ -450,14 +451,12 @@ "expires": "समाप्त होता है", "expiresOn": "इस दिन समाप्त होता है", "expiry_and_validity": "समाप्ति और वैधता", - "csv_nothing_to_export": "Nothing to export", "export_backup": "बैकअप निर्यात करें", "export_csv": "Export CSV", "export_lightning_logs": "लाइटनिंग लॉग्स निर्यात करें", "export_logs": "लॉग निर्यात करें", "export_outputs": "आउटपुट निर्यात करें", "export_payjoin_logs": "Payjoin लॉग एक्सपोर्ट करें", - "generating_csv": "Generating CSV...", "extend_session": "सत्र बढ़ाएँ", "external": "बाहरी", "external_wallet": "बाहरी वॉलेट", @@ -494,6 +493,7 @@ "gas_price": "गैस मूल्य", "general": "सामान्य", "generate_name": "नाम उत्पन्न करें", + "generating_csv": "Generating CSV...", "generating_gift_card": "गिफ्ट कार्ड जनरेट किया जा रहा है", "generating_transaction": "लेन-देन जनरेट किया जा रहा है", "get_a": "एक प्राप्त करें ", @@ -737,6 +737,22 @@ "payments": "भुगतान", "pending": " (लंबित)", "percentageOf": "${amount} का", + "picker_chip_all": "सभी", + "picker_no_matches": "कोई मेल नहीं", + "picker_section_all_assets": "सभी संपत्तियां (ए-जेड)", + "picker_section_all_currencies": "सभी मुद्राएँ", + "picker_section_crypto": "क्रिप्टो", + "picker_section_cryptocurrencies": "क्रिप्टोकरेंसी", + "picker_section_gas_token": "गैस टोकन", + "picker_section_more_cryptocurrencies": "अधिक क्रिप्टोकरेंसी", + "picker_section_popular": "लोकप्रिय", + "picker_section_recents": "हाल ही", + "picker_section_selected": "चयनित", + "picker_section_stablecoins": "स्थिर सिक्के", + "picker_section_tokenized_stocks": "टोकनयुक्त स्टॉक (xStocks)", + "picker_section_tokens_standard": "टोकन (${standard})", + "picker_see_all": "सभी देखें", + "picker_show_less": "कम दिखाओ", "pin_at_top": "${token} को शीर्ष पर पिन करें", "pin_is_incorrect": "PIN गलत है", "pin_number": "पिन नंबर", @@ -928,12 +944,16 @@ "select_a_wallet": "एक वॉलेट चुनें", "select_address_to_copy": "कॉपी करने के लिए पता चुनें", "select_all": "सभी चुनें", + "select_asset": "संपत्ति का चयन करें", "select_backup_file": "बैकअप फ़ाइल चुनें", "select_buy_provider_notice": "ऊपर किसी खरीद प्रदाता का चयन करें। आप ऐप सेटिंग्स में अपना डिफ़ॉल्ट खरीद प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", "select_destination": "कृपया बैकअप फ़ाइल के लिए गंतव्य चुनें।", + "select_fiat_currency_title": "मुद्रा चुनें", "select_hw_account_below": "कृपया नीचे पुनर्स्थापित करने के लिए खाता चुनें:", "select_manufacturer_title": "निर्माता चुनें", "select_network": "नेटवर्क चुनें", + "select_network_subtitle": "यह संपत्ति कई नेटवर्क में मौजूद है. जिसे आप उपयोग करना चाहते हैं उसे चुनें", + "select_network_title": "नेटवर्क चुनें", "select_other_wallet": "अन्य वॉलेट चुनें", "select_receiver": "प्राप्तकर्ता चुनें", "select_sell_provider_notice": "ऊपर किसी विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग्स में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", @@ -1092,7 +1112,7 @@ "swipe_to_send": "भेजने के लिए स्वाइप करें", "switch_wallet": "वॉलेट बदलें", "switchToETHWallet": "कृपया Ethereum वॉलेट पर स्विच करें और फिर से प्रयास करें", - "switchToEVMCompatibleWallet": "कृपया EVM-संगत वॉलेट पर स्विच करें और फिर से प्रयास करें (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "कृपया वॉलेटकनेक्ट संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (${chains})।", "symbol": "प्रतीक", "sync_all_wallets": "सभी वॉलेट सिंक करें", "sync_attempting": "सिंक करने का प्रयास किया जा रहा है", @@ -1397,4 +1417,4 @@ "zcash_card_missing_funds": "फंड गायब हैं?", "zcash_card_scan": "स्कैन", "zcash_card_warning": "प्रक्रिया पूरी होने तक ऐप बंद न करें। यदि आप ऐसा करते हैं, तो यह प्रक्रिया शुरू से फिर से शुरू करनी होगी।" -} +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 985f360d6..aa81926d1 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Stvaranje novog novčanika", "creating_new_wallet_error": "Greška: ${description}", "creation_date": "Datum izrade", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Trenutna zamjena", "current_wallet": "Trenutni novčanik", "custom": "Prilagođeno", @@ -450,14 +451,12 @@ "expires": "Ističe", "expiresOn": "Istječe", "expiry_and_validity": "Istek i valjanost", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Izvezi sigurnosnu kopiju", "export_csv": "Export CSV", "export_lightning_logs": "Izvezi Lightning zapise", "export_logs": "Izvezi zapise", "export_outputs": "Izvoz izlaza", "export_payjoin_logs": "Izvezi Payjoin zapise", - "generating_csv": "Generating CSV...", "extend_session": "Produži sesiju", "external": "Vanjski", "external_wallet": "Vanjski novčanik", @@ -494,6 +493,7 @@ "gas_price": "Cijena gasa", "general": "Općenito", "generate_name": "Generiraj naziv", + "generating_csv": "Generating CSV...", "generating_gift_card": "Generiranje poklon kartice", "generating_transaction": "Generiranje transakcije", "get_a": "Nabavite ", @@ -736,6 +736,22 @@ "payments": "Plaćanja", "pending": " (na čekanju)", "percentageOf": "od ${amount}", + "picker_chip_all": "Sve", + "picker_no_matches": "Nema podudaranja", + "picker_section_all_assets": "Sva sredstva (A-Z)", + "picker_section_all_currencies": "Sve valute", + "picker_section_crypto": "Kripto", + "picker_section_cryptocurrencies": "Kriptovalute", + "picker_section_gas_token": "Žeton za plin", + "picker_section_more_cryptocurrencies": "Više kriptovaluta", + "picker_section_popular": "Popularan", + "picker_section_recents": "Nedavni", + "picker_section_selected": "Odabrano", + "picker_section_stablecoins": "Stablecoins", + "picker_section_tokenized_stocks": "Tokenizirane dionice (xStocks)", + "picker_section_tokens_standard": "Tokeni (${standard})", + "picker_see_all": "Vidi sve", + "picker_show_less": "Prikaži manje", "pin_at_top": "Prikvači ${token} na vrh", "pin_is_incorrect": "PIN je netočan", "pin_number": "PIN broj", @@ -926,12 +942,16 @@ "select_a_wallet": "Odaberite novčanik", "select_address_to_copy": "Odaberite adresu za kopiranje", "select_all": "Odaberi sve", + "select_asset": "Odaberite sredstvo", "select_backup_file": "Odaberite datoteku sigurnosne kopije", "select_buy_provider_notice": "Odaberite gore pružatelja usluge kupnje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluge kupnje u postavkama aplikacije.", "select_destination": "Molimo odaberite odredište za datoteku sigurnosne kopije.", + "select_fiat_currency_title": "Odaberite Valutu", "select_hw_account_below": "Molimo odaberite račun koji želite vratiti u nastavku:", "select_manufacturer_title": "Odaberite proizvođača", "select_network": "Odaberite mrežu", + "select_network_subtitle": "Ovo sredstvo je prisutno u više mreža. Odaberite onu koju želite koristiti", + "select_network_title": "Odaberite Mreža", "select_other_wallet": "Odaberite drugi novčanik", "select_receiver": "Odaberite primatelja", "select_sell_provider_notice": "Odaberite pružatelja usluge prodaje iznad. Ovaj zaslon možete preskočiti tako da u postavkama aplikacije postavite zadanog pružatelja usluge prodaje.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "Prijeđite prstom za slanje", "switch_wallet": "Prebaci novčanik", "switchToETHWallet": "Molimo prebacite se na Ethereum novčanik i pokušajte ponovno", - "switchToEVMCompatibleWallet": "Molimo prebacite se na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Prebacite se na novčanik kompatibilan s WalletConnectom i pokušajte ponovno (${chains}).", "symbol": "Simbol", "sync_all_wallets": "Sinkroniziraj sve novčanike", "sync_attempting": "Pokušaj sinkronizacije", @@ -1395,4 +1415,4 @@ "zcash_card_missing_funds": "Nedostaju sredstva?", "zcash_card_scan": "Skeniraj", "zcash_card_warning": "Ne zatvarajte aplikaciju dok se postupak ne dovrši; ako to učinite, postupak će se morati ponovno pokrenuti ispočetka." -} +} \ No newline at end of file diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index 1961fa1b7..af2c2880b 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Ստեղծվում է նոր դրամապանակ", "creating_new_wallet_error": "Սխալ՝ ${description}", "creation_date": "Ստեղծման ամսաթիվ", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Ընթացիկ փոխանակում", "current_wallet": "Ընթացիկ դրամապանակ", "custom": "Հատուկ", @@ -450,14 +451,12 @@ "expires": "Լրանում է", "expiresOn": "Լրանում է", "expiry_and_validity": "Ժամկետ և վավերականություն", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Արտահանել պահուստային պատճենը", "export_csv": "Export CSV", "export_lightning_logs": "Արտահանել Lightning-ի տեղեկամատյանները", "export_logs": "Արտահանել տեղեկամատյանները", "export_outputs": "Արտահանել ելքերը", "export_payjoin_logs": "Արտահանել Payjoin-ի մատյանները", - "generating_csv": "Generating CSV...", "extend_session": "Երկարացնել սեսիան", "external": "Արտաքին", "external_wallet": "Արտաքին դրամապանակ", @@ -494,6 +493,7 @@ "gas_price": "Գազի գին", "general": "Ընդհանուր", "generate_name": "Ստեղծել անուն", + "generating_csv": "Generating CSV...", "generating_gift_card": "Նվեր քարտի ստեղծում", "generating_transaction": "Գործարքի ստեղծում", "get_a": "Ստանալ ", @@ -735,6 +735,22 @@ "payments": "Վճարումներ", "pending": " (սպասման մեջ)", "percentageOf": "${amount}-ից", + "picker_chip_all": "Բոլորը", + "picker_no_matches": "Համընկնումներ չկան", + "picker_section_all_assets": "Բոլոր ակտիվները (A-Z)", + "picker_section_all_currencies": "Բոլոր արժույթները", + "picker_section_crypto": "Կրիպտո", + "picker_section_cryptocurrencies": "Կրիպտոարժույթներ", + "picker_section_gas_token": "Գազի նշան", + "picker_section_more_cryptocurrencies": "Ավելի շատ կրիպտոարժույթներ", + "picker_section_popular": "Հանրաճանաչ", + "picker_section_recents": "Վերջերս", + "picker_section_selected": "Ընտրված է", + "picker_section_stablecoins": "Stablecoins", + "picker_section_tokenized_stocks": "Tokenized Stocks (xStocks)", + "picker_section_tokens_standard": "Նշաններ (${standard})", + "picker_see_all": "Տես բոլորը", + "picker_show_less": "Ցույց տալ ավելի քիչ", "pin_at_top": "${token}-ը ամրացնել վերևում", "pin_is_incorrect": "PIN-ը սխալ է", "pin_number": "PIN համար", @@ -925,12 +941,16 @@ "select_a_wallet": "Ընտրեք դրամապանակը", "select_address_to_copy": "Ընտրեք հասցեն՝ պատճենելու համար", "select_all": "Ընտրել բոլորը", + "select_asset": "Ընտրեք Ակտիվ", "select_backup_file": "Ընտրել պահուստային ֆայլը", "select_buy_provider_notice": "Վերևում ընտրեք գնման մատակարար։ Դուք կարող եք բաց թողնել այս էկրանը՝ հավելվածի կարգավորումներում սահմանելով ձեր լռելայն գնման մատակարարը։", "select_destination": "Խնդրում ենք ընտրել պահուստային ֆայլի նպատակակետը։", + "select_fiat_currency_title": "Ընտրեք արժույթ", "select_hw_account_below": "Խնդրում ենք ներքևում ընտրել, թե որ հաշիվը վերականգնել․", "select_manufacturer_title": "Ընտրեք արտադրողին", "select_network": "Ընտրեք ցանցը", + "select_network_subtitle": "Այս ակտիվը առկա է բազմաթիվ ցանցերում: Ընտրեք մեկը, որը ցանկանում եք օգտագործել", + "select_network_title": "Ընտրեք Ցանց", "select_other_wallet": "Ընտրեք այլ դրամապանակ", "select_receiver": "Ընտրեք ստացողին", "select_sell_provider_notice": "Վերևում ընտրեք վաճառքի մատակարար։ Դուք կարող եք բաց թողնել այս էկրանը՝ հավելվածի կարգավորումներում սահմանելով ձեր լռելայն վաճառքի մատակարարին։", @@ -1088,7 +1108,7 @@ "swipe_to_send": "Ուղարկելու համար սահեցրեք", "switch_wallet": "Փոխել դրամապանակը", "switchToETHWallet": "Խնդրում ենք անցնել Ethereum դրամապանակի և կրկին փորձել", - "switchToEVMCompatibleWallet": "Խնդրում ենք անցնել EVM-ի հետ համատեղելի դրամապանակի և փորձել կրկին (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Խնդրում ենք անցնել WalletConnect-ի համատեղելի դրամապանակին և նորից փորձել (${chains}):", "symbol": "Սիմվոլ", "sync_all_wallets": "Համաժամեցնել բոլոր դրամապանակները", "sync_attempting": "Համաժամացման փորձ", @@ -1392,4 +1412,4 @@ "zcash_card_missing_funds": "Միջոցները բացակա՞յում են", "zcash_card_scan": "Սկանավորել", "zcash_card_warning": "Մի փակեք հավելվածը մինչև ընթացակարգի ավարտը, քանի որ հակառակ դեպքում այս գործընթացը պետք է վերագործարկվի զրոյից։" -} +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index d223330d2..105c51270 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Membuat dompet baru", "creating_new_wallet_error": "Kesalahan: ${description}", "creation_date": "Tanggal Pembuatan", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Swap Saat Ini", "current_wallet": "Dompet saat ini", "custom": "Kustom", @@ -450,14 +451,12 @@ "expires": "Kedaluwarsa", "expiresOn": "Kedaluwarsa pada", "expiry_and_validity": "Kedaluwarsa dan Validitas", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Ekspor cadangan", "export_csv": "Export CSV", "export_lightning_logs": "Ekspor log Lightning", "export_logs": "Ekspor log", "export_outputs": "Ekspor keluaran", "export_payjoin_logs": "Ekspor log Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Perpanjang Sesi", "external": "Eksternal", "external_wallet": "Dompet eksternal", @@ -494,6 +493,7 @@ "gas_price": "Harga gas", "general": "Umum", "generate_name": "Buat Nama", + "generating_csv": "Generating CSV...", "generating_gift_card": "Sedang Membuat Kartu Hadiah", "generating_transaction": "Membuat transaksi", "get_a": "Dapatkan ", @@ -738,6 +738,22 @@ "payments": "Pembayaran", "pending": " (tertunda)", "percentageOf": "dari ${amount}", + "picker_chip_all": "Semua", + "picker_no_matches": "Tidak ada kecocokan", + "picker_section_all_assets": "Semua Aset (A-Z)", + "picker_section_all_currencies": "Semua Mata Uang", + "picker_section_crypto": "kripto", + "picker_section_cryptocurrencies": "Mata uang kripto", + "picker_section_gas_token": "Token Gas", + "picker_section_more_cryptocurrencies": "Lebih Banyak Cryptocurrency", + "picker_section_popular": "Populer", + "picker_section_recents": "Terbaru", + "picker_section_selected": "Terpilih", + "picker_section_stablecoins": "Stablecoin", + "picker_section_tokenized_stocks": "Saham yang Diberi Token (xStocks)", + "picker_section_tokens_standard": "Token (${standard})", + "picker_see_all": "Lihat semuanya", + "picker_show_less": "Tampilkan lebih sedikit", "pin_at_top": "Sematkan ${token} di atas", "pin_is_incorrect": "PIN tidak benar", "pin_number": "Nomor PIN", @@ -929,12 +945,16 @@ "select_a_wallet": "Pilih dompet", "select_address_to_copy": "Pilih Alamat untuk Disalin", "select_all": "Pilih semua", + "select_asset": "Pilih Aset", "select_backup_file": "Pilih file cadangan", "select_buy_provider_notice": "Pilih penyedia beli di atas. Anda dapat melewati layar ini dengan mengatur penyedia beli default Anda di pengaturan aplikasi.", "select_destination": "Silakan pilih lokasi tujuan untuk file cadangan.", + "select_fiat_currency_title": "Pilih Mata Uang", "select_hw_account_below": "Silakan pilih akun yang akan dipulihkan di bawah ini:", "select_manufacturer_title": "Pilih Produsen", "select_network": "Pilih Jaringan", + "select_network_subtitle": "Aset ini ada di beberapa jaringan. Pilih salah satu yang ingin Anda gunakan", + "select_network_title": "Pilih Jaringan", "select_other_wallet": "Pilih Wallet lain", "select_receiver": "Pilih Penerima", "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia jual default Anda di pengaturan aplikasi.", @@ -1093,7 +1113,7 @@ "swipe_to_send": "Geser untuk mengirim", "switch_wallet": "Ganti Wallet", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", - "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan WalletConnect dan coba lagi (${chains}).", "symbol": "Simbol", "sync_all_wallets": "Sinkronkan semua dompet", "sync_attempting": "Mencoba menyinkronkan", @@ -1397,4 +1417,4 @@ "zcash_card_missing_funds": "Dana hilang?", "zcash_card_scan": "Pindai", "zcash_card_warning": "Jangan tutup aplikasi sampai prosedur selesai. Jika Anda melakukannya, proses ini harus dimulai ulang dari awal." -} +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 8c0c9a1aa..f2349d14f 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Creazione di un nuovo portafoglio", "creating_new_wallet_error": "Errore: ${description}", "creation_date": "Data di creazione", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Scambio in corso", "current_wallet": "Portafoglio corrente", "custom": "Personalizzato", @@ -450,14 +451,12 @@ "expires": "Scade", "expiresOn": "Scade il", "expiry_and_validity": "Scadenza e validità", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Esporta backup", "export_csv": "Export CSV", "export_lightning_logs": "Esporta i log di Lightning", "export_logs": "Esporta registri", "export_outputs": "Esporta output", "export_payjoin_logs": "Esporta i log Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Estendi la sessione", "external": "Esterno", "external_wallet": "Portafoglio esterno", @@ -494,6 +493,7 @@ "gas_price": "Prezzo del gas", "general": "Generale", "generate_name": "Genera nome", + "generating_csv": "Generating CSV...", "generating_gift_card": "Generazione della carta regalo", "generating_transaction": "Generazione della transazione", "get_a": "Ottieni un ", @@ -737,6 +737,22 @@ "payments": "Pagamenti", "pending": " (in sospeso)", "percentageOf": "di ${amount}", + "picker_chip_all": "Tutto", + "picker_no_matches": "Nessuna corrispondenza", + "picker_section_all_assets": "Tutte le risorse (A-Z)", + "picker_section_all_currencies": "Tutte le valute", + "picker_section_crypto": "Criptovaluta", + "picker_section_cryptocurrencies": "Criptovalute", + "picker_section_gas_token": "Gettone del gas", + "picker_section_more_cryptocurrencies": "Altre criptovalute", + "picker_section_popular": "Popolare", + "picker_section_recents": "Recenti", + "picker_section_selected": "Selezionato", + "picker_section_stablecoins": "Stablecoin", + "picker_section_tokenized_stocks": "Azioni tokenizzate (xStocks)", + "picker_section_tokens_standard": "Gettoni (${standard})", + "picker_see_all": "Vedi tutto", + "picker_show_less": "Mostra meno", "pin_at_top": "Fissa ${token} in alto", "pin_is_incorrect": "Il PIN non è corretto", "pin_number": "Numero PIN", @@ -926,12 +942,16 @@ "select_a_wallet": "Seleziona un wallet", "select_address_to_copy": "Seleziona l'indirizzo da copiare", "select_all": "Seleziona tutto", + "select_asset": "Seleziona Risorsa", "select_backup_file": "Seleziona il file di backup", "select_buy_provider_notice": "Seleziona un provider di acquisto qui sopra. Puoi saltare questa schermata impostando il provider di acquisto predefinito nelle impostazioni dell'app.", "select_destination": "Seleziona la destinazione per il file di backup.", + "select_fiat_currency_title": "Seleziona Valuta", "select_hw_account_below": "Seleziona l'account da ripristinare qui sotto:", "select_manufacturer_title": "Seleziona produttore", "select_network": "Seleziona rete", + "select_network_subtitle": "Questa risorsa è presente in più reti. Seleziona quello che desideri utilizzare", + "select_network_title": "Seleziona Rete", "select_other_wallet": "Seleziona un altro Wallet", "select_receiver": "Seleziona destinatario", "select_sell_provider_notice": "Seleziona un provider di vendita qui sopra. Puoi saltare questa schermata impostando il provider di vendita predefinito nelle impostazioni dell'app.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "Scorri per inviare", "switch_wallet": "Cambia wallet", "switchToETHWallet": "Passa a un wallet Ethereum e riprova", - "switchToEVMCompatibleWallet": "Passa a un wallet compatibile con EVM e riprova (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Passa a un portafoglio compatibile con WalletConnect e riprova (${chains}).", "symbol": "Simbolo", "sync_all_wallets": "Sincronizza tutti i wallet", "sync_attempting": "Sincronizzazione in corso", @@ -1396,4 +1416,4 @@ "zcash_card_missing_funds": "Fondi mancanti?", "zcash_card_scan": "Scansiona", "zcash_card_warning": "Non chiudere l'app finché la procedura non è completata, altrimenti sarà necessario riavviare il processo da zero." -} +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3cae50928..97af836b3 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "新しいウォレットを作成中", "creating_new_wallet_error": "エラー: ${description}", "creation_date": "作成日", + "csv_nothing_to_export": "Nothing to export", "current_swap": "現在のスワップ", "current_wallet": "現在のウォレット", "custom": "カスタム", @@ -450,14 +451,12 @@ "expires": "有効期限", "expiresOn": "有効期限", "expiry_and_validity": "有効期限と有効性", - "csv_nothing_to_export": "Nothing to export", "export_backup": "バックアップをエクスポート", "export_csv": "Export CSV", "export_lightning_logs": "Lightningログをエクスポート", "export_logs": "ログをエクスポート", "export_outputs": "アウトプットをエクスポート", "export_payjoin_logs": "Payjoinログをエクスポート", - "generating_csv": "Generating CSV...", "extend_session": "セッションを延長", "external": "外部", "external_wallet": "外部ウォレット", @@ -495,6 +494,7 @@ "general": "一般", "generate_name": "名前を生成", "generated_gift_card": "ギフトカードの生成", + "generating_csv": "Generating CSV...", "generating_gift_card": "ギフトカードを生成中", "generating_transaction": "トランザクションを生成中", "get_a": "入手する ", @@ -737,6 +737,22 @@ "payments": "支払い", "pending": " (保留中)", "percentageOf": "${amount}の", + "picker_chip_all": "全て", + "picker_no_matches": "一致しません", + "picker_section_all_assets": "すべてのアセット (A ~ Z)", + "picker_section_all_currencies": "すべての通貨", + "picker_section_crypto": "暗号", + "picker_section_cryptocurrencies": "暗号通貨", + "picker_section_gas_token": "ガストークン", + "picker_section_more_cryptocurrencies": "より多くの暗号通貨", + "picker_section_popular": "人気のある", + "picker_section_recents": "最近", + "picker_section_selected": "選択済み", + "picker_section_stablecoins": "ステーブルコイン", + "picker_section_tokenized_stocks": "トークン化された株式 (xStocks)", + "picker_section_tokens_standard": "トークン (${standard})", + "picker_see_all": "全て見る", + "picker_show_less": "表示を少なくする", "pin_at_top": "${token} を上部にピン留め", "pin_is_incorrect": "PINが正しくありません", "pin_number": "PIN番号", @@ -926,12 +942,16 @@ "select_a_wallet": "ウォレットを選択", "select_address_to_copy": "コピーするアドレスを選択", "select_all": "すべて選択", + "select_asset": "アセットの選択", "select_backup_file": "バックアップファイルを選択", "select_buy_provider_notice": "上の購入プロバイダーを選択してください。アプリ設定でデフォルトの購入プロバイダーを設定すると、この画面をスキップできます。", "select_destination": "バックアップファイルの保存先を選択してください。", + "select_fiat_currency_title": "通貨の選択", "select_hw_account_below": "以下から復元するアカウントを選択してください:", "select_manufacturer_title": "メーカーを選択", "select_network": "ネットワークを選択", + "select_network_subtitle": "この資産は複数のネットワークに存在します。使用したいものを選択してください", + "select_network_title": "ネットワークの選択", "select_other_wallet": "他のウォレットを選択", "select_receiver": "受信者を選択", "select_sell_provider_notice": "上記の売却プロバイダーを選択してください。アプリの設定でデフォルトの売却プロバイダーを設定すると、この画面をスキップできます。", @@ -1090,7 +1110,7 @@ "swipe_to_send": "スワイプして送信", "switch_wallet": "ウォレットを切り替える", "switchToETHWallet": "Ethereumウォレットに切り替えて、もう一度お試しください", - "switchToEVMCompatibleWallet": "EVM互換ウォレットに切り替えて、もう一度お試しください(Ethereum、Polygon)", + "switchToWCCompatibleWallet": "WalletConnect と互換性のあるウォレットに切り替えて、もう一度お試しください (${chains})。", "symbol": "シンボル", "sync_all_wallets": "すべてのウォレットを同期", "sync_attempting": "同期を試みています", @@ -1394,4 +1414,4 @@ "zcash_card_missing_funds": "資金が見当たりませんか?", "zcash_card_scan": "スキャン", "zcash_card_warning": "手順が完了するまでアプリを閉じないでください。閉じると、このプロセスを最初からやり直す必要があります。" -} +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 1975e9a90..54df24f7b 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "새 지갑 생성 중", "creating_new_wallet_error": "오류: ${description}", "creation_date": "생성일", + "csv_nothing_to_export": "Nothing to export", "current_swap": "현재 스왑", "current_wallet": "현재 지갑", "custom": "사용자 지정", @@ -450,14 +451,12 @@ "expires": "만료됨", "expiresOn": "만료일", "expiry_and_validity": "만료 및 유효 기간", - "csv_nothing_to_export": "Nothing to export", "export_backup": "백업 내보내기", "export_csv": "Export CSV", "export_lightning_logs": "Lightning 로그 내보내기", "export_logs": "로그 내보내기", "export_outputs": "출력 내보내기", "export_payjoin_logs": "Payjoin 로그 내보내기", - "generating_csv": "Generating CSV...", "extend_session": "세션 연장", "external": "외부", "external_wallet": "외부 지갑", @@ -494,6 +493,7 @@ "gas_price": "가스 가격", "general": "일반", "generate_name": "이름 생성", + "generating_csv": "Generating CSV...", "generating_gift_card": "기프트 카드 생성 중", "generating_transaction": "트랜잭션 생성 중", "get_a": "받기 ", @@ -737,6 +737,22 @@ "payments": "결제", "pending": " (보류 중)", "percentageOf": "${amount}의", + "picker_chip_all": "모두", + "picker_no_matches": "일치하는 항목 없음", + "picker_section_all_assets": "모든 자산(A-Z)", + "picker_section_all_currencies": "모든 통화", + "picker_section_crypto": "암호화폐", + "picker_section_cryptocurrencies": "암호화폐", + "picker_section_gas_token": "가스 토큰", + "picker_section_more_cryptocurrencies": "더 많은 암호화폐", + "picker_section_popular": "인기 있는", + "picker_section_recents": "최근", + "picker_section_selected": "선택된", + "picker_section_stablecoins": "스테이블코인", + "picker_section_tokenized_stocks": "토큰화된 주식(xStocks)", + "picker_section_tokens_standard": "토큰(${standard})", + "picker_see_all": "모두 보기", + "picker_show_less": "간략히 보기", "pin_at_top": "${token}을(를) 상단에 고정", "pin_is_incorrect": "PIN이 올바르지 않습니다", "pin_number": "PIN 번호", @@ -926,12 +942,16 @@ "select_a_wallet": "지갑 선택", "select_address_to_copy": "복사할 주소를 선택하세요", "select_all": "모두 선택", + "select_asset": "자산 선택", "select_backup_file": "백업 파일 선택", "select_buy_provider_notice": "위에서 구매 제공업체를 선택하세요. 앱 설정에서 기본 구매 제공업체를 설정하면 이 화면을 건너뛸 수 있습니다.", "select_destination": "백업 파일의 저장 위치를 선택해 주세요.", + "select_fiat_currency_title": "통화 선택", "select_hw_account_below": "아래에서 복구할 계정을 선택해 주세요:", "select_manufacturer_title": "제조업체 선택", "select_network": "네트워크 선택", + "select_network_subtitle": "이 자산은 여러 네트워크에 존재합니다. 사용하고 싶은 것을 선택하세요", + "select_network_title": "네트워크 선택", "select_other_wallet": "다른 Wallet 선택", "select_receiver": "수신자 선택", "select_sell_provider_notice": "위에서 판매 제공업체를 선택하세요. 앱 설정에서 기본 판매 제공업체를 설정하면 이 화면을 건너뛸 수 있습니다.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "밀어서 보내기", "switch_wallet": "지갑 전환", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도하세요", - "switchToEVMCompatibleWallet": "EVM 호환 지갑(Ethereum, Polygon)으로 전환한 후 다시 시도하세요", + "switchToWCCompatibleWallet": "WalletConnect 호환 지갑으로 전환한 후 다시 시도하세요(${chains}).", "symbol": "심볼", "sync_all_wallets": "모든 지갑 동기화", "sync_attempting": "동기화를 시도하는 중", @@ -1394,4 +1414,4 @@ "zcash_card_missing_funds": "자금이 사라졌나요?", "zcash_card_scan": "스캔", "zcash_card_warning": "절차가 완료될 때까지 앱을 닫지 마십시오. 닫으면 이 과정을 처음부터 다시 시작해야 합니다." -} +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 6a6584c4c..93b4cc856 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "ပိုက်ဆံအိတ်အသစ် ဖန်တီးနေသည်", "creating_new_wallet_error": "အမှား: ${description}", "creation_date": "ဖန်တီးသည့်နေ့စွဲ", + "csv_nothing_to_export": "Nothing to export", "current_swap": "လက်ရှိ Swap", "current_wallet": "လက်ရှိ Wallet", "custom": "စိတ်ကြိုက်", @@ -450,14 +451,12 @@ "expires": "သက်တမ်းကုန်ဆုံးသည်", "expiresOn": "သက်တမ်းကုန်ဆုံးမည့်ရက်", "expiry_and_validity": "သက်တမ်းကုန်ဆုံးရက်နှင့် အကျုံးဝင်မှု", - "csv_nothing_to_export": "Nothing to export", "export_backup": "အရန်ကူးကို ထုတ်ယူရန်", "export_csv": "Export CSV", "export_lightning_logs": "Lightning မှတ်တမ်းများကို ထုတ်ယူပါ", "export_logs": "မှတ်တမ်းများကို ထုတ်ယူရန်", "export_outputs": "Outputs များကို ထုတ်ယူရန်", "export_payjoin_logs": "Payjoin မှတ်တမ်းများကို တင်ပို့ပါ", - "generating_csv": "Generating CSV...", "extend_session": "စက်ရှင် သက်တမ်းတိုးရန်", "external": "ပြင်ပ", "external_wallet": "ပြင်ပ Wallet", @@ -494,6 +493,7 @@ "gas_price": "ဂတ်စ်စျေးနှုန်း", "general": "အထွေထွေ", "generate_name": "အမည်ထုတ်ပေးပါ", + "generating_csv": "Generating CSV...", "generating_gift_card": "လက်ဆောင်ကတ် ထုတ်လုပ်နေသည်", "generating_transaction": "ငွေလွှဲပြောင်းမှုကို ဖန်တီးနေသည်", "get_a": "ရယူပါ ", @@ -736,6 +736,22 @@ "payments": "ပေးချေမှုများ", "pending": " (စောင့်ဆိုင်းဆဲ)", "percentageOf": "${amount} ၏", + "picker_chip_all": "အားလုံး", + "picker_no_matches": "တိုက်ဆိုင်မှု မရှိပါ။", + "picker_section_all_assets": "ပိုင်ဆိုင်မှုအားလုံး (A-Z)", + "picker_section_all_currencies": "ငွေကြေးအားလုံး", + "picker_section_crypto": "Crypto", + "picker_section_cryptocurrencies": "Cryptocurrencies", + "picker_section_gas_token": "ဓာတ်ငွေ့တိုကင်", + "picker_section_more_cryptocurrencies": "နောက်ထပ် Cryptocurrencies", + "picker_section_popular": "လူကြိုက်များသည်။", + "picker_section_recents": "မကြာမှီ", + "picker_section_selected": "ရွေးချယ်ခဲ့သည်။", + "picker_section_stablecoins": "Stablecoins", + "picker_section_tokenized_stocks": "Tokenized Stocks (xStocks)", + "picker_section_tokens_standard": "တိုကင်များ (${standard})", + "picker_see_all": "အားလုံးကြည့်", + "picker_show_less": "လျှော့ပြပါ။", "pin_at_top": "${token} ကို အပေါ်ဆုံးတွင် ပင်ထိုးပါ", "pin_is_incorrect": "PIN မမှန်ပါ။", "pin_number": "PIN နံပါတ်", @@ -925,12 +941,16 @@ "select_a_wallet": "ပိုက်ဆံအိတ်ကို ရွေးပါ", "select_address_to_copy": "ကူးယူရန် လိပ်စာကို ရွေးချယ်ပါ", "select_all": "အားလုံးကို ရွေးချယ်ပါ", + "select_asset": "ပိုင်ဆိုင်မှုကို ရွေးပါ။", "select_backup_file": "အရန်ကူးဖိုင်ကို ရွေးပါ", "select_buy_provider_notice": "အပေါ်တွင်ရှိသော ဝယ်ယူမှု ပံ့ပိုးသူကို ရွေးချယ်ပါ။ App settings တွင် သင့်မူလ ဝယ်ယူမှု ပံ့ပိုးသူကို သတ်မှတ်ထားခြင်းဖြင့် ဤစခရင်ကို ကျော်သွားနိုင်သည်။", "select_destination": "အရန်ကူးဖိုင်အတွက် သိမ်းဆည်းမည့်နေရာကို ရွေးချယ်ပါ။", + "select_fiat_currency_title": "ငွေကြေးကို ရွေးပါ။", "select_hw_account_below": "အောက်တွင် ပြန်လည်ရယူရန် မည်သည့်အကောင့်ကို ရွေးချယ်မည်ကို ကျေးဇူးပြု၍ ရွေးပါ။", "select_manufacturer_title": "ထုတ်လုပ်သူကို ရွေးချယ်ပါ", "select_network": "ကွန်ရက်ကို ရွေးချယ်ပါ", + "select_network_subtitle": "ဤပိုင်ဆိုင်မှုသည် ကွန်ရက်များစွာတွင် ရှိနေသည်။ သင်အသုံးပြုလိုသောတစ်ခုကို ရွေးပါ။", + "select_network_title": "Network ကို ရွေးပါ။", "select_other_wallet": "အခြား Wallet ကို ရွေးချယ်ပါ", "select_receiver": "လက်ခံသူကို ရွေးချယ်ပါ", "select_sell_provider_notice": "အထက်တွင်ရှိသော အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏ မူလ အရောင်းဝန်ဆောင်မှုပေးသူကို သတ်မှတ်ထားခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။", @@ -1089,7 +1109,7 @@ "swipe_to_send": "ပို့ရန် ပွတ်ဆွဲပါ", "switch_wallet": "ပိုက်ဆံအိတ် ပြောင်းရန်", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်မံကြိုးစားကြည့်ပါ။", - "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM နှင့် တွဲဖက်အသုံးပြုနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်မံကြိုးစားကြည့်ပါ (Ethereum၊ Polygon)", + "switchToWCCompatibleWallet": "ကျေးဇူးပြု၍ WalletConnect တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (${chains})။", "symbol": "သင်္ကေတ", "sync_all_wallets": "ပိုက်ဆံအိတ်အားလုံးကို စင့်ခ်လုပ်ရန်", "sync_attempting": "ထပ်တူပြုလုပ်ရန် ကြိုးစားနေသည်", @@ -1393,4 +1413,4 @@ "zcash_card_missing_funds": "ငွေကြေး ပျောက်ဆုံးနေပါသလား?", "zcash_card_scan": "စကင်", "zcash_card_warning": "လုပ်ငန်းစဉ် ပြီးဆုံးသည်အထိ အက်ပ်ကို မပိတ်ပါနှင့်။ ပိတ်လိုက်ပါက ဤလုပ်ငန်းစဉ်ကို အစမှ ပြန်လည်စတင်ရမည်ဖြစ်သည်။" -} +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 6919aa5de..80a37a412 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -275,6 +275,7 @@ "creating_new_wallet": "Nieuwe wallet aanmaken", "creating_new_wallet_error": "Fout: ${description}", "creation_date": "Aanmaakdatum", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Huidige swap", "current_wallet": "Huidige wallet", "custom": "Aangepast", @@ -448,14 +449,12 @@ "expires": "Verloopt", "expiresOn": "Verloopt op", "expiry_and_validity": "Vervaldatum en geldigheid", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Back-up exporteren", "export_csv": "Export CSV", "export_lightning_logs": "Lightning-logboeken exporteren", "export_logs": "Exporteer logboeken", "export_outputs": "Outputs exporteren", "export_payjoin_logs": "Payjoin-logboeken exporteren", - "generating_csv": "Generating CSV...", "extend_session": "Sessie verlengen", "external": "Extern", "external_wallet": "Externe wallet", @@ -492,6 +491,7 @@ "gas_price": "Gasprijs", "general": "Algemeen", "generate_name": "Naam genereren", + "generating_csv": "Generating CSV...", "generating_gift_card": "Cadeaubon genereren", "generating_transaction": "Transactie genereren", "get_a": "Krijg een ", @@ -733,6 +733,22 @@ "payments": "Betalingen", "pending": " (in behandeling)", "percentageOf": "van ${amount}", + "picker_chip_all": "Alle", + "picker_no_matches": "Geen overeenkomsten", + "picker_section_all_assets": "Alle activa (A-Z)", + "picker_section_all_currencies": "Alle valuta's", + "picker_section_crypto": "Crypto", + "picker_section_cryptocurrencies": "Cryptocurrencies", + "picker_section_gas_token": "Gas-token", + "picker_section_more_cryptocurrencies": "Meer cryptocurrencies", + "picker_section_popular": "Populair", + "picker_section_recents": "Recent", + "picker_section_selected": "Gekozen", + "picker_section_stablecoins": "Stabiele munten", + "picker_section_tokenized_stocks": "Tokenized aandelen (xStocks)", + "picker_section_tokens_standard": "Tokens (${standard})", + "picker_see_all": "Bekijk alles", + "picker_show_less": "Laat minder zien", "pin_at_top": "Zet ${token} bovenaan vast", "pin_is_incorrect": "PIN is onjuist", "pin_number": "PIN-nummer", @@ -922,12 +938,16 @@ "select_a_wallet": "Selecteer een wallet", "select_address_to_copy": "Selecteer adres om te kopiëren", "select_all": "Alles selecteren", + "select_asset": "Selecteer Activa", "select_backup_file": "Selecteer een back-upbestand", "select_buy_provider_notice": "Selecteer hierboven een koopprovider. Je kunt dit scherm overslaan door je standaard koopprovider in te stellen in app-instellingen.", "select_destination": "Selecteer de bestemming voor het back-upbestand.", + "select_fiat_currency_title": "Selecteer Valuta", "select_hw_account_below": "Selecteer hieronder welk account je wilt herstellen:", "select_manufacturer_title": "Selecteer fabrikant", "select_network": "Selecteer Netwerk", + "select_network_subtitle": "Deze asset is aanwezig in meerdere netwerken. Selecteer degene die u wilt gebruiken", + "select_network_title": "Selecteer Netwerk", "select_other_wallet": "Selecteer een andere wallet", "select_receiver": "Selecteer ontvanger", "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. Je kunt dit scherm overslaan door je standaardverkoopprovider in te stellen in de app-instellingen.", @@ -1086,7 +1106,7 @@ "swipe_to_send": "Swipe om te verzenden", "switch_wallet": "Wissel van wallet", "switchToETHWallet": "Schakel over naar een Ethereum-wallet en probeer het opnieuw", - "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele wallet en probeer het opnieuw (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Schakel over naar een WalletConnect-compatibele portemonnee en probeer het opnieuw (${chains}).", "symbol": "Symbool", "sync_all_wallets": "Alle wallets synchroniseren", "sync_attempting": "Bezig met synchroniseren", @@ -1391,4 +1411,4 @@ "zcash_card_missing_funds": "Fondsen ontbreken?", "zcash_card_scan": "Scannen", "zcash_card_warning": "Sluit de app niet voordat de procedure is voltooid. Als je dit wel doet, moet dit proces helemaal opnieuw worden gestart." -} +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 1404187bb..5719de701 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Tworzenie nowego portfela", "creating_new_wallet_error": "Błąd: ${description}", "creation_date": "Data utworzenia", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Bieżący swap", "current_wallet": "Bieżący portfel", "custom": "Niestandardowy", @@ -449,14 +450,12 @@ "expires": "Wygasa", "expiresOn": "Wygasa", "expiry_and_validity": "Termin ważności i ważność", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Eksportuj kopię zapasową", "export_csv": "Export CSV", "export_lightning_logs": "Eksportuj logi Lightning", "export_logs": "Eksportuj logi", "export_outputs": "Eksportuj wyjścia", "export_payjoin_logs": "Eksportuj logi Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Przedłuż sesję", "external": "Zewnętrzny", "external_wallet": "Zewnętrzny portfel", @@ -493,6 +492,7 @@ "gas_price": "Cena gas", "general": "Ogólne", "generate_name": "Wygeneruj nazwę", + "generating_csv": "Generating CSV...", "generating_gift_card": "Generowanie karty podarunkowej", "generating_transaction": "Generowanie transakcji", "get_a": "Uzyskaj ", @@ -735,6 +735,22 @@ "payments": "Płatności", "pending": " (w toku)", "percentageOf": "z ${amount}", + "picker_chip_all": "Wszystko", + "picker_no_matches": "Brak dopasowań", + "picker_section_all_assets": "Wszystkie zasoby (A-Z)", + "picker_section_all_currencies": "Wszystkie waluty", + "picker_section_crypto": "Krypto", + "picker_section_cryptocurrencies": "Kryptowaluty", + "picker_section_gas_token": "Żeton gazu", + "picker_section_more_cryptocurrencies": "Więcej kryptowalut", + "picker_section_popular": "Popularny", + "picker_section_recents": "Najnowsze", + "picker_section_selected": "Wybrany", + "picker_section_stablecoins": "Stablecoiny", + "picker_section_tokenized_stocks": "Tokenizowane akcje (xStocks)", + "picker_section_tokens_standard": "Tokeny (${standard})", + "picker_see_all": "Zobacz wszystko", + "picker_show_less": "Pokaż mniej", "pin_at_top": "Przypnij ${token} na górze", "pin_is_incorrect": "PIN jest nieprawidłowy", "pin_number": "Numer PIN", @@ -924,12 +940,16 @@ "select_a_wallet": "Wybierz portfel", "select_address_to_copy": "Wybierz adres do skopiowania", "select_all": "Zaznacz wszystko", + "select_asset": "Wybierz Zasób", "select_backup_file": "Wybierz plik kopii zapasowej", "select_buy_provider_notice": "Wybierz powyżej dostawcę zakupu. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę zakupu w ustawieniach aplikacji.", "select_destination": "Wybierz miejsce docelowe dla pliku kopii zapasowej.", + "select_fiat_currency_title": "Wybierz Waluta", "select_hw_account_below": "Wybierz poniżej konto do przywrócenia:", "select_manufacturer_title": "Wybierz producenta", "select_network": "Wybierz sieć", + "select_network_subtitle": "Ten zasób jest obecny w wielu sieciach. Wybierz ten, którego chcesz użyć", + "select_network_title": "Wybierz opcję Sieć", "select_other_wallet": "Wybierz inny portfel", "select_receiver": "Wybierz odbiorcę", "select_sell_provider_notice": "Wybierz powyżej dostawcę sprzedaży. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.", @@ -1088,7 +1108,7 @@ "swipe_to_send": "Przesuń, aby wysłać", "switch_wallet": "Przełącz portfel", "switchToETHWallet": "Przełącz się na portfel Ethereum i spróbuj ponownie", - "switchToEVMCompatibleWallet": "Przełącz się na portfel kompatybilny z EVM i spróbuj ponownie (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Przełącz się na portfel zgodny z WalletConnect i spróbuj ponownie (${chains}).", "symbol": "Symbol", "sync_all_wallets": "Synchronizuj wszystkie portfele", "sync_attempting": "Trwa synchronizacja", @@ -1392,4 +1412,4 @@ "zcash_card_missing_funds": "Brakuje środków?", "zcash_card_scan": "Skanuj", "zcash_card_warning": "Nie zamykaj aplikacji do czasu zakończenia procedury. Jeśli to zrobisz, proces będzie musiał rozpocząć się od nowa." -} +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index a594749f8..17684190c 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Criando nova carteira", "creating_new_wallet_error": "Erro: ${description}", "creation_date": "Data de criação", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Troca atual", "current_wallet": "Carteira atual", "custom": "Personalizado", @@ -450,14 +451,12 @@ "expires": "Expira", "expiresOn": "Expira em", "expiry_and_validity": "Expiração e validade", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Exportar backup", "export_csv": "Export CSV", "export_lightning_logs": "Exportar logs do Lightning", "export_logs": "Exportar logs", "export_outputs": "Exportar saídas", "export_payjoin_logs": "Exportar logs do Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Estender sessão", "external": "Externo", "external_wallet": "Carteira externa", @@ -494,6 +493,7 @@ "gas_price": "Preço do gas", "general": "Geral", "generate_name": "Gerar Nome", + "generating_csv": "Generating CSV...", "generating_gift_card": "Gerando cartão-presente", "generating_transaction": "Gerando transação", "get_a": "Obter um ", @@ -738,6 +738,22 @@ "payments": "Pagamentos", "pending": " (pendente)", "percentageOf": "de ${amount}", + "picker_chip_all": "Todos", + "picker_no_matches": "Nenhuma correspondência", + "picker_section_all_assets": "Todos os ativos (A-Z)", + "picker_section_all_currencies": "Todas as moedas", + "picker_section_crypto": "Criptografia", + "picker_section_cryptocurrencies": "Criptomoedas", + "picker_section_gas_token": "Token de Gás", + "picker_section_more_cryptocurrencies": "Mais criptomoedas", + "picker_section_popular": "Popular", + "picker_section_recents": "Recentes", + "picker_section_selected": "Selecionado", + "picker_section_stablecoins": "Moedas estáveis", + "picker_section_tokenized_stocks": "Ações tokenizadas (xStocks)", + "picker_section_tokens_standard": "Tokens (${standard})", + "picker_see_all": "Ver tudo", + "picker_show_less": "Mostrar menos", "pin_at_top": "Fixar ${token} no topo", "pin_is_incorrect": "O PIN está incorreto", "pin_number": "Número do PIN", @@ -927,12 +943,16 @@ "select_a_wallet": "Selecione uma carteira", "select_address_to_copy": "Selecione o endereço para copiar", "select_all": "Selecionar tudo", + "select_asset": "Selecione Ativo", "select_backup_file": "Selecionar arquivo de backup", "select_buy_provider_notice": "Selecione um provedor de compra acima. Você pode pular esta tela definindo seu provedor de compra padrão nas configurações do app.", "select_destination": "Selecione o destino para o arquivo de backup.", + "select_fiat_currency_title": "Selecione a moeda", "select_hw_account_below": "Selecione abaixo qual conta restaurar:", "select_manufacturer_title": "Selecionar fabricante", "select_network": "Selecionar rede", + "select_network_subtitle": "Este ativo está presente em múltiplas redes. Selecione aquele que você deseja usar", + "select_network_title": "Selecione Rede", "select_other_wallet": "Selecionar outra carteira", "select_receiver": "Selecionar destinatário", "select_sell_provider_notice": "Selecione um provedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.", @@ -1091,7 +1111,7 @@ "swipe_to_send": "Deslize para enviar", "switch_wallet": "Alternar carteira", "switchToETHWallet": "Por favor, mude para uma carteira Ethereum e tente novamente", - "switchToEVMCompatibleWallet": "Por favor, mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Mude para uma carteira compatível com WalletConnect e tente novamente (${chains}).", "symbol": "Símbolo", "sync_all_wallets": "Sincronizar todas as carteiras", "sync_attempting": "Tentando sincronizar", @@ -1396,4 +1416,4 @@ "zcash_card_missing_funds": "Fundos em falta?", "zcash_card_scan": "Escanear", "zcash_card_warning": "Não feche o aplicativo até que o procedimento seja concluído; se você fizer isso, esse processo precisará ser reiniciado do zero." -} +} \ No newline at end of file diff --git a/res/values/strings_pt_BR.arb b/res/values/strings_pt_BR.arb index 7faa03a42..fe41b7ab8 100644 --- a/res/values/strings_pt_BR.arb +++ b/res/values/strings_pt_BR.arb @@ -732,6 +732,11 @@ "payments": "Pagamentos", "pending": " (pendente)", "percentageOf": "de ${amount}", + "picker_section_crypto": "Cripto", + "picker_section_more_cryptocurrencies": "Mais criptomoedas", + "picker_section_tokens_standard": "Tokens (${standard})", + "picker_see_all": "Ver tudo", + "picker_show_less": "Mostrar menos", "pin_at_top": "Fixar ${token} no topo", "pin_is_incorrect": "O PIN está incorreto", "pin_number": "Número do PIN", @@ -1085,7 +1090,7 @@ "swipe_to_send": "Deslize para enviar", "switch_wallet": "Alternar carteira", "switchToETHWallet": "Por favor, mude para uma carteira Ethereum e tente novamente", - "switchToEVMCompatibleWallet": "Por favor, mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Mude para uma carteira compatível com WalletConnect e tente novamente (${chains}).", "symbol": "Símbolo", "sync_all_wallets": "Sincronizar todas as carteiras", "sync_attempting": "Tentando sincronizar", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 577256929..b3541bc35 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Создание нового кошелька", "creating_new_wallet_error": "Ошибка: ${description}", "creation_date": "Дата создания", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Текущий обмен", "current_wallet": "Текущий кошелёк", "custom": "Пользовательский", @@ -450,14 +451,12 @@ "expires": "Истекает", "expiresOn": "Истекает", "expiry_and_validity": "Срок действия и действительность", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Экспорт резервной копии", "export_csv": "Export CSV", "export_lightning_logs": "Экспорт логов Lightning", "export_logs": "Экспорт журналов", "export_outputs": "Экспорт выходов", "export_payjoin_logs": "Экспорт журналов Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Продлить сессию", "external": "Внешний", "external_wallet": "Внешний кошелёк", @@ -494,6 +493,7 @@ "gas_price": "Цена газа", "general": "Общие", "generate_name": "Сгенерировать имя", + "generating_csv": "Generating CSV...", "generating_gift_card": "Создание подарочной карты", "generating_transaction": "Генерация транзакции", "get_a": "Получить ", @@ -737,6 +737,22 @@ "payments": "Платежи", "pending": " (в ожидании)", "percentageOf": "из ${amount}", + "picker_chip_all": "Все", + "picker_no_matches": "Нет совпадений", + "picker_section_all_assets": "Все активы (А-Я)", + "picker_section_all_currencies": "Все валюты", + "picker_section_crypto": "Крипто", + "picker_section_cryptocurrencies": "Криптовалюты", + "picker_section_gas_token": "Газовый токен", + "picker_section_more_cryptocurrencies": "Больше криптовалют", + "picker_section_popular": "Популярный", + "picker_section_recents": "Недавние", + "picker_section_selected": "Выбрано", + "picker_section_stablecoins": "Стейблкоины", + "picker_section_tokenized_stocks": "Токенизированные акции (xStocks)", + "picker_section_tokens_standard": "Токены (${standard})", + "picker_see_all": "Посмотреть все", + "picker_show_less": "Показать меньше", "pin_at_top": "Закрепить ${token} сверху", "pin_is_incorrect": "PIN неверный", "pin_number": "PIN-код", @@ -926,12 +942,16 @@ "select_a_wallet": "Выберите кошелёк", "select_address_to_copy": "Выберите адрес для копирования", "select_all": "Выбрать все", + "select_asset": "Выберите актив", "select_backup_file": "Выберите файл резервной копии", "select_buy_provider_notice": "Выберите выше провайдера для покупки. Вы можете пропустить этот экран, установив провайдера покупки по умолчанию в настройках приложения.", "select_destination": "Пожалуйста, выберите место назначения для файла резервной копии.", + "select_fiat_currency_title": "Выберите валюту", "select_hw_account_below": "Пожалуйста, выберите ниже, какую учетную запись восстановить:", "select_manufacturer_title": "Выберите производителя", "select_network": "Выберите сеть", + "select_network_subtitle": "Этот актив присутствует в нескольких сетях. Выберите тот, который вы хотите использовать", + "select_network_title": "Выберите сеть", "select_other_wallet": "Выбрать другой кошелек", "select_receiver": "Выберите получателя", "select_sell_provider_notice": "Выберите провайдера для продажи выше. Вы можете пропустить этот экран, установив провайдера для продажи по умолчанию в настройках приложения.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "Проведите, чтобы отправить", "switch_wallet": "Переключить кошелёк", "switchToETHWallet": "Пожалуйста, переключитесь на кошелёк Ethereum и повторите попытку", - "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с WalletConnect, и повторите попытку (${chains}).", "symbol": "Символ", "sync_all_wallets": "Синхронизировать все кошельки", "sync_attempting": "Выполняется синхронизация", @@ -1394,4 +1414,4 @@ "zcash_card_missing_funds": "Не хватает средств?", "zcash_card_scan": "Сканировать", "zcash_card_warning": "Не закрывайте приложение до завершения процедуры. Если вы это сделаете, процесс придется перезапустить с нуля." -} +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 8829e9647..932925cd7 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "กำลังสร้างกระเป๋าเงินใหม่", "creating_new_wallet_error": "ข้อผิดพลาด: ${description}", "creation_date": "วันที่สร้าง", + "csv_nothing_to_export": "Nothing to export", "current_swap": "การสวอปปัจจุบัน", "current_wallet": "กระเป๋าเงินปัจจุบัน", "custom": "กำหนดเอง", @@ -450,14 +451,12 @@ "expires": "หมดอายุ", "expiresOn": "หมดอายุวันที่", "expiry_and_validity": "วันหมดอายุและระยะเวลาที่มีผล", - "csv_nothing_to_export": "Nothing to export", "export_backup": "ส่งออกข้อมูลสำรอง", "export_csv": "Export CSV", "export_lightning_logs": "ส่งออกล็อก Lightning", "export_logs": "ส่งออกบันทึก", "export_outputs": "ส่งออกเอาต์พุต", "export_payjoin_logs": "ส่งออกล็อก Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "ขยายเซสชัน", "external": "ภายนอก", "external_wallet": "กระเป๋าเงินภายนอก", @@ -494,6 +493,7 @@ "gas_price": "ราคา Gas", "general": "ทั่วไป", "generate_name": "สร้างชื่อ", + "generating_csv": "Generating CSV...", "generating_gift_card": "กำลังสร้างบัตรของขวัญ", "generating_transaction": "กำลังสร้างธุรกรรม", "get_a": "รับ ", @@ -736,6 +736,22 @@ "payments": "การชำระเงิน", "pending": " (รอดำเนินการ)", "percentageOf": "จาก ${amount}", + "picker_chip_all": "ทั้งหมด", + "picker_no_matches": "ไม่มีการแข่งขัน", + "picker_section_all_assets": "ทรัพย์สินทั้งหมด (A-Z)", + "picker_section_all_currencies": "สกุลเงินทั้งหมด", + "picker_section_crypto": "การเข้ารหัสลับ", + "picker_section_cryptocurrencies": "สกุลเงินดิจิทัล", + "picker_section_gas_token": "โทเค็นแก๊ส", + "picker_section_more_cryptocurrencies": "Cryptocurrencies เพิ่มเติม", + "picker_section_popular": "เป็นที่นิยม", + "picker_section_recents": "ล่าสุด", + "picker_section_selected": "เลือกแล้ว", + "picker_section_stablecoins": "Stablecoins", + "picker_section_tokenized_stocks": "หุ้นโทเค็น (xStocks)", + "picker_section_tokens_standard": "โทเค็น (${standard})", + "picker_see_all": "ดูทั้งหมด", + "picker_show_less": "แสดงน้อยลง", "pin_at_top": "ปักหมุด ${token} ไว้ด้านบน", "pin_is_incorrect": "PIN ไม่ถูกต้อง", "pin_number": "หมายเลข PIN", @@ -925,12 +941,16 @@ "select_a_wallet": "เลือกวอลเล็ต", "select_address_to_copy": "เลือกที่อยู่เพื่อคัดลอก", "select_all": "เลือกทั้งหมด", + "select_asset": "เลือกสินทรัพย์", "select_backup_file": "เลือกไฟล์สำรองข้อมูล", "select_buy_provider_notice": "เลือกผู้ให้บริการซื้อด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยตั้งค่าผู้ให้บริการซื้อเริ่มต้นในการตั้งค่าแอป", "select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรองข้อมูล", + "select_fiat_currency_title": "เลือกสกุลเงิน", "select_hw_account_below": "โปรดเลือกบัญชีที่จะกู้คืนด้านล่าง:", "select_manufacturer_title": "เลือกผู้ผลิต", "select_network": "เลือกเครือข่าย", + "select_network_subtitle": "เนื้อหานี้มีอยู่ในหลายเครือข่าย เลือกอันที่คุณต้องการใช้", + "select_network_title": "เลือกเครือข่าย", "select_other_wallet": "เลือก Wallet อื่น", "select_receiver": "เลือกผู้รับ", "select_sell_provider_notice": "เลือกผู้ให้บริการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยตั้งค่าผู้ให้บริการขายเริ่มต้นในการตั้งค่าแอป", @@ -1089,7 +1109,7 @@ "swipe_to_send": "ปัดเพื่อส่ง", "switch_wallet": "สลับกระเป๋าเงิน", "switchToETHWallet": "โปรดสลับไปยังกระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", - "switchToEVMCompatibleWallet": "โปรดสลับไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ WalletConnect แล้วลองอีกครั้ง (${chains})", "symbol": "สัญลักษณ์", "sync_all_wallets": "ซิงค์กระเป๋าเงินทั้งหมด", "sync_attempting": "กำลังพยายามซิงค์", @@ -1393,4 +1413,4 @@ "zcash_card_missing_funds": "ยอดเงินหายไป?", "zcash_card_scan": "สแกน", "zcash_card_warning": "อย่าปิดแอปจนกว่าขั้นตอนจะเสร็จสิ้น หากคุณปิดแอป กระบวนการนี้จะต้องเริ่มใหม่ตั้งแต่ต้น" -} +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e08f506e5..5422ef2dd 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Gumagawa ng bagong wallet", "creating_new_wallet_error": "Error: ${description}", "creation_date": "Petsa ng Paglikha", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Kasalukuyang Swap", "current_wallet": "Kasalukuyang wallet", "custom": "Pasadya", @@ -450,14 +451,12 @@ "expires": "Mag-e-expire", "expiresOn": "Mag-e-expire sa", "expiry_and_validity": "Pag-expire at Pagiging Balido", - "csv_nothing_to_export": "Nothing to export", "export_backup": "I-export ang backup", "export_csv": "Export CSV", "export_lightning_logs": "I-export ang mga log ng Lightning", "export_logs": "I-export ang mga log", "export_outputs": "I-export ang mga output", "export_payjoin_logs": "I-export ang mga Payjoin log", - "generating_csv": "Generating CSV...", "extend_session": "Palawigin ang session", "external": "Panlabas", "external_wallet": "Panlabas na wallet", @@ -494,6 +493,7 @@ "gas_price": "Presyo ng gas", "general": "Pangkalahatan", "generate_name": "Bumuo ng Pangalan", + "generating_csv": "Generating CSV...", "generating_gift_card": "Ginagawa ang Gift Card", "generating_transaction": "Ginagawa ang transaksyon", "get_a": "Kumuha ng ", @@ -736,6 +736,22 @@ "payments": "Mga Pagbabayad", "pending": " (nakabinbin)", "percentageOf": "ng ${amount}", + "picker_chip_all": "Lahat", + "picker_no_matches": "Walang tugma", + "picker_section_all_assets": "Lahat ng Asset (A-Z)", + "picker_section_all_currencies": "Lahat ng Pera", + "picker_section_crypto": "Crypto", + "picker_section_cryptocurrencies": "Cryptocurrencies", + "picker_section_gas_token": "Gas Token", + "picker_section_more_cryptocurrencies": "Higit pang Cryptocurrencies", + "picker_section_popular": "Sikat", + "picker_section_recents": "Recents", + "picker_section_selected": "Napili", + "picker_section_stablecoins": "Mga Stablecoin", + "picker_section_tokenized_stocks": "Mga Tokenized na Stock (xStocks)", + "picker_section_tokens_standard": "Mga Token (${standard})", + "picker_see_all": "Tingnan lahat", + "picker_show_less": "Magpakita ng mas kaunti", "pin_at_top": "I-pin ang ${token} sa itaas", "pin_is_incorrect": "Mali ang PIN", "pin_number": "Numero ng PIN", @@ -925,12 +941,16 @@ "select_a_wallet": "Pumili ng wallet", "select_address_to_copy": "Piliin ang Address na Kokopyahin", "select_all": "Piliin lahat", + "select_asset": "Piliin ang Asset", "select_backup_file": "Piliin ang backup file", "select_buy_provider_notice": "Pumili ng provider para bumili sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na provider para bumili sa mga setting ng app.", "select_destination": "Mangyaring piliin ang patutunguhan ng backup file.", + "select_fiat_currency_title": "Piliin ang Pera", "select_hw_account_below": "Mangyaring piliin sa ibaba kung aling account ang ire-restore:", "select_manufacturer_title": "Piliin ang Manufacturer", "select_network": "Pumili ng Network", + "select_network_subtitle": "Ang asset na ito ay nasa maraming network. Piliin ang gusto mong gamitin", + "select_network_title": "Piliin ang Network", "select_other_wallet": "Pumili ng iba pang Wallet", "select_receiver": "Piliin ang Tatanggap", "select_sell_provider_notice": "Pumili ng sell provider sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", @@ -1089,7 +1109,7 @@ "swipe_to_send": "I-swipe para magpadala", "switch_wallet": "Lumipat ng Wallet", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", - "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM-compatible na wallet at subukang muli (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Mangyaring lumipat sa isang WalletConnect na katugmang wallet at subukang muli (${chains}).", "symbol": "Simbolo", "sync_all_wallets": "I-sync ang lahat ng wallet", "sync_attempting": "Sinusubukang i-sync", @@ -1393,4 +1413,4 @@ "zcash_card_missing_funds": "Nawawalang pondo?", "zcash_card_scan": "I-scan", "zcash_card_warning": "Huwag isara ang app hanggang sa makumpleto ang proseso; kung gagawin mo ito, kakailanganing magsimula muli mula sa simula." -} +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index f467fd2a9..53ffe19fc 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Yeni cüzdan oluşturuluyor", "creating_new_wallet_error": "Hata: ${description}", "creation_date": "Oluşturulma Tarihi", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Mevcut Takas", "current_wallet": "Geçerli cüzdan", "custom": "Özel", @@ -450,14 +451,12 @@ "expires": "Sona erme tarihi", "expiresOn": "Şu tarihte sona erer", "expiry_and_validity": "Son Kullanma ve Geçerlilik", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Yedeklemeyi dışa aktar", "export_csv": "Export CSV", "export_lightning_logs": "Lightning günlüklerini dışa aktar", "export_logs": "Günlükleri dışa aktar", "export_outputs": "Çıktıları dışa aktar", "export_payjoin_logs": "Payjoin günlüklerini dışa aktar", - "generating_csv": "Generating CSV...", "extend_session": "Oturumu Uzat", "external": "Harici", "external_wallet": "Harici cüzdan", @@ -494,6 +493,7 @@ "gas_price": "Gas ücreti", "general": "Genel", "generate_name": "Ad Oluştur", + "generating_csv": "Generating CSV...", "generating_gift_card": "Hediye Kartı Oluşturuluyor", "generating_transaction": "İşlem oluşturuluyor", "get_a": "Bir ", @@ -736,6 +736,22 @@ "payments": "Ödemeler", "pending": " (beklemede)", "percentageOf": "${amount} tutarının", + "picker_chip_all": "Tüm", + "picker_no_matches": "Eşleşme yok", + "picker_section_all_assets": "Tüm Varlıklar (A'dan Z'ye)", + "picker_section_all_currencies": "Tüm Para Birimleri", + "picker_section_crypto": "Kripto", + "picker_section_cryptocurrencies": "Kripto para birimleri", + "picker_section_gas_token": "Gaz Jetonu", + "picker_section_more_cryptocurrencies": "Daha Fazla Kripto Para Birimi", + "picker_section_popular": "Popüler", + "picker_section_recents": "Son Kullanılanlar", + "picker_section_selected": "Seçildi", + "picker_section_stablecoins": "Stablecoin'ler", + "picker_section_tokenized_stocks": "Tokenleştirilmiş Hisse Senetleri (xStocks)", + "picker_section_tokens_standard": "Jetonlar (${standard})", + "picker_see_all": "Tümünü gör", + "picker_show_less": "Daha az göster", "pin_at_top": "${token}'ı üste sabitle", "pin_is_incorrect": "PIN yanlış", "pin_number": "PIN numarası", @@ -925,12 +941,16 @@ "select_a_wallet": "Bir cüzdan seçin", "select_address_to_copy": "Kopyalanacak Adresi Seçin", "select_all": "Tümünü seç", + "select_asset": "Varlık Seç", "select_backup_file": "Yedekleme dosyasını seç", "select_buy_provider_notice": "Yukarıdan bir satın alma sağlayıcısı seçin. Uygulama ayarlarında varsayılan satın alma sağlayıcınızı belirleyerek bu ekranı atlayabilirsiniz.", "select_destination": "Lütfen yedekleme dosyası için bir hedef seçin.", + "select_fiat_currency_title": "Para Birimi Seçin", "select_hw_account_below": "Lütfen aşağıdan geri yüklenecek hesabı seçin:", "select_manufacturer_title": "Üretici Seçin", "select_network": "Ağ Seç", + "select_network_subtitle": "Bu varlık birden fazla ağda mevcut. Kullanmak istediğinizi seçin", + "select_network_title": "Ağ Seçin", "select_other_wallet": "Başka bir Cüzdan seçin", "select_receiver": "Alıcı Seçin", "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı belirleyerek bu ekranı atlayabilirsiniz.", @@ -1089,7 +1109,7 @@ "swipe_to_send": "Göndermek için kaydırın", "switch_wallet": "Cüzdan Değiştir", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", - "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Lütfen WalletConnect uyumlu bir cüzdana geçin ve tekrar deneyin (${chains}).", "symbol": "Sembol", "sync_all_wallets": "Tüm cüzdanları senkronize et", "sync_attempting": "Senkronizasyon deneniyor", @@ -1393,4 +1413,4 @@ "zcash_card_missing_funds": "Bakiye eksik mi?", "zcash_card_scan": "Tara", "zcash_card_warning": "İşlem tamamlanana kadar uygulamayı kapatmayın; aksi takdirde bu işlemin baştan yeniden başlatılması gerekecektir." -} +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 425541d8b..1115fb88b 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Створення нового гаманця", "creating_new_wallet_error": "Помилка: ${description}", "creation_date": "Дата створення", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Поточний своп", "current_wallet": "Поточний гаманець", "custom": "Власний", @@ -450,14 +451,12 @@ "expires": "Термін дії закінчується", "expiresOn": "Дійсний до", "expiry_and_validity": "Термін дії та чинність", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Експортувати резервну копію", "export_csv": "Export CSV", "export_lightning_logs": "Експортувати логи Lightning", "export_logs": "Експорт журналів", "export_outputs": "Експорт виходів", "export_payjoin_logs": "Експорт журналів Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Подовжити сеанс", "external": "Зовнішній", "external_wallet": "Зовнішній гаманець", @@ -494,6 +493,7 @@ "gas_price": "Ціна газу", "general": "Загальні", "generate_name": "Згенерувати ім’я", + "generating_csv": "Generating CSV...", "generating_gift_card": "Генерація подарункової картки", "generating_transaction": "Створення транзакції", "get_a": "Отримати ", @@ -736,6 +736,22 @@ "payments": "Платежі", "pending": " (в очікуванні)", "percentageOf": "з ${amount}", + "picker_chip_all": "все", + "picker_no_matches": "Немає збігів", + "picker_section_all_assets": "Усі активи (A-Z)", + "picker_section_all_currencies": "Усі валюти", + "picker_section_crypto": "Крипто", + "picker_section_cryptocurrencies": "Криптовалюти", + "picker_section_gas_token": "Газ Токен", + "picker_section_more_cryptocurrencies": "Більше криптовалют", + "picker_section_popular": "Популярний", + "picker_section_recents": "Останні", + "picker_section_selected": "Вибране", + "picker_section_stablecoins": "Стайблкойни", + "picker_section_tokenized_stocks": "Токенізовані акції (xStocks)", + "picker_section_tokens_standard": "Жетони (${standard})", + "picker_see_all": "Переглянути всі", + "picker_show_less": "Показувати менше", "pin_at_top": "Закріпити ${token} зверху", "pin_is_incorrect": "PIN-код неправильний", "pin_number": "PIN-номер", @@ -926,12 +942,16 @@ "select_a_wallet": "Виберіть гаманець", "select_address_to_copy": "Виберіть адресу для копіювання", "select_all": "Вибрати все", + "select_asset": "Виберіть Актив", "select_backup_file": "Виберіть файл резервної копії", "select_buy_provider_notice": "Виберіть вище постачальника для купівлі. Ви можете пропустити цей екран, встановивши постачальника для купівлі за замовчуванням у налаштуваннях застосунку.", "select_destination": "Будь ласка, виберіть місце призначення для файлу резервної копії.", + "select_fiat_currency_title": "Виберіть Валюта", "select_hw_account_below": "Будь ласка, виберіть нижче, який обліковий запис відновити:", "select_manufacturer_title": "Виберіть виробника", "select_network": "Виберіть мережу", + "select_network_subtitle": "Цей актив присутній у кількох мережах. Виберіть той, який хочете використовувати", + "select_network_title": "Виберіть Мережа", "select_other_wallet": "Виберіть інший гаманець", "select_receiver": "Виберіть одержувача", "select_sell_provider_notice": "Виберіть вище провайдера для продажу. Ви можете пропустити цей екран, встановивши провайдера для продажу за замовчуванням у налаштуваннях застосунку.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "Проведіть, щоб надіслати", "switch_wallet": "Перемкнути гаманець", "switchToETHWallet": "Будь ласка, перемкніться на гаманець Ethereum і спробуйте ще раз", - "switchToEVMCompatibleWallet": "Будь ласка, перемкніться на гаманець, сумісний з EVM, і спробуйте ще раз (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Перейдіть на гаманець, сумісний з WalletConnect, і повторіть спробу (${chains}).", "symbol": "Символ", "sync_all_wallets": "Синхронізувати всі гаманці", "sync_attempting": "Спроба синхронізації", @@ -1394,4 +1414,4 @@ "zcash_card_missing_funds": "Зникли кошти?", "zcash_card_scan": "Сканувати", "zcash_card_warning": "Не закривайте застосунок, доки процедура не завершиться. Якщо ви це зробите, цей процес потрібно буде перезапустити з нуля." -} +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index f05214f25..551477995 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "نیا والیٹ بنایا جا رہا ہے", "creating_new_wallet_error": "خرابی: ${description}", "creation_date": "تخلیق کی تاریخ", + "csv_nothing_to_export": "Nothing to export", "current_swap": "موجودہ سواپ", "current_wallet": "موجودہ والیٹ", "custom": "حسبِ ضرورت", @@ -450,14 +451,12 @@ "expires": "میعاد ختم ہوتا ہے", "expiresOn": "میعاد ختم ہونے کی تاریخ", "expiry_and_validity": "میعادِ ختم اور درستگی", - "csv_nothing_to_export": "Nothing to export", "export_backup": "بیک اپ ایکسپورٹ کریں", "export_csv": "Export CSV", "export_lightning_logs": "لائٹننگ لاگز برآمد کریں", "export_logs": "لاگز برآمد کریں", "export_outputs": "آؤٹ پٹس ایکسپورٹ کریں", "export_payjoin_logs": "Payjoin لاگز ایکسپورٹ کریں", - "generating_csv": "Generating CSV...", "extend_session": "سیشن میں توسیع کریں", "external": "بیرونی", "external_wallet": "بیرونی والیٹ", @@ -494,6 +493,7 @@ "gas_price": "گیس کی قیمت", "general": "عمومی", "generate_name": "نام بنائیں", + "generating_csv": "Generating CSV...", "generating_gift_card": "گفٹ کارڈ تیار کیا جا رہا ہے", "generating_transaction": "ٹرانزیکشن تیار کی جا رہی ہے", "get_a": "حاصل کریں ", @@ -738,6 +738,22 @@ "payments": "ادائیگیاں", "pending": " (زیرِ التواء)", "percentageOf": "${amount} کا", + "picker_chip_all": "تمام", + "picker_no_matches": "کوئی میچ نہیں", + "picker_section_all_assets": "تمام اثاثے (A-Z)", + "picker_section_all_currencies": "تمام کرنسیاں", + "picker_section_crypto": "کرپٹو", + "picker_section_cryptocurrencies": "کرپٹو کرنسی", + "picker_section_gas_token": "گیس ٹوکن", + "picker_section_more_cryptocurrencies": "مزید کریپٹو کرنسی", + "picker_section_popular": "مقبول", + "picker_section_recents": "حالیہ", + "picker_section_selected": "منتخب", + "picker_section_stablecoins": "سٹیبل کوائنز", + "picker_section_tokenized_stocks": "ٹوکنائزڈ اسٹاکس (xStocks)", + "picker_section_tokens_standard": "ٹوکنز (${standard})", + "picker_see_all": "سب دیکھیں", + "picker_show_less": "کم دکھائیں۔", "pin_at_top": "${token} کو اوپر پن کریں", "pin_is_incorrect": "PIN غلط ہے", "pin_number": "PIN نمبر", @@ -927,12 +943,16 @@ "select_a_wallet": "ایک والیٹ منتخب کریں", "select_address_to_copy": "کاپی کرنے کے لیے ایڈریس منتخب کریں", "select_all": "سب منتخب کریں", + "select_asset": "اثاثہ منتخب کریں۔", "select_backup_file": "بیک اپ فائل منتخب کریں", "select_buy_provider_notice": "اوپر خریداری فراہم کنندہ منتخب کریں۔ آپ ایپ کی ترتیبات میں اپنا ڈیفالٹ خریداری فراہم کنندہ سیٹ کر کے اس اسکرین کو چھوڑ سکتے ہیں۔", "select_destination": "براہِ کرم بیک اپ فائل کے لیے منزل منتخب کریں۔", + "select_fiat_currency_title": "کرنسی کا انتخاب کریں۔", "select_hw_account_below": "براہ کرم نیچے بحال کرنے کے لیے اکاؤنٹ منتخب کریں:", "select_manufacturer_title": "مینوفیکچرر منتخب کریں", "select_network": "نیٹ ورک منتخب کریں", + "select_network_subtitle": "یہ اثاثہ متعدد نیٹ ورکس میں موجود ہے۔ جس کو آپ استعمال کرنا چاہتے ہیں اسے منتخب کریں۔", + "select_network_title": "نیٹ ورک کو منتخب کریں۔", "select_other_wallet": "دوسرا والیٹ منتخب کریں", "select_receiver": "وصول کنندہ منتخب کریں", "select_sell_provider_notice": "اوپر کسی سیل فراہم کنندہ کو منتخب کریں۔ آپ ایپ کی سیٹنگز میں اپنا ڈیفالٹ سیل فراہم کنندہ سیٹ کر کے اس اسکرین کو چھوڑ سکتے ہیں۔", @@ -1091,7 +1111,7 @@ "swipe_to_send": "بھیجنے کے لیے سوائپ کریں", "switch_wallet": "والیٹ تبدیل کریں", "switchToETHWallet": "براہِ کرم Ethereum والیٹ پر سوئچ کریں اور دوبارہ کوشش کریں", - "switchToEVMCompatibleWallet": "براہ کرم ایک EVM کے ساتھ مطابقت رکھنے والے والیٹ پر سوئچ کریں اور دوبارہ کوشش کریں (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "براہ کرم WalletConnect کے موافق والیٹ پر سوئچ کریں اور دوبارہ کوشش کریں (${chains})۔", "symbol": "علامت", "sync_all_wallets": "تمام والیٹس کو ہم آہنگ کریں", "sync_attempting": "ہم آہنگی کی کوشش کی جا رہی ہے", @@ -1395,4 +1415,4 @@ "zcash_card_missing_funds": "فنڈز غائب ہیں؟", "zcash_card_scan": "اسکین کریں", "zcash_card_warning": "طریقہ کار مکمل ہونے تک ایپ بند نہ کریں۔ اگر آپ ایسا کریں گے تو یہ عمل شروع سے دوبارہ شروع کرنا پڑے گا۔" -} +} \ No newline at end of file diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 2d503a179..5fcbf829a 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -276,6 +276,7 @@ "creating_new_wallet": "Đang tạo ví mới", "creating_new_wallet_error": "Lỗi: ${description}", "creation_date": "Ngày tạo", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Hoán đổi hiện tại", "current_wallet": "Ví hiện tại", "custom": "Tùy chỉnh", @@ -449,14 +450,12 @@ "expires": "Hết hạn", "expiresOn": "Hết hạn vào", "expiry_and_validity": "Thời hạn và hiệu lực", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Xuất bản sao lưu", "export_csv": "Export CSV", "export_lightning_logs": "Xuất nhật ký Lightning", "export_logs": "Xuất nhật ký", "export_outputs": "Xuất đầu ra", "export_payjoin_logs": "Xuất nhật ký Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Gia hạn phiên", "external": "Bên ngoài", "external_wallet": "Ví ngoài", @@ -493,6 +492,7 @@ "gas_price": "Giá gas", "general": "Chung", "generate_name": "Tạo tên", + "generating_csv": "Generating CSV...", "generating_gift_card": "Đang tạo thẻ quà tặng", "generating_transaction": "Đang tạo giao dịch", "get_a": "Nhận ", @@ -734,6 +734,22 @@ "payments": "Thanh toán", "pending": " (đang chờ)", "percentageOf": "của ${amount}", + "picker_chip_all": "Tất cả", + "picker_no_matches": "Không có kết quả phù hợp", + "picker_section_all_assets": "Tất cả tài sản (A-Z)", + "picker_section_all_currencies": "Tất cả các loại tiền tệ", + "picker_section_crypto": "tiền điện tử", + "picker_section_cryptocurrencies": "Tiền điện tử", + "picker_section_gas_token": "Mã thông báo khí", + "picker_section_more_cryptocurrencies": "Thêm tiền điện tử", + "picker_section_popular": "Phổ biến", + "picker_section_recents": "Gần đây", + "picker_section_selected": "Đã chọn", + "picker_section_stablecoins": "Stablecoin", + "picker_section_tokenized_stocks": "Cổ phiếu được mã hóa (xStocks)", + "picker_section_tokens_standard": "Mã thông báo (${standard})", + "picker_see_all": "Xem tất cả", + "picker_show_less": "Hiển thị ít hơn", "pin_at_top": "Ghim ${token} lên đầu", "pin_is_incorrect": "PIN không đúng", "pin_number": "Mã PIN", @@ -923,12 +939,16 @@ "select_a_wallet": "Chọn một ví", "select_address_to_copy": "Chọn địa chỉ để sao chép", "select_all": "Chọn tất cả", + "select_asset": "Chọn nội dung", "select_backup_file": "Chọn tệp sao lưu", "select_buy_provider_notice": "Chọn nhà cung cấp mua ở trên. Bạn có thể bỏ qua màn hình này bằng cách đặt nhà cung cấp mua mặc định trong phần cài đặt ứng dụng.", "select_destination": "Vui lòng chọn vị trí lưu tệp sao lưu.", + "select_fiat_currency_title": "Chọn tiền tệ", "select_hw_account_below": "Vui lòng chọn tài khoản cần khôi phục bên dưới:", "select_manufacturer_title": "Chọn nhà sản xuất", "select_network": "Chọn mạng", + "select_network_subtitle": "Tài sản này có mặt trong nhiều mạng. Chọn cái bạn muốn sử dụng", + "select_network_title": "Chọn mạng", "select_other_wallet": "Chọn ví khác", "select_receiver": "Chọn người nhận", "select_sell_provider_notice": "Chọn nhà cung cấp bán ở trên. Bạn có thể bỏ qua màn hình này bằng cách đặt nhà cung cấp bán mặc định trong cài đặt ứng dụng.", @@ -1086,7 +1106,7 @@ "swipe_to_send": "Vuốt để gửi", "switch_wallet": "Chuyển đổi ví", "switchToETHWallet": "Vui lòng chuyển sang ví Ethereum và thử lại", - "switchToEVMCompatibleWallet": "Vui lòng chuyển sang ví tương thích với EVM và thử lại (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Vui lòng chuyển sang ví tương thích với WalletConnect và thử lại (${chains}).", "symbol": "Ký hiệu", "sync_all_wallets": "Đồng bộ tất cả ví", "sync_attempting": "Đang thử đồng bộ", @@ -1390,4 +1410,4 @@ "zcash_card_missing_funds": "Thiếu tiền?", "zcash_card_scan": "Quét", "zcash_card_warning": "Không đóng ứng dụng cho đến khi quy trình hoàn tất; nếu bạn làm vậy, quy trình này sẽ phải bắt đầu lại từ đầu." -} +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 0d97c86dc..2fd9dcf77 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "Ń ṣẹ̀dá àpamọ́wọ́ tuntun", "creating_new_wallet_error": "Aṣiṣe: ${description}", "creation_date": "Ọjọ́ ìdásílẹ̀", + "csv_nothing_to_export": "Nothing to export", "current_swap": "Swap lọwọlọwọ", "current_wallet": "Apamọwọ lọwọlọwọ", "custom": "Àdàkọ", @@ -451,14 +452,12 @@ "expires": "Yóò parí", "expiresOn": "Yóò parí ní", "expiry_and_validity": "Ọjọ́ ìparí àti ìmúlò", - "csv_nothing_to_export": "Nothing to export", "export_backup": "Gbé ẹ̀dà àfipamọ́ jáde", "export_csv": "Export CSV", "export_lightning_logs": "Gbe àwọn àkọọlẹ Lightning jáde", "export_logs": "Gbe àwọn ìwé-àkọsílẹ̀ jáde", "export_outputs": "Gbe àwọn output jáde", "export_payjoin_logs": "Gbejade àwọn ìkọ̀ọ́lẹ̀ Payjoin", - "generating_csv": "Generating CSV...", "extend_session": "Fa igba iṣẹ́ pọ̀ síi", "external": "Ita", "external_wallet": "Apamọwọ ita", @@ -495,6 +494,7 @@ "gas_price": "Iye gaasi", "general": "Gbogbogbo", "generate_name": "Ṣẹda Orúkọ", + "generating_csv": "Generating CSV...", "generating_gift_card": "Ń ṣe Ẹ̀bùn Káàdì", "generating_transaction": "Ṣíṣe ìṣòwò", "get_a": "Gba ", @@ -737,6 +737,22 @@ "payments": "Awọn ìsanwó", "pending": " (ń dúró)", "percentageOf": "ti ${amount}", + "picker_chip_all": "Gbogbo", + "picker_no_matches": "Ko si ibaamu", + "picker_section_all_assets": "Gbogbo Awọn dukia (A-Z)", + "picker_section_all_currencies": "Gbogbo Owo", + "picker_section_crypto": "Crypto", + "picker_section_cryptocurrencies": "Awọn owo iworo", + "picker_section_gas_token": "Gaasi Àmi", + "picker_section_more_cryptocurrencies": "Diẹ Cryptocurrencies", + "picker_section_popular": "Gbajumo", + "picker_section_recents": "Awọn aipẹ", + "picker_section_selected": "Ti yan", + "picker_section_stablecoins": "Stablecoins", + "picker_section_tokenized_stocks": "Awọn akojopo Tokini (xStocks)", + "picker_section_tokens_standard": "Àmi (${standard})", + "picker_see_all": "Wo gbogbo", + "picker_show_less": "Ṣe afihan kere si", "pin_at_top": "Fi ${token} mọ́ òkè", "pin_is_incorrect": "PIN kò tọ́", "pin_number": "Nọ́mbà PIN", @@ -926,12 +942,16 @@ "select_a_wallet": "Yan apamọwọ kan", "select_address_to_copy": "Yan Adirẹsi láti Daakọ", "select_all": "Yan gbogbo", + "select_asset": "Yan dukia", "select_backup_file": "Yan faili afẹ́yinti", "select_buy_provider_notice": "Yan olupese rira loke. O le foju iboju yii kọja nipa ṣiṣeto olupese rira aiyipada rẹ ninu awọn eto app.", "select_destination": "Jọwọ yan ibi ìpamọ́ fún fáìlì afẹ́yinti.", + "select_fiat_currency_title": "Yan Owo", "select_hw_account_below": "Jọwọ yan àkántì tí o fẹ́ mú padà ní isalẹ:", "select_manufacturer_title": "Yan Olupese", "select_network": "Yan Nẹ́tíwọ́ọ̀kì", + "select_network_subtitle": "Ohun-ini yii wa ni awọn nẹtiwọọki pupọ. Yan eyi ti o fẹ lati lo", + "select_network_title": "Yan Nẹtiwọọki", "select_other_wallet": "Yan Apamọwọ mìíràn", "select_receiver": "Yan Olùgbà", "select_sell_provider_notice": "Yan olupese tita kan loke. O le foju iboju yii kọja nipa tito olupese tita aiyipada rẹ ninu awọn eto app.", @@ -1090,7 +1110,7 @@ "swipe_to_send": "Ra lati fi ránṣẹ́", "switch_wallet": "Yí apamọwọ padà", "switchToETHWallet": "Jọwọ yipada sí apamọwọ Ethereum kí o sì tún gbìyànjú lẹ́ẹ̀kansi", - "switchToEVMCompatibleWallet": "Jọwọ yipada sí apamọwọ tí ó bá EVM mu, kí o sì tún gbìyànjú lẹ́ẹ̀kansi (Ethereum, Polygon)", + "switchToWCCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu WalletConnect ki o tun gbiyanju lẹẹkansi (${chains}).", "symbol": "Àmì", "sync_all_wallets": "Muṣiṣẹpọ gbogbo awọn woleti", "sync_attempting": "Ń gbìyànjú láti ṣe amuṣiṣẹpọ", @@ -1394,4 +1414,4 @@ "zcash_card_missing_funds": "Ṣe owó rẹ sọnù?", "zcash_card_scan": "Ṣàwárí", "zcash_card_warning": "Maṣe pa ohun elo naa titi ilana naa yoo fi pari; bí o bá ṣe bẹ́ẹ̀, ilana yìí yóò ní láti tún bẹ̀rẹ̀ láti ìbẹ̀rẹ̀." -} +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index af8b72c00..017e28c7b 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -277,6 +277,7 @@ "creating_new_wallet": "正在创建新钱包", "creating_new_wallet_error": "错误:${description}", "creation_date": "创建日期", + "csv_nothing_to_export": "Nothing to export", "current_swap": "当前兑换", "current_wallet": "当前钱包", "custom": "自定义", @@ -450,14 +451,12 @@ "expires": "到期", "expiresOn": "到期于", "expiry_and_validity": "有效期和有效性", - "csv_nothing_to_export": "Nothing to export", "export_backup": "导出备份", "export_csv": "Export CSV", "export_lightning_logs": "导出 Lightning 日志", "export_logs": "导出日志", "export_outputs": "导出输出", "export_payjoin_logs": "导出 Payjoin 日志", - "generating_csv": "Generating CSV...", "extend_session": "延长会话", "external": "外部", "external_wallet": "外部钱包", @@ -494,6 +493,7 @@ "gas_price": "Gas 费", "general": "通用", "generate_name": "生成名称", + "generating_csv": "Generating CSV...", "generating_gift_card": "正在生成礼品卡", "generating_transaction": "正在生成交易", "get_a": "获取一个", @@ -736,6 +736,22 @@ "payments": "支付", "pending": "(待处理)", "percentageOf": "${amount} 的", + "picker_chip_all": "全部", + "picker_no_matches": "没有匹配项", + "picker_section_all_assets": "所有资产(A-Z)", + "picker_section_all_currencies": "所有货币", + "picker_section_crypto": "加密货币", + "picker_section_cryptocurrencies": "加密货币", + "picker_section_gas_token": "天然气代币", + "picker_section_more_cryptocurrencies": "更多加密货币", + "picker_section_popular": "受欢迎的", + "picker_section_recents": "最近的内容", + "picker_section_selected": "已选择", + "picker_section_stablecoins": "稳定币", + "picker_section_tokenized_stocks": "代币化股票 (xStocks)", + "picker_section_tokens_standard": "代币(${standard})", + "picker_see_all": "查看全部", + "picker_show_less": "显示较少", "pin_at_top": "将 ${token} 置顶", "pin_is_incorrect": "PIN 不正确", "pin_number": "PIN 码", @@ -925,12 +941,16 @@ "select_a_wallet": "选择钱包", "select_address_to_copy": "选择要复制的地址", "select_all": "全选", + "select_asset": "选择资产", "select_backup_file": "选择备份文件", "select_buy_provider_notice": "请在上方选择一个买入服务提供商。您可以在应用设置中设置默认买入服务提供商,以跳过此屏幕。", "select_destination": "请选择备份文件的保存位置。", + "select_fiat_currency_title": "选择货币", "select_hw_account_below": "请在下方选择要恢复的账户:", "select_manufacturer_title": "选择制造商", "select_network": "选择网络", + "select_network_subtitle": "该资产存在于多个网络中。选择您要使用的", + "select_network_title": "选择网络", "select_other_wallet": "选择其他钱包", "select_receiver": "选择收款方", "select_sell_provider_notice": "请选择上方的出售服务提供商。您可以在应用设置中设置默认的出售服务提供商,以跳过此屏幕。", @@ -1089,7 +1109,7 @@ "swipe_to_send": "滑动以发送", "switch_wallet": "切换钱包", "switchToETHWallet": "请切换到以太坊钱包后重试", - "switchToEVMCompatibleWallet": "请切换到 EVM 兼容的钱包并重试(以太坊、Polygon)", + "switchToWCCompatibleWallet": "請切換到 WalletConnect 相容錢包並重試 (${chains})。", "symbol": "代号", "sync_all_wallets": "同步所有钱包", "sync_attempting": "正在尝试同步", @@ -1393,4 +1413,4 @@ "zcash_card_missing_funds": "资金不见了?", "zcash_card_scan": "扫描", "zcash_card_warning": "在该过程完成之前请勿关闭应用程序,否则该过程将需要从头重新开始。" -} +} \ No newline at end of file diff --git a/res/values/strings_zh_tw.arb b/res/values/strings_zh_tw.arb index 6e8de98b0..4fb7cbf95 100644 --- a/res/values/strings_zh_tw.arb +++ b/res/values/strings_zh_tw.arb @@ -631,6 +631,11 @@ "payments": "支付", "pending": " (待處理)", "percentageOf": "的 ${amount}", + "picker_section_crypto": "加密貨幣", + "picker_section_more_cryptocurrencies": "更多加密貨幣", + "picker_section_tokens_standard": "代幣(${standard})", + "picker_see_all": "查看全部", + "picker_show_less": "顯示較少", "pin_at_top": "將 ${token} 釘選至頂端", "pin_is_incorrect": "PIN 不正確", "pin_number": "PIN 碼", @@ -941,7 +946,7 @@ "sweeping_wallet_alert": "這應該不會花很長時間。請勿離開此畫面,否則被歸集的資金可能會遺失。", "switch_wallet": "切換錢包", "switchToETHWallet": "請切換到以太坊錢包後再試一次", - "switchToEVMCompatibleWallet": "請切換至 EVM 相容的錢包後再試一次(Ethereum、Polygon)", + "switchToWCCompatibleWallet": "請切換到 WalletConnect 相容錢包並重試 (${chains})。", "symbol": "代號", "sync_all_wallets": "同步所有錢包", "sync_status_attempting_scan": "正在嘗試掃描", diff --git a/scripts/prepare_moneroc.sh b/scripts/prepare_moneroc.sh index 0a328f5f3..d8caf006a 100755 --- a/scripts/prepare_moneroc.sh +++ b/scripts/prepare_moneroc.sh @@ -16,7 +16,7 @@ fi # NOTE: Make sure to update monero_c prebuilds link in workflow files # https://github.com/MrCyjaneK/monero_c/releases/download/v0.18.4.6-RC2/release-bundle.zip git fetch -a -git checkout 3bfb3856a838f2bf6b729501837bb0295dedf25d +git checkout 0b324fe33ff5709feb69e2892767c1be9349957d git reset --hard git submodule update --init --force --recursive diff --git a/scripts/prepare_zcash.sh b/scripts/prepare_zcash.sh index 5abc3212d..2b121d8ae 100755 --- a/scripts/prepare_zcash.sh +++ b/scripts/prepare_zcash.sh @@ -2,7 +2,7 @@ set -x -e cd "$(dirname "$0")" -HASH=647231e2e6d93c1d6c16d4019cd3a11a3aaa9504 +HASH=5800cfdfc89ae46d8a343721d052d5e02470c2a7 if [[ ! -d "zcash_lib/.git" ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index 6a5385f86..a16d88f21 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -938,6 +938,7 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/spl_token.dart'; +import 'package:cw_core/transaction_direction.dart'; """; const solanaCWHeaders = """ @@ -1033,6 +1034,23 @@ abstract class Solana { }); Future discoverAndAddWalletTokens(WalletBase wallet); + + TransactionInfo getTransactionInfo( +{ + required String id, + required DateTime blockTime, + required String to, + required String from, + String? tokenSymbol, + required TransactionDirection direction, + required double solAmount, + required bool isPending, + required double txFee, + } + ); + + double getPendingTransactionAmount(PendingTransaction tx); + double getPendingTransactionFee(PendingTransaction tx); } class JupiterSwapFailedException implements Exception { @@ -1076,6 +1094,7 @@ Future generateTron(bool hasImplementation) async { const tronCommonHeaders = """ import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_base.dart'; @@ -1084,6 +1103,7 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/tron_token.dart'; import 'package:hive/hive.dart'; +import 'package:cw_core/transaction_direction.dart'; """; const tronCWHeaders = """ @@ -1091,6 +1111,7 @@ import 'package:cw_evm/evm_chain_mnemonics.dart'; import 'package:cw_tron/tron_transaction_credentials.dart'; import 'package:cw_tron/tron_transaction_info.dart'; import 'package:cw_tron/tron_wallet_creation_credentials.dart'; +import 'package:cw_tron/pending_tron_transaction.dart'; import 'package:cw_tron/tron_client.dart'; import 'package:cw_tron/tron_wallet.dart'; @@ -1131,6 +1152,19 @@ abstract class Tron { List getDefaultTokenContractAddresses(); List getDefaultTokenSymbols(); bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress); + TransactionInfo getTransactionInfo({ + required String id, + required BigInt tronAmount, + int? txFee, + String? tokenSymbol, + required TransactionDirection direction, + required DateTime blockTime, + String? to, + String? from, + required bool isPending, + }); + String getPendingTransactionFee(PendingTransaction tx); + String getPendingTransactionAmount(PendingTransaction tx); } """; @@ -1361,6 +1395,7 @@ Future generateEVM(bool hasImplementation) async { import 'dart:math' as math; import 'package:cake_wallet/core/utilities.dart'; import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/hardware/hardware_account_data.dart'; @@ -1379,6 +1414,7 @@ import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger; import 'package:bitbox_flutter/bitbox_flutter.dart' as bitbox; import 'package:trezor_connect/trezor_connect.dart' as trezor; import 'package:web3dart/web3dart.dart'; +import 'package:cw_core/transaction_direction.dart'; """; const evmCWHeaders = """ @@ -1389,6 +1425,7 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_evm/utils/evm_chain_formatter.dart'; import 'package:cw_evm/evm_chain_mnemonics.dart'; +import 'package:cw_evm/pending_evm_chain_transaction.dart'; import 'package:cw_evm/evm_chain_registry.dart'; import 'package:cw_evm/evm_erc20_balance.dart'; import 'package:cw_evm/evm_chain_transaction_credentials.dart'; @@ -1608,6 +1645,28 @@ abstract class EVM { WalletBase wallet, TransactionPriority priority, ); + + TransactionInfo getTransactionInfo( + { + required String id, + required int height, + required BigInt ethAmount, + required BigInt ethFee, + required String tokenSymbol, + int exponent = 18, + required TransactionDirection direction, + required bool isPending, + required DateTime date, + required int confirmations, + String? to, + String? from, + String? evmSignatureName, + String? contractAddress, + required int chainId, + } + ); + BigInt getPendingTransactionFee(PendingTransaction tx); + String getPendingTransactionAmount(PendingTransaction tx); Future discoverAndAddWalletTokens(WalletBase wallet); }