From 65799a8764b339c2db329400d74bd7462632e63d Mon Sep 17 00:00:00 2001
From: Adegoke David <64401859+Blazebrain@users.noreply.github.com>
Date: Wed, 24 Apr 2024 03:04:16 +0100
Subject: [PATCH 1/7] fix: Issue with the privateKey of Solana wallets being
 different accross various apps (#1400)

---
 cw_solana/lib/solana_wallet.dart | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart
index ad58c4293..43a6d0b83 100644
--- a/cw_solana/lib/solana_wallet.dart
+++ b/cw_solana/lib/solana_wallet.dart
@@ -27,6 +27,7 @@ import 'package:hex/hex.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 import 'package:shared_preferences/shared_preferences.dart';
+import 'package:solana/base58.dart';
 import 'package:solana/metaplex.dart' as metaplex;
 import 'package:solana/solana.dart';
 
@@ -108,7 +109,17 @@ abstract class SolanaWalletBase
   String? get seed => _mnemonic;
 
   @override
-  String get privateKey => HEX.encode(_keyPairData!.bytes);
+  String get privateKey {
+    final privateKeyBytes = _keyPairData!.bytes;
+
+    final publicKeyBytes = _keyPairData!.publicKey.bytes;
+
+    final encodedBytes = privateKeyBytes + publicKeyBytes;
+
+    final privateKey = base58encode(encodedBytes);
+
+    return privateKey;
+  }
 
   Future<void> init() async {
     final boxName = "${walletInfo.name.replaceAll(" ", "_")}_${SPLToken.boxName}";
@@ -135,8 +146,8 @@ abstract class SolanaWalletBase
     assert(mnemonic != null || privateKey != null);
 
     if (privateKey != null) {
-      final privateKeyBytes = HEX.decode(privateKey);
-      return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes);
+      final privateKeyBytes = base58decode(privateKey);
+      return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes.take(32).toList());
     }
 
     return Wallet.fromMnemonic(mnemonic!, account: 0, change: 0);

