From e596c19b402cc4f6e7d415abaea7a8626a2aae5a Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Thu, 6 Mar 2025 01:41:23 +0200
Subject: [PATCH 01/14] Fixate decimal points to 2 (#2066)

---
 lib/buy/moonpay/moonpay_provider.dart | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart
index 959d38a57..a6966db33 100644
--- a/lib/buy/moonpay/moonpay_provider.dart
+++ b/lib/buy/moonpay/moonpay_provider.dart
@@ -168,8 +168,7 @@ class MoonPayProvider extends BuyProvider {
 
     final params = {
       'baseCurrencyCode': baseCurrencyCode,
-      'baseCurrencyAmount': amount.toString(),
-      'amount': amount.toString(),
+      'baseCurrencyAmount': amount.toStringAsFixed(2),
       'paymentMethod': paymentMethod,
       'areFeesIncluded': 'false',
       'apiKey': _apiKey
@@ -232,7 +231,7 @@ class MoonPayProvider extends BuyProvider {
           ? '#${Palette.blueCraiola.value.toRadixString(16).substring(2, 8)}'
           : '#${Palette.moderateSlateBlue.value.toRadixString(16).substring(2, 8)}',
       'baseCurrencyCode': isBuyAction ? quote.fiatCurrency.name : quote.cryptoCurrency.name,
-      'baseCurrencyAmount': amount.toString(),
+      'baseCurrencyAmount': amount.toStringAsFixed(2),
       'walletAddress': cryptoCurrencyAddress,
       'lockAmount': 'false',
       'showAllCurrencies': 'false',

From 09f20b2a7bf3ef15bfcfcf4471e1f9dfad94708a Mon Sep 17 00:00:00 2001
From: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Date: Thu, 6 Mar 2025 01:25:38 +0100
Subject: [PATCH 02/14] CW-843: Enhance Wallet Groups Implementation (#2045)

* feat: Enhance Wallet Groups Implementation by using hashedIdentifiers instead of parentAddresses

* fix: Call updateWalletGroups even if group has an hash identifier

* feat: Add secrets to workflow

* feat: Enhance Wallet Groups Implementation by using hashedIdentifiers instead of parentAddresses

* Handle wallet grouping edgecase where wallet is restored via non seed medium

* fix: Valid wallet/wallet groups not showing up when choosing wallet/groups for creating new wallets
---
 .../workflows/automated_integration_test.yml  |   4 +
 .github/workflows/pr_test_build_android.yml   |   1 +
 .github/workflows/pr_test_build_linux.yml     |   1 +
 .../bitcoin_wallet_creation_credentials.dart  |   2 -
 ...coin_cash_wallet_creation_credentials.dart |   2 -
 cw_core/lib/wallet_credentials.dart           |   2 -
 cw_core/lib/wallet_info.dart                  |  11 +-
 ...evm_chain_wallet_creation_credentials.dart |   1 -
 .../lib/nano_wallet_creation_credentials.dart |   2 -
 .../solana_wallet_creation_credentials.dart   |   2 -
 .../lib/tron_wallet_creation_credentials.dart |   2 -
 ios/Podfile.lock                              |   2 +-
 lib/bitcoin/cw_bitcoin.dart                   |   2 -
 lib/bitcoin_cash/cw_bitcoin_cash.dart         |   2 -
 lib/core/new_wallet_arguments.dart            |   2 -
 lib/di.dart                                   |  11 +-
 lib/entities/hash_wallet_identifier.dart      |  21 +++
 lib/entities/wallet_edit_page_arguments.dart  |   4 +-
 lib/entities/wallet_group.dart                |  11 +-
 lib/entities/wallet_manager.dart              | 145 ++++++++++++------
 lib/ethereum/cw_ethereum.dart                 |   2 -
 lib/nano/cw_nano.dart                         |   2 -
 lib/polygon/cw_polygon.dart                   |   2 -
 lib/reactions/on_current_wallet_change.dart   |   4 +
 lib/solana/cw_solana.dart                     |   2 -
 .../new_wallet/wallet_group_display_page.dart |   1 -
 lib/src/screens/wallet/wallet_edit_page.dart  |   4 +-
 .../screens/wallet_list/wallet_list_page.dart |   2 +-
 lib/tron/cw_tron.dart                         |  13 +-
 lib/view_model/wallet_creation_vm.dart        |   6 +-
 .../wallet_groups_display_view_model.dart     |  10 +-
 .../wallet_list/wallet_edit_view_model.dart   |   4 +-
 lib/view_model/wallet_new_vm.dart             |   7 -
 tool/configure.dart                           |  13 +-
 tool/utils/secret_key.dart                    |   2 +
 35 files changed, 181 insertions(+), 123 deletions(-)
 create mode 100644 lib/entities/hash_wallet_identifier.dart

diff --git a/.github/workflows/automated_integration_test.yml b/.github/workflows/automated_integration_test.yml
index 0869db8ea..539513111 100644
--- a/.github/workflows/automated_integration_test.yml
+++ b/.github/workflows/automated_integration_test.yml
@@ -223,6 +223,10 @@ jobs:
          echo "const nanoTestWalletReceiveAddress = '${{ secrets.NANO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
          echo "const wowneroTestWalletReceiveAddress = '${{ secrets.WOWNERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart
          echo "const moneroTestWalletBlockHeight =  '${{ secrets.MONERO_TEST_WALLET_BLOCK_HEIGHT }}';" >> lib/.secrets.g.dart
+         # end of test secrets
+         echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart
+         echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart
+         echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> lib/.secrets.g.dart
 
      - name: Rename app
        run: |
diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 25fb144e3..6c7e82409 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -172,6 +172,7 @@ jobs:
           # end of test secrets
           echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart
+          echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> lib/.secrets.g.dart
 
       - name: prepare monero_c and cache
         run: |
diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml
index a9d8085b6..e307dc410 100644
--- a/.github/workflows/pr_test_build_linux.yml
+++ b/.github/workflows/pr_test_build_linux.yml
@@ -168,6 +168,7 @@ jobs:
           # end of test secrets
           echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart
+          echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> lib/.secrets.g.dart
 
       - name: prepare monero_c and cache
         run: |
diff --git a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart
index a1b1418b8..177d61e87 100644
--- a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart
@@ -11,13 +11,11 @@ class BitcoinNewWalletCredentials extends WalletCredentials {
     String? derivationPath,
     String? passphrase,
     this.mnemonic,
-    String? parentAddress,
   }) : super(
           name: name,
           walletInfo: walletInfo,
           password: password,
           passphrase: passphrase,
-          parentAddress: parentAddress,
         );
 
   final String? mnemonic;
diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart
index af93cdbf8..90004a485 100644
--- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart
+++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart
@@ -8,13 +8,11 @@ class BitcoinCashNewWalletCredentials extends WalletCredentials {
     String? password,
     String? passphrase,
     this.mnemonic,
-    String? parentAddress,
   }) : super(
           name: name,
           walletInfo: walletInfo,
           password: password,
           passphrase: passphrase,
-          parentAddress: parentAddress
         );
   final String? mnemonic;
 }
diff --git a/cw_core/lib/wallet_credentials.dart b/cw_core/lib/wallet_credentials.dart
index 55c24bf37..30ae2546c 100644
--- a/cw_core/lib/wallet_credentials.dart
+++ b/cw_core/lib/wallet_credentials.dart
@@ -10,7 +10,6 @@ abstract class WalletCredentials {
     this.passphrase,
     this.derivationInfo,
     this.hardwareWalletType,
-    this.parentAddress,
   }) {
     if (this.walletInfo != null && derivationInfo != null) {
       this.walletInfo!.derivationInfo = derivationInfo;
@@ -19,7 +18,6 @@ abstract class WalletCredentials {
 
   final String name;
   final int? height;
-  String? parentAddress;
   int? seedPhraseLength;
   String? password;
   String? passphrase;
diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart
index bd035e30a..d62e61941 100644
--- a/cw_core/lib/wallet_info.dart
+++ b/cw_core/lib/wallet_info.dart
@@ -81,6 +81,8 @@ class WalletInfo extends HiveObject {
     this.derivationInfo,
     this.hardwareWalletType,
     this.parentAddress,
+    this.hashedWalletIdentifier,
+    this.isNonSeedWallet,
   ) : _yatLastUsedAddressController = StreamController<String>.broadcast();
 
   factory WalletInfo.external({
@@ -99,6 +101,8 @@ class WalletInfo extends HiveObject {
     DerivationInfo? derivationInfo,
     HardwareWalletType? hardwareWalletType,
     String? parentAddress,
+    String? hashedWalletIdentifier,
+    bool? isNonSeedWallet,
   }) {
     return WalletInfo(
       id,
@@ -116,6 +120,8 @@ class WalletInfo extends HiveObject {
       derivationInfo,
       hardwareWalletType,
       parentAddress,
+      hashedWalletIdentifier,
+      isNonSeedWallet ?? false,
     );
   }
 
@@ -196,8 +202,11 @@ class WalletInfo extends HiveObject {
   @HiveField(24)
   List<String>? manualAddresses;
 
-  
+  @HiveField(25)
+  String? hashedWalletIdentifier;
 
+  @HiveField(26, defaultValue: false)
+  bool isNonSeedWallet;
 
   String get yatLastUsedAddress => yatLastUsedAddressRaw ?? '';
 
diff --git a/cw_evm/lib/evm_chain_wallet_creation_credentials.dart b/cw_evm/lib/evm_chain_wallet_creation_credentials.dart
index 5075e6289..d9595a243 100644
--- a/cw_evm/lib/evm_chain_wallet_creation_credentials.dart
+++ b/cw_evm/lib/evm_chain_wallet_creation_credentials.dart
@@ -7,7 +7,6 @@ class EVMChainNewWalletCredentials extends WalletCredentials {
     required super.name,
     super.walletInfo,
     super.password,
-    super.parentAddress,
     this.mnemonic,
     super.passphrase,
   });
diff --git a/cw_nano/lib/nano_wallet_creation_credentials.dart b/cw_nano/lib/nano_wallet_creation_credentials.dart
index 59789aec7..8eb6dc2d2 100644
--- a/cw_nano/lib/nano_wallet_creation_credentials.dart
+++ b/cw_nano/lib/nano_wallet_creation_credentials.dart
@@ -8,13 +8,11 @@ class NanoNewWalletCredentials extends WalletCredentials {
     String? password,
     DerivationType? derivationType,
     this.mnemonic,
-    String? parentAddress,
     String? passphrase,
   }) : super(
           name: name,
           password: password,
           walletInfo: walletInfo,
-          parentAddress: parentAddress,
           passphrase: passphrase,
         );
 
diff --git a/cw_solana/lib/solana_wallet_creation_credentials.dart b/cw_solana/lib/solana_wallet_creation_credentials.dart
index 121ef2b44..309c41cf3 100644
--- a/cw_solana/lib/solana_wallet_creation_credentials.dart
+++ b/cw_solana/lib/solana_wallet_creation_credentials.dart
@@ -6,14 +6,12 @@ class SolanaNewWalletCredentials extends WalletCredentials {
     required String name,
     WalletInfo? walletInfo,
     String? password,
-    String? parentAddress,
     this.mnemonic,
     String? passphrase,
   }) : super(
           name: name,
           walletInfo: walletInfo,
           password: password,
-          parentAddress: parentAddress,
           passphrase: passphrase,
         );
   final String? mnemonic;
diff --git a/cw_tron/lib/tron_wallet_creation_credentials.dart b/cw_tron/lib/tron_wallet_creation_credentials.dart
index fd9066acd..402cff2ff 100644
--- a/cw_tron/lib/tron_wallet_creation_credentials.dart
+++ b/cw_tron/lib/tron_wallet_creation_credentials.dart
@@ -7,13 +7,11 @@ class TronNewWalletCredentials extends WalletCredentials {
     WalletInfo? walletInfo,
     String? password,
     this.mnemonic,
-    String? parentAddress,
     String? passphrase,
   }) : super(
           name: name,
           walletInfo: walletInfo,
           password: password,
-          parentAddress: parentAddress,
           passphrase: passphrase,
         );
 
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 9e2a8507a..d400d3f81 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -277,4 +277,4 @@ SPEC CHECKSUMS:
 
 PODFILE CHECKSUM: e448f662d4c41f0c0b1ccbb78afd57dbf895a597
 
-COCOAPODS: 1.15.2
+COCOAPODS: 1.15.2
\ No newline at end of file
diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart
index bf9ec0c4d..f93ba9550 100644
--- a/lib/bitcoin/cw_bitcoin.dart
+++ b/lib/bitcoin/cw_bitcoin.dart
@@ -34,7 +34,6 @@ class CWBitcoin extends Bitcoin {
     String? password,
     String? passphrase,
     String? mnemonic,
-    String? parentAddress,
   }) =>
       BitcoinNewWalletCredentials(
         name: name,
@@ -42,7 +41,6 @@ class CWBitcoin extends Bitcoin {
         password: password,
         passphrase: passphrase,
         mnemonic: mnemonic,
-        parentAddress: parentAddress,
       );
 
   @override
diff --git a/lib/bitcoin_cash/cw_bitcoin_cash.dart b/lib/bitcoin_cash/cw_bitcoin_cash.dart
index b74448703..be0323bfa 100644
--- a/lib/bitcoin_cash/cw_bitcoin_cash.dart
+++ b/lib/bitcoin_cash/cw_bitcoin_cash.dart
@@ -17,14 +17,12 @@ class CWBitcoinCash extends BitcoinCash {
     String? password,
     String? passphrase,
     String? mnemonic,
-    String? parentAddress,
   }) =>
       BitcoinCashNewWalletCredentials(
         name: name,
         walletInfo: walletInfo,
         password: password,
         passphrase: passphrase,
-        parentAddress: parentAddress,
         mnemonic: mnemonic,
       );
 
diff --git a/lib/core/new_wallet_arguments.dart b/lib/core/new_wallet_arguments.dart
index 2581c57bb..9e2ef9df4 100644
--- a/lib/core/new_wallet_arguments.dart
+++ b/lib/core/new_wallet_arguments.dart
@@ -3,12 +3,10 @@ import 'package:cw_core/wallet_type.dart';
 class NewWalletArguments {
   final WalletType type;
   final String? mnemonic;
-  final String? parentAddress;
   final bool isChildWallet;
 
   NewWalletArguments({
     required this.type,
-    this.parentAddress,
     this.mnemonic,
     this.isChildWallet = false,
   });
diff --git a/lib/di.dart b/lib/di.dart
index 3e10bd7a1..174183f9a 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -392,11 +392,10 @@ Future<void> setup({
   getIt.registerFactory<NewWalletTypeViewModel>(() => NewWalletTypeViewModel(_walletInfoSource));
 
   getIt.registerFactory<WalletManager>(
-    () {
-      final instance = WalletManager(_walletInfoSource, getIt.get<SharedPreferences>());
-      instance.updateWalletGroups();
-      return instance;
-    },
+    () => WalletManager(
+      _walletInfoSource,
+      getIt.get<SharedPreferences>(),
+    ),
   );
 
   getIt.registerFactoryParam<WalletGroupsDisplayViewModel, WalletType, void>(
@@ -812,7 +811,7 @@ Future<void> setup({
         editingWallet: arguments.editingWallet,
         isWalletGroup: arguments.isWalletGroup,
         groupName: arguments.groupName,
-        parentAddress: arguments.parentAddress,
+        walletGroupKey: arguments.walletGroupKey,
       ),
     );
   });
diff --git a/lib/entities/hash_wallet_identifier.dart b/lib/entities/hash_wallet_identifier.dart
new file mode 100644
index 000000000..8e593ec79
--- /dev/null
+++ b/lib/entities/hash_wallet_identifier.dart
@@ -0,0 +1,21 @@
+import 'dart:convert';
+
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
+import 'package:cw_core/wallet_base.dart';
+import 'package:hashlib/hashlib.dart';
+
+String createHashedWalletIdentifier(WalletBase wallet) {
+  if (wallet.seed == null) return '';
+
+  final salt = secrets.walletGroupSalt;
+  final combined = '$salt.${wallet.seed}';
+
+  // Convert to UTF-8 bytes.
+  final bytes = utf8.encode(combined);
+
+  // Perform SHA-256 hash.
+  final digest = sha256.convert(bytes);
+
+  // Return the hex string representation of the hash.
+  return digest.toString();
+}
diff --git a/lib/entities/wallet_edit_page_arguments.dart b/lib/entities/wallet_edit_page_arguments.dart
index 260471f7e..6217195dc 100644
--- a/lib/entities/wallet_edit_page_arguments.dart
+++ b/lib/entities/wallet_edit_page_arguments.dart
@@ -10,7 +10,7 @@ class WalletEditPageArguments {
     this.isWalletGroup = false,
     this.walletListViewModel,
     this.groupName = '',
-    this.parentAddress = '',
+    this.walletGroupKey = '',
     this.walletEditViewModel,
     this.walletNewVM,
     this.authService,
@@ -19,7 +19,7 @@ class WalletEditPageArguments {
   final WalletListItem editingWallet;
   final bool isWalletGroup;
   final String groupName;
-  final String parentAddress;
+  final String walletGroupKey;
   final WalletListViewModel? walletListViewModel;
 
   final WalletEditViewModel? walletEditViewModel;
diff --git a/lib/entities/wallet_group.dart b/lib/entities/wallet_group.dart
index 9845aea65..ab94f3eb3 100644
--- a/lib/entities/wallet_group.dart
+++ b/lib/entities/wallet_group.dart
@@ -1,13 +1,14 @@
 import 'package:cw_core/wallet_info.dart';
 
 class WalletGroup {
-  WalletGroup(this.parentAddress) : wallets = [];
+  WalletGroup(this.groupKey) : wallets = [];
 
-  /// Main identifier for each group, compulsory.
-  final String parentAddress;
+  /// Primary identifier for the group. Previously was `parentAddress`.
+  /// Now we store either the wallet's hash OR fallback to parentAddress/address.
+  final String groupKey;
 
-  /// Child wallets that share the same parent address within this group
-  List<WalletInfo> wallets;
+  /// Child wallets that share the same group key
+  final List<WalletInfo> wallets;
 
   /// Custom name for the group, editable for multi-child wallet groups
   String? groupName;
diff --git a/lib/entities/wallet_manager.dart b/lib/entities/wallet_manager.dart
index 29c873dae..8bcabcaf2 100644
--- a/lib/entities/wallet_manager.dart
+++ b/lib/entities/wallet_manager.dart
@@ -1,70 +1,61 @@
+import 'package:cake_wallet/entities/hash_wallet_identifier.dart';
 import 'package:cake_wallet/entities/wallet_group.dart';
+import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:hive/hive.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 
 class WalletManager {
-  WalletManager(
-    this._walletInfoSource,
-    this._sharedPreferences,
-  );
+  WalletManager(this._walletInfoSource, this._sharedPreferences);
 
   final Box<WalletInfo> _walletInfoSource;
   final SharedPreferences _sharedPreferences;
 
   final List<WalletGroup> walletGroups = [];
 
-  /// Categorize wallets into groups based on their parentAddress.
-  ///
-  /// Update the lead wallet for each group and clean up empty groups
-  /// i.e remove group if there's no lead wallet (i.e, no wallets left)
   void updateWalletGroups() {
     walletGroups.clear();
 
-    for (var walletInfo in _walletInfoSource.values) {
-      final group = _getOrCreateGroup(_resolveParentAddress(walletInfo));
+    for (final walletInfo in _walletInfoSource.values) {
+      final groupKey = _resolveGroupKey(walletInfo);
+      final group = _getOrCreateGroup(groupKey);
       group.wallets.add(walletInfo);
     }
 
-    walletGroups.removeWhere((group) => group.wallets.isEmpty);
-
+    walletGroups.removeWhere((g) => g.wallets.isEmpty);
     _loadCustomGroupNames();
   }
 
-  /// Function to determine the correct parentAddress for a wallet.
-  ///
-  /// If it's a parent wallet (parentAddress is null),
-  /// use its own address as parentAddress.
-  String _resolveParentAddress(WalletInfo walletInfo) {
+  String _resolveGroupKey(WalletInfo walletInfo) {
+    if (walletInfo.hashedWalletIdentifier != null &&
+        walletInfo.hashedWalletIdentifier!.isNotEmpty) {
+      return walletInfo.hashedWalletIdentifier!;
+    }
+
+    // Fallback to old logic
     return walletInfo.parentAddress ?? walletInfo.address;
   }
 
-  /// Check if a group with the parentAddress already exists,
-  /// If no group exists, create a new one.
-  ///
-  WalletGroup _getOrCreateGroup(String parentAddress) {
+  WalletGroup _getOrCreateGroup(String groupKey) {
     return walletGroups.firstWhere(
-      (group) => group.parentAddress == parentAddress,
+      (g) => g.groupKey == groupKey,
       orElse: () {
-        final newGroup = WalletGroup(parentAddress);
+        final newGroup = WalletGroup(groupKey);
         walletGroups.add(newGroup);
         return newGroup;
       },
     );
   }
 
-  /// Add a new wallet and update lead wallet after adding.
   void addWallet(WalletInfo walletInfo) {
-    final group = _getOrCreateGroup(_resolveParentAddress(walletInfo));
+    final groupKey = _resolveGroupKey(walletInfo);
+    final group = _getOrCreateGroup(groupKey);
     group.wallets.add(walletInfo);
   }
 
-  /// Removes a wallet from a group i.e when it's deleted.
-  ///
-  /// Update lead wallet after removing,
-  /// Remove the group if it's empty (i.e., no lead wallet).
   void removeWallet(WalletInfo walletInfo) {
-    final group = _getOrCreateGroup(_resolveParentAddress(walletInfo));
+    final groupKey = _resolveGroupKey(walletInfo);
+    final group = _getOrCreateGroup(groupKey);
     group.wallets.remove(walletInfo);
 
     if (group.wallets.isEmpty) {
@@ -72,39 +63,99 @@ class WalletManager {
     }
   }
 
-  /// Returns all the child wallets within a group.
-  ///
-  /// If the group is not found, returns an empty group with no wallets.
-  List<WalletInfo> getWalletsInGroup(String parentAddress) {
+  List<WalletInfo> getWalletsInGroup(String groupKey) {
     return walletGroups
         .firstWhere(
-          (group) => group.parentAddress == parentAddress,
-          orElse: () => WalletGroup(parentAddress),
+          (g) => g.groupKey == groupKey,
+          orElse: () => WalletGroup(groupKey),
         )
         .wallets;
   }
 
-  /// Iterate through all groups and load their custom names from storage
   void _loadCustomGroupNames() {
     for (var group in walletGroups) {
-      final groupName = _sharedPreferences.getString('wallet_group_name_${group.parentAddress}');
+      final key = 'wallet_group_name_${group.groupKey}';
+      final groupName = _sharedPreferences.getString(key);
       if (groupName != null && group.wallets.length > 1) {
-        group.groupName = groupName; // Restore custom name
+        group.groupName = groupName;
       }
     }
   }
 
-  /// Save custom name for a group
-  void _saveCustomGroupName(String parentAddress, String name) {
-    _sharedPreferences.setString('wallet_group_name_$parentAddress', name);
+  void _saveCustomGroupName(String groupKey, String name) {
+    _sharedPreferences.setString('wallet_group_name_$groupKey', name);
   }
 
-  // Set custom group name and persist it
-  void setGroupName(String parentAddress, String name) {
-    if (parentAddress.isEmpty || name.isEmpty) return;
+  void setGroupName(String groupKey, String name) {
+    if (groupKey.isEmpty || name.isEmpty) return;
 
-    final group = walletGroups.firstWhere((group) => group.parentAddress == parentAddress);
+    final group = walletGroups.firstWhere((g) => g.groupKey == groupKey);
     group.setCustomName(name);
-    _saveCustomGroupName(parentAddress, name); // Persist the custom name
+    _saveCustomGroupName(groupKey, name);
+  }
+
+  // ---------------------------------------------------------------------------
+  // This performs a Group-Based Lazy Migration:
+  // If the user opens a wallet in an old group,
+  // we migrate ALL wallets that share its old group key to a new hash.
+  // ---------------------------------------------------------------------------
+
+  /// When a user opens a wallet, check if it has a real hash.
+  /// If not, migrate the ENTIRE old group so they keep the same group name
+  /// and end up with the same new hash (preserving grouping).
+  Future<void> ensureGroupHasHashedIdentifier(WalletBase openedWallet) async {
+    WalletInfo walletInfo = openedWallet.walletInfo;
+
+    // If the openedWallet already has an hash, then there is nothing to do
+    if (walletInfo.hashedWalletIdentifier != null &&
+        walletInfo.hashedWalletIdentifier!.isNotEmpty) {
+      updateWalletGroups(); // Still skeptical of calling this here. Looking for a better spot.
+      return;
+    }
+
+    // Identify the old group key for this wallet
+    final oldGroupKey = _resolveGroupKey(walletInfo); // parentAddress fallback
+
+    // Find all wallets that share this old group key (i.e the old group)
+    final oldGroupWallets = _walletInfoSource.values.where((w) {
+      final key = w.hashedWalletIdentifier != null && w.hashedWalletIdentifier!.isNotEmpty
+          ? w.hashedWalletIdentifier
+          : (w.parentAddress ?? w.address);
+      return key == oldGroupKey;
+    }).toList();
+
+    if (oldGroupWallets.isEmpty) {
+      // This shouldn't happen, but just in case it does, we return.
+      return;
+    }
+
+    // Next, we determine the new group hash for these wallets
+    // Since they share the same seed, we can assign that group hash
+    // to all the wallets to preserve grouping.
+    final newGroupHash = createHashedWalletIdentifier(openedWallet);
+
+    // Migrate the old group name from oldGroupKey(i.e parentAddress) to newGroupHash
+    await _migrateGroupName(oldGroupKey, newGroupHash);
+
+    // Then we assign this new hash to each wallet in that old group and save them
+    for (final wallet in oldGroupWallets) {
+      wallet.hashedWalletIdentifier = newGroupHash;
+      await wallet.save();
+    }
+
+    // Finally, we rebuild the groups so that these wallets are now in the new group
+    updateWalletGroups();
+  }
+
+  /// Copy an old group name to the new group key, then remove the old key.
+  Future<void> _migrateGroupName(String oldGroupKey, String newGroupKey) async {
+    final oldNameKey = 'wallet_group_name_$oldGroupKey';
+    final newNameKey = 'wallet_group_name_$newGroupKey';
+
+    final oldGroupName = _sharedPreferences.getString(oldNameKey);
+    if (oldGroupName != null) {
+      await _sharedPreferences.setString(newNameKey, oldGroupName);
+      await _sharedPreferences.remove(oldNameKey);
+    }
   }
 }
diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart
index dc91e4fc2..40c7a0f77 100644
--- a/lib/ethereum/cw_ethereum.dart
+++ b/lib/ethereum/cw_ethereum.dart
@@ -11,7 +11,6 @@ class CWEthereum extends Ethereum {
   WalletCredentials createEthereumNewWalletCredentials({
     required String name,
     String? mnemonic,
-    String? parentAddress,
     WalletInfo? walletInfo,
     String? password,
     String? passphrase,
@@ -20,7 +19,6 @@ class CWEthereum extends Ethereum {
         name: name,
         walletInfo: walletInfo,
         password: password,
-        parentAddress: parentAddress,
         mnemonic: mnemonic,
         passphrase: passphrase,
       );
diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart
index 9a2243d00..463e19d65 100644
--- a/lib/nano/cw_nano.dart
+++ b/lib/nano/cw_nano.dart
@@ -94,14 +94,12 @@ class CWNano extends Nano {
     WalletInfo? walletInfo,
     String? password,
     String? mnemonic,
-    String? parentAddress,
     String? passphrase,
   }) =>
       NanoNewWalletCredentials(
         name: name,
         password: password,
         mnemonic: mnemonic,
-        parentAddress: parentAddress,
         walletInfo: walletInfo,
         passphrase: passphrase,
       );
diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart
index b8f78e9e2..ec98137c5 100644
--- a/lib/polygon/cw_polygon.dart
+++ b/lib/polygon/cw_polygon.dart
@@ -11,7 +11,6 @@ class CWPolygon extends Polygon {
   WalletCredentials createPolygonNewWalletCredentials({
     required String name,
     String? mnemonic,
-    String? parentAddress,
     WalletInfo? walletInfo,
     String? password,
     String? passphrase,
@@ -21,7 +20,6 @@ class CWPolygon extends Polygon {
         walletInfo: walletInfo,
         password: password,
         mnemonic: mnemonic,
-        parentAddress: parentAddress,
         passphrase: passphrase,
       );
 
diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart
index 3840b042e..a6475571d 100644
--- a/lib/reactions/on_current_wallet_change.dart
+++ b/lib/reactions/on_current_wallet_change.dart
@@ -1,6 +1,8 @@
+import 'package:cake_wallet/di.dart';
 import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
 import 'package:cake_wallet/entities/fiat_api_mode.dart';
 import 'package:cake_wallet/entities/update_haven_rate.dart';
+import 'package:cake_wallet/entities/wallet_manager.dart';
 import 'package:cake_wallet/ethereum/ethereum.dart';
 import 'package:cake_wallet/polygon/polygon.dart';
 import 'package:cake_wallet/solana/solana.dart';
@@ -59,6 +61,8 @@ void startCurrentWalletChangeReaction(
         return;
       }
 
+      await getIt.get<WalletManager>().ensureGroupHasHashedIdentifier(wallet);
+
       final node = settingsStore.getCurrentNode(wallet.type);
 
       startWalletSyncStatusChangeReaction(wallet, fiatConversionStore);
diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart
index d8257396f..f0df5fba1 100644
--- a/lib/solana/cw_solana.dart
+++ b/lib/solana/cw_solana.dart
@@ -11,7 +11,6 @@ class CWSolana extends Solana {
   WalletCredentials createSolanaNewWalletCredentials({
     required String name,
     String? mnemonic,
-    String? parentAddress,
     WalletInfo? walletInfo,
     String? password,
     String? passphrase,
@@ -21,7 +20,6 @@ class CWSolana extends Solana {
         walletInfo: walletInfo,
         password: password,
         mnemonic: mnemonic,
-        parentAddress: parentAddress,
         passphrase: passphrase,
       );
 
diff --git a/lib/src/screens/new_wallet/wallet_group_display_page.dart b/lib/src/screens/new_wallet/wallet_group_display_page.dart
index 549449a68..cd64353e2 100644
--- a/lib/src/screens/new_wallet/wallet_group_display_page.dart
+++ b/lib/src/screens/new_wallet/wallet_group_display_page.dart
@@ -150,7 +150,6 @@ class WalletGroupsDisplayBody extends StatelessWidget {
       arguments: NewWalletArguments(
         type: walletGroupsDisplayViewModel.type,
         mnemonic: mnemonic,
-        parentAddress: walletGroupsDisplayViewModel.parentAddress,
         isChildWallet: true,
       ),
     );
diff --git a/lib/src/screens/wallet/wallet_edit_page.dart b/lib/src/screens/wallet/wallet_edit_page.dart
index 340091a1e..9e62284de 100644
--- a/lib/src/screens/wallet/wallet_edit_page.dart
+++ b/lib/src/screens/wallet/wallet_edit_page.dart
@@ -112,7 +112,7 @@ class WalletEditPage extends BasePage {
                                                 pageArguments.editingWallet,
                                                 password: password,
                                                 isWalletGroup: pageArguments.isWalletGroup,
-                                                groupParentAddress: pageArguments.parentAddress,
+                                                walletGroupKey: pageArguments.walletGroupKey,
                                               );
                                             },
                                             callback: (bool isAuthenticatedSuccessfully,
@@ -128,7 +128,7 @@ class WalletEditPage extends BasePage {
                                     await walletEditViewModel.changeName(
                                       pageArguments.editingWallet,
                                       isWalletGroup: pageArguments.isWalletGroup,
-                                      groupParentAddress: pageArguments.parentAddress,
+                                      walletGroupKey: pageArguments.walletGroupKey,
                                     );
                                     confirmed = true;
                                   }
diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart
index 681ca4d8a..569dce958 100644
--- a/lib/src/screens/wallet_list/wallet_list_page.dart
+++ b/lib/src/screens/wallet_list/wallet_list_page.dart
@@ -227,7 +227,7 @@ class WalletListBodyState extends State<WalletListBody> {
                                     editingWallet: wallet,
                                     isWalletGroup: true,
                                     groupName: groupName,
-                                    parentAddress: group.parentAddress,
+                                    walletGroupKey: group.groupKey,
                                   ),
                                 );
                               },
diff --git a/lib/tron/cw_tron.dart b/lib/tron/cw_tron.dart
index bf2fac590..2726e873d 100644
--- a/lib/tron/cw_tron.dart
+++ b/lib/tron/cw_tron.dart
@@ -14,16 +14,15 @@ class CWTron extends Tron {
     WalletInfo? walletInfo,
     String? password,
     String? mnemonic,
-    String? parentAddress,
     String? passphrase,
   }) =>
       TronNewWalletCredentials(
-          name: name,
-          walletInfo: walletInfo,
-          password: password,
-          mnemonic: mnemonic,
-          passphrase: passphrase,
-          parentAddress: parentAddress);
+        name: name,
+        walletInfo: walletInfo,
+        password: password,
+        mnemonic: mnemonic,
+        passphrase: passphrase,
+      );
 
   @override
   WalletCredentials createTronRestoreWalletFromSeedCredentials({
diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart
index bd6732b4a..edaff441d 100644
--- a/lib/view_model/wallet_creation_vm.dart
+++ b/lib/view_model/wallet_creation_vm.dart
@@ -4,6 +4,7 @@ import 'package:cake_wallet/core/wallet_creation_service.dart';
 import 'package:cake_wallet/di.dart';
 import 'package:cake_wallet/entities/background_tasks.dart';
 import 'package:cake_wallet/entities/generate_name.dart';
+import 'package:cake_wallet/entities/hash_wallet_identifier.dart';
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/nano/nano.dart';
 import 'package:cake_wallet/store/app_store.dart';
@@ -103,13 +104,16 @@ abstract class WalletCreationVMBase with Store {
         showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven,
         derivationInfo: credentials.derivationInfo ?? getDefaultCreateDerivation(),
         hardwareWalletType: credentials.hardwareWalletType,
-        parentAddress: credentials.parentAddress,
       );
 
       credentials.walletInfo = walletInfo;
       final wallet = restoreWallet != null
           ? await processFromRestoredWallet(credentials, restoreWallet)
           : await process(credentials);
+
+      final isNonSeedWallet = isRecovery ? wallet.seed == null : false;
+      walletInfo.isNonSeedWallet = isNonSeedWallet;
+      walletInfo.hashedWalletIdentifier = createHashedWalletIdentifier(wallet);
       walletInfo.address = wallet.walletAddresses.address;
       await _walletInfoSource.add(walletInfo);
       await _appStore.changeCurrentWallet(wallet);
diff --git a/lib/view_model/wallet_groups_display_view_model.dart b/lib/view_model/wallet_groups_display_view_model.dart
index 08515febf..09d6d656c 100644
--- a/lib/view_model/wallet_groups_display_view_model.dart
+++ b/lib/view_model/wallet_groups_display_view_model.dart
@@ -47,8 +47,6 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
   @observable
   WalletInfo? selectedSingleWallet;
 
-  @observable
-  String? parentAddress;
 
   @observable
   bool isFetchingMnemonic;
@@ -77,9 +75,6 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
         walletToUse.name,
       );
 
-      parentAddress =
-          isGroupSelected ? selectedWalletGroup!.parentAddress : selectedSingleWallet!.address;
-
       return wallet.seed;
     } catch (e) {
       return null;
@@ -130,11 +125,14 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
         // Check that selected wallet type is not present already in group
         bool isSameTypeAsSelectedWallet = wallet.type == type;
 
+        bool isNonSeedWallet = wallet.isNonSeedWallet;
+
         // Exclude if any of these conditions are true
         return isNonBIP39Wallet ||
             isNanoDerivationType ||
             isElectrumDerivationType ||
-            isSameTypeAsSelectedWallet;
+            isSameTypeAsSelectedWallet ||
+            isNonSeedWallet;
       });
 
       if (shouldExcludeGroup) continue;
diff --git a/lib/view_model/wallet_list/wallet_edit_view_model.dart b/lib/view_model/wallet_list/wallet_edit_view_model.dart
index 343f160db..5379f1679 100644
--- a/lib/view_model/wallet_list/wallet_edit_view_model.dart
+++ b/lib/view_model/wallet_list/wallet_edit_view_model.dart
@@ -40,7 +40,7 @@ abstract class WalletEditViewModelBase with Store {
   Future<void> changeName(
     WalletListItem walletItem, {
     String? password,
-    String? groupParentAddress,
+    String? walletGroupKey,
     bool isWalletGroup = false,
   }) async {
     state = WalletEditRenamePending();
@@ -48,7 +48,7 @@ abstract class WalletEditViewModelBase with Store {
     if (isWalletGroup) {
       _walletManager.updateWalletGroups();
 
-      _walletManager.setGroupName(groupParentAddress!, newName);
+      _walletManager.setGroupName(walletGroupKey!, newName);
     } else {
       await _walletLoadingService.renameWallet(
         walletItem.type,
diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart
index aa933eadc..0cd730028 100644
--- a/lib/view_model/wallet_new_vm.dart
+++ b/lib/view_model/wallet_new_vm.dart
@@ -109,7 +109,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
           password: walletPassword,
           passphrase: passphrase,
           mnemonic: newWalletArguments!.mnemonic,
-          parentAddress: newWalletArguments!.parentAddress,
         );
       case WalletType.haven:
         return haven!.createHavenNewWalletCredentials(
@@ -119,7 +118,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
           name: name,
           password: walletPassword,
           mnemonic: newWalletArguments!.mnemonic,
-          parentAddress: newWalletArguments!.parentAddress,
           passphrase: passphrase,
         );
       case WalletType.bitcoinCash:
@@ -128,7 +126,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
           password: walletPassword,
           passphrase: passphrase,
           mnemonic: newWalletArguments!.mnemonic,
-          parentAddress: newWalletArguments!.parentAddress,
         );
       case WalletType.nano:
       case WalletType.banano:
@@ -136,7 +133,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
           name: name,
           password: walletPassword,
           mnemonic: newWalletArguments!.mnemonic,
-          parentAddress: newWalletArguments!.parentAddress,
           passphrase: passphrase,
         );
       case WalletType.polygon:
@@ -144,7 +140,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
           name: name,
           password: walletPassword,
           mnemonic: newWalletArguments!.mnemonic,
-          parentAddress: newWalletArguments!.parentAddress,
           passphrase: passphrase,
         );
       case WalletType.solana:
@@ -152,7 +147,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
           name: name,
           password: walletPassword,
           mnemonic: newWalletArguments!.mnemonic,
-          parentAddress: newWalletArguments!.parentAddress,
           passphrase: passphrase,
         );
       case WalletType.tron:
@@ -160,7 +154,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
           name: name,
           password: walletPassword,
           mnemonic: newWalletArguments!.mnemonic,
-          parentAddress: newWalletArguments!.parentAddress,
           passphrase: passphrase,
         );
       case WalletType.wownero:
diff --git a/tool/configure.dart b/tool/configure.dart
index 214288078..c26e3f44b 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -160,7 +160,7 @@ abstract class Bitcoin {
     String? passphrase,
   });
   WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({required String name, required String password, required String wif, WalletInfo? walletInfo});
-  WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic, String? parentAddress});
+  WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic});
   WalletCredentials createBitcoinHardwareWalletCredentials({required String name, required HardwareAccountData accountData, WalletInfo? walletInfo});
   List<String> getWordList();
   Map<String, String> getWalletKeys(Object wallet);
@@ -882,7 +882,7 @@ import 'package:eth_sig_util/util/utils.dart';
 abstract class Ethereum {
   List<String> getEthereumWordList(String language);
   WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
-  WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase});
+  WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? passphrase});
   WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
   WalletCredentials createEthereumRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
   WalletCredentials createEthereumHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo});
@@ -989,7 +989,7 @@ import 'package:eth_sig_util/util/utils.dart';
 abstract class Polygon {
   List<String> getPolygonWordList(String language);
   WalletService createPolygonWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
-  WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase});
+  WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? passphrase});
   WalletCredentials createPolygonRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
   WalletCredentials createPolygonRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
   WalletCredentials createPolygonHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo});
@@ -1077,7 +1077,7 @@ abstract class BitcoinCash {
       Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect);
 
   WalletCredentials createBitcoinCashNewWalletCredentials(
-      {required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic, String? parentAddress});
+      {required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic});
 
   WalletCredentials createBitcoinCashRestoreWalletFromSeedCredentials(
       {required String name, required String mnemonic, required String password, String? passphrase});
