diff --git a/assets/arbitrum_node_list.yml b/assets/arbitrum_node_list.yml
index 63894f18a..019a5838d 100644
--- a/assets/arbitrum_node_list.yml
+++ b/assets/arbitrum_node_list.yml
@@ -1,12 +1,15 @@
-
uri: arbitrum.nownodes.io
- is_default: true
useSSL: true
isEnabledForAutoSwitching: true
+ label: "NOWNodes"
-
uri: arbitrum.drpc.org
useSSL: true
+ label: "dRPC"
-
uri: arbitrum-one-rpc.publicnode.com
useSSL: true
- isEnabledForAutoSwitching: true
\ No newline at end of file
+ isDefault: true
+ isEnabledForAutoSwitching: true
+ label: "PublicNode"
\ No newline at end of file
diff --git a/assets/base_node_list.yml b/assets/base_node_list.yml
index 990e972a4..053882639 100644
--- a/assets/base_node_list.yml
+++ b/assets/base_node_list.yml
@@ -1,15 +1,19 @@
-
uri: base.nownodes.io
+ isDefault: true
useSSL: true
isEnabledForAutoSwitching: true
+ label: "NOWNodes"
-
uri: base.llamarpc.com
useSSL: true
+ label: "LlamaNodes"
-
uri: base-rpc.publicnode.com
- is_default: true
useSSL: true
isEnabledForAutoSwitching: true
+ label: "PublicNode"
-
uri: 1rpc.io/base
- useSSL: true
\ No newline at end of file
+ useSSL: true
+ label: "1RPC"
\ No newline at end of file
diff --git a/assets/bitcoin_cash_electrum_server_list.yml b/assets/bitcoin_cash_electrum_server_list.yml
index 770bdbc05..b8c4e17df 100644
--- a/assets/bitcoin_cash_electrum_server_list.yml
+++ b/assets/bitcoin_cash_electrum_server_list.yml
@@ -1,12 +1,11 @@
-
uri: bitcoincash.stackwallet.com:50002
- is_default: true
+ isDefault: true
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Stack Wallet"
-
uri: bch.aftrek.org:50002
useSSL: true
isEnabledForAutoSwitching: true
--
- uri: node.minisatoshi.cash:50002
- useSSL: true
+ label: "Aftrek"
diff --git a/assets/bitcoin_electrum_server_list.yml b/assets/bitcoin_electrum_server_list.yml
index c3a92e948..4346d1d31 100644
--- a/assets/bitcoin_electrum_server_list.yml
+++ b/assets/bitcoin_electrum_server_list.yml
@@ -2,14 +2,21 @@
uri: btc-electrum.cakewallet.com:50002
useSSL: true
isDefault: true
+ isOfficial: true
isEnabledForAutoSwitching: true
+ label: "Cake Wallet Electrum"
-
uri: electrs.cakewallet.com:50001
+ isOfficial: true
+ label: "Cake Wallet Electrs"
-
uri: fulcrum.sethforprivacy.com:50002
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Seth For Privacy"
-
uri: electrum.cakewallet.com:50002
+ isOfficial: true
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Cake Wallet (Legacy)"
diff --git a/assets/bsc_node_list.yml b/assets/bsc_node_list.yml
index 20e0cdcca..4403b6b01 100644
--- a/assets/bsc_node_list.yml
+++ b/assets/bsc_node_list.yml
@@ -3,26 +3,33 @@
useSSL: true
isDefault: true
isEnabledForAutoSwitching: true
+ label: "BNBChain"
-
uri: bsc-dataseed2.bnbchain.org
useSSL: true
isEnabledForAutoSwitching: true
+ label: "BNBChain #2"
-
uri: bsc-dataseed.nariox.org
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Nariox"
-
uri: bsc-dataseed.defibit.io
useSSL: true
isEnabledForAutoSwitching: true
+ label: "DeFibit"
-
uri: bsc-dataseed.ninicoin.io
useSSL: true
isEnabledForAutoSwitching: true
+ label: "NiniCoin"
-
uri: bsc.nodereal.io
useSSL: true
isEnabledForAutoSwitching: true
+ label: "NodeReal"
-
uri: bsc-dataseed-public.bnbchain.org
useSSL: true
+ label: "BNBChain Public"
\ No newline at end of file
diff --git a/assets/decred_node_list.yml b/assets/decred_node_list.yml
index 9f5938e8c..7121867e0 100644
--- a/assets/decred_node_list.yml
+++ b/assets/decred_node_list.yml
@@ -1,8 +1,10 @@
-
uri: default-spv-nodes
- is_default: true
+ isDefault: true
isEnabledForAutoSwitching: true
+ label: "Decred"
-
uri: dcrd.sethforprivacy.com:9108
useSSL: true
- isEnabledForAutoSwitching: true
\ No newline at end of file
+ isEnabledForAutoSwitching: true
+ label: "Seth For Privacy"
\ No newline at end of file
diff --git a/assets/dogecoin_electrum_server_list.yml b/assets/dogecoin_electrum_server_list.yml
index 087b0af2b..010535be3 100644
--- a/assets/dogecoin_electrum_server_list.yml
+++ b/assets/dogecoin_electrum_server_list.yml
@@ -1,12 +1,15 @@
-
uri: dogecoin.stackwallet.com:50022
- is_default: true
+ isDefault: true
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Stack Wallet"
-
uri: doge.aftrek.org:50002
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Aftrek"
-
uri: electrum1.cipig.net:20060
- useSSL: true
\ No newline at end of file
+ useSSL: true
+ label: "Cipig"
\ No newline at end of file
diff --git a/assets/ethereum_server_list.yml b/assets/ethereum_server_list.yml
index 0ba098fc5..08c2f4ae5 100644
--- a/assets/ethereum_server_list.yml
+++ b/assets/ethereum_server_list.yml
@@ -3,18 +3,21 @@
useSSL: true
isDefault: true
isEnabledForAutoSwitching: true
+ label: "PublicNode"
-
uri: eth.llamarpc.com
useSSL: true
+ label: "LlamaNodes"
-
uri: rpc.flashbots.net
useSSL: true
+ label: "Flashbots"
-
uri: eth-mainnet.public.blastapi.io
useSSL: true
+ label: "Blast"
-
uri: eth.nownodes.io
useSSL: true
isEnabledForAutoSwitching: true
--
- uri: ethereum.publicnode.com
\ No newline at end of file
+ label: "NOWNodes"
\ No newline at end of file
diff --git a/assets/haven_node_list.yml b/assets/haven_node_list.yml
index 27d9ee611..2dfa644b7 100644
--- a/assets/haven_node_list.yml
+++ b/assets/haven_node_list.yml
@@ -1,4 +1,4 @@
-
uri: nodes.havenprotocol.org:443
useSSL: true
- is_default: true
\ No newline at end of file
+ isDefault: true
\ No newline at end of file
diff --git a/assets/lightning_deposit_help.svg b/assets/lightning_deposit_help.svg
deleted file mode 100644
index 5cecc0bab..000000000
--- a/assets/lightning_deposit_help.svg
+++ /dev/null
@@ -1,99 +0,0 @@
-
diff --git a/assets/litecoin_electrum_server_list.yml b/assets/litecoin_electrum_server_list.yml
index 18b982aa1..b2c559910 100644
--- a/assets/litecoin_electrum_server_list.yml
+++ b/assets/litecoin_electrum_server_list.yml
@@ -2,20 +2,27 @@
uri: ltc-electrum.cakewallet.com:50002
useSSL: true
isDefault: true
+ isOfficial: true
isEnabledForAutoSwitching: true
+ label: "Cake Wallet"
-
uri: litecoin.stackwallet.com:20063
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Stack Wallet"
-
uri: electrum-ltc.bysh.me:50002
useSSL: true
+ label: "Bysh"
-
uri: lightweight.fiatfaucet.com:50002
useSSL: true
+ label: "Fiat Faucet"
-
uri: electrum.ltc.xurious.com:50002
useSSL: true
+ label: "Xurious"
-
uri: backup.electrum-ltc.org:443
useSSL: true
+ label: "Electrum-LTC"
diff --git a/assets/nano_node_list.yml b/assets/nano_node_list.yml
index aa1d8e3c9..1f153a290 100644
--- a/assets/nano_node_list.yml
+++ b/assets/nano_node_list.yml
@@ -1,34 +1,37 @@
+-
+ uri: rpc.nano.to
+ isDefault: true
+ useSSL: true
+ isEnabledForAutoSwitching: true
+ label: "Nano.to"
-
uri: nano.nownodes.io
useSSL: true
isEnabledForAutoSwitching: true
--
- uri: rpc.nano.to
- is_default: true
- useSSL: true
- isEnabledForAutoSwitching: true
+ label: "NOWNodes"
-
uri: node.nautilus.io
path: /api
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Nautilus"
-
uri: app.natrium.io
path: /api
useSSL: true
+ label: "Natrium"
-
uri: rainstorm.city
path: /api
useSSL: true
+ label: "Rainstorm City"
-
uri: node.somenano.com
path: /proxy
useSSL: true
+ label: "SomeNano"
-
uri: nanoslo.0x.no
path: /proxy
useSSL: true
--
- uri: www.bitrequest.app
- port: 8020
- useSSL: true
\ No newline at end of file
+ label: "0x.no"
\ No newline at end of file
diff --git a/assets/node_list.yml b/assets/node_list.yml
index 568bffb2c..a1568319a 100644
--- a/assets/node_list.yml
+++ b/assets/node_list.yml
@@ -1,34 +1,36 @@
-
+ label: "Cake Wallet"
uri: xmr-node.cakewallet.com:18081
- is_default: true
+ isDefault: true
+ isOfficial: true
trusted: true
useSSL: true
isEnabledForAutoSwitching: true
-
+ label: "Cake Wallet (Onion)"
uri: cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081
- is_default: false
-
+ label: "Seth For Privacy"
uri: node.sethforprivacy.com:443
useSSL: true
- is_default: false
isEnabledForAutoSwitching: true
-
+ label: "MoneroDevs"
uri: node.monerodevs.org:18089
useSSL: true
- is_default: false
-
+ label: "MoneroDevs #2"
uri: node2.monerodevs.org:18089
useSSL: true
- is_default: false
-
+ label: "MoneroDevs #3"
uri: node3.monerodevs.org:18089
useSSL: true
- is_default: false
-
+ label: "Feather Wallet"
uri: selsta1.featherwallet.net:18081
useSSL: true
- is_default: false
-
+ label: "StormyCloud"
uri: xmr.stormycloud.org:18089
useSSL: true
- is_default: false
diff --git a/assets/polygon_node_list.yml b/assets/polygon_node_list.yml
index 822a8b4f6..9760dd7a3 100644
--- a/assets/polygon_node_list.yml
+++ b/assets/polygon_node_list.yml
@@ -1,14 +1,14 @@
--
- uri: polygon-rpc.com
-
uri: polygon-bor-rpc.publicnode.com
useSSL: true
isDefault: true
isEnabledForAutoSwitching: true
+ label: "polygon-bor-rpc.publicnode.com"
-
- uri: polygon.llamarpc.com
- useSSL: true
+ uri: polygon-rpc.com
+ label: "Ankr"
-
uri: matic.nownodes.io
useSSL: true
- isEnabledForAutoSwitching: true
\ No newline at end of file
+ isEnabledForAutoSwitching: true
+ label: "NOWNodes"
\ No newline at end of file
diff --git a/assets/solana_node_list.yml b/assets/solana_node_list.yml
index e1d7971c6..e2ad7a272 100644
--- a/assets/solana_node_list.yml
+++ b/assets/solana_node_list.yml
@@ -1,16 +1,20 @@
+-
+ uri: solana-mainnet.core.chainstack.com
+ useSSL: true
+ isDefault: true
+ isEnabledForAutoSwitching: true
+ label: "Chainstack"
-
uri: rpc.ankr.com
useSSL: true
+ label: "Ankr"
-
uri: api.mainnet-beta.solana.com:443
useSSL: true
isEnabledForAutoSwitching: true
+ label: "Solana Beta"
-
uri: solana-rpc.publicnode.com:443
useSSL: true
isEnabledForAutoSwitching: true
--
- uri: solana-mainnet.core.chainstack.com
- useSSL: true
- is_default: true
- isEnabledForAutoSwitching: true
\ No newline at end of file
+ label: "PublicNode"
\ No newline at end of file
diff --git a/assets/tron_node_list.yml b/assets/tron_node_list.yml
index 595bba971..3837ec4ee 100644
--- a/assets/tron_node_list.yml
+++ b/assets/tron_node_list.yml
@@ -1,13 +1,15 @@
--
- uri: tron-rpc.publicnode.com:443
- is_default: false
- useSSL: true
-
uri: api.trongrid.io
- is_default: true
+ isDefault: true
useSSL: true
isEnabledForAutoSwitching: true
+ label: "TronGrid"
+-
+ uri: tron-rpc.publicnode.com:443
+ useSSL: true
+ label: "PublicNode"
-
uri: trx.nownodes.io
useSSL: true
- isEnabledForAutoSwitching: true
\ No newline at end of file
+ isEnabledForAutoSwitching: true
+ label: "NOWNodes"
\ No newline at end of file
diff --git a/assets/wownero_node_list.yml b/assets/wownero_node_list.yml
index 893f82984..5356fa5d5 100644
--- a/assets/wownero_node_list.yml
+++ b/assets/wownero_node_list.yml
@@ -1,14 +1,12 @@
-
uri: node3.monerodevs.org:34568
- is_default: true
+ isDefault: true
useSSL: false
isEnabledForAutoSwitching: true
-
uri: node2.monerodevs.org:34568
- is_default: false
useSSL: false
isEnabledForAutoSwitching: true
-
uri: node.monerodevs.org:34568
- is_default: false
useSSL: false
diff --git a/assets/zano_node_list.yml b/assets/zano_node_list.yml
index 17bba5f44..93923e6bd 100644
--- a/assets/zano_node_list.yml
+++ b/assets/zano_node_list.yml
@@ -1,9 +1,12 @@
-
uri: 37.27.100.59:10500
- is_default: true
+ isDefault: true
useSSL: false
isEnabledForAutoSwitching: true
+ label: "Zano"
-
uri: zano.cakewallet.com:11211
useSSL: false
- isEnabledForAutoSwitching: true
\ No newline at end of file
+ isOfficial: true
+ isEnabledForAutoSwitching: true
+ label: "Cake Wallet"
diff --git a/assets/zcash_node_list.yml b/assets/zcash_node_list.yml
index 88db5c54c..afdd49599 100644
--- a/assets/zcash_node_list.yml
+++ b/assets/zcash_node_list.yml
@@ -1,12 +1,20 @@
-- uri: zec.rocks:443
- is_default: false
+-
+ uri: zec-node.cakewallet.com:443
+ isDefault: true
+ isOfficial: true
useSSL: true
isEnabledForAutoSwitching: true
-- uri: zec-node.cakewallet.com:443
- is_default: true
+ label: "Cake Wallet"
+-
+ uri: zec.rocks:443
useSSL: true
isEnabledForAutoSwitching: true
-- uri: 2c4whzg26j6hgjh22rxynj3oig4gm22ga7x74weclujywxye23v3u5id.onion:9067
+ label: "Zec.rocks"
+-
+ uri: 2c4whzg26j6hgjh22rxynj3oig4gm22ga7x74weclujywxye23v3u5id.onion:9067
useSSL: false
-- uri: bvp2l442g5ogma7rywzahm7eqyhpp3g26n3gvvxeioqn5csio2ir6myd.onion:9067
+ label: "Cake Wallet (Tor)"
+-
+ uri: bvp2l442g5ogma7rywzahm7eqyhpp3g26n3gvvxeioqn5csio2ir6myd.onion:9067
useSSL: false
+ label: "Cake Wallet (Tor #2)"
\ No newline at end of file
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 243a88b26..ec5492116 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -790,9 +790,10 @@ abstract class ElectrumWalletBase
if (server.toLowerCase().contains('electrs')) {
node!.isElectrs = true;
- if (node!.isInBox) {
+ // TODO figure out why condition was needed
+ // if (node!.isInBox) {
node!.save();
- }
+ // }
return node!.isElectrs!;
}
}
diff --git a/cw_core/lib/db/sqlite.dart b/cw_core/lib/db/sqlite.dart
index 593b1b14f..eea479a80 100644
--- a/cw_core/lib/db/sqlite.dart
+++ b/cw_core/lib/db/sqlite.dart
@@ -41,7 +41,7 @@ Future initDb({String? pathOverride}) async {
}
}
await db?.close();
- db = await openDatabase(dbFile.path, version: 7,
+ db = await openDatabase(dbFile.path, version: 8,
onUpgrade: (Database db, int oldVersion, int newVersion) async {
printV("migrating: $oldVersion, $newVersion");
if (oldVersion <= 1) {
@@ -104,6 +104,9 @@ CREATE TABLE IF NOT EXISTS BalanceCardStyleSettings (
definition: 'TEXT',
);
}
+ if(oldVersion <= 7) {
+ await _createNodeTable(db);
+ }
},
onCreate: (Database db, int version) async {
await db.execute(
@@ -202,6 +205,7 @@ CREATE TABLE BalanceCardStyleSettings (
);
''');
await _createBridgeTransferTable(db);
+ await _createNodeTable(db);
await _createTradeTable(db);
}
);
@@ -330,4 +334,26 @@ CREATE TABLE IF NOT EXISTS BridgeTransfer (
CREATE INDEX IF NOT EXISTS idx_bridgetransfer_wallet_id
ON BridgeTransfer(wallet_id);
''');
+}
+
+Future _createNodeTable(Database db) async {
+ db.execute("""
+CREATE TABLE Node (
+NodeId INTEGER PRIMARY KEY,
+uri TEXT NOT NULL,
+path TEXT,
+login TEXT,
+label TEXT,
+password TEXT,
+isPow INTEGER NOT NULL,
+useSSL INTEGER,
+typeRaw INTEGER NOT NULL,
+trusted INTEGER NOT NULL,
+socksProxyAddress TEXT,
+isEnabledForAutoSwitching BOOLEAN DEFAULT FALSE,
+isOfficial BOOLEAN DEFAULT FALSE,
+isBuiltin BOOLEAN DEFAULT FALSE,
+isDefault BOOLEAN DEFAULT FALSE
+);
+ """);
}
\ No newline at end of file
diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart
index 6ed3964a2..b3478ed4a 100644
--- a/cw_core/lib/node.dart
+++ b/cw_core/lib/node.dart
@@ -1,33 +1,62 @@
+import 'dart:convert';
import 'dart:io';
-import 'package:cw_core/keyable.dart';
+import 'dart:math' as math;
+
+import 'package:blockchain_utils/hex/hex.dart';
+import 'package:cw_core/node_list.dart';
+import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/utils/proxy_socket/abstract.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
-import 'package:cw_core/utils/print_verbose.dart';
-import 'dart:convert';
-import 'package:hive/hive.dart';
-import 'package:cw_core/hive_type_ids.dart';
import 'package:cw_core/wallet_type.dart';
-import 'dart:math' as math;
-import 'package:convert/convert.dart';
-
import 'package:crypto/crypto.dart';
+import 'package:sqflite/sqflite.dart';
-part 'node.g.dart';
+import 'db/sqlite.dart';
Uri createUriFromElectrumAddress(String address, String path) =>
Uri.tryParse('tcp://$address$path')!;
-@HiveType(typeId: Node.typeId)
-class Node extends HiveObject with Keyable {
+Future validateBuiltinNodes() async {
+ // ensures nodes stored as builtin in the db correspond to the nodes in the .yml files
+
+ final builtinFromDb = await Node.getAllBuiltin();
+ final builtinFromList = await loadAllDefaultNodes();
+
+ for (final listNode in builtinFromList) {
+ // preserve proxy settings from user
+ try {
+ final matchedDbNode = builtinFromDb.firstWhere(
+ (dbNode) => dbNode.uri == listNode.uri
+ );
+ listNode.socksProxyAddress = matchedDbNode.socksProxyAddress;
+ } catch(e) {}
+ }
+
+ final dbSet = builtinFromDb.toSet();
+ final listSet = builtinFromList.toSet();
+
+ final nodesToDelete = dbSet.difference(listSet);
+ final nodesToAdd = listSet.difference(dbSet);
+
+ for (final node in nodesToDelete) await node.delete();
+ for (final node in nodesToAdd) await node.save();
+}
+
+class Node {
Node({
+ this.id = 0,
this.label,
this.login,
this.password,
this.useSSL,
+ this.isPow = false,
this.trusted = false,
this.socksProxyAddress,
this.path = '',
this.isEnabledForAutoSwitching = false,
+ this.isOfficial = false,
+ this.isBuiltin = false,
+ this.isDefault = false,
String? uri,
WalletType? type,
}) {
@@ -50,62 +79,144 @@ class Node extends HiveObject with Keyable {
trusted: $trusted,
socksProxyAddress: $socksProxyAddress,
isEnabledForAutoSwitching: $isEnabledForAutoSwitching,
+ isOfficial: $isOfficial,
+ isBuiltin: $isBuiltin,
+ isDefault: $isDefault
})""";
}
Node.fromMap(Map map)
- : uriRaw = map['uri'] as String? ?? '',
+ : id = (map[selfIdColumn] ?? 0) as int,
+ uriRaw = map['uri'] as String? ?? '',
path = map['path'] as String? ?? '',
login = map['login'] as String?,
label = map['label'] as String?,
password = map['password'] as String?,
- useSSL = map['useSSL'] as bool?,
- trusted = map['trusted'] as bool? ?? false,
- socksProxyAddress = map['socksProxyPort'] as String?,
- isEnabledForAutoSwitching = map['isEnabledForAutoSwitching'] as bool? ?? false;
+ isPow = (map["isPow"] != null && map['isPow'] != 0) as bool? ?? false,
+ useSSL = (map['useSSL'] != 0) as bool?,
+ typeRaw = (map["typeRaw"] ?? 0) as int,
+ trusted = (map['trusted'] != 0) as bool? ?? false,
+ socksProxyAddress = map['socksProxyAddress'] as String?,
+ isEnabledForAutoSwitching = (map['isEnabledForAutoSwitching'] != 0) as bool? ?? false,
+ isOfficial = (map['isOfficial'] != 0) as bool? ?? false,
+ isBuiltin = (map['isBuiltin'] != 0) as bool? ?? false,
+ isDefault = (map['isDefault'] != 0) as bool? ?? false;
- static const typeId = NODE_TYPE_ID;
- static const boxName = 'Nodes';
+ Map toMap() {
+ return {
+ selfIdColumn: id,
+ 'uri': uriRaw,
+ 'path': path,
+ 'login': login,
+ "label": label,
+ 'password': password,
+ "isPow": isPow,
+ 'useSSL': useSSL,
+ "typeRaw": typeRaw,
+ 'trusted': trusted,
+ 'socksProxyAddress': socksProxyAddress,
+ 'isEnabledForAutoSwitching': isEnabledForAutoSwitching,
+ "isOfficial": isOfficial,
+ "isBuiltin": isBuiltin,
+ "isDefault": isDefault
+ };
+ }
- @HiveField(0, defaultValue: '')
+ Future delete() async {
+ return await db!.delete(tableName, where: '${selfIdColumn} = ?', whereArgs: [id]);
+ }
+
+ static Future deleteAll() async {
+ return await db!.delete(tableName, where: "isPow = ?", whereArgs: [false]);
+ }
+
+ static Future deleteAllPow() async {
+ return await db!.delete(tableName, where: "isPow = ?", whereArgs: [true]);
+ }
+
+ Future save() async {
+
+ final json = toMap();
+ if (json[selfIdColumn] == 0) {
+ json[selfIdColumn] = null;
+ }
+ id = await db!.insert(tableName, json, conflictAlgorithm: ConflictAlgorithm.replace);
+ return id;
+ }
+
+
+ static Future> selectList(String where, List whereArgs, {String? orderBy}) async {
+ if(orderBy == null) {
+ orderBy = selfIdColumn;
+ }
+ final list = await db!.query(
+ tableName,
+ where: where.isNotEmpty ? where : "1 = 1",
+ whereArgs: whereArgs.isNotEmpty ? whereArgs : null,
+ orderBy: orderBy,
+ );
+ printV("selectList: $list");
+ return List.generate(list.length, (index) => Node.fromMap(list[index]));
+ }
+
+
+ static Future> getAll() async {
+ return selectList("isPow = ?", [false]);
+ }
+
+ static Future> getAllBuiltin() async {
+ return selectList("isPow = ? AND isBuiltin = ?", [false, true]);
+ }
+
+ static Future> getAllPowBuiltin() async {
+ return selectList("isPow = ? AND isBuiltin = ?", [true, true]);
+ }
+
+ static Future> getAllForWalletType(WalletType type) async {
+ return selectList("typeRaw = ? AND isPow = ?", [serializeToInt(type), false]);
+ }
+
+ static Future getDefaultForWalletType(WalletType type) async {
+ return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), false, true])).firstOrNull;
+ }
+
+ static Future getDefaultPowForWalletType(WalletType type) async {
+ return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), true, true])).firstOrNull;
+ }
+
+ static Future> getAllForWalletTypePow(WalletType type) async {
+ return selectList("typeRaw = ? AND isPow = ?", [serializeToInt(type), true]);
+ }
+
+ static Future> getAllPow() async {
+ return selectList("isPow = ?", [true]);
+ }
+
+
+ int id;
late String uriRaw;
-
- @HiveField(1)
String? login;
-
- @HiveField(2)
String? password;
-
- @HiveField(3, defaultValue: 0)
late int typeRaw;
-
- @HiveField(4)
bool? useSSL;
-
- @HiveField(5, defaultValue: false)
bool trusted;
-
- @HiveField(6)
+ bool isPow;
String? socksProxyAddress;
-
- @HiveField(7, defaultValue: '')
String? path;
-
- @HiveField(8)
bool? isElectrs;
-
- @HiveField(9)
bool? supportsSilentPayments;
-
- @HiveField(10)
bool? supportsMweb;
-
- @HiveField(11, defaultValue: false)
bool isEnabledForAutoSwitching;
+ bool isOfficial;
+ bool isBuiltin;
+ bool isDefault;
- @HiveField(12, defaultValue: '')
String? label;
+ static String get tableName => "Node";
+ static String get selfIdColumn => "${tableName}Id";
+
+
bool get isSSL => useSSL ?? false;
bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
@@ -167,18 +278,11 @@ class Node extends HiveObject with Keyable {
socksProxyAddress.hashCode ^
path.hashCode;
- @override
- dynamic get keyIndex {
- _keyIndex ??= key;
- return _keyIndex;
- }
WalletType get type => deserializeFromInt(typeRaw);
set type(WalletType type) => typeRaw = serializeToInt(type);
- dynamic _keyIndex;
-
Future requestNode() async {
try {
switch (type) {
@@ -228,7 +332,7 @@ class Node extends HiveObject with Keyable {
body: jsonBody,
);
-
+
final resBody = json.decode(response.body) as Map;
return resBody['result']['height'] != null;
diff --git a/cw_core/lib/node_legacy.dart b/cw_core/lib/node_legacy.dart
new file mode 100644
index 000000000..3c39b6f90
--- /dev/null
+++ b/cw_core/lib/node_legacy.dart
@@ -0,0 +1,237 @@
+import 'dart:io';
+import 'package:cw_core/keyable.dart';
+import 'package:cw_core/node_list.dart';
+import 'package:cw_core/utils/proxy_socket/abstract.dart';
+import 'package:cw_core/utils/proxy_wrapper.dart';
+import 'package:cw_core/utils/print_verbose.dart';
+import 'dart:convert';
+import 'package:hive/hive.dart';
+import 'package:cw_core/hive_type_ids.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'dart:math' as math;
+import 'package:convert/convert.dart';
+
+import 'package:crypto/crypto.dart';
+
+import 'cake_hive.dart';
+import 'node.dart' as node_new;
+
+part "node_legacy.g.dart";
+
+Future performNodeHiveMigration() async {
+ if(!CakeHive.isAdapterRegistered(Node.typeId)) {
+ CakeHive.registerAdapter(NodeAdapter());
+ }
+
+ final nodeBox = await CakeHive.openBox(Node.boxName);
+ final powNodeBox = await CakeHive.openBox(Node.boxName+"pow");
+ final builtinNodes = await loadAllDefaultNodes();
+ final builtinPowNodes = await loadDefaultNanoPowNodes();
+ await Node.migrateAllToSqlite(nodeBox, powNodeBox, builtinNodes, builtinPowNodes);
+
+
+}
+
+Uri createUriFromElectrumAddress(String address, String path) =>
+ Uri.tryParse('tcp://$address$path')!;
+
+@HiveType(typeId: Node.typeId)
+class Node extends HiveObject with Keyable {
+ Node({
+ this.label,
+ this.login,
+ this.password,
+ this.useSSL,
+ this.trusted = false,
+ this.socksProxyAddress,
+ this.path = '',
+ this.isEnabledForAutoSwitching = false,
+ String? uri,
+ WalletType? type,
+ }) {
+ if (uri != null) {
+ uriRaw = uri;
+ }
+ if (type != null) {
+ this.type = type;
+ }
+ }
+
+ static Future migrateAllToSqlite(Box nodeBox, Box powNodeBox,
+ List defaultNodes, List defaultPowNodes) async {
+ final list = nodeBox.values.toList();
+ final powList = powNodeBox.values.toList();
+ for (final node in list) {
+ if(defaultNodes.any((item)=>item.uri == node.uri)) {
+ // default nodes will be added by validateBuiltinNodes(), no need to migrate them.
+ await node.delete();
+ continue;
+ }
+ await node.migrateToSqlite(
+ isPow: false,
+ isBuiltin: false,
+ isOfficial: false);
+ await node.delete();
+ }
+ for (final node in powList) {
+ if(defaultPowNodes.any((item)=>item.uri == node.uri)) {
+ await node.delete();
+ continue;
+ }
+ await node.migrateToSqlite(
+ isPow: true,
+ isBuiltin: false,
+ isOfficial: false);
+ await node.delete();
+ }
+ }
+
+ Future migrateToSqlite({required bool isPow, required bool isBuiltin, required bool isOfficial}) async {
+ final newNode = node_new.Node(
+ id: key as int,
+ login: login,
+ label: label,
+ password: password,
+ type: type,
+ useSSL: useSSL,
+ trusted: trusted,
+ socksProxyAddress: socksProxyAddress,
+ isPow: isPow,
+ path: path,
+ uri: uriRaw,
+ isEnabledForAutoSwitching: isEnabledForAutoSwitching,
+ isOfficial: isOfficial,
+ isBuiltin: isBuiltin,
+ );
+ await newNode.save();
+ }
+
+
+ Node.fromMap(Map map)
+ : uriRaw = map['uri'] as String? ?? '',
+ path = map['path'] as String? ?? '',
+ login = map['login'] as String?,
+ label = map['label'] as String?,
+ password = map['password'] as String?,
+ useSSL = map['useSSL'] as bool?,
+ trusted = map['trusted'] as bool? ?? false,
+ socksProxyAddress = map['socksProxyPort'] as String?,
+ isEnabledForAutoSwitching = map['isEnabledForAutoSwitching'] as bool? ?? false;
+
+ static const typeId = NODE_TYPE_ID;
+ static const boxName = 'Nodes';
+
+ @HiveField(0, defaultValue: '')
+ late String uriRaw;
+
+ @HiveField(1)
+ String? login;
+
+ @HiveField(2)
+ String? password;
+
+ @HiveField(3, defaultValue: 0)
+ late int typeRaw;
+
+ @HiveField(4)
+ bool? useSSL;
+
+ @HiveField(5, defaultValue: false)
+ bool trusted;
+
+ @HiveField(6)
+ String? socksProxyAddress;
+
+ @HiveField(7, defaultValue: '')
+ String? path;
+
+ @HiveField(8)
+ bool? isElectrs;
+
+ @HiveField(9)
+ bool? supportsSilentPayments;
+
+ @HiveField(10)
+ bool? supportsMweb;
+
+ @HiveField(11, defaultValue: false)
+ bool isEnabledForAutoSwitching;
+
+ @HiveField(12, defaultValue: '')
+ String? label;
+
+ bool get isSSL => useSSL ?? false;
+
+ bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
+
+ Uri get uri {
+ switch (type) {
+ case WalletType.monero:
+ case WalletType.zcash:
+ case WalletType.haven:
+ case WalletType.wownero:
+ return Uri.http(uriRaw, '');
+ case WalletType.bitcoin:
+ case WalletType.litecoin:
+ case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
+ return createUriFromElectrumAddress(uriRaw, path!);
+ case WalletType.nano:
+ case WalletType.banano:
+ case WalletType.ethereum:
+ case WalletType.polygon:
+ case WalletType.base:
+ case WalletType.bsc:
+ case WalletType.arbitrum:
+ case WalletType.solana:
+ case WalletType.tron:
+ case WalletType.zano:
+ case WalletType.decred:
+ return Uri.parse(
+ "http${isSSL ? "s" : ""}://$uriRaw${path!.startsWith("/") || path!.isEmpty ? path : "/$path"}");
+ case WalletType.none:
+ throw Exception('Unexpected type ${type.toString()} for Node uri');
+ }
+ }
+
+ bool get isValidProxyAddress => socksProxyAddress?.contains(':') ?? false;
+
+ @override
+ bool operator ==(other) =>
+ other is Node &&
+ (other.uriRaw == uriRaw &&
+ other.login == login &&
+ other.label == label &&
+ other.password == password &&
+ other.typeRaw == typeRaw &&
+ other.useSSL == useSSL &&
+ other.trusted == trusted &&
+ other.socksProxyAddress == socksProxyAddress &&
+ other.path == path);
+
+ @override
+ int get hashCode =>
+ uriRaw.hashCode ^
+ login.hashCode ^
+ label.hashCode ^
+ password.hashCode ^
+ typeRaw.hashCode ^
+ useSSL.hashCode ^
+ trusted.hashCode ^
+ socksProxyAddress.hashCode ^
+ path.hashCode;
+
+ @override
+ dynamic get keyIndex {
+ _keyIndex ??= key;
+ return _keyIndex;
+ }
+
+ WalletType get type => deserializeFromInt(typeRaw);
+
+ set type(WalletType type) => typeRaw = serializeToInt(type);
+
+ dynamic _keyIndex;
+
+
+}
\ No newline at end of file
diff --git a/cw_core/lib/node_list.dart b/cw_core/lib/node_list.dart
new file mode 100644
index 000000000..e46f0eee4
--- /dev/null
+++ b/cw_core/lib/node_list.dart
@@ -0,0 +1,188 @@
+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> 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 = [];
+
+ for (final raw in loadedNodes) {
+ if (raw is Map) {
+ final map = Map.from(raw);
+ map["isBuiltin"] = 1;
+ map["isOfficial"] = ((map["isOfficial"] as bool? ?? false) ? 1 : 0);
+ map["isDefault"] = ((map["isDefault"] as bool? ?? false) ? 1 : 0);
+ final node = Node.fromMap(Map.from(map));
+ node.type = type;
+ nodes.add(node);
+ }
+ }
+
+ return nodes;
+}
+
+Future> loadDefaultNanoPowNodes() async {
+ final powNodesRaw = await rootBundle.loadString('assets/nano_pow_node_list.yml');
+ final loadedPowNodes = loadYaml(powNodesRaw) as YamlList;
+ final nodes = [];
+
+ for (final raw in loadedPowNodes) {
+ if (raw is Map) {
+ final node = Node.fromMap(Map.from(raw));
+ node.isPow = true;
+ node.type = WalletType.nano;
+ nodes.add(node);
+ }
+ }
+
+ return nodes;
+}
+
+Future> loadAllDefaultNodes() 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);
+
+ return moneroNodes +
+ bitcoinElectrumServerList +
+ litecoinElectrumServerList +
+ havenNodes +
+ ethereumNodes +
+ bitcoinCashElectrumServerList +
+ nanoNodes +
+ polygonNodes +
+ solanaNodes +
+ tronNodes +
+ zanoNodes +
+ decredNodes +
+ dogecoinElectrumServerList +
+ baseNodes +
+ arbitrumNodes +
+ zcashNodes +
+ bscNodes;
+}
+
+Future resetToDefault() async {
+
+ final nodes = await loadAllDefaultNodes();
+
+ final currentNodes = await Node.getAll();
+
+ // after reset, nodes should retain the id to correspond with the ones in shared prefs.
+ // alternative would be nuking the shared prefs on reset
+ for (final node in nodes) {
+ try {
+ final curr = currentNodes.firstWhere(
+ (item) => item.uri == node.uri && item.typeRaw == node.typeRaw,
+ );
+ node.id = curr.id;
+ } catch(e) {}
+
+ }
+
+ await Node.deleteAll();
+ for(final node in nodes) {
+ await node.save();
+ }
+}
+
+Future resetPowToDefault() async {
+ final nanoPowNodes = await loadDefaultNanoPowNodes();
+ await Node.deleteAllPow();
+ for(final node in nanoPowNodes) {
+ node.save();
+ }
+}
+
+Future getDefaultNodeFromFiles(WalletType type, {bool isPow = false}) async {
+ final nodes = isPow ? await loadDefaultNanoPowNodes() : await loadDefaultNodes(type);
+ try {
+ return nodes.firstWhere((item)=>item.isDefault);
+ } catch(e) {
+ // ideally the yamls would always have a default, but this is better than nothing
+ return nodes.first;
+ }
+}
+
+
+
diff --git a/lib/core/node_switching_service.dart b/lib/core/node_switching_service.dart
index c17ec2e47..d7908eebe 100644
--- a/lib/core/node_switching_service.dart
+++ b/lib/core/node_switching_service.dart
@@ -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 nodeSource;
final Map> _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(
diff --git a/lib/di.dart b/lib/di.dart
index 50a7cefcf..aa42887d7 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -326,8 +326,8 @@ import 'src/screens/buy/buy_sell_page.dart';
final getIt = GetIt.instance;
var _isSetupFinished = false;
-late Box _nodeSource;
-late Box _powNodeSource;
+// late Box _nodeSource;
+// late Box _powNodeSource;
late Box _contactSource;
late Box _templates;
late Box _exchangeTemplates;
@@ -337,8 +337,6 @@ late Box _unspentCoinsInfoSource;
late Box _payjoinSessionSource;
late Box _anonpayInvoiceInfoSource;
Future setup({
- required Box nodeSource,
- required Box powNodeSource,
required Box contactSource,
required Box templates,
required Box exchangeTemplates,
@@ -350,8 +348,6 @@ Future setup({
required SecureStorage secureStorage,
required GlobalKey navigatorKey,
}) async {
- _nodeSource = nodeSource;
- _powNodeSource = powNodeSource;
_contactSource = contactSource;
_templates = templates;
_exchangeTemplates = exchangeTemplates;
@@ -376,8 +372,6 @@ Future setup({
(secrets.wyreAccountId.isNotEmpty);
final settingsStore = await SettingsStoreBase.load(
- nodeSource: _nodeSource,
- powNodeSource: _powNodeSource,
isBitcoinBuyEnabled: isBitcoinBuyEnabled,
);
@@ -385,18 +379,16 @@ Future setup({
return;
}
- getIt.registerFactory>(() => _nodeSource);
- getIt.registerFactory>(() => _powNodeSource, instanceName: Node.boxName + "pow");
getIt.registerSingleton(AuthenticationStore());
getIt.registerSingleton(WalletListStore());
- getIt.registerSingleton(NodeListStoreBase.instance);
+ // getIt.registerSingleton(NodeListStoreBase.instance);
getIt.registerSingleton(settingsStore);
getIt.registerSingleton(AppStore(
authenticationStore: getIt.get(),
walletList: getIt.get(),
settingsStore: getIt.get(),
- nodeListStore: getIt.get(),
+ // nodeListStore: getIt.get(),
themeStore: getIt.get()));
getIt.registerSingleton(
TradesStore(appStore: getIt.get()));
@@ -1126,22 +1118,22 @@ Future setup({
getIt.registerFactory(() => AddressListPage(getIt.get()));
+ getIt.registerLazySingleton(() {
+ final appStore = getIt.get();
+ return NodeListViewModel(appStore);
+ });
+
getIt.registerFactoryParam(
- (showHidden, _) => NewAddressesPage(
+ (showHidden, _) => NewAddressesPage(
showHidden: showHidden,
addressListViewModel: getIt(),
dashboardViewModel: getIt(),
),
);
- getIt.registerFactory(() {
+ getIt.registerLazySingleton(() {
final appStore = getIt.get();
- return NodeListViewModel(_nodeSource, appStore);
- });
-
- getIt.registerFactory(() {
- final appStore = getIt.get();
- return PowNodeListViewModel(_powNodeSource, appStore);
+ return PowNodeListViewModel(appStore);
});
getIt.registerFactory(() => ConnectionSyncViewModel(getIt.get(), getIt.get().wallet!));
@@ -1184,12 +1176,14 @@ Future setup({
final WalletType type = args['type'] as WalletType? ?? getIt.get().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());
+ isPow,
+ getIt.get(),
+ getIt.get(),
+ type,
+ getIt.get(),
+ editingNode: editingNode
+ );
}
);
@@ -1791,7 +1785,6 @@ Future setup({
getIt.registerLazySingleton(() => NodeSwitchingService(
appStore: getIt.get(),
settingsStore: getIt.get(),
- nodeSource: _nodeSource,
));
getIt.registerFactoryParam(
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index df3977d00..e578a34af 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -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 defaultSettingsMigration(
{required int version,
required SharedPreferences sharedPreferences,
required SecureStorage secureStorage,
- required Box nodes,
- required Box powNodes,
required Box contactSource,
required Box havenSeedStore}) async {
if (Platform.isIOS) {
@@ -70,7 +69,7 @@ Future 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 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 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 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 defaultSettingsMigration(
case 11:
await _changeDefaultNode(
- nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.monero,
newDefaultUri: newCakeWalletMoneroUri,
@@ -196,38 +188,35 @@ Future 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 defaultSettingsMigration(
break;
case 18:
- addWalletNodeList(nodes: nodes, type: WalletType.monero);
+ addWalletNodeList(type: WalletType.monero);
break;
case 19:
@@ -245,25 +234,22 @@ Future 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 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 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 defaultSettingsMigration(
break;
case 29:
await _changeDefaultNode(
- nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoin,
newDefaultUri: newCakeWalletBitcoinUri,
@@ -326,25 +308,23 @@ Future 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 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 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 defaultSettingsMigration(
);
break;
case 40:
- await removeMoneroWorld(sharedPreferences: sharedPreferences, nodes: nodes);
+ await removeMoneroWorld(sharedPreferences: sharedPreferences);
break;
case 41:
_changeExchangeProviderAvailability(
@@ -390,14 +368,14 @@ Future 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 defaultSettingsMigration(
);
break;
case 44:
- _fixNodesUseSSLFlag(nodes);
+ _fixNodesUseSSLFlag();
await _changeDefaultNode(
- nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoin,
newDefaultUri: newCakeWalletBitcoinUri,
@@ -421,7 +398,6 @@ Future defaultSettingsMigration(
oldUri: ['cakewallet.com'],
);
_changeDefaultNode(
- nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.tron,
newDefaultUri: tronDefaultNodeUri,
@@ -436,10 +412,9 @@ Future 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 defaultSettingsMigration(
],
);
_changeDefaultNode(
- nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.solana,
newDefaultUri: solanaDefaultNodeUri,
@@ -461,10 +435,9 @@ Future 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 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 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 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 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 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 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 defaultSettingsMigration(
}
Future _updateNode({
- required Box 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 _updateNode({
/// generic function for changing any wallet default node
/// instead of making a new function for each change
Future _changeDefaultNode({
- required Box nodes,
required SharedPreferences sharedPreferences,
required WalletType type,
required String currentNodePreferenceKey,
@@ -678,19 +646,21 @@ Future _changeDefaultNode({
List?
oldUri, // ignore, if you want to force replace the node regardless of the user's current node
}) async {
+ List 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 _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 _changeExchangeProviderAvailability(SharedPreferences sharedPrefere
);
}
-Future _fixNodesUseSSLFlag(Box nodes) async {
- for (Node node in nodes.values) {
+Future _fixNodesUseSSLFlag() async {
+ final nodes = await Node.getAll();
+ for (Node node in nodes) {
switch (node.uriRaw) {
case cakeWalletLitecoinElectrumUri:
case cakeWalletBitcoinElectrumUri:
@@ -781,7 +708,8 @@ Future _fixNodesUseSSLFlag(Box nodes) async {
}
}
-Future updateNanoNodeList({required Box nodes}) async {
+Future updateNanoNodeList() async {
+ final nodes = await Node.getAll();
final nodeList = await loadDefaultNodes(WalletType.nano);
var listOfNewEndpoints = [
"app.natrium.io",
@@ -792,14 +720,14 @@ Future updateNanoNodeList({required Box 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 validateBitcoinSavedTransactionPriority(SharedPreferences sharedPre
}
}
-Future replaceNodesMigration({required Box nodes}) async {
+Future replaceNodesMigration() async {
final replaceNodes = {
'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 nodes = await Node.getAll();
+ nodes.forEach((Node node) async {
final nodeToReplace = replaceNodes[node.uri];
if (nodeToReplace != null) {
@@ -937,16 +866,12 @@ Future replaceNodesMigration({required Box nodes}) async {
});
}
-Node? getBitcoinTestnetDefaultElectrumServer({required Box nodes}) {
- return nodes.values
- .firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
- nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
-}
+Future getBitcoinTestnetDefaultElectrumServer()async {
+ final nodes = await Node.getAll();
-Node? getDefaultNode({required Box 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 insecureStorageMigration({
@@ -1057,8 +982,9 @@ Future rewriteSecureStoragePin({required SecureStorage secureStorage}) asy
);
}
-Future updateNodeTypes({required Box nodes}) async {
- nodes.values.forEach((node) async {
+Future updateNodeTypes() async {
+ List nodes = await Node.getAll();
+ nodes.forEach((node) async {
if (node.type == null) {
node.type = WalletType.monero;
await node.save();
@@ -1146,206 +1072,13 @@ Future updateBtcNanoWalletInfos() async {}
// }
// }
-Future checkCurrentNodes(
- Box nodeSource, Box 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 resetBitcoinElectrumServer(
- Box nodeSource, SharedPreferences sharedPreferences) async {
+Future 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 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 migrateExchangeStatus(SharedPreferences sharedPreferences) async {
await sharedPreferences.remove(PreferencesKey.disableExchangeKey);
}
-Future addNanoPowNodeList({required Box nodes}) async {
+Future 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 nodes}) {
- return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultPowNodeUri) ??
- nodes.values.firstWhereOrNull((node) => (node.type == WalletType.nano));
+Future getNanoDefaultPowNode() async {
+ final nodes = await Node.getAll();
+ return nodes.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultPowNodeUri) ??
+ nodes.firstWhereOrNull((node) => (node.type == WalletType.nano));
}
-Future addWalletNodeList({required Box nodes, required WalletType type}) async {
+Future addWalletNodeList({required WalletType type}) async {
+ final nodes = await Node.getAll();
final List 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 removeMoneroWorld(
- {required SharedPreferences sharedPreferences, required Box 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 removeMoneroWorld(
if (needToReplaceCurrentMoneroNode) {
await _changeDefaultNode(
- nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.monero,
newDefaultUri: newCakeWalletMoneroUri,
@@ -1430,8 +1166,7 @@ Future removeMoneroWorld(
}
}
-Future migrateExistingNodesToUseAutoSwitching(
- {required Box nodes, required Box powNodes}) async {
+Future migrateExistingNodesToUseAutoSwitching() async {
final listOfDefaultNodesWithAutoSwitching = [
'bitcoincash.stackwallet.com:50002',
'bch.aftrek.org:50002',
@@ -1465,12 +1200,24 @@ Future 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 _addXautTokenToExistingEthereumWallets() async {
diff --git a/lib/entities/node_check.dart b/lib/entities/node_check.dart
new file mode 100644
index 000000000..aee8e4045
--- /dev/null
+++ b/lib/entities/node_check.dart
@@ -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 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 powNodePreferenceKeys = {
+ WalletType.nano: PreferencesKey.currentNanoPowNodeIdKey
+};
+
+Future 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 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);
+ }
+}
\ No newline at end of file
diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart
index bf4e05869..e69de29bb 100644
--- a/lib/entities/node_list.dart
+++ b/lib/entities/node_list.dart
@@ -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> 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 = [];
-
- for (final raw in loadedNodes) {
- if (raw is Map) {
- final node = Node.fromMap(Map.from(raw));
- node.type = type;
- nodes.add(node);
- }
- }
-
- return nodes;
-}
-
-Future> loadDefaultNanoPowNodes() async {
- final powNodesRaw = await rootBundle.loadString('assets/nano_pow_node_list.yml');
- final loadedPowNodes = loadYaml(powNodesRaw) as YamlList;
- final nodes = [];
-
- for (final raw in loadedPowNodes) {
- if (raw is Map) {
- final node = Node.fromMap(Map.from(raw));
- node.type = WalletType.nano;
- nodes.add(node);
- }
- }
-
- return nodes;
-}
-
-Future resetToDefault(Box 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 resetPowToDefault(Box powNodeSource) async {
- final nanoPowNodes = await loadDefaultNanoPowNodes();
- final nodes = nanoPowNodes;
- await powNodeSource.clear();
- await powNodeSource.addAll(nodes);
-}
diff --git a/lib/main.dart b/lib/main.dart
index 61dea0d6e..d8a66241c 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -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 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 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.boxName);
- final nodes = await CakeHive.openBox(Node.boxName);
- final powNodes =
- await CakeHive.openBox(Node.boxName + "pow"); // must be different from Node.boxName
final transactionDescriptions = await CakeHive.openBox(
TransactionDescription.boxName,
encryptionKey: transactionDescriptionsBoxKey);
await performTradeHiveMigration(secureStorage);
+ await performNodeHiveMigration();
+ await validateBuiltinNodes();
final orders = await CakeHive.openBox(Order.boxName, encryptionKey: ordersBoxKey);
final templates = await CakeHive.openBox(Template.boxName);
@@ -309,8 +307,6 @@ Future 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 initializeAppConfigs({bool loadWallet = true}) async {
payjoinSessionSource: payjoinSessionSource,
anonpayInvoiceInfo: anonpayInvoiceInfo,
havenSeedStore: havenSeedStore,
- initialMigrationVersion: 65,
+ initialMigrationVersion: 66,
);
}
Future initialSetup({
required bool loadWallet,
required SharedPreferences sharedPreferences,
- required Box nodes,
- required Box powNodes,
required Box contactSource,
required Box ordersSource,
// required FiatConvertationService fiatConvertationService,
@@ -350,13 +344,9 @@ Future 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 initialSetup({
navigatorKey: navigatorKey,
secureStorage: secureStorage,
);
+ final settingsStore = getIt();
+ await checkCurrentNodes(sharedPreferences, settingsStore);
await getIt.get().resetAuthDataOnNewInstall(sharedPreferences);
await bootstrapOffline();
- final settingsStore = getIt();
if (!settingsStore.currentBuiltinTor) {
bootstrapOnline(navigatorKey, loadWallet: loadWallet);
}
diff --git a/lib/new-ui/widgets/send_page/send_confirm_sheet.dart b/lib/new-ui/widgets/send_page/send_confirm_sheet.dart
index 853a82adb..65e6f8d6c 100644
--- a/lib/new-ui/widgets/send_page/send_confirm_sheet.dart
+++ b/lib/new-ui/widgets/send_page/send_confirm_sheet.dart
@@ -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 {
diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart
index bc407531a..92bccb27a 100644
--- a/lib/src/screens/nodes/node_create_or_edit_page.dart
+++ b/lib/src/screens/nodes/node_create_or_edit_page.dart
@@ -128,15 +128,16 @@ class _NodeCreateOrEditPageState extends State {
),
) ??
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 {
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();
}
diff --git a/lib/src/screens/nodes/pow_node_create_or_edit_page.dart b/lib/src/screens/nodes/pow_node_create_or_edit_page.dart
index 44968836b..72b64ed8b 100644
--- a/lib/src/screens/nodes/pow_node_create_or_edit_page.dart
+++ b/lib/src/screens/nodes/pow_node_create_or_edit_page.dart
@@ -143,7 +143,7 @@ class _PowNodeCreateOrEditPageState extends State {
}
await widget.nodeCreateOrEditViewModel.save(
- editingNode: widget.editingNode, saveAsCurrent: widget.isSelected ?? false);
+ saveAsCurrent: widget.isSelected ?? false);
Navigator.of(context).pop();
},
text: S.of(context).save,
diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart
index 525252d89..19a23be48 100644
--- a/lib/src/screens/nodes/widgets/node_form.dart
+++ b/lib/src/screens/nodes/widgets/node_form.dart
@@ -65,66 +65,77 @@ class NodeFormState extends State {
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 {
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,
diff --git a/lib/src/screens/settings/manage_nodes_page.dart b/lib/src/screens/settings/manage_nodes_page.dart
index 841a440c9..02c2e4e6f 100644
--- a/lib/src/screens/settings/manage_nodes_page.dart
+++ b/lib/src/screens/settings/manage_nodes_page.dart
@@ -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,
diff --git a/lib/store/app_store.dart b/lib/store/app_store.dart
index 466b235a6..dd41fe948 100644
--- a/lib/store/app_store.dart
+++ b/lib/store/app_store.dart
@@ -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;
diff --git a/lib/store/node_list_store.dart b/lib/store/node_list_store.dart
index 2990f9575..e69de29bb 100644
--- a/lib/store/node_list_store.dart
+++ b/lib/store/node_list_store.dart
@@ -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();
-
- static StreamSubscription? _onNodesSourceChange;
- static NodeListStore? _instance;
-
- static NodeListStore get instance {
- if (_instance != null) {
- return _instance!;
- }
-
- final nodeSource = getIt.get>();
- _instance = NodeListStore();
- _instance!.nodes.clear();
- _instance!.nodes.addAll(nodeSource.values);
- _onNodesSourceChange?.cancel();
- _onNodesSourceChange = nodeSource.bindToList(_instance!.nodes);
-
- return _instance!;
- }
-
- final ObservableList nodes;
-}
diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart
index 9551942e7..d13205651 100644
--- a/lib/store/settings_store.dart
+++ b/lib/store/settings_store.dart
@@ -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 load(
- {required Box nodeSource,
- required Box 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 _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 _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;
diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart
index 42d289dd3..e3f101c1d 100644
--- a/lib/utils/exception_handler.dart
+++ b/lib/utils/exception_handler.dart
@@ -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;
- }
}
diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart
index a238b0d14..774136ac4 100644
--- a/lib/view_model/node_list/node_create_or_edit_view_model.dart
+++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart
@@ -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 _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 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 delete({required Node editingNode}) async {
+ await editingNode.delete();
+ if(nodeListViewModel != null) {
+ nodeListViewModel!.bindNodes();
+ }
+ if(powNodeListViewModel != null) {
+ powNodeListViewModel!.bindNodes();
+ }
+ }
+
+ @action
+ Future 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;
diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart
index e64b9473e..55207f0df 100644
--- a/lib/view_model/node_list/node_list_view_model.dart
+++ b/lib/view_model/node_list/node_list_view_model.dart
@@ -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(),
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 nodes;
final SettingsStore settingsStore;
- final Box _nodeSource;
final AppStore _appStore;
Future 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 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));
+
}
}
diff --git a/lib/view_model/node_list/pow_node_list_view_model.dart b/lib/view_model/node_list/pow_node_list_view_model.dart
index d917779c2..b7e185e2b 100644
--- a/lib/view_model/node_list/pow_node_list_view_model.dart
+++ b/lib/view_model/node_list/pow_node_list_view_model.dart
@@ -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(),
settingsStore = _appStore.settingsStore {
- _bindNodes();
+ bindNodes();
reaction((_) => _appStore.wallet, (WalletBase? _wallet) {
- _bindNodes();
+ bindNodes();
});
}
@@ -50,17 +51,16 @@ abstract class PowNodeListViewModelBase with Store {
final ObservableList nodes;
final SettingsStore settingsStore;
- final Box