mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
Add Robinhood Chain (#3398)
* fix android CI * feat: Add Robinhood Chain, all major flows done. minor issue now is our providers don't support it yet as its still pretty early, two weeks from launch * feat: Add Robinhood Chain, all major flows done. minor issue now is our providers don't support it yet as its still pretty early, two weeks from launch * Cleanup * auto-reformat * fix ui issue and contact listing for tokens * fix: missing icons and crash for fee priority in settings * chore: cleanup * fixes from feedbacks * fix: review issues and sync to latest dev feat: switch history api to etherscan, add history toggle to privacy settings, exclude robETH from exchange pickers, skip tokens discovery for chains that moralis hasn't indexed, add tests * fix: address Robinhood review comments * fix: show Solana token icons in history * fix: address review comments and default Robinhood to PublicNode * fix: revert filter and refuse unmapped networks in provider --------- Co-authored-by: Robert Malikowski <malikowskirobert@gmail.com>
This commit is contained in:
co-authored by
Robert Malikowski
parent
77e4b946eb
commit
046e57c598
@@ -137,6 +137,7 @@ class DFXBuyProvider extends BuyProvider {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
return wallet.signMessage(message);
|
||||
|
||||
@@ -108,6 +108,7 @@ class RobinhoodBuyProvider extends BuyProvider {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.dogecoin:
|
||||
|
||||
@@ -113,6 +113,7 @@ class AddressValidator extends TextValidator {
|
||||
case CryptoCurrency.eth:
|
||||
case CryptoCurrency.baseEth:
|
||||
case CryptoCurrency.arbEth:
|
||||
case CryptoCurrency.robEth:
|
||||
case CryptoCurrency.mana:
|
||||
case CryptoCurrency.matic:
|
||||
case CryptoCurrency.maticpoly:
|
||||
@@ -271,6 +272,7 @@ class AddressValidator extends TextValidator {
|
||||
case CryptoCurrency.avaxc:
|
||||
case CryptoCurrency.baseEth:
|
||||
case CryptoCurrency.arbEth:
|
||||
case CryptoCurrency.robEth:
|
||||
return [42];
|
||||
case CryptoCurrency.bch:
|
||||
return [42, 54, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35];
|
||||
@@ -382,6 +384,7 @@ class AddressValidator extends TextValidator {
|
||||
case CryptoCurrency.maticpoly:
|
||||
case CryptoCurrency.baseEth:
|
||||
case CryptoCurrency.arbEth:
|
||||
case CryptoCurrency.robEth:
|
||||
case CryptoCurrency.arb:
|
||||
pattern = '0x[0-9a-zA-Z]+';
|
||||
case CryptoCurrency.nano:
|
||||
|
||||
@@ -37,6 +37,7 @@ class SeedValidator extends Validator<MnemonicItem> {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return evm!.getEVMWordList(language);
|
||||
case WalletType.bitcoinCash:
|
||||
return getBitcoinWordList(language);
|
||||
|
||||
@@ -81,6 +81,7 @@ class WalletCreationService {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.dogecoin:
|
||||
|
||||
@@ -1234,6 +1234,7 @@ Future<void> setup({
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return evm!.createEVMWalletService(param1, SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.bitcoinCash:
|
||||
return bitcoinCash!.createBitcoinCashWalletService(
|
||||
|
||||
@@ -64,6 +64,7 @@ const dogecoinDefaultNodeUri = 'dogecoin.stackwallet.com:50022';
|
||||
const baseDefaultNodeUri = 'base-rpc.publicnode.com';
|
||||
const arbitrumDefaultNodeUri = 'arbitrum-one-rpc.publicnode.com';
|
||||
const bscDefaultNodeUri = 'bsc-dataseed.bnbchain.org';
|
||||
const robinhoodDefaultNodeUri = "robinhood-rpc.publicnode.com";
|
||||
const zcashDefaultNodeUri = 'zec.rocks:443';
|
||||
|
||||
Future<void> defaultSettingsMigration(
|
||||
@@ -660,6 +661,12 @@ Future<void> defaultSettingsMigration(
|
||||
break;
|
||||
case 72:
|
||||
await createDefaultChartsData();
|
||||
await addWalletNodeList(type: WalletType.robinhood);
|
||||
await _changeDefaultNode(
|
||||
sharedPreferences: sharedPreferences,
|
||||
type: WalletType.robinhood,
|
||||
currentNodePreferenceKey: PreferencesKey.currentRobinhoodNodeIdKey,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -16,6 +16,7 @@ const Map<WalletType, String> nodePreferenceKeys = {
|
||||
WalletType.base: PreferencesKey.currentBaseNodeIdKey,
|
||||
WalletType.arbitrum: PreferencesKey.currentArbitrumNodeIdKey,
|
||||
WalletType.bsc: PreferencesKey.currentBscNodeIdKey,
|
||||
WalletType.robinhood: PreferencesKey.currentRobinhoodNodeIdKey,
|
||||
WalletType.nano: PreferencesKey.currentNanoNodeIdKey,
|
||||
WalletType.decred: PreferencesKey.currentDecredNodeIdKey,
|
||||
WalletType.bitcoinCash: PreferencesKey.currentBitcoinCashNodeIdKey,
|
||||
|
||||
@@ -13,6 +13,7 @@ class PreferencesKey {
|
||||
static const currentBaseNodeIdKey = 'current_node_id_base';
|
||||
static const currentArbitrumNodeIdKey = 'current_node_id_arbitrum';
|
||||
static const currentBscNodeIdKey = 'current_node_id_bsc';
|
||||
static const currentRobinhoodNodeIdKey = "current_node_id_robinhood";
|
||||
static const currentNanoNodeIdKey = 'current_node_id_nano';
|
||||
static const currentNanoPowNodeIdKey = 'current_node_id_nano_pow';
|
||||
static const currentDecredNodeIdKey = 'current_node_id_decred';
|
||||
@@ -92,6 +93,7 @@ class PreferencesKey {
|
||||
static const useBaseScan = 'use_base_scan';
|
||||
static const useArbiScan = 'use_arbitrum_scan';
|
||||
static const useBscScan = 'use_bscscan';
|
||||
static const useRobinhoodScan = "use_robinhood_scan";
|
||||
static const useTronGrid = 'use_trongrid';
|
||||
static const useMempoolFeeAPI = 'use_mempool_fee_api';
|
||||
static const evmHiddenChainIds = 'evm_hidden_chain_ids';
|
||||
|
||||
@@ -30,6 +30,7 @@ List<TransactionPriority> priorityForWalletType(WalletType type) {
|
||||
case WalletType.dogecoin:
|
||||
return dogecoin!.getTransactionPriorities();
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
case WalletType.solana:
|
||||
|
||||
+5
-2
@@ -199,10 +199,13 @@ class CWEVM extends EVM {
|
||||
@override
|
||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) {
|
||||
final evmWallet = wallet as EVMChainWallet;
|
||||
final chainName = EVMChainUtils.getDefaultTokenSymbol(evmWallet.selectedChainId).toLowerCase();
|
||||
return evmWallet.getErc20Token(contractAddress, chainName);
|
||||
return evmWallet.getErc20Token(contractAddress, getMoralisChainName(wallet));
|
||||
}
|
||||
|
||||
@override
|
||||
String? getMoralisChainName(WalletBase wallet) =>
|
||||
EVMChainUtils.getMoralisChainName((wallet as EVMChainWallet).selectedChainId);
|
||||
|
||||
@override
|
||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
|
||||
transaction as EVMChainTransactionInfo;
|
||||
|
||||
@@ -356,6 +356,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
return 'cchain';
|
||||
case 'ARB':
|
||||
return 'arbitrum';
|
||||
case "ROB":
|
||||
return "hood";
|
||||
default:
|
||||
return tag.toLowerCase();
|
||||
}
|
||||
@@ -366,6 +368,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
'POLY' => 'MATIC',
|
||||
'AVAXC' => 'CCHAIN',
|
||||
'ARBITRUM' => 'ARB',
|
||||
"HOOD" => "ROB",
|
||||
_ => network,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
|
||||
'AVAXC': '0x1111111111111111111111111111111111111111',
|
||||
'ARB': '0x1111111111111111111111111111111111111111',
|
||||
'BASE': '0x1111111111111111111111111111111111111111',
|
||||
"ROB": "0x1111111111111111111111111111111111111111",
|
||||
|
||||
// Others
|
||||
'SOL': '11111111111111111111111111111111',
|
||||
@@ -516,6 +517,7 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
|
||||
return switch (tag) {
|
||||
'TRX' => 'tron',
|
||||
'AVAXC' => 'avax',
|
||||
"ROB" => "hood",
|
||||
_ => tag?.toLowerCase(),
|
||||
};
|
||||
}
|
||||
@@ -524,6 +526,7 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
|
||||
return switch (blockchain) {
|
||||
'tron' => 'TRX',
|
||||
'avax' => 'AVAXC',
|
||||
"hood" => "ROB",
|
||||
_ => blockchain?.toUpperCase(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -457,6 +457,8 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||
return 'zcash';
|
||||
case 'AVAXC':
|
||||
return 'avax';
|
||||
case "ROB":
|
||||
return "robinhood";
|
||||
default:
|
||||
return tag.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
|
||||
required CryptoCurrency to,
|
||||
required bool isFixedRateMode,
|
||||
}) async {
|
||||
if (!_isPairSupported(from, to)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final uri = Uri.https(apiAuthority, getCoins);
|
||||
final response = await ProxyWrapper().get(clearnetUri: uri);
|
||||
@@ -96,6 +100,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
|
||||
required bool isReceiveAmount}) async {
|
||||
try {
|
||||
if (amount == 0) return 0.0;
|
||||
if (!_isPairSupported(from, to)) return 0.0;
|
||||
if (isFixedRateMode && !supportsFixedRate) {
|
||||
return 0.0;
|
||||
}
|
||||
@@ -191,13 +196,24 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
|
||||
required bool isFixedRateMode,
|
||||
required bool isSendAll,
|
||||
}) async {
|
||||
final sendNetwork = _networkFor(request.fromCurrency);
|
||||
final receiveNetwork = _networkFor(request.toCurrency);
|
||||
if (sendNetwork == null || receiveNetwork == null) {
|
||||
throw TradeNotCreatedException(
|
||||
description,
|
||||
description: "SwapTrade has no network for "
|
||||
"${request.fromCurrency.title} ${request.fromCurrency.tag ?? ""} or "
|
||||
"${request.toCurrency.title} ${request.toCurrency.tag ?? ""}",
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
final params = <String, dynamic>{};
|
||||
var body = <String, dynamic>{
|
||||
'coin_send': _normalizeCurrency(request.fromCurrency),
|
||||
'coin_send_network': _networkFor(request.fromCurrency),
|
||||
'coin_send_network': sendNetwork,
|
||||
'coin_receive': _normalizeCurrency(request.toCurrency),
|
||||
'coin_receive_network': _networkFor(request.toCurrency),
|
||||
'coin_receive_network': receiveNetwork,
|
||||
'amount_send': request.fromAmount,
|
||||
'recipient': request.toAddress,
|
||||
'ref': 'cake',
|
||||
@@ -396,22 +412,16 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
|
||||
}
|
||||
}
|
||||
|
||||
String _networkFor(CryptoCurrency currency) {
|
||||
final network = switch (currency) {
|
||||
CryptoCurrency.eth => 'ETH',
|
||||
CryptoCurrency.bnb => 'BNB_BSC',
|
||||
CryptoCurrency.usdterc20 => 'USDT_ERC20',
|
||||
CryptoCurrency.usdttrc20 => 'TRX_USDT_S2UZ',
|
||||
CryptoCurrency.usdtbsc => 'USDT_BSC',
|
||||
CryptoCurrency.sol => 'SOL',
|
||||
CryptoCurrency.btc => 'BTC',
|
||||
CryptoCurrency.xmr => 'XMR',
|
||||
CryptoCurrency.ltc => 'LTC',
|
||||
CryptoCurrency.ada => 'ADA',
|
||||
CryptoCurrency.bch => 'BCH',
|
||||
CryptoCurrency.zec => 'ZEC',
|
||||
_ => currency.title.toUpperCase(),
|
||||
};
|
||||
return network;
|
||||
}
|
||||
bool _isPairSupported(CryptoCurrency from, CryptoCurrency to) =>
|
||||
_networkFor(from) != null && _networkFor(to) != null;
|
||||
|
||||
String? _networkFor(CryptoCurrency currency) =>
|
||||
switch ((currency.title.toUpperCase(), currency.tag?.toUpperCase())) {
|
||||
("BNB", "BSC") => "BNB_BSC",
|
||||
("USDT", "ETH") => "USDT_ERC20",
|
||||
("USDT", "TRX") => "TRX_USDT_S2UZ",
|
||||
("USDT", "BSC") => "USDT_BSC",
|
||||
(final title, null) => title,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -612,7 +612,10 @@ class _NewSendPageState extends State<NewSendPage> {
|
||||
subtitle:
|
||||
"~${output.estimatedFee} ${widget.sendViewModel.currencySymbol} (${output.estimatedFeeFiatAmount} ${widget.sendViewModel.fiatCurrency})",
|
||||
// Without fee priorities the row does nothing,
|
||||
// so it must not be announced as interactive.
|
||||
// so it must not be announced as interactive or
|
||||
// show a tappable arrow.
|
||||
showArrow: widget
|
||||
.sendViewModel.feesViewModel.hasFeesPriority,
|
||||
onTap: widget.sendViewModel.feesViewModel
|
||||
.hasFeesPriority
|
||||
? () =>
|
||||
|
||||
@@ -481,6 +481,7 @@ class _MultiNetworkPickerBodyState extends State<_MultiNetworkPickerBody> {
|
||||
|
||||
String _shortChainLabel(CryptoCurrency c) {
|
||||
if (cryptoCurrencyOrTokenToWalletType(c) == WalletType.bsc) return 'BSC';
|
||||
if (cryptoCurrencyOrTokenToWalletType(c) == WalletType.robinhood) return "ROB";
|
||||
return chainNameForCurrency(c);
|
||||
}
|
||||
|
||||
@@ -493,7 +494,7 @@ class _MultiNetworkPickerBodyState extends State<_MultiNetworkPickerBody> {
|
||||
}
|
||||
|
||||
bool _isL2NativeEth(CryptoCurrency c) =>
|
||||
c == CryptoCurrency.arbEth || c == CryptoCurrency.baseEth;
|
||||
c == CryptoCurrency.arbEth || c == CryptoCurrency.baseEth || c == CryptoCurrency.robEth;
|
||||
|
||||
_SelSection? _selectedSection({
|
||||
required List<CryptoCurrency> recents,
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import "package:cw_core/currency_for_wallet_type.dart";
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -36,6 +37,7 @@ class ReceiveInfoBox extends StatelessWidget {
|
||||
case WalletType.polygon:
|
||||
case WalletType.zano:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
if (autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.disabled) return null;
|
||||
return ReceiveInfoBox(
|
||||
iconPath: "",
|
||||
@@ -43,8 +45,7 @@ class ReceiveInfoBox extends StatelessWidget {
|
||||
onDismissed: onDismissed,
|
||||
bottomWidget: InfoboxCurrencyRow(
|
||||
currencies: supportedCurrencies ?? [],
|
||||
chainIconPath:
|
||||
"assets/new-ui/chain_badges/${walletTypeToString(type).toLowerCase()}.svg",
|
||||
chainIconPath: walletTypeToCryptoCurrency(type).chainIconPath ?? "",
|
||||
));
|
||||
default:
|
||||
if (autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.disabled) return null;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||
import "package:cw_core/currency_for_wallet_type.dart";
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class ReceiveTokenDisplay extends StatelessWidget {
|
||||
const ReceiveTokenDisplay({super.key, required this.addressListViewModel});
|
||||
@@ -35,7 +35,7 @@ class ReceiveTokenDisplay extends StatelessWidget {
|
||||
children: [
|
||||
CakeImageWidget(
|
||||
imageUrl:
|
||||
"assets/new-ui/chain_badges/${addressListViewModel.wallet.type == WalletType.bsc ? 'bnb' : walletTypeToString(addressListViewModel.wallet.type).toLowerCase()}.svg",
|
||||
walletTypeToCryptoCurrency(addressListViewModel.wallet.type).chainIconPath,
|
||||
width: 16,
|
||||
height: 16,
|
||||
colorFilter:
|
||||
|
||||
@@ -11,6 +11,7 @@ const List<WalletType> walletConnectCompatibleChains = [
|
||||
WalletType.base,
|
||||
WalletType.arbitrum,
|
||||
WalletType.bsc,
|
||||
WalletType.robinhood,
|
||||
WalletType.solana,
|
||||
];
|
||||
|
||||
@@ -39,6 +40,7 @@ bool isEVMCompatibleChain(WalletType walletType) {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -93,6 +95,8 @@ String getChainNameSpaceAndIdBasedOnWalletType(WalletType walletType, {int? chai
|
||||
return EVMChainId.arbitrum.chain();
|
||||
case WalletType.bsc:
|
||||
return EVMChainId.bsc.chain();
|
||||
case WalletType.robinhood:
|
||||
return EVMChainId.robinhood.chain();
|
||||
case WalletType.solana:
|
||||
return SolanaChainId.mainnet.chain();
|
||||
default:
|
||||
@@ -107,6 +111,7 @@ List<String> getChainSupportedMethodsOnWalletType(WalletType walletType) {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return EVMSupportedMethods.values.map((e) => e.name).toList();
|
||||
case WalletType.solana:
|
||||
return SolanaSupportedMethods.values.map((e) => e.name).toList();
|
||||
|
||||
@@ -7,6 +7,7 @@ bool isBIP39Wallet(WalletType walletType) {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.bitcoin:
|
||||
@@ -49,6 +50,7 @@ bool hasTokens(WalletType walletType) {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -61,6 +63,7 @@ String tokenStandardFor(WalletType walletType) {
|
||||
case WalletType.polygon:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.base:
|
||||
case WalletType.robinhood:
|
||||
return 'ERC-20';
|
||||
case WalletType.bsc:
|
||||
return 'BEP-20';
|
||||
|
||||
@@ -388,9 +388,12 @@ class _ContactListBodyState extends State<ContactListBody> {
|
||||
}
|
||||
|
||||
Widget generateContactRaw(BuildContext context, ContactRecord contact, bool isLast) {
|
||||
final image = contact.type == CryptoCurrency.baseEth
|
||||
? 'assets/new-ui/crypto_full_icons/base.svg'
|
||||
: contact.type.iconPath;
|
||||
const l2NativeChainIcons = {
|
||||
CryptoCurrency.baseEth: "assets/new-ui/crypto_full_icons/base.svg",
|
||||
CryptoCurrency.arbEth: "assets/new-ui/crypto_full_icons/arbitrum.svg",
|
||||
CryptoCurrency.robEth: "assets/new-ui/crypto_full_icons/robinhood.svg",
|
||||
};
|
||||
final image = l2NativeChainIcons[contact.type] ?? contact.type.iconPath;
|
||||
final currencyIcon = (image != null && image.isNotEmpty)
|
||||
? CakeImageWidget(imageUrl: image, height: 24, width: 24)
|
||||
: const SizedBox(height: 24, width: 24);
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/setting_action_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/setting_actions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter_svg/svg.dart";
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
@@ -36,6 +37,7 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||
this.baseIcon = Image.asset('assets/new-ui/crypto_full_icons/base.svg'),
|
||||
this.arbitrumIcon = Image.asset('assets/new-ui/crypto_full_icons/arbitrum.svg'),
|
||||
this.bscIcon = Image.asset('assets/new-ui/crypto_full_icons/bnb.svg'),
|
||||
this.robinhoodIcon = SvgPicture.asset("assets/new-ui/crypto_full_icons/robinhood.svg"),
|
||||
this.solanaIcon = Image.asset('assets/new-ui/crypto_full_icons/solana.svg'),
|
||||
this.tronIcon = Image.asset('assets/new-ui/crypto_full_icons/tron.svg'),
|
||||
this.wowneroIcon = Image.asset('assets/new-ui/crypto_full_icons/wownero.svg'),
|
||||
@@ -67,6 +69,7 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||
Image baseIcon;
|
||||
Image arbitrumIcon;
|
||||
Image bscIcon;
|
||||
Widget robinhoodIcon;
|
||||
Image solanaIcon;
|
||||
Image tronIcon;
|
||||
Image wowneroIcon;
|
||||
@@ -261,6 +264,8 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||
return arbitrumIcon;
|
||||
case WalletType.bsc:
|
||||
return bscIcon;
|
||||
case WalletType.robinhood:
|
||||
return robinhoodIcon;
|
||||
case WalletType.tron:
|
||||
return tronIcon;
|
||||
case WalletType.wownero:
|
||||
|
||||
@@ -93,6 +93,14 @@ class ConnectionSyncPage extends BasePage {
|
||||
onChanged: (val) {
|
||||
_connectionSyncViewModel.setUseBaseScan(val);
|
||||
}),
|
||||
if (_connectionSyncViewModel.canUseRobinhoodScan)
|
||||
ListItemToggle(
|
||||
keyValue: "can_use_robinhoodscan",
|
||||
label: S.of(context).robinhoodscan_history,
|
||||
value: _connectionSyncViewModel.useRobinhoodScan,
|
||||
onChanged: (val) {
|
||||
_connectionSyncViewModel.setUseRobinhoodScan(val);
|
||||
}),
|
||||
if (_connectionSyncViewModel.canUseArbiScan)
|
||||
ListItemToggle(
|
||||
keyValue: "can_use_arbiscan",
|
||||
|
||||
@@ -6,6 +6,7 @@ enum EVMChainId {
|
||||
base,
|
||||
arbitrum,
|
||||
bsc,
|
||||
robinhood,
|
||||
}
|
||||
|
||||
extension EVMChainIdX on EVMChainId {
|
||||
@@ -24,6 +25,7 @@ extension EVMChainIdX on EVMChainId {
|
||||
EVMChainId.base => 8453,
|
||||
EVMChainId.arbitrum => 42161,
|
||||
EVMChainId.bsc => 56,
|
||||
EVMChainId.robinhood => 4663,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class KeyServiceImpl implements WalletConnectKeyService {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return evm!.getPrivateKey(wallet);
|
||||
case WalletType.solana:
|
||||
return solana!.getPrivateKey(wallet);
|
||||
@@ -33,6 +34,7 @@ class KeyServiceImpl implements WalletConnectKeyService {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return evm!.getPublicKey(wallet);
|
||||
case WalletType.solana:
|
||||
return solana!.getPublicKey(wallet);
|
||||
@@ -52,6 +54,7 @@ class KeyServiceImpl implements WalletConnectKeyService {
|
||||
'eip155:137',
|
||||
'eip155:8453',
|
||||
'eip155:42161',
|
||||
"eip155:4663",
|
||||
],
|
||||
privateKey: _getPrivateKeyForWallet(wallet),
|
||||
publicKey: _getPublicKeyForWallet(wallet),
|
||||
|
||||
@@ -120,6 +120,7 @@ abstract class SettingsStoreBase with Store {
|
||||
required this.useBaseScan,
|
||||
required this.useArbiScan,
|
||||
required this.useBscScan,
|
||||
required this.useRobinhoodScan,
|
||||
required this.usePolygonScan,
|
||||
required this.useTronGrid,
|
||||
required this.useMempoolFeeAPI,
|
||||
@@ -533,6 +534,11 @@ abstract class SettingsStoreBase with Store {
|
||||
reaction((_) => useBscScan,
|
||||
(bool useBscScan) => _sharedPreferences.setBool(PreferencesKey.useBscScan, useBscScan));
|
||||
|
||||
reaction(
|
||||
(_) => useRobinhoodScan,
|
||||
(bool useRobinhoodScan) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.useRobinhoodScan, useRobinhoodScan));
|
||||
|
||||
reaction((_) => useTronGrid,
|
||||
(bool useTronGrid) => _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid));
|
||||
|
||||
@@ -978,6 +984,9 @@ abstract class SettingsStoreBase with Store {
|
||||
@observable
|
||||
bool useBscScan;
|
||||
|
||||
@observable
|
||||
bool useRobinhoodScan;
|
||||
|
||||
@observable
|
||||
bool useTronGrid;
|
||||
|
||||
@@ -1144,6 +1153,8 @@ abstract class SettingsStoreBase with Store {
|
||||
return PreferencesKey.currentArbitrumNodeIdKey;
|
||||
case 56:
|
||||
return PreferencesKey.currentBscNodeIdKey;
|
||||
case 4663:
|
||||
return PreferencesKey.currentRobinhoodNodeIdKey;
|
||||
default:
|
||||
// Default to Ethereum for unknown chainIds
|
||||
return PreferencesKey.currentEthereumNodeIdKey;
|
||||
@@ -1338,6 +1349,7 @@ abstract class SettingsStoreBase with Store {
|
||||
final useBaseScan = sharedPreferences.getBool(PreferencesKey.useBaseScan) ?? true;
|
||||
final useArbiScan = sharedPreferences.getBool(PreferencesKey.useArbiScan) ?? true;
|
||||
final useBscScan = sharedPreferences.getBool(PreferencesKey.useBscScan) ?? true;
|
||||
final useRobinhoodScan = sharedPreferences.getBool(PreferencesKey.useRobinhoodScan) ?? true;
|
||||
final useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true;
|
||||
final useMempoolFeeAPI = sharedPreferences.getBool(PreferencesKey.useMempoolFeeAPI) ?? true;
|
||||
final useBlinkProtection = sharedPreferences.getBool(PreferencesKey.useBlinkProtection) ?? true;
|
||||
@@ -1402,6 +1414,7 @@ abstract class SettingsStoreBase with Store {
|
||||
final baseNodeId = sharedPreferences.getInt(PreferencesKey.currentBaseNodeIdKey);
|
||||
final arbitrumNodeId = sharedPreferences.getInt(PreferencesKey.currentArbitrumNodeIdKey);
|
||||
final bscNodeId = sharedPreferences.getInt(PreferencesKey.currentBscNodeIdKey);
|
||||
final robinhoodNodeId = sharedPreferences.getInt(PreferencesKey.currentRobinhoodNodeIdKey);
|
||||
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey);
|
||||
final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
|
||||
@@ -1455,6 +1468,8 @@ abstract class SettingsStoreBase with Store {
|
||||
nodeSource.firstWhereOrNull((e) => e.uriRaw == zcashDefaultNodeUri);
|
||||
final bscNode = nodeSource.firstWhereOrNull((e) => e.id == bscNodeId) ??
|
||||
nodeSource.firstWhereOrNull((e) => e.uriRaw == bscDefaultNodeUri);
|
||||
final robinhoodNode = nodeSource.firstWhereOrNull((e) => e.id == robinhoodNodeId) ??
|
||||
nodeSource.firstWhereOrNull((e) => e.uriRaw == robinhoodDefaultNodeUri);
|
||||
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
final deviceName = await _getDeviceName() ?? '';
|
||||
@@ -1523,6 +1538,10 @@ abstract class SettingsStoreBase with Store {
|
||||
nodes[WalletType.bsc] = bscNode;
|
||||
}
|
||||
|
||||
if (robinhoodNode != null) {
|
||||
nodes[WalletType.robinhood] = robinhoodNode;
|
||||
}
|
||||
|
||||
if (bitcoinCashElectrumServer != null) {
|
||||
nodes[WalletType.bitcoinCash] = bitcoinCashElectrumServer;
|
||||
}
|
||||
@@ -1725,6 +1744,7 @@ abstract class SettingsStoreBase with Store {
|
||||
useBaseScan: useBaseScan,
|
||||
useArbiScan: useArbiScan,
|
||||
useBscScan: useBscScan,
|
||||
useRobinhoodScan: useRobinhoodScan,
|
||||
useTronGrid: useTronGrid,
|
||||
useMempoolFeeAPI: useMempoolFeeAPI,
|
||||
useBlinkProtection: useBlinkProtection,
|
||||
@@ -1972,6 +1992,7 @@ abstract class SettingsStoreBase with Store {
|
||||
useBaseScan = sharedPreferences.getBool(PreferencesKey.useBaseScan) ?? true;
|
||||
useArbiScan = sharedPreferences.getBool(PreferencesKey.useArbiScan) ?? true;
|
||||
useBscScan = sharedPreferences.getBool(PreferencesKey.useBscScan) ?? true;
|
||||
useRobinhoodScan = sharedPreferences.getBool(PreferencesKey.useRobinhoodScan) ?? true;
|
||||
useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true;
|
||||
useMempoolFeeAPI = sharedPreferences.getBool(PreferencesKey.useMempoolFeeAPI) ?? true;
|
||||
useBlinkProtection = sharedPreferences.getBool(PreferencesKey.useBlinkProtection) ?? true;
|
||||
@@ -2014,6 +2035,7 @@ abstract class SettingsStoreBase with Store {
|
||||
final baseNodeId = sharedPreferences.getInt(PreferencesKey.currentBaseNodeIdKey);
|
||||
final arbitrumNodeId = sharedPreferences.getInt(PreferencesKey.currentArbitrumNodeIdKey);
|
||||
final bscNodeId = sharedPreferences.getInt(PreferencesKey.currentBscNodeIdKey);
|
||||
final robinhoodNodeId = sharedPreferences.getInt(PreferencesKey.currentRobinhoodNodeIdKey);
|
||||
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
|
||||
final tronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
|
||||
@@ -2031,6 +2053,7 @@ abstract class SettingsStoreBase with Store {
|
||||
final baseNode = await Node.get(baseNodeId ?? -1);
|
||||
final arbitrumNode = await Node.get(arbitrumNodeId ?? -1);
|
||||
final bscNode = await Node.get(bscNodeId ?? -1);
|
||||
final robinhoodNode = await Node.get(robinhoodNodeId ?? -1);
|
||||
final bitcoinCashNode = await Node.get(bitcoinCashElectrumServerId ?? -1);
|
||||
final nanoNode = await Node.get(nanoNodeId ?? -1);
|
||||
final solanaNode = await Node.get(solanaNodeId ?? -1);
|
||||
@@ -2077,6 +2100,10 @@ abstract class SettingsStoreBase with Store {
|
||||
nodes[WalletType.bsc] = bscNode;
|
||||
}
|
||||
|
||||
if (robinhoodNode != null) {
|
||||
nodes[WalletType.robinhood] = robinhoodNode;
|
||||
}
|
||||
|
||||
if (bitcoinCashNode != null) {
|
||||
nodes[WalletType.bitcoinCash] = bitcoinCashNode;
|
||||
}
|
||||
@@ -2230,6 +2257,7 @@ abstract class SettingsStoreBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
final chainId = evm!.getChainIdByWalletType(node.type);
|
||||
final preferenceKey = _getEVMNodePreferenceKey(chainId);
|
||||
await _sharedPreferences.setInt(preferenceKey, node.id);
|
||||
|
||||
@@ -12,6 +12,8 @@ String getQrImage(WalletType type) {
|
||||
return 'assets/images/arbitrum_chain_QR.svg';
|
||||
case WalletType.bsc:
|
||||
return 'assets/images/bnb_chain_QR.svg';
|
||||
case WalletType.robinhood:
|
||||
return "assets/images/eth_chain_qr.svg";
|
||||
case WalletType.solana:
|
||||
return 'assets/images/sol_chain_qr.svg';
|
||||
case WalletType.tron:
|
||||
@@ -55,6 +57,8 @@ String getChainMonoImage(WalletType type) {
|
||||
return 'assets/images/arbitrum_chain_mono.svg';
|
||||
case WalletType.bsc:
|
||||
return 'assets/images/bnb_chain_mono.svg';
|
||||
case WalletType.robinhood:
|
||||
return "assets/images/robinhood_chain_mono.svg";
|
||||
case WalletType.solana:
|
||||
return 'assets/images/sol_chain_mono.svg';
|
||||
case WalletType.tron:
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/evm/evm.dart';
|
||||
import 'package:cake_wallet/solana/solana.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/currency_for_wallet_type.dart';
|
||||
import 'package:cw_core/erc20_token.dart';
|
||||
@@ -12,7 +11,6 @@ import "package:cw_core/utils/print_verbose.dart";
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
||||
class TokenUtilities {
|
||||
static Future<List<Erc20Token>> loadAllUniqueEvmTokens() async {
|
||||
@@ -192,6 +190,7 @@ class TokenUtilities {
|
||||
WalletType.base => 8453,
|
||||
WalletType.arbitrum => 42161,
|
||||
WalletType.bsc => 56,
|
||||
WalletType.robinhood => 4663,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
@@ -298,7 +297,12 @@ 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 == "BSC"));
|
||||
(tag == "ETH" ||
|
||||
tag == "POL" ||
|
||||
tag == "BASE" ||
|
||||
tag == "ARB" ||
|
||||
tag == "BSC" ||
|
||||
tag == "ROB"));
|
||||
|
||||
if (isPotentialEVM) {
|
||||
// Try by tag first if available (e.g., 'POL', 'BASE', 'ARB')
|
||||
|
||||
@@ -56,6 +56,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.zcash:
|
||||
@@ -100,6 +101,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
||||
WalletType.base,
|
||||
WalletType.arbitrum,
|
||||
WalletType.bsc,
|
||||
WalletType.robinhood,
|
||||
WalletType.tron,
|
||||
WalletType.solana,
|
||||
WalletType.monero,
|
||||
|
||||
@@ -219,6 +219,7 @@ abstract class BalanceViewModelBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
return S.current.xmr_full_balance;
|
||||
|
||||
@@ -1300,6 +1300,7 @@ abstract class DashboardViewModelBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
|
||||
@@ -194,10 +194,10 @@ abstract class HomeSettingsViewModelBase with Store {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isPotentialScamViaMoralis = await _isPotentialScamTokenViaMoralis(
|
||||
contractAddress,
|
||||
getChainNameBasedOnWalletType(_balanceViewModel.wallet.type),
|
||||
);
|
||||
final moralisChainName = evm!.getMoralisChainName(_balanceViewModel.wallet);
|
||||
|
||||
final isPotentialScamViaMoralis = moralisChainName != null &&
|
||||
await _isPotentialScamTokenViaMoralis(contractAddress, moralisChainName);
|
||||
|
||||
bool isUnverifiedContract = await _isContractUnverified(
|
||||
contractAddress,
|
||||
@@ -221,6 +221,7 @@ abstract class HomeSettingsViewModelBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
defaultTokenAddresses = evm!.getDefaultTokenContractAddresses(_balanceViewModel.wallet);
|
||||
break;
|
||||
case WalletType.solana:
|
||||
@@ -262,6 +263,7 @@ abstract class HomeSettingsViewModelBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
defaultTokenSymbols = evm!.getDefaultTokenSymbols(_balanceViewModel.wallet);
|
||||
break;
|
||||
case WalletType.solana:
|
||||
|
||||
@@ -207,6 +207,7 @@ class TransactionListItem extends ActionListItem with Keyable {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
final asset = assetOfTransaction;
|
||||
final price = balanceViewModel.fiatConversionStore.prices[asset];
|
||||
amount = calculateFiatAmountRaw(
|
||||
|
||||
@@ -277,7 +277,8 @@ abstract class ExchangeTradeViewModelBase with Store {
|
||||
_isTokenBelongingToWallet(CryptoCurrency.arbEth) ||
|
||||
_isTokenBelongingToWallet(CryptoCurrency.trx) ||
|
||||
_isTokenBelongingToWallet(CryptoCurrency.sol) ||
|
||||
_isTokenBelongingToWallet(CryptoCurrency.bnb);
|
||||
_isTokenBelongingToWallet(CryptoCurrency.bnb) ||
|
||||
_isTokenBelongingToWallet(CryptoCurrency.robEth);
|
||||
|
||||
if (!canSend) {
|
||||
return 'Wallet currency ${wallet.currency.title} does not match trade from currency ${tradeFrom.title} or is not a supported token for this wallet.';
|
||||
@@ -346,6 +347,7 @@ abstract class ExchangeTradeViewModelBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return _createERC681URI(fromCurrency, inputAddress, amount);
|
||||
case WalletType.solana:
|
||||
return SolanaURI(
|
||||
|
||||
@@ -1547,6 +1547,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
depositCurrency = CryptoCurrency.bnb;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
break;
|
||||
case WalletType.robinhood:
|
||||
depositCurrency = CryptoCurrency.robEth;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
break;
|
||||
case WalletType.solana:
|
||||
depositCurrency = CryptoCurrency.sol;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
|
||||
@@ -126,6 +126,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.banano:
|
||||
case WalletType.nano:
|
||||
|
||||
@@ -35,6 +35,7 @@ class WalletRestoreFromQRCode {
|
||||
'base-wallet': WalletType.base,
|
||||
'arbitrum-wallet': WalletType.arbitrum,
|
||||
'bsc-wallet': WalletType.bsc,
|
||||
"robinhood-wallet": WalletType.robinhood,
|
||||
'nano-wallet': WalletType.nano,
|
||||
'nano_wallet': WalletType.nano,
|
||||
'bitcoincash': WalletType.bitcoinCash,
|
||||
|
||||
@@ -109,6 +109,7 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.zcash:
|
||||
return false;
|
||||
}
|
||||
@@ -128,8 +129,8 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
wallet.type != WalletType.banano &&
|
||||
wallet.type != WalletType.solana &&
|
||||
wallet.type != WalletType.tron &&
|
||||
wallet.chainId !=
|
||||
42161; // Wallet type is generic for all EVM chains, so we need to check the chainId
|
||||
wallet.chainId != 42161 &&
|
||||
wallet.chainId != 4663;
|
||||
|
||||
@computed
|
||||
bool get isElectrumWallet =>
|
||||
|
||||
@@ -189,12 +189,14 @@ abstract class OutputBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
final isNative = [
|
||||
CryptoCurrency.eth,
|
||||
CryptoCurrency.maticpoly,
|
||||
CryptoCurrency.baseEth,
|
||||
CryptoCurrency.arbEth,
|
||||
CryptoCurrency.bnb
|
||||
CryptoCurrency.bnb,
|
||||
CryptoCurrency.robEth
|
||||
].contains(cryptoCurrencyHandler());
|
||||
|
||||
final fee = isNative
|
||||
|
||||
@@ -293,6 +293,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.tron:
|
||||
case WalletType.solana:
|
||||
case WalletType.bitcoin:
|
||||
@@ -1273,6 +1274,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
WalletType.solana,
|
||||
WalletType.tron,
|
||||
WalletType.arbitrum,
|
||||
WalletType.robinhood,
|
||||
WalletType.zcash,
|
||||
].contains(wallet.type)) {
|
||||
throw Exception('Priority is null for wallet type: ${wallet.type}');
|
||||
@@ -1311,6 +1313,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return evm!.createEVMTransactionCredentials(
|
||||
outputs,
|
||||
priority: priority,
|
||||
|
||||
@@ -205,6 +205,9 @@ abstract class ConnectionSyncViewModelBase with Store {
|
||||
@computed
|
||||
bool get useBaseScan => _settingsStore.useBaseScan;
|
||||
|
||||
@computed
|
||||
bool get useRobinhoodScan => _settingsStore.useRobinhoodScan;
|
||||
|
||||
@computed
|
||||
bool get useArbiScan => _settingsStore.useArbiScan;
|
||||
|
||||
@@ -223,6 +226,9 @@ abstract class ConnectionSyncViewModelBase with Store {
|
||||
@computed
|
||||
bool get canUseBaseScan => _wallet.chainId == 8453;
|
||||
|
||||
@computed
|
||||
bool get canUseRobinhoodScan => _wallet.chainId == 4663;
|
||||
|
||||
@computed
|
||||
bool get canUseArbiScan => _wallet.chainId == 42161;
|
||||
|
||||
@@ -271,6 +277,12 @@ abstract class ConnectionSyncViewModelBase with Store {
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseRobinhoodScan(bool value) {
|
||||
_settingsStore.useRobinhoodScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseTronGrid(bool value) {
|
||||
_settingsStore.useTronGrid = value;
|
||||
|
||||
@@ -104,6 +104,7 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||
WalletType.solana,
|
||||
WalletType.tron,
|
||||
WalletType.arbitrum,
|
||||
WalletType.robinhood,
|
||||
].contains(_wallet.type));
|
||||
|
||||
String getDisplayPriority(dynamic priority) {
|
||||
|
||||
@@ -476,6 +476,8 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||
return "https://arbiscan.io/tx/${txId}";
|
||||
case WalletType.bsc:
|
||||
return "https://bscscan.com/tx/${txId}";
|
||||
case WalletType.robinhood:
|
||||
return "https://robinhoodchain.blockscout.com/tx/${txId}";
|
||||
case WalletType.polygon:
|
||||
return "https://polygonscan.com/tx/${txId}";
|
||||
case WalletType.nano:
|
||||
|
||||
@@ -562,6 +562,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||
"assets/images/usdt_wallet_icon.svg",
|
||||
"assets/images/more_tokens.svg",
|
||||
];
|
||||
case 4663:
|
||||
return [
|
||||
"assets/new-ui/crypto_full_icons/robinhood.svg",
|
||||
"assets/images/usdg_icon.png",
|
||||
"assets/images/more_tokens.svg",
|
||||
];
|
||||
default:
|
||||
return [
|
||||
"assets/new-ui/crypto_full_icons/ethereum.svg",
|
||||
|
||||
@@ -171,6 +171,7 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
items.addAll([
|
||||
@@ -321,6 +322,8 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
return 'arbitrum-wallet';
|
||||
case WalletType.bsc:
|
||||
return 'bsc-wallet';
|
||||
case WalletType.robinhood:
|
||||
return "robinhood-wallet";
|
||||
case WalletType.solana:
|
||||
return 'solana-wallet';
|
||||
case WalletType.tron:
|
||||
|
||||
@@ -83,6 +83,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return evm!.createEVMNewWalletCredentials(
|
||||
name: name,
|
||||
password: walletPassword,
|
||||
|
||||
@@ -54,6 +54,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
case WalletType.decred:
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
@@ -97,6 +98,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
WalletType.base,
|
||||
WalletType.arbitrum,
|
||||
WalletType.bsc,
|
||||
WalletType.robinhood,
|
||||
WalletType.nano,
|
||||
WalletType.banano,
|
||||
WalletType.solana,
|
||||
@@ -179,6 +181,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return evm!.createEVMRestoreWalletFromSeedCredentials(
|
||||
name: name,
|
||||
mnemonic: seed,
|
||||
@@ -288,6 +291,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
case WalletType.base:
|
||||
case WalletType.arbitrum:
|
||||
case WalletType.bsc:
|
||||
case WalletType.robinhood:
|
||||
return evm!.createEVMRestoreWalletFromPrivateKey(
|
||||
name: name,
|
||||
password: password,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/core/wallet_loading_service.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
@@ -32,13 +31,6 @@ abstract class WalletSwitcherViewModelBase with Store {
|
||||
Future<List<WalletInfo>> getWallets(WalletType? walletType) async {
|
||||
final wiList = await WalletInfo.getAll();
|
||||
if (walletType == null) return wiList;
|
||||
|
||||
// For EVM-compatible wallet types, show all EVM-compatible wallets
|
||||
// This allows users to switch between any EVM wallet regardless of the specific chain
|
||||
if (isEVMCompatibleChain(walletType)) {
|
||||
return wiList.where((wallet) => isEVMCompatibleChain(wallet.type)).toList();
|
||||
}
|
||||
|
||||
return wiList.where((wallet) => wallet.type == walletType).toList();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user