@@ -1161,7 +1161,6 @@ abstract class Nano {
     required String name,
     String? password,
     String? mnemonic,
-    String? parentAddress,
     WalletInfo? walletInfo,
     String? passphrase,
   });
@@ -1281,7 +1280,7 @@ abstract class Solana {
   List<String> getSolanaWordList(String language);
   WalletService createSolanaWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
   WalletCredentials createSolanaNewWalletCredentials(
-      {required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase});
+      {required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? passphrase});
   WalletCredentials createSolanaRestoreWalletFromSeedCredentials(
       {required String name, required String mnemonic, required String password, String? passphrase});
   WalletCredentials createSolanaRestoreWalletFromPrivateKey(
@@ -1369,7 +1368,7 @@ import 'package:cw_tron/default_tron_tokens.dart';
 abstract class Tron {
   List<String> getTronWordList(String language);
   WalletService createTronWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
-  WalletCredentials createTronNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? parentAddress, String? passphrase});
+  WalletCredentials createTronNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? passphrase});
   WalletCredentials createTronRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
   WalletCredentials createTronRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
   String getAddress(WalletBase wallet);
diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart
index 48614900a..0ef38e939 100644
--- a/tool/utils/secret_key.dart
+++ b/tool/utils/secret_key.dart
@@ -77,6 +77,7 @@ class SecretKey {
     SecretKey('moneroTestWalletBlockHeight', () => ''),
     SecretKey('chainflipApiKey', () => ''),
     SecretKey('chainflipAffiliateFee', () => ''),
+    SecretKey('walletGroupSalt', () => hex.encode(encrypt.Key.fromSecureRandom(16).bytes)),
   ];
 
   static final evmChainsSecrets = [
@@ -88,6 +89,7 @@ class SecretKey {
 
   static final solanaSecrets = [
     SecretKey('ankrApiKey', () => ''),
+    SecretKey('nowNodesApiKey', () => ''),
     SecretKey('chainStackApiKey', () => ''),
   ];
 

From 1aad8366c4786ffddbd0afcd5b18cd2a6257eff8 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Thu, 6 Mar 2025 19:39:41 +0200
Subject: [PATCH 03/14] Cw 793 implement kryptonim dfx to fiat buy sell option
 (#2068)

* init commit

* add authorization data

* Update lib/buy/kryptonim/kryptonim.dart

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 .github/workflows/pr_test_build_android.yml |   1 +
 .github/workflows/pr_test_build_linux.yml   |   1 +
 assets/images/kryptonim_dark.png            | Bin 0 -> 20086 bytes
 assets/images/kryptonim_light.png           | Bin 0 -> 19654 bytes
 lib/buy/buy_provider.dart                   |   2 +-
 lib/buy/buy_quote.dart                      |  26 +++
 lib/buy/dfx/dfx_buy_provider.dart           |   4 +-
 lib/buy/kryptonim/kryptonim.dart            | 222 ++++++++++++++++++++
 lib/buy/meld/meld_buy_provider.dart         |   2 +-
 lib/buy/moonpay/moonpay_provider.dart       |   4 +-
 lib/buy/onramper/onramper_buy_provider.dart |   2 +-
 lib/buy/payment_method.dart                 |   9 +
 lib/di.dart                                 |   5 +
 lib/entities/provider_types.dart            |  14 +-
 lib/view_model/buy/buy_sell_view_model.dart |   2 +-
 tool/utils/secret_key.dart                  |   1 +
 16 files changed, 285 insertions(+), 10 deletions(-)
 create mode 100644 assets/images/kryptonim_dark.png
 create mode 100644 assets/images/kryptonim_light.png
 create mode 100644 lib/buy/kryptonim/kryptonim.dart

diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 6c7e82409..762144ac1 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -172,6 +172,7 @@ jobs:
           # end of test secrets
           echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart
+          echo "const kryptonimApiKey = '${{ secrets.KRYPTONIM_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> lib/.secrets.g.dart
 
       - name: prepare monero_c and cache
diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml
index e307dc410..c5cb26dd9 100644
--- a/.github/workflows/pr_test_build_linux.yml
+++ b/.github/workflows/pr_test_build_linux.yml
@@ -168,6 +168,7 @@ jobs:
           # end of test secrets
           echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart
+          echo "const kryptonimApiKey = '${{ secrets.KRYPTONIM_API_KEY }}';" >> lib/.secrets.g.dart
           echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> lib/.secrets.g.dart
 
       - name: prepare monero_c and cache
diff --git a/assets/images/kryptonim_dark.png b/assets/images/kryptonim_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..646d550bac3af58eef0b07247f3882a5418098f6
GIT binary patch
literal 20086
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
bDFpr>tmA9K84ZD)00000NkvXXu0mjfHE~1x

literal 0
HcmV?d00001

diff --git a/assets/images/kryptonim_light.png b/assets/images/kryptonim_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..85e64a3f2296e0c9ba9f36bf8049d6b36c2a42ac
GIT binary patch
literal 19654
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
YAAETU0ll{R=Kufz07*qoM6N<$f~wlfivR!s

literal 0
HcmV?d00001

diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart
index 8e79e16b8..ea2bcae8f 100644
--- a/lib/buy/buy_provider.dart
+++ b/lib/buy/buy_provider.dart
@@ -49,7 +49,7 @@ abstract class BuyProvider {
       throw UnimplementedError();
 
   Future<List<PaymentMethod>> getAvailablePaymentTypes(
-          String fiatCurrency, String cryptoCurrency, bool isBuyAction) async =>
+      String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async =>
       [];
 
   Future<List<Quote>?> fetchQuote(
diff --git a/lib/buy/buy_quote.dart b/lib/buy/buy_quote.dart
index 72ab7bd7d..8da70361d 100644
--- a/lib/buy/buy_quote.dart
+++ b/lib/buy/buy_quote.dart
@@ -289,6 +289,29 @@ class Quote extends SelectableOption {
     );
   }
 
+  factory Quote.fromKryptonimJson(
+      Map<String, dynamic> json, bool isBuyAction, PaymentType paymentType) {
+    final fees = json['fees'] as Map<String, dynamic>;
+    final rate = _toDouble(json['rate']) ?? 0.0;
+    final limits = json['limits'] as Map<String, dynamic>;
+    final minLimit = _toDouble(limits['min_amount']) ?? 0.0;
+    final maxLimit = _toDouble(limits['max_amount']) ?? double.infinity;
+    final convertedAmount = _toDouble(json['converted_amount']) ?? 0.0;
+    final amount = _toDouble(json['amount']) ?? 0.0;
+    final calculatedRate = amount / convertedAmount;
+    return Quote(
+        rate:  calculatedRate,
+        feeAmount: _toDouble(fees['totalFee']) ?? 0.0,
+        networkFee: _toDouble(fees['network_fee']) ?? 0.0,
+        transactionFee: _toDouble(fees['operation_fee']) ?? 0.0,
+        payout: _toDouble(json['amount']) ?? 0.0,
+        paymentType: paymentType,
+        recommendations: [],
+        provider: ProvidersHelper.getProviderByType(ProviderType.kriptonim)!,
+        isBuyAction: isBuyAction,
+        limits: Limits(min: minLimit, max: maxLimit));
+  }
+
   static double? _toDouble(dynamic value) {
     if (value is int) {
       return value.toDouble();
@@ -299,4 +322,7 @@ class Quote extends SelectableOption {
     }
     return null;
   }
+
+  @override
+  String toString() => 'Quote: rate: $rate, feeAmount: $feeAmount, networkFee: $networkFee, transactionFee: $transactionFee, payout: $payout, paymentType: $paymentType, provider: $provider, quoteId: $quoteId, recommendations: $recommendations, isBuyAction: $isBuyAction, rampId: $rampId, rampName: $rampName, rampIconPath: $rampIconPath, [limits: min: ${limits?.min}, max: ${limits?.max}]';
 }
diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart
index eba48632b..ac50665f0 100644
--- a/lib/buy/dfx/dfx_buy_provider.dart
+++ b/lib/buy/dfx/dfx_buy_provider.dart
@@ -168,7 +168,7 @@ class DFXBuyProvider extends BuyProvider {
   }
 
   Future<List<PaymentMethod>> getAvailablePaymentTypes(
-      String fiatCurrency, String cryptoCurrency, bool isBuyAction) async {
+      String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async {
     final List<PaymentMethod> paymentMethods = [];
 
     if (isBuyAction) {
@@ -190,7 +190,7 @@ class DFXBuyProvider extends BuyProvider {
         });
       }
     } else {
-      final assetCredentials = await fetchAssetCredential(cryptoCurrency);
+      final assetCredentials = await fetchAssetCredential(cryptoCurrency.title);
       if (assetCredentials.isNotEmpty) {
         if (assetCredentials['sellable'] == true) {
           final availablePaymentTypes = [
diff --git a/lib/buy/kryptonim/kryptonim.dart b/lib/buy/kryptonim/kryptonim.dart
new file mode 100644
index 000000000..c439fa2f7
--- /dev/null
+++ b/lib/buy/kryptonim/kryptonim.dart
@@ -0,0 +1,222 @@
+import 'dart:convert';
+
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
+import 'package:cake_wallet/buy/buy_provider.dart';
+import 'package:cake_wallet/buy/buy_quote.dart';
+import 'package:cake_wallet/buy/payment_method.dart';
+import 'package:cake_wallet/entities/fiat_currency.dart';
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
+import 'package:cake_wallet/utils/show_pop_up.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/wallet_base.dart';
+import 'package:flutter/material.dart';
+import 'dart:developer';
+import 'package:http/http.dart' as http;
+import 'package:url_launcher/url_launcher.dart';
+
+class KryptonimBuyProvider extends BuyProvider {
+  KryptonimBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
+      : super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: null);
+
+  static const _isProduction = true;
+
+  static const _baseUrl = _isProduction ? 'app.kryptonim.com' : 'intg-api.kryptonim.com';
+  static const _baseWidgetUrl = _isProduction ? 'buy.kryptonim.com' : 'intg.kryptonim.com';
+  static const _quotePath = '/v2/ramp/buy/quotes';
+  static const _merchantId = 'a70fe053';
+
+  static String get _kryptonimApiKey => secrets.kryptonimApiKey;
+
+  @override
+  String get title => 'Kryptonim';
+
+  @override
+  String get providerDescription => 'Kryptonim Buy Provider';
+
+  @override
+  String get lightIcon => 'assets/images/kryptonim_light.png';
+
+  @override
+  String get darkIcon => 'assets/images/kryptonim_dark.png';
+
+  @override
+  bool get isAggregator => false;
+
+  Future<Map<String, dynamic>> getExchangeRates(
+      {required CryptoCurrency cryptoCurrency,
+      required String fiatCurrency,
+      required double amount}) async {
+    final url = Uri.https(_baseUrl, _quotePath, {'m': _merchantId});
+
+    final headers = {
+      'accept': 'application/json',
+      'Content-Type': 'application/json',
+      'Authorization': _kryptonimApiKey,
+    };
+
+    final body = jsonEncode({
+      'amount': amount,
+      'currency': fiatCurrency,
+      'converted_currency': cryptoCurrency.title,
+      'blockchain': _normalizeBlockChain(cryptoCurrency),
+      'quote_currency': fiatCurrency,
+    });
+
+    try {
+      final response = await http.post(url, headers: headers, body: body);
+
+      if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 401) {
+        return jsonDecode(response.body) as Map<String, dynamic>;
+      } else {
+        return {};
+      }
+    } catch (e) {
+      return {};
+    }
+  }
+
+  @override
+  Future<List<PaymentMethod>> getAvailablePaymentTypes(
+      String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async {
+
+    final data = await getExchangeRates(
+      cryptoCurrency: cryptoCurrency,
+      fiatCurrency: fiatCurrency,
+      amount: 100.0,
+    );
+
+    if (data.isEmpty || !data.containsKey('data')) return [];
+
+    final paymentMethods = (data['data'] as List<dynamic>)
+        .map((e) => PaymentMethod.fromKryptonimJson(e as Map<String, dynamic>))
+        .toList();
+
+    return paymentMethods;
+  }
+
+  @override
+  Future<List<Quote>?> fetchQuote({
+    required CryptoCurrency cryptoCurrency,
+    required FiatCurrency fiatCurrency,
+    required double amount,
+    required bool isBuyAction,
+    required String walletAddress,
+    PaymentType? paymentType,
+    String? countryCode,
+  }) async {
+    log('Kryptonim: Fetching quote: ${isBuyAction ? cryptoCurrency : fiatCurrency} -> ${isBuyAction ? fiatCurrency : cryptoCurrency}, amount: $amount');
+
+    final data = await getExchangeRates(
+      cryptoCurrency: cryptoCurrency,
+      fiatCurrency: fiatCurrency.toString(),
+      amount: amount,
+    );
+
+    if (!data.containsKey('data') || (data['data'] as List).isEmpty) {
+      return null;
+    }
+
+    final quotesList = data['data'] as List<dynamic>;
+
+    Map<String, dynamic>? selectedPaymentMethod;
+
+    if (paymentType == PaymentType.all || paymentType == null) {
+      selectedPaymentMethod = quotesList.first as Map<String, dynamic>;
+    } else {
+      for (var quote in quotesList) {
+        final quotePaymentType = PaymentMethod.getPaymentTypeId(quote['payment_method'] as String?);
+        if (quotePaymentType == paymentType) {
+          selectedPaymentMethod = quote as Map<String, dynamic>;
+          break;
+        }
+      }
+    }
+
+    if (selectedPaymentMethod == null) {
+      return null;
+    }
+
+    final selectedPaymentType =
+        PaymentMethod.getPaymentTypeId(selectedPaymentMethod['payment_method'] as String?);
+    final quote = Quote.fromKryptonimJson(selectedPaymentMethod, isBuyAction, selectedPaymentType);
+
+    quote.setFiatCurrency = fiatCurrency;
+    quote.setCryptoCurrency = cryptoCurrency;
+
+    return [quote];
+  }
+
+  @override
+  Future<void>? launchProvider(
+      {required BuildContext context,
+      required Quote quote,
+      required double amount,
+      required bool isBuyAction,
+      required String cryptoCurrencyAddress,
+      String? countryCode}) async {
+    final params = {
+      'amount': amount.toInt().toString(),
+      'currency': quote.fiatCurrency.name,
+      'convertedCurrency': quote.cryptoCurrency.title,
+      'blockchain': _normalizeBlockChain(quote.cryptoCurrency),
+      'address': cryptoCurrencyAddress,
+      'paymentMethod': normalizePaymentMethod(quote.paymentType),
+    };
+
+    final uri = Uri.https(_baseWidgetUrl, '/redirect-form', params);
+
+    try {
+      if (await canLaunchUrl(uri)) {
+        await launchUrl(uri, mode: LaunchMode.externalApplication);
+      } else {
+        throw Exception('Could not launch URL');
+      }
+    } catch (e) {
+      await showPopUp<void>(
+        context: context,
+        builder: (BuildContext context) {
+          return AlertWithOneAction(
+            alertTitle: "Kryptonim",
+            alertContent: "Payment provider is unavailable: $e",
+            buttonText: "OK",
+            buttonAction: () => Navigator.of(context).pop(),
+          );
+        },
+      );
+    }
+  }
+
+  String normalizePaymentMethod(PaymentType paymentType) {
+    switch (paymentType) {
+      case PaymentType.bankTransfer:
+        return 'bank';
+      case PaymentType.creditCard:
+      case PaymentType.debitCard:
+        return 'card';
+      default:
+        return paymentType.name.toLowerCase();
+    }
+  }
+
+  String _normalizeBlockChain(CryptoCurrency cur) {
+    String? blockchain = switch (cur.tag) {
+      'ETH' => 'Ethereum',
+      'POL' => 'Polygon',
+      'AVAXC' => 'Avalanche',
+      'SOL' => 'Solana',
+      _ => null,
+    };
+
+    if (blockchain == null) {
+      blockchain = switch (cur) {
+        CryptoCurrency.btc => 'Bitcoin',
+        CryptoCurrency.ltc => 'Litecoin',
+        CryptoCurrency.eth => 'Ethereum',
+        CryptoCurrency.maticpoly => 'Matic',
+        _ => null,
+      };
+    }
+
+    return blockchain ?? cur.fullName ?? '';
+  }
+}
diff --git a/lib/buy/meld/meld_buy_provider.dart b/lib/buy/meld/meld_buy_provider.dart
index a9759aab8..81ad35a40 100644
--- a/lib/buy/meld/meld_buy_provider.dart
+++ b/lib/buy/meld/meld_buy_provider.dart
@@ -53,7 +53,7 @@ class MeldBuyProvider extends BuyProvider {
 
   @override
   Future<List<PaymentMethod>> getAvailablePaymentTypes(
-      String fiatCurrency, String cryptoCurrency, bool isBuyAction) async {
+      String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async {
     final params = {'fiatCurrencies': fiatCurrency, 'statuses': 'LIVE,RECENTLY_ADDED,BUILDING'};
 
     final path = '$_providersProperties$_paymentMethodsPath';
diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart
index a6966db33..7bca7d405 100644
--- a/lib/buy/moonpay/moonpay_provider.dart
+++ b/lib/buy/moonpay/moonpay_provider.dart
@@ -126,11 +126,11 @@ class MoonPayProvider extends BuyProvider {
   }
 
   Future<List<PaymentMethod>> getAvailablePaymentTypes(
-      String fiatCurrency, String cryptoCurrency, bool isBuyAction) async {
+      String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async {
     final List<PaymentMethod> paymentMethods = [];
 
     if (isBuyAction) {
-      final fiatBuyCredentials = await fetchFiatCredentials(fiatCurrency, cryptoCurrency, null);
+      final fiatBuyCredentials = await fetchFiatCredentials(fiatCurrency, cryptoCurrency.title, null);
       if (fiatBuyCredentials.isNotEmpty) {
         final paymentMethod = fiatBuyCredentials['paymentMethod'] as String?;
         paymentMethods.add(PaymentMethod.fromMoonPayJson(
diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart
index f229cb833..5480ab2cd 100644
--- a/lib/buy/onramper/onramper_buy_provider.dart
+++ b/lib/buy/onramper/onramper_buy_provider.dart
@@ -48,7 +48,7 @@ class OnRamperBuyProvider extends BuyProvider {
   bool get isAggregator => true;
 
   Future<List<PaymentMethod>> getAvailablePaymentTypes(
-      String fiatCurrency, String cryptoCurrency, bool isBuyAction) async {
+      String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async {
     final params = {
       'fiatCurrency': fiatCurrency,
       'type': isBuyAction ? 'buy' : 'sell',
diff --git a/lib/buy/payment_method.dart b/lib/buy/payment_method.dart
index cf85c441b..14b119aa0 100644
--- a/lib/buy/payment_method.dart
+++ b/lib/buy/payment_method.dart
@@ -218,6 +218,15 @@ class PaymentMethod extends SelectableOption {
         customDescription: json['description'] as String?);
   }
 
+  factory PaymentMethod.fromKryptonimJson(Map<String, dynamic> json) {
+    final type = PaymentMethod.getPaymentTypeId(json['payment_method'] as String?);
+    return PaymentMethod(
+      paymentMethodType: type,
+      customTitle: json['payment_method'] as String? ?? 'Unknown',
+      customIconPath: 'assets/images/card.png',
+    );
+  }
+
   static PaymentType getPaymentTypeId(String? type) {
     switch (type?.toLowerCase()) {
       case 'banktransfer':
diff --git a/lib/di.dart b/lib/di.dart
index 174183f9a..83b3efaea 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -255,6 +255,7 @@ import 'package:get_it/get_it.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 import 'package:shared_preferences/shared_preferences.dart';
+import 'buy/kryptonim/kryptonim.dart';
 import 'buy/meld/meld_buy_provider.dart';
 import 'src/screens/buy/buy_sell_page.dart';
 import 'cake_pay/cake_pay_payment_credantials.dart';
@@ -1019,6 +1020,10 @@ Future<void> setup({
     wallet: getIt.get<AppStore>().wallet!,
   ));
 
+  getIt.registerFactory<KryptonimBuyProvider>(() => KryptonimBuyProvider(
+    wallet: getIt.get<AppStore>().wallet!,
+  ));
+
   getIt.registerFactoryParam<WebViewPage, String, Uri>((title, uri) => WebViewPage(title, uri));
 
   getIt.registerFactory(() => ExchangeViewModel(
diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart
index c65ac267b..5888970b0 100644
--- a/lib/entities/provider_types.dart
+++ b/lib/entities/provider_types.dart
@@ -1,5 +1,6 @@
 import 'package:cake_wallet/buy/buy_provider.dart';
 import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
+import 'package:cake_wallet/buy/kryptonim/kryptonim.dart';
 import 'package:cake_wallet/buy/meld/meld_buy_provider.dart';
 import 'package:cake_wallet/buy/moonpay/moonpay_provider.dart';
 import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
@@ -8,7 +9,7 @@ import 'package:cake_wallet/di.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:http/http.dart';
 
-enum ProviderType { robinhood, dfx, onramper, moonpay, meld }
+enum ProviderType { robinhood, dfx, onramper, moonpay, meld, kriptonim }
 
 extension ProviderTypeName on ProviderType {
   String get title {
@@ -23,6 +24,8 @@ extension ProviderTypeName on ProviderType {
         return 'MoonPay';
       case ProviderType.meld:
         return 'Meld';
+      case ProviderType.kriptonim:
+        return 'Kriptonim';
     }
   }
 
@@ -38,6 +41,8 @@ extension ProviderTypeName on ProviderType {
         return 'moonpay_provider';
       case ProviderType.meld:
         return 'meld_provider';
+      case ProviderType.kriptonim:
+        return 'kriptonim_provider';
     }
   }
 }
@@ -59,6 +64,7 @@ class ProvidersHelper {
           ProviderType.dfx,
           ProviderType.robinhood,
           ProviderType.moonpay,
+          ProviderType.kriptonim
         ];
       case WalletType.litecoin:
       case WalletType.bitcoinCash:
@@ -66,13 +72,15 @@ class ProvidersHelper {
         return [
           ProviderType.onramper,
           ProviderType.robinhood,
-          ProviderType.moonpay
+          ProviderType.moonpay,
+          ProviderType.kriptonim
         ];
       case WalletType.tron:
         return [
           ProviderType.onramper,
           ProviderType.robinhood,
           ProviderType.moonpay,
+          ProviderType.kriptonim
         ];
       case WalletType.none:
       case WalletType.haven:
@@ -127,6 +135,8 @@ class ProvidersHelper {
         return getIt.get<MoonPayProvider>();
       case ProviderType.meld:
         return getIt.get<MeldBuyProvider>();
+      case ProviderType.kriptonim:
+        return getIt.get<KryptonimBuyProvider>();
       default:
         return null;
     }
diff --git a/lib/view_model/buy/buy_sell_view_model.dart b/lib/view_model/buy/buy_sell_view_model.dart
index 508d68a82..02b2b3576 100644
--- a/lib/view_model/buy/buy_sell_view_model.dart
+++ b/lib/view_model/buy/buy_sell_view_model.dart
@@ -351,7 +351,7 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
     paymentMethodState = PaymentMethodLoading();
     selectedPaymentMethod = null;
     final result = await Future.wait(providerList.map((element) => element
-        .getAvailablePaymentTypes(fiatCurrency.title, cryptoCurrency.title, isBuyAction)
+        .getAvailablePaymentTypes(fiatCurrency.title, cryptoCurrency, isBuyAction)
         .timeout(
           Duration(seconds: 10),
           onTimeout: () => [],
diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart
index 0ef38e939..a8ebcc8cc 100644
--- a/tool/utils/secret_key.dart
+++ b/tool/utils/secret_key.dart
@@ -77,6 +77,7 @@ class SecretKey {
     SecretKey('moneroTestWalletBlockHeight', () => ''),
     SecretKey('chainflipApiKey', () => ''),
     SecretKey('chainflipAffiliateFee', () => ''),
+    SecretKey('kryptonimApiKey', () => ''),
     SecretKey('walletGroupSalt', () => hex.encode(encrypt.Key.fromSecureRandom(16).bytes)),
   ];
 

From c2996ac303ee34de675c70e4612081760186ffa1 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Thu, 6 Mar 2025 20:00:10 +0200
Subject: [PATCH 04/14] CW-983-SwapTrade-enhancements (#2057)

* Update swaptrade_exchange_provider.dart

* fix network and trade state issues

* Update trade_filter_store.dart

* hopefully final changes :3

* re-enable swaptrade [skip ci]

* fix rate calculation issue

* Add refund address

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
---
 lib/entities/default_settings_migration.dart  |  7 +++
 .../provider/swaptrade_exchange_provider.dart | 44 ++++++++++++-------
 lib/exchange/trade_state.dart                 |  2 +
 lib/main.dart                                 |  2 +-
 lib/store/dashboard/trade_filter_store.dart   | 16 +++++--
 .../dashboard/dashboard_view_model.dart       |  5 +++
 6 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index a02b40d44..e57d71174 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -401,6 +401,13 @@ Future<void> defaultSettingsMigration(
             enabled: false,
           );
 			    break;
+        case 48:
+          _changeExchangeProviderAvailability(
+            sharedPreferences,
+            providerName: "SwapTrade",
+            enabled: true,
+          );
+			    break;
         default:
           break;
       }
diff --git a/lib/exchange/provider/swaptrade_exchange_provider.dart b/lib/exchange/provider/swaptrade_exchange_provider.dart
index 9553c9559..d3f64b712 100644
--- a/lib/exchange/provider/swaptrade_exchange_provider.dart
+++ b/lib/exchange/provider/swaptrade_exchange_provider.dart
@@ -26,9 +26,11 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
               CryptoCurrency.ltc,
               CryptoCurrency.ada,
               CryptoCurrency.bch,
-              CryptoCurrency.usdt,
+              CryptoCurrency.usdterc20,
+              CryptoCurrency.usdttrc20,
               CryptoCurrency.bnb,
               CryptoCurrency.xmr,
+              CryptoCurrency.zec,
             ].contains(element))
         .toList())
   ];
@@ -39,6 +41,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
   static const getRate = '/api/swap/get-rate';
   static const getCoins = '/api/swap/get-coins';
   static const createOrder = '/api/swap/create-order';
+  static const order = '/api/swap/order';
 
   @override
   String get title => 'SwapTrade';
@@ -108,6 +111,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
       final body = <String, String>{
         'coin_send': _normalizeCurrency(from),
         'coin_receive': _normalizeCurrency(to),
+        'amount': amount.toString(),
         'ref': 'cake',
       };
 
@@ -120,7 +124,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
 
       final data = responseBody['data'] as Map<String, dynamic>;
       double rate = double.parse(data['price'].toString());
-      return rate;
+      return rate > 0 ? isFixedRateMode ? amount / rate : rate / amount : 0.0;
     } catch (e) {
       printV("error fetching rate: ${e.toString()}");
       return 0.0;
@@ -138,18 +142,16 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
       final params = <String, dynamic>{};
       var body = <String, dynamic>{
         'coin_send': _normalizeCurrency(request.fromCurrency),
+        'coin_send_network': _networkFor(request.fromCurrency),
         'coin_receive': _normalizeCurrency(request.toCurrency),
+        'coin_receive_network': _networkFor(request.toCurrency),
         'amount_send': request.fromAmount,
         'recipient': request.toAddress,
         'ref': 'cake',
         'markup': markup,
+        'refund_address': request.refundAddress,
       };
 
-      String? fromNetwork = _networkFor(request.fromCurrency);
-      String? toNetwork = _networkFor(request.toCurrency);
-      if (fromNetwork != null) body['coin_send_network'] = fromNetwork;
-      if (toNetwork != null) body['coin_receive_network'] = toNetwork;
-
       final uri = Uri.https(apiAuthority, createOrder, params);
       final response = await post(uri, body: body, headers: headers);
       final responseBody = json.decode(response.body) as Map<String, dynamic>;
@@ -193,7 +195,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
         'order_id': id,
       };
 
-      final uri = Uri.https(apiAuthority, createOrder, params);
+      final uri = Uri.https(apiAuthority, order, params);
       final response = await post(uri, body: body, headers: headers);
       final responseBody = json.decode(response.body) as Map<String, dynamic>;
 
@@ -211,10 +213,14 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
       final toCurrency = responseData['coin_receive'] as String;
       final to = CryptoCurrency.fromString(toCurrency);
       final inputAddress = responseData['server_address'] as String;
+      final payoutAddress = responseData['recipient'] as String;
       final status = responseData['status'] as String;
       final state = TradeState.deserialize(raw: status);
       final response_id = responseData['order_id'] as String;
       final expectedSendAmount = responseData['amount_send'] as String;
+      final expectedReceiveAmount = responseData['amount_receive'] as String;
+      final memo = responseData['memo'] as String?;
+      final createdAt = responseData['created_at'] as String?;
 
       return Trade(
         id: response_id,
@@ -223,7 +229,11 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
         provider: description,
         inputAddress: inputAddress,
         amount: expectedSendAmount,
+        payoutAddress: payoutAddress,
         state: state,
+        receiveAmount: expectedReceiveAmount,
+        memo: memo,
+        createdAt: DateTime.tryParse(createdAt ?? ''),
       );
     } catch (e) {
       printV("error getting trade: ${e.toString()}");
@@ -242,14 +252,14 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
     }
   }
 
-  String? _networkFor(CryptoCurrency currency) {
-    switch (currency) {
-      case CryptoCurrency.usdt:
-        return "USDT_ERC20";
-      case CryptoCurrency.bnb:
-        return "BNB_BSC";
-      default:
-        return null;
-    }
+  String _networkFor(CryptoCurrency currency) {
+    final network = switch (currency) {
+      CryptoCurrency.eth => 'ETH',
+      CryptoCurrency.bnb => 'BNB_BSC',
+      CryptoCurrency.usdterc20 => 'USDT_ERC20',
+      CryptoCurrency.usdttrc20 => 'TRX_USDT_S2UZ',
+      _ => '',
+    };
+    return network;
   }
 }
diff --git a/lib/exchange/trade_state.dart b/lib/exchange/trade_state.dart
index 6d2472a11..7bce8c7e7 100644
--- a/lib/exchange/trade_state.dart
+++ b/lib/exchange/trade_state.dart
@@ -131,6 +131,8 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
       case 'success':
       case 'done':
         return success;
+      case 'expired':
+        return expired;
       default:
         throw Exception('Unexpected token: $raw in TradeState deserialize');
     }
diff --git a/lib/main.dart b/lib/main.dart
index 0e02ef97b..1eedfa6a9 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -215,7 +215,7 @@ Future<void> initializeAppConfigs() async {
     secureStorage: secureStorage,
     anonpayInvoiceInfo: anonpayInvoiceInfo,
     havenSeedStore: havenSeedStore,
-    initialMigrationVersion: 47,
+    initialMigrationVersion: 48,
   );
 }
 
diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart
index a2c6e3646..6a98329d6 100644
--- a/lib/store/dashboard/trade_filter_store.dart
+++ b/lib/store/dashboard/trade_filter_store.dart
@@ -19,7 +19,8 @@ abstract class TradeFilterStoreBase with Store {
         displayChainflip = true,
         displayThorChain = true,
         displayLetsExchange = true,
-        displayStealthEx = true;
+        displayStealthEx = true,
+        displaySwapTrade = true;
 
   @observable
   bool displayXMRTO;
@@ -54,6 +55,9 @@ abstract class TradeFilterStoreBase with Store {
   @observable
   bool displayStealthEx;
 
+  @observable
+  bool displaySwapTrade;
+
   @computed
   bool get displayAllTrades =>
       displayChangeNow &&
@@ -64,7 +68,8 @@ abstract class TradeFilterStoreBase with Store {
       displayChainflip &&
       displayThorChain &&
       displayLetsExchange &&
-      displayStealthEx;
+      displayStealthEx &&
+      displaySwapTrade;
 
   @action
   void toggleDisplayExchange(ExchangeProviderDescription provider) {
@@ -102,6 +107,8 @@ abstract class TradeFilterStoreBase with Store {
       case ExchangeProviderDescription.stealthEx:
         displayStealthEx = !displayStealthEx;
         break;
+        case ExchangeProviderDescription.swapTrade:
+        displaySwapTrade = !displaySwapTrade;
       case ExchangeProviderDescription.all:
         if (displayAllTrades) {
           displayChangeNow = false;
@@ -115,6 +122,7 @@ abstract class TradeFilterStoreBase with Store {
           displayThorChain = false;
           displayLetsExchange = false;
           displayStealthEx = false;
+          displaySwapTrade = false;
         } else {
           displayChangeNow = true;
           displaySideShift = true;
@@ -127,6 +135,7 @@ abstract class TradeFilterStoreBase with Store {
           displayThorChain = true;
           displayLetsExchange = true;
           displayStealthEx = true;
+          displaySwapTrade = true;
         }
         break;
     }
@@ -158,7 +167,8 @@ abstract class TradeFilterStoreBase with Store {
                     item.trade.provider == ExchangeProviderDescription.thorChain) ||
                 (displayLetsExchange &&
                     item.trade.provider == ExchangeProviderDescription.letsExchange) ||
-                (displayStealthEx && item.trade.provider == ExchangeProviderDescription.stealthEx))
+                (displayStealthEx && item.trade.provider == ExchangeProviderDescription.stealthEx) ||
+                (displaySwapTrade && item.trade.provider == ExchangeProviderDescription.swapTrade))
             .toList()
         : _trades;
   }
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 99283a409..40a07e666 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -152,6 +152,11 @@ abstract class DashboardViewModelBase with Store {
                 caption: ExchangeProviderDescription.stealthEx.title,
                 onChanged: () =>
                     tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.stealthEx)),
+            FilterItem(
+                value: () => tradeFilterStore.displaySwapTrade,
+                caption: ExchangeProviderDescription.swapTrade.title,
+                onChanged: () => tradeFilterStore
+                    .toggleDisplayExchange(ExchangeProviderDescription.swapTrade)),
           ]
         },
         subname = '',

From 6cc9f4f757d41cee9deb48de9aea9dcb11f788ca Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Thu, 6 Mar 2025 10:00:44 -0800
Subject: [PATCH 05/14] CW-949 backup error messages (#2059)

* [skip-ci] minor

* dont initialize with restore button enabled + error handling updates
---
 .../restore_from_backup_view_model.dart       | 33 +++++++++++++++----
 lib/view_model/wallet_restore_view_model.dart |  1 -
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/lib/view_model/restore_from_backup_view_model.dart b/lib/view_model/restore_from_backup_view_model.dart
index 247e6d43d..f9894b592 100644
--- a/lib/view_model/restore_from_backup_view_model.dart
+++ b/lib/view_model/restore_from_backup_view_model.dart
@@ -13,13 +13,12 @@ import 'package:cake_wallet/store/authentication_store.dart';
 
 part 'restore_from_backup_view_model.g.dart';
 
-class RestoreFromBackupViewModel = RestoreFromBackupViewModelBase
-    with _$RestoreFromBackupViewModel;
+class RestoreFromBackupViewModel = RestoreFromBackupViewModelBase with _$RestoreFromBackupViewModel;
 
 abstract class RestoreFromBackupViewModelBase with Store {
   RestoreFromBackupViewModelBase(this.backupService)
-  : state = InitialExecutionState(),
-    filePath = '';
+      : state = InitialExecutionState(),
+        filePath = '';
 
   final BackupService backupService;
 
@@ -45,8 +44,14 @@ abstract class RestoreFromBackupViewModelBase with Store {
       final file = File(filePath);
       final data = await file.readAsBytes();
 
+      
       await backupService.importBackup(data, password);
-      await initializeAppAtRoot(reInitializing: true);
+
+      try {
+        await initializeAppAtRoot(reInitializing: true);
+      } catch (e, s) {
+        throw Exception('failed_app_initialization: $e $s');
+      }
 
       final store = getIt.get<AppStore>();
       ReactionDisposer? reaction;
@@ -63,11 +68,25 @@ abstract class RestoreFromBackupViewModelBase with Store {
 
       state = ExecutedSuccessfullyState();
     } catch (e, s) {
-      var msg = e.toString();
+      var msg = e.toString().toLowerCase();
 
-      if (msg.toLowerCase().contains("message authentication code (mac)")) {
+      // can't use a switch here because of .contains() / not an exact match
+      bool shouldBeMadeAware = false;
+      if (msg.contains("message authentication code (mac)")) {
         msg = 'Incorrect backup password';
+      } else if (msg.contains("faileddecryption")) {
+        msg = 'Failed to decrypt backup file, please check you entered the right password';
+      } else if (msg.contains("failed_to_decode")) {
+        msg = 'Failed to decode backup file, please try again';
+        shouldBeMadeAware = true;
+      } else if (msg.contains("failed_app_initialization")) {
+        msg = 'Failed to initialize app, please try again';
+        shouldBeMadeAware = true;
       } else {
+        shouldBeMadeAware = true;
+      }
+
+      if (shouldBeMadeAware) {
         await ExceptionHandler.onError(FlutterErrorDetails(
           exception: e,
           stack: s,
diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart
index 8a497a605..3e5220447 100644
--- a/lib/view_model/wallet_restore_view_model.dart
+++ b/lib/view_model/wallet_restore_view_model.dart
@@ -67,7 +67,6 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
         availableModes = [WalletRestoreMode.seed];
         break;
     }
-    isButtonEnabled = !hasSeedLanguageSelector && !hasBlockchainHeightLanguageSelector;
     walletCreationService.changeWalletType(type: type);
   }
 

From bcbc7ee130ec2a49a38637afde961e2053ea8cab Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Thu, 6 Mar 2025 20:04:41 +0200
Subject: [PATCH 06/14] rename success rate label (#2055)

* rename success rate label

* move successRate quote to the recommended section

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 lib/buy/buy_quote.dart                      |  2 +-
 lib/view_model/buy/buy_sell_view_model.dart | 11 +++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/lib/buy/buy_quote.dart b/lib/buy/buy_quote.dart
index 8da70361d..1805b7e1a 100644
--- a/lib/buy/buy_quote.dart
+++ b/lib/buy/buy_quote.dart
@@ -16,7 +16,7 @@ extension RecommendationTitle on ProviderRecommendation {
       case ProviderRecommendation.lowKyc:
         return 'LOW KYC';
       case ProviderRecommendation.successRate:
-        return 'SUCCESS RATE';
+        return 'HIGHEST SUCCESS RATE';
     }
   }
 }
diff --git a/lib/view_model/buy/buy_sell_view_model.dart b/lib/view_model/buy/buy_sell_view_model.dart
index 02b2b3576..436f66905 100644
--- a/lib/view_model/buy/buy_sell_view_model.dart
+++ b/lib/view_model/buy/buy_sell_view_model.dart
@@ -415,6 +415,17 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
       return true;
     }).toList();
 
+    final List<Quote> successRateQuotes = validQuotes.where((element) =>
+    element.provider is OnRamperBuyProvider &&
+        element.recommendations.contains(ProviderRecommendation.successRate)
+    ).toList();
+
+    for (final quote in successRateQuotes) {
+      if (!uniqueProviderQuotes.contains(quote)) {
+        uniqueProviderQuotes.add(quote);
+      }
+    }
+
     sortedRecommendedQuotes.addAll(uniqueProviderQuotes);
 
     sortedQuotes = ObservableList.of(

From c7a03559f78e780067da383d77dfa6daba8012df Mon Sep 17 00:00:00 2001
From: tuxsudo <tuxsudo@tux.pizza>
Date: Thu, 6 Mar 2025 13:06:00 -0500
Subject: [PATCH 07/14] Update setting in privacy_page.dart (#2056)

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 lib/src/screens/settings/privacy_page.dart | 2 +-
 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_hy.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_vi.arb                  | 1 +
 res/values/strings_yo.arb                  | 1 +
 res/values/strings_zh.arb                  | 1 +
 29 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart
index 8652c4af6..238e58eab 100644
--- a/lib/src/screens/settings/privacy_page.dart
+++ b/lib/src/screens/settings/privacy_page.dart
@@ -73,7 +73,7 @@ class PrivacyPage extends BasePage {
                       _privacySettingsViewModel.setIsAppSecure(value);
                     }),
               SettingsSwitcherCell(
-                  title: S.current.disable_trade_option,
+                  title: S.current.disable_exchange_option,
                   value: _privacySettingsViewModel.disableTradeOption,
                   onValueChange: (BuildContext _, bool value) {
                     _privacySettingsViewModel.setDisableTradeOption(value);
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index 0bffae6c4..84f0c17ce 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -226,6 +226,7 @@
   "disable_buy": "تعطيل إجراء الشراء",
   "disable_cake_2fa": "تعطيل 2 عامل المصادقة",
   "disable_exchange": "تعطيل التبادل",
+  "disable_exchange_option": "تعطيل خيار التبادل",
   "disable_fee_api_warning": "من خلال إيقاف تشغيل هذا ، قد تكون معدلات الرسوم غير دقيقة في بعض الحالات ، لذلك قد ينتهي بك الأمر إلى دفع مبالغ زائدة أو دفع رسوم المعاملات الخاصة بك",
   "disable_fiat": "تعطيل fiat",
   "disable_sell": "قم بتعطيل إجراء البيع",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index 5195ab39c..c67d8915a 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Деактивирайте действието за покупка",
   "disable_cake_2fa": "Деактивирайте Cake 2FA",
   "disable_exchange": "Деактивиране на борса",
+  "disable_exchange_option": "Опция за деактивиране на обмен",
   "disable_fee_api_warning": "Като изключите това, таксите могат да бъдат неточни в някои случаи, така че може да се препланите или да не плащате таксите за вашите транзакции",
   "disable_fiat": "Деактивиране на fiat",
   "disable_sell": "Деактивирайте действието за продажба",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index 4babb1070..349ae67bc 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Zakázat akci nákupu",
   "disable_cake_2fa": "Zakázat Cake 2FA",
   "disable_exchange": "Zakázat směnárny",
+  "disable_exchange_option": "Zakázat možnost výměny",
   "disable_fee_api_warning": "Tímto vypnutím by sazby poplatků mohly být v některých případech nepřesné, takže byste mohli skončit přepláváním nebo nedoplatkem poplatků za vaše transakce",
   "disable_fiat": "Zakázat fiat",
   "disable_sell": "Zakázat akci prodeje",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 69c9e5783..895fa4183 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Kaufaktion deaktivieren",
   "disable_cake_2fa": "Cake 2FA deaktivieren",
   "disable_exchange": "Exchange deaktivieren",
+  "disable_exchange_option": "Deaktivieren Sie die Exchange -Option",
   "disable_fee_api_warning": "Wenn dies ausgeschaltet wird, sind die Gebührenquoten in einigen Fällen möglicherweise ungenau, sodass Sie die Gebühren für Ihre Transaktionen möglicherweise überbezahlt oder unterzahlt",
   "disable_fiat": "Fiat deaktivieren",
   "disable_sell": "Verkaufsaktion deaktivieren",
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index 8fa1f92b5..c03841cb9 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Disable buy action",
   "disable_cake_2fa": "Disable Cake 2FA",
   "disable_exchange": "Disable exchange",
+  "disable_exchange_option": "Disable Exchange option",
   "disable_fee_api_warning": "By turning this off, the fee rates might be inaccurate in some cases, so you might end up overpaying or underpaying the fees for your transactions",
   "disable_fiat": "Disable fiat",
   "disable_sell": "Disable sell action",
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index c6363a15f..dcff955bb 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Desactivar acción de compra",
   "disable_cake_2fa": "Desactivar 2FA",
   "disable_exchange": "Deshabilitar intercambio",
+  "disable_exchange_option": "Deshabilitar la opción de intercambio",
   "disable_fee_api_warning": "Al apagar esto, las tasas de tarifas pueden ser inexactas en algunos casos, por lo que puede terminar pagando en exceso o pagando menos las tarifas por sus transacciones",
   "disable_fiat": "Deshabilitar fiat",
   "disable_sell": "Desactivar acción de venta",
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index 41409968a..379290a29 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Désactiver l'action d'achat",
   "disable_cake_2fa": "Désactiver Cake 2FA",
   "disable_exchange": "Désactiver l'échange",
+  "disable_exchange_option": "Désactiver l'option d'échange",
   "disable_fee_api_warning": "En désactivant cela, les taux de frais peuvent être inexacts dans certains cas, vous pourriez donc finir par payer trop ou sous-paiement les frais pour vos transactions",
   "disable_fiat": "Désactiver les montants en fiat",
   "disable_sell": "Désactiver l'action de vente",
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index c528c58d2..125ceeaf5 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Kashe alama",
   "disable_cake_2fa": "Musaki Cake 2FA",
   "disable_exchange": "Kashe musanya",
+  "disable_exchange_option": "Musaki zaɓi Canji",
   "disable_fee_api_warning": "Ta hanyar juya wannan kashe, kudaden da zai iya zama ba daidai ba a wasu halaye, saboda haka zaku iya ƙare da overpaying ko a ƙarƙashin kudaden don ma'amaloli",
   "disable_fiat": "Dakatar da fiat",
   "disable_sell": "Kashe karbuwa",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index cc1a7c6e1..074f3ba09 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -226,6 +226,7 @@
   "disable_buy": "खरीद कार्रवाई अक्षम करें",
   "disable_cake_2fa": "केक 2FA अक्षम करें",
   "disable_exchange": "एक्सचेंज अक्षम करें",
+  "disable_exchange_option": "विनिमय विकल्प अक्षम करें",
   "disable_fee_api_warning": "इसे बंद करने से, कुछ मामलों में शुल्क दरें गलत हो सकती हैं, इसलिए आप अपने लेनदेन के लिए फीस को कम कर सकते हैं या कम कर सकते हैं",
   "disable_fiat": "िएट को अक्षम करें",
   "disable_sell": "बेचने की कार्रवाई अक्षम करें",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 9aae5501e..be447f24d 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Onemogući kupnju",
   "disable_cake_2fa": "Onemogući Cake 2FA",
   "disable_exchange": "Onemogući exchange",
+  "disable_exchange_option": "Onemogući opciju razmjene",
   "disable_fee_api_warning": "Isključivanjem ovoga, stope naknade u nekim bi slučajevima mogle biti netočne, tako da biste mogli preplatiti ili predati naknadu za vaše transakcije",
   "disable_fiat": "Isključi, fiat",
   "disable_sell": "Onemogući akciju prodaje",
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index bc99fda74..551e28cef 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Անջատել գնում գործողությունը",
   "disable_cake_2fa": "Անջատել Cake 2FA",
   "disable_exchange": "Անջատել փոխանակումը",
+  "disable_exchange_option": "Անջատեք փոխանակման տարբերակը",
   "disable_fee_api_warning": "Դրանից անջատելով, վճարների տեմպերը որոշ դեպքերում կարող են անճիշտ լինել, այնպես որ դուք կարող եք վերջ տալ ձեր գործարքների համար վճարների գերավճարների կամ գերավճարների վրա",
   "disable_fiat": "Անջատել ֆիատ",
   "disable_sell": "Անջատել վաճառք գործողությունը",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index 1458d69ef..a171f3243 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Nonaktifkan tindakan beli",
   "disable_cake_2fa": "Nonaktifkan Kue 2FA",
   "disable_exchange": "Nonaktifkan pertukaran",
+  "disable_exchange_option": "Nonaktifkan opsi pertukaran",
   "disable_fee_api_warning": "Dengan mematikan ini, tarif biaya mungkin tidak akurat dalam beberapa kasus, jadi Anda mungkin akan membayar lebih atau membayar biaya untuk transaksi Anda",
   "disable_fiat": "Nonaktifkan fiat",
   "disable_sell": "Nonaktifkan aksi jual",
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index 0ec8de33a..f035c3493 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Disabilita l'azione di acquisto",
   "disable_cake_2fa": "Disabilita Cake 2FA",
   "disable_exchange": "Disabilita scambio",
+  "disable_exchange_option": "Disabilita l'opzione di scambio",
   "disable_fee_api_warning": "Disattivando quest'opzione, i tassi delle commissioni potrebbero essere inaccurati in alcuni casi, quindi potresti finire per pagare troppo o troppo poco le commissioni per le tue transazioni",
   "disable_fiat": "Disabilita fiat",
   "disable_sell": "Disabilita l'azione di vendita",
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index e4b16ec85..89fcc5391 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -226,6 +226,7 @@
   "disable_buy": "購入アクションを無効にする",
   "disable_cake_2fa": "Cake 2FA を無効にする",
   "disable_exchange": "交換を無効にする",
+  "disable_exchange_option": "交換オプションを無効にします",
   "disable_fee_api_warning": "これをオフにすることで、料金金利は場合によっては不正確になる可能性があるため、取引の費用が過払いまたは不足している可能性があります",
   "disable_fiat": "フィアットを無効にする",
   "disable_sell": "販売アクションを無効にする",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 056a091c2..e8e23a1a2 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -226,6 +226,7 @@
   "disable_buy": "구매 행동 비활성화",
   "disable_cake_2fa": "케이크 2FA 비활성화",
   "disable_exchange": "교환 비활성화",
+  "disable_exchange_option": "교환 옵션을 비활성화합니다",
   "disable_fee_api_warning": "이것을 끄면 경우에 따라 수수료가 부정확 할 수 있으므로 거래 수수료를 초과 지불하거나 지불 할 수 있습니다.",
   "disable_fiat": "법정화폐 비활성화",
   "disable_sell": "판매 조치 비활성화",
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index a4a17760c..c21413a44 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -226,6 +226,7 @@
   "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။",
   "disable_cake_2fa": "ကိတ်မုန့် 2FA ကို ပိတ်ပါ။",
   "disable_exchange": "လဲလှယ်မှုကို ပိတ်ပါ။",
+  "disable_exchange_option": "ငွေလဲရွေး option ကိုပိတ်ပါ",
   "disable_fee_api_warning": "ဤအရာကိုဖွင့်ခြင်းအားဖြင့်အချို့သောကိစ္စရပ်များတွင်အခကြေးငွေနှုန်းထားများသည်တိကျမှုရှိနိုင်သည်,",
   "disable_fiat": "Fiat ကိုပိတ်ပါ။",
   "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index e950a75bd..0b32a7fc9 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Koopactie uitschakelen",
   "disable_cake_2fa": "Taart 2FA uitschakelen",
   "disable_exchange": "Uitwisseling uitschakelen",
+  "disable_exchange_option": "Schakel Exchange -optie uit",
   "disable_fee_api_warning": "Door dit uit te schakelen, kunnen de tarieven in sommige gevallen onnauwkeurig zijn, dus u kunt de vergoedingen voor uw transacties te veel betalen of te weinig betalen",
   "disable_fiat": "Schakel Fiat uit",
   "disable_sell": "Verkoopactie uitschakelen",
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index e4ac7286d..b5acc57ed 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Wyłącz akcję kupna",
   "disable_cake_2fa": "Wyłącz Cake 2FA",
   "disable_exchange": "Wyłącz wymianę",
+  "disable_exchange_option": "Wyłącz opcję wymiany",
   "disable_fee_api_warning": "Wyłączając to, stawki opłaty mogą być w niektórych przypadkach niedokładne, więc możesz skończyć się przepłaceniem lub wynagrodzeniem opłat za transakcje",
   "disable_fiat": "Wyłącz waluty FIAT",
   "disable_sell": "Wyłącz akcję sprzedaży",
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index 5e0c246bd..8ec99f0f8 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Desativar ação de compra",
   "disable_cake_2fa": "Desabilitar o Cake 2FA",
   "disable_exchange": "Desativar troca",
+  "disable_exchange_option": "Desativar opção de troca",
   "disable_fee_api_warning": "Ao desativar isso, as taxas de taxas podem ser imprecisas em alguns casos, para que você possa acabar pagando demais ou pagando as taxas por suas transações",
   "disable_fiat": "Desativar fiat",
   "disable_sell": "Desativar ação de venda",
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index f09ca70e2..8ef7ac579 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Отключить действие покупки",
   "disable_cake_2fa": "Отключить торт 2FA",
   "disable_exchange": "Отключить обмен",
+  "disable_exchange_option": "Отключить вариант обмена",
   "disable_fee_api_warning": "Выключив это, в некоторых случаях ставки платы могут быть неточными, так что вы можете в конечном итоге переплачивать или недоплачивать сборы за ваши транзакции",
   "disable_fiat": "Отключить фиат",
   "disable_sell": "Отключить действие продажи",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index 5206db0bf..414bbe52f 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -226,6 +226,7 @@
   "disable_buy": "ปิดการใช้งานการซื้อ",
   "disable_cake_2fa": "ปิดการใช้งานเค้ก 2FA",
   "disable_exchange": "ปิดใช้งานการแลกเปลี่ยน",
+  "disable_exchange_option": "ปิดการใช้งานตัวเลือกการแลกเปลี่ยน",
   "disable_fee_api_warning": "โดยการปิดสิ่งนี้อัตราค่าธรรมเนียมอาจไม่ถูกต้องในบางกรณีดังนั้นคุณอาจจบลงด้วยการจ่ายเงินมากเกินไปหรือจ่ายค่าธรรมเนียมสำหรับการทำธุรกรรมของคุณมากเกินไป",
   "disable_fiat": "ปิดใช้งานสกุลเงินตรา",
   "disable_sell": "ปิดการใช้งานการขาย",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index 4befe732a..46a7540bd 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Huwag paganahin ang pagkilos ng pagbili",
   "disable_cake_2fa": "Huwag paganahin ang Cake 2FA",
   "disable_exchange": "Huwag paganahin ang palitan",
+  "disable_exchange_option": "Huwag paganahin ang pagpipilian sa palitan",
   "disable_fee_api_warning": "Sa pamamagitan ng pag -off nito, ang mga rate ng bayad ay maaaring hindi tumpak sa ilang mga kaso, kaya maaari mong tapusin ang labis na bayad o pagsuporta sa mga bayarin para sa iyong mga transaksyon",
   "disable_fiat": "Huwag paganahin ang fiat",
   "disable_sell": "Huwag paganahin ang pagkilos ng pagbebenta",
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index efb00c98f..8fcacb9ba 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Satın alma işlemini devre dışı bırak",
   "disable_cake_2fa": "Cake 2FA'yı Devre Dışı Bırak",
   "disable_exchange": "Borsayı devre dışı bırak",
+  "disable_exchange_option": "Değişim seçeneğini devre dışı bırak",
   "disable_fee_api_warning": "Bunu kapatarak, ücret oranları bazı durumlarda yanlış olabilir, bu nedenle işlemleriniz için ücretleri fazla ödeyebilir veya az ödeyebilirsiniz.",
   "disable_fiat": "İtibari paraları devre dışı bırak",
   "disable_sell": "Satış işlemini devre dışı bırak",
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index c670b174a..6b111f72f 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Вимкнути дію покупки",
   "disable_cake_2fa": "Вимкнути Cake 2FA",
   "disable_exchange": "Вимкнути можливість обміну",
+  "disable_exchange_option": "Вимкнути варіант обміну",
   "disable_fee_api_warning": "Вимкнувши це, ставки плати в деяких випадках можуть бути неточними, тому ви можете переплатити або недооплатити плату за свої транзакції",
   "disable_fiat": "Вимкнути фиат",
   "disable_sell": "Вимкнути дію продажу",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index 8a12b50dc..d1a2b4ca9 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -226,6 +226,7 @@
   "disable_buy": "خرید ایکشن کو غیر فعال کریں۔",
   "disable_cake_2fa": "کیک 2FA کو غیر فعال کریں۔",
   "disable_exchange": "تبادلے کو غیر فعال کریں۔",
+  "disable_exchange_option": "ایکسچینج آپشن کو غیر فعال کریں",
   "disable_fee_api_warning": "اس کو بند کرنے سے ، کچھ معاملات میں فیس کی شرح غلط ہوسکتی ہے ، لہذا آپ اپنے لین دین کے لئے فیسوں کو زیادہ ادائیگی یا ادائیگی ختم کرسکتے ہیں۔",
   "disable_fiat": "فیاٹ کو غیر فعال کریں۔",
   "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔",
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index 637e10a76..2aba61ef3 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -225,6 +225,7 @@
   "disable_buy": "Vô hiệu hóa chức năng mua",
   "disable_cake_2fa": "Vô hiệu hóa 2FA Cake",
   "disable_exchange": "Vô hiệu hóa chức năng trao đổi",
+  "disable_exchange_option": "Tắt tùy chọn trao đổi",
   "disable_fee_api_warning": "Khi tắt chức năng này, tỉ lệ phí có thể không chính xác trong một số trường hợp, dẫn đến bạn trả quá hoặc không đủ phí cho giao dịch của mình.",
   "disable_fiat": "Vô hiệu hóa tiền tệ fiat",
   "disable_sell": "Vô hiệu hóa chức năng bán",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index ca2f6ade0..744159a30 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -226,6 +226,7 @@
   "disable_buy": "Ko iṣọrọ ọja",
   "disable_cake_2fa": "Ko 2FA Cake sii",
   "disable_exchange": "Pa ilé pàṣípààrọ̀",
+  "disable_exchange_option": "Mu aṣayan paṣipaarọ",
   "disable_fee_api_warning": "Nipa yiyi eyi kuro, awọn oṣuwọn owo naa le jẹ aiṣe deede ni awọn ọrọ kan, nitorinaa o le pari apọju tabi awọn idiyele ti o ni agbara fun awọn iṣowo rẹ",
   "disable_fiat": "Pa owó tí ìjọba pàṣẹ wa lò",
   "disable_sell": "Ko iṣọrọ iṣọrọ",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index d272b08b2..a3b5ec421 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -226,6 +226,7 @@
   "disable_buy": "禁用购买操作",
   "disable_cake_2fa": "禁用蛋糕 2FA",
   "disable_exchange": "禁用交换",
+  "disable_exchange_option": "禁用交换选项",
   "disable_fee_api_warning": "通过将其关闭,在某些情况下,收费率可能不准确,因此您最终可能会超额付款或支付交易费用",
   "disable_fiat": "禁用法令",
   "disable_sell": "禁用卖出操作",

From 3dabad81f4207e81ccd59fb958d6a80dccc7eb38 Mon Sep 17 00:00:00 2001
From: tuxsudo <tuxsudo@tux.pizza>
Date: Thu, 6 Mar 2025 18:34:17 -0500
Subject: [PATCH 08/14] Fix whitespace (#2070)

---
 ios/Runner/InfoBase.plist | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist
index aec00022b..69ab926b8 100644
--- a/ios/Runner/InfoBase.plist
+++ b/ios/Runner/InfoBase.plist
@@ -2,6 +2,8 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+	<key>CADisableMinimumFrameDurationOnPhone</key>
+	<true/>
 	<key>BGTaskSchedulerPermittedIdentifiers</key>
 	<array>
 		<string>com.fotolockr.cakewallet.monero_sync_task</string>

From e56dd1256dbf4ca278e52811e2f728ead8366016 Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Fri, 7 Mar 2025 02:48:22 +0200
Subject: [PATCH 09/14] V4.23.3 RC (#2069)

* V4.23.3 RC

* update release notes [skip ci]
---
 assets/text/Monerocom_Release_Notes.txt |  4 ++--
 assets/text/Release_Notes.txt           |  6 ++----
 ios/Podfile.lock                        |  4 ++--
 lib/buy/moonpay/moonpay_provider.dart   | 26 ++++++++++++-------------
 scripts/android/app_env.sh              |  8 ++++----
 scripts/ios/app_env.sh                  |  8 ++++----
 scripts/linux/app_env.sh                |  4 ++--
 scripts/macos/app_env.sh                |  8 ++++----
 scripts/windows/build_exe_installer.iss |  2 +-
 9 files changed, 33 insertions(+), 37 deletions(-)

diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt
index 011435baa..d1f91139b 100644
--- a/assets/text/Monerocom_Release_Notes.txt
+++ b/assets/text/Monerocom_Release_Notes.txt
@@ -1,3 +1,3 @@
-Ledger fixes
-UI enhancements
+UI/UX enhancements
+Stability improvements
 Bug fixes
\ No newline at end of file
diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt
index ca69e0b98..d1f91139b 100644
--- a/assets/text/Release_Notes.txt
+++ b/assets/text/Release_Notes.txt
@@ -1,5 +1,3 @@
-Zano enhancements
-Ethereum enhancements
-Ledger fixes
-UI enhancements
+UI/UX enhancements
+Stability improvements
 Bug fixes
\ No newline at end of file
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index d400d3f81..120194ee0 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -240,7 +240,7 @@ SPEC CHECKSUMS:
   connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
   CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
   cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
-  cw_mweb: 87af74f9659fed0c1a2cbfb44413f1070e79e3ae
+  cw_mweb: 22cd01dfb8ad2d39b15332006f22046aaa8352a3
   cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
   device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
   device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
@@ -277,4 +277,4 @@ SPEC CHECKSUMS:
 
 PODFILE CHECKSUM: e448f662d4c41f0c0b1ccbb78afd57dbf895a597
 
-COCOAPODS: 1.15.2
\ No newline at end of file
+COCOAPODS: 1.15.2
diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart
index 7bca7d405..10148dd30 100644
--- a/lib/buy/moonpay/moonpay_provider.dart
+++ b/lib/buy/moonpay/moonpay_provider.dart
@@ -130,7 +130,8 @@ class MoonPayProvider extends BuyProvider {
     final List<PaymentMethod> paymentMethods = [];
 
     if (isBuyAction) {
-      final fiatBuyCredentials = await fetchFiatCredentials(fiatCurrency, cryptoCurrency.title, null);
+      final fiatBuyCredentials =
+          await fetchFiatCredentials(fiatCurrency, cryptoCurrency.title, null);
       if (fiatBuyCredentials.isNotEmpty) {
         final paymentMethod = fiatBuyCredentials['paymentMethod'] as String?;
         paymentMethods.add(PaymentMethod.fromMoonPayJson(
@@ -223,7 +224,6 @@ class MoonPayProvider extends BuyProvider {
       required bool isBuyAction,
       required String cryptoCurrencyAddress,
       String? countryCode}) async {
-
     final Map<String, String> params = {
       'theme': themeToMoonPayTheme(_settingsStore.currentTheme),
       'language': _settingsStore.languageCode,
@@ -246,19 +246,17 @@ class MoonPayProvider extends BuyProvider {
     if (!isBuyAction) params['quoteCurrencyCode'] = quote.cryptoCurrency.name;
 
     try {
-      {
-        final uri = await requestMoonPayUrl(
-            walletAddress: cryptoCurrencyAddress,
-            settingsStore: _settingsStore,
-            isBuyAction: isBuyAction,
-            amount: amount.toString(),
-            params: params);
+      final uri = await requestMoonPayUrl(
+          walletAddress: cryptoCurrencyAddress,
+          settingsStore: _settingsStore,
+          isBuyAction: isBuyAction,
+          amount: amount.toString(),
+          params: params);
 
-        if (await canLaunchUrl(uri)) {
-          await launchUrl(uri, mode: LaunchMode.externalApplication);
-        } else {
-          throw Exception('Could not launch URL');
-        }
+      if (await canLaunchUrl(uri)) {
+        await launchUrl(uri, mode: LaunchMode.externalApplication);
+      } else {
+        throw Exception('Could not launch URL');
       }
     } catch (e) {
       if (context.mounted) {
diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh
index 8b1d46264..9419ae1c6 100644
--- a/scripts/android/app_env.sh
+++ b/scripts/android/app_env.sh
@@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
 APP_ANDROID_TYPE=$1
 
 MONERO_COM_NAME="Monero.com"
-MONERO_COM_VERSION="1.20.2"
-MONERO_COM_BUILD_NUMBER=114
+MONERO_COM_VERSION="1.20.3"
+MONERO_COM_BUILD_NUMBER=115
 MONERO_COM_BUNDLE_ID="com.monero.app"
 MONERO_COM_PACKAGE="com.monero.app"
 MONERO_COM_SCHEME="monero.com"
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="4.23.2"
-CAKEWALLET_BUILD_NUMBER=247
+CAKEWALLET_VERSION="4.23.3"
+CAKEWALLET_BUILD_NUMBER=248
 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
 CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
 CAKEWALLET_SCHEME="cakewallet"
diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh
index c6d3778f3..491b7d06a 100644
--- a/scripts/ios/app_env.sh
+++ b/scripts/ios/app_env.sh
@@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
 APP_IOS_TYPE=$1
 
 MONERO_COM_NAME="Monero.com"
-MONERO_COM_VERSION="1.20.2"
-MONERO_COM_BUILD_NUMBER=112
+MONERO_COM_VERSION="1.20.3"
+MONERO_COM_BUILD_NUMBER=113
 MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="4.23.2"
-CAKEWALLET_BUILD_NUMBER=298
+CAKEWALLET_VERSION="4.23.3"
+CAKEWALLET_BUILD_NUMBER=301
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 HAVEN_NAME="Haven"
diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh
index 325d2b335..91ab2cdeb 100755
--- a/scripts/linux/app_env.sh
+++ b/scripts/linux/app_env.sh
@@ -14,8 +14,8 @@ if [ -n "$1" ]; then
 fi
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="1.13.2"
-CAKEWALLET_BUILD_NUMBER=47
+CAKEWALLET_VERSION="1.13.3"
+CAKEWALLET_BUILD_NUMBER=48
 
 if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then
     echo "Wrong app type."
diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh
index f554d4d01..234d07c66 100755
--- a/scripts/macos/app_env.sh
+++ b/scripts/macos/app_env.sh
@@ -16,13 +16,13 @@ if [ -n "$1" ]; then
 fi
 
 MONERO_COM_NAME="Monero.com"
-MONERO_COM_VERSION="1.10.2"
-MONERO_COM_BUILD_NUMBER=44
+MONERO_COM_VERSION="1.10.3"
+MONERO_COM_BUILD_NUMBER=45
 MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="1.16.2"
-CAKEWALLET_BUILD_NUMBER=105
+CAKEWALLET_VERSION="1.16.3"
+CAKEWALLET_BUILD_NUMBER=106
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
diff --git a/scripts/windows/build_exe_installer.iss b/scripts/windows/build_exe_installer.iss
index b2dd60130..3fb0cd1aa 100644
--- a/scripts/windows/build_exe_installer.iss
+++ b/scripts/windows/build_exe_installer.iss
@@ -1,5 +1,5 @@
 #define MyAppName "Cake Wallet"
-#define MyAppVersion "0.4.2"
+#define MyAppVersion "0.4.3"
 #define MyAppPublisher "Cake Labs LLC"
 #define MyAppURL "https://cakewallet.com/"
 #define MyAppExeName "CakeWallet.exe"

From be4e0d6ac8093d384bf1367c61013ffb606f79c3 Mon Sep 17 00:00:00 2001
From: OmarHatem <omarh.ismail1@gmail.com>
Date: Sun, 9 Mar 2025 00:59:55 +0200
Subject: [PATCH 10/14] minor fix [skip ci]

---
 cw_polygon/lib/polygon_wallet.dart | 2 +-
 cw_solana/lib/solana_wallet.dart   | 2 +-
 cw_tron/lib/tron_wallet.dart       | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/cw_polygon/lib/polygon_wallet.dart b/cw_polygon/lib/polygon_wallet.dart
index f9aff16c3..4db24b32a 100644
--- a/cw_polygon/lib/polygon_wallet.dart
+++ b/cw_polygon/lib/polygon_wallet.dart
@@ -121,7 +121,7 @@ class PolygonWallet extends EVMChainWallet {
       if (!hasKeysFile) rethrow;
     }
 
-    final balance = EVMChainERC20Balance.fromJSON(data?['balance'] as String) ??
+    final balance = EVMChainERC20Balance.fromJSON(data?['balance'] as String?) ??
         EVMChainERC20Balance(BigInt.zero);
 
     final WalletKeysData keysData;
diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart
index 15c065918..248f1282b 100644
--- a/cw_solana/lib/solana_wallet.dart
+++ b/cw_solana/lib/solana_wallet.dart
@@ -407,7 +407,7 @@ abstract class SolanaWalletBase
       if (!hasKeysFile) rethrow;
     }
 
-    final balance = SolanaBalance.fromJSON(data?['balance'] as String) ?? SolanaBalance(0.0);
+    final balance = SolanaBalance.fromJSON(data?['balance'] as String?) ?? SolanaBalance(0.0);
 
     final WalletKeysData keysData;
     // Migrate wallet from the old scheme to then new .keys file scheme
diff --git a/cw_tron/lib/tron_wallet.dart b/cw_tron/lib/tron_wallet.dart
index cfa80f0d3..b8d5eceec 100644
--- a/cw_tron/lib/tron_wallet.dart
+++ b/cw_tron/lib/tron_wallet.dart
@@ -144,7 +144,7 @@ abstract class TronWalletBase
       if (!hasKeysFile) rethrow;
     }
 
-    final balance = TronBalance.fromJSON(data?['balance'] as String) ?? TronBalance(BigInt.zero);
+    final balance = TronBalance.fromJSON(data?['balance'] as String?) ?? TronBalance(BigInt.zero);
 
     final WalletKeysData keysData;
     // Migrate wallet from the old scheme to then new .keys file scheme

From 1cb8651ffcde44d69c7b6660ac1fb8b029e219de Mon Sep 17 00:00:00 2001
From: Seth For Privacy <40500387+sethforprivacy@users.noreply.github.com>
Date: Sun, 9 Mar 2025 17:10:12 -0400
Subject: [PATCH 11/14] Improve build docs and optimize Dockerfile for Android
 and Linux builds (#2016)

* Update build docs and migrate Android builds to Docker

* Update NDK and move steps directly into Dockerfile

* Fix NDK installation via script and Dockerfile

* Migrate to @MrCyjaneK's existing Dockerfile (with optimizations)

* Add .dockerignore and migrate Dockerfile to root of project

* Revert .gitignore changes

* Update Android and Linux builds and resolve Linux build issue

* Fix git repo for Linux and Android build instructions

* Set branch to latest release in build docs

* Ensure `flutter clean` is run before building

* Fix Linux completion example

* Don't build Zano for Linux

* Apply suggestions from code review

Co-authored-by: cyan <cyjan@mrcyjanek.net>

* Explicitly add automake package to Dockerfile

* Improve logging on Android and Linux builds via Docker

* Improve Dockerfile comments and ordering

* Fix issues in macOS and iOS builds docs (thanks @MrCyjaneK)

* Update docs/builds/IOS.md [skip ci]

* Update docs/builds/IOS.md [skip ci]

* Update docs/builds/MACOS.md [skip ci]

* Update docs/builds/IOS.md [skip ci]

* Fix and improve iOS and macOS build docs

* Windows build doc improvements

Co-authored-by: cyan <cyjan@mrcyjanek.net>

* add missing dependency to Dockerfile

* Update Windows build docs

* More fixes and optimizations to the Windows build docs

* Add git config to Windows build doc

* Fix shell location/commands in Windows build doc

* Fix WSL commands in Windows build doc

* Apply suggestions from code review

Co-authored-by: cyan <cyjan@mrcyjanek.net>

---------

Co-authored-by: cyan <cyjan@mrcyjanek.net>
---
 .dockerignore                                 |   1 +
 scripts/linux/Dockerfile.linux => Dockerfile  | 125 +++++++------
 build-guide-linux.md                          | 176 ------------------
 build-guide-win.md                            |  38 ----
 .../NEW_WALLET_TYPES.md                       |   0
 SECURITY.md => docs/SECURITY.md               |   0
 docs/builds/ANDROID.md                        |  60 ++++++
 docs/builds/IOS.md                            | 143 ++++++++++++++
 docs/builds/LINUX.md                          |  96 ++++++++++
 docs/builds/MACOS.md                          | 135 ++++++++++++++
 docs/builds/WINDOWS.md                        |  92 +++++++++
 howto-build-android.md                        | 149 ---------------
 howto-build-ios.md                            | 101 ----------
 howto-build-macos.md                          | 112 -----------
 howto-build-windows.md                        |  57 ------
 linux/CMakeLists.txt                          |   3 -
 scripts/android/install_ndk.sh                |   4 +-
 scripts/linux/build_monero_all.sh             |   2 +-
 18 files changed, 594 insertions(+), 700 deletions(-)
 create mode 100644 .dockerignore
 rename scripts/linux/Dockerfile.linux => Dockerfile (62%)
 delete mode 100644 build-guide-linux.md
 delete mode 100644 build-guide-win.md
 rename how_to_add_new_wallet_type.md => docs/NEW_WALLET_TYPES.md (100%)
 rename SECURITY.md => docs/SECURITY.md (100%)
 create mode 100644 docs/builds/ANDROID.md
 create mode 100644 docs/builds/IOS.md
 create mode 100644 docs/builds/LINUX.md
 create mode 100644 docs/builds/MACOS.md
 create mode 100644 docs/builds/WINDOWS.md
 delete mode 100644 howto-build-android.md
 delete mode 100644 howto-build-ios.md
 delete mode 100644 howto-build-macos.md
 delete mode 100644 howto-build-windows.md

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..f59ec20aa
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git a/scripts/linux/Dockerfile.linux b/Dockerfile
similarity index 62%
rename from scripts/linux/Dockerfile.linux
rename to Dockerfile
index b41873cf5..dae174a61 100644
--- a/scripts/linux/Dockerfile.linux
+++ b/Dockerfile
@@ -1,83 +1,87 @@
 # Usage:
-# docker build . -f Dockerfile.linux -t ghcr.io/cake-tech/cake_wallet:main-linux
+# docker build . -f Dockerfile -t ghcr.io/cake-tech/cake_wallet:main-linux
 # docker push ghcr.io/cake-tech/cake_wallet:main-linux
 
-FROM --platform=linux/amd64 docker.io/debian:12
-
-LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet
-
-ENV GOLANG_VERSION=1.23.4
-# comes from https://developer.android.com/studio/#command-tools
-ENV ANDROID_SDK_TOOLS_VERSION=11076708
-# https://developer.android.com/studio/releases/build-tools
-ENV ANDROID_PLATFORM_VERSION=34
-ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0
-
-ENV FLUTTER_VERSION=3.24.0
-
-# If we ever need to migrate the home directory...
-RUN sed -i 's|^root:[^:]*:[^:]*:[^:]*:[^:]*:/root:|root:x:0:0:root:/root:|' /etc/passwd
-# mkdir -p /root && rm -rf /root && cp -a /root /root
-ENV HOME=/root
 # Heavily inspired by cirrusci images
 # https://github.com/cirruslabs/docker-images-android/blob/master/sdk/tools/Dockerfile
 # https://github.com/cirruslabs/docker-images-android/blob/master/sdk/34/Dockerfile
 # https://github.com/cirruslabs/docker-images-android/blob/master/sdk/34-ndk/Dockerfile
 # https://github.com/cirruslabs/docker-images-flutter/blob/master/sdk/Dockerfile
 
+FROM --platform=linux/amd64 docker.io/debian:12
+
+LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet
+
+# Set necessary environment variables
+# Set Go version to latest known-working version
+ENV GOLANG_VERSION=1.23.4
+
+# Pin Flutter version to latest known-working version
+ENV FLUTTER_VERSION=3.24.4
+
+# Pin Android Studio, platform, and build tools versions to latest known-working version
+# Comes from https://developer.android.com/studio/#command-tools
+ENV ANDROID_SDK_TOOLS_VERSION=11076708
+# Comes from https://developer.android.com/studio/releases/build-tools
+ENV ANDROID_PLATFORM_VERSION=34
+ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0
+
+# If we ever need to migrate the home directory...
+RUN sed -i 's|^root:[^:]*:[^:]*:[^:]*:[^:]*:/root:|root:x:0:0:root:/root:|' /etc/passwd
+# mkdir -p /root && rm -rf /root && cp -a /root /root
+ENV HOME=/root
 ENV ANDROID_HOME=/opt/android-sdk-linux \
     LANG=en_US.UTF-8 \
     LC_ALL=en_US.UTF-8 \
     LANGUAGE=en_US:en
 
+# Set Android SDK paths
 ENV ANDROID_SDK_ROOT=$ANDROID_HOME \
     PATH=${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/emulator
 
+# Upgrade base image
+RUN apt-get update \
+    && apt-get upgrade -y
+
+# Install all build dependencies
 RUN set -o xtrace \
     && cd /opt \
-    && apt-get update \
-    && apt-get upgrade -y \
-    && apt-get install -y jq \
-    && apt-get install -y default-jdk \
-    && apt-get install -y sudo wget zip unzip git openssh-client curl bc software-properties-common build-essential ruby-full ruby-bundler libstdc++6 libpulse0 libglu1-mesa locales lcov libsqlite3-dev --no-install-recommends \
+    && apt-get install -y --no-install-recommends --no-install-suggests \
+    # Core dependencies
+    bc build-essential curl default-jdk git jq lcov libglu1-mesa libpulse0 libsqlite3-dev libstdc++6 locales openssh-client ruby-bundler ruby-full software-properties-common sudo unzip wget zip \
     # for x86 emulators
-    && apt-get install -y libxtst6 libnss3-dev libnspr4 libxss1 libatk-bridge2.0-0 libgtk-3-0 libgdk-pixbuf2.0-0 \
-    && apt-get install -y -qq xxd \
-    && apt-get install -y lftp \
-    && apt-get install -qq -y sqlite3 libsqlite3-dev \
-    # linux desktop dependencies
-    && apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev \
+    libatk-bridge2.0-0 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libnss3-dev libsqlite3-dev libxtst6 libxss1 lftp sqlite3 xxd \
+    # Linux desktop dependencies
+    clang cmake libgtk-3-dev ninja-build pkg-config \
     # monero_c dependencies
-    && apt-get install -y ccache build-essential autoconf libtool gperf llvm \
+    autoconf automake build-essential ccache gperf libtool llvm \
     # extra stuff for KVM
-    && apt-get install -y udev qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils \
-    # for linux tests
-    && apt-get install -y xvfb network-manager ffmpeg x11-utils \
-    # for aarch64-linux-gnu
-    && apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
-    && rm -rf /var/lib/apt/lists/* \
+    bridge-utils libvirt-clients libvirt-daemon-system qemu-kvm udev \
+    # Linux test dependencies
+    ffmpeg network-manager x11-utils xvfb psmisc \
+    # aarch64-linux-gnu dependencies
+    g++-aarch64-linux-gnu gcc-aarch64-linux-gnu \
+    && apt clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
     && sh -c 'echo "en_US.UTF-8 UTF-8" > /etc/locale.gen' \
     && locale-gen \
     && update-locale LANG=en_US.UTF-8
 
-# install nodejs for actions
-RUN apt-get update && \
-    apt-get install -y curl && \
-    curl -fsSL https://deb.nodesource.com/setup_23.x | bash - && \
-    apt-get install -y nodejs && \
-    apt-get clean && \
-    rm -rf /var/lib/apt/lists/*
-
-RUN wget https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz &&\
-    rm -rf /usr/local/go &&\
-    tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-amd64.tar.gz
+# Install nodejs for Github Actions
+RUN curl -fsSL https://deb.nodesource.com/setup_23.x | bash - && \
+    apt-get install -y --no-install-recommends nodejs && \
+    apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
 
+# Install Go
 ENV PATH=${PATH}:/usr/local/go/bin:${HOME}/go/bin
 ENV GOROOT=/usr/local/go
 ENV GOPATH=${HOME}/go
-RUN go install golang.org/x/mobile/cmd/gomobile@latest
-RUN gomobile init
+RUN wget https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz &&\
+    rm -rf /usr/local/go &&\
+    tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-amd64.tar.gz && \
+    go install golang.org/x/mobile/cmd/gomobile@latest && \
+    gomobile init
 
+# Install Android SDK commandline tools and emulator
 RUN wget -q https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS_VERSION}_latest.zip -O android-sdk-tools.zip \
     && mkdir -p ${ANDROID_HOME}/cmdline-tools/ \
     && unzip -q android-sdk-tools.zip -d ${ANDROID_HOME}/cmdline-tools/ \
@@ -94,10 +98,10 @@ RUN wget -q https://dl.google.com/android/repository/commandlinetools-linux-${AN
     && git config --global user.email "czarek@cakewallet.com" \
     && git config --global user.name "CakeWallet CI"
 
-# emulator is not available on linux/arm64 (https://issuetracker.google.com/issues/227219818)
+# Handle emulator not being available on linux/arm64 (https://issuetracker.google.com/issues/227219818)
 RUN if [ $(uname -m) == "x86_64" ]; then sdkmanager emulator ; fi
 
-# Extra dependencies to not download them for cake wallet build
+# Pre-install extra Android SDK dependencies in order to not have to download them for each build
 RUN yes | sdkmanager \
     "platforms;android-$ANDROID_PLATFORM_VERSION" \
     "build-tools;$ANDROID_BUILD_TOOLS_VERSION" \
@@ -107,26 +111,26 @@ RUN yes | sdkmanager \
     "build-tools;33.0.0" \
     "build-tools;35.0.0"
 
+# Install extra NDK dependency for sp_scanner
 ENV ANDROID_NDK_VERSION=27.2.12479018
-
-# Extra ndk dependency for sp_scanner
 RUN yes | sdkmanager "ndk;$ANDROID_NDK_VERSION" \
     "ndk;27.0.12077973"
 
-# https://github.com/ReactiveCircus/android-emulator-runner dependencies for tests
+# Install dependencies for tests
+# Comes from https://github.com/ReactiveCircus/android-emulator-runner
 RUN yes | sdkmanager "system-images;android-29;default;x86" \
     "system-images;android-29;default;x86_64" \
     "system-images;android-31;default;x86_64" \
     "platforms;android-29"
 
-# fake the KVM status so android emulator doesn't complain (that much)
+# Fake the KVM status so the Android emulator doesn't complain (that much)
 RUN (addgroup kvm || true) && \
     adduser root kvm && \
     mkdir -p /etc/udev/rules.d/ && \
     echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | tee /etc/udev/rules.d/99-kvm4all.rules
 
+# Install rustup, rust toolchains, and cargo-ndk
 ENV PATH=${HOME}/.cargo/bin:${PATH}
-
 RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \
     cargo install cargo-ndk && \
     for target in aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android x86_64-unknown-linux-gnu; \
@@ -134,17 +138,16 @@ RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \
         rustup target add --toolchain stable $target; \
     done
 
-
+# Download and install Flutter
 ENV HOME=${HOME}
 ENV FLUTTER_HOME=${HOME}/sdks/flutter/${FLUTTER_VERSION}
 ENV FLUTTER_ROOT=$FLUTTER_HOME
-
 ENV PATH=${PATH}:${FLUTTER_HOME}/bin:${FLUTTER_HOME}/bin/cache/dart-sdk/bin
 
-RUN git clone --depth 1 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME}
-
-RUN yes | flutter doctor --android-licenses \
+RUN git clone --depth 1 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME} \
+    && yes | flutter doctor --android-licenses \
     && flutter doctor \
     && chown -R root:root ${FLUTTER_HOME}
 
+# Download and pre-cache necessary Flutter artifacts to speed up builds
 RUN flutter precache
diff --git a/build-guide-linux.md b/build-guide-linux.md
deleted file mode 100644
index df5f0f601..000000000
--- a/build-guide-linux.md
+++ /dev/null
@@ -1,176 +0,0 @@
-# Building CakeWallet for Linux
-
-## Requirements and Setup
-
-The following are the system requirements to build CakeWallet for your Linux device.
-
-```
-Ubuntu >= 16.04
-Flutter 3.10.x
-```
-
-## Building CakeWallet on Linux
-
-These steps will help you configure and execute a build of CakeWallet from its source code.
-
-### 1. Installing Package Dependencies
-
-CakeWallet requires some packages to be installed on your build system. You may easily install them on your build system with the following command:
-
-`$ sudo apt install build-essential cmake pkg-config git curl autoconf libtool`
-
-> [!WARNING]
->
-> ### Check gcc version
->
-> It is needed to use gcc 10 or 9 to successfully link dependencies with flutter.\
-> To check what gcc version you are using:
->
-> ```bash
-> $ gcc --version
-> $ g++ --version
-> ```
->
-> If you are using gcc version newer than 10, then you need to downgrade to version 10.4.0:
->
-> ```bash
-> $ sudo apt install gcc-10 g++-10
-> $ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10
-> $ sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10
-> ```
-
-> [!NOTE]
->
-> Alternatively, you can use the [nix-shell](https://nixos.org/) with the `gcc10.nix` file\
-> present on `scripts/linux` like so:
-> ```bash
-> $ nix-shell gcc10.nix
-> ```
-> This will get you in a nix environment with all the required dependencies that you can use to build the software from,\
-> and it works in any linux distro.
-
-### 2. Installing Flutter
-
-Need to install flutter. For this please check section [How to install flutter on Linux](https://docs.flutter.dev/get-started/install/linux).
-
-### 3. Verify Installations
-
-Verify that the Flutter has been correctly installed on your system with the following command:
-
-`$ flutter doctor`
-
-The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding.
-
-```
-Doctor summary (to see all details, run flutter doctor -v):
-[✓] Flutter (Channel stable, 3.10.x, on Linux, locale en_US.UTF-8)
-```
-
-### 4. Acquiring the CakeWallet Source Code
-
-Download CakeWallet source code
-
-`$ git clone https://github.com/cake-tech/cake_wallet.git --branch linux/password-direct-input`
-
-Proceed into the source code before proceeding with the next steps:
-
-`$ cd cake_wallet/scripts/linux/`
-
-To configure some project properties run:
-
-`$ ./cakewallet.sh`
-
-Build the Monero libraries and their dependencies:
-
-`$ ./build_all.sh`
-
-Now the dependencies need to be copied into the CakeWallet project with this command:
-
-`$ ./setup.sh`
-
-It is now time to change back to the base directory of the CakeWallet source code:
-
-`$ cd ../../`
-
-Install Flutter package dependencies with this command:
-
-`$ flutter pub get`
-
-> #### If you will get an error like:
->
-> ```
-> The plugin `cw_shared_external` requires your app to be migrated to the Android embedding v2. Follow the steps on the migration doc above and re-run
-> this command.
-> ```
->
-> Then need to config Android project settings. For this open `scripts/android` (`$ cd scripts/android`) directory and run followed commands:
->
-> ```
-> $ source ./app_env.sh cakewallet
-> $ ./app_config.sh
-> $ cd ../..
-> ```
->
-> Then re-configure Linux project again. For this open `scripts/linux` (`$cd scripts/linux`) directory and run:
-> `$ ./cakewallet.sh`
-> and back to project root directory:
-> `$ cd ../..`
-> and fetch dependencies again
-> `$ flutter pub get`
-
-Your CakeWallet binary will be built with some specific keys for iterate with 3rd party services. You may generate these secret keys placeholders with the following command:
-
-`$ dart run tool/generate_new_secrets.dart`
-
-We will generate mobx models for the project.
-
-`$ ./model_generator.sh`
-
-Then we need to generate localization files.
-
-`$ dart run tool/generate_localization.dart`
-
-### 5. Build!
-
-`$ flutter build linux --release`
-
-Path to executable file will be:
-
-`build/linux/x64/release/bundle/cake_wallet`
-
-> ### Troubleshooting
->
-> If you got an error while building the application with `$ flutter build linux --release` command, add `-v` argument to the command (`$ flutter build linux -v --release`) to get details.\
-> If you got in flutter build logs: undefined reference to `hid_free_enumeration`, or another error with undefined reference to `hid_*`, then rebuild monero lib without hidapi lib. Check does exists `libhidapi-dev` in your scope and remove it from your scope for build without it.
-
-# Flatpak
-
-For package the built application into flatpak you need firstly to install `flatpak` and `flatpak-builder`:
-
-`$ sudo apt install flatpak flatpak-builder`
-
-Then need to [add flathub](https://flatpak.org/setup/Ubuntu) (or just `$ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo`). Then need to install freedesktop runtime and sdk:
-
-`$ flatpak install flathub org.freedesktop.Platform//22.08 org.freedesktop.Sdk//22.08`
-
-To build with using of `flatpak-build` directory run next:
-
-`$ flatpak-builder --force-clean flatpak-build com.cakewallet.CakeWallet.yml`
-
-And then export bundle:
-
-`$ flatpak build-export export flatpak-build`
-
-`$ flatpak build-bundle export cake_wallet.flatpak com.cakewallet.CakeWallet`
-
-Result file: `cake_wallet.flatpak` should be generated in the current directory.
-
-For install generated flatpak file use:
-
-`$ flatpak --user install cake_wallet.flatpak`
-
-For run the installed application run:
-
-`$ flatpak run com.cakewallet.CakeWallet`
-
-Copyright (c) 2023 Cake Technologies LLC.
diff --git a/build-guide-win.md b/build-guide-win.md
deleted file mode 100644
index 8cfd02c4c..000000000
--- a/build-guide-win.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Building CakeWallet for Windows
-
-## Requirements and Setup
-
-The following are the system requirements to build CakeWallet for your Windows PC.
-
-```
-Windows 10 or later (64-bit), x86-64 based
-Flutter 3 or above
-```
-
-## Building CakeWallet on Windows
-
-These steps will help you configure and execute a build of CakeWallet from its source code.
-
-### 1. Installing Package Dependencies
-
-For build CakeWallet windows application from sources you will be needed to have:
-> [Install Flutter]Follow installation guide (https://docs.flutter.dev/get-started/install/windows) and install do not miss to dev tools (install https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) which are required for windows desktop development (need to install Git for Windows and Visual Studio 2022). Then install `Desktop development with C++` packages via GUI Visual Studio 2022, or Visual Studio Build Tools 2022 including: `C++ Build Tools core features`, `C++ 2022 Redistributable Update`, `C++ core desktop features`, `MVC v143 - VS 2022 C++ x64/x86 build tools`, `C++ CMake tools for Windows`, `Testing tools core features - Build Tools`, `C++ AddressSanitizer`.
-> [Install WSL] for building monero dependencies need to install Windows WSL (https://learn.microsoft.com/en-us/windows/wsl/install) and required packages for WSL (Ubuntu):
-`$ sudo apt update `
-`$ sudo apt build-essential cmake gcc-mingw-w64 g++-mingw-w64 autoconf libtool pkg-config`
-
-### 2. Pull CakeWallet source code
-
-You can download CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git by following next command:
-`$ git clone https://github.com/cake-tech/cake_wallet.git --branch MrCyjaneK-cyjan-monerodart`
-OR you can download it as [Zip archive](https://github.com/cake-tech/cake_wallet/archive/refs/heads/MrCyjaneK-cyjan-monerodart.zip)
-
-### 3. Build Monero, Monero_c and their dependencies
-
-For use monero in the application need to build Monero wrapper - Monero_C which will be used by monero.dart package. For that need to run shell (bash - typically same named utility should be available after WSL is enabled in your system) with previously installed WSL, then change current directory to the application project directory with your used shell and then change current directory to `scripts/windows`: `$ cd scripts/windows`. Run build script: `$ ./build_all.sh`.
-
-### 4. Configure and build CakeWallet application
-
-To configure the application open directory where you have downloaded or unarchived CakeWallet sources and run `cakewallet.bat`.
-Or if you used WSL and have active shell session you can run `$ ./cakewallet.sh` script in `scripts/windows` which will run `cakewallet.bat` in WSL.
-After execution of `cakewallet.bat` you should to get `Cake Wallet.zip` in project root directory which will contains `CakeWallet.exe` file and another needed files for run the application. Now you can extract files from `Cake Wallet.zip` archive and run the application.
diff --git a/how_to_add_new_wallet_type.md b/docs/NEW_WALLET_TYPES.md
similarity index 100%
rename from how_to_add_new_wallet_type.md
rename to docs/NEW_WALLET_TYPES.md
diff --git a/SECURITY.md b/docs/SECURITY.md
similarity index 100%
rename from SECURITY.md
rename to docs/SECURITY.md
diff --git a/docs/builds/ANDROID.md b/docs/builds/ANDROID.md
new file mode 100644
index 000000000..61d04185e
--- /dev/null
+++ b/docs/builds/ANDROID.md
@@ -0,0 +1,60 @@
+# Building Cake Wallet for Android
+
+## Requirements and Setup
+
+As we use Docker with a custom Dockerfile to build Cake Wallet, the only dependency for building Cake on your local host is the Docker Engine.
+
+You can find the latest instructions for installing Docker on your given OS on the official website:
+
+- <https://docs.docker.com/engine/install/>
+
+NOTE: If building on a Mac with an M-series CPU (arm64), you may encounter segmentation faults when building. If you do, simply retry the build.
+
+## Building Cake Wallet or Monero.com
+
+### Using the pre-built builder image
+
+In order to build the latest version of Cake Wallet, simply run the following:
+
+```bash
+git clone --branch main https://github.com/cake-tech/cake_wallet.git
+# NOTE: Replace `main` with the latest release tag available at https://github.com/cake-tech/cake_wallet/releases/latest.
+cd cake_wallet
+# docker build -t ghcr.io/cake-tech/cake_wallet:main-linux . # Uncomment to build the docker image yourself instead of pulling it from the registry
+docker run -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:main-linux bash -x << EOF
+set -x -e
+pushd scripts/android
+    source ./app_env.sh cakewallet
+    # source ./app_env.sh monero.com # Uncomment this line to build monero.com
+    ./app_config.sh
+    ./build_monero_all.sh
+    ./build_mwebd.sh --dont-install
+popd
+pushd android/app
+    [[ -f key.jks ]] || keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass hunter1 -keypass hunter1
+popd
+flutter clean
+./model_generator.sh
+dart run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=hunter1 keyPassword=hunter1
+dart run tool/generate_localization.dart
+dart run tool/generate_new_secrets.dart
+flutter build apk --release --split-per-abi
+EOF
+```
+
+You should see the command complete with similar output:
+
+```bash
+Running Gradle task 'assembleRelease'...                          519.1s
+✓ Built build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk (56.3MB)
+✓ Built build/app/outputs/flutter-apk/app-arm64-v8a-release.apk (55.8MB)
+✓ Built build/app/outputs/flutter-apk/app-x86_64-release.apk (56.4MB)
+```
+
+Final builds can be found in `build/app/outputs/flutter-apk/` as seen above.
+
+## Signing builds
+
+While properly signing builds is outside of the scope of this guide (very few users want or need to run their own built APKs), to learn more about how to sign APKs you can check out the Zeus team's fantastic guide:
+
+- <https://github.com/ZeusLN/zeus/blob/master/docs/ReproducibleBuilds.md#signing-apks>
diff --git a/docs/builds/IOS.md b/docs/builds/IOS.md
new file mode 100644
index 000000000..dd75bfed7
--- /dev/null
+++ b/docs/builds/IOS.md
@@ -0,0 +1,143 @@
+# Building Cake Wallet for iOS
+
+## Requirements and Setup
+
+The following are the system requirements to build Cake Wallet for your iOS device.
+
+```txt
+macOS 15.3.1
+Xcode 16.2
+Flutter 3.24.4
+```
+
+NOTE: Newer versions of macOS and Xcode may also work, but have not been confirmed to work by the Cake team.
+
+### 1. Installing dependencies
+
+For installing dependency tools you can use brew [Install brew](https://brew.sh).
+
+You may easily install them on your build system with the following command:
+
+```zsh
+brew install automake ccache cmake cocoapods go libtool pkgconfig xz
+sudo softwareupdate --install-rosetta --agree-to-license
+```
+
+### 2. Installing Xcode
+
+Download and install the latest version of [Xcode](https://developer.apple.com/xcode/) from macOS App Store.
+
+Run the following to properly initialize Xcode:
+
+```zsh
+sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
+sudo xcodebuild -runFirstLaunch
+```
+
+To enable iOS build support for Xcode, perform the following:
+
+1. Open Xcode
+2. Navigate to settings
+3. Open Components tab
+4. Click "Get" next to iOS 18.2 (or any other version that is showing up as default)
+
+### 3. Installing Flutter
+
+Install Flutter, specifically version `3.24.4` by following the [official docs](https://docs.flutter.dev/get-started/install/macos/desktop?tab=download).
+
+NOTE: as `3.24.4` is not the latest version, you'll need to download it from <https://docs.flutter.dev/release/archive> instead of the link in the docs above.
+
+### 4. Installing Rust
+
+Install Rust from the [rustup.rs](https://rustup.rs/) website.
+
+```zsh
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+### 5. Verify Flutter and Xcode installation
+
+Verify that Flutter and Xcode have been correctly installed on your system with the following command:
+
+`flutter doctor`
+
+The output of this command should appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding.
+
+```zsh
+Doctor summary (to see all details, run flutter doctor -v):
+[✓] Flutter (Channel stable, 3.24.4, on macOS 15.x.x)
+[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
+```
+
+### 6. Acquiring the Cake Wallet source code
+
+Download the latest release tag of Cake Wallet and enter the source code directory:
+
+```zsh
+git clone https://github.com/cake-tech/cake_wallet.git --branch main
+cd cake_wallet/scripts/ios/
+```
+
+NOTE: Replace `main` with the latest release tag available at <https://github.com/cake-tech/cake_wallet/releases/latest>.
+
+### 7. Setup and build Cake Wallet from source
+
+We need to generate project settings like app name, app icon, package name, etc, including what specific variant of the app we want to build.
+
+To build Cake Wallet from source, run the following:
+
+```zsh
+source ./app_env.sh cakewallet
+```
+
+For Monero.com, instead do:
+
+```zsh
+source ./app_env.sh monero.com
+```
+
+Build the necessary libraries and their dependencies:
+
+```zsh
+./build_monero_all.sh
+./build_mwebd.sh
+```
+
+NOTE: This step will take quite a while, so be sure you grab a cup of coffee or a good book!
+
+Then run the configuration script to setup app name, app icon, etc:
+
+```zsh
+./app_config.sh
+```
+
+### 8. Prepare Flutter
+
+Change back to the root directory of the Cake Wallet source code and install Flutter package dependencies:
+
+```zsh
+cd ../../
+flutter pub get
+```
+
+Generate secrets as placeholders for official API keys etc. along with localization files and mobx models:
+
+```zsh
+dart run tool/generate_new_secrets.dart
+dart run tool/generate_localization.dart
+./model_generator.sh
+```
+
+### 9. Build
+
+```zsh
+flutter build ios --release --no-codesign
+```
+
+Then you can open `ios/Runner.xcworkspace` with Xcode to archive the application.
+
+If you want to run on a connected device, simply run:
+
+```zsh
+flutter run
+```
diff --git a/docs/builds/LINUX.md b/docs/builds/LINUX.md
new file mode 100644
index 000000000..cd8466e6d
--- /dev/null
+++ b/docs/builds/LINUX.md
@@ -0,0 +1,96 @@
+# Building Cake Wallet for Linux
+
+## Requirements and Setup
+
+As we use Docker with a custom Dockerfile to build Cake Wallet, the only dependency for building Cake on your local host is the Docker Engine.
+
+You can find the latest instructions for installing Docker on your given OS on the official website:
+
+- <https://docs.docker.com/engine/install/>
+
+NOTE: If building on a Mac with an M-series CPU (arm64), you may encounter segmentation faults when building. If you do, simply retry the build.
+
+## Building Cake Wallet or Monero.com
+
+### Using the pre-built builder image
+
+In order to build the latest version of Cake Wallet, simply run the following:
+
+```bash
+git clone --branch main https://github.com/cake-tech/cake_wallet.git
+# NOTE: Replace `main` with the latest release tag available at https://github.com/cake-tech/cake_wallet/releases/latest.
+cd cake_wallet
+# docker build -t ghcr.io/cake-tech/cake_wallet:main-linux . # Uncomment to build the docker image yourself instead of pulling it from the registry
+docker run -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:main-linux bash -x << EOF
+set -x -e
+pushd scripts
+    ./gen_android_manifest.sh
+popd
+pushd scripts/linux
+    source ./app_env.sh cakewallet
+    # source ./app_env.sh monero.com # Uncomment this line to build monero.com
+    ./app_config.sh
+    ./build_monero_all.sh
+popd
+flutter clean
+./model_generator.sh
+dart run tool/generate_localization.dart
+dart run tool/generate_new_secrets.dart
+flutter build linux
+EOF
+```
+
+You should see the command complete with similar output:
+
+```bash
++ dart run tool/generate_localization.dart
++ dart run tool/generate_new_secrets.dart
++ flutter build linux
+
+Building Linux application...                                   
+✓ Built build/linux/x64/release/bundle/cake_wallet
+```
+
+Final builds can be found in `build/linux/x64/release/bundle/` as seen above.
+
+
+## Flatpak (optional)
+
+To package the built binaries as a flatpak, you need first to install `flatpak` and `flatpak-builder`:
+
+```bash
+sudo apt install flatpak flatpak-builder
+```
+
+Add the necessary Flathub:
+
+```bash
+flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
+```
+
+Then need to install freedesktop runtime and sdk:
+
+```bash
+flatpak install flathub org.freedesktop.Platform//22.08 org.freedesktop.Sdk//22.08
+```
+
+Next, build the flatpak bundle:
+
+```bash
+flatpak-builder --force-clean flatpak-build com.cakewallet.CakeWallet.yml
+```
+
+And then export bundle:
+
+```bash
+flatpak build-export export flatpak-build
+flatpak build-bundle export cake_wallet.flatpak com.cakewallet.CakeWallet
+```
+
+The Flatpak file, `cake_wallet.flatpak`, should be generated in the current directory.
+
+To install the newly built Flatpak, run:
+
+```bash
+flatpak --user install cake_wallet.flatpak
+```
diff --git a/docs/builds/MACOS.md b/docs/builds/MACOS.md
new file mode 100644
index 000000000..af3d8c1df
--- /dev/null
+++ b/docs/builds/MACOS.md
@@ -0,0 +1,135 @@
+# Building Cake Wallet for macOS
+
+## Requirements and Setup
+
+The following are the system requirements to build Cake Wallet for your macOS device.
+
+```txt
+macOS 15.3.1
+Xcode 16.2
+Flutter 3.24.4
+```
+
+### 1. Installing dependencies
+
+For installing dependency tools you can use brew [Install brew](https://brew.sh).
+
+You may easily install them on your build system with the following command:
+
+```zsh
+brew install autoconf automake binutils ccache cmake cocoapods go libtool pigz pkg-config
+sudo softwareupdate --install-rosetta --agree-to-license
+```
+
+### 2. Installing Xcode
+
+Download and install the latest version of [Xcode](https://developer.apple.com/xcode/) from macOS App Store.
+
+Run the following to properly initialize Xcode:
+
+```zsh
+sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
+sudo xcodebuild -runFirstLaunch
+```
+
+### 3. Installing Flutter
+
+Install Flutter, specifically version `3.24.4` by following the [official docs](https://docs.flutter.dev/get-started/install/macos/desktop?tab=download).
+
+NOTE: as `3.24.4` is not the latest version, you'll need to download it from <https://docs.flutter.dev/release/archive> instead of the link in the docs above.
+
+### 4. Installing Rust
+
+Install Rust from the [rustup.rs](https://rustup.rs/) website.
+
+```zsh
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+### 5. Verify Flutter and Xcode installation
+
+Verify that Flutter and Xcode have been correctly installed on your system with the following command:
+
+`flutter doctor`
+
+The output of this command should appear like this, indicating successful installations. If there are problems with your installation of Flutter or Xcode, they **must** be corrected before proceeding.
+
+```zsh
+Doctor summary (to see all details, run flutter doctor -v):
+[✓] Flutter (Channel stable, 3.24.4, on macOS 15.x.x)
+...
+[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
+...
+```
+
+### 6. Acquiring the Cake Wallet source code
+
+Download the latest release tag of Cake Wallet and enter the source code directory:
+
+```zsh
+git clone https://github.com/cake-tech/cake_wallet.git --branch main
+cd cake_wallet/scripts/macos/
+```
+
+NOTE: Replace `main` with the latest release tag available at <https://github.com/cake-tech/cake_wallet/releases/latest>.
+
+### 7. Setup and build Cake Wallet from source
+
+We need to generate project settings like app name, app icon, package name, etc, including what specific variant of the app we want to build.
+
+To build Cake Wallet from source, run the following:
+
+```zsh
+source ./app_env.sh cakewallet
+```
+
+For Monero.com, instead do:
+
+```zsh
+source ./app_env.sh monero.com
+```
+
+Build the necessary libraries and their dependencies:
+
+```zsh
+./build_monero_all.sh
+```
+
+NOTE: This step will take quite a while, so be sure you grab a cup of coffee or a good book!
+
+Then run the configuration script to setup app name, app icon, etc:
+
+```zsh
+./app_config.sh
+```
+
+### 8. Prepare Flutter
+
+Change back to the root directory of the Cake Wallet source code and install Flutter package dependencies:
+
+```zsh
+cd ../../
+flutter pub get
+```
+
+Generate secrets as placeholders for official API keys etc. along with localization files and mobx models:
+
+```zsh
+dart run tool/generate_new_secrets.dart
+dart run tool/generate_localization.dart
+./model_generator.sh
+```
+
+### 9. Build
+
+```zsh
+flutter build macos --release
+```
+
+Then you can open `macos/Runner.xcworkspace` with Xcode to archive the application.
+
+If you want to run on a connected device, simply run:
+
+```zsh
+flutter run
+```
diff --git a/docs/builds/WINDOWS.md b/docs/builds/WINDOWS.md
new file mode 100644
index 000000000..1b5d7a0e8
--- /dev/null
+++ b/docs/builds/WINDOWS.md
@@ -0,0 +1,92 @@
+# Building Cake Wallet for Windows
+
+## Requirements and Setup
+
+The following are the system requirements to build Cake Wallet for your Windows PC.
+
+```txt
+Windows 10 or later (64-bit), x86-64 based
+Flutter 3.24.4
+```
+
+### 1. Installing Flutter
+
+Install Flutter, specifically version `3.24.4` by following the [official docs](https://docs.flutter.dev/get-started/install/windows).
+
+In order for Flutter to function, you'll also need to enable Developer Mode:
+
+Start Menu > search for "Run" > type `ms-settings:developers`, and turn on Developer Mode.
+
+NOTE: as `3.24.4` is not the latest version, you'll need to download it from <https://docs.flutter.dev/release/archive> instead of the link in the docs above.
+
+### 2. Install Development Tools
+
+Install Git for Windows and Visual Studio 2022:
+
+1. Follow the [Development Tools](https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) installation instructions
+   1. NOTE: Be sure to install the `Desktop Development with C++` workload in Visual Studio as outlined in the docs.
+2. Add `git` to your path by going to Start Menu > search "environment" > Environment Variables > double-click Path > Add `C:\Program Files\Git\bin\` on a new line.
+
+Lastly, you'll need to install Nuget separately:
+
+1. Download the exe from <https://dist.nuget.org/win-x86-commandline/latest/nuget.exe>
+2. Create a new directory, `C:\Program Files\Nuget\`
+3. Move or copy the `nuget.exe` binary you just downloaded into the newly created directory above.
+4. Add `nuget` to your path by going to Start Menu > search "environment" > Environment Variables > double-click Path > Add `C:\Program Files\Nuget\` on a new line.
+
+### 3. Installing WSL (Windows Subsystem for Linux)
+
+For building Monero dependencies, it is required to install Windows [WSL](https://learn.microsoft.com/en-us/windows/wsl) and required packages for WSL (Ubuntu).
+
+1. Open a Powershell window by going to the Start Menu and searching for "Powershell"
+2. Install WSL with the command `wsl --install`
+3. Install the necessary Ubuntu dependencies
+
+```powershell
+wsl --install
+wsl sudo apt update
+wsl sudo apt install -y autoconf build-essential ccache cmake curl gcc gcc-mingw-w64-x86-64 git g++ g++-mingw-w64-x86-64 gperf lbzip2 libtool make pkg-config pigz
+```
+
+### 4. Installing Rust
+
+Install Rust and other Rust-related dependencies using [rustup.rs](https://rustup.rs/#) by running the following command:
+
+```bash
+wsl curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+### 5. Acquiring the Cake Wallet source code
+
+Download the latest release tag of Cake Wallet and enter the source code directory:
+
+```powershell
+git clone https://github.com/cake-tech/cake_wallet.git --branch main
+cd cake_wallet
+```
+
+NOTE: Replace `main` with the latest release tag available at <https://github.com/cake-tech/cake_wallet/releases/latest>.
+
+### 6. Build Monero, monero_c, and dependencies
+
+To use Monero in Cake Wallet, you must build the Monero_C wrapper which will be used by monero.dart package.
+
+Run the following in a WSL terminal window (set the Git username and email as desired):
+
+```powershell
+wsl
+git config --global user.email "builds@cakewallet.com"
+git config --global user.name "builds"
+./build_all.sh
+```
+
+### 7. Configure and build Cake Wallet application
+
+To configure the application, run the following:
+
+```powershell
+exit
+.\cakewallet.bat
+```
+
+After running the script above, you should get `Cake Wallet.zip` in the project's root directory which will contain `CakeWallet.exe` and other needed files for running the application. Now you can extract files from `Cake Wallet.zip` archive and run the application.
diff --git a/howto-build-android.md b/howto-build-android.md
deleted file mode 100644
index 5afecfba3..000000000
--- a/howto-build-android.md
+++ /dev/null
@@ -1,149 +0,0 @@
-# Building Cake Wallet for Android
-
-## Requirements and Setup
-
-The following are the system requirements to build Cake Wallet for your Android device.
-
-```
-Ubuntu >= 20.04 
-Android SDK 29 or higher (better to have the latest one 33)
-Android NDK 17c
-Flutter 3.24.4
-```
-
-### 1. Installing Package Dependencies
-
-CakeWallet cannot be built without the following packages installed on your system.
-
-- curl
-
-- unzip
-
-- automake
-
-- build-essential
-
-- file
-
-- pkg-config
-
-- git
-
-- python
-
-- libtool
-
-- libtinfo5
-
-- cmake
-
-- openjdk-8-jre-headless
-
-- clang
-
-You may easily install them on your build system with the following command:
-
-`$ sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake openjdk-8-jre-headless clang`
-
-### 2. Installing Android Studio and Android toolchain
-
-You may download and install the latest version of Android Studio [here](https://developer.android.com/studio#downloads). After installing, start Android Studio, and go through the "Setup Wizard." This installs the latest Android SDK, Android SDK Command-line Tools, and Android SDK Build-Tools, which are required by Cake Wallet. **Be sure you are installing SDK version 28 or later when stepping through the wizard**
-
-### 3. Installing Flutter
-
-Install Flutter with version `3.24.4`. For this please check section [Install Flutter manually](https://docs.flutter.dev/get-started/install/linux#install-flutter-manually).
-
-### 4. Installing rustup
-
-Install rustup from the [rustup.rs](https://rustup.rs/) website.
-
-### 5. Verify Installations
-
-Verify that the Android toolchain, Flutter, and Android Studio have been correctly installed on your system with the following command:
-
-`$ flutter doctor`
-
-The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding.
-```
-Doctor summary (to see all details, run flutter doctor -v):
-[✓] Flutter (Channel stable, 3.24.4, on Linux, locale en_US.UTF-8)
-[✓] Android toolchain - develop for Android devices (Android SDK version 29 or higher)
-[✓] Android Studio (version 4.0 or higher)
-```
-
-### 6. Generate a secure keystore for Android
-
-`$ keytool -genkey -v -keystore $HOME/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key`
-
-You will be prompted to create two passwords. First you will be prompted for the "store password", followed by a "key password" towards the end of the creation process. **TAKE NOTE OF THESE PASSWORDS!** You will need them in later steps. 
-
-### 7. Acquiring the Cake Wallet Source Code
-
-Create the directory that will be use to store the Cake Wallet source...
-
-```
-$ sudo mkdir -p /opt/android
-$ sudo chown $USER /opt/android
-$ cd /opt/android
-```
-
-..and download the source code into that directory.
-
-`$ git clone https://github.com/cake-tech/cake_wallet.git --branch main`
-
-Proceed into the source code before proceeding with the next steps:
-
-`$ cd cake_wallet/scripts/android/`
-
-### 8. Installing Android NDK
-
-`$ ./install_ndk.sh`
-
-### 9. Execute Build & Setup Commands for Cak eWallet
-
-We need to generate project settings like app name, app icon, package name, etc. For this need to setup environment variables and configure project files. 
-
-Please pick what app you want to build: cakewallet or monero.com.
-
-`$ source ./app_env.sh <cakewallet OR monero.com>`
-(it should be like `$ source ./app_env.sh cakewallet` or `$ source ./app_env.sh monero.com`)
-
-Then run configuration script for setup app name, app icon and etc:
-
-`$ ./app_config.sh`  
-
-Build the Monero libraries and their dependencies:
-
-`$ ./build_all.sh`
-
-It is now time to change back to the base directory of the Cake Wallet source code:
-
-`$ cd ../../`
-
-Install Flutter package dependencies with this command:
-
-`$ flutter pub get`
-
-Your Cake Wallet binary will be built with cryptographic salts, which are used for secure encryption of your data. You may generate these secret salts with the following command:
-
-`$ dart run tool/generate_new_secrets.dart`
-
-Next, we must generate key properties based on the secure keystore you generated for Android (in step 5). **MODIFY THE FOLLOWING COMMAND** with the "store password" and "key password" you assigned when creating your keystore (in step 5).
-
-`$ dart run tool/generate_android_key_properties.dart keyAlias=key storeFile=$HOME/key.jks storePassword=<store password> keyPassword=<key password>`
-
-**REMINDER:** The *above* command will **not** succeed unless you replaced the `storePassword` and `keyPassword` variables with the correct passwords for your keystore.
-
-Then we need to generate localization files.
-
-`$ dart run tool/generate_localization.dart`
-
-Finally build mobx models for the app:
-
-`$ ./model_generator.sh`
-
-### 10. Build!
-
-`$ flutter build apk --release`
-
-Copyright (c) 2024 Cake Labs LLC
diff --git a/howto-build-ios.md b/howto-build-ios.md
deleted file mode 100644
index 753e17e93..000000000
--- a/howto-build-ios.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Building Cake Wallet for iOS
-
-## Requirements and Setup
-
-The following are the system requirements to build Cake Wallet for your iOS device.
-
-```
-macOS >= 14.0 
-Xcode 15.3
-Flutter 3.24.4
-```
-
-### 1. Installing Package Dependencies
-
-Cake Wallet cannot be built without the following packages installed on your build system.
-
-For installing dependency tools you can use brew [Install brew](https://brew.sh).
-
-You may easily install them on your build system with the following command:
-
-`$ brew install cmake xz cocoapods`
-
-### 2. Installing Xcode
-
-You may download and install the latest version of [Xcode](https://developer.apple.com/xcode/) from macOS App Store. 
-
-### 3. Installing Flutter
-
-Need to install flutter with version `3.24.4`. For this please check section [Install Flutter](https://docs.flutter.dev/get-started/install/macos/mobile-ios?tab=download).
-
-### 4. Installing rustup
-
-Install rustup from the [rustup.rs](https://rustup.rs/) website.
-
-### 5. Verify Installations
-
-Verify that the Flutter and Xcode have been correctly installed on your system with the following command:
-
-`$ flutter doctor`
-
-The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding.
-```
-Doctor summary (to see all details, run flutter doctor -v):
-[✓] Flutter (Channel stable, 3.24.4, on macOS 14.x.x)
-[✓] Xcode - develop for iOS and macOS (Xcode 15.3)
-```
-
-### 6. Acquiring the CakeWallet source code
-
-Download the source code.
-
-`$ git clone https://github.com/cake-tech/cake_wallet.git --branch main`
-
-Proceed into the source code before proceeding with the next steps:
-
-`$ cd cake_wallet/scripts/ios/`
-
-### 7. Execute Build & Setup Commands for Cake Wallet
-
-We need to generate project settings like app name, app icon, package name, etc. For this, we need to setup environment variables and configure project files. 
-
-Please pick what app you want to build: cakewallet or monero.com.
-
-`$ source ./app_env.sh <cakewallet OR monero.com>`
-(it should be like `$ source ./app_env.sh cakewallet` or `$ source ./app_env.sh monero.com`)
-
-Then run configuration script for setup app name, app icon and etc:
-
-`$ ./app_config.sh`  
-
-Build the Monero libraries and their dependencies:
-
-`$ ./build_monero_all.sh`
-
-It is now time to change back to the base directory of the Cake Wallet source code:
-
-`$ cd ../../`
-
-Install Flutter package dependencies with this command:
-
-`$ flutter pub get`
-
-Your Cake Wallet binary will be built with cryptographic salts, which are used for secure encryption of your data. You may generate these secret salts with the following command:
-
-`$ dart run tool/generate_new_secrets.dart`
-
-Then we need to generate localization files and mobx models.
-
-`$ ./configure_cake_wallet.sh ios`
-
-### 8. Build!
-
-`$ flutter build ios --release`
-
-Then you can open `ios/Runner.xcworkspace` with Xcode and you can archive the application.
-
-Or if you want to run to connected device:
-
-`$ flutter run --release`
-
-Copyright (c) 2024 Cake Labs LLC
diff --git a/howto-build-macos.md b/howto-build-macos.md
deleted file mode 100644
index a497e1ffa..000000000
--- a/howto-build-macos.md
+++ /dev/null
@@ -1,112 +0,0 @@
-# Building Cake Wallet for macOS
-
-## Requirements and Setup
-
-The following are the system requirements to build Cake Wallet for your macOS device.
-
-```
-macOS >= 14.0 
-Xcode 15.3
-Flutter 3.24.4
-```
-
-### 1. Installing Package Dependencies
-
-Cake Wallet cannot be built without the following packages installed on your build system.
-
-For installing dependency tools you can use brew [Install brew](https://brew.sh).
-
-You may easily install them on your build system with the following command:
-
-`$ brew install cmake xz automake autoconf libtool boost@1.76 zmq cocoapods`
-
-`$ brew link boost@1.76`
-
-### 2. Installing Xcode
-
-You may download and install the latest version of [Xcode](https://developer.apple.com/xcode/) from macOS App Store. 
-
-### 3. Installing Flutter
-
-Need to install flutter with version `3.24.4`. For this please check section [Install Flutter](https://docs.flutter.dev/get-started/install/macos/desktop?tab=download).
-
-### 4. Installing rustup
-
-Install rustup from the [rustup.rs](https://rustup.rs/) website.
-
-### 5. Verify Installations
-
-Verify that Flutter and Xcode have been correctly installed on your system with the following command:
-
-`$ flutter doctor`
-
-The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding.
-```
-Doctor summary (to see all details, run flutter doctor -v):
-[✓] Flutter (Channel stable, 3.24.4, on macOS 14.x.x)
-[✓] Xcode - develop for iOS and macOS (Xcode 15.3)
-```
-
-### 6. Acquiring the Cake Wallet source code
-
-Download the source code.
-
-`$ git clone https://github.com/cake-tech/cake_wallet.git --branch main`
-
-Proceed into the source code before proceeding with the next steps:
-
-`$ cd cake_wallet/scripts/macos/`
-
-### 7. Execute Build & Setup Commands for Cake Wallet
-
-We need to generate project settings like app name, app icon, package name, etc. For this need to setup environment variables and configure project files. 
-
-Please pick what app you want to build: cakewallet or monero.com.
-
-`$ source ./app_env.sh <cakewallet OR monero.com>`
-(it should be like `$ source ./app_env.sh cakewallet` or `$ source ./app_env.sh monero.com`)
-
-Then run configuration script for setup app name, app icon and etc:
-
-`$ ./app_config.sh`
-
-Build the Monero libraries and their dependencies:
-
-`$ ./build_monero_all.sh`
-
-If you be needed to build universal monero lib, then it will require additional steps. Steps for build universal monero lib on mac with Apple Silicon (arm64):
-
-- Need to install Rosetta: `$ softwareupdate --install-rosetta`
-- Need to install [Brew](https://brew.sh/) with rosetta: `$ arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"` (or take another way to install brew, but be use that you have installed it into /usr/local as it's using for x86_64 macs)
-- Install dependencies for build monero wallet lib for x86_64 with brew: `$ arch -x86_64 /usr/local/bin/brew install automake autoconf libtool openssl boost@1.76 zmq` and link installed boost@1.76 for x86_64 `$ arch -x86_64 /usr/local/bin/brew link boost@1.76`
-- Run building script with additional argument: `$ ./build_monero_all.sh universal`
-
-If you will be needed to build monero wallet lib only for x86_64 on arm64 mac, then you need use steps above, but run build script with rosetta without arguments: `$ arch -x86_64 ./build_monero_all.sh`.
-
-It is now time to change back to the base directory of the Cake Wallet source code:
-
-`$ cd ../../`
-
-Install Flutter package dependencies with this command:
-
-`$ flutter pub get`
-
-Your Cake Wallet binary will be built with cryptographic salts, which are used for secure encryption of your data. You may generate these secret salts with the following command:
-
-`$ dart run tool/generate_new_secrets.dart`
-
-Then we need to generate localization files and mobx models.
-
-`$ ./configure_cake_wallet.sh macos`
-
-### 8. Build!
-
-`$ flutter build macos --release`
-
-Then you can open `macos/Runner.xcworkspace` with Xcode and you can to archive the application.
-
-Or if you want to run to connected device:
-
-`$ flutter run --release`
-
-Copyright (c) 2024 Cake Labs LLC
diff --git a/howto-build-windows.md b/howto-build-windows.md
deleted file mode 100644
index 3ebecaa61..000000000
--- a/howto-build-windows.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Building Cake Wallet for Windows
-
-## Requirements and Setup
-
-The following are the system requirements to build CakeWallet for your Windows PC.
-
-```
-Windows 10 or later (64-bit), x86-64 based
-Flutter 3.24.4
-```
-
-### 1. Installing Flutter
-
-Install Flutter with version `3.24.4`. Follow the Flutter [installation guide](https://docs.flutter.dev/get-started/install/windows).
-
-### 2. Install Development Tools
-
-Install Git for Windows and Visual Studio 2022. Follow the [Development Tools](https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) installation instructions.
-
-Then install `Desktop development with C++` packages via Visual Studio 2022, or Visual Studio Build Tools 2022 including:
-- `C++ Build Tools core features`
-- `C++ 2022 Redistributable Update`
-- `C++ core desktop features`
-- `MVC v143 - VS 2022 C++ x64/x86 build tools`
-- `C++ CMake tools for Windows`
-- `Testing tools core features - Build Tools`
-- `C++ AddressSanitizer`.
-
-### 3. Installing rustup
-
-Install rustup from the [rustup.rs](https://rustup.rs/#) website. Download and run the 64-bit rustup-init.exe
-
-### 4. Installing WSL (Windows Subsystem for Linux)
-
-For building monero dependencies, it is required to install Windows WSL (https://learn.microsoft.com/en-us/windows/wsl/install) and required packages for WSL (Ubuntu):
-`$ sudo apt update `
-`$ sudo apt build-essential cmake gcc-mingw-w64 g++-mingw-w64 autoconf libtool pkg-config`
-
-### 5. Pull Cake Wallet source code
-
-You can download CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git:
-`$ git clone https://github.com/cake-tech/cake_wallet.git --branch MrCyjaneK-cyjan-monerodart`
-OR you can download it as [Zip archive](https://github.com/cake-tech/cake_wallet/archive/refs/heads/MrCyjaneK-cyjan-monerodart.zip)
-
-### 6. Build Monero, monero_c and their dependencies
-
-To use Monero in Cake Wallet, you must build the Monero_C wrapper which will be used by monero.dart package.
-
-For that you need to run the shell (bash - typically same named utility should be available after WSL is enabled in your system) with the previously installed WSL install, then change current directory to the application project directory with your shell then change current directory to `scripts/windows`: `$ cd scripts/windows`. Run build script: `$ ./build_all.sh`.
-
-### 7. Configure and build Cake Wallet application
-
-To configure the application, open the directory where you have downloaded or unarchived Cake Wallet sources and run `cakewallet.bat`.
-Or if you used WSL and have active shell session you can run `$ ./cakewallet.sh` script in `scripts/windows` which will run `cakewallet.bat` in WSL.
-After execution of `cakewallet.bat` you should to get `Cake Wallet.zip` in project root directory which will contain `CakeWallet.exe` file and another needed files for run the application. Now you can extract files from `Cake Wallet.zip` archive and run the application.
-
-Copyright (c) 2024 Cake Labs LLC.
diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt
index 0b6f32fd6..a87e938f3 100644
--- a/linux/CMakeLists.txt
+++ b/linux/CMakeLists.txt
@@ -119,9 +119,6 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/monero_c/release/monero/${
 install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/monero_c/release/wownero/${LIB_TRIPLET}_libwallet2_api_c.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "wownero_libwallet2_api_c.so"
   COMPONENT Runtime)
 
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/monero_c/release/zano/${LIB_TRIPLET}_libwallet2_api_c.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "zano_libwallet2_api_c.so"
-  COMPONENT Runtime)
-
 install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
   COMPONENT Runtime)
 
diff --git a/scripts/android/install_ndk.sh b/scripts/android/install_ndk.sh
index ea131eb39..d6799dbd8 100755
--- a/scripts/android/install_ndk.sh
+++ b/scripts/android/install_ndk.sh
@@ -6,9 +6,9 @@ TOOLCHAIN_A32_DIR=${TOOLCHAIN_DIR}_aarch
 TOOLCHAIN_A64_DIR=${TOOLCHAIN_DIR}_aarch64
 TOOLCHAIN_x86_DIR=${TOOLCHAIN_DIR}_i686
 TOOLCHAIN_x86_64_DIR=${TOOLCHAIN_DIR}_x86_64
-ANDROID_NDK_SHA256="3f541adbd0330a9205ba12697f6d04ec90752c53d6b622101a2a8a856e816589"
+ANDROID_NDK_SHA256="7a1302d9bfbc37d46be90b2285f4737508ffe08a346cf2424c5c6a744de2db22"
 
- curl https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip -o ${ANDROID_NDK_ZIP}
+ curl https://dl.google.com/android/repository/android-ndk-r27c-linux.zip -o ${ANDROID_NDK_ZIP}
  echo $ANDROID_NDK_SHA256 $ANDROID_NDK_ZIP | sha256sum -c || exit 1
  unzip $ANDROID_NDK_ZIP -d $WORKDIR
 
diff --git a/scripts/linux/build_monero_all.sh b/scripts/linux/build_monero_all.sh
index 7113d88ef..7948d87a1 100755
--- a/scripts/linux/build_monero_all.sh
+++ b/scripts/linux/build_monero_all.sh
@@ -7,7 +7,7 @@ cd "$(dirname "$0")"
 
 ../prepare_moneroc.sh
 
-for COIN in monero wownero zano;
+for COIN in monero wownero;
 do
     pushd ../monero_c
         for target in x86_64-linux-gnu # aarch64-linux-gnu

From c5f5d1dd4dc93b31b516b80e6b678e7f02ea0715 Mon Sep 17 00:00:00 2001
From: OmarHatem <omarh.ismail1@gmail.com>
Date: Mon, 10 Mar 2025 11:49:16 +0200
Subject: [PATCH 12/14] fix edit token page minor fixes

---
 lib/src/screens/dashboard/dashboard_page.dart         |  7 ++-----
 .../settings/widgets/settings_switcher_cell.dart      | 11 ++++++++---
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart
index f219409da..cf1f6fa17 100644
--- a/lib/src/screens/dashboard/dashboard_page.dart
+++ b/lib/src/screens/dashboard/dashboard_page.dart
@@ -187,7 +187,6 @@ class _DashboardPageView extends BasePage {
   int get initialPage => dashboardViewModel.shouldShowMarketPlaceInDashboard ? 1 : 0;
   ObservableList<Widget> pages = ObservableList<Widget>();
   bool _isEffectsInstalled = false;
-  StreamSubscription<bool>? _onInactiveSub;
 
   @override
   Widget body(BuildContext context) {
@@ -275,7 +274,7 @@ class _DashboardPageView extends BasePage {
   }
 
   void _setEffects(BuildContext context) async {
-    if (_isEffectsInstalled) {
+    if (_isEffectsInstalled || !context.mounted) {
       return;
     }
     if (dashboardViewModel.shouldShowMarketPlaceInDashboard) {
@@ -305,11 +304,9 @@ class _DashboardPageView extends BasePage {
     _showHavenPopup(context);
 
     var needToPresentYat = false;
-    var isInactive = false;
 
-    _onInactiveSub = rootKey.currentState?.isInactive.listen(
+    rootKey.currentState?.isInactive.listen(
       (inactive) {
-        isInactive = inactive;
 
         if (needToPresentYat) {
           Future<void>.delayed(Duration(milliseconds: 500)).then(
diff --git a/lib/src/screens/settings/widgets/settings_switcher_cell.dart b/lib/src/screens/settings/widgets/settings_switcher_cell.dart
index bc3421ead..6173cb34d 100644
--- a/lib/src/screens/settings/widgets/settings_switcher_cell.dart
+++ b/lib/src/screens/settings/widgets/settings_switcher_cell.dart
@@ -1,4 +1,3 @@
-import 'package:flutter/cupertino.dart';
 import 'package:cake_wallet/src/widgets/standard_list.dart';
 import 'package:cake_wallet/src/widgets/standard_switch.dart';
 import 'package:flutter/material.dart';
@@ -30,7 +29,13 @@ class SettingsSwitcherCell extends StandardListRow {
       height: 56,
       padding: EdgeInsets.only(left: 12, right: 12),
       child: TextButton(
-        onPressed: () => onValueChange?.call(context, !value),
+        onPressed: () {
+          if (onTap != null) {
+            onTap!.call(context);
+          } else {
+            onValueChange?.call(context, !value);
+          }
+        },
         style: ButtonStyle(
           //backgroundColor: MaterialStateProperty.all(Theme.of(context).cardColor),
           shape: MaterialStateProperty.all(
@@ -45,7 +50,7 @@ class SettingsSwitcherCell extends StandardListRow {
           children: <Widget>[
             if (leading != null) leading,
             buildCenter(context, hasLeftOffset: leading != null),
-            if (trailing != null) trailing,
+            trailing,
           ],
         ),
       ),

From 1e4dbb5bc9a9e882d1ce0dbbc0c447fbe9d131fe Mon Sep 17 00:00:00 2001
From: OmarHatem <omarh.ismail1@gmail.com>
Date: Mon, 10 Mar 2025 14:13:21 +0200
Subject: [PATCH 13/14] Ignore packet loss errors [skip ci]

---
 lib/utils/exception_handler.dart | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart
index 17e6daed3..547ffa571 100644
--- a/lib/utils/exception_handler.dart
+++ b/lib/utils/exception_handler.dart
@@ -217,6 +217,7 @@ class ExceptionHandler {
     "invalid signature",
     "invalid password",
     "NetworkImage._loadAsync",
+    "SSLV3_ALERT_BAD_RECORD_MAC",
     // Temporary ignored, More context: Flutter secure storage reads the values as null some times
     // probably when the device was locked and then opened on Cake
     // this is solved by a restart of the app

From 1c8af1afae756306ca68a7c91fca6a8064812ee0 Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Mon, 10 Mar 2025 16:37:23 -0700
Subject: [PATCH 14/14] Mweb checkbox (#2000)

* [skip-ci] wip

* [skip-ci] styles still need updating

* working but needs style updates

* fix checkbox caption color

* sort mweb coins to be last when selecting inputs

* ui fixes

* [skip-ci] default to mweb-checkbox being off

* adaptable page view builder + workaround for keyboard actions

* Fix checkbox themeing and send card sizing

* Update lib/src/screens/send/widgets/send_card.dart

---------

Co-authored-by: tuxpizza <tuxsudo@tux.pizza>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 cw_bitcoin/lib/electrum_wallet.dart         |   4 +-
 lib/di.dart                                 |   2 +-
 lib/src/screens/send/send_page.dart         | 594 ++++++++++---------
 lib/src/screens/send/widgets/send_card.dart | 620 +++++++++++---------
 lib/src/widgets/adaptable_page_view.dart    | 202 +++++++
 lib/src/widgets/standard_checkbox.dart      |   4 +-
 lib/view_model/send/send_view_model.dart    |  12 +-
 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_hy.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_vi.arb                   |   1 +
 res/values/strings_yo.arb                   |   1 +
 res/values/strings_zh.arb                   |   1 +
 35 files changed, 885 insertions(+), 581 deletions(-)
 create mode 100644 lib/src/widgets/adaptable_page_view.dart

diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 64595b253..fd778571f 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -632,8 +632,8 @@ abstract class ElectrumWalletBase
     }).toList();
     final unconfirmedCoins = availableInputs.where((utx) => utx.confirmations == 0).toList();
 
-    // sort the unconfirmed coins so that mweb coins are first:
-    availableInputs.sort((a, b) => a.bitcoinAddressRecord.type == SegwitAddresType.mweb ? -1 : 1);
+    // sort the unconfirmed coins so that mweb coins are last:
+    availableInputs.sort((a, b) => a.bitcoinAddressRecord.type == SegwitAddresType.mweb ? 1 : -1);
 
     for (int i = 0; i < availableInputs.length; i++) {
       final utx = availableInputs[i];
diff --git a/lib/di.dart b/lib/di.dart
index 83b3efaea..ccd0908d1 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -748,7 +748,7 @@ Future<void> setup({
       getIt.get<ContactListViewModel>(),
       _transactionDescriptionBox,
       getIt.get<AppStore>().wallet!.isHardwareWallet ? getIt.get<LedgerViewModel>() : null,
-      coinTypeToSpendFrom: coinTypeToSpendFrom ?? UnspentCoinType.any,
+      coinTypeToSpendFrom: coinTypeToSpendFrom ?? UnspentCoinType.nonMweb,
       getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom),
     ),
   );
diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart
index d3c741c0c..7e7080d0f 100644
--- a/lib/src/screens/send/send_page.dart
+++ b/lib/src/screens/send/send_page.dart
@@ -14,14 +14,17 @@ import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'
 import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart';
 import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
 import 'package:cake_wallet/src/screens/send/widgets/send_card.dart';
+import 'package:cake_wallet/src/widgets/adaptable_page_view.dart';
 import 'package:cake_wallet/src/widgets/add_template_button.dart';
 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
 import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
+import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
 import 'package:cake_wallet/src/widgets/picker.dart';
 import 'package:cake_wallet/src/widgets/primary_button.dart';
 import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
 import 'package:cake_wallet/src/widgets/template_tile.dart';
 import 'package:cake_wallet/src/widgets/trail_button.dart';
+import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
 import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart';
 import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
 import 'package:cake_wallet/themes/theme_base.dart';
@@ -38,6 +41,7 @@ import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
 import 'package:cw_core/crypto_currency.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:keyboard_actions/keyboard_actions.dart';
 import 'package:mobx/mobx.dart';
 import 'package:smooth_page_indicator/smooth_page_indicator.dart';
 import 'package:url_launcher/url_launcher.dart';
@@ -93,7 +97,7 @@ class SendPage extends BasePage {
     return MergeSemantics(
       child: SizedBox(
         height: isMobileView ? 37 : 45,
-        width: isMobileView ? 37 : 45,
+        width: isMobileView ? 47: 45,
         child: ButtonTheme(
           minWidth: double.minPositive,
           child: Semantics(
@@ -114,18 +118,6 @@ class SendPage extends BasePage {
   @override
   AppBarStyle get appBarStyle => AppBarStyle.transparent;
 
-  double _sendCardHeight(BuildContext context) {
-    double initialHeight = 480;
-    if (sendViewModel.hasCoinControl) {
-      initialHeight += 55;
-    }
-
-    if (!responsiveLayoutUtil.shouldRenderMobileUI) {
-      return initialHeight - 66;
-    }
-    return initialHeight;
-  }
-
   @override
   void onClose(BuildContext context) {
     sendViewModel.onClose();
@@ -174,285 +166,316 @@ class SendPage extends BasePage {
   Widget body(BuildContext context) {
     _setEffects(context);
 
-    return GestureDetector(
-      onLongPress: () =>
-          sendViewModel.balanceViewModel.isReversing = !sendViewModel.balanceViewModel.isReversing,
-      onLongPressUp: () =>
-          sendViewModel.balanceViewModel.isReversing = !sendViewModel.balanceViewModel.isReversing,
-      child: Form(
-        key: _formKey,
-        child: ScrollableWithBottomSection(
-            contentPadding: EdgeInsets.only(bottom: 24),
-            content: FocusTraversalGroup(
-              policy: OrderedTraversalPolicy(),
-              child: Column(
-                children: <Widget>[
-                  Container(
-                      height: _sendCardHeight(context),
-                      child: Observer(
-                        builder: (_) {
-                          return PageView.builder(
-                              scrollDirection: Axis.horizontal,
-                              controller: controller,
-                              itemCount: sendViewModel.outputs.length,
-                              itemBuilder: (context, index) {
-                                final output = sendViewModel.outputs[index];
+    return Observer(builder: (_) {
+      List<Widget> sendCards = [];
+      List<KeyboardActionsItem> keyboardActions = [];
+      for (var output in sendViewModel.outputs) {
+        var cryptoAmountFocus = FocusNode();
+        var fiatAmountFocus = FocusNode();
+        sendCards.add(SendCard(
+          currentTheme: currentTheme,
+          key: output.key,
+          output: output,
+          sendViewModel: sendViewModel,
+          initialPaymentRequest: initialPaymentRequest,
+          cryptoAmountFocus: cryptoAmountFocus,
+          fiatAmountFocus: fiatAmountFocus,
+        ));
+        keyboardActions.add(KeyboardActionsItem(
+            focusNode: cryptoAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]));
+        keyboardActions.add(KeyboardActionsItem(
+            focusNode: fiatAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]));
+      }
+      return Stack(
+        children: [
+          KeyboardActions(
+            config: KeyboardActionsConfig(
+              keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
+              keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
+              nextFocus: false,
+              actions: keyboardActions,
+            ),
+            child: Container(
+              height: 0,
+              color: Colors.transparent,
+            ),
+          ),
+          GestureDetector(
+            onLongPress: () => sendViewModel.balanceViewModel.isReversing =
+                !sendViewModel.balanceViewModel.isReversing,
+            onLongPressUp: () => sendViewModel.balanceViewModel.isReversing =
+                !sendViewModel.balanceViewModel.isReversing,
+            child: Form(
+              key: _formKey,
+              child: ScrollableWithBottomSection(
+                  contentPadding: EdgeInsets.only(bottom: 24),
+                  content: FocusTraversalGroup(
+                    policy: OrderedTraversalPolicy(),
+                    child: Column(
+                      children: <Widget>[
+                        PageViewHeightAdaptable(
+                          controller: controller,
+                          children: sendCards,
+                        ),
+                        SizedBox(height: 10),
+                        Padding(
+                          padding: EdgeInsets.only(left: 24, right: 24, bottom: 10),
+                          child: Container(
+                            height: 10,
+                            child: Observer(
+                              builder: (_) {
+                                final count = sendViewModel.outputs.length;
 
-                                return SendCard(
-                                  key: output.key,
-                                  output: output,
-                                  sendViewModel: sendViewModel,
-                                  initialPaymentRequest: initialPaymentRequest,
+                                return count > 1
+                                    ? Semantics(
+                                        label: 'Page Indicator',
+                                        hint: 'Swipe to change receiver',
+                                        excludeSemantics: true,
+                                        child: SmoothPageIndicator(
+                                          controller: controller,
+                                          count: count,
+                                          effect: ScrollingDotsEffect(
+                                              spacing: 6.0,
+                                              radius: 6.0,
+                                              dotWidth: 6.0,
+                                              dotHeight: 6.0,
+                                              dotColor: Theme.of(context)
+                                                  .extension<SendPageTheme>()!
+                                                  .indicatorDotColor,
+                                              activeDotColor: Theme.of(context)
+                                                  .extension<SendPageTheme>()!
+                                                  .templateBackgroundColor),
+                                        ))
+                                    : Offstage();
+                              },
+                            ),
+                          ),
+                        ),
+                        Container(
+                          height: 40,
+                          width: double.infinity,
+                          padding: EdgeInsets.only(left: 24),
+                          child: SingleChildScrollView(
+                            scrollDirection: Axis.horizontal,
+                            child: Observer(
+                              builder: (_) {
+                                final templates = sendViewModel.templates;
+                                final itemCount = templates.length;
+
+                                return Row(
+                                  children: <Widget>[
+                                    AddTemplateButton(
+                                      key: ValueKey('send_page_add_template_button_key'),
+                                      onTap: () =>
+                                          Navigator.of(context).pushNamed(Routes.sendTemplate),
+                                      currentTemplatesLength: templates.length,
+                                    ),
+                                    ListView.builder(
+                                      scrollDirection: Axis.horizontal,
+                                      shrinkWrap: true,
+                                      physics: NeverScrollableScrollPhysics(),
+                                      itemCount: itemCount,
+                                      itemBuilder: (context, index) {
+                                        final template = templates[index];
+                                        return TemplateTile(
+                                          key: UniqueKey(),
+                                          to: template.name,
+                                          hasMultipleRecipients:
+                                              template.additionalRecipients != null &&
+                                                  template.additionalRecipients!.length > 1,
+                                          amount: template.isCurrencySelected
+                                              ? template.amount
+                                              : template.amountFiat,
+                                          from: template.isCurrencySelected
+                                              ? template.cryptoCurrency
+                                              : template.fiatCurrency,
+                                          onTap: () async {
+                                            sendViewModel.state = IsExecutingState();
+                                            if (template.additionalRecipients?.isNotEmpty ??
+                                                false) {
+                                              sendViewModel.clearOutputs();
+
+                                              for (int i = 0;
+                                                  i < template.additionalRecipients!.length;
+                                                  i++) {
+                                                Output output;
+                                                try {
+                                                  output = sendViewModel.outputs[i];
+                                                } catch (e) {
+                                                  sendViewModel.addOutput();
+                                                  output = sendViewModel.outputs[i];
+                                                }
+
+                                                await _setInputsFromTemplate(
+                                                  context,
+                                                  output: output,
+                                                  template: template.additionalRecipients![i],
+                                                );
+                                              }
+                                            } else {
+                                              final output = _defineCurrentOutput();
+                                              await _setInputsFromTemplate(
+                                                context,
+                                                output: output,
+                                                template: template,
+                                              );
+                                            }
+                                            sendViewModel.state = InitialExecutionState();
+                                          },
+                                          onRemove: () {
+                                            showPopUp<void>(
+                                              context: context,
+                                              builder: (dialogContext) {
+                                                return AlertWithTwoActions(
+                                                    alertTitle: S.of(context).template,
+                                                    alertContent:
+                                                        S.of(context).confirm_delete_template,
+                                                    rightButtonText: S.of(context).delete,
+                                                    leftButtonText: S.of(context).cancel,
+                                                    actionRightButton: () {
+                                                      Navigator.of(dialogContext).pop();
+                                                      sendViewModel.sendTemplateViewModel
+                                                          .removeTemplate(template: template);
+                                                    },
+                                                    actionLeftButton: () =>
+                                                        Navigator.of(dialogContext).pop());
+                                              },
+                                            );
+                                          },
+                                        );
+                                      },
+                                    ),
+                                  ],
                                 );
-                              });
-                        },
-                      )),
-                  Padding(
-                    padding: EdgeInsets.only(left: 24, right: 24, bottom: 10),
-                    child: Container(
-                      height: 10,
-                      child: Observer(
-                        builder: (_) {
-                          final count = sendViewModel.outputs.length;
-
-                          return count > 1
-                              ? Semantics(
-                                  label: 'Page Indicator',
-                                  hint: 'Swipe to change receiver',
-                                  excludeSemantics: true,
-                                  child: SmoothPageIndicator(
-                                    controller: controller,
-                                    count: count,
-                                    effect: ScrollingDotsEffect(
-                                        spacing: 6.0,
-                                        radius: 6.0,
-                                        dotWidth: 6.0,
-                                        dotHeight: 6.0,
-                                        dotColor: Theme.of(context)
-                                            .extension<SendPageTheme>()!
-                                            .indicatorDotColor,
-                                        activeDotColor: Theme.of(context)
-                                            .extension<SendPageTheme>()!
-                                            .templateBackgroundColor),
-                                  ))
-                              : Offstage();
-                        },
-                      ),
+                              },
+                            ),
+                          ),
+                        ),
+                      ],
                     ),
                   ),
-                  Container(
-                    height: 40,
-                    width: double.infinity,
-                    padding: EdgeInsets.only(left: 24),
-                    child: SingleChildScrollView(
-                      scrollDirection: Axis.horizontal,
-                      child: Observer(
+                  bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
+                  bottomSection: Column(
+                    children: [
+                      if (sendViewModel.hasCurrecyChanger)
+                        Observer(
+                          builder: (_) => Padding(
+                            padding: EdgeInsets.only(bottom: 12),
+                            child: PrimaryButton(
+                              key: ValueKey('send_page_change_asset_button_key'),
+                              onPressed: () => presentCurrencyPicker(context),
+                              text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})',
+                              color: Colors.transparent,
+                              textColor:
+                                  Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
+                            ),
+                          ),
+                        ),
+                      if (sendViewModel.sendTemplateViewModel.hasMultiRecipient)
+                        Padding(
+                            padding: EdgeInsets.only(bottom: 12),
+                            child: PrimaryButton(
+                              key: ValueKey('send_page_add_receiver_button_key'),
+                              onPressed: () {
+                                sendViewModel.addOutput();
+                                Future.delayed(const Duration(milliseconds: 250), () {
+                                  controller.jumpToPage(sendViewModel.outputs.length - 1);
+                                });
+                              },
+                              text: S.of(context).add_receiver,
+                              color: Colors.transparent,
+                              textColor:
+                                  Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
+                              isDottedBorder: true,
+                              borderColor: Theme.of(context)
+                                  .extension<SendPageTheme>()!
+                                  .templateDottedBorderColor,
+                            )),
+                      Observer(
                         builder: (_) {
-                          final templates = sendViewModel.templates;
-                          final itemCount = templates.length;
+                          return LoadingPrimaryButton(
+                            key: ValueKey('send_page_send_button_key'),
+                            onPressed: () async {
+                              if (sendViewModel.state is IsExecutingState) return;
+                              if (_formKey.currentState != null &&
+                                  !_formKey.currentState!.validate()) {
+                                if (sendViewModel.outputs.length > 1) {
+                                  showErrorValidationAlert(context);
+                                }
 
-                          return Row(
-                            children: <Widget>[
-                              AddTemplateButton(
-                                key: ValueKey('send_page_add_template_button_key'),
-                                onTap: () => Navigator.of(context).pushNamed(Routes.sendTemplate),
-                                currentTemplatesLength: templates.length,
-                              ),
-                              ListView.builder(
-                                scrollDirection: Axis.horizontal,
-                                shrinkWrap: true,
-                                physics: NeverScrollableScrollPhysics(),
-                                itemCount: itemCount,
-                                itemBuilder: (context, index) {
-                                  final template = templates[index];
-                                  return TemplateTile(
-                                    key: UniqueKey(),
-                                    to: template.name,
-                                    hasMultipleRecipients: template.additionalRecipients != null &&
-                                        template.additionalRecipients!.length > 1,
-                                    amount: template.isCurrencySelected
-                                        ? template.amount
-                                        : template.amountFiat,
-                                    from: template.isCurrencySelected
-                                        ? template.cryptoCurrency
-                                        : template.fiatCurrency,
-                                    onTap: () async {
-                                      sendViewModel.state = IsExecutingState();
-                                      if (template.additionalRecipients?.isNotEmpty ?? false) {
-                                        sendViewModel.clearOutputs();
+                                return;
+                              }
 
-                                        for (int i = 0;
-                                            i < template.additionalRecipients!.length;
-                                            i++) {
-                                          Output output;
-                                          try {
-                                            output = sendViewModel.outputs[i];
-                                          } catch (e) {
-                                            sendViewModel.addOutput();
-                                            output = sendViewModel.outputs[i];
-                                          }
+                              final notValidItems = sendViewModel.outputs
+                                  .where(
+                                      (item) => item.address.isEmpty || item.cryptoAmount.isEmpty)
+                                  .toList();
 
-                                          await _setInputsFromTemplate(
-                                            context,
-                                            output: output,
-                                            template: template.additionalRecipients![i],
-                                          );
-                                        }
-                                      } else {
-                                        final output = _defineCurrentOutput();
-                                        await _setInputsFromTemplate(
-                                          context,
-                                          output: output,
-                                          template: template,
-                                        );
-                                      }
-                                      sendViewModel.state = InitialExecutionState();
-                                    },
-                                    onRemove: () {
-                                      showPopUp<void>(
-                                        context: context,
-                                        builder: (dialogContext) {
-                                          return AlertWithTwoActions(
-                                              alertTitle: S.of(context).template,
-                                              alertContent: S.of(context).confirm_delete_template,
-                                              rightButtonText: S.of(context).delete,
-                                              leftButtonText: S.of(context).cancel,
-                                              actionRightButton: () {
-                                                Navigator.of(dialogContext).pop();
-                                                sendViewModel.sendTemplateViewModel
-                                                    .removeTemplate(template: template);
-                                              },
-                                              actionLeftButton: () =>
-                                                  Navigator.of(dialogContext).pop());
+                              if (notValidItems.isNotEmpty) {
+                                showErrorValidationAlert(context);
+                                return;
+                              }
+
+                              if (sendViewModel.wallet.isHardwareWallet) {
+                                if (!sendViewModel.ledgerViewModel!.isConnected) {
+                                  await Navigator.of(context).pushNamed(Routes.connectDevices,
+                                      arguments: ConnectDevicePageParams(
+                                        walletType: sendViewModel.walletType,
+                                        onConnectDevice: (BuildContext context, _) {
+                                          sendViewModel.ledgerViewModel!
+                                              .setLedger(sendViewModel.wallet);
+                                          Navigator.of(context).pop();
                                         },
-                                      );
-                                    },
-                                  );
+                                      ));
+                                } else {
+                                  sendViewModel.ledgerViewModel!.setLedger(sendViewModel.wallet);
+                                }
+                              }
+
+                              if (sendViewModel.wallet.type == WalletType.monero) {
+                                int amount = 0;
+                                for (var item in sendViewModel.outputs) {
+                                  amount += item.formattedCryptoAmount;
+                                }
+                                if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
+                                  await Navigator.of(context).pushNamed(Routes.urqrAnimatedPage,
+                                      arguments: 'export-outputs');
+                                  await Future.delayed(
+                                      Duration(seconds: 1)); // wait for monero to refresh the state
+                                }
+                                if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
+                                  return;
+                                }
+                              }
+
+                              final check = sendViewModel.shouldDisplayTotp();
+                              authService.authenticateAction(
+                                context,
+                                conditionToDetermineIfToUse2FA: check,
+                                onAuthSuccess: (value) async {
+                                  if (value) {
+                                    await sendViewModel.createTransaction();
+                                  }
                                 },
-                              ),
-                            ],
+                              );
+                            },
+                            text: S.of(context).send,
+                            color: Theme.of(context).primaryColor,
+                            textColor: Colors.white,
+                            isLoading: sendViewModel.state is IsExecutingState ||
+                                sendViewModel.state is TransactionCommitting ||
+                                sendViewModel.state is IsAwaitingDeviceResponseState,
+                            isDisabled: !sendViewModel.isReadyForSend,
                           );
                         },
-                      ),
-                    ),
-                  ),
-                ],
-              ),
+                      )
+                    ],
+                  )),
             ),
-            bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
-            bottomSection: Column(
-              children: [
-                if (sendViewModel.hasCurrecyChanger)
-                  Observer(
-                    builder: (_) => Padding(
-                      padding: EdgeInsets.only(bottom: 12),
-                      child: PrimaryButton(
-                        key: ValueKey('send_page_change_asset_button_key'),
-                        onPressed: () => presentCurrencyPicker(context),
-                        text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})',
-                        color: Colors.transparent,
-                        textColor: Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
-                      ),
-                    ),
-                  ),
-                if (sendViewModel.sendTemplateViewModel.hasMultiRecipient)
-                  Padding(
-                      padding: EdgeInsets.only(bottom: 12),
-                      child: PrimaryButton(
-                        key: ValueKey('send_page_add_receiver_button_key'),
-                        onPressed: () {
-                          sendViewModel.addOutput();
-                          Future.delayed(const Duration(milliseconds: 250), () {
-                            controller.jumpToPage(sendViewModel.outputs.length - 1);
-                          });
-                        },
-                        text: S.of(context).add_receiver,
-                        color: Colors.transparent,
-                        textColor: Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
-                        isDottedBorder: true,
-                        borderColor:
-                            Theme.of(context).extension<SendPageTheme>()!.templateDottedBorderColor,
-                      )),
-                Observer(
-                  builder: (_) {
-                    return LoadingPrimaryButton(
-                      key: ValueKey('send_page_send_button_key'),
-                      onPressed: () async {
-                        if (sendViewModel.state is IsExecutingState) return;
-                        if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
-                          if (sendViewModel.outputs.length > 1) {
-                            showErrorValidationAlert(context);
-                          }
-
-                          return;
-                        }
-
-                        final notValidItems = sendViewModel.outputs
-                            .where((item) => item.address.isEmpty || item.cryptoAmount.isEmpty)
-                            .toList();
-
-                        if (notValidItems.isNotEmpty) {
-                          showErrorValidationAlert(context);
-                          return;
-                        }
-
-                        if (sendViewModel.wallet.isHardwareWallet) {
-                          if (!sendViewModel.ledgerViewModel!.isConnected) {
-                            await Navigator.of(context).pushNamed(
-                                Routes.connectDevices,
-                                arguments: ConnectDevicePageParams(
-                                  walletType: sendViewModel.walletType,
-                                  onConnectDevice: (BuildContext context, _) {
-                                    sendViewModel.ledgerViewModel!
-                                        .setLedger(sendViewModel.wallet);
-                                    Navigator.of(context).pop();
-                                  },
-                                ));
-                          } else {
-                            sendViewModel.ledgerViewModel!
-                                .setLedger(sendViewModel.wallet);
-                          }
-                        }
-
-                        if (sendViewModel.wallet.type == WalletType.monero) {
-                          int amount = 0;
-                          for (var item in sendViewModel.outputs) {
-                            amount += item.formattedCryptoAmount;
-                          }
-                          if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
-                            await Navigator.of(context).pushNamed(Routes.urqrAnimatedPage, arguments: 'export-outputs');
-                            await Future.delayed(Duration(seconds: 1)); // wait for monero to refresh the state
-                          }
-                          if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
-                            return;
-                          }
-                        }
-
-                        final check = sendViewModel.shouldDisplayTotp();
-                        authService.authenticateAction(
-                          context,
-                          conditionToDetermineIfToUse2FA: check,
-                          onAuthSuccess: (value) async {
-                            if (value) {
-                              await sendViewModel.createTransaction();
-                            }
-                          },
-                        );
-                      },
-                      text: S.of(context).send,
-                      color: Theme.of(context).primaryColor,
-                      textColor: Colors.white,
-                      isLoading: sendViewModel.state is IsExecutingState ||
-                          sendViewModel.state is TransactionCommitting ||
-                          sendViewModel.state is IsAwaitingDeviceResponseState,
-                      isDisabled: !sendViewModel.isReadyForSend,
-                    );
-                  },
-                )
-              ],
-            )),
-      ),
-    );
+          ),
+        ],
+      );
+    });
   }
 
   BuildContext? dialogContext;
@@ -525,13 +548,12 @@ class SendPage extends BasePage {
 
       if (state is TransactionCommitted) {
         WidgetsBinding.instance.addPostFrameCallback((_) async {
-
           if (!context.mounted) {
             return;
           }
 
-          final successMessage = S.of(context).send_success(
-              sendViewModel.selectedCryptoCurrency.toString());
+          final successMessage =
+              S.of(context).send_success(sendViewModel.selectedCryptoCurrency.toString());
 
           final waitMessage = sendViewModel.walletType == WalletType.solana
               ? '. ${S.of(context).waitFewSecondForTxUpdate}'
@@ -539,10 +561,8 @@ class SendPage extends BasePage {
 
           String alertContent = "$successMessage$waitMessage";
 
-          await Navigator.of(context).pushNamed(
-              Routes.transactionSuccessPage,
-              arguments: alertContent
-          );
+          await Navigator.of(context)
+              .pushNamed(Routes.transactionSuccessPage, arguments: alertContent);
 
           newContactAddress = newContactAddress ?? sendViewModel.newContactAddress();
           if (newContactAddress?.address != null && isRegularElectrumAddress(newContactAddress!.address)) {
@@ -562,7 +582,7 @@ class SendPage extends BasePage {
                     leftButtonText: S.of(_dialogContext).ignor,
                     alertLeftActionButtonKey: ValueKey('send_page_sent_dialog_ignore_button_key'),
                     alertRightActionButtonKey:
-                    ValueKey('send_page_sent_dialog_add_contact_button_key'),
+                        ValueKey('send_page_sent_dialog_add_contact_button_key'),
                     actionRightButton: () {
                       Navigator.of(_dialogContext).pop();
                       RequestReviewHandler.requestReview();
diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart
index 24cbd2061..f1cac5c9f 100644
--- a/lib/src/screens/send/widgets/send_card.dart
+++ b/lib/src/screens/send/widgets/send_card.dart
@@ -1,6 +1,7 @@
 import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
 import 'package:cake_wallet/src/screens/receive/widgets/currency_input_field.dart';
 import 'package:cake_wallet/src/widgets/picker.dart';
+import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
 import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
 import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
@@ -12,6 +13,7 @@ import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
 import 'package:cake_wallet/view_model/send/output.dart';
 import 'package:cw_core/transaction_priority.dart';
+import 'package:cw_core/unspent_coin_type.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_mobx/flutter_mobx.dart';
@@ -24,40 +26,58 @@ import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
 import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
 
+import '../../../../themes/extensions/cake_text_theme.dart';
+import '../../../../themes/theme_base.dart';
+
 class SendCard extends StatefulWidget {
   SendCard({
     Key? key,
     required this.output,
     required this.sendViewModel,
+    required this.currentTheme,
     this.initialPaymentRequest,
+    this.cryptoAmountFocus,
+    this.fiatAmountFocus,
   }) : super(key: key);
 
   final Output output;
   final SendViewModel sendViewModel;
   final PaymentRequest? initialPaymentRequest;
+  final FocusNode? cryptoAmountFocus;
+  final FocusNode? fiatAmountFocus;
+  final ThemeBase currentTheme;
+
 
   @override
   SendCardState createState() => SendCardState(
         output: output,
         sendViewModel: sendViewModel,
         initialPaymentRequest: initialPaymentRequest,
+        currentTheme: currentTheme
+        // cryptoAmountFocus: cryptoAmountFocus ?? FocusNode(),
+        // fiatAmountFocus: fiatAmountFocus ?? FocusNode(),
+        // cryptoAmountFocus: FocusNode(),
+        // fiatAmountFocus: FocusNode(),
       );
 }
 
 class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<SendCard> {
-  SendCardState({required this.output, required this.sendViewModel, this.initialPaymentRequest})
-      : addressController = TextEditingController(),
+  SendCardState({
+    required this.output,
+    required this.sendViewModel,
+    this.initialPaymentRequest,
+    required this.currentTheme,
+  })  : addressController = TextEditingController(),
         cryptoAmountController = TextEditingController(),
         fiatAmountController = TextEditingController(),
         noteController = TextEditingController(),
         extractedAddressController = TextEditingController(),
-        cryptoAmountFocus = FocusNode(),
-        fiatAmountFocus = FocusNode(),
         addressFocusNode = FocusNode();
 
   static const prefixIconWidth = 34.0;
   static const prefixIconHeight = 34.0;
 
+  final ThemeBase currentTheme;
   final Output output;
   final SendViewModel sendViewModel;
   final PaymentRequest? initialPaymentRequest;
@@ -67,8 +87,6 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
   final TextEditingController fiatAmountController;
   final TextEditingController noteController;
   final TextEditingController extractedAddressController;
-  final FocusNode cryptoAmountFocus;
-  final FocusNode fiatAmountFocus;
   final FocusNode addressFocusNode;
 
   bool _effectsInstalled = false;
@@ -101,310 +119,336 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
     super.build(context);
     _setEffects(context);
 
-    return Stack(
-      children: [
-        KeyboardActions(
-          config: KeyboardActionsConfig(
-            keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
-            keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
-            nextFocus: false,
-            actions: [
-              KeyboardActionsItem(
-                focusNode: cryptoAmountFocus,
-                toolbarButtons: [(_) => KeyboardDoneButton()],
+    // return Stack(
+    //   children: [
+    // return KeyboardActions(
+    //   config: KeyboardActionsConfig(
+    //     keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
+    //     keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
+    //     nextFocus: false,
+    //     actions: [
+    //       KeyboardActionsItem(
+    //         focusNode: cryptoAmountFocus,
+    //         toolbarButtons: [(_) => KeyboardDoneButton()],
+    //       ),
+    //       KeyboardActionsItem(
+    //         focusNode: fiatAmountFocus,
+    //         toolbarButtons: [(_) => KeyboardDoneButton()],
+    //       )
+    //     ],
+    //   ),
+    //   // child: Container(
+    //   //   height: 0,
+    //   //   color: Colors.transparent,
+    //   // ),      child:
+    //   child: SizedBox(
+    //     height: 100,
+    //     width: 100,
+    //     child: Text('Send Card'),
+    //   ),
+    // );
+    return Container(
+      decoration: responsiveLayoutUtil.shouldRenderMobileUI
+          ? BoxDecoration(
+              borderRadius: BorderRadius.only(
+                  bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
+              gradient: LinearGradient(
+                colors: [
+                  Theme.of(context).extension<SendPageTheme>()!.firstGradientColor,
+                  Theme.of(context).extension<SendPageTheme>()!.secondGradientColor,
+                ],
+                begin: Alignment.topLeft,
+                end: Alignment.bottomRight,
               ),
-              KeyboardActionsItem(
-                focusNode: fiatAmountFocus,
-                toolbarButtons: [(_) => KeyboardDoneButton()],
-              )
-            ],
-          ),
-          child: Container(
-            height: 0,
-            color: Colors.transparent,
-          ),
+            )
+          : null,
+      child: Padding(
+        padding: EdgeInsets.fromLTRB(
+          24,
+          responsiveLayoutUtil.shouldRenderMobileUI ? 110 : 55,
+          24,
+          responsiveLayoutUtil.shouldRenderMobileUI ? 32 : 0,
         ),
-        Container(
-          decoration: responsiveLayoutUtil.shouldRenderMobileUI
-              ? BoxDecoration(
-                  borderRadius: BorderRadius.only(
-                      bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
-                  gradient: LinearGradient(
-                    colors: [
-                      Theme.of(context).extension<SendPageTheme>()!.firstGradientColor,
-                      Theme.of(context).extension<SendPageTheme>()!.secondGradientColor,
-                    ],
-                    begin: Alignment.topLeft,
-                    end: Alignment.bottomRight,
-                  ),
-                )
-              : null,
-          child: Padding(
-            padding: EdgeInsets.fromLTRB(
-              24,
-              responsiveLayoutUtil.shouldRenderMobileUI ? 110 : 55,
-              24,
-              responsiveLayoutUtil.shouldRenderMobileUI ? 32 : 0,
-            ),
-            child: SingleChildScrollView(
-              child: Observer(
-                builder: (_) => Column(
-                  mainAxisSize: MainAxisSize.min,
-                  children: <Widget>[
-                    Observer(builder: (_) {
-                      final validator = output.isParsedAddress
-                          ? sendViewModel.textValidator
-                          : sendViewModel.addressValidator;
+        child: Observer(
+          builder: (_) => Column(
+            mainAxisSize: MainAxisSize.min,
+            children: <Widget>[
+              Observer(builder: (_) {
+                final validator = output.isParsedAddress
+                    ? sendViewModel.textValidator
+                    : sendViewModel.addressValidator;
 
-                      return AddressTextField(
-                        addressKey: ValueKey('send_page_address_textfield_key'),
-                        focusNode: addressFocusNode,
-                        controller: addressController,
-                        onURIScanned: (uri) {
-                          final paymentRequest = PaymentRequest.fromUri(uri);
-                          addressController.text = paymentRequest.address;
-                          cryptoAmountController.text = paymentRequest.amount;
-                          noteController.text = paymentRequest.note;
-                        },
-                        options: [
-                          AddressTextFieldOption.paste,
-                          AddressTextFieldOption.qrCode,
-                          AddressTextFieldOption.addressBook
-                        ],
-                        buttonColor:
-                            Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
+                return AddressTextField(
+                  addressKey: ValueKey('send_page_address_textfield_key'),
+                  focusNode: addressFocusNode,
+                  controller: addressController,
+                  onURIScanned: (uri) {
+                    final paymentRequest = PaymentRequest.fromUri(uri);
+                    addressController.text = paymentRequest.address;
+                    cryptoAmountController.text = paymentRequest.amount;
+                    noteController.text = paymentRequest.note;
+                  },
+                  options: [
+                    AddressTextFieldOption.paste,
+                    AddressTextFieldOption.qrCode,
+                    AddressTextFieldOption.addressBook
+                  ],
+                  buttonColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
+                  borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
+                  textStyle:
+                      TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
+                  hintStyle: TextStyle(
+                      fontSize: 14,
+                      fontWeight: FontWeight.w500,
+                      color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
+                  onPushPasteButton: (context) async {
+                    output.resetParsedAddress();
+                    await output.fetchParsedAddress(context);
+                  },
+                  onPushAddressBookButton: (context) async {
+                    output.resetParsedAddress();
+                  },
+                  onSelectedContact: (contact) {
+                    output.loadContact(contact);
+                  },
+                  validator: validator,
+                  selectedCurrency: sendViewModel.selectedCryptoCurrency,
+                );
+              }),
+              if (output.isParsedAddress)
+                Padding(
+                    padding: const EdgeInsets.only(top: 20),
+                    child: BaseTextFormField(
+                        controller: extractedAddressController,
+                        readOnly: true,
                         borderColor:
                             Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
                         textStyle: TextStyle(
                             fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
-                        hintStyle: TextStyle(
-                            fontSize: 14,
-                            fontWeight: FontWeight.w500,
-                            color:
-                                Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
-                        onPushPasteButton: (context) async {
-                          output.resetParsedAddress();
-                          await output.fetchParsedAddress(context);
-                        },
-                        onPushAddressBookButton: (context) async {
-                          output.resetParsedAddress();
-                        },
-                        onSelectedContact: (contact) {
-                          output.loadContact(contact);
-                        },
-                        validator: validator,
-                        selectedCurrency: sendViewModel.selectedCryptoCurrency,
-                      );
-                    }),
-                    if (output.isParsedAddress)
-                      Padding(
-                          padding: const EdgeInsets.only(top: 20),
-                          child: BaseTextFormField(
-                              controller: extractedAddressController,
-                              readOnly: true,
-                              borderColor: Theme.of(context)
-                                  .extension<SendPageTheme>()!
-                                  .textFieldBorderColor,
-                              textStyle: TextStyle(
-                                  fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
-                              validator: sendViewModel.addressValidator)),
-                    CurrencyAmountTextField(
-                        currencyPickerButtonKey: ValueKey('send_page_currency_picker_button_key'),
-                        amountTextfieldKey: ValueKey('send_page_amount_textfield_key'),
-                        sendAllButtonKey: ValueKey('send_page_send_all_button_key'),
-                        currencyAmountTextFieldWidgetKey:
-                            ValueKey('send_page_crypto_currency_amount_textfield_widget_key'),
-                        selectedCurrency: sendViewModel.selectedCryptoCurrency.title,
-                        amountFocusNode: cryptoAmountFocus,
-                        amountController: cryptoAmountController,
-                        isAmountEditable: true,
-                        onTapPicker: () => _presentPicker(context),
-                        isPickerEnable: sendViewModel.hasMultipleTokens,
-                        tag: sendViewModel.selectedCryptoCurrency.tag,
-                        allAmountButton:
-                            !sendViewModel.isBatchSending && sendViewModel.shouldDisplaySendALL,
-                        currencyValueValidator: output.sendAll
-                            ? sendViewModel.allAmountValidator
-                            : sendViewModel.amountValidator,
-                        allAmountCallback: () async => output.setSendAll(sendViewModel.balance)),
-                    Divider(
-                        height: 1,
-                        color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
-                    Observer(
-                      builder: (_) => Padding(
-                        padding: EdgeInsets.only(top: 10),
-                        child: Row(
-                          mainAxisSize: MainAxisSize.max,
-                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                          children: <Widget>[
-                            Expanded(
-                              child: Text(
-                                S.of(context).available_balance + ':',
-                                style: TextStyle(
-                                    fontSize: 12,
-                                    fontWeight: FontWeight.w600,
-                                    color: Theme.of(context)
-                                        .extension<SendPageTheme>()!
-                                        .textFieldHintColor),
-                              ),
-                            ),
-                            Text(
-                              sendViewModel.balance,
-                              style: TextStyle(
-                                  fontSize: 12,
-                                  fontWeight: FontWeight.w600,
-                                  color: Theme.of(context)
-                                      .extension<SendPageTheme>()!
-                                      .textFieldHintColor),
-                            )
-                          ],
+                        validator: sendViewModel.addressValidator)),
+              CurrencyAmountTextField(
+                  currencyPickerButtonKey: ValueKey('send_page_currency_picker_button_key'),
+                  amountTextfieldKey: ValueKey('send_page_amount_textfield_key'),
+                  sendAllButtonKey: ValueKey('send_page_send_all_button_key'),
+                  currencyAmountTextFieldWidgetKey:
+                      ValueKey('send_page_crypto_currency_amount_textfield_widget_key'),
+                  selectedCurrency: sendViewModel.selectedCryptoCurrency.title,
+                  amountFocusNode: widget.cryptoAmountFocus,
+                  amountController: cryptoAmountController,
+                  isAmountEditable: true,
+                  onTapPicker: () => _presentPicker(context),
+                  isPickerEnable: sendViewModel.hasMultipleTokens,
+                  tag: sendViewModel.selectedCryptoCurrency.tag,
+                  allAmountButton:
+                      !sendViewModel.isBatchSending && sendViewModel.shouldDisplaySendALL,
+                  currencyValueValidator: output.sendAll
+                      ? sendViewModel.allAmountValidator
+                      : sendViewModel.amountValidator,
+                  allAmountCallback: () async => output.setSendAll(sendViewModel.balance)),
+              Divider(
+                  height: 1,
+                  color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
+              Observer(
+                builder: (_) => Padding(
+                  padding: EdgeInsets.only(top: 10),
+                  child: Row(
+                    mainAxisSize: MainAxisSize.max,
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: <Widget>[
+                      Expanded(
+                        child: Text(
+                          S.of(context).available_balance + ':',
+                          style: TextStyle(
+                              fontSize: 12,
+                              fontWeight: FontWeight.w600,
+                              color:
+                                  Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
                         ),
                       ),
-                    ),
-                    if (!sendViewModel.isFiatDisabled)
-                      CurrencyAmountTextField(
-                          amountTextfieldKey: ValueKey('send_page_fiat_amount_textfield_key'),
-                          currencyAmountTextFieldWidgetKey:
-                              ValueKey('send_page_fiat_currency_amount_textfield_widget_key'),
-                          selectedCurrency: sendViewModel.fiat.title,
-                          amountFocusNode: fiatAmountFocus,
-                          amountController: fiatAmountController,
-                          hintText: '0.00',
-                          isAmountEditable: true,
-                          allAmountButton: false),
-                    Divider(
-                        height: 1,
-                        color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
-                    Padding(
-                      padding: EdgeInsets.only(top: 20),
-                      child: BaseTextFormField(
-                        key: ValueKey('send_page_note_textfield_key'),
-                        controller: noteController,
-                        keyboardType: TextInputType.multiline,
-                        maxLines: null,
-                        borderColor:
-                            Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
-                        textStyle: TextStyle(
-                            fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
-                        hintText: S.of(context).note_optional,
-                        placeholderTextStyle: TextStyle(
-                            fontSize: 14,
-                            fontWeight: FontWeight.w500,
+                      Text(
+                        sendViewModel.balance,
+                        style: TextStyle(
+                            fontSize: 12,
+                            fontWeight: FontWeight.w600,
                             color:
                                 Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
-                      ),
-                    ),
-                    if (sendViewModel.hasFees)
-                      Observer(
-                        builder: (_) => GestureDetector(
-                          key: ValueKey('send_page_select_fee_priority_button_key'),
-                          onTap: sendViewModel.hasFeesPriority
-                              ? () => pickTransactionPriority(context)
-                              : () {},
-                          child: Container(
-                            padding: EdgeInsets.only(top: 24),
+                      )
+                    ],
+                  ),
+                ),
+              ),
+              if (!sendViewModel.isFiatDisabled)
+                CurrencyAmountTextField(
+                    amountTextfieldKey: ValueKey('send_page_fiat_amount_textfield_key'),
+                    currencyAmountTextFieldWidgetKey:
+                        ValueKey('send_page_fiat_currency_amount_textfield_widget_key'),
+                    selectedCurrency: sendViewModel.fiat.title,
+                    amountFocusNode: widget.fiatAmountFocus,
+                    amountController: fiatAmountController,
+                    hintText: '0.00',
+                    isAmountEditable: true,
+                    allAmountButton: false),
+              Divider(
+                  height: 1,
+                  color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
+              Padding(
+                padding: EdgeInsets.only(top: 20),
+                child: BaseTextFormField(
+                  key: ValueKey('send_page_note_textfield_key'),
+                  controller: noteController,
+                  keyboardType: TextInputType.multiline,
+                  maxLines: null,
+                  borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
+                  textStyle:
+                      TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
+                  hintText: S.of(context).note_optional,
+                  placeholderTextStyle: TextStyle(
+                      fontSize: 14,
+                      fontWeight: FontWeight.w500,
+                      color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
+                ),
+              ),
+              if (sendViewModel.hasFees)
+                Observer(
+                  builder: (_) => GestureDetector(
+                    key: ValueKey('send_page_select_fee_priority_button_key'),
+                    onTap: sendViewModel.hasFeesPriority
+                        ? () => pickTransactionPriority(context)
+                        : () {},
+                    child: Container(
+                      padding: EdgeInsets.only(top: 24),
+                      child: Row(
+                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: <Widget>[
+                          Text(
+                            S.of(context).send_estimated_fee,
+                            style: TextStyle(
+                                fontSize: 12, fontWeight: FontWeight.w500, color: Colors.white),
+                          ),
+                          Container(
                             child: Row(
-                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                               crossAxisAlignment: CrossAxisAlignment.start,
                               children: <Widget>[
-                                Text(
-                                  S.of(context).send_estimated_fee,
-                                  style: TextStyle(
-                                      fontSize: 12,
-                                      fontWeight: FontWeight.w500,
-                                      color: Colors.white),
-                                ),
-                                Container(
-                                  child: Row(
-                                    crossAxisAlignment: CrossAxisAlignment.start,
-                                    children: <Widget>[
-                                      Column(
-                                        mainAxisAlignment: MainAxisAlignment.start,
-                                        crossAxisAlignment: CrossAxisAlignment.end,
-                                        children: [
-                                          Text(
-                                            output.estimatedFee.toString() +
-                                                ' ' +
-                                                sendViewModel.currency.toString(),
-                                            style: TextStyle(
-                                              fontSize: 12,
-                                              fontWeight: FontWeight.w600,
-                                              color: Colors.white,
-                                            ),
-                                          ),
-                                          Padding(
-                                            padding: EdgeInsets.only(top: 5),
-                                            child: sendViewModel.isFiatDisabled
-                                                ? const SizedBox(height: 14)
-                                                : Text(
-                                                    output.estimatedFeeFiatAmount +
-                                                        ' ' +
-                                                        sendViewModel.fiat.title,
-                                                    style: TextStyle(
-                                                      fontSize: 12,
-                                                      fontWeight: FontWeight.w600,
-                                                      color: Theme.of(context)
-                                                          .extension<SendPageTheme>()!
-                                                          .textFieldHintColor,
-                                                    ),
-                                                  ),
-                                          ),
-                                        ],
+                                Column(
+                                  mainAxisAlignment: MainAxisAlignment.start,
+                                  crossAxisAlignment: CrossAxisAlignment.end,
+                                  children: [
+                                    Text(
+                                      output.estimatedFee.toString() +
+                                          ' ' +
+                                          sendViewModel.currency.toString(),
+                                      style: TextStyle(
+                                        fontSize: 12,
+                                        fontWeight: FontWeight.w600,
+                                        color: Colors.white,
                                       ),
-                                      Padding(
-                                        padding: EdgeInsets.only(top: 2, left: 5),
-                                        child: Icon(
-                                          Icons.arrow_forward_ios,
-                                          size: 12,
-                                          color: Colors.white,
-                                        ),
-                                      )
-                                    ],
+                                    ),
+                                    Padding(
+                                      padding: EdgeInsets.only(top: 5),
+                                      child: sendViewModel.isFiatDisabled
+                                          ? const SizedBox(height: 14)
+                                          : Text(
+                                              output.estimatedFeeFiatAmount +
+                                                  ' ' +
+                                                  sendViewModel.fiat.title,
+                                              style: TextStyle(
+                                                fontSize: 12,
+                                                fontWeight: FontWeight.w600,
+                                                color: Theme.of(context)
+                                                    .extension<SendPageTheme>()!
+                                                    .textFieldHintColor,
+                                              ),
+                                            ),
+                                    ),
+                                  ],
+                                ),
+                                Padding(
+                                  padding: EdgeInsets.only(top: 2, left: 5),
+                                  child: Icon(
+                                    Icons.arrow_forward_ios,
+                                    size: 12,
+                                    color: Colors.white,
                                   ),
                                 )
                               ],
                             ),
-                          ),
-                        ),
+                          )
+                        ],
                       ),
-                    if (sendViewModel.hasCoinControl)
-                      Padding(
-                        padding: EdgeInsets.only(top: 6),
-                        child: GestureDetector(
-                          key: ValueKey('send_page_unspent_coin_button_key'),
-                          onTap: () => Navigator.of(context).pushNamed(
-                            Routes.unspentCoinsList,
-                            arguments: widget.sendViewModel.coinTypeToSpendFrom,
-                          ),
-                          child: Container(
-                            color: Colors.transparent,
-                            child: Row(
-                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                              children: [
-                                Text(
-                                  S.of(context).coin_control,
-                                  style: TextStyle(
-                                      fontSize: 12,
-                                      fontWeight: FontWeight.w600,
-                                      color: Colors.white),
-                                ),
-                                Icon(
-                                  Icons.arrow_forward_ios,
-                                  size: 12,
-                                  color: Colors.white,
-                                ),
-                              ],
-                            ),
-                          ),
-                        ),
-                      ),
-                  ],
+                    ),
+                  ),
                 ),
-              ),
-            ),
+              if (sendViewModel.hasCoinControl)
+                Padding(
+                  padding: EdgeInsets.only(top: 6),
+                  child: GestureDetector(
+                    key: ValueKey('send_page_unspent_coin_button_key'),
+                    onTap: () => Navigator.of(context).pushNamed(
+                      Routes.unspentCoinsList,
+                      arguments: widget.sendViewModel.coinTypeToSpendFrom,
+                    ),
+                    child: Container(
+                      color: Colors.transparent,
+                      child: Row(
+                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                        children: [
+                          Text(
+                            S.of(context).coin_control,
+                            style: TextStyle(
+                                fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white),
+                          ),
+                          Icon(
+                            Icons.arrow_forward_ios,
+                            size: 12,
+                            color: Colors.white,
+                          ),
+                        ],
+                      ),
+                    ),
+                  ),
+                ),
+              if (sendViewModel.currency == CryptoCurrency.ltc)
+                Observer(
+                  builder: (_) => Padding(
+                    padding: EdgeInsets.only(top: 14),
+                    child: GestureDetector(
+                      key: ValueKey('send_page_unspent_coin_button_key'),
+                      onTap: () {
+                        bool value =
+                            widget.sendViewModel.coinTypeToSpendFrom == UnspentCoinType.any;
+                        sendViewModel.setAllowMwebCoins(!value);
+                      },
+                      child: Container(
+                        color: Colors.transparent,
+                        child: Row(
+                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                          children: [
+                            StandardCheckbox(
+                              caption: S.of(context).litecoin_mweb_allow_coins,
+                              captionColor: Colors.white,
+                              borderColor: currentTheme.type == ThemeType.bright
+                                  ? Colors.white
+                                  : Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
+                              iconColor: currentTheme.type == ThemeType.bright
+                                  ? Colors.white
+                                  : Theme.of(context).primaryColor,
+                              value:
+                                  widget.sendViewModel.coinTypeToSpendFrom == UnspentCoinType.any,
+                              onChanged: (bool? value) {
+                                sendViewModel.setAllowMwebCoins(value ?? false);
+                              },
+                            ),
+                          ],
+                        ),
+                      ),
+                    ),
+                  ),
+                ),
+            ],
           ),
-        )
-      ],
+        ),
+      ),
     );
   }
 
diff --git a/lib/src/widgets/adaptable_page_view.dart b/lib/src/widgets/adaptable_page_view.dart
new file mode 100644
index 000000000..c6800ae22
--- /dev/null
+++ b/lib/src/widgets/adaptable_page_view.dart
@@ -0,0 +1,202 @@
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
+
+const _firstLayoutMaxHeight = 10000.0;
+
+class PageViewHeightAdaptable extends StatefulWidget {
+  const PageViewHeightAdaptable({
+    super.key,
+    required this.controller,
+    required this.children,
+  }) : assert(children.length > 0, 'children must not be empty');
+
+  final PageController controller;
+  final List<Widget> children;
+
+  @override
+  State<PageViewHeightAdaptable> createState() => _PageViewHeightAdaptableState();
+}
+
+class _PageViewHeightAdaptableState extends State<PageViewHeightAdaptable> {
+  final _sizes = <int, Size>{};
+
+  @override
+  void didUpdateWidget(PageViewHeightAdaptable oldWidget) {
+    super.didUpdateWidget(oldWidget);
+
+    _sizes.clear();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return ListenableBuilder(
+      listenable: widget.controller,
+      builder: (context, child) => _SizingContainer(
+        sizes: _sizes,
+        page: widget.controller.hasClients ? widget.controller.page ?? 0 : 0,
+        child: child!,
+      ),
+      child: LayoutBuilder(
+        builder: (context, constraints) => PageView(
+          controller: widget.controller,
+          children: [
+            for (final (i, child) in widget.children.indexed)
+              Stack(
+                alignment: Alignment.topCenter,
+                clipBehavior: Clip.hardEdge,
+                children: [
+                  SizedBox.fromSize(size: _sizes[i]),
+                  Positioned(
+                    left: 0,
+                    top: 0,
+                    right: 0,
+                    child: _SizeAware(
+                      child: child,
+                      // don't setState, we'll use it in the layout phase
+                      onSizeLaidOut: (size) {
+                        _sizes[i] = size;
+                      },
+                    ),
+                  ),
+                ],
+              ),
+          ],
+        ),
+      ),
+    );
+  }
+}
+
+typedef _OnSizeLaidOutCallback = void Function(Size);
+
+class _SizingContainer extends SingleChildRenderObjectWidget {
+  const _SizingContainer({
+    super.child,
+    required this.sizes,
+    required this.page,
+  });
+
+  final Map<int, Size> sizes;
+  final double page;
+
+  @override
+  _RenderSizingContainer createRenderObject(BuildContext context) {
+    return _RenderSizingContainer(
+      sizes: sizes,
+      page: page,
+    );
+  }
+
+  @override
+  void updateRenderObject(
+    BuildContext context,
+    _RenderSizingContainer renderObject,
+  ) {
+    renderObject
+      ..sizes = sizes
+      ..page = page;
+  }
+}
+
+class _RenderSizingContainer extends RenderProxyBox {
+  _RenderSizingContainer({
+    RenderBox? child,
+    required Map<int, Size> sizes,
+    required double page,
+  })  : _sizes = sizes,
+        _page = page,
+        super(child);
+
+  Map<int, Size> _sizes;
+  Map<int, Size> get sizes => _sizes;
+  set sizes(Map<int, Size> value) {
+    if (_sizes == value) return;
+    _sizes = value;
+    markNeedsLayout();
+  }
+
+  double _page;
+  double get page => _page;
+  set page(double value) {
+    if (_page == value) return;
+    _page = value;
+    markNeedsLayout();
+  }
+
+  @override
+  void performLayout() {
+    if (child case final child?) {
+      child.layout(
+        constraints.copyWith(
+          minWidth: constraints.maxWidth,
+          minHeight: 0,
+          maxHeight: constraints.hasBoundedHeight ? null : _firstLayoutMaxHeight,
+        ),
+        parentUsesSize: true,
+      );
+
+      final a = sizes[page.floor()]!;
+      final b = sizes[page.ceil()]!;
+
+      final height = lerpDouble(a.height, b.height, page - page.floor());
+
+      child.layout(
+        constraints.copyWith(minHeight: height, maxHeight: height),
+        parentUsesSize: true,
+      );
+      size = child.size;
+    } else {
+      size = computeSizeForNoChild(constraints);
+    }
+  }
+}
+
+class _SizeAware extends SingleChildRenderObjectWidget {
+  const _SizeAware({
+    required Widget child,
+    required this.onSizeLaidOut,
+  }) : super(child: child);
+
+  final _OnSizeLaidOutCallback onSizeLaidOut;
+
+  @override
+  _RenderSizeAware createRenderObject(BuildContext context) {
+    return _RenderSizeAware(
+      onSizeLaidOut: onSizeLaidOut,
+    );
+  }
+
+  @override
+  void updateRenderObject(BuildContext context, _RenderSizeAware renderObject) {
+    renderObject.onSizeLaidOut = onSizeLaidOut;
+  }
+}
+
+class _RenderSizeAware extends RenderProxyBox {
+  _RenderSizeAware({
+    RenderBox? child,
+    required _OnSizeLaidOutCallback onSizeLaidOut,
+  })  : _onSizeLaidOut = onSizeLaidOut,
+        super(child);
+
+  _OnSizeLaidOutCallback? _onSizeLaidOut;
+  _OnSizeLaidOutCallback get onSizeLaidOut => _onSizeLaidOut!;
+  set onSizeLaidOut(_OnSizeLaidOutCallback value) {
+    if (_onSizeLaidOut == value) return;
+    _onSizeLaidOut = value;
+    markNeedsLayout();
+  }
+
+  @override
+  void performLayout() {
+    super.performLayout();
+
+    onSizeLaidOut(
+      getDryLayout(
+        constraints.copyWith(maxHeight: double.infinity),
+      ),
+    );
+  }
+}
\ No newline at end of file
diff --git a/lib/src/widgets/standard_checkbox.dart b/lib/src/widgets/standard_checkbox.dart
index d61b84d1d..2b06ff1c6 100644
--- a/lib/src/widgets/standard_checkbox.dart
+++ b/lib/src/widgets/standard_checkbox.dart
@@ -9,6 +9,7 @@ class StandardCheckbox extends StatelessWidget {
       this.gradientBackground = false,
       this.borderColor,
       this.iconColor,
+      this.captionColor,
       required this.onChanged});
 
   final bool value;
@@ -16,6 +17,7 @@ class StandardCheckbox extends StatelessWidget {
   final bool gradientBackground;
   final Color? borderColor;
   final Color? iconColor;
+  final Color? captionColor;
   final Function(bool) onChanged;
 
   @override
@@ -68,7 +70,7 @@ class StandardCheckbox extends StatelessWidget {
                     fontSize: 16.0,
                     fontFamily: 'Lato',
                     fontWeight: FontWeight.normal,
-                    color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
+                    color: captionColor ?? Theme.of(context).extension<CakeTextTheme>()!.titleColor,
                     decoration: TextDecoration.none,
                   ),
                 ),
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 998521ede..3dce212af 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -77,7 +77,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
     this.transactionDescriptionBox,
     this.ledgerViewModel,
     this.unspentCoinsListViewModel, {
-    this.coinTypeToSpendFrom = UnspentCoinType.any,
+    this.coinTypeToSpendFrom = UnspentCoinType.nonMweb,
   })  : state = InitialExecutionState(),
         currencies = appStore.wallet!.balance.keys.toList(),
         selectedCryptoCurrency = appStore.wallet!.currency,
@@ -112,7 +112,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
 
   ObservableList<Output> outputs;
 
-  final UnspentCoinType coinTypeToSpendFrom;
+  @observable
+  UnspentCoinType coinTypeToSpendFrom;
 
   bool get showAddressBookPopup => _settingsStore.showAddressBookPopupEnabled;
 
@@ -135,6 +136,13 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
     addOutput();
   }
 
+  @action
+  void setAllowMwebCoins(bool allow) {
+    if (wallet.type == WalletType.litecoin) {
+      coinTypeToSpendFrom = allow ? UnspentCoinType.any : UnspentCoinType.nonMweb;
+    }
+  }
+
   @computed
   bool get isBatchSending => outputs.length > 1;
 
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index 84f0c17ce..faf14e18d 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -394,6 +394,7 @@
   "light_theme": "فاتح",
   "litecoin_enable_mweb_sync": "تمكين MWEB المسح الضوئي",
   "litecoin_mweb": "mweb",
+  "litecoin_mweb_allow_coins": "السماح للعملات المعدنية MWEB",
   "litecoin_mweb_always_scan": "اضبط MWEB دائمًا على المسح الضوئي",
   "litecoin_mweb_description": "MWEB هو بروتوكول جديد يجلب معاملات أسرع وأرخص وأكثر خصوصية إلى Litecoin",
   "litecoin_mweb_dismiss": "رفض",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index c67d8915a..7ac75f00e 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -394,6 +394,7 @@
   "light_theme": "Светло",
   "litecoin_enable_mweb_sync": "Активирайте сканирането на MWeb",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Позволете на MWeb монети",
   "litecoin_mweb_always_scan": "Задайте MWeb винаги сканиране",
   "litecoin_mweb_description": "MWeb е нов протокол, който носи по -бърз, по -евтин и повече частни транзакции на Litecoin",
   "litecoin_mweb_dismiss": "Уволнение",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index 349ae67bc..f777ffe60 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -394,6 +394,7 @@
   "light_theme": "Světlý",
   "litecoin_enable_mweb_sync": "Povolit skenování MWeb",
   "litecoin_mweb": "MWeb",
+  "litecoin_mweb_allow_coins": "Povolte mweb mince",
   "litecoin_mweb_always_scan": "Nastavit MWeb vždy skenování",
   "litecoin_mweb_description": "MWEB je nový protokol, který do Litecoin přináší rychlejší, levnější a více soukromých transakcí",
   "litecoin_mweb_dismiss": "Propustit",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 895fa4183..35012b20d 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -394,6 +394,7 @@
   "light_theme": "Hell",
   "litecoin_enable_mweb_sync": "Aktivieren Sie das MWEB-Scannen",
   "litecoin_mweb": "MWeb",
+  "litecoin_mweb_allow_coins": "MWEB -Münzen zulassen",
   "litecoin_mweb_always_scan": "Setzen Sie MWeb immer scannen",
   "litecoin_mweb_description": "MWWB ist ein neues Protokoll, das schnellere, billigere und privatere Transaktionen zu Litecoin bringt",
   "litecoin_mweb_dismiss": "Zurückweisen",
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index c03841cb9..6875794fd 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -394,6 +394,7 @@
   "light_theme": "Light",
   "litecoin_enable_mweb_sync": "Enable MWEB scanning",
   "litecoin_mweb": "MWEB",
+  "litecoin_mweb_allow_coins": "Allow MWEB coins",
   "litecoin_mweb_always_scan": "Set MWEB always scanning",
   "litecoin_mweb_description": "MWEB is a new protocol that brings faster, cheaper, and more private transactions to Litecoin",
   "litecoin_mweb_dismiss": "Dismiss",
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index dcff955bb..42e7eedc0 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -394,6 +394,7 @@
   "light_theme": "Ligero",
   "litecoin_enable_mweb_sync": "Habilitar el escaneo mweb",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Permitir monedas mweb",
   "litecoin_mweb_always_scan": "Establecer mweb siempre escaneo",
   "litecoin_mweb_description": "Mweb es un nuevo protocolo que trae transacciones más rápidas, más baratas y más privadas a Litecoin",
   "litecoin_mweb_dismiss": "Despedir",
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index 379290a29..4960d980a 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -394,6 +394,7 @@
   "light_theme": "Clair",
   "litecoin_enable_mweb_sync": "Activer la numérisation MWEB",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Autoriser les pièces MWeb",
   "litecoin_mweb_always_scan": "Définir MWEB Score Scanning",
   "litecoin_mweb_description": "MWEB est un nouveau protocole qui apporte des transactions plus rapides, moins chères et plus privées à Litecoin",
   "litecoin_mweb_dismiss": "Rejeter",
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index 125ceeaf5..068457568 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -394,6 +394,7 @@
   "light_theme": "Haske",
   "litecoin_enable_mweb_sync": "Kunna binciken Mweb",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Bada izinin Coins na Mweb",
   "litecoin_mweb_always_scan": "Saita Mweb koyaushe",
   "litecoin_mweb_description": "Mweb shine sabon tsarin yarjejeniya da ya kawo da sauri, mai rahusa, da kuma ma'amaloli masu zaman kansu zuwa Litecoin",
   "litecoin_mweb_dismiss": "Tuɓe \\ sallama",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index 074f3ba09..248b0230c 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -394,6 +394,7 @@
   "light_theme": "रोशनी",
   "litecoin_enable_mweb_sync": "MWEB स्कैनिंग सक्षम करें",
   "litecoin_mweb": "मावली",
+  "litecoin_mweb_allow_coins": "MWEB सिक्कों की अनुमति दें",
   "litecoin_mweb_always_scan": "MWEB हमेशा स्कैनिंग सेट करें",
   "litecoin_mweb_description": "MWEB एक नया प्रोटोकॉल है जो लिटकोइन के लिए तेजी से, सस्ता और अधिक निजी लेनदेन लाता है",
   "litecoin_mweb_dismiss": "नकार देना",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index be447f24d..5c83942a1 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -394,6 +394,7 @@
   "light_theme": "Svijetla",
   "litecoin_enable_mweb_sync": "Omogućite MWEB skeniranje",
   "litecoin_mweb": "MWeb",
+  "litecoin_mweb_allow_coins": "Dopustite MWeb kovanice",
   "litecoin_mweb_always_scan": "Postavite MWeb uvijek skeniranje",
   "litecoin_mweb_description": "MWEB je novi protokol koji u Litecoin donosi brže, jeftinije i privatnije transakcije",
   "litecoin_mweb_dismiss": "Odbaciti",
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index 551e28cef..2719015cc 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -394,6 +394,7 @@
   "light_theme": "Լուսավոր",
   "litecoin_enable_mweb_sync": "Միացնել MWEB սկան",
   "litecoin_mweb": "Մուեբ",
+  "litecoin_mweb_allow_coins": "Թույլ տվեք MWeb մետաղադրամներ",
   "litecoin_mweb_always_scan": "Սահմանեք Mweb Միշտ սկանավորում",
   "litecoin_mweb_description": "Mweb- ը նոր արձանագրություն է, որը բերում է ավելի արագ, ավելի էժան եւ ավելի մասնավոր գործարքներ դեպի LITECOIN",
   "litecoin_mweb_dismiss": "Հեռացնել",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index a171f3243..ccf4367e3 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -394,6 +394,7 @@
   "light_theme": "Terang",
   "litecoin_enable_mweb_sync": "Aktifkan pemindaian MWEB",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Izinkan koin mWeb",
   "litecoin_mweb_always_scan": "Atur mWeb selalu memindai",
   "litecoin_mweb_description": "MWEB adalah protokol baru yang membawa transaksi yang lebih cepat, lebih murah, dan lebih pribadi ke Litecoin",
   "litecoin_mweb_dismiss": "Membubarkan",
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index f035c3493..a1682a11f 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -394,6 +394,7 @@
   "light_theme": "Chiaro",
   "litecoin_enable_mweb_sync": "Abilita la scansione MWeb",
   "litecoin_mweb": "MWeb",
+  "litecoin_mweb_allow_coins": "Consenti monete mWeb",
   "litecoin_mweb_always_scan": "Imposta MWeb per scansionare sempre",
   "litecoin_mweb_description": "MWeb è un nuovo protocollo che porta transazioni più veloci, più economiche e più private a Litecoin",
   "litecoin_mweb_dismiss": "Chiudi",
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index 89fcc5391..f97baf7b4 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -395,6 +395,7 @@
   "light_theme": "光",
   "litecoin_enable_mweb_sync": "MWEBスキャンを有効にします",
   "litecoin_mweb": "mweb",
+  "litecoin_mweb_allow_coins": "MWEBコインを許可します",
   "litecoin_mweb_always_scan": "MWEBを常にスキャンします",
   "litecoin_mweb_description": "MWEBは、Litecoinにより速く、より安価で、よりプライベートなトランザクションをもたらす新しいプロトコルです",
   "litecoin_mweb_dismiss": "却下する",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index e8e23a1a2..75af5c195 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -394,6 +394,7 @@
   "light_theme": "빛",
   "litecoin_enable_mweb_sync": "mweb 스캔을 활성화합니다",
   "litecoin_mweb": "mweb",
+  "litecoin_mweb_allow_coins": "mweb 코인을 허용하십시오",
   "litecoin_mweb_always_scan": "mweb는 항상 스캔을 설정합니다",
   "litecoin_mweb_description": "MWEB는 Litecoin에 더 빠르고 저렴하며 개인 거래를 제공하는 새로운 프로토콜입니다.",
   "litecoin_mweb_dismiss": "해고하다",
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index c21413a44..9f200a030 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -394,6 +394,7 @@
   "light_theme": "အလင်း",
   "litecoin_enable_mweb_sync": "mweb scanning ဖွင့်ပါ",
   "litecoin_mweb": "မင်္ဂလာပါ",
+  "litecoin_mweb_allow_coins": "mweb ဒင်္ဂါးများကိုခွင့်ပြုပါ",
   "litecoin_mweb_always_scan": "Mweb အမြဲစကင်ဖတ်စစ်ဆေးပါ",
   "litecoin_mweb_description": "Mweb သည် Protocol အသစ်ဖြစ်ပြီး LitCoin သို့ပိုမိုဈေးချိုသာသော, စျေးသက်သက်သာသာသုံးခြင်းနှင့်ပိုမိုများပြားသောပုဂ္ဂလိကငွေပို့ဆောင်မှုများကိုဖြစ်ပေါ်စေသည်",
   "litecoin_mweb_dismiss": "ထုတ်ပစ်",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 0b32a7fc9..1b41eea22 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -394,6 +394,7 @@
   "light_theme": "Licht",
   "litecoin_enable_mweb_sync": "MWEB -scanning inschakelen",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Sta mweb munten toe",
   "litecoin_mweb_always_scan": "Stel mweb altijd op scannen",
   "litecoin_mweb_description": "MWEB is een nieuw protocol dat snellere, goedkopere en meer privé -transacties naar Litecoin brengt",
   "litecoin_mweb_dismiss": "Afwijzen",
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index b5acc57ed..8b96bde04 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -394,6 +394,7 @@
   "light_theme": "Jasny",
   "litecoin_enable_mweb_sync": "Włącz skanowanie MWEB",
   "litecoin_mweb": "MWEB",
+  "litecoin_mweb_allow_coins": "Zezwalaj na monety MWEB",
   "litecoin_mweb_always_scan": "Ustaw MWEB zawsze skanowanie",
   "litecoin_mweb_description": "MWEB to nowy protokół, który przynosi szybciej, tańsze i bardziej prywatne transakcje do Litecoin",
   "litecoin_mweb_dismiss": "Odrzucać",
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index 8ec99f0f8..096c3f413 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -394,6 +394,7 @@
   "light_theme": "Luz",
   "litecoin_enable_mweb_sync": "Ativar digitalização do MWEB",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Permitir moedas MWEB",
   "litecoin_mweb_always_scan": "Definir mweb sempre digitalizando",
   "litecoin_mweb_description": "MWEB é um novo protocolo que traz transações mais rápidas, baratas e mais privadas para o Litecoin",
   "litecoin_mweb_dismiss": "Liberar",
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index 8ef7ac579..6fe82abcf 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -394,6 +394,7 @@
   "light_theme": "Светлая",
   "litecoin_enable_mweb_sync": "Включить MWEB сканирование",
   "litecoin_mweb": "Мвеб",
+  "litecoin_mweb_allow_coins": "Разрешить монеты MWEB",
   "litecoin_mweb_always_scan": "Установить MWEB всегда сканирование",
   "litecoin_mweb_description": "MWEB - это новый протокол, который приносит быстрее, дешевле и более частные транзакции в Litecoin",
   "litecoin_mweb_dismiss": "Увольнять",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index 414bbe52f..35e94e508 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -394,6 +394,7 @@
   "light_theme": "สว่าง",
   "litecoin_enable_mweb_sync": "เปิดใช้งานการสแกน MWEB",
   "litecoin_mweb": "mweb",
+  "litecoin_mweb_allow_coins": "อนุญาตให้เหรียญ MWEB",
   "litecoin_mweb_always_scan": "ตั้งค่าการสแกน MWEB เสมอ",
   "litecoin_mweb_description": "MWEB เป็นโปรโตคอลใหม่ที่นำการทำธุรกรรมที่เร็วกว่าราคาถูกกว่าและเป็นส่วนตัวมากขึ้นไปยัง Litecoin",
   "litecoin_mweb_dismiss": "อนุญาตให้ออกไป",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index 46a7540bd..d9cdbbb3e 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -394,6 +394,7 @@
   "light_theme": "Light",
   "litecoin_enable_mweb_sync": "Paganahin ang pag -scan ng MWeb",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Payagan ang mga barya ng MWEB",
   "litecoin_mweb_always_scan": "Itakda ang MWeb na laging nag -scan",
   "litecoin_mweb_description": "Ang MWeb ay isang bagong protocol na nagdadala ng mas mabilis, mas mura, at mas maraming pribadong mga transaksyon sa Litecoin",
   "litecoin_mweb_dismiss": "Tanggalin",
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index 8fcacb9ba..5d7c77050 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -394,6 +394,7 @@
   "light_theme": "Aydınlık",
   "litecoin_enable_mweb_sync": "MWEB taramasını etkinleştir",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "MWEB Coins'e izin ver",
   "litecoin_mweb_always_scan": "MWEB'i her zaman taramayı ayarlayın",
   "litecoin_mweb_description": "MWEB, Litecoin'e daha hızlı, daha ucuz ve daha fazla özel işlem getiren yeni bir protokoldür",
   "litecoin_mweb_dismiss": "Azletmek",
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index 6b111f72f..1a6d113b0 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -394,6 +394,7 @@
   "light_theme": "Світла",
   "litecoin_enable_mweb_sync": "Увімкнути сканування MWEB",
   "litecoin_mweb": "Мвеб",
+  "litecoin_mweb_allow_coins": "Дозволити монети MWEB",
   "litecoin_mweb_always_scan": "Встановити mweb завжди сканувати",
   "litecoin_mweb_description": "MWEB - це новий протокол, який приносить швидкі, дешевші та більш приватні транзакції Litecoin",
   "litecoin_mweb_dismiss": "Звільнити",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index d1a2b4ca9..a7b70dae2 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -394,6 +394,7 @@
   "light_theme": "روشنی",
   "litecoin_enable_mweb_sync": "MWEB اسکیننگ کو فعال کریں",
   "litecoin_mweb": "MWEB",
+  "litecoin_mweb_allow_coins": "MWEB سکے کی اجازت دیں",
   "litecoin_mweb_always_scan": "MWEB ہمیشہ اسکیننگ سیٹ کریں",
   "litecoin_mweb_description": "MWEB ایک نیا پروٹوکول ہے جو لیٹیکوئن میں تیز ، سستا اور زیادہ نجی لین دین لاتا ہے",
   "litecoin_mweb_dismiss": "خارج",
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index 2aba61ef3..ff547e77b 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -393,6 +393,7 @@
   "light_theme": "Chủ đề sáng",
   "litecoin_enable_mweb_sync": "Bật quét MWEB",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Cho phép tiền xu MWEB",
   "litecoin_mweb_always_scan": "Đặt MWEB luôn quét",
   "litecoin_mweb_description": "MWEB là một giao thức mới mang lại các giao dịch nhanh hơn, rẻ hơn và riêng tư hơn cho Litecoin",
   "litecoin_mweb_dismiss": "Miễn nhiệm",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 744159a30..6eb66754c 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -395,6 +395,7 @@
   "light_theme": "Funfun bí eérú",
   "litecoin_enable_mweb_sync": "Mu mweb ọlọjẹ",
   "litecoin_mweb": "Mweb",
+  "litecoin_mweb_allow_coins": "Gba awọn owo Mweb gba",
   "litecoin_mweb_always_scan": "Ṣeto mweb nigbagbogbo n ṣayẹwo",
   "litecoin_mweb_description": "Mweb jẹ ilana ilana tuntun ti o mu iyara wa yiyara, din owo, ati awọn iṣowo ikọkọ diẹ sii si Livcoin",
   "litecoin_mweb_dismiss": "Tuka",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index a3b5ec421..ed890c17a 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -394,6 +394,7 @@
   "light_theme": "艳丽",
   "litecoin_enable_mweb_sync": "启用MWEB扫描",
   "litecoin_mweb": "MWEB",
+  "litecoin_mweb_allow_coins": "允许MWEB硬币",
   "litecoin_mweb_always_scan": "设置MWEB总是扫描",
   "litecoin_mweb_description": "MWEB是一项新协议,它将更快,更便宜和更多的私人交易带给Litecoin",
   "litecoin_mweb_dismiss": "解雇",