From dcfb2b2b730f27a849f0e866acba48517b821195 Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Wed, 24 Apr 2024 17:00:53 -0700
Subject: [PATCH 2/7] fix empty string case (#1401)

* bio auth mac fix

* remove comment and change duration from 2 to 0

* cherry pick previous changes

* fix empty string case

* add support for path for all currency types

* disable paths on electrum and monero nodes

* undo mac auth changes

* stuff I missed

* 1 last thing

* another thing I missed
---
 cw_bitcoin/pubspec.lock                       | 32 +++++++++-----
 cw_core/lib/node.dart                         |  6 +--
 cw_core/pubspec.lock                          | 32 +++++++++-----
 cw_core/pubspec.yaml                          |  1 +
 cw_haven/pubspec.lock                         | 44 +++++++++++--------
 cw_monero/example/pubspec.lock                | 30 ++++++++-----
 cw_monero/pubspec.lock                        | 44 +++++++++++--------
 cw_nano/pubspec.lock                          | 44 +++++++++++--------
 lib/core/node_address_validator.dart          |  6 ++-
 lib/entities/biometric_auth.dart              |  2 +-
 lib/locales/yoruba_intl.dart                  |  2 +-
 lib/src/screens/nodes/widgets/node_form.dart  | 26 ++++++-----
 .../validable_annotated_editable_text.dart    |  2 +-
 lib/view_model/auth_view_model.dart           |  2 +-
 .../node_create_or_edit_view_model.dart       | 19 +++++++-
 15 files changed, 182 insertions(+), 110 deletions(-)

diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock
index 3d828243c..53cf550c8 100644
--- a/cw_bitcoin/pubspec.lock
+++ b/cw_bitcoin/pubspec.lock
@@ -217,10 +217,10 @@ packages:
     dependency: transitive
     description:
       name: collection
-      sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
+      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
       url: "https://pub.dev"
     source: hosted
-    version: "1.17.1"
+    version: "1.17.2"
   convert:
     dependency: transitive
     description:
@@ -434,18 +434,18 @@ packages:
     dependency: transitive
     description:
       name: matcher
-      sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
+      sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
       url: "https://pub.dev"
     source: hosted
-    version: "0.12.15"
+    version: "0.12.16"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
       url: "https://pub.dev"
     source: hosted
-    version: "0.2.0"
+    version: "0.5.0"
   meta:
     dependency: transitive
     description:
@@ -663,10 +663,10 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
       url: "https://pub.dev"
     source: hosted
-    version: "1.9.1"
+    version: "1.10.0"
   stack_trace:
     dependency: transitive
     description:
@@ -711,10 +711,10 @@ packages:
     dependency: transitive
     description:
       name: test_api
-      sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
+      sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.1"
+    version: "0.6.0"
   timing:
     dependency: transitive
     description:
@@ -748,13 +748,21 @@ packages:
     source: hosted
     version: "2.1.4"
   watcher:
-    dependency: transitive
+    dependency: "direct overridden"
     description:
       name: watcher
       sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
       url: "https://pub.dev"
     source: hosted
     version: "1.1.0"
+  web:
+    dependency: transitive
+    description:
+      name: web
+      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.1.4-beta"
   web_socket_channel:
     dependency: transitive
     description:
@@ -788,5 +796,5 @@ packages:
     source: hosted
     version: "3.1.2"
 sdks:
-  dart: ">=3.0.0 <4.0.0"
+  dart: ">=3.1.0-185.0.dev <4.0.0"
   flutter: ">=3.10.0"
diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart
index d7e91d692..9d0806851 100644
--- a/cw_core/lib/node.dart
+++ b/cw_core/lib/node.dart
@@ -10,7 +10,7 @@ import 'package:http/io_client.dart' as ioc;
 
 part 'node.g.dart';
 
-Uri createUriFromElectrumAddress(String address) => Uri.tryParse('tcp://$address')!;
+Uri createUriFromElectrumAddress(String address, String path) => Uri.tryParse('tcp://$address$path')!;
 
 @HiveType(typeId: Node.typeId)
 class Node extends HiveObject with Keyable {
@@ -83,7 +83,7 @@ class Node extends HiveObject with Keyable {
       case WalletType.bitcoin:
       case WalletType.litecoin:
       case WalletType.bitcoinCash:
-        return createUriFromElectrumAddress(uriRaw);
+        return createUriFromElectrumAddress(uriRaw, path ?? '');
       case WalletType.nano:
       case WalletType.banano:
         if (isSSL) {
@@ -94,7 +94,7 @@ class Node extends HiveObject with Keyable {
       case WalletType.ethereum:
       case WalletType.polygon:
       case WalletType.solana:
-        return Uri.https(uriRaw, '');
+        return Uri.https(uriRaw, path ?? '');
       default:
         throw Exception('Unexpected type ${type.toString()} for Node uri');
     }
diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock
index 678e57b54..aef76f300 100644
--- a/cw_core/pubspec.lock
+++ b/cw_core/pubspec.lock
@@ -149,10 +149,10 @@ packages:
     dependency: transitive
     description:
       name: collection
-      sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
+      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
       url: "https://pub.dev"
     source: hosted
-    version: "1.17.1"
+    version: "1.17.2"
   convert:
     dependency: transitive
     description:
@@ -343,18 +343,18 @@ packages:
     dependency: transitive
     description:
       name: matcher
-      sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
+      sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
       url: "https://pub.dev"
     source: hosted
-    version: "0.12.15"
+    version: "0.12.16"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
       url: "https://pub.dev"
     source: hosted
-    version: "0.2.0"
+    version: "0.5.0"
   meta:
     dependency: transitive
     description:
@@ -564,10 +564,10 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
       url: "https://pub.dev"
     source: hosted
-    version: "1.9.1"
+    version: "1.10.0"
   stack_trace:
     dependency: transitive
     description:
@@ -612,10 +612,10 @@ packages:
     dependency: transitive
     description:
       name: test_api
-      sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
+      sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.1"
+    version: "0.6.0"
   timing:
     dependency: transitive
     description:
@@ -641,13 +641,21 @@ packages:
     source: hosted
     version: "2.1.4"
   watcher:
-    dependency: transitive
+    dependency: "direct overridden"
     description:
       name: watcher
       sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
       url: "https://pub.dev"
     source: hosted
     version: "1.1.0"
+  web:
+    dependency: transitive
+    description:
+      name: web
+      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.1.4-beta"
   web_socket_channel:
     dependency: transitive
     description:
@@ -681,5 +689,5 @@ packages:
     source: hosted
     version: "3.1.2"
 sdks:
-  dart: ">=3.0.0 <4.0.0"
+  dart: ">=3.1.0-185.0.dev <4.0.0"
   flutter: ">=3.10.0"
diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml
index 04a840d4e..36fe9967e 100644
--- a/cw_core/pubspec.yaml
+++ b/cw_core/pubspec.yaml
@@ -33,6 +33,7 @@ dev_dependencies:
   mobx_codegen: ^2.0.7
   hive_generator: ^2.0.1
 
+
 # For information on the generic Dart part of this file, see the
 # following page: https://dart.dev/tools/pub/pubspec
 
diff --git a/cw_haven/pubspec.lock b/cw_haven/pubspec.lock
index b0a350cc7..d84523539 100644
--- a/cw_haven/pubspec.lock
+++ b/cw_haven/pubspec.lock
@@ -69,10 +69,10 @@ packages:
     dependency: transitive
     description:
       name: build_daemon
-      sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf"
+      sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.0"
+    version: "4.0.0"
   build_resolvers:
     dependency: "direct dev"
     description:
@@ -85,10 +85,10 @@ packages:
     dependency: "direct dev"
     description:
       name: build_runner
-      sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727
+      sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.3"
+    version: "2.4.9"
   build_runner_core:
     dependency: transitive
     description:
@@ -149,10 +149,10 @@ packages:
     dependency: transitive
     description:
       name: collection
-      sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
+      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
       url: "https://pub.dev"
     source: hosted
-    version: "1.17.1"
+    version: "1.17.2"
   convert:
     dependency: transitive
     description:
@@ -350,18 +350,18 @@ packages:
     dependency: transitive
     description:
       name: matcher
-      sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
+      sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
       url: "https://pub.dev"
     source: hosted
-    version: "0.12.15"
+    version: "0.12.16"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
       url: "https://pub.dev"
     source: hosted
-    version: "0.2.0"
+    version: "0.5.0"
   meta:
     dependency: transitive
     description:
@@ -563,10 +563,10 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
       url: "https://pub.dev"
     source: hosted
-    version: "1.9.1"
+    version: "1.10.0"
   stack_trace:
     dependency: transitive
     description:
@@ -611,10 +611,10 @@ packages:
     dependency: transitive
     description:
       name: test_api
-      sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
+      sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.1"
+    version: "0.6.0"
   timing:
     dependency: transitive
     description:
@@ -640,13 +640,21 @@ packages:
     source: hosted
     version: "2.1.4"
   watcher:
-    dependency: transitive
+    dependency: "direct overridden"
     description:
       name: watcher
-      sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
+      sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
       url: "https://pub.dev"
     source: hosted
-    version: "1.0.2"
+    version: "1.1.0"
+  web:
+    dependency: transitive
+    description:
+      name: web
+      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.1.4-beta"
   web_socket_channel:
     dependency: transitive
     description:
@@ -680,5 +688,5 @@ packages:
     source: hosted
     version: "3.1.1"
 sdks:
-  dart: ">=3.0.0 <4.0.0"
+  dart: ">=3.1.0-185.0.dev <4.0.0"
   flutter: ">=3.7.0"
diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock
index c9ca8d92b..ece0d4395 100644
--- a/cw_monero/example/pubspec.lock
+++ b/cw_monero/example/pubspec.lock
@@ -53,10 +53,10 @@ packages:
     dependency: transitive
     description:
       name: collection
-      sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
+      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
       url: "https://pub.dev"
     source: hosted
-    version: "1.17.1"
+    version: "1.17.2"
   convert:
     dependency: transitive
     description:
@@ -213,18 +213,18 @@ packages:
     dependency: transitive
     description:
       name: matcher
-      sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
+      sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
       url: "https://pub.dev"
     source: hosted
-    version: "0.12.15"
+    version: "0.12.16"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
       url: "https://pub.dev"
     source: hosted
-    version: "0.2.0"
+    version: "0.5.0"
   meta:
     dependency: transitive
     description:
@@ -354,10 +354,10 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
       url: "https://pub.dev"
     source: hosted
-    version: "1.9.1"
+    version: "1.10.0"
   stack_trace:
     dependency: transitive
     description:
@@ -394,10 +394,10 @@ packages:
     dependency: transitive
     description:
       name: test_api
-      sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
+      sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.1"
+    version: "0.6.0"
   typed_data:
     dependency: transitive
     description:
@@ -414,6 +414,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.1.4"
+  web:
+    dependency: transitive
+    description:
+      name: web
+      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.1.4-beta"
   win32:
     dependency: transitive
     description:
@@ -431,5 +439,5 @@ packages:
     source: hosted
     version: "0.2.0+3"
 sdks:
-  dart: ">=3.0.6 <4.0.0"
+  dart: ">=3.1.0-185.0.dev <4.0.0"
   flutter: ">=3.7.0"
diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock
index 0f8f2c90e..b736f80cb 100644
--- a/cw_monero/pubspec.lock
+++ b/cw_monero/pubspec.lock
@@ -69,10 +69,10 @@ packages:
     dependency: transitive
     description:
       name: build_daemon
-      sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf"
+      sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.0"
+    version: "4.0.0"
   build_resolvers:
     dependency: "direct dev"
     description:
@@ -85,10 +85,10 @@ packages:
     dependency: "direct dev"
     description:
       name: build_runner
-      sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727
+      sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.3"
+    version: "2.4.9"
   build_runner_core:
     dependency: transitive
     description:
@@ -149,10 +149,10 @@ packages:
     dependency: transitive
     description:
       name: collection
-      sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
+      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
       url: "https://pub.dev"
     source: hosted
-    version: "1.17.1"
+    version: "1.17.2"
   convert:
     dependency: transitive
     description:
@@ -366,18 +366,18 @@ packages:
     dependency: transitive
     description:
       name: matcher
-      sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
+      sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
       url: "https://pub.dev"
     source: hosted
-    version: "0.12.15"
+    version: "0.12.16"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
       url: "https://pub.dev"
     source: hosted
-    version: "0.2.0"
+    version: "0.5.0"
   meta:
     dependency: transitive
     description:
@@ -587,10 +587,10 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
       url: "https://pub.dev"
     source: hosted
-    version: "1.9.1"
+    version: "1.10.0"
   stack_trace:
     dependency: transitive
     description:
@@ -635,10 +635,10 @@ packages:
     dependency: transitive
     description:
       name: test_api
-      sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
+      sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.1"
+    version: "0.6.0"
   timing:
     dependency: transitive
     description:
@@ -664,13 +664,21 @@ packages:
     source: hosted
     version: "2.1.4"
   watcher:
-    dependency: transitive
+    dependency: "direct overridden"
     description:
       name: watcher
-      sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
+      sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
       url: "https://pub.dev"
     source: hosted
-    version: "1.0.2"
+    version: "1.1.0"
+  web:
+    dependency: transitive
+    description:
+      name: web
+      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.1.4-beta"
   web_socket_channel:
     dependency: transitive
     description:
@@ -704,5 +712,5 @@ packages:
     source: hosted
     version: "3.1.1"
 sdks:
-  dart: ">=3.0.6 <4.0.0"
+  dart: ">=3.1.0-185.0.dev <4.0.0"
   flutter: ">=3.7.0"
diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock
index a42bb9ab4..0ebc5e75f 100644
--- a/cw_nano/pubspec.lock
+++ b/cw_nano/pubspec.lock
@@ -93,10 +93,10 @@ packages:
     dependency: transitive
     description:
       name: build_daemon
-      sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169"
+      sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.1"
+    version: "4.0.1"
   build_resolvers:
     dependency: transitive
     description:
@@ -109,10 +109,10 @@ packages:
     dependency: "direct dev"
     description:
       name: build_runner
-      sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727
+      sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.3"
+    version: "2.4.9"
   build_runner_core:
     dependency: transitive
     description:
@@ -173,10 +173,10 @@ packages:
     dependency: transitive
     description:
       name: collection
-      sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
+      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
       url: "https://pub.dev"
     source: hosted
-    version: "1.17.1"
+    version: "1.17.2"
   convert:
     dependency: transitive
     description:
@@ -419,18 +419,18 @@ packages:
     dependency: transitive
     description:
       name: matcher
-      sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
+      sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
       url: "https://pub.dev"
     source: hosted
-    version: "0.12.15"
+    version: "0.12.16"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
       url: "https://pub.dev"
     source: hosted
-    version: "0.2.0"
+    version: "0.5.0"
   meta:
     dependency: transitive
     description:
@@ -713,10 +713,10 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
       url: "https://pub.dev"
     source: hosted
-    version: "1.9.1"
+    version: "1.10.0"
   stack_trace:
     dependency: transitive
     description:
@@ -761,10 +761,10 @@ packages:
     dependency: transitive
     description:
       name: test_api
-      sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
+      sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.1"
+    version: "0.6.0"
   timing:
     dependency: transitive
     description:
@@ -790,13 +790,21 @@ packages:
     source: hosted
     version: "2.1.4"
   watcher:
-    dependency: transitive
+    dependency: "direct overridden"
     description:
       name: watcher
-      sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
+      sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
       url: "https://pub.dev"
     source: hosted
-    version: "1.0.2"
+    version: "1.1.0"
+  web:
+    dependency: transitive
+    description:
+      name: web
+      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.1.4-beta"
   web_socket_channel:
     dependency: transitive
     description:
@@ -830,5 +838,5 @@ packages:
     source: hosted
     version: "3.1.2"
 sdks:
-  dart: ">=3.0.0 <4.0.0"
+  dart: ">=3.1.0-185.0.dev <4.0.0"
   flutter: ">=3.7.0"
diff --git a/lib/core/node_address_validator.dart b/lib/core/node_address_validator.dart
index c1fe4ba91..0c8a0c37c 100644
--- a/lib/core/node_address_validator.dart
+++ b/lib/core/node_address_validator.dart
@@ -11,5 +11,9 @@ class NodeAddressValidator extends TextValidator {
 
 class NodePathValidator extends TextValidator {
   NodePathValidator()
-      : super(errorMessage: S.current.error_text_node_address, pattern: '^([/0-9a-zA-Z.\-]+)?\$');
+      : super(
+          errorMessage: S.current.error_text_node_address,
+          pattern: '^([/0-9a-zA-Z.\-]+)?\$',
+          isAutovalidate: true,
+        );
 }
diff --git a/lib/entities/biometric_auth.dart b/lib/entities/biometric_auth.dart
index febbfa469..4b2bfd906 100644
--- a/lib/entities/biometric_auth.dart
+++ b/lib/entities/biometric_auth.dart
@@ -29,4 +29,4 @@ class BiometricAuth {
 
     return false;
   }
-}
+}
\ No newline at end of file
diff --git a/lib/locales/yoruba_intl.dart b/lib/locales/yoruba_intl.dart
index 889c21cb7..f16188529 100644
--- a/lib/locales/yoruba_intl.dart
+++ b/lib/locales/yoruba_intl.dart
@@ -955,4 +955,4 @@ String get todayLabel => 'Oyọ';
 
   @override
   String get noSpellCheckReplacementsLabel => "";
-}
+}
\ No newline at end of file
diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart
index e8c4b0ab3..74daa41cc 100644
--- a/lib/src/screens/nodes/widgets/node_form.dart
+++ b/lib/src/screens/nodes/widgets/node_form.dart
@@ -96,18 +96,20 @@ class NodeForm extends StatelessWidget {
             ],
           ),
           SizedBox(height: 10.0),
