diff --git a/crypto_plugins/flutter_libmonero b/crypto_plugins/flutter_libmonero index 201ebc2ca..d892955bf 160000 --- a/crypto_plugins/flutter_libmonero +++ b/crypto_plugins/flutter_libmonero @@ -1 +1 @@ -Subproject commit 201ebc2ca4ef003b2b264af47467868a00fcbd73 +Subproject commit d892955bf7f4273855395091b9009243185d48f1 diff --git a/lib/models/node_model.dart b/lib/models/node_model.dart index af5f8cbc1..2aeaa893b 100644 --- a/lib/models/node_model.dart +++ b/lib/models/node_model.dart @@ -26,6 +26,8 @@ class NodeModel { final bool isFailover; // @HiveField(9) final bool isDown; + // @HiveField(10) + final bool? trusted; NodeModel({ required this.host, @@ -38,6 +40,7 @@ class NodeModel { required this.isFailover, required this.isDown, this.loginName, + this.trusted, }); NodeModel copyWith({ @@ -50,6 +53,7 @@ class NodeModel { String? coinName, bool? isFailover, bool? isDown, + bool? trusted, }) { return NodeModel( host: host ?? this.host, @@ -62,6 +66,7 @@ class NodeModel { coinName: coinName ?? this.coinName, isFailover: isFailover ?? this.isFailover, isDown: isDown ?? this.isDown, + trusted: trusted ?? this.trusted, ); } @@ -82,6 +87,7 @@ class NodeModel { map['coinName'] = coinName; map['isFailover'] = isFailover; map['isDown'] = isDown; + map['trusted'] = trusted; return map; } diff --git a/lib/models/type_adaptors/node_model.g.dart b/lib/models/type_adaptors/node_model.g.dart index 580c36a75..597468c56 100644 --- a/lib/models/type_adaptors/node_model.g.dart +++ b/lib/models/type_adaptors/node_model.g.dart @@ -26,14 +26,15 @@ class NodeModelAdapter extends TypeAdapter { loginName: fields[5] as String?, coinName: fields[7] as String, isFailover: fields[8] as bool, - isDown: fields[8] as bool, + isDown: fields[9] as bool, + trusted: fields[10] as bool?, ); } @override void write(BinaryWriter writer, NodeModel obj) { writer - ..writeByte(10) + ..writeByte(11) ..writeByte(0) ..write(obj.id) ..writeByte(1) @@ -53,7 +54,9 @@ class NodeModelAdapter extends TypeAdapter { ..writeByte(8) ..write(obj.isFailover) ..writeByte(9) - ..write(obj.isDown); + ..write(obj.isDown) + ..writeByte(10) + ..write(obj.trusted); } @override diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index e29b0888f..7db6e5845 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -328,6 +328,7 @@ class _AddEditNodeViewState extends ConsumerState { enabled: true, coinName: coin.name, isFailover: formData.isFailover!, + trusted: formData.trusted!, isDown: false, ); @@ -352,6 +353,7 @@ class _AddEditNodeViewState extends ConsumerState { enabled: true, coinName: coin.name, isFailover: formData.isFailover!, + trusted: formData.trusted!, isDown: false, ); @@ -621,11 +623,11 @@ class _AddEditNodeViewState extends ConsumerState { class NodeFormData { String? name, host, login, password; int? port; - bool? useSSL, isFailover; + bool? useSSL, isFailover, trusted; @override String toString() { - return "{ name: $name, host: $host, port: $port, useSSL: $useSSL }"; + return "{ name: $name, host: $host, port: $port, useSSL: $useSSL, trusted: $trusted }"; } } @@ -666,8 +668,10 @@ class _NodeFormState extends ConsumerState { bool _useSSL = false; bool _isFailover = false; + bool _trusted = false; int? port; late bool enableSSLCheckbox; + late bool trustedCheckbox; late final bool enableAuthFields; @@ -733,6 +737,7 @@ class _NodeFormState extends ConsumerState { ref.read(nodeFormDataProvider).port = port; ref.read(nodeFormDataProvider).useSSL = _useSSL; ref.read(nodeFormDataProvider).isFailover = _isFailover; + ref.read(nodeFormDataProvider).trusted = _trusted; } @override @@ -764,12 +769,17 @@ class _NodeFormState extends ConsumerState { _usernameController.text = node.loginName ?? ""; _useSSL = node.useSSL; _isFailover = node.isFailover; + _trusted = node.trusted ?? false; if (widget.coin == Coin.epicCash) { enableSSLCheckbox = !node.host.startsWith("http"); } else { enableSSLCheckbox = true; } - print("enableSSLCheckbox: $enableSSLCheckbox"); + if (widget.coin == Coin.monero || widget.coin == Coin.wownero) { + trustedCheckbox = node.trusted ?? false; + } else { + trustedCheckbox = false; + } WidgetsBinding.instance.addPostFrameCallback((_) { // update provider state object so test connection works without having to modify a field in the ui first @@ -1106,6 +1116,57 @@ class _NodeFormState extends ConsumerState { ), ], ), + if (widget.coin == Coin.monero || widget.coin == Coin.wownero) + Row( + children: [ + GestureDetector( + onTap: !widget.readOnly /*&& trustedCheckbox*/ + ? () { + setState(() { + _trusted = !_trusted; + }); + _updateState(); + } + : null, + child: Container( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + width: 20, + height: 20, + child: Checkbox( + fillColor: !widget.readOnly /*&& trustedCheckbox*/ + ? null + : MaterialStateProperty.all(Theme.of(context) + .extension()! + .checkboxBGDisabled), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + value: _trusted, + onChanged: !widget.readOnly /*&& trustedCheckbox*/ + ? (newValue) { + setState(() { + _trusted = newValue!; + }); + _updateState(); + } + : null, + ), + ), + const SizedBox( + width: 12, + ), + Text( + "Trusted", + style: STextStyles.itemSubtitle12(context), + ) + ], + ), + ), + ), + ], + ), if (widget.coin != Coin.monero && widget.coin != Coin.wownero && widget.coin != Coin.epicCash) diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index ad8ad7301..1816e9886 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -70,15 +70,13 @@ class _NodeDetailsViewState extends ConsumerState { switch (coin) { case Coin.epicCash: try { - - testPassed = await testEpicNodeConnection( - NodeFormData() - ..host = node!.host - ..useSSL = node.useSSL - ..port = node.port, - ) != - null; - + testPassed = await testEpicNodeConnection( + NodeFormData() + ..host = node!.host + ..useSSL = node.useSSL + ..port = node.port, + ) != + null; } catch (e, s) { Logging.instance.log("$e\n$s", level: LogLevel.Warning); testPassed = false; @@ -388,6 +386,7 @@ class _NodeDetailsViewState extends ConsumerState { port: ref.read(nodeFormDataProvider).port, name: ref.read(nodeFormDataProvider).name, useSSL: ref.read(nodeFormDataProvider).useSSL, + trusted: ref.read(nodeFormDataProvider).trusted, loginName: ref.read(nodeFormDataProvider).login, isFailover: ref.read(nodeFormDataProvider).isFailover, diff --git a/lib/services/coins/monero/monero_wallet.dart b/lib/services/coins/monero/monero_wallet.dart index d9c6ae42b..a7b8fcade 100644 --- a/lib/services/coins/monero/monero_wallet.dart +++ b/lib/services/coins/monero/monero_wallet.dart @@ -398,7 +398,10 @@ class MoneroWallet extends CoinServiceAPI { final node = await _getCurrentNode(); final host = Uri.parse(node.host).host; await walletBase!.connectToNode( - node: Node(uri: "$host:${node.port}", type: WalletType.monero)); + node: Node( + uri: "$host:${node.port}", + type: WalletType.monero, + trusted: node.trusted ?? false)); await walletBase!.startSync(); await DB.instance .put(boxName: walletId, key: "id", value: _walletId); @@ -666,7 +669,10 @@ class MoneroWallet extends CoinServiceAPI { final node = await _getCurrentNode(); final host = Uri.parse(node.host).host; await walletBase!.connectToNode( - node: Node(uri: "$host:${node.port}", type: WalletType.monero)); + node: Node( + uri: "$host:${node.port}", + type: WalletType.monero, + trusted: node.trusted ?? false)); await walletBase!.rescan(height: credentials.height); walletBase!.close(); } catch (e, s) { @@ -775,7 +781,10 @@ class MoneroWallet extends CoinServiceAPI { final node = await _getCurrentNode(); final host = Uri.parse(node.host).host; await walletBase?.connectToNode( - node: Node(uri: "$host:${node.port}", type: WalletType.monero)); + node: Node( + uri: "$host:${node.port}", + type: WalletType.monero, + trusted: node.trusted ?? false)); } await walletBase?.startSync(); await refresh(); @@ -851,7 +860,10 @@ class MoneroWallet extends CoinServiceAPI { final host = Uri.parse(node.host).host; await walletBase?.connectToNode( - node: Node(uri: "$host:${node.port}", type: WalletType.monero)); + node: Node( + uri: "$host:${node.port}", + type: WalletType.monero, + trusted: node.trusted ?? false)); // TODO: is this sync call needed? Do we need to notify ui here? await walletBase?.startSync(); diff --git a/lib/services/node_service.dart b/lib/services/node_service.dart index ca1aae082..8a0e17ad7 100644 --- a/lib/services/node_service.dart +++ b/lib/services/node_service.dart @@ -33,11 +33,15 @@ class NodeService extends ChangeNotifier { ); } } else { - // update all fields but copy over previously set enabled state + // update all fields but copy over previously set enabled and trusted states await DB.instance.put( boxName: DB.boxNameNodeModels, key: savedNode.id, - value: defaultNode.copyWith(enabled: savedNode.enabled)); + value: defaultNode.copyWith( + enabled: savedNode.enabled, + isFailover: savedNode.isFailover, + trusted: savedNode.trusted, + )); } // check if a default node is the primary node for the crypto currency @@ -49,6 +53,8 @@ class NodeService extends ChangeNotifier { coin: coin, node: defaultNode.copyWith( enabled: primaryNode.enabled, + isFailover: primaryNode.isFailover, + trusted: primaryNode.trusted, ), ); } @@ -161,6 +167,17 @@ class NodeService extends ChangeNotifier { String? password, bool shouldNotifyListeners, ) async { + // check if the node being edited is the primary one; if it is, setPrimaryNodeFor coin + final coin = coinFromPrettyName(editedNode.coinName); + var primaryNode = getPrimaryNodeFor(coin: coin); + if (primaryNode?.id == editedNode.id) { + await setPrimaryNodeFor( + coin: coin, + node: editedNode, + shouldNotifyListeners: true, + ); + } + return add(editedNode, password, shouldNotifyListeners); } diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index e45e33aec..744e83a97 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -108,6 +108,7 @@ abstract class DefaultNodes { coinName: Coin.monero.name, isFailover: true, isDown: false, + trusted: true, ); static NodeModel get wownero => NodeModel( @@ -120,6 +121,7 @@ abstract class DefaultNodes { coinName: Coin.wownero.name, isFailover: true, isDown: false, + trusted: true, ); static NodeModel get epicCash => NodeModel(