Rebase node-sqlite-migration onto dev

Squashed migration of node Hive→SQLite, default-node handling,
isPow/proxy support, arbitrum node updates, and related fixes.
Replays node-sqlite-migration on top of current dev without the
amount-refactor merge that the original branch carried.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Omar
2026-05-26 17:04:36 +02:00
co-authored by Claude Opus 4.7
parent f3de4b2588
commit ac05166e95
72 changed files with 1205 additions and 1056 deletions
+7 -9
View File
@@ -14,7 +14,6 @@ class NodeSwitchingService {
NodeSwitchingService({
required this.appStore,
required this.settingsStore,
required this.nodeSource,
});
static const int _healthCheckIntervalSeconds = 30;
@@ -38,7 +37,6 @@ class NodeSwitchingService {
final AppStore appStore;
final SettingsStore settingsStore;
final Box<Node> nodeSource;
final Map<WalletType, List<dynamic>> _usedNodeKeys = {};
@@ -118,13 +116,13 @@ class NodeSwitchingService {
WalletType walletType,
) async {
for (final node in nodes) {
if (!_usedNodeKeys[walletType]!.contains(node.key)) {
if (!_usedNodeKeys[walletType]!.contains(node.id)) {
final isActive = await node.requestNode();
if (isActive) {
return node;
} else {
printV('Node ${node.uriRaw} is not active. Marking as used.');
_usedNodeKeys[walletType]!.add(node.key);
_usedNodeKeys[walletType]!.add(node.id);
}
}
}
@@ -157,7 +155,7 @@ class NodeSwitchingService {
final currentNode = settingsStore.getCurrentNode(nodeWalletType, chainId: chainId);
// Get all trusted nodes for this wallet type
final trustedNodes = nodeSource.values
final trustedNodes = (await Node.getAll())
.where((node) => node.type == nodeWalletType && node.isEnabledForAutoSwitching)
.toList();
@@ -171,8 +169,8 @@ class NodeSwitchingService {
_usedNodeKeys.putIfAbsent(nodeWalletType, () => []);
// Add current node to used list if not already there
if (!_usedNodeKeys[nodeWalletType]!.contains(currentNode.key)) {
_usedNodeKeys[nodeWalletType]!.add(currentNode.key);
if (!_usedNodeKeys[nodeWalletType]!.contains(currentNode.id)) {
_usedNodeKeys[nodeWalletType]!.add(currentNode.id);
}
// Try to find an active unused node
@@ -199,8 +197,8 @@ class NodeSwitchingService {
}
// Ensure the selected node is marked as used
if (!_usedNodeKeys[nodeWalletType]!.contains(nextNode.key)) {
_usedNodeKeys[nodeWalletType]!.add(nextNode.key);
if (!_usedNodeKeys[nodeWalletType]!.contains(nextNode.id)) {
_usedNodeKeys[nodeWalletType]!.add(nextNode.id);
}
printV(
+19 -26
View File
@@ -326,8 +326,8 @@ import 'src/screens/buy/buy_sell_page.dart';
final getIt = GetIt.instance;
var _isSetupFinished = false;
late Box<Node> _nodeSource;
late Box<Node> _powNodeSource;
// late Box<Node> _nodeSource;
// late Box<Node> _powNodeSource;
late Box<Contact> _contactSource;
late Box<Template> _templates;
late Box<ExchangeTemplate> _exchangeTemplates;
@@ -337,8 +337,6 @@ late Box<UnspentCoinsInfo> _unspentCoinsInfoSource;
late Box<PayjoinSession> _payjoinSessionSource;
late Box<AnonpayInvoiceInfo> _anonpayInvoiceInfoSource;
Future<void> setup({
required Box<Node> nodeSource,
required Box<Node> powNodeSource,
required Box<Contact> contactSource,
required Box<Template> templates,
required Box<ExchangeTemplate> exchangeTemplates,
@@ -350,8 +348,6 @@ Future<void> setup({
required SecureStorage secureStorage,
required GlobalKey<NavigatorState> navigatorKey,
}) async {
_nodeSource = nodeSource;
_powNodeSource = powNodeSource;
_contactSource = contactSource;
_templates = templates;
_exchangeTemplates = exchangeTemplates;
@@ -376,8 +372,6 @@ Future<void> setup({
(secrets.wyreAccountId.isNotEmpty);
final settingsStore = await SettingsStoreBase.load(
nodeSource: _nodeSource,
powNodeSource: _powNodeSource,
isBitcoinBuyEnabled: isBitcoinBuyEnabled,
);
@@ -385,18 +379,16 @@ Future<void> setup({
return;
}
getIt.registerFactory<Box<Node>>(() => _nodeSource);
getIt.registerFactory<Box<Node>>(() => _powNodeSource, instanceName: Node.boxName + "pow");
getIt.registerSingleton(AuthenticationStore());
getIt.registerSingleton<WalletListStore>(WalletListStore());
getIt.registerSingleton(NodeListStoreBase.instance);
// getIt.registerSingleton(NodeListStoreBase.instance);
getIt.registerSingleton<SettingsStore>(settingsStore);
getIt.registerSingleton<AppStore>(AppStore(
authenticationStore: getIt.get<AuthenticationStore>(),
walletList: getIt.get<WalletListStore>(),
settingsStore: getIt.get<SettingsStore>(),
nodeListStore: getIt.get<NodeListStore>(),
// nodeListStore: getIt.get<NodeListStore>(),
themeStore: getIt.get<ThemeStore>()));
getIt.registerSingleton<TradesStore>(
TradesStore(appStore: getIt.get<AppStore>()));
@@ -1126,22 +1118,22 @@ Future<void> setup({
getIt.registerFactory(() => AddressListPage(getIt.get<WalletAddressListViewModel>()));
getIt.registerLazySingleton(() {
final appStore = getIt.get<AppStore>();
return NodeListViewModel(appStore);
});
getIt.registerFactoryParam<NewAddressesPage, bool, void>(
(showHidden, _) => NewAddressesPage(
(showHidden, _) => NewAddressesPage(
showHidden: showHidden,
addressListViewModel: getIt<WalletAddressListViewModel>(),
dashboardViewModel: getIt<DashboardViewModel>(),
),
);
getIt.registerFactory(() {
getIt.registerLazySingleton(() {
final appStore = getIt.get<AppStore>();
return NodeListViewModel(_nodeSource, appStore);
});
getIt.registerFactory(() {
final appStore = getIt.get<AppStore>();
return PowNodeListViewModel(_powNodeSource, appStore);
return PowNodeListViewModel(appStore);
});
getIt.registerFactory(() => ConnectionSyncViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
@@ -1184,12 +1176,14 @@ Future<void> setup({
final WalletType type = args['type'] as WalletType? ?? getIt.get<AppStore>().wallet!.type;
final bool isPow = args['isPow'] as bool? ?? false;
final Node? editingNode = args['editingNode'] as Node?;
final nodeSourceArgs = isPow ? _powNodeSource : _nodeSource;
return NodeCreateOrEditViewModel(
nodeSourceArgs,
type,
editingNode,
getIt.get<SettingsStore>());
isPow,
getIt.get<NodeListViewModel>(),
getIt.get<PowNodeListViewModel>(),
type,
getIt.get<SettingsStore>(),
editingNode: editingNode
);
}
);
@@ -1791,7 +1785,6 @@ Future<void> setup({
getIt.registerLazySingleton(() => NodeSwitchingService(
appStore: getIt.get<AppStore>(),
settingsStore: getIt.get<SettingsStore>(),
nodeSource: _nodeSource,
));
getIt.registerFactoryParam<BridgeAmountPage, CryptoCurrency, void>(
+119 -372
View File
@@ -18,6 +18,7 @@ import 'package:cake_wallet/wownero/wownero.dart';
import 'package:collection/collection.dart';
import 'package:cw_core/node.dart';
import 'package:cake_wallet/entities/sync_status_display_mode.dart';
import 'package:cw_core/node_list.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/root_dir.dart';
import 'package:cw_core/spl_token.dart';
@@ -61,8 +62,6 @@ Future<void> defaultSettingsMigration(
{required int version,
required SharedPreferences sharedPreferences,
required SecureStorage secureStorage,
required Box<Node> nodes,
required Box<Node> powNodes,
required Box<Contact> contactSource,
required Box<HavenSeedStore> havenSeedStore}) async {
if (Platform.isIOS) {
@@ -70,7 +69,7 @@ Future<void> defaultSettingsMigration(
}
// check current nodes for nullability regardless of the version
await checkCurrentNodes(nodes, powNodes, sharedPreferences);
// await checkCurrentNodes(sharedPreferences);
final isNewInstall =
sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null;
@@ -103,10 +102,9 @@ Future<void> defaultSettingsMigration(
await sharedPreferences.setInt(
PreferencesKey.currentBalanceDisplayModeKey, BalanceDisplayMode.availableBalance.raw);
await sharedPreferences.setBool('save_recipient_address', true);
await resetToDefault(nodes);
await resetToDefault();
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.monero,
currentNodePreferenceKey: PreferencesKey.currentNodeIdKey,
@@ -114,30 +112,26 @@ Future<void> defaultSettingsMigration(
trusted: true,
);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoin,
currentNodePreferenceKey: PreferencesKey.currentBitcoinElectrumSererIdKey,
useSSL: true,
);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.litecoin,
currentNodePreferenceKey: PreferencesKey.currentLitecoinElectrumSererIdKey,
useSSL: true,
);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.haven,
currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
);
break;
case 2:
await replaceNodesMigration(nodes: nodes);
await replaceNodesMigration();
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.monero,
newDefaultUri: newCakeWalletMoneroUri,
@@ -152,13 +146,12 @@ Future<void> defaultSettingsMigration(
);
break;
case 3:
await updateNodeTypes(nodes: nodes);
await addWalletNodeList(nodes: nodes, type: WalletType.bitcoin);
await updateNodeTypes();
await addWalletNodeList(type: WalletType.bitcoin);
break;
case 4:
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoin,
newDefaultUri: newCakeWalletBitcoinUri,
@@ -185,7 +178,6 @@ Future<void> defaultSettingsMigration(
case 11:
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.monero,
newDefaultUri: newCakeWalletMoneroUri,
@@ -196,38 +188,35 @@ Future<void> defaultSettingsMigration(
break;
case 12:
await checkCurrentNodes(nodes, powNodes, sharedPreferences);
// await checkCurrentNodes(sharedPreferences);
break;
case 13:
await resetBitcoinElectrumServer(nodes, sharedPreferences);
await resetBitcoinElectrumServer(sharedPreferences);
break;
case 15:
await addWalletNodeList(nodes: nodes, type: WalletType.litecoin);
await addWalletNodeList(type: WalletType.litecoin);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.litecoin,
currentNodePreferenceKey: PreferencesKey.currentLitecoinElectrumSererIdKey,
);
await checkCurrentNodes(nodes, powNodes, sharedPreferences);
// await checkCurrentNodes(sharedPreferences);
break;
case 16:
await addWalletNodeList(nodes: nodes, type: WalletType.haven);
await addWalletNodeList(type: WalletType.haven);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.haven,
currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
);
await checkCurrentNodes(nodes, powNodes, sharedPreferences);
// await checkCurrentNodes(sharedPreferences);
break;
case 17:
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.haven,
currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
@@ -235,7 +224,7 @@ Future<void> defaultSettingsMigration(
break;
case 18:
addWalletNodeList(nodes: nodes, type: WalletType.monero);
addWalletNodeList(type: WalletType.monero);
break;
case 19:
@@ -245,25 +234,22 @@ Future<void> defaultSettingsMigration(
await migrateExchangeStatus(sharedPreferences);
break;
case 21:
await addWalletNodeList(nodes: nodes, type: WalletType.ethereum);
await addWalletNodeList(type: WalletType.ethereum);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.ethereum,
currentNodePreferenceKey: PreferencesKey.currentEthereumNodeIdKey,
);
break;
case 22:
await addWalletNodeList(nodes: nodes, type: WalletType.nano);
await addNanoPowNodeList(nodes: powNodes);
await addWalletNodeList(type: WalletType.nano);
await addNanoPowNodeList();
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.nano,
currentNodePreferenceKey: PreferencesKey.currentNanoNodeIdKey,
);
await _changeDefaultNode(
nodes: powNodes,
sharedPreferences: sharedPreferences,
type: WalletType.nano,
currentNodePreferenceKey: PreferencesKey.currentNanoPowNodeIdKey,
@@ -271,18 +257,16 @@ Future<void> defaultSettingsMigration(
);
break;
case 23:
await addWalletNodeList(nodes: nodes, type: WalletType.bitcoinCash);
await addWalletNodeList(type: WalletType.bitcoinCash);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoinCash,
currentNodePreferenceKey: PreferencesKey.currentBitcoinCashNodeIdKey,
);
break;
case 24:
await addWalletNodeList(nodes: nodes, type: WalletType.polygon);
await addWalletNodeList(type: WalletType.polygon);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.polygon,
currentNodePreferenceKey: PreferencesKey.currentPolygonNodeIdKey,
@@ -299,9 +283,8 @@ Future<void> defaultSettingsMigration(
// await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences);
break;
case 27:
await addWalletNodeList(nodes: nodes, type: WalletType.solana);
await addWalletNodeList( type: WalletType.solana);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.solana,
currentNodePreferenceKey: PreferencesKey.currentSolanaNodeIdKey,
@@ -313,7 +296,6 @@ Future<void> defaultSettingsMigration(
break;
case 29:
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoin,
newDefaultUri: newCakeWalletBitcoinUri,
@@ -326,25 +308,23 @@ Future<void> defaultSettingsMigration(
await disableServiceStatusFiatDisabled(sharedPreferences);
break;
case 31:
await updateNanoNodeList(nodes: nodes);
await updateNanoNodeList();
break;
case 32:
await updateBtcNanoWalletInfos();
break;
case 33:
await addWalletNodeList(nodes: nodes, type: WalletType.tron);
await addWalletNodeList(type: WalletType.tron);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.tron,
currentNodePreferenceKey: PreferencesKey.currentTronNodeIdKey,
);
break;
case 34:
addWalletNodeList(nodes: nodes, type: WalletType.bitcoin);
addWalletNodeList(type: WalletType.bitcoin);
case 35:
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoin,
newDefaultUri: newCakeWalletBitcoinUri,
@@ -354,9 +334,8 @@ Future<void> defaultSettingsMigration(
);
break;
case 36:
await addWalletNodeList(nodes: nodes, type: WalletType.wownero);
await addWalletNodeList(type: WalletType.wownero);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.wownero,
currentNodePreferenceKey: PreferencesKey.currentWowneroNodeIdKey,
@@ -370,9 +349,8 @@ Future<void> defaultSettingsMigration(
await fixBtcDerivationPaths();
break;
case 39:
_fixNodesUseSSLFlag(nodes);
_fixNodesUseSSLFlag();
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.nano,
newDefaultUri: nanoDefaultNodeUri,
@@ -382,7 +360,7 @@ Future<void> defaultSettingsMigration(
);
break;
case 40:
await removeMoneroWorld(sharedPreferences: sharedPreferences, nodes: nodes);
await removeMoneroWorld(sharedPreferences: sharedPreferences);
break;
case 41:
_changeExchangeProviderAvailability(
@@ -390,14 +368,14 @@ Future<void> defaultSettingsMigration(
providerName: "SwapTrade",
enabled: false,
);
addWalletNodeList(nodes: nodes, type: WalletType.bitcoin);
addWalletNodeList(nodes: nodes, type: WalletType.tron);
addWalletNodeList(type: WalletType.bitcoin);
addWalletNodeList(type: WalletType.tron);
break;
case 42:
_fixNodesUseSSLFlag(nodes);
_fixNodesUseSSLFlag();
break;
case 43:
_fixNodesUseSSLFlag(nodes);
_fixNodesUseSSLFlag();
_changeExchangeProviderAvailability(
sharedPreferences,
providerName: "THORChain",
@@ -410,9 +388,8 @@ Future<void> defaultSettingsMigration(
);
break;
case 44:
_fixNodesUseSSLFlag(nodes);
_fixNodesUseSSLFlag();
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoin,
newDefaultUri: newCakeWalletBitcoinUri,
@@ -421,7 +398,6 @@ Future<void> defaultSettingsMigration(
oldUri: ['cakewallet.com'],
);
_changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.tron,
newDefaultUri: tronDefaultNodeUri,
@@ -436,10 +412,9 @@ Future<void> defaultSettingsMigration(
case 45:
// await _backupHavenSeeds(havenSeedStore);
addWalletNodeList(nodes: nodes, type: WalletType.polygon);
addWalletNodeList(nodes: nodes, type: WalletType.ethereum);
addWalletNodeList(type: WalletType.polygon);
addWalletNodeList(type: WalletType.ethereum);
_changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.tron,
newDefaultUri: tronDefaultNodeUri,
@@ -451,7 +426,6 @@ Future<void> defaultSettingsMigration(
],
);
_changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.solana,
newDefaultUri: solanaDefaultNodeUri,
@@ -461,10 +435,9 @@ Future<void> defaultSettingsMigration(
);
break;
case 46:
await _fixNodesUseSSLFlag(nodes);
await addWalletNodeList(nodes: nodes, type: WalletType.litecoin);
await _fixNodesUseSSLFlag();
await addWalletNodeList(type: WalletType.litecoin);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.solana,
newDefaultUri: solanaDefaultNodeUri,
@@ -477,21 +450,18 @@ Future<void> defaultSettingsMigration(
],
);
await _updateNode(
nodes: nodes,
currentUri: "ethereum.publicnode.com",
newUri: "ethereum-rpc.publicnode.com",
useSSL: true,
);
await _updateNode(
nodes: nodes,
currentUri: "polygon-bor.publicnode.com",
newUri: "polygon-bor-rpc.publicnode.com",
useSSL: true,
);
case 47:
await addWalletNodeList(nodes: nodes, type: WalletType.zano);
await addWalletNodeList(type: WalletType.zano);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.zano,
currentNodePreferenceKey: PreferencesKey.currentZanoNodeIdKey,
@@ -508,9 +478,8 @@ Future<void> defaultSettingsMigration(
);
break;
case 48:
await addWalletNodeList(nodes: nodes, type: WalletType.decred);
await addWalletNodeList(type: WalletType.decred);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.decred,
currentNodePreferenceKey: PreferencesKey.currentDecredNodeIdKey,
@@ -524,36 +493,32 @@ Future<void> defaultSettingsMigration(
);
break;
case 50:
migrateExistingNodesToUseAutoSwitching(nodes: nodes, powNodes: powNodes);
migrateExistingNodesToUseAutoSwitching();
break;
case 51:
_changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.zano,
currentNodePreferenceKey: PreferencesKey.currentZanoNodeIdKey,
);
await addWalletNodeList(nodes: nodes, type: WalletType.dogecoin);
await addWalletNodeList(type: WalletType.dogecoin);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.dogecoin,
currentNodePreferenceKey: PreferencesKey.currentDogecoinNodeIdKey,
);
break;
case 52:
await addWalletNodeList(nodes: nodes, type: WalletType.base);
await addWalletNodeList(type: WalletType.base);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.base,
currentNodePreferenceKey: PreferencesKey.currentBaseNodeIdKey,
);
break;
case 53:
await addWalletNodeList(nodes: nodes, type: WalletType.arbitrum);
case 53:
await addWalletNodeList(type: WalletType.arbitrum);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.arbitrum,
currentNodePreferenceKey: PreferencesKey.currentArbitrumNodeIdKey,
@@ -563,9 +528,8 @@ Future<void> defaultSettingsMigration(
await _backupWowneroSeeds(havenSeedStore);
break;
case 55:
await addWalletNodeList(nodes: nodes, type: WalletType.zcash);
await addWalletNodeList(type: WalletType.zcash);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.zcash,
currentNodePreferenceKey: PreferencesKey.currentZcashNodeIdKey,
@@ -577,9 +541,8 @@ Future<void> defaultSettingsMigration(
case 57:
await _addXautTokenToExistingEthereumWallets();
await addWalletNodeList(nodes: nodes, type: WalletType.bsc);
await addWalletNodeList(type: WalletType.bsc);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bsc,
currentNodePreferenceKey: PreferencesKey.currentBscNodeIdKey,
@@ -624,13 +587,18 @@ Future<void> defaultSettingsMigration(
break;
case 65:
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.base,
currentNodePreferenceKey: PreferencesKey.currentBaseNodeIdKey,
oldUri: ['base.nownodes.io'],
);
break;
case 66:
await _changeDefaultNode(
sharedPreferences: sharedPreferences,
type: WalletType.arbitrum,
currentNodePreferenceKey: PreferencesKey.currentArbitrumNodeIdKey,
oldUri: ["arbitrum.nownodes.io"]);
default:
break;
}
@@ -647,12 +615,13 @@ Future<void> defaultSettingsMigration(
}
Future<void> _updateNode({
required Box<Node> nodes,
required String currentUri,
String? newUri,
bool? useSSL,
}) async {
for (Node node in nodes.values) {
final nodes = await Node.getAll();
for (Node node in nodes) {
if (node.uriRaw == currentUri) {
if (newUri != null) {
node.uriRaw = newUri;
@@ -668,7 +637,6 @@ Future<void> _updateNode({
/// generic function for changing any wallet default node
/// instead of making a new function for each change
Future<void> _changeDefaultNode({
required Box<Node> nodes,
required SharedPreferences sharedPreferences,
required WalletType type,
required String currentNodePreferenceKey,
@@ -678,19 +646,21 @@ Future<void> _changeDefaultNode({
List<String>?
oldUri, // ignore, if you want to force replace the node regardless of the user's current node
}) async {
List<Node> nodes = await Node.getAll();
final currentNodeId = sharedPreferences.getInt(currentNodePreferenceKey);
final bool shouldReplace;
if (currentNodeId == null) {
shouldReplace = true;
} else {
final currentNode = nodes.values.firstWhere((node) => node.key == currentNodeId);
shouldReplace = oldUri?.any((e) => currentNode.uriRaw.contains(e)) ?? true;
final currentNode = nodes.firstWhereOrNull((node) => node.id == currentNodeId);
shouldReplace = currentNode == null || oldUri?.any((e) => currentNode!.uriRaw.contains(e)) ?? true;
}
if (shouldReplace) {
newDefaultUri ??= _getDefaultNodeUri(type);
newDefaultUri ??= (await getDefaultNodeFromFiles(type)).uriRaw;
var newNodeId =
nodes.values.firstWhereOrNull((element) => element.uriRaw == newDefaultUri)?.key;
nodes.firstWhereOrNull((element) => element.uriRaw == newDefaultUri)?.id;
// new node doesn't exist, then add it
if (newNodeId == null) {
@@ -701,55 +671,11 @@ Future<void> _changeDefaultNode({
trusted: trusted,
);
await nodes.add(newNode);
newNodeId = newNode.key;
await newNode.save();
newNodeId = newNode.id;
}
await sharedPreferences.setInt(currentNodePreferenceKey, newNodeId as int);
}
}
String _getDefaultNodeUri(WalletType type) {
switch (type) {
case WalletType.monero:
return newCakeWalletMoneroUri;
case WalletType.bitcoin:
return newCakeWalletBitcoinUri;
case WalletType.litecoin:
return cakeWalletLitecoinElectrumUri;
case WalletType.haven:
return havenDefaultNodeUri;
case WalletType.ethereum:
return ethereumDefaultNodeUri;
case WalletType.nano:
return nanoDefaultNodeUri;
case WalletType.bitcoinCash:
return cakeWalletBitcoinCashDefaultNodeUri;
case WalletType.polygon:
return polygonDefaultNodeUri;
case WalletType.solana:
return solanaDefaultNodeUri;
case WalletType.tron:
return tronDefaultNodeUri;
case WalletType.wownero:
return wowneroDefaultNodeUri;
case WalletType.zano:
return zanoDefaultNodeUri;
case WalletType.decred:
return decredDefaultUri;
case WalletType.dogecoin:
return dogecoinDefaultNodeUri;
case WalletType.base:
return baseDefaultNodeUri;
case WalletType.arbitrum:
return arbitrumDefaultNodeUri;
case WalletType.bsc:
return bscDefaultNodeUri;
case WalletType.zcash:
return zcashDefaultNodeUri;
case WalletType.banano:
case WalletType.none:
return '';
await sharedPreferences.setInt(currentNodePreferenceKey, newNodeId);
}
}
@@ -767,8 +693,9 @@ Future<void> _changeExchangeProviderAvailability(SharedPreferences sharedPrefere
);
}
Future<void> _fixNodesUseSSLFlag(Box<Node> nodes) async {
for (Node node in nodes.values) {
Future<void> _fixNodesUseSSLFlag() async {
final nodes = await Node.getAll();
for (Node node in nodes) {
switch (node.uriRaw) {
case cakeWalletLitecoinElectrumUri:
case cakeWalletBitcoinElectrumUri:
@@ -781,7 +708,8 @@ Future<void> _fixNodesUseSSLFlag(Box<Node> nodes) async {
}
}
Future<void> updateNanoNodeList({required Box<Node> nodes}) async {
Future<void> updateNanoNodeList() async {
final nodes = await Node.getAll();
final nodeList = await loadDefaultNodes(WalletType.nano);
var listOfNewEndpoints = <String>[
"app.natrium.io",
@@ -792,14 +720,14 @@ Future<void> updateNanoNodeList({required Box<Node> nodes}) async {
];
// add new nodes:
for (final node in nodeList) {
if (listOfNewEndpoints.contains(node.uriRaw) && !nodes.values.contains(node)) {
await nodes.add(node);
if (listOfNewEndpoints.contains(node.uriRaw) && !nodes.contains(node)) {
await node.save();
}
}
// update the nautilus node:
final nautilusNode =
nodes.values.firstWhereOrNull((element) => element.uriRaw == "node.perish.co");
nodes.firstWhereOrNull((element) => element.uriRaw == "node.perish.co");
if (nautilusNode != null) {
nautilusNode.uriRaw = "node.nautilus.io";
nautilusNode.path = "/api";
@@ -916,16 +844,17 @@ Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPre
}
}
Future<void> replaceNodesMigration({required Box<Node> nodes}) async {
Future<void> replaceNodesMigration() async {
final replaceNodes = <String, Node>{
'eu-node.cakewallet.io:18081':
Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
'node.cakewallet.io:18081':
Node(uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
Node(uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
'node.xmr.ru:13666': Node(uri: 'node.monero.net:18081', type: WalletType.monero)
};
nodes.values.forEach((Node node) async {
List<Node> nodes = await Node.getAll();
nodes.forEach((Node node) async {
final nodeToReplace = replaceNodes[node.uri];
if (nodeToReplace != null) {
@@ -937,16 +866,12 @@ Future<void> replaceNodesMigration({required Box<Node> nodes}) async {
});
}
Node? getBitcoinTestnetDefaultElectrumServer({required Box<Node> nodes}) {
return nodes.values
.firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
}
Future<Node?> getBitcoinTestnetDefaultElectrumServer()async {
final nodes = await Node.getAll();
Node? getDefaultNode({required Box<Node> nodes, required WalletType type}) {
final defaultUri = _getDefaultNodeUri(type);
return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == defaultUri) ??
nodes.values.firstWhereOrNull((node) => node.type == type);
return nodes
.firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
nodes.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
}
Future<void> insecureStorageMigration({
@@ -1057,8 +982,9 @@ Future<void> rewriteSecureStoragePin({required SecureStorage secureStorage}) asy
);
}
Future<void> updateNodeTypes({required Box<Node> nodes}) async {
nodes.values.forEach((node) async {
Future<void> updateNodeTypes() async {
List<Node> nodes = await Node.getAll();
nodes.forEach((node) async {
if (node.type == null) {
node.type = WalletType.monero;
await node.save();
@@ -1146,206 +1072,13 @@ Future<void> updateBtcNanoWalletInfos() async {}
// }
// }
Future<void> checkCurrentNodes(
Box<Node> nodeSource, Box<Node> powNodeSource, SharedPreferences sharedPreferences) async {
final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
final currentBitcoinElectrumSeverId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
final currentLitecoinElectrumSeverId =
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
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);
final currentBitcoinCashNodeId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
final currentDogecoinNodeId = sharedPreferences.getInt(PreferencesKey.currentDogecoinNodeIdKey);
final currentSolanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
final currentTronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
final currentWowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
final currentZanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey);
final currentZcashNodeId = sharedPreferences.getInt(PreferencesKey.currentZcashNodeIdKey);
final currentMoneroNode =
nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId);
final currentBitcoinElectrumServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinElectrumSeverId);
final currentLitecoinElectrumServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentLitecoinElectrumSeverId);
final currentHavenNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId);
final currentEthereumNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId);
final currentPolygonNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentPolygonNodeId);
final currentBaseNodeServer =
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 =
nodeSource.values.firstWhereOrNull((node) => node.key == currentDecredNodeId);
final currentNanoPowNodeServer =
powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId);
final currentBitcoinCashNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId);
final currentDogecoinNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentDogecoinNodeId);
final currentSolanaNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentSolanaNodeId);
final currentTronNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentTronNodeId);
final currentWowneroNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentWowneroNodeId);
final currentZanoNode =
nodeSource.values.firstWhereOrNull((node) => node.key == currentZanoNodeId);
final currentZcashNode =
nodeSource.values.firstWhereOrNull((node) => node.key == currentZcashNodeId);
if (currentMoneroNode == null) {
final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
await nodeSource.add(newCakeWalletNode);
await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, newCakeWalletNode.key as int);
}
if (currentBitcoinElectrumServer == null) {
final cakeWalletElectrum = Node(
uri: cakeWalletBitcoinElectrumUri,
type: WalletType.bitcoin,
useSSL: false,
isEnabledForAutoSwitching: true);
await nodeSource.add(cakeWalletElectrum);
final cakeWalletElectrumTestnet =
Node(uri: publicBitcoinTestnetElectrumUri, type: WalletType.bitcoin, useSSL: false);
await nodeSource.add(cakeWalletElectrumTestnet);
await sharedPreferences.setInt(
PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletElectrum.key as int);
}
if (currentLitecoinElectrumServer == null) {
final cakeWalletElectrum =
Node(uri: cakeWalletLitecoinElectrumUri, type: WalletType.litecoin, useSSL: false);
await nodeSource.add(cakeWalletElectrum);
await sharedPreferences.setInt(
PreferencesKey.currentLitecoinElectrumSererIdKey, cakeWalletElectrum.key as int);
}
if (currentHavenNodeServer == null) {
final node = Node(uri: havenDefaultNodeUri, type: WalletType.haven);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, node.key as int);
}
if (currentEthereumNodeServer == null) {
final node = Node(uri: ethereumDefaultNodeUri, type: WalletType.ethereum);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, node.key as int);
}
if (currentNanoNodeServer == null) {
final node = Node(uri: nanoDefaultNodeUri, useSSL: true, type: WalletType.nano);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int);
}
if (currentNanoPowNodeServer == null) {
Node? node = powNodeSource.values
.firstWhereOrNull((node) => node.uri.toString() == nanoDefaultPowNodeUri);
if (node == null) {
node = Node(uri: nanoDefaultPowNodeUri, useSSL: true, type: WalletType.nano);
await powNodeSource.add(node);
}
await sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, node.key as int);
}
if (currentBitcoinCashNodeServer == null) {
final node =
Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash, useSSL: false);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
}
if (currentDogecoinNodeServer == null) {
final node = Node(uri: dogecoinDefaultNodeUri, type: WalletType.dogecoin, useSSL: true);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentDogecoinNodeIdKey, node.key as int);
}
if (currentPolygonNodeServer == null) {
final node = Node(uri: polygonDefaultNodeUri, type: WalletType.polygon);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int);
}
if (currentBaseNodeServer == null) {
final node = Node(uri: baseDefaultNodeUri, type: WalletType.base);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentBaseNodeIdKey, node.key as int);
}
if (currentArbitrumNodeServer == null) {
final node = Node(uri: arbitrumDefaultNodeUri, type: WalletType.arbitrum);
await nodeSource.add(node);
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);
await sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int);
}
if (currentTronNodeServer == null) {
final node = Node(uri: tronDefaultNodeUri, type: WalletType.tron);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, node.key as int);
}
if (currentWowneroNodeServer == null) {
final node = Node(uri: wowneroDefaultNodeUri, type: WalletType.wownero);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, node.key as int);
}
if (currentZanoNode == null) {
final node = Node(uri: zanoDefaultNodeUri, type: WalletType.zano);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.key as int);
}
if (currentDecredNodeServer == null) {
final node = Node(uri: decredDefaultUri, type: WalletType.decred);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentDecredNodeIdKey, node.key as int);
}
if (currentZcashNode == null) {
final node = Node(uri: zcashDefaultNodeUri, type: WalletType.zcash, useSSL: true);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentZcashNodeIdKey, node.key as int);
}
}
Future<void> resetBitcoinElectrumServer(
Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
Future<void> resetBitcoinElectrumServer(SharedPreferences sharedPreferences) async {
final nodeSource = await Node.getAll();
final currentElectrumSeverId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
final oldElectrumServer = nodeSource.values
final oldElectrumServer = nodeSource
.firstWhereOrNull((node) => node.uri.toString().contains('electrumx.cakewallet.com'));
var cakeWalletNode = nodeSource.values
var cakeWalletNode = nodeSource
.firstWhereOrNull((node) => node.uriRaw.toString() == cakeWalletBitcoinElectrumUri);
if (cakeWalletNode == null) {
@@ -1357,12 +1090,12 @@ Future<void> resetBitcoinElectrumServer(
// final cakeWalletElectrumTestnet =
// Node(uri: publicBitcoinTestnetElectrumUri, type: WalletType.bitcoin, useSSL: false);
// await nodeSource.add(cakeWalletElectrumTestnet);
await nodeSource.add(cakeWalletNode);
await cakeWalletNode.save();
}
if (currentElectrumSeverId == oldElectrumServer?.key) {
if (currentElectrumSeverId == oldElectrumServer?.id) {
await sharedPreferences.setInt(
PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletNode.key as int);
PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletNode.id);
}
await oldElectrumServer?.delete();
@@ -1380,38 +1113,42 @@ Future<void> migrateExchangeStatus(SharedPreferences sharedPreferences) async {
await sharedPreferences.remove(PreferencesKey.disableExchangeKey);
}
Future<void> addNanoPowNodeList({required Box<Node> nodes}) async {
Future<void> addNanoPowNodeList() async {
final nodeList = await loadDefaultNanoPowNodes();
final nodes = await Node.getAllPow();
for (var node in nodeList) {
if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
await nodes.add(node);
if (nodes.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
await node.save();
}
}
}
Node? getNanoDefaultPowNode({required Box<Node> nodes}) {
return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultPowNodeUri) ??
nodes.values.firstWhereOrNull((node) => (node.type == WalletType.nano));
Future<Node?> getNanoDefaultPowNode() async {
final nodes = await Node.getAll();
return nodes.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultPowNodeUri) ??
nodes.firstWhereOrNull((node) => (node.type == WalletType.nano));
}
Future<void> addWalletNodeList({required Box<Node> nodes, required WalletType type}) async {
Future<void> addWalletNodeList({required WalletType type}) async {
final nodes = await Node.getAll();
final List<Node> nodeList = await loadDefaultNodes(type);
for (var node in nodeList) {
if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
await nodes.add(node);
if (nodes.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
await node.save();
}
}
}
Future<void> removeMoneroWorld(
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
{required SharedPreferences sharedPreferences}) async {
final nodes = await Node.getAll();
const cakeWalletMoneroNodeUriPattern = '.moneroworld.com';
final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
final currentMoneroNode = nodes.values.firstWhere((node) => node.key == currentMoneroNodeId);
final currentMoneroNode = nodes.firstWhere((node) => node.id == currentMoneroNodeId);
final needToReplaceCurrentMoneroNode =
currentMoneroNode.uri.toString().contains(cakeWalletMoneroNodeUriPattern);
nodes.values.forEach((node) async {
nodes.forEach((node) async {
if (node.type == WalletType.monero &&
node.uri.toString().contains(cakeWalletMoneroNodeUriPattern)) {
await node.delete();
@@ -1420,7 +1157,6 @@ Future<void> removeMoneroWorld(
if (needToReplaceCurrentMoneroNode) {
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.monero,
newDefaultUri: newCakeWalletMoneroUri,
@@ -1430,8 +1166,7 @@ Future<void> removeMoneroWorld(
}
}
Future<void> migrateExistingNodesToUseAutoSwitching(
{required Box<Node> nodes, required Box<Node> powNodes}) async {
Future<void> migrateExistingNodesToUseAutoSwitching() async {
final listOfDefaultNodesWithAutoSwitching = [
'bitcoincash.stackwallet.com:50002',
'bch.aftrek.org:50002',
@@ -1465,12 +1200,24 @@ Future<void> migrateExistingNodesToUseAutoSwitching(
'zano.cakewallet.com:11211',
'electrum.cakewallet.com:50002',
];
for (var node in [...nodes.values.toList(), ...powNodes.values.toList()]) {
final nodes = await Node.getAll();
for (var node in nodes) {
if (listOfDefaultNodesWithAutoSwitching.contains(node.uriRaw)) {
node.isEnabledForAutoSwitching = true;
await node.save();
}
}
final powNodes = await Node.getAllPow();
for(var node in powNodes) {
if (listOfDefaultNodesWithAutoSwitching.contains(node.uriRaw)) {
node.isEnabledForAutoSwitching = true;
node.isPow = true;
await node.save();
}
}
}
Future<void> _addXautTokenToExistingEthereumWallets() async {
+69
View File
@@ -0,0 +1,69 @@
import 'package:cake_wallet/core/utilities.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/node_list.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:shared_preferences/shared_preferences.dart';
const Map<WalletType, String> nodePreferenceKeys = {
WalletType.monero: PreferencesKey.currentNodeIdKey,
WalletType.bitcoin: PreferencesKey.currentBitcoinElectrumSererIdKey,
WalletType.litecoin: PreferencesKey.currentLitecoinElectrumSererIdKey,
WalletType.haven: PreferencesKey.currentHavenNodeIdKey,
WalletType.ethereum: PreferencesKey.currentEthereumNodeIdKey,
WalletType.polygon: PreferencesKey.currentPolygonNodeIdKey,
WalletType.base: PreferencesKey.currentBaseNodeIdKey,
WalletType.arbitrum: PreferencesKey.currentArbitrumNodeIdKey,
WalletType.bsc: PreferencesKey.currentBscNodeIdKey,
WalletType.nano: PreferencesKey.currentNanoNodeIdKey,
WalletType.decred: PreferencesKey.currentDecredNodeIdKey,
WalletType.bitcoinCash: PreferencesKey.currentBitcoinCashNodeIdKey,
WalletType.dogecoin: PreferencesKey.currentDogecoinNodeIdKey,
WalletType.solana: PreferencesKey.currentSolanaNodeIdKey,
WalletType.tron: PreferencesKey.currentTronNodeIdKey,
WalletType.wownero: PreferencesKey.currentWowneroNodeIdKey,
WalletType.zano: PreferencesKey.currentZanoNodeIdKey,
WalletType.zcash: PreferencesKey.currentZcashNodeIdKey,
};
const Map<WalletType, String> powNodePreferenceKeys = {
WalletType.nano: PreferencesKey.currentNanoPowNodeIdKey
};
Future<void> checkNodeForWalletType(SharedPreferences sharedPreferences, SettingsStore settingsStore, WalletType type, bool isPow) async {
final preferenceKey = isPow ? powNodePreferenceKeys[type] : nodePreferenceKeys[type];
if(preferenceKey == null) {
return;
}
final currentId = await sharedPreferences.getInt(preferenceKey);
final nodes = isPow ? await Node.getAllForWalletTypePow(type) : await Node.getAllForWalletType(type);
final currentNode = nodes.firstWhereOrNull((item)=>item.id == currentId);
if(currentNode == null) {
final newNode = (isPow
? await Node.getDefaultPowForWalletType(type)
: await Node.getDefaultForWalletType(type)) ??
await getDefaultNodeFromFiles(type, isPow: isPow);
final newId = await newNode.save();
sharedPreferences.setInt(preferenceKey, newId);
settingsStore.nodes[type] = newNode;
} else {
settingsStore.nodes[type] = currentNode;
}
}
Future<void> checkCurrentNodes(SharedPreferences sharedPreferences, SettingsStore settingsStore) async {
for(final walletType in nodePreferenceKeys.keys) {
await checkNodeForWalletType(sharedPreferences, settingsStore, walletType, false);
}
for(final walletType in powNodePreferenceKeys.keys) {
await checkNodeForWalletType(sharedPreferences, settingsStore, walletType, true);
}
}
-148
View File
@@ -1,148 +0,0 @@
import 'package:flutter/services.dart';
import 'package:hive/hive.dart';
import "package:yaml/yaml.dart";
import 'package:cw_core/node.dart';
import 'package:cw_core/wallet_type.dart';
Future<List<Node>> loadDefaultNodes(WalletType type) async {
String path;
switch (type) {
case WalletType.monero:
path = 'assets/node_list.yml';
break;
case WalletType.bitcoin:
path = 'assets/bitcoin_electrum_server_list.yml';
break;
case WalletType.litecoin:
path = 'assets/litecoin_electrum_server_list.yml';
break;
case WalletType.haven:
path = 'assets/haven_node_list.yml';
break;
// TODO: (refactoring) each wallet would have its path, so `wallet.nodePath` would be decided based on chain id in Evm wallet
case WalletType.ethereum:
path = 'assets/ethereum_server_list.yml';
break;
case WalletType.nano:
path = 'assets/nano_node_list.yml';
break;
case WalletType.bitcoinCash:
path = 'assets/bitcoin_cash_electrum_server_list.yml';
break;
case WalletType.polygon:
path = 'assets/polygon_node_list.yml';
break;
case WalletType.solana:
path = 'assets/solana_node_list.yml';
break;
case WalletType.tron:
path = 'assets/tron_node_list.yml';
break;
case WalletType.wownero:
path = 'assets/wownero_node_list.yml';
break;
case WalletType.zano:
path = 'assets/zano_node_list.yml';
break;
case WalletType.decred:
path = 'assets/decred_node_list.yml';
break;
case WalletType.dogecoin:
path = 'assets/dogecoin_electrum_server_list.yml';
break;
case WalletType.base:
path = 'assets/base_node_list.yml';
break;
case WalletType.arbitrum:
path = 'assets/arbitrum_node_list.yml';
break;
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 = '';
break;
}
final nodesRaw = await rootBundle.loadString(path);
final loadedNodes = loadYaml(nodesRaw) as YamlList;
final nodes = <Node>[];
for (final raw in loadedNodes) {
if (raw is Map) {
final node = Node.fromMap(Map<String, Object>.from(raw));
node.type = type;
nodes.add(node);
}
}
return nodes;
}
Future<List<Node>> loadDefaultNanoPowNodes() async {
final powNodesRaw = await rootBundle.loadString('assets/nano_pow_node_list.yml');
final loadedPowNodes = loadYaml(powNodesRaw) as YamlList;
final nodes = <Node>[];
for (final raw in loadedPowNodes) {
if (raw is Map) {
final node = Node.fromMap(Map<String, Object>.from(raw));
node.type = WalletType.nano;
nodes.add(node);
}
}
return nodes;
}
Future<void> resetToDefault(Box<Node> nodeSource) async {
final moneroNodes = await loadDefaultNodes(WalletType.monero);
final bitcoinElectrumServerList = await loadDefaultNodes(WalletType.bitcoin);
final litecoinElectrumServerList = await loadDefaultNodes(WalletType.litecoin);
final bitcoinCashElectrumServerList = await loadDefaultNodes(WalletType.bitcoinCash);
final havenNodes = await loadDefaultNodes(WalletType.haven);
final ethereumNodes = await loadDefaultNodes(WalletType.ethereum);
final nanoNodes = await loadDefaultNodes(WalletType.nano);
final polygonNodes = await loadDefaultNodes(WalletType.polygon);
final solanaNodes = await loadDefaultNodes(WalletType.solana);
final tronNodes = await loadDefaultNodes(WalletType.tron);
final decredNodes = await loadDefaultNodes(WalletType.decred);
final zanoNodes = await loadDefaultNodes(WalletType.zano);
final dogecoinElectrumServerList = await loadDefaultNodes(WalletType.dogecoin);
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 +
litecoinElectrumServerList +
havenNodes +
ethereumNodes +
bitcoinCashElectrumServerList +
nanoNodes +
polygonNodes +
solanaNodes +
tronNodes +
zanoNodes +
decredNodes +
dogecoinElectrumServerList +
baseNodes +
arbitrumNodes +
zcashNodes +
bscNodes;
await nodeSource.clear();
await nodeSource.addAll(nodes);
}
Future<void> resetPowToDefault(Box<Node> powNodeSource) async {
final nanoPowNodes = await loadDefaultNanoPowNodes();
final nodes = nanoPowNodes;
await powNodeSource.clear();
await powNodeSource.addAll(nodes);
}
+7 -16
View File
@@ -16,6 +16,7 @@ import 'package:cake_wallet/entities/default_settings_migration.dart';
import 'package:cake_wallet/entities/get_encryption_key.dart';
import 'package:cake_wallet/entities/haven_seed_store.dart';
import 'package:cake_wallet/entities/language_service.dart';
import 'package:cake_wallet/entities/node_check.dart';
import 'package:cake_wallet/entities/template.dart';
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:cake_wallet/exchange/exchange_template.dart';
@@ -46,6 +47,7 @@ import 'package:cw_core/hive_type_ids.dart';
import 'package:cw_core/key.dart';
import 'package:cw_core/mweb_utxo.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/node_legacy.dart' show performNodeHiveMigration;
import 'package:cw_core/payjoin_session.dart';
import 'package:cw_core/root_dir.dart';
import 'package:cw_core/spl_token.dart';
@@ -220,9 +222,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
CakeHive.registerAdapter(ContactAdapter());
}
if (!CakeHive.isAdapterRegistered(Node.typeId)) {
CakeHive.registerAdapter(NodeAdapter());
}
if (!CakeHive.isAdapterRegistered(TransactionDescription.typeId)) {
CakeHive.registerAdapter(TransactionDescriptionAdapter());
@@ -286,13 +285,12 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey);
final contacts = await CakeHive.openBox<Contact>(Contact.boxName);
final nodes = await CakeHive.openBox<Node>(Node.boxName);
final powNodes =
await CakeHive.openBox<Node>(Node.boxName + "pow"); // must be different from Node.boxName
final transactionDescriptions = await CakeHive.openBox<TransactionDescription>(
TransactionDescription.boxName,
encryptionKey: transactionDescriptionsBoxKey);
await performTradeHiveMigration(secureStorage);
await performNodeHiveMigration();
await validateBuiltinNodes();
final orders = await CakeHive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey);
final templates = await CakeHive.openBox<Template>(Template.boxName);
@@ -309,8 +307,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
await initialSetup(
loadWallet: loadWallet,
sharedPreferences: await SharedPreferences.getInstance(),
nodes: nodes,
powNodes: powNodes,
contactSource: contacts,
ordersSource: orders,
unspentCoinsInfoSource: unspentCoinsInfoSource,
@@ -322,15 +318,13 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
payjoinSessionSource: payjoinSessionSource,
anonpayInvoiceInfo: anonpayInvoiceInfo,
havenSeedStore: havenSeedStore,
initialMigrationVersion: 65,
initialMigrationVersion: 66,
);
}
Future<void> initialSetup({
required bool loadWallet,
required SharedPreferences sharedPreferences,
required Box<Node> nodes,
required Box<Node> powNodes,
required Box<Contact> contactSource,
required Box<Order> ordersSource,
// required FiatConvertationService fiatConvertationService,
@@ -350,13 +344,9 @@ Future<void> initialSetup({
version: initialMigrationVersion,
sharedPreferences: sharedPreferences,
contactSource: contactSource,
nodes: nodes,
powNodes: powNodes,
havenSeedStore: havenSeedStore,
);
await setup(
nodeSource: nodes,
powNodeSource: powNodes,
contactSource: contactSource,
ordersSource: ordersSource,
templates: templates,
@@ -368,11 +358,12 @@ Future<void> initialSetup({
navigatorKey: navigatorKey,
secureStorage: secureStorage,
);
final settingsStore = getIt<SettingsStore>();
await checkCurrentNodes(sharedPreferences, settingsStore);
await getIt.get<ResetService>().resetAuthDataOnNewInstall(sharedPreferences);
await bootstrapOffline();
final settingsStore = getIt<SettingsStore>();
if (!settingsStore.currentBuiltinTor) {
bootstrapOnline(navigatorKey, loadWallet: loadWallet);
}
@@ -15,6 +15,7 @@ import 'package:cw_core/crypto_amount_format.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mobx/mobx.dart';
class SendConfirmSheet extends StatefulWidget {
@@ -128,15 +128,16 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
),
) ??
false;
if (confirmed) {
await widget.editingNode!.delete();
await widget.nodeCreateOrEditViewModel.delete(editingNode: widget.editingNode!);
Navigator.of(context).pop();
}
},
text: S.of(context).delete,
isDisabled: widget.editingNode == null ||
!widget.nodeCreateOrEditViewModel.isReady ||
widget.editingNode!.isBuiltin ||
(widget.isSelected ?? false),
color: Theme.of(context).colorScheme.errorContainer,
textColor: Theme.of(context).colorScheme.onErrorContainer,
@@ -151,9 +152,9 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
if (_nodeFormKey.currentState != null && !_nodeFormKey.currentState!.validate()) {
return;
}
await widget.nodeCreateOrEditViewModel.save(
editingNode: widget.editingNode, saveAsCurrent: widget.isSelected ?? false);
saveAsCurrent: widget.isSelected ?? false);
if (context.mounted) {
Navigator.of(context).pop();
}
@@ -143,7 +143,7 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
}
await widget.nodeCreateOrEditViewModel.save(
editingNode: widget.editingNode, saveAsCurrent: widget.isSelected ?? false);
saveAsCurrent: widget.isSelected ?? false);
Navigator.of(context).pop();
},
text: S.of(context).save,
+66 -61
View File
@@ -65,66 +65,77 @@ class NodeFormState extends State<NodeForm> {
key: _formKey,
child: NewListSections(
sections: {
'main': [
ListItemTextField(
keyValue: vm.nodeLabelUIKey,
label: 'Node label',
initialValue: vm.label,
),
ListItemTextField(
keyValue: vm.nodeAddressUIKey,
label: S.current.node_address,
initialValue: vm.address,
validator: vm.walletType == WalletType.decred
? NodeAddressValidatorDecredBlankException()
: NodeAddressValidator(),
),
if (vm.hasPathSupport)
if(!(vm.editingNode?.isBuiltin ?? false)) ...{
'main': [
ListItemTextField(
keyValue: vm.nodePathUIKey,
label: '/path',
initialValue: vm.path,
validator: NodePathValidator(),
),
ListItemTextField(
keyValue: vm.nodePortUIKey,
label: S.current.node_port,
initialValue: '',
//keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
validator: NodePortValidator(),
),
if (vm.hasAuthCredentials) ...[
ListItemTextField(
keyValue: vm.nodeUsernameUIKey,
label: S.current.login,
initialValue: vm.login,
keyValue: vm.nodeLabelUIKey,
label: 'Node label',
initialValue: vm.label,
),
ListItemTextField(
keyValue: vm.nodePasswordUIKey,
label: S.current.password,
initialValue: vm.password,
keyValue: vm.nodeAddressUIKey,
label: S.current.node_address,
initialValue: vm.address,
validator: vm.walletType == WalletType.decred
? NodeAddressValidatorDecredBlankException()
: NodeAddressValidator(),
),
]
],
'advanced': [
ListItemCheckbox(
keyValue: vm.useSSLUIKey,
label: S.current.use_ssl,
value: vm.useSSL,
onChanged: (value) => vm.useSSL = value),
ListItemCheckbox(
keyValue: vm.nodeTrustedUIKey,
label: S.current.trusted,
value: vm.trusted,
onChanged: (value) => vm.trusted = value,
),
if (vm.usesEmbeddedProxy)
if (vm.hasPathSupport)
ListItemTextField(
keyValue: vm.nodePathUIKey,
label: '/path',
initialValue: vm.path,
validator: NodePathValidator(),
),
ListItemTextField(
keyValue: vm.nodePortUIKey,
label: S.current.node_port,
initialValue: '',
//keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
validator: NodePortValidator(),
),
if (vm.hasAuthCredentials) ...[
ListItemTextField(
keyValue: vm.nodeUsernameUIKey,
label: S.current.login,
initialValue: vm.login,
),
ListItemTextField(
keyValue: vm.nodePasswordUIKey,
label: S.current.password,
initialValue: vm.password,
),
]
],
'advanced': [
ListItemCheckbox(
keyValue: vm.nodeEmbeddedTorProxyUIKey,
label: 'Embedded Tor SOCKS Proxy',
value: vm.usesEmbeddedProxy,
onChanged: (_) {},
keyValue: vm.useSSLUIKey,
label: S.current.use_ssl,
value: vm.useSSL,
onChanged: (value) => vm.useSSL = value),
ListItemCheckbox(
keyValue: vm.nodeTrustedUIKey,
label: S.current.trusted,
value: vm.trusted,
onChanged: (value) => vm.trusted = value,
),
if (vm.usesEmbeddedProxy)
ListItemCheckbox(
keyValue: vm.nodeEmbeddedTorProxyUIKey,
label: 'Embedded Tor SOCKS Proxy',
value: vm.usesEmbeddedProxy,
onChanged: (_) {},
),
if(FeatureFlag.isAutomaticNodeSwitchingEnabled)
ListItemCheckbox(
keyValue: vm.autoSwitchingUIKey,
label: S.current.enable_for_auto_switching,
value: vm.isEnabledForAutoSwitching,
onChanged: (value) => vm.isEnabledForAutoSwitching = value),
],
},
"proxy" : [
ListItemCheckbox(
keyValue: vm.useSocksProxyUIKey,
label: 'Use SOCKS Proxy',
@@ -141,13 +152,7 @@ class NodeFormState extends State<NodeForm> {
initialValue: vm.socksProxyAddress,
validator: SocksProxyNodeAddressValidator(),
),
if(FeatureFlag.isAutomaticNodeSwitchingEnabled)
ListItemCheckbox(
keyValue: vm.autoSwitchingUIKey,
label: S.current.enable_for_auto_switching,
value: vm.isEnabledForAutoSwitching,
onChanged: (value) => vm.isEnabledForAutoSwitching = value),
],
]
},
controllers: _controllers,
getCheckboxValue: vm.getCheckboxValue,
@@ -94,9 +94,9 @@ class ManageNodesPage extends BasePage {
nodeListViewModel?.nodes[index] ?? powNodeListViewModel!.nodes[index];
late bool isSelected;
if (isPow) {
isSelected = node.keyIndex == powNodeListViewModel!.currentNode.keyIndex;
isSelected = node.id == powNodeListViewModel!.currentNode.id;
} else {
isSelected = node.keyIndex == nodeListViewModel!.currentNode.keyIndex;
isSelected = node.id == nodeListViewModel!.currentNode.id;
}
final nodeListRow = NodeListRow(
title: node.uriRaw,
-3
View File
@@ -14,7 +14,6 @@ import 'package:cw_core/transaction_history.dart';
import 'package:cake_wallet/store/wallet_list_store.dart';
import 'package:cake_wallet/store/authentication_store.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/store/node_list_store.dart';
import 'package:shared_preferences/shared_preferences.dart';
part 'app_store.g.dart';
@@ -26,7 +25,6 @@ abstract class AppStoreBase with Store {
required this.authenticationStore,
required this.walletList,
required this.settingsStore,
required this.nodeListStore,
required this.themeStore,
}) : _amountParsingProxy = AmountParsingProxy(settingsStore.displayAmountsInSatoshi) {
reaction(
@@ -47,7 +45,6 @@ abstract class AppStoreBase with Store {
SettingsStore settingsStore;
NodeListStore nodeListStore;
ThemeStore themeStore;
-34
View File
@@ -1,34 +0,0 @@
import 'dart:async';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/di.dart';
import 'package:cw_core/node.dart';
import 'package:cake_wallet/utils/mobx.dart';
part 'node_list_store.g.dart';
class NodeListStore = NodeListStoreBase with _$NodeListStore;
abstract class NodeListStoreBase with Store {
NodeListStoreBase() : nodes = ObservableList<Node>();
static StreamSubscription<BoxEvent>? _onNodesSourceChange;
static NodeListStore? _instance;
static NodeListStore get instance {
if (_instance != null) {
return _instance!;
}
final nodeSource = getIt.get<Box<Node>>();
_instance = NodeListStore();
_instance!.nodes.clear();
_instance!.nodes.addAll(nodeSource.values);
_onNodesSourceChange?.cancel();
_onNodesSourceChange = nodeSource.bindToList(_instance!.nodes);
return _instance!;
}
final ObservableList<Node> nodes;
}
+78 -55
View File
@@ -995,7 +995,7 @@ abstract class SettingsStoreBase with Store {
@observable
bool mwebCardDisplay;
@observable
bool showZcashMissingFundsCard;
@@ -1104,8 +1104,7 @@ abstract class SettingsStoreBase with Store {
_sharedPreferences.setBool(PreferencesKey.shouldShowReceiveWarning, value);
static Future<SettingsStore> load(
{required Box<Node> nodeSource,
required Box<Node> powNodeSource,
{
required bool isBitcoinBuyEnabled,
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance}) async {
@@ -1318,43 +1317,66 @@ abstract class SettingsStoreBase with Store {
final decredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
final dogecoinNodeId = sharedPreferences.getInt(PreferencesKey.currentDogecoinNodeIdKey);
final nodeSource = await Node.getAll();
final powNodeSource = await Node.getAllPow();
/// get the selected node, if null, then use the default
final moneroNode = nodeSource.get(nodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == newCakeWalletMoneroUri);
final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == newCakeWalletBitcoinUri);
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == cakeWalletLitecoinElectrumUri);
final ethereumNode = nodeSource.get(ethereumNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == ethereumDefaultNodeUri);
final polygonNode = nodeSource.get(polygonNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == polygonDefaultNodeUri);
final baseNode = nodeSource.get(baseNodeId) ??
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) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == nanoDefaultNodeUri);
final decredNode = nodeSource.get(decredNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == decredDefaultUri);
final nanoPowNode = powNodeSource.get(nanoPowNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == nanoDefaultPowNodeUri);
final solanaNode = nodeSource.get(solanaNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == solanaDefaultNodeUri);
final tronNode = nodeSource.get(tronNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == tronDefaultNodeUri);
final wowneroNode = nodeSource.get(wowneroNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == wowneroDefaultNodeUri);
final zanoNode = nodeSource.get(zanoNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == zanoDefaultNodeUri);
final zcashNode = nodeSource.get(zcashNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == zcashDefaultNodeUri);
final dogecoinNode = nodeSource.get(dogecoinNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == dogecoinDefaultNodeUri);
final moneroNode = nodeSource.firstWhereOrNull((e) => e.id == nodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == newCakeWalletMoneroUri);
final bitcoinElectrumServer =
nodeSource.firstWhereOrNull((e) => e.id == bitcoinElectrumServerId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == newCakeWalletBitcoinUri);
final litecoinElectrumServer =
nodeSource.firstWhereOrNull((e) => e.id == litecoinElectrumServerId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == cakeWalletLitecoinElectrumUri);
final ethereumNode =
nodeSource.firstWhereOrNull((e) => e.id == ethereumNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == ethereumDefaultNodeUri);
final polygonNode =
nodeSource.firstWhereOrNull((e) => e.id == polygonNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == polygonDefaultNodeUri);
final baseNode =
nodeSource.firstWhereOrNull((e) => e.id == baseNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == baseDefaultNodeUri);
final arbitrumNode =
nodeSource.firstWhereOrNull((e) => e.id == arbitrumNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == arbitrumDefaultNodeUri);
final bitcoinCashElectrumServer =
nodeSource.firstWhereOrNull((e) => e.id == bitcoinCashElectrumServerId) ??
nodeSource.firstWhereOrNull(
(e) => e.uriRaw == cakeWalletBitcoinCashDefaultNodeUri);
final nanoNode =
nodeSource.firstWhereOrNull((e) => e.id == nanoNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == nanoDefaultNodeUri);
final decredNode =
nodeSource.firstWhereOrNull((e) => e.id == decredNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == decredDefaultUri);
final nanoPowNode =
powNodeSource.firstWhereOrNull((e) => e.id == nanoPowNodeId) ??
powNodeSource.firstWhereOrNull(
(e) => e.uriRaw == nanoDefaultPowNodeUri);
final solanaNode =
nodeSource.firstWhereOrNull((e) => e.id == solanaNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == solanaDefaultNodeUri);
final tronNode =
nodeSource.firstWhereOrNull((e) => e.id == tronNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == tronDefaultNodeUri);
final wowneroNode =
nodeSource.firstWhereOrNull((e) => e.id == wowneroNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == wowneroDefaultNodeUri);
final zanoNode =
nodeSource.firstWhereOrNull((e) => e.id == zanoNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == zanoDefaultNodeUri);
final dogecoinNode =
nodeSource.firstWhereOrNull((e) => e.id == dogecoinNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == dogecoinDefaultNodeUri);
final zcashNode =
nodeSource.firstWhereOrNull((e) => e.id == zcashNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == zcashDefaultNodeUri);
final bscNode =
nodeSource.firstWhereOrNull((e) => e.id == bscNodeId) ??
nodeSource.firstWhereOrNull((e) => e.uriRaw == bscDefaultNodeUri);
final packageInfo = await PackageInfo.fromPlatform();
final deviceName = await _getDeviceName() ?? '';
@@ -1572,7 +1594,7 @@ abstract class SettingsStoreBase with Store {
final mwebAdDismissed =
await sharedPreferences.getBool(PreferencesKey.mwebAdDismissed) ?? false;
final balanceHideCounter = await sharedPreferences.getInt(PreferencesKey.balanceHideCounter) ?? 0;
return SettingsStore(
@@ -2085,20 +2107,21 @@ abstract class SettingsStoreBase with Store {
}
Future<void> _saveCurrentNode(Node node, WalletType walletType) async {
switch (walletType) {
case WalletType.bitcoin:
await _sharedPreferences.setInt(
PreferencesKey.currentBitcoinElectrumSererIdKey, node.key as int);
PreferencesKey.currentBitcoinElectrumSererIdKey, node.id);
break;
case WalletType.litecoin:
await _sharedPreferences.setInt(
PreferencesKey.currentLitecoinElectrumSererIdKey, node.key as int);
PreferencesKey.currentLitecoinElectrumSererIdKey, node.id);
break;
case WalletType.monero:
await _sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, node.id);
break;
case WalletType.haven:
await _sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, node.id);
break;
case WalletType.ethereum:
case WalletType.polygon:
@@ -2107,36 +2130,36 @@ abstract class SettingsStoreBase with Store {
case WalletType.bsc:
final chainId = evm!.getChainIdByWalletType(node.type);
final preferenceKey = _getEVMNodePreferenceKey(chainId);
await _sharedPreferences.setInt(preferenceKey, node.key as int);
await _sharedPreferences.setInt(preferenceKey, node.id);
nodes[node.type] = node;
break;
case WalletType.bitcoinCash:
await _sharedPreferences.setInt(
PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
PreferencesKey.currentBitcoinCashNodeIdKey, node.id);
break;
case WalletType.nano:
await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.id);
break;
case WalletType.solana:
await _sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.id);
break;
case WalletType.tron:
await _sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, node.id);
break;
case WalletType.wownero:
await _sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, node.id);
break;
case WalletType.decred:
await _sharedPreferences.setInt(PreferencesKey.currentDecredNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentDecredNodeIdKey, node.id);
break;
case WalletType.zano:
await _sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.id);
break;
case WalletType.dogecoin:
await _sharedPreferences.setInt(PreferencesKey.currentDogecoinNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentDogecoinNodeIdKey, node.id);
break;
case WalletType.zcash:
await _sharedPreferences.setInt(PreferencesKey.currentZcashNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentZcashNodeIdKey, node.id);
break;
case WalletType.none:
throw UnimplementedError();
@@ -2150,7 +2173,7 @@ abstract class SettingsStoreBase with Store {
Future<void> _saveCurrentPowNode(Node node, WalletType walletType) async {
switch (walletType) {
case WalletType.nano:
await _sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, node.key as int);
await _sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, node.id);
break;
default:
break;
+8 -13
View File
@@ -117,7 +117,7 @@ class ExceptionHandler {
if (await onLedgerError(errorDetails)) return;
if (kDebugMode || kProfileMode) {
if (_ignoreError(errorDetails.exception.toString()) ||
if(_ignoreError(errorDetails.exception.toString()) ||
_ignoreError(errorDetails.stack.toString())) {
printV("(BELOW ERROR IS IGNORED AND WILL NOT TRIGGER POPUP IN PROD)");
}
@@ -127,8 +127,7 @@ class ExceptionHandler {
}
if (_ignoreError(errorDetails.exception.toString()) ||
_ignoreError(errorDetails.stack.toString()) ||
_flutterErrorIgnore(errorDetails)) {
_ignoreError(errorDetails.stack.toString())) {
return;
}
@@ -216,7 +215,8 @@ class ExceptionHandler {
return S.current.ledger_error_tx_rejected_by_user;
} else if (errorCode.contains("5515")) {
return S.current.ledger_error_device_locked;
} else if (["6e01", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
} else
if (["6e01", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
return S.current.ledger_error_wrong_app;
}
return null;
@@ -229,8 +229,9 @@ class ExceptionHandler {
context: navigatorKey.currentContext!,
builder: (context) => AlertWithOneAction(
alertTitle: "Ledger Error",
alertContent: interpretErrorCode(errorDetails.exception.toString()) ??
S.of(context).ledger_connection_error,
alertContent:
interpretErrorCode(errorDetails.exception.toString()) ??
S.of(context).ledger_connection_error,
buttonText: S.of(context).close,
buttonAction: () => Navigator.of(context).pop(),
),
@@ -295,7 +296,7 @@ class ExceptionHandler {
"Wallet is null",
"Wrong Device Status: 0x5515 (UNKNOWN)",
"Command handling failed. With error: hostUnreachable",
"FocusScopeNode was used after being disposed",
"_getDismissibleFlushbar",
"_QueuedFuture.execute (package:universal_ble/src/queue.dart:65)",
@@ -438,10 +439,4 @@ class ExceptionHandler {
_hasError = false;
}
static bool _flutterErrorIgnore(FlutterErrorDetails errorDetails) {
// most probably a flutter context error so just ignore it if there is no stack we can debug with
return errorDetails.exception.toString().contains("Null check operator used on a null value") &&
errorDetails.stack == null;
}
}
@@ -5,10 +5,11 @@ import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/utils/permission_handler.dart';
import 'package:collection/collection.dart';
import 'package:cw_core/node.dart';
import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/cupertino.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:permission_handler/permission_handler.dart';
@@ -19,7 +20,7 @@ class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase
abstract class NodeCreateOrEditViewModelBase with Store {
NodeCreateOrEditViewModelBase(
this._nodeSource, this.walletType, this.editingNode, this._settingsStore)
this.isPow, this.nodeListViewModel,this.powNodeListViewModel, this.walletType, this._settingsStore, {this.editingNode})
: state = InitialExecutionState(),
connectionState = InitialExecutionState(),
label = editingNode?.label ?? '',
@@ -36,8 +37,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
editingNode?.isEnabledForAutoSwitching ?? false,
useSocksProxy = editingNode?.socksProxyAddress != null &&
editingNode!.socksProxyAddress!.isNotEmpty,
useSSL = editingNode?.useSSL ?? false {
}
useSSL = editingNode?.useSSL ?? false {}
final nodeLabelUIKey = 'node_label_row_key';
final nodeAddressUIKey = 'node_address_row_key';
@@ -110,6 +110,15 @@ abstract class NodeCreateOrEditViewModelBase with Store {
@observable
String socksProxyAddress;
@observable
Node? editingNode;
@observable
bool isPow;
final NodeListViewModel? nodeListViewModel;
final PowNodeListViewModel? powNodeListViewModel;
@computed
bool get isReady =>
(address.isNotEmpty) ||
@@ -158,8 +167,6 @@ abstract class NodeCreateOrEditViewModelBase with Store {
}
final WalletType walletType;
final Node? editingNode;
final Box<Node> _nodeSource;
final SettingsStore _settingsStore;
void updateViewModelFromText(String key, String value) {
@@ -248,33 +255,45 @@ abstract class NodeCreateOrEditViewModelBase with Store {
void setSocksProxyAddress(String val) => socksProxyAddress = val;
@action
Future<void> save({Node? editingNode, bool saveAsCurrent = false}) async {
final node = Node(
label: label,
uri: uri,
path: path,
type: walletType,
login: login,
password: password,
useSSL: useSSL,
trusted: trusted,
isEnabledForAutoSwitching: isEnabledForAutoSwitching,
socksProxyAddress: socksProxyAddress);
Future<void> delete({required Node editingNode}) async {
await editingNode.delete();
if(nodeListViewModel != null) {
nodeListViewModel!.bindNodes();
}
if(powNodeListViewModel != null) {
powNodeListViewModel!.bindNodes();
}
}
@action
Future<void> save({bool saveAsCurrent = false}) async {
editingNode ??= Node();
editingNode!.type = walletType;
editingNode!.label = label;
editingNode!.uriRaw = uri;
editingNode!.path = path;
editingNode!.login = login;
editingNode!.password = password;
editingNode!.isPow = isPow;
editingNode!.useSSL = useSSL;
editingNode!.trusted = trusted;
editingNode!.socksProxyAddress = socksProxyAddress;
try {
state = IsExecutingState();
if (editingNode != null) {
await _nodeSource.put(editingNode.key, node);
} else if (_existingNode(node) != null) {
setAsCurrent(_existingNode(node)!);
} else {
await _nodeSource.add(node);
setAsCurrent(_nodeSource.values.last);
}
await editingNode!.save();
if (saveAsCurrent) {
setAsCurrent(node);
setAsCurrent(editingNode!);
}
state = ExecutedSuccessfullyState();
if(nodeListViewModel != null) {
nodeListViewModel!.bindNodes();
}
if(powNodeListViewModel != null) {
powNodeListViewModel!.bindNodes();
}
} catch (e) {
state = FailureState(e.toString());
}
@@ -301,15 +320,6 @@ abstract class NodeCreateOrEditViewModelBase with Store {
}
}
Node? _existingNode(Node node) {
final nodes = _nodeSource.values.toList();
nodes.forEach((item) {
item.login ??= '';
item.password ??= '';
item.useSSL ??= false;
});
return nodes.firstWhereOrNull((item) => item == node);
}
@action
void setAsCurrent(Node node) => _settingsStore.nodes[walletType] = node;
@@ -1,8 +1,7 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/utils/mobx.dart';
import 'package:cw_core/node_list.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cake_wallet/store/settings_store.dart';
@@ -18,13 +17,13 @@ part 'node_list_view_model.g.dart';
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
abstract class NodeListViewModelBase with Store {
NodeListViewModelBase(this._nodeSource, this._appStore)
NodeListViewModelBase(this._appStore)
: nodes = ObservableList<Node>(),
settingsStore = _appStore.settingsStore {
_bindNodes();
bindNodes();
reaction((_) => _appStore.wallet, (WalletBase? _wallet) {
_bindNodes();
bindNodes();
});
reaction((_) {
@@ -35,7 +34,7 @@ abstract class NodeListViewModelBase with Store {
}
return null;
}, (_) {
_bindNodes();
bindNodes();
});
}
@@ -73,24 +72,24 @@ abstract class NodeListViewModelBase with Store {
final ObservableList<Node> nodes;
final SettingsStore settingsStore;
final Box<Node> _nodeSource;
final AppStore _appStore;
Future<void> reset() async {
await resetToDefault(_nodeSource);
await resetToDefault();
final wallet = _appStore.wallet!;
final walletType = wallet.type;
Node node;
if (walletType == WalletType.bitcoin && wallet.isTestnet) {
node = getBitcoinTestnetDefaultElectrumServer(nodes: _nodeSource)!;
node = (await getBitcoinTestnetDefaultElectrumServer())!;
} else if (isEVMCompatibleChain(walletType)) {
final chainId = evm!.getSelectedChainId(wallet);
if (chainId != null) {
final nodeWalletType = evm!.getWalletTypeByChainId(chainId);
if (nodeWalletType != null) {
node = getDefaultNode(nodes: _nodeSource, type: nodeWalletType)!;
node = (await Node.getDefaultForWalletType(nodeWalletType))!;
} else {
throw Exception(
'Cannot reset node for EVM wallet: wallet type not found for chainId: $chainId');
@@ -99,7 +98,7 @@ abstract class NodeListViewModelBase with Store {
throw Exception('Cannot reset node for EVM wallet: chainId is null');
}
} else {
node = getDefaultNode(nodes: _nodeSource, type: walletType)!;
node = (await Node.getDefaultForWalletType(_appStore.wallet!.type))!;
}
await setAsCurrent(node);
@@ -130,7 +129,7 @@ abstract class NodeListViewModelBase with Store {
}
@action
void _bindNodes() {
Future<void> bindNodes() async {
nodes.clear();
final wallet = _appStore.wallet!;
final walletType = wallet.type;
@@ -141,11 +140,8 @@ abstract class NodeListViewModelBase with Store {
if (chainId != null) {
final nodeWalletType = evm!.getWalletTypeByChainId(chainId);
if (nodeWalletType != null) {
_nodeSource.bindToList(
nodes,
filter: (val) => val.type == nodeWalletType,
initialFire: true,
);
nodes.addAll(await Node.getAllForWalletType(nodeWalletType));
return;
}
}
@@ -154,10 +150,7 @@ abstract class NodeListViewModelBase with Store {
}
// For non-EVM wallets, use the wallet type directly
_nodeSource.bindToList(
nodes,
filter: (val) => val.type == walletType,
initialFire: true,
);
nodes.addAll(await Node.getAllForWalletType(walletType));
}
}
@@ -1,6 +1,7 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/utils/mobx.dart';
import 'package:cw_core/node_list.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
@@ -16,13 +17,13 @@ part 'pow_node_list_view_model.g.dart';
class PowNodeListViewModel = PowNodeListViewModelBase with _$PowNodeListViewModel;
abstract class PowNodeListViewModelBase with Store {
PowNodeListViewModelBase(this._nodeSource, this._appStore)
PowNodeListViewModelBase(this._appStore)
: nodes = ObservableList<Node>(),
settingsStore = _appStore.settingsStore {
_bindNodes();
bindNodes();
reaction((_) => _appStore.wallet, (WalletBase? _wallet) {
_bindNodes();
bindNodes();
});
}
@@ -50,17 +51,16 @@ abstract class PowNodeListViewModelBase with Store {
final ObservableList<Node> nodes;
final SettingsStore settingsStore;
final Box<Node> _nodeSource;
final AppStore _appStore;
Future<void> reset() async {
await resetPowToDefault(_nodeSource);
await resetPowToDefault();
Node node;
switch (_appStore.wallet!.type) {
case WalletType.nano:
node = getNanoDefaultPowNode(nodes: _nodeSource)!;
node = (await getNanoDefaultPowNode())!;
break;
default:
throw Exception('Unexpected wallet type: ${_appStore.wallet!.type} for pow node list');
@@ -76,12 +76,8 @@ abstract class PowNodeListViewModelBase with Store {
settingsStore.powNodes[_appStore.wallet!.type] = node;
@action
void _bindNodes() {
Future<void> bindNodes() async {
nodes.clear();
_nodeSource.bindToList(
nodes,
filter: (val) => val.type == _appStore.wallet!.type,
initialFire: true,
);
nodes.addAll(await Node.getAllPow());
}
}
@@ -62,7 +62,7 @@ abstract class RestoreFromBackupViewModelBase with Store {
final store = getIt.get<AppStore>();
ReactionDisposer? reaction;
await store.settingsStore.reload(nodeSource: getIt.get<Box<Node>>());
//await store.settingsStore.reload(nodeSource: getIt.get<Box<Node>>());
await store.themeStore.loadSavedTheme(isFromBackup: true);
reaction = autorun((_) {
final wallet = store.wallet;