-          Row(
-            children: <Widget>[
-              Expanded(
-                child: BaseTextFormField(
-                  controller: _pathController,
-                  hintText: "/path",
-                  validator: NodePathValidator(),
-                ),
-              )
-            ],
-          ),
-          SizedBox(height: 10.0),
+          if (nodeViewModel.hasPathSupport) ...[
+            Row(
+              children: <Widget>[
+                Expanded(
+                  child: BaseTextFormField(
+                    controller: _pathController,
+                    hintText: "/path",
+                    validator: NodePathValidator(),
+                  ),
+                )
+              ],
+            ),
+            SizedBox(height: 10.0),
+          ],
           Row(
             children: <Widget>[
               Expanded(
diff --git a/lib/src/widgets/validable_annotated_editable_text.dart b/lib/src/widgets/validable_annotated_editable_text.dart
index 6c3fc4f16..16ccc76f6 100644
--- a/lib/src/widgets/validable_annotated_editable_text.dart
+++ b/lib/src/widgets/validable_annotated_editable_text.dart
@@ -167,4 +167,4 @@ class ValidatableAnnotatedEditableTextState extends EditableTextState {
 
     return TextSpan(style: widget.style, text: text);
   }
-}
+}
\ No newline at end of file
diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart
index e50f4db0c..4fb93cfea 100644
--- a/lib/view_model/auth_view_model.dart
+++ b/lib/view_model/auth_view_model.dart
@@ -125,4 +125,4 @@ abstract class AuthViewModelBase with Store {
       _authService.saveLastAuthTime();
     }
   }
