From 308de0389d226690aa5e553b0c396dd0143d2bb3 Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 5 Feb 2026 13:48:26 +0100 Subject: [PATCH] CW-1368: Add Binance Smart Chain (#2836) * feat: Add Binance Smart Chain support to wallet types and EVM chain registry * feat: Add BSC node list and support in wallet type and chain ID mappings * feat: Add BSC default tokens and update evm utility functions * feat: Integrate BSC support in node settings and management * feat: Add BSC support to config scripts and wallet type generation * feat: Add BSC support to EVM chain ID and switcher * feat: Extend BSC support in wallet utilities and chain type checks * feat: Add BSC support to different wallet functions * feat: Add BSCURI class and implement for uri handling * feat: Update Android and iOS configurations to support BSC URL schemes * feat: Add BSC support to different functionalities and settings * refactor: Update wallet type name from'Binance Smart Chain' to BNB Smart Chain * feat: Add switcher icon and updates token utils * Review fixes * More changes to BSC name, wallet listing and images * Add more default tokens --- android/app/src/main/AndroidManifestBase.xml | 3 + assets/bsc_node_list.yml | 28 ++++++ assets/images/bnb_chain_QR.svg | 5 + assets/images/bnb_chain_mono.svg | 3 + assets/images/crypto/BNB.webp | Bin 0 -> 5722 bytes assets/images/evm_switcher_icons/bnb_icon.svg | 3 + cw_core/lib/crypto_currency.dart | 2 +- cw_core/lib/currency_for_wallet_type.dart | 6 ++ cw_core/lib/erc20_token.dart | 1 + cw_core/lib/node.dart | 2 + cw_core/lib/wallet_type.dart | 14 +++ cw_evm/lib/clients/bsc_client.dart | 47 ++++++++++ cw_evm/lib/clients/evm_chain_client.dart | 4 +- cw_evm/lib/evm_chain_client_factory.dart | 3 + cw_evm/lib/evm_chain_default_tokens.dart | 2 + cw_evm/lib/evm_chain_registry.dart | 35 +++++++ cw_evm/lib/evm_chain_transaction_info.dart | 8 +- cw_evm/lib/evm_chain_wallet.dart | 1 + cw_evm/lib/tokens/bsc_tokens.dart | 88 ++++++++++++++++++ cw_evm/lib/utils/evm_chain_utils.dart | 7 ++ .../components/common_test_flows.dart | 4 + ios/Runner/InfoBase.plist | 20 ++++ lib/buy/dfx/dfx_buy_provider.dart | 1 + lib/buy/robinhood/robinhood_buy_provider.dart | 1 + lib/core/payment_uris.dart | 15 +++ lib/core/seed_validator.dart | 1 + lib/core/wallet_creation_service.dart | 1 + lib/di.dart | 1 + lib/entities/default_settings_migration.dart | 20 ++++ lib/entities/ens_record.dart | 1 + lib/entities/node_list.dart | 7 +- lib/entities/preferences_key.dart | 3 + lib/entities/priority_for_wallet_type.dart | 1 + lib/main.dart | 2 +- lib/reactions/wallet_connect.dart | 7 +- lib/reactions/wallet_utils.dart | 2 + .../desktop_wallet_selection_dropdown.dart | 3 + .../dashboard/widgets/menu_widget.dart | 5 +- lib/src/screens/settings/privacy_page.dart | 8 ++ .../chain_service/eth/evm_chain_id.dart | 2 + .../wallet_connect_key_service.dart | 2 + lib/src/widgets/evm_switcher.dart | 56 +++-------- lib/src/widgets/evm_switcher_row.dart | 25 ++--- lib/store/settings_store.dart | 45 +++++++++ lib/utils/qr_util.dart | 59 +++++------- lib/utils/token_utilities.dart | 10 +- .../advanced_privacy_settings_view_model.dart | 2 + .../anon_invoice_page_view_model.dart | 3 +- .../dashboard/balance_view_model.dart | 1 + .../dashboard/dashboard_view_model.dart | 1 + .../dashboard/home_settings_view_model.dart | 1 + .../dashboard/transaction_list_item.dart | 1 + .../exchange/exchange_trade_view_model.dart | 10 +- .../exchange/exchange_view_model.dart | 4 + .../node_create_or_edit_view_model.dart | 1 + .../restore/wallet_restore_from_qr_code.dart | 1 + lib/view_model/send/fees_view_model.dart | 2 + lib/view_model/send/output.dart | 5 +- .../send/send_template_view_model.dart | 5 +- lib/view_model/send/send_view_model.dart | 14 ++- .../settings/privacy_settings_view_model.dart | 11 +++ .../transaction_details_view_model.dart | 6 +- .../wallet_address_list_view_model.dart | 23 +++-- lib/view_model/wallet_keys_view_model.dart | 3 + lib/view_model/wallet_new_vm.dart | 1 + lib/view_model/wallet_restore_view_model.dart | 20 ++-- pubspec_base.yaml | 1 + res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 1 + res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fa.arb | 3 +- res/values/strings_fr.arb | 1 + res/values/strings_gn.arb | 1 + res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 3 +- res/values/strings_hy.arb | 1 + res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_vi.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + scripts/android/pubspec_gen.sh | 2 +- scripts/ios/app_config.sh | 2 +- scripts/linux/app_config.sh | 2 +- scripts/macos/app_config.sh | 2 +- tool/configure.dart | 24 +++-- tool/utils/secret_key.dart | 2 + 103 files changed, 609 insertions(+), 157 deletions(-) create mode 100644 assets/bsc_node_list.yml create mode 100644 assets/images/bnb_chain_QR.svg create mode 100644 assets/images/bnb_chain_mono.svg create mode 100644 assets/images/crypto/BNB.webp create mode 100644 assets/images/evm_switcher_icons/bnb_icon.svg create mode 100644 cw_evm/lib/clients/bsc_client.dart create mode 100644 cw_evm/lib/tokens/bsc_tokens.dart diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index d2ffeef5f..4981d5d19 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -112,6 +112,9 @@ + + + diff --git a/assets/bsc_node_list.yml b/assets/bsc_node_list.yml new file mode 100644 index 000000000..20e0cdcca --- /dev/null +++ b/assets/bsc_node_list.yml @@ -0,0 +1,28 @@ +- + uri: bsc-dataseed.bnbchain.org + useSSL: true + isDefault: true + isEnabledForAutoSwitching: true +- + uri: bsc-dataseed2.bnbchain.org + useSSL: true + isEnabledForAutoSwitching: true +- + uri: bsc-dataseed.nariox.org + useSSL: true + isEnabledForAutoSwitching: true +- + uri: bsc-dataseed.defibit.io + useSSL: true + isEnabledForAutoSwitching: true +- + uri: bsc-dataseed.ninicoin.io + useSSL: true + isEnabledForAutoSwitching: true +- + uri: bsc.nodereal.io + useSSL: true + isEnabledForAutoSwitching: true +- + uri: bsc-dataseed-public.bnbchain.org + useSSL: true diff --git a/assets/images/bnb_chain_QR.svg b/assets/images/bnb_chain_QR.svg new file mode 100644 index 000000000..1b1f4b1e2 --- /dev/null +++ b/assets/images/bnb_chain_QR.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/bnb_chain_mono.svg b/assets/images/bnb_chain_mono.svg new file mode 100644 index 000000000..58da53fde --- /dev/null +++ b/assets/images/bnb_chain_mono.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/crypto/BNB.webp b/assets/images/crypto/BNB.webp new file mode 100644 index 0000000000000000000000000000000000000000..59976f31c7412add56809087a0b649100552aee9 GIT binary patch literal 5722 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 Mipm}_Wmup90F!wJ@Bjb+ literal 0 HcmV?d00001 diff --git a/assets/images/evm_switcher_icons/bnb_icon.svg b/assets/images/evm_switcher_icons/bnb_icon.svg new file mode 100644 index 000000000..b1f1841b8 --- /dev/null +++ b/assets/images/evm_switcher_icons/bnb_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index b04a2bcfa..96826cca2 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -147,7 +147,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const xmr = CryptoCurrency(title: 'XMR', fullName: 'Monero', raw: 0, name: 'xmr', iconPath: 'assets/images/crypto/monero.webp', decimals: 12); static const ada = CryptoCurrency(title: 'ADA', fullName: 'Cardano', raw: 1, name: 'ada', iconPath: 'assets/images/ada_icon.png', decimals: 6); static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/images/crypto/bitcoin-cash.webp', decimals: 8); - static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'Binance Coin', raw: 3, name: 'bnb', iconPath: 'assets/images/bnb_icon.png', decimals: 8); + static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'Binance Coin', raw: 3, name: 'bnb', iconPath: 'assets/images/crypto/BNB.webp', decimals: 8); static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/images/crypto/bitcoin.webp', decimals: 8); static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/images/crypto/dai.webp', decimals: 18); static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png', decimals: 8); diff --git a/cw_core/lib/currency_for_wallet_type.dart b/cw_core/lib/currency_for_wallet_type.dart index 8928bfdb0..65b752484 100644 --- a/cw_core/lib/currency_for_wallet_type.dart +++ b/cw_core/lib/currency_for_wallet_type.dart @@ -24,6 +24,8 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type, {bool isTestnet = fal return CryptoCurrency.baseEth; case WalletType.arbitrum: return CryptoCurrency.arbEth; + case WalletType.bsc: + return CryptoCurrency.bnb; case WalletType.bitcoinCash: return CryptoCurrency.bch; case WalletType.nano: @@ -62,6 +64,8 @@ CryptoCurrency getCryptoCurrencyByChainId(int chainId) { return CryptoCurrency.baseEth; case 42161: return CryptoCurrency.arbEth; + case 56: + return CryptoCurrency.bnb; default: return CryptoCurrency.eth; } @@ -79,6 +83,8 @@ int? getChainIdByCryptoCurrency(CryptoCurrency currency) { return 8453; case CryptoCurrency.arbEth: return 42161; + case CryptoCurrency.bnb: + return 56; default: return null; } diff --git a/cw_core/lib/erc20_token.dart b/cw_core/lib/erc20_token.dart index 841be33c2..e19cbc63f 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -72,6 +72,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { static const polygonBoxName = 'PolygonErc20Tokens'; static const baseBoxName = 'BaseErc20Tokens'; static const arbitrumBoxName = 'ArbitrumErc20Tokens'; + static const bscBoxName = 'BscErc20Tokens'; @override bool operator ==(Object other) => other is Erc20Token && other.contractAddress == contractAddress; diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 67ef15c63..edd06bb70 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -122,6 +122,7 @@ class Node extends HiveObject with Keyable { case WalletType.ethereum: case WalletType.polygon: case WalletType.base: + case WalletType.bsc: case WalletType.arbitrum: case WalletType.solana: case WalletType.tron: @@ -188,6 +189,7 @@ class Node extends HiveObject with Keyable { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.tron: case WalletType.dogecoin: diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index 0cb974cbb..e40885610 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -22,6 +22,7 @@ const walletTypes = [ WalletType.base, WalletType.arbitrum, WalletType.zcash, + WalletType.bsc, ]; @HiveType(typeId: WALLET_TYPE_TYPE_ID) @@ -82,6 +83,9 @@ enum WalletType { @HiveField(18) zcash, + + @HiveField(19) + bsc, } int serializeToInt(WalletType type) { @@ -122,6 +126,8 @@ int serializeToInt(WalletType type) { return 16; case WalletType.zcash: return 17; + case WalletType.bsc: + return 18; case WalletType.none: return -1; } @@ -165,6 +171,8 @@ WalletType deserializeFromInt(int raw) { return WalletType.arbitrum; case 17: return WalletType.zcash; + case 18: + return WalletType.bsc; default: throw Exception('Unexpected token: $raw for WalletType deserializeFromInt'); } @@ -208,6 +216,8 @@ String walletTypeToString(WalletType type) { return 'Arbitrum'; case WalletType.zcash: return 'Zcash'; + case WalletType.bsc: + return 'BNB Smart Chain'; case WalletType.none: return ''; } @@ -251,6 +261,8 @@ String walletTypeToDisplayName(WalletType type) { return 'Arbitrum (ARB)'; case WalletType.zcash: return 'Zcash (ZEC)'; + case WalletType.bsc: + return 'BNB Smart Chain (BNB)'; case WalletType.none: return ''; } @@ -275,6 +287,8 @@ WalletType? cryptoCurrencyToWalletType(CryptoCurrency type) { return WalletType.base; case CryptoCurrency.arbEth: return WalletType.arbitrum; + case CryptoCurrency.bnb: + return WalletType.bsc; case CryptoCurrency.bch: return WalletType.bitcoinCash; case CryptoCurrency.nano: diff --git a/cw_evm/lib/clients/bsc_client.dart b/cw_evm/lib/clients/bsc_client.dart new file mode 100644 index 000000000..314a3e0c0 --- /dev/null +++ b/cw_evm/lib/clients/bsc_client.dart @@ -0,0 +1,47 @@ +import 'package:cw_evm/clients/evm_chain_client.dart'; +import 'package:flutter/foundation.dart'; +import 'package:web3dart/web3dart.dart'; + +class BSCClient extends EVMChainClient { + BSCClient() : super(chainId: 56); + + @override + Transaction createTransaction({ + required EthereumAddress from, + required EthereumAddress to, + required EtherAmount amount, + EtherAmount? maxPriorityFeePerGas, + Uint8List? data, + int? maxGas, + EtherAmount? gasPrice, + EtherAmount? maxFeePerGas, + int? nonce, + }) { + EtherAmount? finalGasPrice = gasPrice; + + if (gasPrice == null && maxFeePerGas != null) { + // If we have EIP-1559 parameters but no legacy gasPrice, then use maxFeePerGas as gasPrice + // BSC RPC nodes may have issues with EIP-1559 transaction encoding + finalGasPrice = maxFeePerGas; + } + + return Transaction( + from: from, + to: to, + value: amount, + data: data, + maxGas: maxGas, + gasPrice: finalGasPrice, + nonce: nonce, + // maxFeePerGas: maxFeePerGas, + // maxPriorityFeePerGas: maxPriorityFeePerGas, + ); + } + + @override + Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) => signedTransaction; + + @override + int get chainId => 56; +} + diff --git a/cw_evm/lib/clients/evm_chain_client.dart b/cw_evm/lib/clients/evm_chain_client.dart index 861a59d10..5bb5d1ab1 100644 --- a/cw_evm/lib/clients/evm_chain_client.dart +++ b/cw_evm/lib/clients/evm_chain_client.dart @@ -277,12 +277,14 @@ class EVMChainClient { currency == CryptoCurrency.maticpoly || currency == CryptoCurrency.baseEth || currency == CryptoCurrency.arbEth || + currency == CryptoCurrency.bnb || contractAddress != null); bool isNativeToken = currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly || currency == CryptoCurrency.baseEth || - currency == CryptoCurrency.arbEth; + currency == CryptoCurrency.arbEth || + currency == CryptoCurrency.bnb; // Get nonce with "pending" block tag to include pending transactions // This prevents "Nonce too low" errors when sending multiple transactions quickly diff --git a/cw_evm/lib/evm_chain_client_factory.dart b/cw_evm/lib/evm_chain_client_factory.dart index 61c73fdb8..bd55af384 100644 --- a/cw_evm/lib/evm_chain_client_factory.dart +++ b/cw_evm/lib/evm_chain_client_factory.dart @@ -1,5 +1,6 @@ import 'package:cw_evm/clients/arbitrum_client.dart'; import 'package:cw_evm/clients/base_client.dart'; +import 'package:cw_evm/clients/bsc_client.dart'; import 'package:cw_evm/clients/ethereum_client.dart'; import 'package:cw_evm/clients/polygon_client.dart'; import 'package:cw_evm/clients/evm_chain_client.dart'; @@ -29,6 +30,8 @@ class EVMChainClientFactory { return BaseClient(); case 42161: return ArbitrumClient(); + case 56: + return BSCClient(); default: return EVMChainClient(chainId: chainId); } diff --git a/cw_evm/lib/evm_chain_default_tokens.dart b/cw_evm/lib/evm_chain_default_tokens.dart index bc1496f94..f305d718c 100644 --- a/cw_evm/lib/evm_chain_default_tokens.dart +++ b/cw_evm/lib/evm_chain_default_tokens.dart @@ -1,6 +1,7 @@ import 'package:cw_core/erc20_token.dart'; import 'package:cw_evm/tokens/arbitrum_tokens.dart'; import 'package:cw_evm/tokens/base_tokens.dart'; +import 'package:cw_evm/tokens/bsc_tokens.dart'; import 'package:cw_evm/tokens/ethereum_tokens.dart'; import 'package:cw_evm/tokens/polygon_tokens.dart'; @@ -12,6 +13,7 @@ class EVMChainDefaultTokens { 137 => PolygonTokens.tokens, 8453 => BaseTokens.tokens, 42161 => ArbitrumTokens.tokens, + 56 => BSCTokens.tokens, _ => [], }; } diff --git a/cw_evm/lib/evm_chain_registry.dart b/cw_evm/lib/evm_chain_registry.dart index 4ea89a7a6..9eb56e38d 100644 --- a/cw_evm/lib/evm_chain_registry.dart +++ b/cw_evm/lib/evm_chain_registry.dart @@ -155,6 +155,41 @@ class EvmChainRegistry { WalletType.arbitrum, 'ARB', ); + + // BNB Smart Chain + _registerChain( + const ChainConfig( + chainId: 56, + name: 'BNB Smart Chain', + shortCode: 'bsc', + caip2: 'eip155:56', + nativeCurrency: CryptoCurrency.bnb, + capabilities: ChainCapabilities( + supportsERC20: true, + supportsEIP1559: true, + supportsInternalTx: true, + supportsSubscriptions: false, + supportsENS: false, + ), + defaultRpcEndpoints: [ + 'bsc-dataseed1.binance.org', + 'bsc-dataseed2.binance.org', + 'bsc-dataseed1.defibit.io', + 'bsc-dataseed1.nodereal.io', + 'bsc.llamarpc.com', + 'bsc-rpc.publicnode.com', + ], + explorerUrls: [ + 'https://bscscan.com', + ], + feeModel: FeeModel( + type: FeeType.eip1559, + defaultGasLimit: 21000, + ), + ), + WalletType.bsc, + 'BSC', + ); } void _registerChain( diff --git a/cw_evm/lib/evm_chain_transaction_info.dart b/cw_evm/lib/evm_chain_transaction_info.dart index 9f4bc63ec..47da8a24c 100644 --- a/cw_evm/lib/evm_chain_transaction_info.dart +++ b/cw_evm/lib/evm_chain_transaction_info.dart @@ -50,10 +50,16 @@ class EVMChainTransactionInfo extends TransactionInfo { /// Get fee currency symbol based on wallet type String get feeCurrency => EVMChainUtils.getFeeCurrency(chainId); + String get _displayTokenSymbol { + if (chainId == 56 && tokenSymbol.toUpperCase() == 'BSC-USD') return 'USDT'; + + return tokenSymbol; + } + @override String amountFormatted() { final amount = formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString()); - return '${amount.substring(0, min(10, amount.length))} $tokenSymbol'; + return '${amount.substring(0, min(10, amount.length))} $_displayTokenSymbol'; } @override diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index 8e86f821a..c7f20a792 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -368,6 +368,7 @@ abstract class EVMChainWalletBase 137 => "0x2791bca1f2de4661ed88a30c99a7a9449aa84174", 8453 => "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", 42161 => "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + 56 => "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", _ => throw Exception("Unsupported chain ID: $selectedChainId"), }; } diff --git a/cw_evm/lib/tokens/bsc_tokens.dart b/cw_evm/lib/tokens/bsc_tokens.dart new file mode 100644 index 000000000..2e003f2fd --- /dev/null +++ b/cw_evm/lib/tokens/bsc_tokens.dart @@ -0,0 +1,88 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/erc20_token.dart'; + +/// Default ERC20 tokens for Binance Smart Chain +class BSCTokens { + static List get tokens { + final tokens = [ + Erc20Token( + name: "USD Coin", + symbol: "USDC", + contractAddress: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", + decimal: 18, + enabled: true, + ), + Erc20Token( + name: "Ethereum", + symbol: "ETH", + contractAddress: "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", + decimal: 18, + enabled: true, + ), + Erc20Token( + name: "Tether USD", + symbol: "USDT", + contractAddress: "0x55d398326f99059fF775485246999027B3197955", + decimal: 18, + enabled: true, + ), + Erc20Token( + name: "USDe", + symbol: "USDe", + contractAddress: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34", + decimal: 18, + enabled: true, + ), + Erc20Token( + name: "PancakeSwap Token", + symbol: "CAKE", + contractAddress: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82", + decimal: 18, + enabled: false, + ), + Erc20Token( + name: "Cardano Token", + symbol: "ADA", + contractAddress: "0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47", + decimal: 18, + enabled: false, + ), + Erc20Token( + name: "PEPE", + symbol: "PEPE", + contractAddress: "0x25d887ce7a35172c62febfd67a1856f20faebb00", + decimal: 18, + enabled: false, + ), + Erc20Token( + name: "Wrapped BTC", + symbol: "WBTC", + contractAddress: "0x0555E30da8f98308EdB960aa94C0Db47230d2B9c", + decimal: 8, + enabled: false, + ), + Erc20Token( + name: "Wrapped BNB", + symbol: "WBNB", + contractAddress: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + decimal: 18, + enabled: false, + ), + ]; + + return tokens.map((token) { + String? iconPath; + if (token.iconPath?.isEmpty ?? true) { + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} + } else { + iconPath = token.iconPath; + } + + return Erc20Token.copyWith(token, icon: iconPath, tag: 'BSC'); + }).toList(); + } +} diff --git a/cw_evm/lib/utils/evm_chain_utils.dart b/cw_evm/lib/utils/evm_chain_utils.dart index f824bcd90..2f882c20f 100644 --- a/cw_evm/lib/utils/evm_chain_utils.dart +++ b/cw_evm/lib/utils/evm_chain_utils.dart @@ -9,6 +9,7 @@ class EVMChainUtils { 1 => _ethereumPriorityFee(priority), 137 => _polygonPriorityFee(priority), 8453 => _basePriorityFee(priority), + 56 => _ethereumPriorityFee(priority), 42161 => 0, // Arbitrum doesn't use priority fees _ => _ethereumPriorityFee(priority), }; @@ -29,6 +30,7 @@ class EVMChainUtils { 137 => "${sanitizedName}_${Erc20Token.polygonBoxName}", 8453 => "${sanitizedName}_${Erc20Token.baseBoxName}", 42161 => "${sanitizedName}_${Erc20Token.arbitrumBoxName}", + 56 => "${sanitizedName}_${Erc20Token.bscBoxName}", _ => "${sanitizedName}_${Erc20Token.ethereumBoxName}", }; } @@ -39,6 +41,7 @@ class EVMChainUtils { 137 => 'polygon_transactions.json', 8453 => 'base_transactions.json', 42161 => 'arbitrum_transactions.json', + 56 => 'bsc_transactions.json', _ => 'transactions_$chainId.json', // Generic format for other chains }; } @@ -50,6 +53,7 @@ class EVMChainUtils { 137 => 'use_polygonscan', 8453 => 'use_basescan', 42161 => 'use_arbiscan', + 56 => 'use_bscscan', _ => 'use_etherscan', }; } @@ -60,6 +64,7 @@ class EVMChainUtils { 137 => 'POL', 8453 => 'BASE', 42161 => 'ARB', + 56 => 'BSC', _ => 'ETH', }; } @@ -70,6 +75,7 @@ class EVMChainUtils { 137 => 'MATIC', 8453 => 'ETH', 42161 => 'ETH', + 56 => 'BNB', _ => 'ETH', }; } @@ -80,6 +86,7 @@ class EVMChainUtils { 137 => 'MATIC', 8453 => 'BASE', 42161 => 'ARBITRUM', + 56 => 'BNB', _ => 'ETH', }; } diff --git a/integration_test/components/common_test_flows.dart b/integration_test/components/common_test_flows.dart index ba4210934..d885e3e14 100644 --- a/integration_test/components/common_test_flows.dart +++ b/integration_test/components/common_test_flows.dart @@ -358,6 +358,8 @@ class CommonTestFlows { return secrets.baseTestWalletSeeds; case WalletType.arbitrum: return secrets.arbitrumTestWalletSeeds; + case WalletType.bsc: + return secrets.bscTestWalletSeeds; case WalletType.tron: return secrets.tronTestWalletSeeds; case WalletType.nano: @@ -398,6 +400,8 @@ class CommonTestFlows { return secrets.baseTestWalletReceiveAddress; case WalletType.arbitrum: return secrets.arbitrumTestWalletReceiveAddress; + case WalletType.bsc: + return secrets.bscTestWalletReceiveAddress; case WalletType.solana: return secrets.solanaTestWalletReceiveAddress; case WalletType.tron: diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index 3486cc40e..a7f443f22 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -342,6 +342,26 @@ arbitrum-wallet + + CFBundleTypeRole + Editor + CFBundleURLName + bsc + CFBundleURLSchemes + + bsc + + + + CFBundleTypeRole + Viewer + CFBundleURLName + bsc-wallet + CFBundleURLSchemes + + bsc-wallet + + CFBundleTypeRole Viewer diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index 5f4c66854..f927b702d 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -137,6 +137,7 @@ class DFXBuyProvider extends BuyProvider { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.tron: return wallet.signMessage(message); diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index 48b46c7dd..7cd992812 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -107,6 +107,7 @@ class RobinhoodBuyProvider extends BuyProvider { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.tron: case WalletType.dogecoin: diff --git a/lib/core/payment_uris.dart b/lib/core/payment_uris.dart index 74bd73763..1a5613433 100644 --- a/lib/core/payment_uris.dart +++ b/lib/core/payment_uris.dart @@ -116,6 +116,21 @@ class ArbitrumURI extends PaymentURI { } } +class BSCURI extends PaymentURI { + BSCURI({required super.amount, required super.address}); + + @override + String toString() { + var base = 'bsc:$address'; + + if (amount.isNotEmpty) { + base += '?amount=${amount.replaceAll(',', '.')}'; + } + + return base; + } +} + class BitcoinCashURI extends PaymentURI { BitcoinCashURI({required super.amount, required super.address}); diff --git a/lib/core/seed_validator.dart b/lib/core/seed_validator.dart index 893ebfad6..1edfd9c33 100644 --- a/lib/core/seed_validator.dart +++ b/lib/core/seed_validator.dart @@ -37,6 +37,7 @@ class SeedValidator extends Validator { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return evm!.getEVMWordList(language); case WalletType.bitcoinCash: return getBitcoinWordList(language); diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index 27167bccc..a5cc435e4 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -79,6 +79,7 @@ class WalletCreationService { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.tron: case WalletType.dogecoin: diff --git a/lib/di.dart b/lib/di.dart index 05c1da248..776f52b2d 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -1202,6 +1202,7 @@ Future setup({ case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return evm!.createEVMWalletService(param1, SettingsStoreBase.walletPasswordDirectInput); case WalletType.bitcoinCash: return bitcoinCash!.createBitcoinCashWalletService(_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput); diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index a71604e64..f2684e5c4 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -51,6 +51,7 @@ const decredDefaultUri = "default-spv-nodes"; const dogecoinDefaultNodeUri = 'dogecoin.stackwallet.com:50022'; const baseDefaultNodeUri = 'base.nownodes.io'; const arbitrumDefaultNodeUri = 'arbitrum.nownodes.io'; +const bscDefaultNodeUri = 'bsc-dataseed.bnbchain.org'; const zcashDefaultNodeUri = 'zec-node.cakewallet.com:443'; Future defaultSettingsMigration( @@ -572,6 +573,14 @@ Future defaultSettingsMigration( await sharedPreferences.setString( PreferencesKey.syncStatusDisplayMode, SyncStatusDisplayMode.blocksRemaining.name); break; + case 57: + await addWalletNodeList(nodes: nodes, type: WalletType.bsc); + await _changeDefaultNode( + nodes: nodes, + sharedPreferences: sharedPreferences, + type: WalletType.bsc, + currentNodePreferenceKey: PreferencesKey.currentBscNodeIdKey, + ); default: break; } @@ -684,6 +693,8 @@ String _getDefaultNodeUri(WalletType type) { return baseDefaultNodeUri; case WalletType.arbitrum: return arbitrumDefaultNodeUri; + case WalletType.bsc: + return bscDefaultNodeUri; case WalletType.zcash: return zcashDefaultNodeUri; case WalletType.banano: @@ -1095,6 +1106,7 @@ Future checkCurrentNodes( final currentPolygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final currentBaseNodeId = sharedPreferences.getInt(PreferencesKey.currentBaseNodeIdKey); final currentArbitrumNodeId = sharedPreferences.getInt(PreferencesKey.currentArbitrumNodeIdKey); + final currentBscNodeId = sharedPreferences.getInt(PreferencesKey.currentBscNodeIdKey); final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); final currentDecredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey); @@ -1123,6 +1135,8 @@ Future checkCurrentNodes( nodeSource.values.firstWhereOrNull((node) => node.key == currentBaseNodeId); final currentArbitrumNodeServer = nodeSource.values.firstWhereOrNull((node) => node.key == currentArbitrumNodeId); + final currentBscNodeServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentBscNodeId); final currentNanoNodeServer = nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId); final currentDecredNodeServer = @@ -1228,6 +1242,12 @@ Future checkCurrentNodes( await sharedPreferences.setInt(PreferencesKey.currentArbitrumNodeIdKey, node.key as int); } + if (currentBscNodeServer == null) { + final node = Node(uri: bscDefaultNodeUri, type: WalletType.bsc); + await nodeSource.add(node); + await sharedPreferences.setInt(PreferencesKey.currentBscNodeIdKey, node.key as int); + } + if (currentSolanaNodeServer == null) { final node = Node(uri: solanaDefaultNodeUri, type: WalletType.solana); await nodeSource.add(node); diff --git a/lib/entities/ens_record.dart b/lib/entities/ens_record.dart index 8e725f21f..239b5f45c 100644 --- a/lib/entities/ens_record.dart +++ b/lib/entities/ens_record.dart @@ -38,6 +38,7 @@ class EnsRecord { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: default: return (await ens.withName(name).getAddress()).hex; } diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart index 68a99e026..bf4e05869 100644 --- a/lib/entities/node_list.dart +++ b/lib/entities/node_list.dart @@ -59,6 +59,9 @@ Future> loadDefaultNodes(WalletType type) async { case WalletType.zcash: path = 'assets/zcash_node_list.yml'; break; + case WalletType.bsc: + path = 'assets/bsc_node_list.yml'; + break; case WalletType.banano: case WalletType.none: path = ''; @@ -113,6 +116,7 @@ Future resetToDefault(Box nodeSource) async { final baseNodes = await loadDefaultNodes(WalletType.base); final arbitrumNodes = await loadDefaultNodes(WalletType.arbitrum); final zcashNodes = await loadDefaultNodes(WalletType.zcash); + final bscNodes = await loadDefaultNodes(WalletType.bsc); final nodes = moneroNodes + bitcoinElectrumServerList + @@ -129,7 +133,8 @@ Future resetToDefault(Box nodeSource) async { dogecoinElectrumServerList + baseNodes + arbitrumNodes + - zcashNodes; + zcashNodes + + bscNodes; await nodeSource.clear(); await nodeSource.addAll(nodes); diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 8cc6be1d4..08e96e92e 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -10,6 +10,7 @@ class PreferencesKey { static const currentPolygonNodeIdKey = 'current_node_id_matic'; static const currentBaseNodeIdKey = 'current_node_id_base'; static const currentArbitrumNodeIdKey = 'current_node_id_arbitrum'; + static const currentBscNodeIdKey = 'current_node_id_bsc'; static const currentNanoNodeIdKey = 'current_node_id_nano'; static const currentNanoPowNodeIdKey = 'current_node_id_nano_pow'; static const currentDecredNodeIdKey = 'current_node_id_decred'; @@ -56,6 +57,7 @@ class PreferencesKey { static const ethereumTransactionPriority = 'current_fee_priority_ethereum'; static const polygonTransactionPriority = 'current_fee_priority_polygon'; static const baseTransactionPriority = 'current_fee_priority_base'; + static const bscTransactionPriority = 'current_fee_priority_bsc'; static const bitcoinCashTransactionPriority = 'current_fee_priority_bitcoin_cash'; static const zanoTransactionPriority = 'current_fee_priority_zano'; static const wowneroTransactionPriority = 'current_fee_priority_wownero'; @@ -83,6 +85,7 @@ class PreferencesKey { static const usePolygonScan = 'use_polygonscan'; static const useBaseScan = 'use_base_scan'; static const useArbiScan = 'use_arbitrum_scan'; + static const useBscScan = 'use_bscscan'; static const useTronGrid = 'use_trongrid'; static const useMempoolFeeAPI = 'use_mempool_fee_api'; static const evmHiddenChainIds = 'evm_hidden_chain_ids'; diff --git a/lib/entities/priority_for_wallet_type.dart b/lib/entities/priority_for_wallet_type.dart index a7ae6fcbd..f41c3b34b 100644 --- a/lib/entities/priority_for_wallet_type.dart +++ b/lib/entities/priority_for_wallet_type.dart @@ -23,6 +23,7 @@ List priorityForWalletType(WalletType type) { case WalletType.ethereum: case WalletType.polygon: case WalletType.base: + case WalletType.bsc: return evm!.getTransactionPriorities(); case WalletType.bitcoinCash: return bitcoinCash!.getTransactionPriorities(); diff --git a/lib/main.dart b/lib/main.dart index 9d8a416ea..482580af1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -313,7 +313,7 @@ Future initializeAppConfigs({bool loadWallet = true}) async { payjoinSessionSource: payjoinSessionSource, anonpayInvoiceInfo: anonpayInvoiceInfo, havenSeedStore: havenSeedStore, - initialMigrationVersion: 56, + initialMigrationVersion: 57, ); } diff --git a/lib/reactions/wallet_connect.dart b/lib/reactions/wallet_connect.dart index a7929d346..2c1bece63 100644 --- a/lib/reactions/wallet_connect.dart +++ b/lib/reactions/wallet_connect.dart @@ -11,6 +11,7 @@ bool isEVMCompatibleChain(WalletType walletType) { case WalletType.ethereum: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return true; default: return false; @@ -18,7 +19,6 @@ bool isEVMCompatibleChain(WalletType walletType) { } // Blink Protection is supported on Ethereum and Base chains -//TODO: Add BNB Smart Chain to this list when we integrate it bool canSupportBlinkProtection(int? chainId) { if (chainId == null) return false; @@ -32,6 +32,7 @@ bool isNFTACtivatedChain(WalletType walletType, int? chainId) { case 8453: case 137: case 42161: + case 56: return true; default: return false; @@ -53,6 +54,7 @@ bool isWalletConnectCompatibleChain(WalletType walletType) { case WalletType.ethereum: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return true; default: return false; @@ -73,6 +75,8 @@ String getChainNameSpaceAndIdBasedOnWalletType(WalletType walletType, {int? chai return EVMChainId.base.chain(); case WalletType.arbitrum: return EVMChainId.arbitrum.chain(); + case WalletType.bsc: + return EVMChainId.bsc.chain(); case WalletType.solana: return SolanaChainId.mainnet.chain(); default: @@ -86,6 +90,7 @@ List getChainSupportedMethodsOnWalletType(WalletType walletType) { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return EVMSupportedMethods.values.map((e) => e.name).toList(); case WalletType.solana: return SolanaSupportedMethods.values.map((e) => e.name).toList(); diff --git a/lib/reactions/wallet_utils.dart b/lib/reactions/wallet_utils.dart index 9dff92f2e..1b9e3bcd0 100644 --- a/lib/reactions/wallet_utils.dart +++ b/lib/reactions/wallet_utils.dart @@ -6,6 +6,7 @@ bool isBIP39Wallet(WalletType walletType) { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.tron: case WalletType.bitcoin: @@ -46,6 +47,7 @@ bool hasTokens(WalletType walletType) { case WalletType.zano: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return true; default: return false; 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 4ab6e20b1..1ae7c210c 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 @@ -41,6 +41,7 @@ class _DesktopWalletSelectionDropDownState extends State { 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'), @@ -66,6 +66,7 @@ class MenuWidgetState extends State { Image polygonIcon; Image baseIcon; Image arbitrumIcon; + Image bscIcon; Image solanaIcon; Image tronIcon; Image wowneroIcon; @@ -258,6 +259,8 @@ class MenuWidgetState extends State { return baseIcon; case WalletType.arbitrum: return arbitrumIcon; + case WalletType.bsc: + return bscIcon; case WalletType.tron: return tronIcon; case WalletType.wownero: diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 9eaab190d..73e069bee 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -142,6 +142,14 @@ class PrivacyPage extends BasePage { _privacySettingsViewModel.setUseArbiScan(value); }, ), + if (_privacySettingsViewModel.canUseBscScan) + SettingsSwitcherCell( + title: S.current.bscscan_history, + value: _privacySettingsViewModel.useBscScan, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setUseBscScan(value); + }, + ), if (_privacySettingsViewModel.canUseTronGrid) SettingsSwitcherCell( title: S.current.trongrid_history, diff --git a/lib/src/screens/wallet_connect/services/chain_service/eth/evm_chain_id.dart b/lib/src/screens/wallet_connect/services/chain_service/eth/evm_chain_id.dart index 3acc6b7b4..d13b99bcf 100644 --- a/lib/src/screens/wallet_connect/services/chain_service/eth/evm_chain_id.dart +++ b/lib/src/screens/wallet_connect/services/chain_service/eth/evm_chain_id.dart @@ -5,6 +5,7 @@ enum EVMChainId { polygon, base, arbitrum, + bsc, } extension EVMChainIdX on EVMChainId { @@ -22,6 +23,7 @@ extension EVMChainIdX on EVMChainId { EVMChainId.polygon => 137, EVMChainId.base => 8453, EVMChainId.arbitrum => 42161, + EVMChainId.bsc => 56, }; } diff --git a/lib/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart b/lib/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart index e813f0555..0d280959b 100644 --- a/lib/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart +++ b/lib/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart @@ -22,6 +22,7 @@ class KeyServiceImpl implements WalletConnectKeyService { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return evm!.getPrivateKey(wallet); case WalletType.solana: return solana!.getPrivateKey(wallet); @@ -36,6 +37,7 @@ class KeyServiceImpl implements WalletConnectKeyService { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return evm!.getPublicKey(wallet); case WalletType.solana: return solana!.getPublicKey(wallet); diff --git a/lib/src/widgets/evm_switcher.dart b/lib/src/widgets/evm_switcher.dart index 7c5713d53..5f834d57e 100644 --- a/lib/src/widgets/evm_switcher.dart +++ b/lib/src/widgets/evm_switcher.dart @@ -14,52 +14,26 @@ class EvmSwitcherDataItem { required this.svgPath, required this.chainId, }); - - static const ethereum = EvmSwitcherDataItem( - name: 'Ethereum', - svgPath: 'assets/images/evm_switcher_icons/ethereum.svg', - chainId: 1, - ); - - static const polygon = EvmSwitcherDataItem( - name: 'Polygon', - svgPath: 'assets/images/evm_switcher_icons/polygon.svg', - chainId: 137, - ); - - static const arbitrum = EvmSwitcherDataItem( - name: 'Arbitrum', - svgPath: 'assets/images/evm_switcher_icons/arbitrum.svg', - chainId: 42161, - ); - - static const base = EvmSwitcherDataItem( - name: 'Base', - svgPath: 'assets/images/evm_switcher_icons/base.svg', - chainId: 8453, - ); - - static const items = [ - ethereum, - polygon, - arbitrum, - base, - ]; } String _getSvgPathForChain(String chainName) { final name = chainName.toLowerCase(); - if (name.contains('ethereum')) { - return 'assets/images/evm_switcher_icons/ethereum.svg'; - } else if (name.contains('polygon')) { - return 'assets/images/evm_switcher_icons/polygon.svg'; - } else if (name.contains('arbitrum')) { - return 'assets/images/evm_switcher_icons/arbitrum.svg'; - } else if (name.contains('base')) { - return 'assets/images/evm_switcher_icons/base.svg'; + + switch (name) { + case 'ethereum': + return 'assets/images/crypto/ethereum.webp'; + case 'polygon': + return 'assets/images/crypto/polygon.webp'; + case 'arbitrum': + return 'assets/images/crypto/arbitrum.webp'; + case 'base': + return 'assets/images/crypto/base_icon.webp'; + case 'bnb': + case 'bsc': + return 'assets/images/crypto/BNB.webp'; + default: + return 'assets/images/crypto/ethereum.webp'; } - // Default to ethereum if unknown - return 'assets/images/evm_switcher_icons/ethereum.svg'; } class EvmSwitcher extends StatefulWidget { diff --git a/lib/src/widgets/evm_switcher_row.dart b/lib/src/widgets/evm_switcher_row.dart index d65500217..d1c269be4 100644 --- a/lib/src/widgets/evm_switcher_row.dart +++ b/lib/src/widgets/evm_switcher_row.dart @@ -1,7 +1,7 @@ +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/src/widgets/evm_switcher.dart'; import 'package:cake_wallet/src/widgets/standard_switch.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; class EvmSwitcherRow extends StatelessWidget { const EvmSwitcherRow({ @@ -45,23 +45,24 @@ class EvmSwitcherRow extends StatelessWidget { Row( spacing: 8.0, children: [ - SvgPicture.asset( - data.svgPath, + CakeImageWidget( + imageUrl: data.svgPath, width: 16, height: 16, - colorFilter: ColorFilter.mode( - resolvedForegroundColor, BlendMode.srcIn), ), - Text(data.name, - style: TextStyle( - color: resolvedForegroundColor, fontSize: 14)), + Text( + data.name, + style: TextStyle(color: resolvedForegroundColor, fontSize: 14), + ), if (selected && !editMode) - SvgPicture.asset("assets/images/evm_switcher_checkmark.svg", - width: 18, height: 18), + CakeImageWidget( + imageUrl: "assets/images/evm_switcher_checkmark.svg", + width: 18, + height: 18, + ), ], ), - if (editMode) - StandardSwitch(value: editSwitchValue, onTapped: onTap) + if (editMode) StandardSwitch(value: editSwitchValue, onTapped: onTap) ], ), ), diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 0a57047ba..cabf3ba74 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -112,6 +112,7 @@ abstract class SettingsStoreBase with Store { required this.useEtherscan, required this.useBaseScan, required this.useArbiScan, + required this.useBscScan, required this.usePolygonScan, required this.useTronGrid, required this.useMempoolFeeAPI, @@ -146,6 +147,7 @@ abstract class SettingsStoreBase with Store { TransactionPriority? initialEVMTransactionPriority, TransactionPriority? initialPolygonTransactionPriority, TransactionPriority? initialBaseTransactionPriority, + TransactionPriority? initialBscTransactionPriority, TransactionPriority? initialBitcoinCashTransactionPriority, TransactionPriority? initialZanoTransactionPriority, TransactionPriority? initialDecredTransactionPriority, @@ -238,6 +240,10 @@ abstract class SettingsStoreBase with Store { priority[WalletType.base] = initialBaseTransactionPriority; } + if (initialBscTransactionPriority != null) { + priority[WalletType.bsc] = initialBscTransactionPriority; + } + if (initialBitcoinCashTransactionPriority != null) { priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority; } @@ -305,6 +311,9 @@ abstract class SettingsStoreBase with Store { case WalletType.base: key = PreferencesKey.baseTransactionPriority; break; + case WalletType.bsc: + key = PreferencesKey.bscTransactionPriority; + break; case WalletType.zano: key = PreferencesKey.zanoTransactionPriority; break; @@ -477,6 +486,9 @@ abstract class SettingsStoreBase with Store { reaction((_) => useArbiScan, (bool useArbiScan) => _sharedPreferences.setBool(PreferencesKey.useArbiScan, useArbiScan)); + reaction((_) => useBscScan, + (bool useBscScan) => _sharedPreferences.setBool(PreferencesKey.useBscScan, useBscScan)); + reaction((_) => useTronGrid, (bool useTronGrid) => _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid)); @@ -853,6 +865,9 @@ abstract class SettingsStoreBase with Store { @observable bool useArbiScan; + @observable + bool useBscScan; + @observable bool useTronGrid; @@ -981,6 +996,8 @@ abstract class SettingsStoreBase with Store { return PreferencesKey.currentBaseNodeIdKey; case 42161: return PreferencesKey.currentArbitrumNodeIdKey; + case 56: + return PreferencesKey.currentBscNodeIdKey; default: // Default to Ethereum for unknown chainIds return PreferencesKey.currentEthereumNodeIdKey; @@ -1043,6 +1060,7 @@ abstract class SettingsStoreBase with Store { TransactionPriority? evmTransactionPriority; TransactionPriority? polygonTransactionPriority; TransactionPriority? baseTransactionPriority; + TransactionPriority? bscTransactionPriority; TransactionPriority? bitcoinCashTransactionPriority; TransactionPriority? wowneroTransactionPriority; TransactionPriority? zanoTransactionPriority; @@ -1070,6 +1088,10 @@ abstract class SettingsStoreBase with Store { baseTransactionPriority = evm?.deserializeEVMTransactionPriority( sharedPreferences.getInt(PreferencesKey.baseTransactionPriority)!); } + if (sharedPreferences.getInt(PreferencesKey.bscTransactionPriority) != null) { + bscTransactionPriority = evm?.deserializeEVMTransactionPriority( + sharedPreferences.getInt(PreferencesKey.bscTransactionPriority)!); + } if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) { bitcoinCashTransactionPriority = bitcoinCash?.deserializeBitcoinCashTransactionPriority( sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!); @@ -1098,6 +1120,7 @@ abstract class SettingsStoreBase with Store { decredTransactionPriority ??= decred?.getDecredTransactionPriorityMedium(); polygonTransactionPriority ??= evm?.getDefaultTransactionPriority(); baseTransactionPriority ??= evm?.getDefaultTransactionPriority(); + bscTransactionPriority ??= evm?.getDefaultTransactionPriority(); zanoTransactionPriority ??= zano?.getDefaultTransactionPriority(); final currentBalanceDisplayMode = BalanceDisplayMode.deserialize( @@ -1148,6 +1171,7 @@ abstract class SettingsStoreBase with Store { final usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; final useBaseScan = sharedPreferences.getBool(PreferencesKey.useBaseScan) ?? true; final useArbiScan = sharedPreferences.getBool(PreferencesKey.useArbiScan) ?? true; + final useBscScan = sharedPreferences.getBool(PreferencesKey.useBscScan) ?? true; final useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true; final useMempoolFeeAPI = sharedPreferences.getBool(PreferencesKey.useMempoolFeeAPI) ?? true; final useBlinkProtection = sharedPreferences.getBool(PreferencesKey.useBlinkProtection) ?? true; @@ -1200,6 +1224,7 @@ abstract class SettingsStoreBase with Store { final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final baseNodeId = sharedPreferences.getInt(PreferencesKey.currentBaseNodeIdKey); final arbitrumNodeId = sharedPreferences.getInt(PreferencesKey.currentArbitrumNodeIdKey); + final bscNodeId = sharedPreferences.getInt(PreferencesKey.currentBscNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey); @@ -1225,6 +1250,8 @@ abstract class SettingsStoreBase with Store { nodeSource.values.firstWhereOrNull((e) => e.uriRaw == baseDefaultNodeUri); final arbitrumNode = nodeSource.get(arbitrumNodeId) ?? nodeSource.values.firstWhereOrNull((e) => e.uriRaw == arbitrumDefaultNodeUri); + final bscNode = nodeSource.get(bscNodeId) ?? + nodeSource.values.firstWhereOrNull((e) => e.uriRaw == bscDefaultNodeUri); final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId) ?? nodeSource.values.firstWhereOrNull((e) => e.uriRaw == cakeWalletBitcoinCashDefaultNodeUri); final nanoNode = nodeSource.get(nanoNodeId) ?? @@ -1309,6 +1336,10 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.arbitrum] = arbitrumNode; } + if (bscNode != null) { + nodes[WalletType.bsc] = bscNode; + } + if (bitcoinCashElectrumServer != null) { nodes[WalletType.bitcoinCash] = bitcoinCashElectrumServer; } @@ -1502,6 +1533,7 @@ abstract class SettingsStoreBase with Store { usePolygonScan: usePolygonScan, useBaseScan: useBaseScan, useArbiScan: useArbiScan, + useBscScan: useBscScan, useTronGrid: useTronGrid, useMempoolFeeAPI: useMempoolFeeAPI, useBlinkProtection: useBlinkProtection, @@ -1552,6 +1584,7 @@ abstract class SettingsStoreBase with Store { initialEVMTransactionPriority: evmTransactionPriority, initialPolygonTransactionPriority: polygonTransactionPriority, initialBaseTransactionPriority: baseTransactionPriority, + initialBscTransactionPriority: bscTransactionPriority, initialSyncMode: savedSyncMode, initialSyncAll: savedSyncAll, shouldShowYatPopup: shouldShowYatPopup, @@ -1607,6 +1640,10 @@ abstract class SettingsStoreBase with Store { priority[WalletType.base] = evm!.deserializeEVMTransactionPriority( sharedPreferences.getInt(PreferencesKey.baseTransactionPriority)!); } + if (evm != null && sharedPreferences.getInt(PreferencesKey.bscTransactionPriority) != null) { + priority[WalletType.bsc] = evm!.deserializeEVMTransactionPriority( + sharedPreferences.getInt(PreferencesKey.bscTransactionPriority)!); + } if (bitcoinCash != null && sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) { priority[WalletType.bitcoinCash] = bitcoinCash!.deserializeBitcoinCashTransactionPriority( @@ -1706,6 +1743,7 @@ abstract class SettingsStoreBase with Store { usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; useBaseScan = sharedPreferences.getBool(PreferencesKey.useBaseScan) ?? true; useArbiScan = sharedPreferences.getBool(PreferencesKey.useArbiScan) ?? true; + useBscScan = sharedPreferences.getBool(PreferencesKey.useBscScan) ?? true; useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true; useMempoolFeeAPI = sharedPreferences.getBool(PreferencesKey.useMempoolFeeAPI) ?? true; useBlinkProtection = sharedPreferences.getBool(PreferencesKey.useBlinkProtection) ?? true; @@ -1744,6 +1782,7 @@ abstract class SettingsStoreBase with Store { final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final baseNodeId = sharedPreferences.getInt(PreferencesKey.currentBaseNodeIdKey); final arbitrumNodeId = sharedPreferences.getInt(PreferencesKey.currentArbitrumNodeIdKey); + final bscNodeId = sharedPreferences.getInt(PreferencesKey.currentBscNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey); final tronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey); @@ -1760,6 +1799,7 @@ abstract class SettingsStoreBase with Store { final polygonNode = nodeSource.get(polygonNodeId); final baseNode = nodeSource.get(baseNodeId); final arbitrumNode = nodeSource.get(arbitrumNodeId); + final bscNode = nodeSource.get(bscNodeId); final bitcoinCashNode = nodeSource.get(bitcoinCashElectrumServerId); final nanoNode = nodeSource.get(nanoNodeId); final solanaNode = nodeSource.get(solanaNodeId); @@ -1802,6 +1842,10 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.arbitrum] = arbitrumNode; } + if (bscNode != null) { + nodes[WalletType.bsc] = bscNode; + } + if (bitcoinCashNode != null) { nodes[WalletType.bitcoinCash] = bitcoinCashNode; } @@ -1956,6 +2000,7 @@ abstract class SettingsStoreBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: final chainId = evm!.getChainIdByWalletType(node.type); final preferenceKey = _getEVMNodePreferenceKey(chainId); await _sharedPreferences.setInt(preferenceKey, node.key as int); diff --git a/lib/utils/qr_util.dart b/lib/utils/qr_util.dart index 076239511..f03937c32 100644 --- a/lib/utils/qr_util.dart +++ b/lib/utils/qr_util.dart @@ -1,26 +1,19 @@ -import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cw_core/wallet_type.dart'; -String getQrImage(WalletType type, {int? selectedChainId}) { - if (isEVMCompatibleChain(type) && selectedChainId != null) { - switch (selectedChainId) { - case 1: - return 'assets/images/eth_chain_qr.svg'; - case 137: - return 'assets/images/pol_chain_qr.svg'; - case 8453: - return 'assets/images/base_chain_QR.svg'; - case 42161: - return 'assets/images/arbitrum_chain_QR.svg'; - default: - return 'assets/images/eth_chain_qr.svg'; - } - } +String getQrImage(WalletType type) { switch (type) { - case WalletType.solana: - return 'assets/images/sol_chain_qr.svg'; + case WalletType.ethereum: + return 'assets/images/eth_chain_qr.svg'; case WalletType.polygon: return 'assets/images/pol_chain_qr.svg'; + case WalletType.base: + return 'assets/images/base_chain_QR.svg'; + case WalletType.arbitrum: + return 'assets/images/arbitrum_chain_QR.svg'; + case WalletType.bsc: + return 'assets/images/bnb_chain_QR.svg'; + case WalletType.solana: + return 'assets/images/sol_chain_qr.svg'; case WalletType.tron: return 'assets/images/trx_chain_qr.svg'; case WalletType.zano: @@ -46,32 +39,24 @@ String getQrImage(WalletType type, {int? selectedChainId}) { case WalletType.banano: case WalletType.haven: case WalletType.none: - default: return 'assets/images/qr-cake.png'; } } -String getChainMonoImage(WalletType type, {int? selectedChainId}) { - if (isEVMCompatibleChain(type) && selectedChainId != null) { - switch (selectedChainId) { - case 1: - return 'assets/images/eth_chain_mono.svg'; - case 137: - return 'assets/images/pol_chain_mono.svg'; - case 8453: - return 'assets/images/base_chain_mono.svg'; - case 42161: - return 'assets/images/arbitrum_chain_mono.svg'; - default: - return 'assets/images/eth_chain_mono.svg'; - } - } - +String getChainMonoImage(WalletType type) { switch (type) { - case WalletType.solana: - return 'assets/images/sol_chain_mono.svg'; + case WalletType.ethereum: + return 'assets/images/eth_chain_mono.svg'; case WalletType.polygon: return 'assets/images/pol_chain_mono.svg'; + case WalletType.base: + return 'assets/images/base_chain_mono.svg'; + case WalletType.arbitrum: + return 'assets/images/arbitrum_chain_mono.svg'; + case WalletType.bsc: + return 'assets/images/bnb_chain_mono.svg'; + case WalletType.solana: + return 'assets/images/sol_chain_mono.svg'; case WalletType.tron: return 'assets/images/trx_chain_mono.svg'; case WalletType.zano: diff --git a/lib/utils/token_utilities.dart b/lib/utils/token_utilities.dart index 4ba52e6b0..e76544f4a 100644 --- a/lib/utils/token_utilities.dart +++ b/lib/utils/token_utilities.dart @@ -89,6 +89,7 @@ class TokenUtilities { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: final tokens = await loadAllUniqueEvmTokens(); for (final t in tokens) { if (t.contractAddress.toLowerCase() == lower) return t; @@ -127,6 +128,7 @@ class TokenUtilities { WalletType.polygon => '${walletKey}_${Erc20Token.polygonBoxName}', WalletType.base => '${walletKey}_${Erc20Token.baseBoxName}', WalletType.arbitrum => '${walletKey}_${Erc20Token.arbitrumBoxName}', + WalletType.bsc => '${walletKey}_${Erc20Token.bscBoxName}', _ => '${walletKey}_${Erc20Token.ethereumBoxName}', }; } @@ -185,7 +187,8 @@ class TokenUtilities { // Only check EVM registry for currencies that might be EVM-related final isPotentialEVM = isNativeToken(currency) || - (tag != null && (tag == 'ETH' || tag == 'POL' || tag == 'BASE' || tag == 'ARB')); + (tag != null && + (tag == 'ETH' || tag == 'POL' || tag == 'BASE' || tag == 'ARB' || tag == 'BSC')); if (isPotentialEVM) { // Try by tag first if available (e.g., 'POL', 'BASE', 'ARB') @@ -200,11 +203,6 @@ class TokenUtilities { } // Fallback to hardcoded values for chains not in registry yet - // BSC (Binance Smart Chain) - if (title == 'bsc' || title == 'bnb' || tag == 'BSC') { - return 56; - } - // Avalanche C-Chain if (title == 'avalanche' || title == 'avax' || tag == 'AVALANCHE') { return 43114; diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index 6a491f986..d594f087f 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -55,6 +55,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.tron: case WalletType.zcash: @@ -98,6 +99,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { WalletType.polygon, WalletType.base, WalletType.arbitrum, + WalletType.bsc, WalletType.tron, WalletType.solana, WalletType.monero, diff --git a/lib/view_model/anon_invoice_page_view_model.dart b/lib/view_model/anon_invoice_page_view_model.dart index d24a5602f..9adc9c84b 100644 --- a/lib/view_model/anon_invoice_page_view_model.dart +++ b/lib/view_model/anon_invoice_page_view_model.dart @@ -5,7 +5,6 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/utils/qr_util.dart'; -import 'package:cw_core/currency_for_wallet_type.dart'; import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -177,7 +176,7 @@ abstract class AnonInvoicePageViewModelBase with Store { String get currentWalletName => _wallet.name; @computed - String get qrImage => getQrImage(_wallet.type, selectedChainId: _wallet.chainId); + String get qrImage => getQrImage(_wallet.type); @action void reset() { diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 36987916d..ded394207 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -177,6 +177,7 @@ abstract class BalanceViewModelBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.tron: return S.current.xmr_full_balance; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index d01c39f4e..f1ee457e3 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -947,6 +947,7 @@ abstract class DashboardViewModelBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.nano: case WalletType.banano: diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index dc6d54dd4..5de47abc1 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -211,6 +211,7 @@ abstract class HomeSettingsViewModelBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: defaultTokenAddresses = evm!.getDefaultTokenContractAddresses(_balanceViewModel.wallet); break; case WalletType.solana: diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index 8aef7a8b7..d9c72f8cc 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -174,6 +174,7 @@ class TransactionListItem extends ActionListItem with Keyable { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: final asset = evm!.assetOfTransaction(balanceViewModel.wallet, transaction); final price = balanceViewModel.fiatConvertationStore.prices[asset]; amount = calculateFiatAmountRaw( diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 58a170203..39a063575 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -365,6 +365,9 @@ abstract class ExchangeTradeViewModelBase with Store { bool _isSplToken() => wallet.currency == CryptoCurrency.sol && tradeFrom?.tag == CryptoCurrency.sol.title; + bool _isBscToken() => + wallet.currency == CryptoCurrency.bnb && tradeFrom?.tag == CryptoCurrency.bnb.tag; + return tradeFrom == wallet.currency || tradesStore.trade!.provider == ExchangeProviderDescription.xmrto || _isEthToken() || @@ -372,7 +375,8 @@ abstract class ExchangeTradeViewModelBase with Store { _isSplToken() || _isTronToken() || _isBaseToken() || - _isArbitrumToken(); + _isArbitrumToken() || + _isBscToken(); } Future registerSwapsXyzTransaction() async { @@ -452,6 +456,8 @@ abstract class ExchangeTradeViewModelBase with Store { return BaseURI(amount: amount, address: inputAddress); case WalletType.arbitrum: return ArbitrumURI(amount: amount, address: inputAddress); + case WalletType.bsc: + return BSCURI(amount: amount, address: inputAddress); case WalletType.solana: return SolanaURI(amount: amount, address: inputAddress); case WalletType.tron: @@ -503,5 +509,5 @@ abstract class ExchangeTradeViewModelBase with Store { } @computed - String get qrImage => getQrImage(wallet.type, selectedChainId: wallet.chainId); + String get qrImage => getQrImage(wallet.type); } diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index c023f91b2..69152d707 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -904,6 +904,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with depositCurrency = CryptoCurrency.arbEth; receiveCurrency = CryptoCurrency.xmr; break; + case WalletType.bsc: + depositCurrency = CryptoCurrency.bnb; + receiveCurrency = CryptoCurrency.xmr; + break; case WalletType.solana: depositCurrency = CryptoCurrency.sol; receiveCurrency = CryptoCurrency.xmr; diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index c833b37fa..18ec024f5 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -82,6 +82,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.banano: case WalletType.nano: diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index e1a8be02f..5548d29eb 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -33,6 +33,7 @@ class WalletRestoreFromQRCode { 'polygon-wallet': WalletType.polygon, 'base-wallet': WalletType.base, 'arbitrum-wallet': WalletType.arbitrum, + 'bsc-wallet': WalletType.bsc, 'nano-wallet': WalletType.nano, 'nano_wallet': WalletType.nano, 'bitcoincash': WalletType.bitcoinCash, diff --git a/lib/view_model/send/fees_view_model.dart b/lib/view_model/send/fees_view_model.dart index cb3b596af..c9f0059cd 100644 --- a/lib/view_model/send/fees_view_model.dart +++ b/lib/view_model/send/fees_view_model.dart @@ -90,6 +90,7 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor case WalletType.ethereum: case WalletType.polygon: case WalletType.base: + case WalletType.bsc: return transactionPriority == evm!.getEVMTransactionPrioritySlow(); case WalletType.bitcoinCash: return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow(); @@ -199,6 +200,7 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor case WalletType.ethereum: case WalletType.polygon: case WalletType.base: + case WalletType.bsc: _settingsStore.setPriority( wallet.type, evm!.getDefaultTransactionPriority(), diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 16864d450..715c36e7e 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -117,6 +117,7 @@ abstract class OutputBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: _amount = evm!.formatterEVMParseAmount(_cryptoAmount); break; case WalletType.wownero: @@ -218,10 +219,12 @@ abstract class OutputBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: final isNative = cryptoCurrencyHandler() == CryptoCurrency.eth || cryptoCurrencyHandler() == CryptoCurrency.maticpoly || cryptoCurrencyHandler() == CryptoCurrency.baseEth || - cryptoCurrencyHandler() == CryptoCurrency.arbEth; + cryptoCurrencyHandler() == CryptoCurrency.arbEth || + cryptoCurrencyHandler() == CryptoCurrency.bnb; String? fee = isNative ? evm!.getEVMNativeEstimatedFee(_wallet) : evm!.getEVMERC20EstimatedFee(_wallet); diff --git a/lib/view_model/send/send_template_view_model.dart b/lib/view_model/send/send_template_view_model.dart index 9a01f0ac4..f1b8a8546 100644 --- a/lib/view_model/send/send_template_view_model.dart +++ b/lib/view_model/send/send_template_view_model.dart @@ -61,10 +61,7 @@ abstract class SendTemplateViewModelBase with Store { _wallet.type != WalletType.haven && _wallet.type != WalletType.solana && _wallet.type != WalletType.tron && - _wallet.chainId != 1 && - _wallet.chainId != 137 && - _wallet.chainId != 8453 && - _wallet.chainId != 42161; + !isEVMCompatibleChain(_wallet.type); @computed CryptoCurrency get cryptoCurrency => _wallet.currency; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 9eabb0244..3db878c2d 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -243,6 +243,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.tron: case WalletType.solana: return wallet.currency; @@ -1005,6 +1006,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return evm!.createEVMTransactionCredentials( outputs, priority: priority, @@ -1166,6 +1168,12 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } if (errorMessage.contains('insufficient funds')) { + final feeCurrency = switch (walletType) { + WalletType.bsc => "BNB", + WalletType.polygon => "POL", + _ => "ETH", + }; + final parsedErrorMessageResult = EVMTransactionErrorFeesHandler.parseEthereumFeesErrorMessage( errorMessage, @@ -1184,9 +1192,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor // Handle successfully parsed errors with specific values return '''${S.current.insufficient_funds_for_tx} \n\n''' - '''${S.current.balance}: ${parsedErrorMessageResult.balanceEth} ${walletType == WalletType.polygon ? "POL" : "ETH"} (${parsedErrorMessageResult.balanceUsd} ${fiatFromSettings.name})\n\n''' - '''${S.current.transaction_cost}: ${parsedErrorMessageResult.txCostEth} ${walletType == WalletType.polygon ? "POL" : "ETH"} (${parsedErrorMessageResult.txCostUsd} ${fiatFromSettings.name})\n\n''' - '''${S.current.overshot}: ${parsedErrorMessageResult.overshotEth} ${walletType == WalletType.polygon ? "POL" : "ETH"} (${parsedErrorMessageResult.overshotUsd} ${fiatFromSettings.name})'''; + '''${S.current.balance}: ${parsedErrorMessageResult.balanceEth} ${feeCurrency} (${parsedErrorMessageResult.balanceUsd} ${fiatFromSettings.name})\n\n''' + '''${S.current.transaction_cost}: ${parsedErrorMessageResult.txCostEth} ${feeCurrency} (${parsedErrorMessageResult.txCostUsd} ${fiatFromSettings.name})\n\n''' + '''${S.current.overshot}: ${parsedErrorMessageResult.overshotEth} ${feeCurrency} (${parsedErrorMessageResult.overshotUsd} ${fiatFromSettings.name})'''; } if (errorMessage.contains('max fee per gas less than block base fee')) { diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 94385e3e6..e716401ec 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -81,6 +81,9 @@ abstract class PrivacySettingsViewModelBase with Store { @computed bool get useArbiScan => _settingsStore.useArbiScan; + @computed + bool get useBscScan => _settingsStore.useBscScan; + @computed bool get useTronGrid => _settingsStore.useTronGrid; @@ -127,6 +130,8 @@ abstract class PrivacySettingsViewModelBase with Store { bool get canUseArbiScan => _wallet.chainId == 42161; + bool get canUseBscScan => _wallet.chainId == 56; + bool get canUseTronGrid => _wallet.type == WalletType.tron; bool get canUseMempoolFeeAPI => _wallet.type == WalletType.bitcoin; @@ -210,6 +215,12 @@ abstract class PrivacySettingsViewModelBase with Store { evm!.updateScanProviderUsageState(_wallet, value); } + @action + void setUseBscScan(bool value) { + _settingsStore.useBscScan = value; + evm!.updateScanProviderUsageState(_wallet, value); + } + @action void setUseMempoolFeeAPI(bool value) => _settingsStore.useMempoolFeeAPI = value; diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 37e403410..70a12fad6 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -5,7 +5,6 @@ import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/evm/evm.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; @@ -72,6 +71,7 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: _addEVMListItems(tx, dateFormat); break; case WalletType.nano: @@ -195,6 +195,8 @@ abstract class TransactionDetailsViewModelBase with Store { return 'https://basescan.org/tx/${txId}'; case WalletType.arbitrum: return 'https://arbiscan.io/tx/${txId}'; + case WalletType.bsc: + return 'https://bscscan.com/tx/${txId}'; case WalletType.polygon: return 'https://polygonscan.com/tx/${txId}'; case WalletType.nano: @@ -246,6 +248,8 @@ abstract class TransactionDetailsViewModelBase with Store { return S.current.view_transaction_on + 'nanexplorer.com'; case WalletType.polygon: return S.current.view_transaction_on + 'polygonscan.com'; + case WalletType.bsc: + return S.current.view_transaction_on + 'bscscan.com'; case WalletType.solana: return S.current.view_transaction_on + 'solscan.io'; case WalletType.tron: 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 1ad9c927b..79cfa77ea 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 @@ -126,6 +126,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return BaseURI(amount: amount, address: address.address); case 42161: return ArbitrumURI(amount: amount, address: address.address); + case 56: + return BSCURI(amount: amount, address: address.address); default: return EthereumURI(amount: amount, address: address.address); } @@ -166,6 +168,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return BaseURI(amount: amount, address: address.address); case WalletType.arbitrum: return ArbitrumURI(amount: amount, address: address.address); + case WalletType.bsc: + return BSCURI(amount: amount, address: address.address); case WalletType.zcash: return ZcashURI(amount: amount, address: address.address); case WalletType.none: @@ -436,7 +440,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo switch (chainId) { case 1: return [ - 'assets/images/eth_icon.svg', + 'assets/images/crypto/ethereum.webp', 'assets/images/usdc_icon.svg', 'assets/images/usdt_wallet_icon.svg', 'assets/images/deuro_icon.svg', @@ -444,7 +448,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo ]; case 137: return [ - 'assets/images/pol_icon.svg', + 'assets/images/crypto/polygon.webp', 'assets/images/eth_pol_icon.svg', 'assets/images/usdc_icon.svg', 'assets/images/usdt_wallet_icon.svg', @@ -452,7 +456,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo ]; case 8453: return [ - 'assets/images/eth_icon.svg', + 'assets/images/crypto/ethereum.webp', 'assets/images/usdc_icon.svg', 'assets/images/more_tokens.svg', ]; @@ -462,9 +466,16 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo 'assets/images/usdc_icon.svg', 'assets/images/more_tokens.svg', ]; + case 56: + return [ + 'assets/images/crypto/BNB.webp', + 'assets/images/usdc_icon.svg', + 'assets/images/usdt_wallet_icon.svg', + 'assets/images/more_tokens.svg', + ]; default: return [ - 'assets/images/eth_icon.svg', + 'assets/images/crypto/ethereum.webp', 'assets/images/usdc_icon.svg', 'assets/images/usdt_wallet_icon.svg', ]; @@ -497,10 +508,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo } @computed - String get qrImage => getQrImage(type, selectedChainId: selectedChainId); + String get qrImage => getQrImage(type); @computed - String get monoImage => getChainMonoImage(type, selectedChainId: selectedChainId); + String get monoImage => getChainMonoImage(type); @computed bool get isBalanceAvailable => isElectrumWallet; diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index c8257d8c4..002f574c0 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -143,6 +143,7 @@ abstract class WalletKeysViewModelBase with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.solana: case WalletType.zcash: case WalletType.tron: @@ -274,6 +275,8 @@ abstract class WalletKeysViewModelBase with Store { return 'base-wallet'; case WalletType.arbitrum: return 'arbitrum-wallet'; + case WalletType.bsc: + return 'bsc-wallet'; case WalletType.solana: return 'solana-wallet'; case WalletType.tron: diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index d1c6f2ce0..cb2f3ed7f 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -82,6 +82,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return evm!.createEVMNewWalletCredentials( name: name, password: walletPassword, diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index d7e668f72..e212e4c99 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -53,6 +53,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: case WalletType.decred: case WalletType.bitcoin: case WalletType.litecoin: @@ -82,18 +83,15 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { late final bool hasSeedLanguageSelector = [WalletType.monero, WalletType.haven, WalletType.wownero].contains(type); - late final bool hasBlockchainHeightSelector = [ - WalletType.monero, - WalletType.haven, - WalletType.wownero, - WalletType.zcash - ].contains(type); - + late final bool hasBlockchainHeightSelector = + [WalletType.monero, WalletType.haven, WalletType.wownero, WalletType.zcash].contains(type); + late final bool hasRestoreFromPrivateKey = [ WalletType.ethereum, WalletType.polygon, WalletType.base, WalletType.arbitrum, + WalletType.bsc, WalletType.nano, WalletType.banano, WalletType.solana, @@ -171,6 +169,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return evm!.createEVMRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, @@ -209,9 +208,9 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { ); case WalletType.decred: return decred!.createDecredRestoreWalletFromSeedCredentials( - name: name, - mnemonic: seed, - password: password, + name: name, + mnemonic: seed, + password: password, ); case WalletType.zcash: return zcash!.createZcashRestoreWalletFromSeedCredentials( @@ -274,6 +273,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: + case WalletType.bsc: return evm!.createEVMRestoreWalletFromPrivateKey( name: name, password: password, diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 4c119500e..f8016d3e4 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -243,6 +243,7 @@ flutter: - assets/base_node_list.yml - assets/arbitrum_node_list.yml - assets/zcash_node_list.yml + - assets/bsc_node_list.yml - assets/text/ - assets/faq/ - assets/animation/ diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 78ed3d845..c782c27f3 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "بلوك متبقي ${status}", "bluetooth": "بلوتوث", "bright_theme": "مشرق", + "bscscan_history": "تاريخ المسح BCS", "bump_fee": "رسوم عثرة", "buy": "اشتري", "buy_alert_content": ".ﺎﻬﻴﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ Monero ﻭﺃ Litecoin ﻭﺃ Ethereum ﻭﺃ Bitcoin ﺔﻈﻔﺤﻣ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index dd34cfce3..a47b5ed17 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} оставащи блока", "bluetooth": "Bluetooth", "bright_theme": "Ярко", + "bscscan_history": "История на BSCScan", "bump_fee": "Такса за бум", "buy": "Купуване", "buy_alert_content": "В момента поддържаме само закупуването на Bitcoin, Ethereum, Litecoin и Monero. Моля, създайте или превключете към своя портфейл Bitcoin, Ethereum, Litecoin или Monero.", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 4381285f9..166f91f33 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "Zbývá ${status} bloků", "bluetooth": "Bluetooth", "bright_theme": "Jasný", + "bscscan_history": "Historie BSCScan", "bump_fee": "Bump Fee", "buy": "Koupit", "buy_alert_content": "V současné době podporujeme pouze nákup bitcoinů, etherea, litecoinů a monero. Vytvořte nebo přepněte na svou peněženku bitcoinů, etherea, litecoinů nebo monero.", @@ -1172,4 +1173,4 @@ "youCanGoBackToYourDapp": "Nyní se můžete vrátit do svého dappu", "your": "Vaše", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 8f0d7eb51..1d026038c 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} verbleibende Blöcke", "bluetooth": "Bluetooth", "bright_theme": "Strahlend hell", + "bscscan_history": "BSCScan-Verlauf", "bump_fee": "Gebühr erhöhen", "buy": "Kaufen", "buy_alert_content": "Derzeit unterstützen wir nur den Kauf von Bitcoin, Ethereum, Litecoin und Monero. Bitte erstellen Sie Ihr Bitcoin-, Ethereum-, Litecoin- oder Monero-Wallet oder wechseln Sie zu diesem.", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index fdc515e91..74b4b2e0b 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Blocks Remaining", "bluetooth": "Bluetooth", "bright_theme": "Bright", + "bscscan_history": "BSCScan History", "bump_fee": "Bump fee", "buy": "Buy", "buy_alert_content": "Currently we only support the purchase of Bitcoin, Ethereum, Litecoin, and Monero. Please create or switch to your Bitcoin, Ethereum, Litecoin, or Monero wallet.", @@ -1173,4 +1174,4 @@ "youCanGoBackToYourDapp": "You can go back to your dApp now", "your": "Your", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index d0a443777..65712e661 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Bloques Restantes", "bluetooth": "Bluetooth", "bright_theme": "Claro", + "bscscan_history": "Historia del escaneo BSC", "bump_fee": "Aumentar tarifa", "buy": "Comprar", "buy_alert_content": "Actualmente solo permitimos la compra de Bitcoin, Ethereum, Litecoin y Monero. Cree o cambie a su billetera de Bitcoin, Ethereum, Litecoin o Monero.", @@ -1174,4 +1175,4 @@ "youCanGoBackToYourDapp": "Ahora puedes volver a tu dApp", "your": "Tu", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_fa.arb b/res/values/strings_fa.arb index 86cf69084..faeca5aa5 100644 --- a/res/values/strings_fa.arb +++ b/res/values/strings_fa.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} بلاک باقی‌مانده", "bluetooth": "بلوتوث", "bright_theme": "روشن", + "bscscan_history": "تاریخچه BSCScan", "bump_fee": "افزایش کارمزد", "buy": "خرید", "buy_alert_content": "در حال حاضر ما فقط از خرید بیت‌کوین، اتریوم، لایت‌کوین و مونرو پشتیبانی می‌کنیم.\nلطفاً کیف پول بیت‌کوین، اتریوم، لایت‌کوین یا مونرو خود را ایجاد کرده یا به آن تغییر دهید.", @@ -1171,4 +1172,4 @@ "youCanGoBackToYourDapp": "اکنون می‌توانید به dApp خود بازگردید", "your": "شما", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 4a3e73c74..cb1b42ed8 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "Blocs Restants : ${status}", "bluetooth": "Bluetooth", "bright_theme": "Vif", + "bscscan_history": "Historique du BSCScan", "bump_fee": "Augmenter les frais", "buy": "Acheter", "buy_alert_content": "Actuellement, nous ne prenons en charge que l'achat de Bitcoin, Ethereum, Litecoin et Monero. Veuillez créer ou basculer vers votre portefeuille Bitcoin, Ethereum, Litecoin ou Monero.", diff --git a/res/values/strings_gn.arb b/res/values/strings_gn.arb index 4815b5a75..2c64db542 100644 --- a/res/values/strings_gn.arb +++ b/res/values/strings_gn.arb @@ -84,6 +84,7 @@ "Blocks_remaining": "${status} Bloque hembýva", "bluetooth": "Bluetooth", "bright_theme": "Omimbiva", + "bscscan_history": "BSCSCAN HISTORIA GUARANI .", "bump_fee": "Mba’erepy", "buy": "Ejogua", "buy_alert_content": "Ko’ág̃a romoneĩnte Bitcoin, Ethereum, Litecoin ha Monero jejogua. Remoheñóĩ térã reiporavo nde virurenda peteĩva ko’ãva apytégui.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 4601874e1..c755a98aa 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Katanga ya rage", "bluetooth": "Bluetooth", "bright_theme": "Mai haske", + "bscscan_history": "Tarihin BCSC", "bump_fee": "Buin", "buy": "Sayi", "buy_alert_content": "A halin yanzu muna tallafawa kawai siyan Bitcoin, Ethereum, Litecoin, da Monero. Da fatan za a ƙirƙiri ko canza zuwa Bitcoin, Ethereum, Litecoin, ko Monero walat.", @@ -1175,4 +1176,4 @@ "youCanGoBackToYourDapp": "Kuna iya komawa zuwa DPP ɗinku yanzu", "your": "Naku", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index e17d9a00c..1b9e681e6 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} शेष रहते हैं", "bluetooth": "ब्लूटूथ", "bright_theme": "उज्ज्वल", + "bscscan_history": "बीएससीस्कैन इतिहास", "bump_fee": "बम्प फीस", "buy": "खरीदें", "buy_alert_content": "वर्तमान में हम केवल बिटकॉइन, एथेरियम, लाइटकॉइन और मोनेरो की खरीद का समर्थन करते हैं। कृपया अपना बिटकॉइन, एथेरियम, लाइटकॉइन, या मोनेरो वॉलेट बनाएं या उस पर स्विच करें।", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index a27d7e27d..f009db3fb 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} preostalih blokova", "bluetooth": "Bluetooth", "bright_theme": "Jarka", + "bscscan_history": "BSCScan povijest", "bump_fee": "Naplata", "buy": "Kupi", "buy_alert_content": "Trenutno podržavamo samo kupnju Bitcoina, Ethereuma, Litecoina i Monera. Izradite ili prijeđite na svoj Bitcoin, Ethereum, Litecoin ili Monero novčanik.", @@ -1172,4 +1173,4 @@ "youCanGoBackToYourDapp": "Sada se možete vratiti na svoj dapp", "your": "Vaš", "yy": "GG" -} +} \ No newline at end of file diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index 8051324e8..1e92f7e7d 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Բլոկ է մնացել", "bluetooth": "Bluetooth", "bright_theme": "Պայծառ", + "bscscan_history": "BSCScan պատմություն", "bump_fee": "Բարձրացնել միջնորդավճարը", "buy": "Գնել", "buy_alert_content": "Այժմ մենք աջակցում ենք միայն Bitcoin, Ethereum, Litecoin և Monero արժույթների գնմանը: Խնդրում ենք ստեղծել կամ վերածանցել Bitcoin, Ethereum, Litecoin կամ Monero արժույթների հաշիվը։", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index ca333a118..ccaf0ef56 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Blok Tersisa", "bluetooth": "Bluetooth", "bright_theme": "Cerah", + "bscscan_history": "Sejarah Pemindaian BSCS", "bump_fee": "Biaya benjolan", "buy": "Beli", "buy_alert_content": "Saat ini kami hanya mendukung pembelian Bitcoin, Ethereum, Litecoin, dan Monero. Harap buat atau alihkan ke dompet Bitcoin, Ethereum, Litecoin, atau Monero Anda.", @@ -1175,4 +1176,4 @@ "youCanGoBackToYourDapp": "Anda dapat kembali ke dapp Anda sekarang", "your": "Milikmu", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index f37f4fa3c..a3143a43a 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Blocchi Rimanenti", "bluetooth": "Bluetooth", "bright_theme": "Chiaro", + "bscscan_history": "Cronologia della scansione BSCS", "bump_fee": "Commissione per bump", "buy": "Compra", "buy_alert_content": "Attualmente supportiamo solo l'acquisto di Bitcoin, Ethereum, Litecoin e Monero. Crea o passa al tuo portafoglio Bitcoin, Ethereum, Litecoin o Monero.", @@ -1175,4 +1176,4 @@ "youCanGoBackToYourDapp": "Puoi tornare al tuo DApp ora", "your": "Tuo", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3662d8fec..b94f177b0 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} 残りのブロック", "bluetooth": "ブルートゥース", "bright_theme": "明るい", + "bscscan_history": "BSCSスキャン履歴", "bump_fee": "バンプ料金", "buy": "購入", "buy_alert_content": "現在、ビットコイン、イーサリアム、ライトコイン、モネロの購入のみをサポートしています。ビットコイン、イーサリアム、ライトコイン、またはモネロのウォレットを作成するか、これらのウォレットに切り替えてください。", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 5acd35f73..136784919 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} 블록 남음", "bluetooth": "블루투스", "bright_theme": "밝은 테마", + "bscscan_history": "BSC스캔 기록", "bump_fee": "수수료 인상", "buy": "구매", "buy_alert_content": "현재 비트코인, 이더리움, 라이트코인, 모네로만 구매를 지원합니다. 비트코인, 이더리움, 라이트코인 또는 모네로 지갑을 생성하거나 전환하세요.", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 069831d41..dad217e01 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} ဘလောက်များ ကျန်နေပါသည်။", "bluetooth": "ဘလူးတုသ်", "bright_theme": "တောက်ပ", + "bscscan_history": "BSCScan သမိုင်း", "bump_fee": "ဝင်ငွေ", "buy": "ဝယ်ပါ။", "buy_alert_content": "လက်ရှိတွင် ကျွန်ုပ်တို့သည် Bitcoin၊ Ethereum၊ Litecoin နှင့် Monero တို့ကိုသာ ဝယ်ယူမှုကို ပံ့ပိုးပေးပါသည်။ သင်၏ Bitcoin၊ Ethereum၊ Litecoin သို့မဟုတ် Monero ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index ac50d866b..c9063b47b 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Resterende blokken", "bluetooth": "Bluetooth", "bright_theme": "Helder", + "bscscan_history": "BSCcan-geschiedenis", "bump_fee": "Bult fee", "buy": "Kopen", "buy_alert_content": "Momenteel ondersteunen we alleen de aankoop van Bitcoin, Ethereum, Litecoin en Monero. Maak of schakel over naar uw Bitcoin-, Ethereum-, Litecoin- of Monero-portemonnee.", @@ -1173,4 +1174,4 @@ "youCanGoBackToYourDapp": "U kunt nu terug naar uw DApp gaan", "your": "Jouw", "yy": "JJ" -} +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 580ffaddd..39dfc30c7 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "Pozostało ${status} bloków", "bluetooth": "Bluetooth", "bright_theme": "Jasny", + "bscscan_history": "Historia skanowania BSCS", "bump_fee": "Zwiększ opłatę", "buy": "Kup", "buy_alert_content": "Obecnie obsługujemy wyłącznie zakup Bitcoin, Ethereum, Litecoin i Monero. Utwórz lub przełącz się na swój portfel Bitcoin, Ethereum, Litecoin lub Monero.", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index e2d84478f..9c6868241 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} blocos restantes", "bluetooth": "Bluetooth", "bright_theme": "Brilhante", + "bscscan_history": "Histórico do BSC Scan", "bump_fee": "Taxa de aumento", "buy": "Comprar", "buy_alert_content": "Atualmente, oferecemos suporte apenas à compra de Bitcoin, Ethereum, Litecoin e Monero. Crie ou troque para sua carteira Bitcoin, Ethereum, Litecoin ou Monero.", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b583acc33..d6cf0a24d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Осталось блоков", "bluetooth": "Bluetooth", "bright_theme": "Яркая", + "bscscan_history": "История BSCскана", "bump_fee": "Повысить комиссию", "buy": "Купить", "buy_alert_content": "В настоящее время мы поддерживаем только покупку биткойнов, Ethereum, Litecoin и Monero. Пожалуйста, создайте или переключитесь на свой кошелек Bitcoin, Ethereum, Litecoin или Monero.", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index e78c5a02a..bdeebd7f4 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} บล็อกที่เหลืออยู่", "bluetooth": "บลูทู ธ", "bright_theme": "สดใส", + "bscscan_history": "ประวัติ BCScan", "bump_fee": "ค่าธรรมเนียมชน", "buy": "ซื้อ", "buy_alert_content": "ขณะนี้เรารองรับการซื้อ Bitcoin, Ethereum, Litecoin และ Monero เท่านั้น โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงิน Bitcoin, Ethereum, Litecoin หรือ Monero", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index c9cdf5f14..838723860 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "Ang natitirang ${status} ay natitira", "bluetooth": "Bluetooth", "bright_theme": "Bright", + "bscscan_history": "Kasaysayan ng BSCScan", "bump_fee": "Dagdagan ang fee", "buy": "Bumili", "buy_alert_content": "Sa kasalukuyan ay sinusuportahan lamang namin ang pagbili ng Bitcoin, Ethereum, Litecoin, at Monero. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum, Litecoin, o Monero Wallet.", @@ -1172,4 +1173,4 @@ "youCanGoBackToYourDapp": "Maaari kang bumalik sa iyong dapp ngayon", "your": "IYONG", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index c9f8680b4..32261b3ef 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Blok Kaldı", "bluetooth": "Bluetooth", "bright_theme": "Parlak", + "bscscan_history": "BSCScan Geçmişi", "bump_fee": "Çarpma ücreti", "buy": "Alış", "buy_alert_content": "Şu anda yalnızca Bitcoin, Ethereum, Litecoin ve Monero satın alımını destekliyoruz. Lütfen Bitcoin, Ethereum, Litecoin veya Monero cüzdanınızı oluşturun veya cüzdanınıza geçin.", @@ -1172,4 +1173,4 @@ "youCanGoBackToYourDapp": "Şimdi Dapp'ınıza geri dönebilirsin", "your": "Senin", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index e3ee842af..a3c3d4cf3 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} Залишилось блоків", "bluetooth": "Блюдот", "bright_theme": "Яскрава", + "bscscan_history": "Історія BSCScan", "bump_fee": "Підвищити комісію", "buy": "Купити", "buy_alert_content": "Наразі ми підтримуємо купівлю лише Bitcoin, Ethereum, Litecoin і Monero. Створіть або перейдіть на свій гаманець Bitcoin, Ethereum, Litecoin або Monero.", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index a293589ea..e88065f5d 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} بلاکس باقی ہیں۔", "bluetooth": "بلوٹوتھ", "bright_theme": "روشن", + "bscscan_history": "BSCSCAN کی تاریخ", "bump_fee": "بمپ فیس", "buy": "خریدنے", "buy_alert_content": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﭧﯿﻟﺍﻭ Monero ﺎﯾ ،Bitcoin، Ethereum، Litecoin ﺎﻨﭘﺍ ﻡ", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index e61543dfc..3499954fe 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "${status} khối còn lại", "bluetooth": "Bluetooth", "bright_theme": "Sáng", + "bscscan_history": "Lịch sử quét BSCS", "bump_fee": "Tăng phí", "buy": "Mua", "buy_alert_content": "Hiện tại chúng tôi chỉ hỗ trợ mua Bitcoin, Ethereum, Litecoin, và Monero. Vui lòng tạo hoặc chuyển sang ví Bitcoin, Ethereum, Litecoin, hoặc Monero của bạn.", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 309c4cf92..812cc2457 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "Àkójọpọ̀ ${status} kikù", "bluetooth": "Bluetooth", "bright_theme": "Funfun", + "bscscan_history": "BCScan itan", "bump_fee": "Ọya ija", "buy": "Rà", "buy_alert_content": "Lọwọlọwọ a ṣe atilẹyin rira Bitcoin, Ethereum, Litecoin, ati Monero. Jọwọ ṣẹda tabi yipada si Bitcoin, Ethereum, Litecoin, tabi apamọwọ Monero.", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 58a66d9e8..d68bbac8d 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -102,6 +102,7 @@ "Blocks_remaining": "剩余 ${status} 区块", "bluetooth": "蓝牙", "bright_theme": "明亮", + "bscscan_history": "BSC扫描历史", "bump_fee": "追加手续费(RBF)", "buy": "购买", "buy_alert_content": "目前仅支持购买比特币、以太坊、莱特币和门罗币。请创建或切换相应钱包。", diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh index f95f63532..9cf8976d6 100755 --- a/scripts/android/pubspec_gen.sh +++ b/scripts/android/pubspec_gen.sh @@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred --dogecoin --base --zcash --arbitrum" + CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred --dogecoin --base --zcash --arbitrum --bsc" ;; esac diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh index 8991921e0..70577e4da 100755 --- a/scripts/ios/app_config.sh +++ b/scripts/ios/app_config.sh @@ -31,7 +31,7 @@ case $APP_IOS_TYPE in ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred --dogecoin --base --zcash --arbitrum" + CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred --dogecoin --base --zcash --arbitrum --bsc" ;; esac diff --git a/scripts/linux/app_config.sh b/scripts/linux/app_config.sh index 78f01fa8d..050bee6c7 100755 --- a/scripts/linux/app_config.sh +++ b/scripts/linux/app_config.sh @@ -13,7 +13,7 @@ CONFIG_ARGS="" case $APP_LINUX_TYPE in $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --dogecoin --base --arbitrum --excludeFlutterSecureStorage";; + CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --dogecoin --base --arbitrum --bsc --excludeFlutterSecureStorage";; esac cp -rf pubspec_description.yaml pubspec.yaml diff --git a/scripts/macos/app_config.sh b/scripts/macos/app_config.sh index 589b5ec1d..64ae2dd96 100755 --- a/scripts/macos/app_config.sh +++ b/scripts/macos/app_config.sh @@ -36,7 +36,7 @@ case $APP_MACOS_TYPE in $MONERO_COM) CONFIG_ARGS="--monero";; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --dogecoin --base --arbitrum";; + CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --dogecoin --base --arbitrum --bsc";; esac cp -rf pubspec_description.yaml pubspec.yaml diff --git a/tool/configure.dart b/tool/configure.dart index 7602672d8..4e2fda080 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -34,8 +34,9 @@ Future main(List args) async { final hasDogecoin = args.contains('${prefix}dogecoin'); final hasBase = args.contains('${prefix}base'); final hasArbitrum = args.contains('${prefix}arbitrum'); + final hasBsc = args.contains('${prefix}bsc'); final hasZcash = args.contains('${prefix}zcash'); - final hasEVM = hasEthereum || hasPolygon || hasBase || hasArbitrum; + final hasEVM = hasEthereum || hasPolygon || hasBase || hasArbitrum || hasBsc; final excludeFlutterSecureStorage = args.contains('${prefix}excludeFlutterSecureStorage'); await generateBitcoin(hasBitcoin); @@ -69,6 +70,7 @@ Future main(List args) async { hasDogecoin: hasDogecoin, hasBase: hasBase, hasArbitrum: hasArbitrum, + hasBsc: hasBsc, hasZcash: hasZcash, ); await generateWalletTypes( @@ -87,6 +89,7 @@ Future main(List args) async { hasDogecoin: hasDogecoin, hasBase: hasBase, hasArbitrum: hasArbitrum, + hasBsc: hasBsc, hasZcash: hasZcash, ); await injectSecureStorage(!excludeFlutterSecureStorage); @@ -740,15 +743,12 @@ abstract class BitcoinCash { """; const bitcoinCashEmptyDefinition = 'BitcoinCash? bitcoinCash;\n'; - const bitcoinCashCWDefinition = - 'BitcoinCash? bitcoinCash = CWBitcoinCash();\n'; + const bitcoinCashCWDefinition = 'BitcoinCash? bitcoinCash = CWBitcoinCash();\n'; final output = '$bitcoinCashCommonHeaders\n' + (hasImplementation ? '$bitcoinCashCWHeaders\n' : '\n') + (hasImplementation ? '$bitcoinCashCwPart\n\n' : '\n') + - (hasImplementation - ? bitcoinCashCWDefinition - : bitcoinCashEmptyDefinition) + + (hasImplementation ? bitcoinCashCWDefinition : bitcoinCashEmptyDefinition) + '\n' + bitcoinCashContent; @@ -883,8 +883,7 @@ abstract class NanoUtil { """; const nanoEmptyDefinition = 'Nano? nano;\nNanoUtil? nanoUtil;\n'; - const nanoCWDefinition = - 'Nano? nano = CWNano();\nNanoUtil? nanoUtil = CWNanoUtil();\n'; + const nanoCWDefinition = 'Nano? nano = CWNano();\nNanoUtil? nanoUtil = CWNanoUtil();\n'; final output = '$nanoCommonHeaders\n' + (hasImplementation ? '$nanoCWHeaders\n' : '\n') + @@ -1674,6 +1673,7 @@ Future generatePubspec({ required bool hasDogecoin, required bool hasBase, required bool hasArbitrum, + required bool hasBsc, required bool hasZcash, }) async { const cwCore = """ @@ -1745,8 +1745,7 @@ Future generatePubspec({ final inputLines = inputText.split('\n'); final dependenciesIndex = inputLines.indexWhere((line) => Platform.isWindows // On Windows it could contains `\r` (Carriage Return). It could be fixed in newer dart versions. - ? line.toLowerCase() == 'dependencies:\r' || - line.toLowerCase() == 'dependencies:' + ? line.toLowerCase() == 'dependencies:\r' || line.toLowerCase() == 'dependencies:' : line.toLowerCase() == 'dependencies:'); var output = cwCore; @@ -1834,6 +1833,7 @@ Future generateWalletTypes({ required bool hasDogecoin, required bool hasBase, required bool hasArbitrum, + required bool hasBsc, required bool hasZcash, }) async { final walletTypesFile = File(walletTypesPath); @@ -1858,6 +1858,10 @@ Future generateWalletTypes({ outputContent += '\tWalletType.ethereum,\n'; } + if (hasBsc) { + outputContent += '\tWalletType.bsc,\n'; + } + if (hasSolana) { outputContent += '\tWalletType.solana,\n'; } diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 35cf46870..c93184cc2 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -57,6 +57,7 @@ class SecretKey { SecretKey('polygonTestWalletSeeds', () => ''), SecretKey('baseTestWalletSeeds', () => ''), SecretKey('arbitrumTestWalletSeeds', () => ''), + SecretKey('bscTestWalletSeeds', () => ''), SecretKey('solanaTestWalletSeeds', () => ''), SecretKey('tronTestWalletSeeds', () => ''), SecretKey('nanoTestWalletSeeds', () => ''), @@ -69,6 +70,7 @@ class SecretKey { SecretKey('polygonTestWalletReceiveAddress', () => ''), SecretKey('baseTestWalletReceiveAddress', () => ''), SecretKey('arbitrumTestWalletReceiveAddress', () => ''), + SecretKey('bscTestWalletReceiveAddress', () => ''), SecretKey('solanaTestWalletReceiveAddress', () => ''), SecretKey('tronTestWalletReceiveAddress', () => ''), SecretKey('nanoTestWalletReceiveAddress', () => ''),