-}
+}
\ No newline at end of file
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 283a32cbf..7fe3d1c98 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
@@ -69,6 +69,24 @@ abstract class NodeCreateOrEditViewModelBase with Store {
 
   bool get hasTestnetSupport => _walletType == WalletType.bitcoin;
 
+  bool get hasPathSupport {
+    switch (_walletType) {
+      case WalletType.ethereum:
+      case WalletType.polygon:
+      case WalletType.solana:
+      case WalletType.banano:
+      case WalletType.nano:
+        return true;
+      case WalletType.none:
+      case WalletType.monero:
+      case WalletType.haven:
+      case WalletType.litecoin:
+      case WalletType.bitcoinCash:
+      case WalletType.bitcoin:
+        return false;
+    }
+  }
+
   String get uri {
     var uri = address;
 
@@ -217,7 +235,6 @@ abstract class NodeCreateOrEditViewModelBase with Store {
       final port = uri.port.toString();
       final path = uri.path;
 
-
       setAddress(ipAddress);
       setPath(path);
       setPassword(rpcPassword);

From 2ac81250c24ebe84610242ac62591a3e063d974f Mon Sep 17 00:00:00 2001
From: Adegoke David <64401859+Blazebrain@users.noreply.github.com>
Date: Thu, 25 Apr 2024 02:14:11 +0100
Subject: [PATCH 3/7] CW-615-Add-Check-For-Contract-Address (#1387)

* feat: Check if address is a valid Externally Owned Address

* feat: Check if the EVM address received when exchanging tokens is a valid EOA address

* move the contract address check to be only in the case of ThorChain [skip ci]

* some enhancements

* feat: Implement check for contract address for inputAddress when exchanging to ETH

* fix: Remove previous implementation and clean up current implementation for the check for contract address

* chore: Remove unneed space

* chore: Remove unneed space

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
---
 lib/core/create_trade_result.dart             |   9 ++
 .../exchange/exchange_view_model.dart         | 120 +++++++++++++++---
 lib/view_model/send/send_view_model.dart      |   6 +-
 res/values/strings_ar.arb                     |   1 +
 res/values/strings_bg.arb                     |   1 +
 res/values/strings_cs.arb                     |   1 +
 res/values/strings_de.arb                     |   1 +
 res/values/strings_en.arb                     |   1 +
 res/values/strings_es.arb                     |   1 +
 res/values/strings_fr.arb                     |   1 +
 res/values/strings_ha.arb                     |   1 +
 res/values/strings_hi.arb                     |   1 +
 res/values/strings_hr.arb                     |   1 +
 res/values/strings_id.arb                     |   1 +
 res/values/strings_it.arb                     |   1 +
 res/values/strings_ja.arb                     |   1 +
 res/values/strings_ko.arb                     |   1 +
 res/values/strings_my.arb                     |   1 +
 res/values/strings_nl.arb                     |   1 +
 res/values/strings_pl.arb                     |   1 +
 res/values/strings_pt.arb                     |   1 +
 res/values/strings_ru.arb                     |   1 +
 res/values/strings_th.arb                     |   1 +
 res/values/strings_tl.arb                     |   1 +
 res/values/strings_tr.arb                     |   1 +
 res/values/strings_uk.arb                     |   1 +
 res/values/strings_ur.arb                     |   1 +
 res/values/strings_yo.arb                     |   1 +
 res/values/strings_zh.arb                     |   1 +
 tool/configure.dart                           |   3 +-
 30 files changed, 146 insertions(+), 18 deletions(-)
 create mode 100644 lib/core/create_trade_result.dart

diff --git a/lib/core/create_trade_result.dart b/lib/core/create_trade_result.dart
new file mode 100644
index 000000000..0e873d51e
--- /dev/null
+++ b/lib/core/create_trade_result.dart
@@ -0,0 +1,9 @@
+class CreateTradeResult {
+  bool result;
+  String? errorMessage;
+
+  CreateTradeResult({
+    required this.result,
+    this.errorMessage,
+  });
+}
diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart
index eba347ac4..4e5902faa 100644
--- a/lib/view_model/exchange/exchange_view_model.dart
+++ b/lib/view_model/exchange/exchange_view_model.dart
@@ -3,8 +3,20 @@ import 'dart:collection';
 import 'dart:convert';
 
 import 'package:bitcoin_base/bitcoin_base.dart';
-import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
+import 'package:cake_wallet/core/create_trade_result.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/sync_status.dart';
+import 'package:cw_core/transaction_priority.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:hive/hive.dart';
+import 'package:http/http.dart' as http;
+import 'package:intl/intl.dart';
+import 'package:mobx/mobx.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
 import 'package:cake_wallet/bitcoin/bitcoin.dart';
+import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
 import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
 import 'package:cake_wallet/entities/exchange_api_mode.dart';
 import 'package:cake_wallet/entities/preferences_key.dart';
@@ -33,14 +45,6 @@ import 'package:cake_wallet/store/settings_store.dart';
 import 'package:cake_wallet/store/templates/exchange_template_store.dart';
 import 'package:cake_wallet/utils/feature_flag.dart';
 import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
-import 'package:cw_core/crypto_currency.dart';
-import 'package:cw_core/sync_status.dart';
-import 'package:cw_core/transaction_priority.dart';
-import 'package:cw_core/wallet_type.dart';
-import 'package:hive/hive.dart';
-import 'package:intl/intl.dart';
-import 'package:mobx/mobx.dart';
-import 'package:shared_preferences/shared_preferences.dart';
 
 part 'exchange_view_model.g.dart';
 
@@ -516,10 +520,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
               trade.walletId = wallet.id;
               trade.fromWalletAddress = wallet.walletAddresses.address;
 
-              if (!isCanCreateTrade(trade)) {
+              final canCreateTrade = await isCanCreateTrade(trade);
+              if (!canCreateTrade.result) {
                 tradeState = TradeIsCreatedFailure(
-                    title: S.current.trade_not_created,
-                    error: S.current.thorchain_taproot_address_not_supported);
+                  title: S.current.trade_not_created,
+                  error: canCreateTrade.errorMessage ?? '',
+                );
                 return;
               }
 
@@ -776,16 +782,100 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
 
   int get receiveMaxDigits => receiveCurrency.decimals;
 
-  bool isCanCreateTrade(Trade trade) {
+  Future<CreateTradeResult> isCanCreateTrade(Trade trade) async {
     if (trade.provider == ExchangeProviderDescription.thorChain) {
       final payoutAddress = trade.payoutAddress ?? '';
       final fromWalletAddress = trade.fromWalletAddress ?? '';
       final tapRootPattern = RegExp(P2trAddress.regex.pattern);
 
       if (tapRootPattern.hasMatch(payoutAddress) || tapRootPattern.hasMatch(fromWalletAddress)) {
-        return false;
+        return CreateTradeResult(
+          result: false,
+          errorMessage: S.current.thorchain_taproot_address_not_supported,
+        );
+      }
+
+      final currenciesToCheckPattern = RegExp('0x[0-9a-zA-Z]');
+
+      // Perform checks for payOutAddress
+      final isPayOutAddressAccordingToPattern = currenciesToCheckPattern.hasMatch(payoutAddress);
+
+      if (isPayOutAddressAccordingToPattern) {
+        final isPayOutAddressEOA = await _isExternallyOwnedAccountAddress(payoutAddress);
+
+        return CreateTradeResult(
+          result: isPayOutAddressEOA,
+          errorMessage:
+              !isPayOutAddressEOA ? S.current.thorchain_contract_address_not_supported : null,
+        );
+      }
+
+      // Perform checks for fromWalletAddress
+      final isFromWalletAddressAddressAccordingToPattern =
+          currenciesToCheckPattern.hasMatch(fromWalletAddress);
+
+      if (isFromWalletAddressAddressAccordingToPattern) {
+        final isFromWalletAddressEOA = await _isExternallyOwnedAccountAddress(fromWalletAddress);
+
+        return CreateTradeResult(
+          result: isFromWalletAddressEOA,
+          errorMessage:
+              !isFromWalletAddressEOA ? S.current.thorchain_contract_address_not_supported : null,
+        );
       }
     }
-    return true;
+    return CreateTradeResult(result: true);
+  }
+
+  String _normalizeReceiveCurrency(CryptoCurrency receiveCurrency) {
+    switch (receiveCurrency) {
+      case CryptoCurrency.eth:
+        return 'eth';
+      case CryptoCurrency.maticpoly:
+        return 'polygon';
+      default:
+        return receiveCurrency.tag ?? '';
+    }
+  }
+
+  Future<bool> _isExternallyOwnedAccountAddress(String receivingAddress) async {
+    final normalizedReceiveCurrency = _normalizeReceiveCurrency(receiveCurrency);
+
+    final isEOAAddress = !(await _isContractAddress(normalizedReceiveCurrency, receivingAddress));
+    return isEOAAddress;
+  }
+
+  Future<bool> _isContractAddress(String chainName, String contractAddress) async {
+    final httpClient = http.Client();
+
+    final uri = Uri.https(
+      'deep-index.moralis.io',
+      '/api/v2.2/erc20/metadata',
+      {
+        "chain": chainName,
+        "addresses": contractAddress,
+      },
+    );
+
+    try {
+      final response = await httpClient.get(
+        uri,
+        headers: {
+          "Accept": "application/json",
+          "X-API-Key": secrets.moralisApiKey,
+        },
+      );
+
+      final decodedResponse = jsonDecode(response.body)[0] as Map<String, dynamic>;
+
+      final name = decodedResponse['name'] as String?;
+
+      bool isContractAddress = name!.isNotEmpty;
+
+      return isContractAddress;
+    } catch (e) {
+      print(e);
+      return false;
+    }
   }
 }
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 038301db4..298cc3eed 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -324,14 +324,16 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
   Future<PendingTransaction?> createTransaction({ExchangeProvider? provider}) async {
     try {
       state = IsExecutingState();
+
       pendingTransaction = await wallet.createTransaction(_credentials());
       if (provider is ThorChainExchangeProvider) {
         final outputCount = pendingTransaction?.outputCount ?? 0;
         if (outputCount > 10) {
-          throw Exception("ThorChain does not support more than 10 outputs");
+          throw Exception("THORChain does not support more than 10 outputs");
         }
+
         if (_hasTaprootInput(pendingTransaction)) {
-          throw Exception("ThorChain does not support Taproot addresses");
+          throw Exception("THORChain does not support Taproot addresses");
         }
       }
       state = ExecutedSuccessfullyState();
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index 15b9712fc..cf9959f17 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -660,6 +660,7 @@
   "template_name": "اسم القالب",
   "third_intro_content": "يعيش Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة على وجه الأرض بـ Yat!",
   "third_intro_title": "يتماشي Yat بلطف مع الآخرين",
+  "thorchain_contract_address_not_supported": "لا يدعم Thorchain الإرسال إلى عنوان العقد",
   "thorchain_taproot_address_not_supported": "لا يدعم مزود Thorchain عناوين Taproot. يرجى تغيير العنوان أو تحديد مزود مختلف.",
   "time": "${minutes}د ${seconds}س",
   "tip": "بقشيش:",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index d479bd57d..bd1cd645d 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -660,6 +660,7 @@
   "template_name": "Име на шаблон",
   "third_intro_content": "Yats също живее извън Cake Wallet. Всеки адрес на портфейл може да бъде заменен с Yat!",
   "third_intro_title": "Yat добре се сработва с други",
+  "thorchain_contract_address_not_supported": "Thorchain не подкрепя изпращането до адрес на договор",
   "thorchain_taproot_address_not_supported": "Доставчикът на Thorchain не поддържа адреси на TapRoot. Моля, променете адреса или изберете друг доставчик.",
   "time": "${minutes} мин ${seconds} сек",
   "tip": "Tip:",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index 547c926af..4d3458bec 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -660,6 +660,7 @@
   "template_name": "Název šablony",
   "third_intro_content": "Yat existuje i mimo Cake Wallet. Jakákoliv adresa peněženky na světě může být nahrazena Yatem!",
   "third_intro_title": "Yat dobře spolupracuje s ostatními",
+  "thorchain_contract_address_not_supported": "Thorchain nepodporuje odeslání na adresu smlouvy",
   "thorchain_taproot_address_not_supported": "Poskytovatel Thorchain nepodporuje adresy Taproot. Změňte adresu nebo vyberte jiného poskytovatele.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Spropitné:",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 97f2ccdc2..7efb0b682 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -661,6 +661,7 @@
   "template_name": "Vorlagenname",
   "third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!",
   "third_intro_title": "Yat spielt gut mit anderen",
+  "thorchain_contract_address_not_supported": "Thorchain unterstützt das Senden an eine Vertragsadresse nicht",
   "thorchain_taproot_address_not_supported": "Der Thorchain -Anbieter unterstützt keine Taproot -Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Hinweis:",
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index 60de404fd..8f8b753d6 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -660,6 +660,7 @@
   "template_name": "Template Name",
   "third_intro_content": "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!",
   "third_intro_title": "Yat plays nicely with others",
+  "thorchain_contract_address_not_supported": "THORChain does not support sending to a contract address",
   "thorchain_taproot_address_not_supported": "The ThorChain provider does not support Taproot addresses. Please change the address or select a different provider.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Tip:",
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 60cac3a8c..7de9cff53 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -661,6 +661,7 @@
   "template_name": "Nombre de la plantilla",
   "third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!",
   "third_intro_title": "Yat juega muy bien con otras",
+  "thorchain_contract_address_not_supported": "Thorchain no admite enviar a una dirección de contrato",
   "thorchain_taproot_address_not_supported": "El proveedor de Thorchain no admite las direcciones de Taproot. Cambie la dirección o seleccione un proveedor diferente.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Consejo:",
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index 691c481c1..2c76122fc 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -660,6 +660,7 @@
   "template_name": "Nom du modèle",
   "third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !",
   "third_intro_title": "Yat est universel",
+  "thorchain_contract_address_not_supported": "Thorchain ne prend pas en charge l'envoi à une adresse de contrat",
   "thorchain_taproot_address_not_supported": "Le fournisseur de Thorchain ne prend pas en charge les adresses de tapoot. Veuillez modifier l'adresse ou sélectionner un autre fournisseur.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Pourboire :",
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index f310f67f3..bac970207 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -662,6 +662,7 @@
   "template_name": "Sunan Samfura",
   "third_intro_content": "Yats suna zaune a wajen Kek Wallet, kuma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!",
   "third_intro_title": "Yat yana wasa da kyau tare da wasu",
+  "thorchain_contract_address_not_supported": "Thorchain baya goyon bayan aika zuwa adireshin kwangila",
   "thorchain_taproot_address_not_supported": "Mai ba da tallafi na ThorChain baya goyan bayan adreshin taproot. Da fatan za a canza adireshin ko zaɓi mai bayarwa daban.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Tukwici:",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index 671c7a765..5a9706bd5 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -662,6 +662,7 @@
   "template_name": "टेम्पलेट नाम",
   "third_intro_content": "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!",
   "third_intro_title": "Yat दूसरों के साथ अच्छा खेलता है",
+  "thorchain_contract_address_not_supported": "थोरचेन एक अनुबंध पते पर भेजने का समर्थन नहीं करता है",
   "thorchain_taproot_address_not_supported": "थोरचेन प्रदाता टैपरोट पते का समर्थन नहीं करता है। कृपया पता बदलें या एक अलग प्रदाता का चयन करें।",
   "time": "${minutes}m ${seconds}s",
   "tip": "टिप:",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 67e25d59a..94f675a1d 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -660,6 +660,7 @@
   "template_name": "Naziv predloška",
   "third_intro_content": "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!",
   "third_intro_title": "Yat se lijepo igra s drugima",
+  "thorchain_contract_address_not_supported": "Thorchain ne podržava slanje na adresu ugovora",
   "thorchain_taproot_address_not_supported": "Thorchain pružatelj ne podržava Taproot adrese. Promijenite adresu ili odaberite drugog davatelja usluga.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Savjet:",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index cca6f9b2a..69e270d10 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -663,6 +663,7 @@
   "template_name": "Nama Templat",
   "third_intro_content": "Yats hidup di luar Cake Wallet juga. Setiap alamat dompet di dunia dapat diganti dengan Yat!",
   "third_intro_title": "Yat bermain baik dengan yang lain",
+  "thorchain_contract_address_not_supported": "Thorchain tidak mendukung pengiriman ke alamat kontrak",
   "thorchain_taproot_address_not_supported": "Penyedia Thorchain tidak mendukung alamat Taproot. Harap ubah alamatnya atau pilih penyedia yang berbeda.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Tip:",
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index 4e04c0498..09b3e43bb 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -662,6 +662,7 @@
   "template_name": "Nome modello",
   "third_intro_content": "Yat può funzionare anche fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con uno Yat!",
   "third_intro_title": "Yat gioca bene con gli altri",
+  "thorchain_contract_address_not_supported": "Thorchain non supporta l'invio a un indirizzo contrattuale",
   "thorchain_taproot_address_not_supported": "Il provider di Thorchain non supporta gli indirizzi di TapRoot. Si prega di modificare l'indirizzo o selezionare un fornitore diverso.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Suggerimento:",
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index b3aa527d6..b067c2721 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -661,6 +661,7 @@
   "template_name": "テンプレート名",
   "third_intro_content": "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!",
   "third_intro_title": "Yatは他の人とうまく遊ぶ",
+  "thorchain_contract_address_not_supported": "Thorchainは、契約アドレスへの送信をサポートしていません",
   "thorchain_taproot_address_not_supported": "Thorchainプロバイダーは、TapRootアドレスをサポートしていません。アドレスを変更するか、別のプロバイダーを選択してください。",
   "time": "${minutes}m ${seconds}s",
   "tip": "ヒント: ",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 6c5800614..d9881ad04 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -661,6 +661,7 @@
   "template_name": "템플릿 이름",
   "third_intro_content": "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!",
   "third_intro_title": "Yat는 다른 사람들과 잘 놉니다.",
+  "thorchain_contract_address_not_supported": "Thorchain은 계약 주소로 보내는 것을 지원하지 않습니다",
   "thorchain_taproot_address_not_supported": "Thorchain 제공 업체는 Taproot 주소를 지원하지 않습니다. 주소를 변경하거나 다른 공급자를 선택하십시오.",
   "time": "${minutes}m ${seconds}s",
   "tip": "팁:",
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index 96f141eae..c36f63414 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -660,6 +660,7 @@
   "template_name": "နမူနာပုံစံ",
   "third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင် နေထိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့်ပိုက်ဆံအိတ်လိပ်စာကို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။",
   "third_intro_title": "Yat သည် အခြားသူများနှင့် ကောင်းစွာကစားသည်။",
+  "thorchain_contract_address_not_supported": "Thorchain သည်စာချုပ်လိပ်စာသို့ပို့ခြင်းမပြုပါ",
   "thorchain_taproot_address_not_supported": "Thorchain Provider သည် Taproot လိပ်စာများကိုမထောက်ခံပါ။ ကျေးဇူးပြု. လိပ်စာကိုပြောင်းပါသို့မဟုတ်အခြားပံ့ပိုးပေးသူကိုရွေးချယ်ပါ။",
   "time": "${minutes}m ${seconds}s",
   "tip": "အကြံပြုချက်-",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 1ce17f706..f258b8f62 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -660,6 +660,7 @@
   "template_name": "Sjabloonnaam",
   "third_intro_content": "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!",
   "third_intro_title": "Yat speelt leuk met anderen",
+  "thorchain_contract_address_not_supported": "Thorchain ondersteunt het verzenden niet naar een contractadres",
   "thorchain_taproot_address_not_supported": "De Thorchain -provider ondersteunt geen Taprooot -adressen. Wijzig het adres of selecteer een andere provider.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Tip:",
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index f48ad5dde..4627d0242 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -660,6 +660,7 @@
   "template_name": "Nazwa szablonu",
   "third_intro_content": "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!",
   "third_intro_title": "Yat ładnie bawi się z innymi",
+  "thorchain_contract_address_not_supported": "Thorchain nie wspiera wysyłania na adres umowy",
   "thorchain_taproot_address_not_supported": "Dostawca Thorchain nie obsługuje adresów TAPROOT. Zmień adres lub wybierz innego dostawcę.",
   "time": "${minutes}m ${seconds}s",
   "tip": "wskazówka:",
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index 15cc9f01e..2a781c76b 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -662,6 +662,7 @@
   "template_name": "Nome do modelo",
   "third_intro_content": "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!",
   "third_intro_title": "Yat joga bem com os outros",
+  "thorchain_contract_address_not_supported": "Thorchain não suporta o envio para um endereço de contrato",
   "thorchain_taproot_address_not_supported": "O provedor de Thorchain não suporta endereços de raiz de Tap. Altere o endereço ou selecione um provedor diferente.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Dica:",
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index ac0fac2ba..22bac3e33 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -661,6 +661,7 @@
   "template_name": "Имя Шаблона",
   "third_intro_content": "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!",
   "third_intro_title": "Yat хорошо взаимодействует с другими",
+  "thorchain_contract_address_not_supported": "Thorchain не поддерживает отправку на адрес контракта",
   "thorchain_taproot_address_not_supported": "Поставщик Thorchain не поддерживает адреса taproot. Пожалуйста, измените адрес или выберите другого поставщика.",
   "time": "${minutes}мин ${seconds}сек",
   "tip": "Совет:",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index 7030f6f7f..c0f58495c 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -660,6 +660,7 @@
   "template_name": "ชื่อแม่แบบ",
   "third_intro_content": "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!",
   "third_intro_title": "Yat ปฏิบัติตนอย่างดีกับผู้อื่น",
+  "thorchain_contract_address_not_supported": "Thorchain ไม่สนับสนุนการส่งไปยังที่อยู่สัญญา",
   "thorchain_taproot_address_not_supported": "ผู้ให้บริการ Thorchain ไม่รองรับที่อยู่ taproot โปรดเปลี่ยนที่อยู่หรือเลือกผู้ให้บริการอื่น",
   "time": "${minutes}m ${seconds}s",
   "tip": "เพิ่มค่าตอบแทน:",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index 05a363bac..8c3b13b3b 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -660,6 +660,7 @@
   "template_name": "Pangalan ng Template",
   "third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!",
   "third_intro_title": "Si Yat ay mahusay na gumaganap sa iba",
+  "thorchain_contract_address_not_supported": "Hindi sinusuportahan ng Thorchain ang pagpapadala sa isang address ng kontrata",
   "thorchain_taproot_address_not_supported": "Ang Tagabigay ng Thorchain ay hindi sumusuporta sa mga address ng taproot. Mangyaring baguhin ang address o pumili ng ibang provider.",
   "time": "${minutes} m ${seconds} s",
   "tip": "Tip:",
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index ce342df2f..534a36c77 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -660,6 +660,7 @@
   "template_name": "şablon adı",
   "third_intro_content": "Yat'lar Cake Wallet'ın dışında da çalışabilir. Dünya üzerindeki herhangi bir cüzdan adresi Yat ile değiştirilebilir!",
   "third_intro_title": "Yat diğerleriyle iyi çalışır",
+  "thorchain_contract_address_not_supported": "Thorchain bir sözleşme adresine göndermeyi desteklemiyor",
   "thorchain_taproot_address_not_supported": "Thorchain sağlayıcısı Taproot adreslerini desteklemiyor. Lütfen adresi değiştirin veya farklı bir sağlayıcı seçin.",
   "time": "${minutes}d ${seconds}s",
   "tip": "Bahşiş:",
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index 4afd47fe2..5d1e2be05 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -661,6 +661,7 @@
   "template_name": "Назва шаблону",
   "third_intro_content": "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!",
   "third_intro_title": "Yat добре взаємодіє з іншими",
+  "thorchain_contract_address_not_supported": "Thorchain не підтримує надсилання на адресу контракту",
   "thorchain_taproot_address_not_supported": "Постачальник Thorchain не підтримує адреси Taproot. Будь ласка, змініть адресу або виберіть іншого постачальника.",
   "time": "${minutes}хв ${seconds}сек",
   "tip": "Порада:",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index fac066ace..d98a85753 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -662,6 +662,7 @@
   "template_name": "ٹیمپلیٹ کا نام",
   "third_intro_content": "Yats بھی Cake والیٹ سے باہر رہتے ہیں۔ زمین پر کسی بھی بٹوے کے پتے کو Yat سے تبدیل کیا جا سکتا ہے!",
   "third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح کھیلتا ہے۔",
+  "thorchain_contract_address_not_supported": "تھورچین معاہدے کے پتے بھیجنے کی حمایت نہیں کرتا ہے",
   "thorchain_taproot_address_not_supported": "تھورچین فراہم کنندہ ٹیپروٹ پتے کی حمایت نہیں کرتا ہے۔ براہ کرم پتہ تبدیل کریں یا ایک مختلف فراہم کنندہ کو منتخب کریں۔",
   "time": "${minutes}m ${seconds}s",
   "tip": "ٹپ:",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 1f131f3d9..faaeb8837 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -661,6 +661,7 @@
   "template_name": "Orukọ Awoṣe",
   "third_intro_content": "A sì lè lo Yats níta Cake Wallet. A lè rọ́pò Àdírẹ́sì kankan àpamọ́wọ́ fún Yat!",
   "third_intro_title": "Àlàáfíà ni Yat àti àwọn ìmíìn jọ wà",
+  "thorchain_contract_address_not_supported": "Thorchain ko ṣe atilẹyin fifiranṣẹ si adirẹsi adehun kan",
   "thorchain_taproot_address_not_supported": "Olupese Trockchain ko ṣe atilẹyin awọn adirẹsi Taproot. Jọwọ yi adirẹsi pada tabi yan olupese ti o yatọ.",
   "time": "${minutes}ìṣj ${seconds}ìṣs",
   "tip": "Owó àfikún:",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index 10d11b2c0..2d5251d86 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -660,6 +660,7 @@
   "template_name": "模板名称",
   "third_intro_content": "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!",
   "third_intro_title": "Yat 和別人玩得很好",
+  "thorchain_contract_address_not_supported": "Thorchain不支持发送到合同地址",
   "thorchain_taproot_address_not_supported": "Thorchain提供商不支持Taproot地址。请更改地址或选择其他提供商。",
   "time": "${minutes}m ${seconds}s",
   "tip": "提示:",
diff --git a/tool/configure.dart b/tool/configure.dart
index 6ee84d63a..d08724e42 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -1057,7 +1057,8 @@ Future<void> generatePubspec(
   final inputFile = File(pubspecOutputPath);
   final inputText = await inputFile.readAsString();
   final inputLines = inputText.split('\n');
-  final dependenciesIndex = inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:'));
+  final dependenciesIndex =
+      inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:'));
   var output = cwCore;
 
   if (hasMonero) {

From fff77519d9cd889b5a17705a1488611640378e33 Mon Sep 17 00:00:00 2001
From: Adegoke David <64401859+Blazebrain@users.noreply.github.com>
Date: Thu, 25 Apr 2024 02:14:53 +0100
Subject: [PATCH 4/7] Generic Fixes: Support Errors and others (#1394)

* fix: Crypto amout formatting when calculating fiat amount

* fix: Issue with some token symbols coming up with a dollar sign

* feat: Split transactions to display on history screen token byh token

* fix: Remove restriction on balance length

* fix: error when a particular token is not available

* fix: Remove token transactions when a token is deleted

* fix: Revert previous change

* make added spl tokens enabled by default
fix issue when entering invalid contract address

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
---
 cw_core/lib/crypto_currency.dart           |  2 +-
 cw_evm/lib/evm_chain_client.dart           |  7 ++-
 cw_evm/lib/evm_chain_wallet.dart           |  6 +++
 cw_solana/lib/solana_transaction_info.dart |  5 +--
 cw_solana/lib/solana_wallet.dart           | 52 +++++++++++-----------
 cw_solana/lib/spl_token.dart               |  4 +-
 lib/entities/calculate_fiat_amount.dart    |  2 +
 lib/ethereum/cw_ethereum.dart              |  6 ++-
 lib/polygon/cw_polygon.dart                |  4 +-
 lib/solana/cw_solana.dart                  |  6 ++-
 10 files changed, 54 insertions(+), 40 deletions(-)

diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart
index f1c1cd8ae..a7edd409f 100644
--- a/cw_core/lib/crypto_currency.dart
+++ b/cw_core/lib/crypto_currency.dart
@@ -10,7 +10,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
     this.fullName,
     this.iconPath,
     this.tag,
-    this.enabled = false,
+    this.enabled = true,
     })
       : super(title: title, raw: raw);
 
diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart
index eebbe4f4f..8f0df3926 100644
--- a/cw_evm/lib/evm_chain_client.dart
+++ b/cw_evm/lib/evm_chain_client.dart
@@ -234,14 +234,17 @@ abstract class EVMChainClient {
 
       final decodedResponse = jsonDecode(response.body)[0] as Map<String, dynamic>;
 
+
+      final symbol = (decodedResponse['symbol'] ?? '') as String;
+      String filteredSymbol = symbol.replaceFirst(RegExp('^\\\$'), '');
+
       final name = decodedResponse['name'] ?? '';
-      final symbol = decodedResponse['symbol'] ?? '';
       final decimal = decodedResponse['decimals'] ?? '0';
       final iconPath = decodedResponse['logo'] ?? '';
 
       return Erc20Token(
         name: name,
-        symbol: symbol,
+        symbol: filteredSymbol,
         contractAddress: contractAddress,
         decimal: int.tryParse(decimal) ?? 0,
         iconPath: iconPath,
diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart
index 4193e590a..558013252 100644
--- a/cw_evm/lib/evm_chain_wallet.dart
+++ b/cw_evm/lib/evm_chain_wallet.dart
@@ -468,9 +468,15 @@ abstract class EVMChainWalletBase
     await token.delete();
 
     balance.remove(token);
+    await _removeTokenTransactionsInHistory(token);
     _updateBalance();
   }
 
+  Future<void> _removeTokenTransactionsInHistory(Erc20Token token) async {
+    transactionHistory.transactions.removeWhere((key, value) => value.tokenSymbol == token.title);
+    await transactionHistory.save();
+  }
+
   Future<Erc20Token?> getErc20Token(String contractAddress, String chainName) async =>
       await _client.getErc20Token(contractAddress, chainName);
 
diff --git a/cw_solana/lib/solana_transaction_info.dart b/cw_solana/lib/solana_transaction_info.dart
index 1b7610e34..7a0844e52 100644
--- a/cw_solana/lib/solana_transaction_info.dart
+++ b/cw_solana/lib/solana_transaction_info.dart
@@ -34,10 +34,7 @@ class SolanaTransactionInfo extends TransactionInfo {
   @override
   String amountFormatted() {
     String stringBalance = solAmount.toString();
-
-    if (stringBalance.toString().length >= 6) {
-      stringBalance = stringBalance.substring(0, 6);
-    }
+    
     return '$stringBalance $tokenSymbol';
   }
 
diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart
index 43a6d0b83..f3eef465c 100644
--- a/cw_solana/lib/solana_wallet.dart
+++ b/cw_solana/lib/solana_wallet.dart
@@ -273,32 +273,12 @@ abstract class SolanaWalletBase
 
     final transactions = await _client.fetchTransactions(address);
 
-    final Map<String, SolanaTransactionInfo> result = {};
-
-    for (var transactionModel in transactions) {
-      result[transactionModel.id] = SolanaTransactionInfo(
-        id: transactionModel.id,
-        to: transactionModel.to,
-        from: transactionModel.from,
-        blockTime: transactionModel.blockTime,
-        direction: transactionModel.isOutgoingTx
-            ? TransactionDirection.outgoing
-            : TransactionDirection.incoming,
-        solAmount: transactionModel.amount,
-        isPending: false,
-        txFee: transactionModel.fee,
-        tokenSymbol: transactionModel.tokenSymbol,
-      );
-    }
-
-    transactionHistory.addMany(result);
-
-    await transactionHistory.save();
+    await _addTransactionsToTransactionHistory(transactions);
   }
 
   /// Fetches the SPL Tokens transactions linked to the token account Public Key
   Future<void> _updateSPLTokenTransactions() async {
-    List<SolanaTransactionModel> splTokenTransactions = [];
+    // List<SolanaTransactionModel> splTokenTransactions = [];
 
     // Make a copy of keys to avoid concurrent modification
     var tokenKeys = List<CryptoCurrency>.from(balance.keys);
@@ -312,13 +292,20 @@ abstract class SolanaWalletBase
           _walletKeyPair!,
         );
 
-        splTokenTransactions.addAll(tokenTxs);
+        // splTokenTransactions.addAll(tokenTxs);
+        await _addTransactionsToTransactionHistory(tokenTxs);
       }
     }
 
+    // await _addTransactionsToTransactionHistory(splTokenTransactions);
+  }
+
+  Future<void> _addTransactionsToTransactionHistory(
+    List<SolanaTransactionModel> transactions,
+  ) async {
     final Map<String, SolanaTransactionInfo> result = {};
 
-    for (var transactionModel in splTokenTransactions) {
+    for (var transactionModel in transactions) {
       result[transactionModel.id] = SolanaTransactionInfo(
         id: transactionModel.id,
         to: transactionModel.to,
@@ -460,12 +447,23 @@ abstract class SolanaWalletBase
     await token.delete();
 
     balance.remove(token);
+    await _removeTokenTransactionsInHistory(token);
     _updateBalance();
   }
 
+  Future<void> _removeTokenTransactionsInHistory(SPLToken token) async {
+    transactionHistory.transactions.removeWhere((key, value) => value.tokenSymbol == token.title);
+    await transactionHistory.save();
+  }
+
   Future<SPLToken?> getSPLToken(String mintAddress) async {
     // Convert SPL token mint address to public key
-    final mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress);
+    final Ed25519HDPublicKey mintPublicKey;
+    try {
+      mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress);
+    } catch (_) {
+      return null;
+    }
 
     // Fetch token's metadata account
     try {
@@ -480,10 +478,12 @@ abstract class SolanaWalletBase
         iconPath = await _client.getIconImageFromTokenUri(token.uri);
       } catch (_) {}
 
+      String filteredTokenSymbol = token.symbol.replaceFirst(RegExp('^\\\$'), '');
+
       return SPLToken.fromMetadata(
         name: token.name,
         mint: token.mint,
-        symbol: token.symbol,
+        symbol: filteredTokenSymbol,
         mintAddress: mintAddress,
         iconPath: iconPath,
       );
diff --git a/cw_solana/lib/spl_token.dart b/cw_solana/lib/spl_token.dart
index 0b3b8b372..a40eb0b86 100644
--- a/cw_solana/lib/spl_token.dart
+++ b/cw_solana/lib/spl_token.dart
@@ -19,7 +19,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin {
   @HiveField(3)
   final int decimal;
 
-  @HiveField(4, defaultValue: false)
+  @HiveField(4, defaultValue: true)
   bool _enabled;
 
   @HiveField(5)
@@ -39,7 +39,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin {
     required this.mint,
     this.iconPath,
     this.tag = 'SOL',
-    bool enabled = false,
+    bool enabled = true,
   })  : _enabled = enabled,
         super(
           name: mint.toLowerCase(),
diff --git a/lib/entities/calculate_fiat_amount.dart b/lib/entities/calculate_fiat_amount.dart
index 689ada31b..b0b38eacb 100644
--- a/lib/entities/calculate_fiat_amount.dart
+++ b/lib/entities/calculate_fiat_amount.dart
@@ -3,6 +3,8 @@ String calculateFiatAmount({double? price, String? cryptoAmount}) {
     return '0.00';
   }
 
+  cryptoAmount = cryptoAmount.replaceAll(',', '.');
+  
   final _amount = double.parse(cryptoAmount);
   final _result = price * _amount;
   final result = _result < 0 ? _result * -1 : _result;
diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart
index 13fe3aafd..61d5b6ae3 100644
--- a/lib/ethereum/cw_ethereum.dart
+++ b/lib/ethereum/cw_ethereum.dart
@@ -142,8 +142,10 @@ class CWEthereum extends Ethereum {
     }
 
     wallet as EthereumWallet;
-    return wallet.erc20Currencies
-        .firstWhere((element) => transaction.tokenSymbol == element.symbol);
+
+    return wallet.erc20Currencies.firstWhere(
+      (element) => transaction.tokenSymbol == element.symbol,
+    );
   }
 
   @override
diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart
index 9f0f9a1bf..5baf4fbbc 100644
--- a/lib/polygon/cw_polygon.dart
+++ b/lib/polygon/cw_polygon.dart
@@ -140,8 +140,10 @@ class CWPolygon extends Polygon {
     }
 
     wallet as PolygonWallet;
+
     return wallet.erc20Currencies.firstWhere(
-        (element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase());
+      (element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase(),
+    );
   }
 
   @override
diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart
index 6f4b17309..af66cf3e5 100644
--- a/lib/solana/cw_solana.dart
+++ b/lib/solana/cw_solana.dart
@@ -110,8 +110,10 @@ class CWSolana extends Solana {
     }
 
     wallet as SolanaWallet;
-    return wallet.splTokenCurrencies
-        .firstWhere((element) => transaction.tokenSymbol == element.symbol);
+
+    return wallet.splTokenCurrencies.firstWhere(
+      (element) => transaction.tokenSymbol == element.symbol,
+    );
   }
 
   @override

From 3732a4c646c2affe228b055a73e560143f8c5216 Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Thu, 25 Apr 2024 05:52:24 -0500
Subject: [PATCH 5/7] Language Fixes for DE (#1409)

---
 lib/buy/dfx/dfx_buy_provider.dart |  4 ++--
 lib/entities/provider_types.dart  |  2 +-
 res/values/strings_de.arb         | 18 +++++++++---------
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart
index 8e2d58d11..b5c5d3b02 100644
--- a/lib/buy/dfx/dfx_buy_provider.dart
+++ b/lib/buy/dfx/dfx_buy_provider.dart
@@ -23,7 +23,7 @@ class DFXBuyProvider extends BuyProvider {
   static const walletName = 'CakeWallet';
 
   @override
-  String get title => 'DFX Connect';
+  String get title => 'DFX.swiss';
 
   @override
   String get providerDescription => S.current.dfx_option_description;
@@ -198,7 +198,7 @@ class DFXBuyProvider extends BuyProvider {
           context: context,
           builder: (BuildContext context) {
             return AlertWithOneAction(
-                alertTitle: "DFX Connect",
+                alertTitle: "DFX.swiss",
                 alertContent: S.of(context).buy_provider_unavailable + ': $e',
                 buttonText: S.of(context).ok,
                 buttonAction: () => Navigator.of(context).pop());
diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart
index 701781cc2..ca168a299 100644
--- a/lib/entities/provider_types.dart
+++ b/lib/entities/provider_types.dart
@@ -22,7 +22,7 @@ extension ProviderTypeName on ProviderType {
       case ProviderType.robinhood:
         return 'Robinhood Connect';
       case ProviderType.dfx:
-        return 'DFX Connect';
+        return 'DFX.swiss';
       case ProviderType.onramper:
         return 'Onramper';
       case ProviderType.moonpay:
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 7efb0b682..0546140eb 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -50,7 +50,7 @@
   "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.",
   "apk_update": "APK-Update",
   "approve": "Genehmigen",
-  "arrive_in_this_address": "${currency} ${tag}wird an dieser Adresse ankommen",
+  "arrive_in_this_address": "${currency} ${tag} wird an dieser Adresse ankommen",
   "ascending": "Aufsteigend",
   "ask_each_time": "Jedes Mal fragen",
   "auth_store_ban_timeout": "ban_timeout",
@@ -87,7 +87,7 @@
   "buy_provider_unavailable": "Anbieter derzeit nicht verfügbar.",
   "buy_with": "Kaufen mit",
   "by_cake_pay": "von Cake Pay",
-  "cake_2fa_preset": "Kuchen 2FA-Voreinstellung",
+  "cake_2fa_preset": "Cake 2FA-Voreinstellung",
   "cake_dark_theme": "Cake Dark Thema",
   "cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!",
   "cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.",
@@ -120,7 +120,7 @@
   "change_wallet_alert_title": "Aktuelle Wallet ändern",
   "choose_account": "Konto auswählen",
   "choose_address": "\n\nBitte wählen Sie die Adresse:",
-  "choose_derivation": "Wählen Sie Brieftaschenableitung",
+  "choose_derivation": "Wählen Sie Wallet-Ableitung",
   "choose_from_available_options": "Wähle aus verfügbaren Optionen:",
   "choose_one": "Wähle ein",
   "choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus",
@@ -199,7 +199,7 @@
   "disable_fiat": "Fiat deaktivieren",
   "disable_sell": "Verkaufsaktion deaktivieren",
   "disableBatteryOptimization": "Batterieoptimierung deaktivieren",
-  "disableBatteryOptimizationDescription": "Möchten Sie die Batterieoptimierung deaktivieren, um die Hintergrundsynchronisierung freier und reibungsloser zu gestalten?",
+  "disableBatteryOptimizationDescription": "Möchten Sie die Batterieoptimierung deaktivieren, um die Hintergrundsynchronisierung reibungsloser zu gestalten?",
   "disabled": "Deaktiviert",
   "discount": "${value} % sparen",
   "display_settings": "Anzeigeeinstellungen",
@@ -459,8 +459,8 @@
   "reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?",
   "reconnection": "Neu verbinden",
   "red_dark_theme": "Red Dark Thema",
-  "red_light_theme": "Rotlichtthema",
-  "redeemed": "Versilbert",
+  "red_light_theme": "Red Light Thema",
+  "redeemed": "Eingelöst",
   "refund_address": "Rückerstattungsadresse",
   "reject": "Ablehnen",
   "remaining": "Rest",
@@ -532,7 +532,7 @@
   "seed_alert_title": "Achtung",
   "seed_alert_yes": "Ja, habe ich",
   "seed_choose": "Seed-Sprache auswählen",
-  "seed_hex_form": "Brieftaschensamen (Sechskantform)",
+  "seed_hex_form": "Seed (Hexformat)",
   "seed_key": "Seed-Schlüssel",
   "seed_language": "Seed-Sprache",
   "seed_language_chinese": "Chinesisch",
@@ -584,7 +584,7 @@
   "send_your_wallet": "Ihre Wallet",
   "sending": "Senden",
   "sent": "Versendet",
-  "service_health_disabled": "Service Health Bulletin ist behindert",
+  "service_health_disabled": "Service Health Bulletin ist deaktiviert",
   "service_health_disabled_message": "Dies ist die Seite \"Service Health Bulletin\", können Sie diese Seite unter Einstellungen -> Privatsphäre aktivieren",
   "settings": "Einstellungen",
   "settings_all": "ALLE",
@@ -822,4 +822,4 @@
   "you_will_get": "Konvertieren zu",
   "you_will_send": "Konvertieren von",
   "yy": "YY"
-}
\ No newline at end of file
+}

From 190c8e06b9c2121e4694ccdd048b3daf61f99270 Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Thu, 25 Apr 2024 06:06:11 -0500
Subject: [PATCH 6/7] Use the latest version of the DFX Auth Api to minimize
 the number of API calls (#1410)

---
 lib/buy/dfx/dfx_buy_provider.dart | 76 +++++++++----------------------
 1 file changed, 21 insertions(+), 55 deletions(-)

diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart
index b5c5d3b02..bf67edd23 100644
--- a/lib/buy/dfx/dfx_buy_provider.dart
+++ b/lib/buy/dfx/dfx_buy_provider.dart
@@ -17,9 +17,8 @@ class DFXBuyProvider extends BuyProvider {
       : super(wallet: wallet, isTestEnvironment: isTestEnvironment);
 
   static const _baseUrl = 'api.dfx.swiss';
-  static const _authPath = '/v1/auth/signMessage';
-  static const _signUpPath = '/v1/auth/signUp';
-  static const _signInPath = '/v1/auth/signIn';
+  // static const _signMessagePath = '/v1/auth/signMessage';
+  static const _authPath = '/v1/auth';
   static const walletName = 'CakeWallet';
 
   @override
@@ -73,21 +72,25 @@ class DFXBuyProvider extends BuyProvider {
   String get walletAddress =>
       wallet.walletAddresses.primaryAddress ?? wallet.walletAddresses.address;
 
-  Future<String> getSignMessage() async {
-    final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress});
+  Future<String> getSignMessage() async =>
+      "By_signing_this_message,_you_confirm_that_you_are_the_sole_owner_of_the_provided_Blockchain_address._Your_ID:_$walletAddress";
 
-    var response = await http.get(uri, headers: {'accept': 'application/json'});
+  // // Lets keep this just in case, but we can avoid this API Call
+  // Future<String> getSignMessage() async {
+  //  final uri = Uri.https(_baseUrl, _signMessagePath, {'address': walletAddress});
+  //
+  //  final response = await http.get(uri, headers: {'accept': 'application/json'});
+  //
+  //  if (response.statusCode == 200) {
+  //    final responseBody = jsonDecode(response.body);
+  //    return responseBody['message'] as String;
+  //  } else {
+  //    throw Exception(
+  //      'Failed to get sign message. Status: ${response.statusCode} ${response.body}');
+  //  }
+  // }
 
-    if (response.statusCode == 200) {
-      final responseBody = jsonDecode(response.body);
-      return responseBody['message'] as String;
-    } else {
-      throw Exception(
-          'Failed to get sign message. Status: ${response.statusCode} ${response.body}');
-    }
-  }
-
-  Future<String> signUp() async {
+  Future<String> auth() async {
     final signMessage = getSignature(await getSignMessage());
 
     final requestBody = jsonEncode({
@@ -96,7 +99,7 @@ class DFXBuyProvider extends BuyProvider {
       'signature': signMessage,
     });
 
-    final uri = Uri.https(_baseUrl, _signUpPath);
+    final uri = Uri.https(_baseUrl, _authPath);
     var response = await http.post(
       uri,
       headers: {'Content-Type': 'application/json'},
@@ -115,33 +118,6 @@ class DFXBuyProvider extends BuyProvider {
     }
   }
 
-  Future<String> signIn() async {
-    final signMessage = getSignature(await getSignMessage());
-
-    final requestBody = jsonEncode({
-      'address': walletAddress,
-      'signature': signMessage,
-    });
-
-    final uri = Uri.https(_baseUrl, _signInPath);
-    var response = await http.post(
-      uri,
-      headers: {'Content-Type': 'application/json'},
-      body: requestBody,
-    );
-
-    if (response.statusCode == 201) {
-      final responseBody = jsonDecode(response.body);
-      return responseBody['accessToken'] as String;
-    } else if (response.statusCode == 403) {
-      final responseBody = jsonDecode(response.body);
-      final message = responseBody['message'] ?? 'Service unavailable in your country';
-      throw Exception(message);
-    } else {
-      throw Exception('Failed to sign in. Status: ${response.statusCode} ${response.body}');
-    }
-  }
-
   String getSignature(String message) {
     switch (wallet.type) {
       case WalletType.ethereum:
@@ -164,17 +140,7 @@ class DFXBuyProvider extends BuyProvider {
       final blockchain = this.blockchain;
       final actionType = isBuyAction == true ? '/buy' : '/sell';
 
-      String accessToken;
-
-      try {
-        accessToken = await signUp();
-      } on Exception catch (e) {
-        if (e.toString().contains('409')) {
-          accessToken = await signIn();
-        } else {
-          rethrow;
-        }
-      }
+      final accessToken = await auth();
 
       final uri = Uri.https('services.dfx.swiss', actionType, {
         'session': accessToken,

From 9ff6da3d5d2db04069deed46c35a15e4138d777e Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Thu, 25 Apr 2024 19:28:18 +0300
Subject: [PATCH 7/7] dynamic max fee rate value (#1395)

---
 lib/bitcoin/cw_bitcoin.dart                   |  6 ++++
 lib/src/screens/send/widgets/send_card.dart   |  2 ++
 .../screens/settings/other_settings_page.dart |  1 +
 .../widgets/setting_priority_picker_cell.dart |  3 ++
 .../rbf_details_list_fee_picker_item.dart     |  2 ++
 .../transaction_details/rbf_details_page.dart |  1 +
 lib/src/widgets/picker.dart                   | 28 +++++++++++++------
 lib/src/widgets/standard_picker_list.dart     |  3 ++
 lib/view_model/send/send_view_model.dart      |  7 +++++
 .../settings/other_settings_view_model.dart   |  7 +++++
 .../transaction_details_view_model.dart       |  2 ++
 tool/configure.dart                           |  1 +
 12 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart
index 862ce9db5..9bdc0f3ac 100644
--- a/lib/bitcoin/cw_bitcoin.dart
+++ b/lib/bitcoin/cw_bitcoin.dart
@@ -291,4 +291,10 @@ class CWBitcoin extends Bitcoin {
       outputsCount,
     );
   }
+
+  @override
+  int getMaxCustomFeeRate(Object wallet) {
+    final bitcoinWallet = wallet as ElectrumWallet;
+    return (bitcoinWallet.feeRate(BitcoinTransactionPriority.fast) * 1.1).round();
+  }
 }
diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart
index 7c2bfedd0..c9ae5182a 100644
--- a/lib/src/screens/send/widgets/send_card.dart
+++ b/lib/src/screens/send/widgets/send_card.dart
@@ -675,6 +675,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
     final selectedItem = items.indexOf(sendViewModel.transactionPriority);
     final customItemIndex = sendViewModel.getCustomPriorityIndex(items);
     final isBitcoinWallet = sendViewModel.walletType == WalletType.bitcoin;
+    final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
     double? customFeeRate = isBitcoinWallet ? sendViewModel.customBitcoinFeeRate.toDouble() : null;
 
     await showPopUp<void>(
@@ -689,6 +690,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
                   sendViewModel.displayFeeRate(priority, customFeeRate?.round()),
               selectedAtIndex: selectedIdx,
               customItemIndex: customItemIndex,
+              maxValue: maxCustomFeeRate,
               title: S.of(context).please_select,
               headerEnabled: !isBitcoinWallet,
               closeOnItemSelected: !isBitcoinWallet,
diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart
index 90139e8c4..9bba51944 100644
--- a/lib/src/screens/settings/other_settings_page.dart
+++ b/lib/src/screens/settings/other_settings_page.dart
@@ -37,6 +37,7 @@ class OtherSettingsPage extends BasePage {
                     customItemIndex: _otherSettingsViewModel.customPriorityItemIndex,
                     onItemSelected: _otherSettingsViewModel.onDisplayBitcoinPrioritySelected,
                     customValue: _otherSettingsViewModel.customBitcoinFeeRate,
+                    maxValue: _otherSettingsViewModel.maxCustomFeeRate?.toDouble(),
                   ) :
                   SettingsPickerCell(
                     title: S.current.settings_fee_priority,
diff --git a/lib/src/screens/settings/widgets/setting_priority_picker_cell.dart b/lib/src/screens/settings/widgets/setting_priority_picker_cell.dart
index bba44606d..118924c4d 100644
--- a/lib/src/screens/settings/widgets/setting_priority_picker_cell.dart
+++ b/lib/src/screens/settings/widgets/setting_priority_picker_cell.dart
@@ -15,6 +15,7 @@ class SettingsPriorityPickerCell<ItemType> extends StandardListRow {
       this.isGridView = false,
       this.matchingCriteria,
       this.customValue,
+      this.maxValue,
       this.customItemIndex,
       this.onItemSelected})
       : super(
@@ -34,6 +35,7 @@ class SettingsPriorityPickerCell<ItemType> extends StandardListRow {
                         displayItem: (ItemType item) => displayItem!(item, sliderValue.round()),
                         selectedAtIndex: selectedAtIndex,
                         customItemIndex: customItemIndex,
+                        maxValue: maxValue,
                         headerEnabled: false,
                         closeOnItemSelected: false,
                         mainAxisAlignment: MainAxisAlignment.center,
@@ -61,6 +63,7 @@ class SettingsPriorityPickerCell<ItemType> extends StandardListRow {
   final bool isGridView;
   final bool Function(ItemType, String)? matchingCriteria;
   double? customValue;
+  double? maxValue;
   int? customItemIndex;
 
   @override
diff --git a/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart b/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart
index 8f722ee7e..7615065d7 100644
--- a/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart
+++ b/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart
@@ -10,6 +10,7 @@ class StandardPickerListItem<T> extends TransactionDetailsListItem {
       required this.onItemSelected,
       required this.selectedIdx,
       required this.customItemIndex,
+      this.maxValue,
       required this.customValue})
       : super(title: title, value: value);
 
@@ -18,6 +19,7 @@ class StandardPickerListItem<T> extends TransactionDetailsListItem {
   final Function(double) onSliderChanged;
   final Function(T) onItemSelected;
   final int selectedIdx;
+  final double? maxValue;
   final int customItemIndex;
   double customValue;
 }
diff --git a/lib/src/screens/transaction_details/rbf_details_page.dart b/lib/src/screens/transaction_details/rbf_details_page.dart
index 875e0a4ef..3faec48a8 100644
--- a/lib/src/screens/transaction_details/rbf_details_page.dart
+++ b/lib/src/screens/transaction_details/rbf_details_page.dart
@@ -74,6 +74,7 @@ class RBFDetailsPage extends BasePage {
                     selectedIdx: item.selectedIdx,
                     customItemIndex: item.customItemIndex,
                     customValue: item.customValue,
+                    maxValue: item.maxValue,
                   );
                 }
 
diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart
index d87b5721e..b744d1db0 100644
--- a/lib/src/widgets/picker.dart
+++ b/lib/src/widgets/picker.dart
@@ -27,14 +27,21 @@ class Picker<Item> extends StatefulWidget {
     this.headerEnabled = true,
     this.closeOnItemSelected = true,
     this.sliderValue,
+    this.minValue,
+    this.maxValue,
     this.customItemIndex,
     this.isWrapped = true,
     this.borderColor,
     this.onSliderChanged,
     this.matchingCriteria,
-  }) : assert(hintText == null ||
-            matchingCriteria !=
-                null); // make sure that if the search field is enabled then there is a searching criteria provided
+  }) : assert(hintText == null || matchingCriteria != null) {
+    // make sure that if the search field is enabled then there is a searching criteria provided
+    if (sliderValue != null && maxValue != null) {
+      if (sliderValue! > maxValue!) {
+        sliderValue = maxValue;
+      }
+    }
+  }
 
   final int selectedAtIndex;
   final List<Item> items;
@@ -49,12 +56,14 @@ class Picker<Item> extends StatefulWidget {
   final String? hintText;
   final bool headerEnabled;
   final bool closeOnItemSelected;
-  final double? sliderValue;
+  double? sliderValue;
+  final double? minValue;
   final int? customItemIndex;
   final bool isWrapped;
   final Color? borderColor;
   final Function(double)? onSliderChanged;
   final bool Function(Item, String)? matchingCriteria;
+  final double? maxValue;
 
   @override
   _PickerState<Item> createState() => _PickerState<Item>(items, images, onItemSelected);
@@ -138,7 +147,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
       containerHeight = height * 0.75;
     }
 
-    final content = Column (
+    final content = Column(
       children: [
         if (widget.title?.isNotEmpty ?? false)
           Container(
@@ -211,8 +220,9 @@ class _PickerState<Item> extends State<Picker<Item>> {
                                         fontWeight: FontWeight.w500,
                                         fontFamily: 'Lato',
                                         decoration: TextDecoration.none,
-                                        color:
-                                            Theme.of(context).extension<CakeTextTheme>()!.titleColor,
+                                        color: Theme.of(context)
+                                            .extension<CakeTextTheme>()!
+                                            .titleColor,
                                       ),
                                     ),
                                   )
@@ -491,8 +501,8 @@ class _PickerState<Item> extends State<Picker<Item>> {
           child: Slider(
             value: widget.sliderValue ?? 1,
             onChanged: isActivated ? widget.onSliderChanged : null,
-            min: 1,
-            max: 100,
+            min: widget.minValue ?? 1,
+            max: widget.maxValue ?? 100,
             divisions: 100,
           ),
         ),
diff --git a/lib/src/widgets/standard_picker_list.dart b/lib/src/widgets/standard_picker_list.dart
index eb1d16900..ea8b07097 100644
--- a/lib/src/widgets/standard_picker_list.dart
+++ b/lib/src/widgets/standard_picker_list.dart
@@ -15,6 +15,7 @@ class StandardPickerList<T> extends StatefulWidget {
     required this.selectedIdx,
     required this.customItemIndex,
     required this.customValue,
+    this.maxValue,
   }) : super(key: key);
 
   final String title;
@@ -26,6 +27,7 @@ class StandardPickerList<T> extends StatefulWidget {
   final String value;
   final int selectedIdx;
   final double customValue;
+  final double? maxValue;
 
   @override
   _StandardPickerListState<T> createState() => _StandardPickerListState<T>();
@@ -59,6 +61,7 @@ class _StandardPickerListState<T> extends State<StandardPickerList<T>> {
             displayItem: adaptedDisplayItem,
             selectedAtIndex: selectedIdx,
             customItemIndex: widget.customItemIndex,
+            maxValue: widget.maxValue,
             headerEnabled: false,
             closeOnItemSelected: false,
             mainAxisAlignment: MainAxisAlignment.center,
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 298cc3eed..2e00d1f0b 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -166,6 +166,13 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
     return null;
   }
 
+  int? get maxCustomFeeRate {
+    if (wallet.type == WalletType.bitcoin) {
+      return bitcoin!.getMaxCustomFeeRate(wallet);
+    }
+    return null;
+  }
+
   @computed
   int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate;
 
diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart
index cf410a1a9..0493acf81 100644
--- a/lib/view_model/settings/other_settings_view_model.dart
+++ b/lib/view_model/settings/other_settings_view_model.dart
@@ -140,6 +140,13 @@ abstract class OtherSettingsViewModelBase with Store {
     return customItem != null ? priorities.indexOf(customItem) : null;
   }
 
+  int? get maxCustomFeeRate {
+    if (_wallet.type == WalletType.bitcoin) {
+      return bitcoin!.getMaxCustomFeeRate(_wallet);
+    }
+    return null;
+  }
+
   @action
   ProviderType onBuyProviderTypeSelected(ProviderType buyProviderType) =>
       _settingsStore.defaultBuyProviders[walletType] = buyProviderType;
diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart
index fd6d3ef6e..be2ebc545 100644
--- a/lib/view_model/transaction_details_view_model.dart
+++ b/lib/view_model/transaction_details_view_model.dart
@@ -348,12 +348,14 @@ abstract class TransactionDetailsViewModelBase with Store {
     final customItem = priorities.firstWhereOrNull(
         (element) => element == sendViewModel.bitcoinTransactionPriorityCustom);
     final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null;
+    final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
 
     RBFListItems.add(StandardPickerListItem(
         title: S.current.estimated_new_fee,
         value: bitcoin!.formatterBitcoinAmountToString(amount: newFee) + ' ${walletTypeToCryptoCurrency(wallet.type)}',
         items: priorityForWalletType(wallet.type),
         customValue: settingsStore.customBitcoinFeeRate.toDouble(),
+        maxValue: maxCustomFeeRate,
         selectedIdx: selectedItem,
         customItemIndex: customItemIndex ?? 0,
         displayItem: (dynamic priority, double sliderValue) =>
diff --git a/tool/configure.dart b/tool/configure.dart
index d08724e42..34a39d28b 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -159,6 +159,7 @@ abstract class Bitcoin {
   Future<bool> isChangeSufficientForFee(Object wallet, String txId, String newFee);
   int getFeeAmountForPriority(Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, {int? size});
   int getFeeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size});
+  int getMaxCustomFeeRate(Object wallet);
 }
   """;