From b56dcaca1ca787361f3c81a2122714131911d182 Mon Sep 17 00:00:00 2001
From: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Date: Wed, 16 Oct 2024 02:58:41 +0100
Subject: [PATCH 01/50] fix: Issue with nownodes on older wallets (#1750)

---
 lib/entities/default_settings_migration.dart | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index 1c46cd605..2b8c49631 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -254,6 +254,7 @@ Future<void> defaultSettingsMigration(
         case 41:
           _deselectQuantex(sharedPreferences);
           await _addSethNode(nodes, sharedPreferences);
+          await updateTronNodesWithNowNodes(sharedPreferences: sharedPreferences, nodes: nodes);
           break;
         default:
           break;
@@ -1317,3 +1318,16 @@ Future<void> removeMoneroWorld(
     await changeMoneroCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
   }
 }
+
+Future<void> updateTronNodesWithNowNodes({
+  required SharedPreferences sharedPreferences,
+  required Box<Node> nodes,
+}) async {
+  final tronNowNodesUri = 'trx.nownodes.io';
+
+  if (nodes.values.any((node) => node.uriRaw == tronNowNodesUri)) return;
+
+  await nodes.add(Node(uri: tronNowNodesUri, type: WalletType.tron));
+
+  await replaceTronDefaultNode(sharedPreferences: sharedPreferences, nodes: nodes);
+}

From cb75f08b35617452ed4a6013172494104c6bfabc Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Wed, 16 Oct 2024 16:28:24 +0300
Subject: [PATCH 02/50] fix P2wpkhAddress btc ltc validation (#1749)

* fix P2wpkhAddress btc ltc validation

* Update address_validator.dart
---
 lib/core/address_validator.dart | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart
index 0aabfa032..21726fab8 100644
--- a/lib/core/address_validator.dart
+++ b/lib/core/address_validator.dart
@@ -36,9 +36,9 @@ class AddressValidator extends TextValidator {
             '|[0-9a-zA-Z]{105}|addr1[0-9a-zA-Z]{98}';
       case CryptoCurrency.btc:
         pattern =
-            '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
+            '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${RegExp(r'(bc|tb)1q[ac-hj-np-z02-9]{25,39}}').pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
       case CryptoCurrency.ltc:
-        pattern = '^${P2wpkhAddress.regex.pattern}\$|^${MwebAddress.regex.pattern}\$';
+        pattern = '^${RegExp(r'ltc1q[ac-hj-np-z02-9]{25,39}').pattern}\$|^${MwebAddress.regex.pattern}\$';
       case CryptoCurrency.nano:
         pattern = '[0-9a-zA-Z_]+';
       case CryptoCurrency.banano:

From 605d164998c0f964267861edfff1972c88e15ab1 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Wed, 16 Oct 2024 20:25:22 +0300
Subject: [PATCH 03/50] Cw 772 restore from qr generates different wallet
 (#1742)

* fix derivation info for QR restoring

* allow all available seed languages for Monero

* set default derivation info for an empty wallet

* fix electrum case
---
 .../restore/restore_from_qr_vm.dart           | 12 +++++-
 lib/view_model/wallet_creation_vm.dart        | 41 +++++++++++--------
 2 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart
index 042a048d9..cbdad85b8 100644
--- a/lib/view_model/restore/restore_from_qr_vm.dart
+++ b/lib/view_model/restore/restore_from_qr_vm.dart
@@ -37,7 +37,8 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
         spendKey = '',
         wif = '',
         address = '',
-        super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel, type: type, isRecovery: true);
+        super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel,
+          type: type, isRecovery: true);
 
   @observable
   int height;
@@ -112,7 +113,14 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
             );
           case WalletType.bitcoin:
           case WalletType.litecoin:
-            final derivationInfo = (await getDerivationInfoFromQRCredentials(restoreWallet)).first;
+
+          final derivationInfoList = await getDerivationInfoFromQRCredentials(restoreWallet);
+          DerivationInfo derivationInfo;
+          if (derivationInfoList.isEmpty) {
+            derivationInfo = getDefaultCreateDerivation()!;
+          } else {
+            derivationInfo = derivationInfoList.first;
+          }
             return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials(
               name: name,
               mnemonic: restoreWallet.mnemonicSeed ?? '',
diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart
index f31f879a1..90b4c5c3a 100644
--- a/lib/view_model/wallet_creation_vm.dart
+++ b/lib/view_model/wallet_creation_vm.dart
@@ -194,24 +194,31 @@ abstract class WalletCreationVMBase with Store {
     final walletType = restoreWallet.type;
     var appStore = getIt.get<AppStore>();
     var node = appStore.settingsStore.getCurrentNode(walletType);
+    
+      switch (walletType) {
+        case WalletType.bitcoin:
+        case WalletType.litecoin:
 
-    switch (walletType) {
-      case WalletType.bitcoin:
-      case WalletType.litecoin:
-        return bitcoin!.getDerivationsFromMnemonic(
-          mnemonic: restoreWallet.mnemonicSeed!,
-          node: node,
-          passphrase: restoreWallet.passphrase,
-        );
-      case WalletType.nano:
-        return nanoUtil!.getDerivationsFromMnemonic(
-          mnemonic: restoreWallet.mnemonicSeed!,
-          node: node,
-        );
-      default:
-        break;
-    }
-    return list;
+          final derivationList = await bitcoin!.getDerivationsFromMnemonic(
+            mnemonic: restoreWallet.mnemonicSeed!,
+            node: node,
+            passphrase: restoreWallet.passphrase,
+          );
+
+
+          if (derivationList.first.transactionsCount == 0 && derivationList.length > 1) return [];
+          
+          return derivationList;
+
+        case WalletType.nano:
+          return nanoUtil!.getDerivationsFromMnemonic(
+            mnemonic: restoreWallet.mnemonicSeed!,
+            node: node,
+          );
+        default:
+          break;
+      }
+      return list;
   }
 
   WalletCredentials getCredentials(dynamic options) => throw UnimplementedError();

From 564f8e2c70c3e377db985097680c377a034e72a9 Mon Sep 17 00:00:00 2001
From: cyan <cyjan@mrcyjanek.net>
Date: Wed, 16 Oct 2024 19:27:04 +0200
Subject: [PATCH 04/50] fix backup on debug builds (#1728)

open transactionDecscriptionBox if it's not open
---
 lib/core/backup_service.dart | 38 ++++++++++++++++++++++++++++++++++--
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart
index ba90a0449..d65530eb5 100644
--- a/lib/core/backup_service.dart
+++ b/lib/core/backup_service.dart
@@ -2,6 +2,7 @@ import 'dart:convert';
 import 'dart:io';
 import 'dart:typed_data';
 import 'package:cake_wallet/core/secure_storage.dart';
+import 'package:cake_wallet/entities/get_encryption_key.dart';
 import 'package:cake_wallet/entities/transaction_description.dart';
 import 'package:cake_wallet/themes/theme_list.dart';
 import 'package:cw_core/root_dir.dart';
@@ -105,7 +106,15 @@ class BackupService {
       if (entity.path == archivePath || entity.path == tmpDir.path) {
         return;
       }
-
+      final filename = entity.absolute;
+      for (var ignore in ignoreFiles) {
+        final filename = entity.absolute.path;
+        if (filename.endsWith(ignore) && !filename.contains("wallets/")) {
+          print("ignoring backup file: $filename");
+          return;
+        }
+      }
+      print("restoring: $filename");
       if (entity.statSync().type == FileSystemEntityType.directory) {
         zipEncoder.addDirectory(Directory(entity.path));
       } else {
@@ -148,14 +157,29 @@ class BackupService {
     await _importPreferencesDump();
   }
 
+  // checked with .endsWith - so this should be the last part of the filename
+  static const ignoreFiles = [
+    "flutter_assets/kernel_blob.bin",
+    "flutter_assets/vm_snapshot_data",
+    "flutter_assets/isolate_snapshot_data",
+    ".lock",
+  ];
+
   Future<void> _importBackupV2(Uint8List data, String password) async {
     final appDir = await getAppDir();
     final decryptedData = await _decryptV2(data, password);
     final zip = ZipDecoder().decodeBytes(decryptedData);
 
+    outer:
     for (var file in zip.files) {
       final filename = file.name;
-
+      for (var ignore in ignoreFiles) { 
+        if (filename.endsWith(ignore) && !filename.contains("wallets/")) {
+          print("ignoring backup file: $filename");
+          continue outer;
+        }
+      }
+      print("restoring: $filename");
       if (file.isFile) {
         final content = file.content as List<int>;
         File('${appDir.path}/' + filename)
@@ -206,6 +230,16 @@ class BackupService {
         json.decode(transactionDescriptionFile.readAsStringSync()) as Map<String, dynamic>;
     final descriptionsMap = jsonData.map((key, value) =>
         MapEntry(key, TransactionDescription.fromJson(value as Map<String, dynamic>)));
+
+    if (!_transactionDescriptionBox.isOpen) {
+      final transactionDescriptionsBoxKey = await getEncryptionKey(secureStorage: secureStorageShared, forKey: TransactionDescription.boxKey);
+      final transactionDescriptionBox = await CakeHive.openBox<TransactionDescription>(
+        TransactionDescription.boxName,
+        encryptionKey: transactionDescriptionsBoxKey,
+      );
+      await transactionDescriptionBox.putAll(descriptionsMap);
+      return;
+    }
     await _transactionDescriptionBox.putAll(descriptionsMap);
   }
 

From cd5a1277a7759e11d3f5d0714abb3b8df8e463db Mon Sep 17 00:00:00 2001
From: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Date: Thu, 17 Oct 2024 02:17:29 +0100
Subject: [PATCH 05/50] Disable sendAll on native EVM Currencies (#1753)

* fix: Issue with nownodes on older wallets

* fix: Disable sendAll on native evm currencies
---
 lib/view_model/send/send_view_model.dart | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 0ad8ba376..334394a18 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -123,7 +123,17 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
   @computed
   bool get isBatchSending => outputs.length > 1;
 
-  bool get shouldDisplaySendALL => walletType != WalletType.solana;
+  bool get shouldDisplaySendALL {
+    if (walletType == WalletType.solana) return false;
+
+    if (walletType == WalletType.ethereum && selectedCryptoCurrency == CryptoCurrency.eth)
+      return false;
+
+      if (walletType == WalletType.polygon && selectedCryptoCurrency == CryptoCurrency.matic)
+      return false;
+
+    return true;
+  }
 
   @computed
   String get pendingTransactionFiatAmount {

From 6c9de67599fb0612ee95a87ab644e8b83ffb858e Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Thu, 17 Oct 2024 14:52:55 +0200
Subject: [PATCH 06/50] Fix fiat rate on receive screen. (#1754)

* Fix fiat rate on receive screen.

* Code cleanup

* Update Receive QR on currency change
---
 .../wallet_address_list_view_model.dart       | 231 ++++++++++--------
 1 file changed, 133 insertions(+), 98 deletions(-)

diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
index 0260dc6b4..3e399266a 100644
--- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
+++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
@@ -1,14 +1,15 @@
-import 'dart:math';
+import 'dart:developer' as dev;
 
 import 'package:cake_wallet/bitcoin/bitcoin.dart';
+import 'package:cake_wallet/core/fiat_conversion_service.dart';
 import 'package:cake_wallet/core/wallet_change_listener_view_model.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/fiat_currency.dart';
 import 'package:cake_wallet/ethereum/ethereum.dart';
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/haven/haven.dart';
 import 'package:cake_wallet/monero/monero.dart';
-import 'package:cake_wallet/nano/nano.dart';
 import 'package:cake_wallet/polygon/polygon.dart';
 import 'package:cake_wallet/solana/solana.dart';
 import 'package:cake_wallet/store/app_store.dart';
@@ -24,16 +25,14 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_i
 import 'package:cake_wallet/wownero/wownero.dart';
 import 'package:cw_core/amount_converter.dart';
 import 'package:cw_core/currency.dart';
-import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_type.dart';
-import 'package:cw_monero/api/wallet.dart';
-import 'package:flutter/foundation.dart';
 import 'package:intl/intl.dart';
 import 'package:mobx/mobx.dart';
 
 part 'wallet_address_list_view_model.g.dart';
 
-class WalletAddressListViewModel = WalletAddressListViewModelBase with _$WalletAddressListViewModel;
+class WalletAddressListViewModel = WalletAddressListViewModelBase
+    with _$WalletAddressListViewModel;
 
 abstract class PaymentURI {
   PaymentURI({required this.amount, required this.address});
@@ -43,12 +42,11 @@ abstract class PaymentURI {
 }
 
 class MoneroURI extends PaymentURI {
-  MoneroURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  MoneroURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'monero:' + address;
+    var base = 'monero:$address';
 
     if (amount.isNotEmpty) {
       base += '?tx_amount=${amount.replaceAll(',', '.')}';
@@ -59,12 +57,11 @@ class MoneroURI extends PaymentURI {
 }
 
 class HavenURI extends PaymentURI {
-  HavenURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  HavenURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'haven:' + address;
+    var base = 'haven:$address';
 
     if (amount.isNotEmpty) {
       base += '?tx_amount=${amount.replaceAll(',', '.')}';
@@ -75,12 +72,11 @@ class HavenURI extends PaymentURI {
 }
 
 class BitcoinURI extends PaymentURI {
-  BitcoinURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  BitcoinURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'bitcoin:' + address;
+    var base = 'bitcoin:$address';
 
     if (amount.isNotEmpty) {
       base += '?amount=${amount.replaceAll(',', '.')}';
@@ -91,12 +87,11 @@ class BitcoinURI extends PaymentURI {
 }
 
 class LitecoinURI extends PaymentURI {
-  LitecoinURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  LitecoinURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'litecoin:' + address;
+    var base = 'litecoin:$address';
 
     if (amount.isNotEmpty) {
       base += '?amount=${amount.replaceAll(',', '.')}';
@@ -107,12 +102,11 @@ class LitecoinURI extends PaymentURI {
 }
 
 class EthereumURI extends PaymentURI {
-  EthereumURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  EthereumURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'ethereum:' + address;
+    var base = 'ethereum:$address';
 
     if (amount.isNotEmpty) {
       base += '?amount=${amount.replaceAll(',', '.')}';
@@ -123,8 +117,7 @@ class EthereumURI extends PaymentURI {
 }
 
 class BitcoinCashURI extends PaymentURI {
-  BitcoinCashURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  BitcoinCashURI({required super.amount, required super.address});
 
   @override
   String toString() {
@@ -139,12 +132,11 @@ class BitcoinCashURI extends PaymentURI {
 }
 
 class NanoURI extends PaymentURI {
-  NanoURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  NanoURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'nano:' + address;
+    var base = 'nano:$address';
     if (amount.isNotEmpty) {
       base += '?amount=${amount.replaceAll(',', '.')}';
     }
@@ -154,12 +146,11 @@ class NanoURI extends PaymentURI {
 }
 
 class PolygonURI extends PaymentURI {
-  PolygonURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  PolygonURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'polygon:' + address;
+    var base = 'polygon:$address';
 
     if (amount.isNotEmpty) {
       base += '?amount=${amount.replaceAll(',', '.')}';
@@ -170,12 +161,12 @@ class PolygonURI extends PaymentURI {
 }
 
 class SolanaURI extends PaymentURI {
-  SolanaURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  SolanaURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'solana:' + address;
+    var base = 'solana:$address';
+
     if (amount.isNotEmpty) {
       base += '?amount=${amount.replaceAll(',', '.')}';
     }
@@ -185,12 +176,12 @@ class SolanaURI extends PaymentURI {
 }
 
 class TronURI extends PaymentURI {
-  TronURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  TronURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'tron:' + address;
+    var base = 'tron:$address';
+
     if (amount.isNotEmpty) {
       base += '?amount=${amount.replaceAll(',', '.')}';
     }
@@ -200,12 +191,11 @@ class TronURI extends PaymentURI {
 }
 
 class WowneroURI extends PaymentURI {
-  WowneroURI({required String amount, required String address})
-      : super(amount: amount, address: address);
+  WowneroURI({required super.amount, required super.address});
 
   @override
   String toString() {
-    var base = 'wownero:' + address;
+    var base = 'wownero:$address';
 
     if (amount.isNotEmpty) {
       base += '?tx_amount=${amount.replaceAll(',', '.')}';
@@ -215,7 +205,8 @@ class WowneroURI extends PaymentURI {
   }
 }
 
-abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store {
+abstract class WalletAddressListViewModelBase
+    extends WalletChangeListenerViewModel with Store {
   WalletAddressListViewModelBase({
     required AppStore appStore,
     required this.yatStore,
@@ -223,9 +214,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
   })  : _baseItems = <ListItem>[],
         selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
         _cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
-        hasAccounts = appStore.wallet!.type == WalletType.monero ||
-            appStore.wallet!.type == WalletType.wownero ||
-            appStore.wallet!.type == WalletType.haven,
+        hasAccounts = [WalletType.monero, WalletType.wownero, WalletType.haven]
+            .contains(appStore.wallet!.type),
         amount = '',
         _settingsStore = appStore.settingsStore,
         super(appStore: appStore) {
@@ -237,9 +227,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
     _init();
 
     selectedCurrency = walletTypeToCryptoCurrency(wallet.type);
-    hasAccounts = wallet.type == WalletType.monero ||
-        wallet.type == WalletType.wownero ||
-        wallet.type == WalletType.haven;
+    hasAccounts = [WalletType.monero, WalletType.wownero, WalletType.haven]
+        .contains(wallet.type);
   }
 
   static const String _cryptoNumberPattern = '0.00000000';
@@ -249,7 +238,11 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
   final FiatConversionStore fiatConversionStore;
   final SettingsStore _settingsStore;
 
-  List<Currency> get currencies => [walletTypeToCryptoCurrency(wallet.type), ...FiatCurrency.all];
+  double? _fiatRate;
+  String _rawAmount = '';
+
+  List<Currency> get currencies =>
+      [walletTypeToCryptoCurrency(wallet.type), ...FiatCurrency.all];
 
   String get buttonTitle {
     if (isElectrumWallet) {
@@ -275,9 +268,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
   WalletType get type => wallet.type;
 
   @computed
-  WalletAddressListItem get address {
-    return WalletAddressListItem(address: wallet.walletAddresses.address, isPrimary: false);
-  }
+  WalletAddressListItem get address => WalletAddressListItem(
+        address: wallet.walletAddresses.address, isPrimary: false);
 
   @computed
   PaymentURI get uri {
@@ -321,8 +313,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
     final addressList = ObservableList<ListItem>();
 
     if (wallet.type == WalletType.monero) {
-      final primaryAddress = monero!.getSubaddressList(wallet).subaddresses.first;
-      final addressItems = monero!.getSubaddressList(wallet).subaddresses.map((subaddress) {
+      final primaryAddress =
+          monero!.getSubaddressList(wallet).subaddresses.first;
+      final addressItems =
+          monero!.getSubaddressList(wallet).subaddresses.map((subaddress) {
         final isPrimary = subaddress == primaryAddress;
 
         return WalletAddressListItem(
@@ -338,8 +332,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
     }
 
     if (wallet.type == WalletType.wownero) {
-      final primaryAddress = wownero!.getSubaddressList(wallet).subaddresses.first;
-      final addressItems = wownero!.getSubaddressList(wallet).subaddresses.map((subaddress) {
+      final primaryAddress =
+          wownero!.getSubaddressList(wallet).subaddresses.first;
+      final addressItems =
+          wownero!.getSubaddressList(wallet).subaddresses.map((subaddress) {
         final isPrimary = subaddress == primaryAddress;
 
         return WalletAddressListItem(
@@ -352,8 +348,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
     }
 
     if (wallet.type == WalletType.haven) {
-      final primaryAddress = haven!.getSubaddressList(wallet).subaddresses.first;
-      final addressItems = haven!.getSubaddressList(wallet).subaddresses.map((subaddress) {
+      final primaryAddress =
+          haven!.getSubaddressList(wallet).subaddresses.first;
+      final addressItems =
+          haven!.getSubaddressList(wallet).subaddresses.map((subaddress) {
         final isPrimary = subaddress == primaryAddress;
 
         return WalletAddressListItem(
@@ -367,7 +365,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
 
     if (isElectrumWallet) {
       if (bitcoin!.hasSelectedSilentPayments(wallet)) {
-        final addressItems = bitcoin!.getSilentPaymentAddresses(wallet).map((address) {
+        final addressItems =
+            bitcoin!.getSilentPaymentAddresses(wallet).map((address) {
           final isPrimary = address.id == 0;
 
           return WalletAddressListItem(
@@ -418,7 +417,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
         if (wallet.type == WalletType.litecoin && addressItems.length >= 1000) {
           // find the index of the last item with a txCount > 0
           final addressItemsList = addressItems.toList();
-          int index = addressItemsList.lastIndexWhere((item) => (item.txCount ?? 0) > 0);
+          int index = addressItemsList
+              .lastIndexWhere((item) => (item.txCount ?? 0) > 0);
           if (index == -1) {
             index = 0;
           }
@@ -432,19 +432,22 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
     if (wallet.type == WalletType.ethereum) {
       final primaryAddress = ethereum!.getAddress(wallet);
 
-      addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress));
+      addressList.add(WalletAddressListItem(
+          isPrimary: true, name: null, address: primaryAddress));
     }
 
     if (wallet.type == WalletType.polygon) {
       final primaryAddress = polygon!.getAddress(wallet);
 
-      addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress));
+      addressList.add(WalletAddressListItem(
+          isPrimary: true, name: null, address: primaryAddress));
     }
 
     if (wallet.type == WalletType.solana) {
       final primaryAddress = solana!.getAddress(wallet);
 
-      addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress));
+      addressList.add(WalletAddressListItem(
+          isPrimary: true, name: null, address: primaryAddress));
     }
 
     if (wallet.type == WalletType.nano) {
@@ -458,18 +461,21 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
     if (wallet.type == WalletType.tron) {
       final primaryAddress = tron!.getAddress(wallet);
 
-      addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress));
+      addressList.add(WalletAddressListItem(
+          isPrimary: true, name: null, address: primaryAddress));
     }
 
     for (var i = 0; i < addressList.length; i++) {
       if (!(addressList[i] is WalletAddressListItem)) continue;
-      (addressList[i] as WalletAddressListItem).isHidden = wallet.walletAddresses.hiddenAddresses
+      (addressList[i] as WalletAddressListItem).isHidden = wallet
+          .walletAddresses.hiddenAddresses
           .contains((addressList[i] as WalletAddressListItem).address);
     }
 
     for (var i = 0; i < addressList.length; i++) {
       if (!(addressList[i] is WalletAddressListItem)) continue;
-      (addressList[i] as WalletAddressListItem).isManual = wallet.walletAddresses.manualAddresses
+      (addressList[i] as WalletAddressListItem).isManual = wallet
+          .walletAddresses.manualAddresses
           .contains((addressList[i] as WalletAddressListItem).address);
     }
 
@@ -487,7 +493,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
 
   Future<void> toggleHideAddress(WalletAddressListItem item) async {
     if (item.isHidden) {
-      wallet.walletAddresses.hiddenAddresses.removeWhere((element) => element == item.address);
+      wallet.walletAddresses.hiddenAddresses
+          .removeWhere((element) => element == item.address);
     } else {
       wallet.walletAddresses.hiddenAddresses.add(item.address);
     }
@@ -512,57 +519,58 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
 
   @computed
   String get accountLabel {
-    if (wallet.type == WalletType.monero) {
-      return monero!.getCurrentAccount(wallet).label;
+    switch (wallet.type) {
+      case WalletType.monero:
+        return monero!.getCurrentAccount(wallet).label;
+      case WalletType.wownero:
+        wownero!.getCurrentAccount(wallet).label;
+      case WalletType.haven:
+        return haven!.getCurrentAccount(wallet).label;
+      default:
+        return '';
     }
-
-    if (wallet.type == WalletType.wownero) {
-      return wownero!.getCurrentAccount(wallet).label;
-    }
-
-    if (wallet.type == WalletType.haven) {
-      return haven!.getCurrentAccount(wallet).label;
-    }
-
     return '';
   }
 
   @computed
-  bool get hasAddressList =>
-      wallet.type == WalletType.monero ||
-      wallet.type == WalletType.wownero ||
-      wallet.type == WalletType.haven ||
-      wallet.type == WalletType.bitcoinCash ||
-      wallet.type == WalletType.bitcoin ||
-      wallet.type == WalletType.litecoin;
+  bool get hasAddressList => [
+        WalletType.monero,
+        WalletType.wownero,
+        WalletType.haven,
+        WalletType.bitcoinCash,
+        WalletType.bitcoin,
+        WalletType.litecoin
+      ].contains(wallet.type);
 
   @computed
-  bool get isElectrumWallet =>
-      wallet.type == WalletType.bitcoin ||
-      wallet.type == WalletType.litecoin ||
-      wallet.type == WalletType.bitcoinCash;
+  bool get isElectrumWallet => [
+        WalletType.bitcoin,
+        WalletType.litecoin,
+        WalletType.bitcoinCash
+      ].contains(wallet.type);
 
   @computed
   bool get isBalanceAvailable => isElectrumWallet;
 
   @computed
   bool get isReceivedAvailable =>
-      wallet.type == WalletType.monero || wallet.type == WalletType.wownero;
+      [WalletType.monero, WalletType.wownero].contains(wallet.type);
 
   @computed
   bool get isSilentPayments =>
-      wallet.type == WalletType.bitcoin && bitcoin!.hasSelectedSilentPayments(wallet);
+      wallet.type == WalletType.bitcoin &&
+      bitcoin!.hasSelectedSilentPayments(wallet);
 
   @computed
   bool get isAutoGenerateSubaddressEnabled =>
-      _settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled &&
+      _settingsStore.autoGenerateSubaddressStatus !=
+          AutoGenerateSubaddressStatus.disabled &&
       !isSilentPayments;
 
   @computed
   bool get showAddManualAddresses =>
       !isAutoGenerateSubaddressEnabled ||
-      wallet.type == WalletType.monero ||
-      wallet.type == WalletType.wownero;
+      [WalletType.monero, WalletType.wownero].contains(wallet.type);
 
   List<ListItem> _baseItems;
 
@@ -574,7 +582,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
 
   @action
   Future<void> setAddressType(dynamic option) async {
-    if (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) {
+    if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type)) {
       await bitcoin!.setAddressType(wallet, option);
     }
   }
@@ -586,13 +594,15 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
       _baseItems.add(WalletAddressHiddenListHeader());
     }
 
-    if (wallet.type == WalletType.monero ||
-        wallet.type == WalletType.wownero ||
-        wallet.type == WalletType.haven) {
+    if ([
+      WalletType.monero,
+      WalletType.wownero,
+      WalletType.haven,
+    ].contains(wallet.type)) {
       _baseItems.add(WalletAccountListHeader());
     }
 
-    if (wallet.type != WalletType.nano && wallet.type != WalletType.banano) {
+    if (![WalletType.nano, WalletType.banano].contains(wallet.type)) {
       _baseItems.add(WalletAddressListHeader());
     }
     if (wallet.isEnabledAutoGenerateSubaddress) {
@@ -603,11 +613,27 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
   @action
   void selectCurrency(Currency currency) {
     selectedCurrency = currency;
+
+    if (currency is FiatCurrency && _settingsStore.fiatCurrency != currency) {
+      final cryptoCurrency = walletTypeToCryptoCurrency(wallet.type);
+
+      dev.log("Requesting Fiat rate for $cryptoCurrency-$currency");
+      FiatConversionService.fetchPrice(
+        crypto: cryptoCurrency,
+        fiat: currency,
+        torOnly: _settingsStore.fiatApiMode == FiatApiMode.torOnly,
+      ).then((value) {
+        dev.log("Received Fiat rate 1 $cryptoCurrency = $value $currency");
+        _fiatRate = value;
+        _convertAmountToCrypto();
+      });
+    }
   }
 
   @action
   void changeAmount(String amount) {
     this.amount = amount;
+    this._rawAmount = amount;
     if (selectedCurrency is FiatCurrency) {
       _convertAmountToCrypto();
     }
@@ -618,11 +644,20 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
     searchText = text;
   }
 
+  @action
   void _convertAmountToCrypto() {
     final cryptoCurrency = walletTypeToCryptoCurrency(wallet.type);
+    final fiatRate =
+        _fiatRate ?? (fiatConversionStore.prices[cryptoCurrency] ?? 0.0);
+
+    if (fiatRate <= 0.0) {
+      dev.log("Invalid Fiat Rate $fiatRate");
+      amount = '';
+      return;
+    }
+
     try {
-      final crypto =
-          double.parse(amount.replaceAll(',', '.')) / fiatConversionStore.prices[cryptoCurrency]!;
+      final crypto = double.parse(_rawAmount.replaceAll(',', '.')) / fiatRate;
       final cryptoAmountTmp = _cryptoNumberFormat.format(crypto);
       if (amount != cryptoAmountTmp) {
         amount = cryptoAmountTmp;

From 5c2735be42db03bf7f4311389804fc7025dea7c1 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Fri, 18 Oct 2024 05:58:57 +0300
Subject: [PATCH 07/50] transaction description key id address (#1755)

* transaction description key id+address

* minor fix[skip ci]

* fix backward compatibility

* add monero primary address
---
 cw_core/lib/wallet_addresses.dart                  |  2 +-
 cw_evm/lib/evm_chain_wallet_addresses.dart         |  3 +++
 cw_monero/lib/monero_wallet_addresses.dart         |  3 +++
 cw_nano/lib/nano_wallet_addresses.dart             |  3 +++
 cw_solana/lib/solana_wallet_addresses.dart         |  3 +++
 cw_tron/lib/tron_wallet_addresses.dart             |  3 +++
 cw_wownero/lib/wownero_wallet_addresses.dart       |  3 +++
 lib/view_model/send/send_view_model.dart           | 12 +++++++++---
 lib/view_model/transaction_details_view_model.dart |  6 ++++--
 9 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart
index ca488cfed..4324823c5 100644
--- a/cw_core/lib/wallet_addresses.dart
+++ b/cw_core/lib/wallet_addresses.dart
@@ -23,7 +23,7 @@ abstract class WalletAddresses {
     return _localAddress ?? address;
   }
 
-  String? get primaryAddress => null;
+  String get primaryAddress;
 
   String? _localAddress;
 
diff --git a/cw_evm/lib/evm_chain_wallet_addresses.dart b/cw_evm/lib/evm_chain_wallet_addresses.dart
index 4615d79ed..7dd501cc5 100644
--- a/cw_evm/lib/evm_chain_wallet_addresses.dart
+++ b/cw_evm/lib/evm_chain_wallet_addresses.dart
@@ -17,6 +17,9 @@ abstract class EVMChainWalletAddressesBase extends WalletAddresses with Store {
   @observable
   String address;
 
+  @override
+  String get primaryAddress => address;
+
   @override
   Future<void> init() async {
     address = walletInfo.address;
diff --git a/cw_monero/lib/monero_wallet_addresses.dart b/cw_monero/lib/monero_wallet_addresses.dart
index c8a4448a4..ae78132d3 100644
--- a/cw_monero/lib/monero_wallet_addresses.dart
+++ b/cw_monero/lib/monero_wallet_addresses.dart
@@ -29,6 +29,9 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store {
   @observable
   String address;
 
+  @override
+  String get primaryAddress => getAddress(accountIndex: account?.id ?? 0, addressIndex: 0);
+
   @override
   String get latestAddress {
     var addressIndex = subaddress_list.numSubaddresses(account?.id??0) - 1;
diff --git a/cw_nano/lib/nano_wallet_addresses.dart b/cw_nano/lib/nano_wallet_addresses.dart
index cc532d2c7..e8eae7737 100644
--- a/cw_nano/lib/nano_wallet_addresses.dart
+++ b/cw_nano/lib/nano_wallet_addresses.dart
@@ -18,6 +18,9 @@ abstract class NanoWalletAddressesBase extends WalletAddresses with Store {
   @observable
   String address;
 
+  @override
+  String get primaryAddress => address;
+
   @observable
   NanoAccount? account;
 
diff --git a/cw_solana/lib/solana_wallet_addresses.dart b/cw_solana/lib/solana_wallet_addresses.dart
index 97a76fb99..19eb91fa1 100644
--- a/cw_solana/lib/solana_wallet_addresses.dart
+++ b/cw_solana/lib/solana_wallet_addresses.dart
@@ -14,6 +14,9 @@ abstract class SolanaWalletAddressesBase extends WalletAddresses with Store {
   @override
   String address;
 
+  @override
+  String get primaryAddress => address;
+
   @override
   Future<void> init() async {
     address = walletInfo.address;
diff --git a/cw_tron/lib/tron_wallet_addresses.dart b/cw_tron/lib/tron_wallet_addresses.dart
index 35939de26..095f97fa9 100644
--- a/cw_tron/lib/tron_wallet_addresses.dart
+++ b/cw_tron/lib/tron_wallet_addresses.dart
@@ -17,6 +17,9 @@ abstract class TronWalletAddressesBase extends WalletAddresses with Store {
   @observable
   String address;
 
+  @override
+  String get primaryAddress => address;
+
   @override
   Future<void> init() async {
     address = walletInfo.address;
diff --git a/cw_wownero/lib/wownero_wallet_addresses.dart b/cw_wownero/lib/wownero_wallet_addresses.dart
index b2f9ec67a..eed81eb45 100644
--- a/cw_wownero/lib/wownero_wallet_addresses.dart
+++ b/cw_wownero/lib/wownero_wallet_addresses.dart
@@ -29,6 +29,9 @@ abstract class WowneroWalletAddressesBase extends WalletAddresses with Store {
   @observable
   String address;
 
+  @override
+  String get primaryAddress => getAddress(accountIndex: account?.id ?? 0, addressIndex: 0);
+
   @override
   String get latestAddress {
     var addressIndex = subaddress_list.numSubaddresses(account?.id??0) - 1;
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 334394a18..4064a1258 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -482,12 +482,18 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
         nano!.updateTransactions(wallet);
       }
 
+
       if (pendingTransaction!.id.isNotEmpty) {
+
+        final descriptionKey = '${pendingTransaction!.id}_${wallet.walletAddresses.primaryAddress}';
         _settingsStore.shouldSaveRecipientAddress
             ? await transactionDescriptionBox.add(TransactionDescription(
-                id: pendingTransaction!.id, recipientAddress: address, transactionNote: note))
-            : await transactionDescriptionBox
-                .add(TransactionDescription(id: pendingTransaction!.id, transactionNote: note));
+            id: descriptionKey,
+            recipientAddress: address,
+            transactionNote: note))
+            : await transactionDescriptionBox.add(TransactionDescription(
+            id: descriptionKey,
+            transactionNote: note));
       }
 
       state = TransactionCommitted();
diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart
index a96d70a90..1833a0f51 100644
--- a/lib/view_model/transaction_details_view_model.dart
+++ b/lib/view_model/transaction_details_view_model.dart
@@ -110,9 +110,11 @@ abstract class TransactionDetailsViewModelBase with Store {
           } catch (e) {}
         }));
 
+    final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
+
     final description = transactionDescriptionBox.values.firstWhere(
-        (val) => val.id == transactionInfo.txHash,
-        orElse: () => TransactionDescription(id: transactionInfo.txHash));
+            (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
+        orElse: () => TransactionDescription(id: descriptionKey));
 
     items.add(TextFieldListItem(
         title: S.current.note_tap_to_change,

From 7faca38cfa52bcb3914c8b20cda291e4eefe594a Mon Sep 17 00:00:00 2001
From: Rafael <github@rafael.saes.dev>
Date: Fri, 18 Oct 2024 20:24:15 -0300
Subject: [PATCH 08/50] fix: sp input calc (#1756)

---
 cw_bitcoin/lib/electrum_wallet.dart | 45 ++++++++++++++++++++++++-----
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index ceaa2f088..527bef3ea 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -784,6 +784,7 @@ abstract class ElectrumWalletBase
   Future<EstimatedTxResult> estimateTxForAmount(
     int credentialsAmount,
     List<BitcoinOutput> outputs,
+    List<BitcoinOutput> updatedOutputs,
     int feeRate, {
     int? inputsCount,
     String? memo,
@@ -812,6 +813,7 @@ abstract class ElectrumWalletBase
         return estimateTxForAmount(
           credentialsAmount,
           outputs,
+          updatedOutputs,
           feeRate,
           inputsCount: utxoDetails.utxos.length + 1,
           memo: memo,
@@ -824,19 +826,30 @@ abstract class ElectrumWalletBase
     }
 
     final changeAddress = await walletAddresses.getChangeAddress(
-      outputs: outputs,
+      outputs: updatedOutputs,
       utxoDetails: utxoDetails,
     );
     final address = RegexUtils.addressTypeFromStr(changeAddress, network);
+    updatedOutputs.add(BitcoinOutput(
+      address: address,
+      value: BigInt.from(amountLeftForChangeAndFee),
+      isChange: true,
+    ));
     outputs.add(BitcoinOutput(
       address: address,
       value: BigInt.from(amountLeftForChangeAndFee),
       isChange: true,
     ));
 
+    // calcFee updates the silent payment outputs to calculate the tx size accounting
+    // for taproot addresses, but if more inputs are needed to make up for fees,
+    // the silent payment outputs need to be recalculated for the new inputs
+    var temp = outputs.map((output) => output).toList();
     int fee = await calcFee(
       utxos: utxoDetails.utxos,
-      outputs: outputs,
+      // Always take only not updated bitcoin outputs here so for every estimation
+      // the SP outputs are re-generated to the proper taproot addresses
+      outputs: temp,
       network: network,
       memo: memo,
       feeRate: feeRate,
@@ -844,18 +857,25 @@ abstract class ElectrumWalletBase
       vinOutpoints: utxoDetails.vinOutpoints,
     );
 
+    updatedOutputs.clear();
+    updatedOutputs.addAll(temp);
+
     if (fee == 0) {
       throw BitcoinTransactionNoFeeException();
     }
 
     int amount = credentialsAmount;
-    final lastOutput = outputs.last;
+    final lastOutput = updatedOutputs.last;
     final amountLeftForChange = amountLeftForChangeAndFee - fee;
 
-    print(amountLeftForChangeAndFee);
-
     if (!_isBelowDust(amountLeftForChange)) {
       // Here, lastOutput already is change, return the amount left without the fee to the user's address.
+      updatedOutputs[updatedOutputs.length - 1] = BitcoinOutput(
+        address: lastOutput.address,
+        value: BigInt.from(amountLeftForChange),
+        isSilentPayment: lastOutput.isSilentPayment,
+        isChange: true,
+      );
       outputs[outputs.length - 1] = BitcoinOutput(
         address: lastOutput.address,
         value: BigInt.from(amountLeftForChange),
@@ -864,6 +884,7 @@ abstract class ElectrumWalletBase
       );
     } else {
       // If has change that is lower than dust, will end up with tx rejected by network rules, so estimate again without the added change
+      updatedOutputs.removeLast();
       outputs.removeLast();
 
       // Still has inputs to spend before failing
@@ -871,16 +892,18 @@ abstract class ElectrumWalletBase
         return estimateTxForAmount(
           credentialsAmount,
           outputs,
+          updatedOutputs,
           feeRate,
           inputsCount: utxoDetails.utxos.length + 1,
           memo: memo,
+          hasSilentPayment: hasSilentPayment,
           useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins,
           coinTypeToSpendFrom: coinTypeToSpendFrom,
         );
       }
 
       final estimatedSendAll = await estimateSendAllTx(
-        outputs,
+        updatedOutputs,
         feeRate,
         memo: memo,
         coinTypeToSpendFrom: coinTypeToSpendFrom,
@@ -913,10 +936,12 @@ abstract class ElectrumWalletBase
       if (spendingAllCoins) {
         throw BitcoinTransactionWrongBalanceException();
       } else {
+        updatedOutputs.removeLast();
         outputs.removeLast();
         return estimateTxForAmount(
           credentialsAmount,
           outputs,
+          updatedOutputs,
           feeRate,
           inputsCount: utxoDetails.utxos.length + 1,
           memo: memo,
@@ -1029,6 +1054,9 @@ abstract class ElectrumWalletBase
           : feeRate(transactionCredentials.priority!);
 
       EstimatedTxResult estimatedTx;
+      final updatedOutputs =
+          outputs.map((e) => BitcoinOutput(address: e.address, value: e.value)).toList();
+
       if (sendAll) {
         estimatedTx = await estimateSendAllTx(
           outputs,
@@ -1042,6 +1070,7 @@ abstract class ElectrumWalletBase
         estimatedTx = await estimateTxForAmount(
           credentialsAmount,
           outputs,
+          updatedOutputs,
           feeRateInt,
           memo: memo,
           hasSilentPayment: hasSilentPayment,
@@ -1052,7 +1081,7 @@ abstract class ElectrumWalletBase
       if (walletInfo.isHardwareWallet) {
         final transaction = await buildHardwareWalletTransaction(
           utxos: estimatedTx.utxos,
-          outputs: outputs,
+          outputs: updatedOutputs,
           publicKeys: estimatedTx.publicKeys,
           fee: BigInt.from(estimatedTx.fee),
           network: network,
@@ -1092,7 +1121,7 @@ abstract class ElectrumWalletBase
       } else {
         txb = BitcoinTransactionBuilder(
           utxos: estimatedTx.utxos,
-          outputs: outputs,
+          outputs: updatedOutputs,
           fee: BigInt.from(estimatedTx.fee),
           network: network,
           memo: estimatedTx.memo,

From 50825a62c194cdd97bf5414487d6d40b246c96a9 Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Fri, 18 Oct 2024 17:05:48 -0700
Subject: [PATCH 09/50] Mweb enhancements 3 (#1744)

* version 4.20.0

* update build numbers

* UI updates and script fix for ios bundle identifier

* disable mweb for desktop

* change hardcoded ltc server ip address
electrum connection enhancement

* MWEB enhancements 2.0 (#1735)

* additional logging and minor fixes

* additional logging and minor fixes

* addresses pt.1

* Allow Wallet Group Names to be the same as Wallet Names (#1730)

* fix: Issues with imaging

* fix: Allow group names to be the same as wallet names

* fix: Bug with wallet grouping when a wallet is minimized

* fix: Bug with wallet grouping when a wallet is minimized

* logs of fixes and experimental changes, close wallet before opening next

* save

* fix icon

* fixes

* [skip ci] updates

* [skip ci] updates

* updates

* minor optimizations

* fix for when switching between wallets

* [skip ci] updates

* [skip ci] updates

* Update cw_bitcoin/lib/litecoin_wallet.dart

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* Update cw_bitcoin/lib/litecoin_wallet.dart

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* mobx

* mostly logging

* stream fix pt.1 [skip ci]

* updates

* some fixes and enhancements

* [skip ci] minor

* potential partial fix for streamsink closed

* fix stream sink closed errors

* fix mweb logo colors

* save

* minor enhancements [skip ci]

* save

* experimental

* minor

* minor [skip ci]

---------

Co-authored-by: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* fix menu list removing from original list

* detach sync status from mwebsyncstatus

* minor

* keep sync status in sync where necessary

* minor

* wip

* appears to work?

* updates

* prevent mwebd from submitting non mweb transactions

* fix unspent coins info not persisting for mweb coins + other minor fixes

* [skip ci] minor

* Polish MWEB card UI

* make sure current chain tip is updated correctly [skip ci]

* [skip ci] review fixes

* [skip ci] detect mweb outputs more thoroughly (fix peg-in commit error)

* fix change address on send ui

* fix qr code scan issue

* get segwit address for pegout even if mweb is selected on the receive screen [skip ci]

* - Fix adding nodes twice
- Fix mempool API parsing error

* (potentially) fix duplicate tx history bug

* [skip ci] fix bc1 address

* don't show contacts prompt on pegin/out + potential unconfirmed balance fixes

* [skip ci] minor cleanup

* fix mweb input detection

* fix showing mweb address for non-mweb transactions

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
Co-authored-by: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Co-authored-by: tuxpizza <tuxsudo@tux.pizza>
---
 cw_bitcoin/lib/electrum.dart                  |  22 ++-
 cw_bitcoin/lib/electrum_wallet.dart           |  69 +++++---
 cw_bitcoin/lib/electrum_wallet_addresses.dart |   6 +-
 cw_bitcoin/lib/litecoin_wallet.dart           | 150 ++++++++++++------
 cw_bitcoin/lib/litecoin_wallet_addresses.dart |  16 +-
 .../lib/pending_bitcoin_transaction.dart      |   6 +
 cw_mweb/lib/cw_mweb.dart                      |   7 +-
 lib/bitcoin/cw_bitcoin.dart                   |  22 ++-
 lib/entities/default_settings_migration.dart  |   8 +-
 .../screens/dashboard/pages/balance_page.dart |  48 +++---
 lib/src/screens/send/send_page.dart           |   5 +
 lib/view_model/wallet_creation_vm.dart        |  46 +++---
 tool/configure.dart                           |   1 +
 13 files changed, 266 insertions(+), 140 deletions(-)

diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart
index 54ccaaef5..a8cb7ee9f 100644
--- a/cw_bitcoin/lib/electrum.dart
+++ b/cw_bitcoin/lib/electrum.dart
@@ -68,8 +68,8 @@ class ElectrumClient {
 
     try {
       await socket?.close();
-      socket = null;
     } catch (_) {}
+    socket = null;
 
     try {
       if (useSSL == false || (useSSL == null && uri.toString().contains("btc-electrum"))) {
@@ -102,7 +102,8 @@ class ElectrumClient {
       return;
     }
 
-    _setConnectionStatus(ConnectionStatus.connected);
+    // use ping to determine actual connection status since we could've just not timed out yet:
+    // _setConnectionStatus(ConnectionStatus.connected);
 
     socket!.listen(
       (Uint8List event) {
@@ -128,7 +129,7 @@ class ElectrumClient {
         print("SOCKET CLOSED!!!!!");
         unterminatedString = '';
         try {
-          if (host == socket?.address.host) {
+          if (host == socket?.address.host || socket == null) {
             _setConnectionStatus(ConnectionStatus.disconnected);
             socket?.destroy();
           }
@@ -178,7 +179,7 @@ class ElectrumClient {
         unterminatedString = '';
       }
     } catch (e) {
-      print(e.toString());
+      print("parse $e");
     }
   }
 
@@ -191,7 +192,7 @@ class ElectrumClient {
     try {
       await callWithTimeout(method: 'server.ping');
       _setConnectionStatus(ConnectionStatus.connected);
-    } on RequestFailedTimeoutException catch (_) {
+    } catch (_) {
       _setConnectionStatus(ConnectionStatus.disconnected);
     }
   }
@@ -431,7 +432,7 @@ class ElectrumClient {
 
       return subscription;
     } catch (e) {
-      print(e.toString());
+      print("subscribe $e");
       return null;
     }
   }
@@ -470,7 +471,8 @@ class ElectrumClient {
 
       return completer.future;
     } catch (e) {
-      print(e.toString());
+      print("callWithTimeout $e");
+      rethrow;
     }
   }
 
@@ -537,6 +539,12 @@ class ElectrumClient {
     onConnectionStatusChange?.call(status);
     _connectionStatus = status;
     _isConnected = status == ConnectionStatus.connected;
+    if (!_isConnected) {
+      try {
+        socket?.destroy();
+      } catch (_) {}
+      socket = null;
+    }
   }
 
   void _handleResponse(Map<String, dynamic> response) {
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 527bef3ea..893cff6f2 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -4,6 +4,7 @@ import 'dart:io';
 import 'dart:isolate';
 
 import 'package:bitcoin_base/bitcoin_base.dart';
+import 'package:cw_bitcoin/bitcoin_wallet.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:cw_core/encryption_file_utils.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
@@ -249,7 +250,7 @@ abstract class ElectrumWalletBase
   int? _currentChainTip;
 
   Future<int> getCurrentChainTip() async {
-    if (_currentChainTip != null) {
+    if ((_currentChainTip ?? 0) > 0) {
       return _currentChainTip!;
     }
     _currentChainTip = await electrumClient.getCurrentBlockChainTip() ?? 0;
@@ -301,6 +302,7 @@ abstract class ElectrumWalletBase
 
   @action
   Future<void> _setListeners(int height, {int? chainTipParam, bool? doSingleScan}) async {
+    if (this is! BitcoinWallet) return;
     final chainTip = chainTipParam ?? await getUpdatedChainTip();
 
     if (chainTip == height) {
@@ -467,7 +469,7 @@ abstract class ElectrumWalletBase
       }
     } catch (e, stacktrace) {
       print(stacktrace);
-      print(e.toString());
+      print("startSync $e");
       syncStatus = FailedSyncStatus();
     }
   }
@@ -479,10 +481,10 @@ abstract class ElectrumWalletBase
         final response =
             await http.get(Uri.parse("http://mempool.cakewallet.com:8999/api/v1/fees/recommended"));
 
-        final result = json.decode(response.body) as Map<String, num>;
-        final slowFee = result['economyFee']?.toInt() ?? 0;
-        int mediumFee = result['hourFee']?.toInt() ?? 0;
-        int fastFee = result['fastestFee']?.toInt() ?? 0;
+        final result = json.decode(response.body) as Map<String, dynamic>;
+        final slowFee = (result['economyFee'] as num?)?.toInt() ?? 0;
+        int mediumFee = (result['hourFee'] as num?)?.toInt() ?? 0;
+        int fastFee = (result['fastestFee'] as num?)?.toInt() ?? 0;
         if (slowFee == mediumFee) {
           mediumFee++;
         }
@@ -491,7 +493,9 @@ abstract class ElectrumWalletBase
         }
         _feeRates = [slowFee, mediumFee, fastFee];
         return;
-      } catch (_) {}
+      } catch (e) {
+        print(e);
+      }
     }
 
     final feeRates = await electrumClient.feeRates(network: network);
@@ -571,7 +575,7 @@ abstract class ElectrumWalletBase
       await electrumClient.connectToUri(node.uri, useSSL: node.useSSL);
     } catch (e, stacktrace) {
       print(stacktrace);
-      print(e.toString());
+      print("connectToNode $e");
       syncStatus = FailedSyncStatus();
     }
   }
@@ -826,8 +830,8 @@ abstract class ElectrumWalletBase
     }
 
     final changeAddress = await walletAddresses.getChangeAddress(
+      inputs: utxoDetails.availableInputs,
       outputs: updatedOutputs,
-      utxoDetails: utxoDetails,
     );
     final address = RegexUtils.addressTypeFromStr(changeAddress, network);
     updatedOutputs.add(BitcoinOutput(
@@ -1181,6 +1185,7 @@ abstract class ElectrumWalletBase
         hasChange: estimatedTx.hasChange,
         isSendAll: estimatedTx.isSendAll,
         hasTaprootInputs: hasTaprootInputs,
+        utxos: estimatedTx.utxos,
       )..addListener((transaction) async {
           transactionHistory.addOne(transaction);
           if (estimatedTx.spendsSilentPayment) {
@@ -1370,7 +1375,7 @@ abstract class ElectrumWalletBase
       });
     }
 
-    // Set the balance of all non-silent payment addresses to 0 before updating
+    // Set the balance of all non-silent payment and non-mweb addresses to 0 before updating
     walletAddresses.allAddresses
         .where((element) => element.type != SegwitAddresType.mweb)
         .forEach((addr) {
@@ -1487,7 +1492,7 @@ abstract class ElectrumWalletBase
         await unspentCoinsInfo.deleteAll(keys);
       }
     } catch (e) {
-      print(e.toString());
+      print("refreshUnspentCoinsInfo $e");
     }
   }
 
@@ -1831,7 +1836,7 @@ abstract class ElectrumWalletBase
 
       return historiesWithDetails;
     } catch (e) {
-      print(e.toString());
+      print("fetchTransactions $e");
       return {};
     }
   }
@@ -1905,7 +1910,9 @@ abstract class ElectrumWalletBase
             if (height > 0) {
               storedTx.height = height;
               // the tx's block itself is the first confirmation so add 1
-              if (currentHeight != null) storedTx.confirmations = currentHeight - height + 1;
+              if ((currentHeight ?? 0) > 0) {
+                storedTx.confirmations = currentHeight! - height + 1;
+              }
               storedTx.isPending = storedTx.confirmations == 0;
             }
 
@@ -1946,9 +1953,13 @@ abstract class ElectrumWalletBase
       }
       await getCurrentChainTip();
 
-      transactionHistory.transactions.values.forEach((tx) async {
-        if (tx.unspents != null && tx.unspents!.isNotEmpty && tx.height != null && tx.height! > 0) {
-          tx.confirmations = await getCurrentChainTip() - tx.height! + 1;
+      transactionHistory.transactions.values.forEach((tx) {
+        if (tx.unspents != null &&
+            tx.unspents!.isNotEmpty &&
+            tx.height != null &&
+            tx.height! > 0 &&
+            (_currentChainTip ?? 0) > 0) {
+          tx.confirmations = _currentChainTip! - tx.height! + 1;
         }
       });
 
@@ -1973,9 +1984,17 @@ abstract class ElectrumWalletBase
     await Future.wait(unsubscribedScriptHashes.map((address) async {
       final sh = address.getScriptHash(network);
       if (!(_scripthashesUpdateSubject[sh]?.isClosed ?? true)) {
-        await _scripthashesUpdateSubject[sh]?.close();
+        try {
+          await _scripthashesUpdateSubject[sh]?.close();
+        } catch (e) {
+          print("failed to close: $e");
+        }
+      }
+      try {
+        _scripthashesUpdateSubject[sh] = await electrumClient.scripthashUpdate(sh);
+      } catch (e) {
+        print("failed scripthashUpdate: $e");
       }
-      _scripthashesUpdateSubject[sh] = await electrumClient.scripthashUpdate(sh);
       _scripthashesUpdateSubject[sh]?.listen((event) async {
         try {
           await updateUnspentsForAddress(address);
@@ -2171,6 +2190,7 @@ abstract class ElectrumWalletBase
 
   @action
   void _onConnectionStatusChange(ConnectionStatus status) {
+
     switch (status) {
       case ConnectionStatus.connected:
         if (syncStatus is NotConnectedSyncStatus ||
@@ -2182,19 +2202,26 @@ abstract class ElectrumWalletBase
 
         break;
       case ConnectionStatus.disconnected:
-        syncStatus = NotConnectedSyncStatus();
+        if (syncStatus is! NotConnectedSyncStatus) {
+          syncStatus = NotConnectedSyncStatus();
+        }
         break;
       case ConnectionStatus.failed:
-        syncStatus = LostConnectionSyncStatus();
+        if (syncStatus is! LostConnectionSyncStatus) {
+          syncStatus = LostConnectionSyncStatus();
+        }
         break;
       case ConnectionStatus.connecting:
-        syncStatus = ConnectingSyncStatus();
+        if (syncStatus is! ConnectingSyncStatus) {
+          syncStatus = ConnectingSyncStatus();
+        }
         break;
       default:
     }
   }
 
   void _syncStatusReaction(SyncStatus syncStatus) async {
+    print("SYNC_STATUS_CHANGE: ${syncStatus}");
     if (syncStatus is SyncingSyncStatus) {
       return;
     }
diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart
index ce1ff9713..6c10dc615 100644
--- a/cw_bitcoin/lib/electrum_wallet_addresses.dart
+++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart
@@ -3,7 +3,7 @@ import 'dart:io' show Platform;
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:cw_bitcoin/bitcoin_address_record.dart';
-import 'package:cw_bitcoin/electrum_wallet.dart';
+import 'package:cw_bitcoin/bitcoin_unspent.dart';
 import 'package:cw_core/wallet_addresses.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_type.dart';
@@ -267,7 +267,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
   }
 
   @action
-  Future<String> getChangeAddress({List<BitcoinOutput>? outputs, UtxoDetails? utxoDetails}) async {
+  Future<String> getChangeAddress({List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
     updateChangeAddresses();
 
     if (changeAddresses.isEmpty) {
@@ -478,7 +478,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
 
       await saveAddressesInBox();
     } catch (e) {
-      print(e.toString());
+      print("updateAddresses $e");
     }
   }
 
diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart
index 29a2df48a..a09850f59 100644
--- a/cw_bitcoin/lib/litecoin_wallet.dart
+++ b/cw_bitcoin/lib/litecoin_wallet.dart
@@ -7,6 +7,7 @@ import 'package:crypto/crypto.dart';
 import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
 import 'package:cw_core/cake_hive.dart';
 import 'package:cw_core/mweb_utxo.dart';
+import 'package:cw_core/unspent_coin_type.dart';
 import 'package:cw_mweb/mwebd.pbgrpc.dart';
 import 'package:fixnum/fixnum.dart';
 import 'package:bip39/bip39.dart' as bip39;
@@ -95,6 +96,36 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     autorun((_) {
       this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
     });
+    reaction((_) => mwebSyncStatus, (status) async {
+      if (mwebSyncStatus is FailedSyncStatus) {
+        // we failed to connect to mweb, check if we are connected to the litecoin node:
+        late int nodeHeight;
+        try {
+          nodeHeight = await electrumClient.getCurrentBlockChainTip() ?? 0;
+        } catch (_) {
+          nodeHeight = 0;
+        }
+
+        if (nodeHeight == 0) {
+          // we aren't connected to the litecoin node, so the current electrum_wallet reactions will take care of this case for us
+        } else {
+          // we're connected to the litecoin node, but we failed to connect to mweb, try again after a few seconds:
+          await CwMweb.stop();
+          await Future.delayed(const Duration(seconds: 5));
+          startSync();
+        }
+      } else if (mwebSyncStatus is SyncingSyncStatus) {
+        syncStatus = mwebSyncStatus;
+      } else if (mwebSyncStatus is SyncronizingSyncStatus) {
+        if (syncStatus is! SyncronizingSyncStatus) {
+          syncStatus = mwebSyncStatus;
+        }
+      } else if (mwebSyncStatus is SyncedSyncStatus) {
+        if (syncStatus is! SyncedSyncStatus) {
+          syncStatus = mwebSyncStatus;
+        }
+      }
+    });
   }
   late final Bip32Slip10Secp256k1 mwebHd;
   late final Box<MwebUtxo> mwebUtxosBox;
@@ -105,6 +136,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
   late bool mwebEnabled;
   bool processingUtxos = false;
 
+  @observable
+  SyncStatus mwebSyncStatus = NotConnectedSyncStatus();
+
   List<int> get scanSecret => mwebHd.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
   List<int> get spendSecret => mwebHd.childKey(Bip32KeyIndex(0x80000001)).privateKey.privKey.raw;
 
@@ -244,13 +278,24 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
   @override
   Future<void> startSync() async {
     print("startSync() called!");
-    if (syncStatus is SyncronizingSyncStatus) {
+    print("STARTING SYNC - MWEB ENABLED: $mwebEnabled");
+    if (!mwebEnabled) {
+      try {
+        // in case we're switching from a litecoin wallet that had mweb enabled
+        CwMweb.stop();
+      } catch (_) {}
+      super.startSync();
       return;
     }
+
+    if (mwebSyncStatus is SyncronizingSyncStatus) {
+      return;
+    }
+
     print("STARTING SYNC - MWEB ENABLED: $mwebEnabled");
     _syncTimer?.cancel();
     try {
-      syncStatus = SyncronizingSyncStatus();
+      mwebSyncStatus = SyncronizingSyncStatus();
       try {
         await subscribeForUpdates();
       } catch (e) {
@@ -261,45 +306,32 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       _feeRatesTimer =
           Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates());
 
-      if (!mwebEnabled) {
-        try {
-          // in case we're switching from a litecoin wallet that had mweb enabled
-          CwMweb.stop();
-        } catch (_) {}
-        try {
-          await updateAllUnspents();
-          await updateTransactions();
-          await updateBalance();
-          syncStatus = SyncedSyncStatus();
-        } catch (e, s) {
-          print(e);
-          print(s);
-          syncStatus = FailedSyncStatus();
-        }
-        return;
-      }
-
+      print("START SYNC FUNCS");
       await waitForMwebAddresses();
       await processMwebUtxos();
       await updateTransactions();
       await updateUnspent();
       await updateBalance();
-    } catch (e) {
-      print("failed to start mweb sync: $e");
-      syncStatus = FailedSyncStatus(error: "failed to start");
+      print("DONE SYNC FUNCS");
+    } catch (e, s) {
+      print("mweb sync failed: $e $s");
+      mwebSyncStatus = FailedSyncStatus(error: "mweb sync failed: $e");
       return;
     }
 
     _syncTimer = Timer.periodic(const Duration(milliseconds: 3000), (timer) async {
-      if (syncStatus is FailedSyncStatus) return;
+      if (mwebSyncStatus is FailedSyncStatus) {
+        _syncTimer?.cancel();
+        return;
+      }
 
       final nodeHeight =
           await electrumClient.getCurrentBlockChainTip() ?? 0; // current block height of our node
 
       if (nodeHeight == 0) {
         // we aren't connected to the ltc node yet
-        if (syncStatus is! NotConnectedSyncStatus) {
-          syncStatus = FailedSyncStatus(error: "Failed to connect to Litecoin node");
+        if (mwebSyncStatus is! NotConnectedSyncStatus) {
+          mwebSyncStatus = FailedSyncStatus(error: "litecoin node isn't connected");
         }
         return;
       }
@@ -309,12 +341,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       try {
         if (resp.blockHeaderHeight < nodeHeight) {
           int h = resp.blockHeaderHeight;
-          syncStatus = SyncingSyncStatus(nodeHeight - h, h / nodeHeight);
+          mwebSyncStatus = SyncingSyncStatus(nodeHeight - h, h / nodeHeight);
         } else if (resp.mwebHeaderHeight < nodeHeight) {
           int h = resp.mwebHeaderHeight;
-          syncStatus = SyncingSyncStatus(nodeHeight - h, h / nodeHeight);
+          mwebSyncStatus = SyncingSyncStatus(nodeHeight - h, h / nodeHeight);
         } else if (resp.mwebUtxosHeight < nodeHeight) {
-          syncStatus = SyncingSyncStatus(1, 0.999);
+          mwebSyncStatus = SyncingSyncStatus(1, 0.999);
         } else {
           if (resp.mwebUtxosHeight > walletInfo.restoreHeight) {
             await walletInfo.updateRestoreHeight(resp.mwebUtxosHeight);
@@ -325,6 +357,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
               int txHeight = transaction.height ?? resp.mwebUtxosHeight;
               final confirmations = (resp.mwebUtxosHeight - txHeight) + 1;
               if (transaction.confirmations == confirmations) continue;
+              if (transaction.confirmations == 0) {
+                updateBalance();
+              }
               transaction.confirmations = confirmations;
               transactionHistory.addOne(transaction);
             }
@@ -332,17 +367,17 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
           }
 
           // prevent unnecessary reaction triggers:
-          if (syncStatus is! SyncedSyncStatus) {
+          if (mwebSyncStatus is! SyncedSyncStatus) {
             // mwebd is synced, but we could still be processing incoming utxos:
             if (!processingUtxos) {
-              syncStatus = SyncedSyncStatus();
+              mwebSyncStatus = SyncedSyncStatus();
             }
           }
           return;
         }
       } catch (e) {
         print("error syncing: $e");
-        syncStatus = FailedSyncStatus(error: e.toString());
+        mwebSyncStatus = FailedSyncStatus(error: e.toString());
       }
     });
   }
@@ -512,8 +547,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     }
     _utxoStream = responseStream.listen((Utxo sUtxo) async {
       // we're processing utxos, so our balance could still be innacurate:
-      if (syncStatus is! SyncronizingSyncStatus && syncStatus is! SyncingSyncStatus) {
-        syncStatus = SyncronizingSyncStatus();
+      if (mwebSyncStatus is! SyncronizingSyncStatus && mwebSyncStatus is! SyncingSyncStatus) {
+        mwebSyncStatus = SyncronizingSyncStatus();
         processingUtxos = true;
         _processingTimer?.cancel();
         _processingTimer = Timer.periodic(const Duration(seconds: 2), (timer) async {
@@ -530,10 +565,18 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
         value: sUtxo.value.toInt(),
       );
 
-      // if (mwebUtxosBox.containsKey(utxo.outputId)) {
-      //   // we've already stored this utxo, skip it:
-      //   return;
-      // }
+      if (mwebUtxosBox.containsKey(utxo.outputId)) {
+        // we've already stored this utxo, skip it:
+        // but do update the utxo height if it's somehow different:
+        final existingUtxo = mwebUtxosBox.get(utxo.outputId);
+        if (existingUtxo!.height != utxo.height) {
+          print(
+              "updating utxo height for $utxo.outputId: ${existingUtxo.height} -> ${utxo.height}");
+          existingUtxo.height = utxo.height;
+          await mwebUtxosBox.put(utxo.outputId, existingUtxo);
+        }
+        return;
+      }
 
       await updateUnspent();
       await updateBalance();
@@ -579,7 +622,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     final height = await electrumClient.getCurrentBlockChainTip();
     if (height == null || status.blockHeaderHeight != height) return;
     if (status.mwebUtxosHeight != height) return; // we aren't synced
-
     int amount = 0;
     Set<String> inputAddresses = {};
     var output = convert.AccumulatorSink<Digest>();
@@ -673,10 +715,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
   @override
   @action
   Future<void> updateAllUnspents() async {
-    // get ltc unspents:
-    await super.updateAllUnspents();
-
     if (!mwebEnabled) {
+      await super.updateAllUnspents();
       return;
     }
 
@@ -712,6 +752,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       }
       mwebUnspentCoins.add(unspent);
     });
+
+    // copy coin control attributes to mwebCoins:
+    await updateCoins(mwebUnspentCoins);
+    // get regular ltc unspents (this resets unspentCoins):
+    await super.updateAllUnspents();
+    // add the mwebCoins:
     unspentCoins.addAll(mwebUnspentCoins);
   }
 
@@ -890,6 +936,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       tx.isMweb = mwebEnabled;
 
       if (!mwebEnabled) {
+        tx.changeAddressOverride =
+            await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(isPegIn: false);
         return tx;
       }
       await waitForMwebAddresses();
@@ -913,12 +961,23 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
           hasMwebOutput = true;
           break;
         }
+        if (output.address.toLowerCase().contains("mweb")) {
+          hasMwebOutput = true;
+          break;
+        }
       }
 
-      if (tx2.mwebBytes != null && tx2.mwebBytes!.isNotEmpty) {
-        hasMwebInput = true;
+      // check if mweb inputs are used:
+      for (final utxo in tx.utxos) {
+        if (utxo.utxo.scriptType == SegwitAddresType.mweb) {
+          hasMwebInput = true;
+        }
       }
 
+      bool isPegIn = !hasMwebInput && hasMwebOutput;
+      bool isRegular = !hasMwebInput && !hasMwebOutput;
+      tx.changeAddressOverride = await (walletAddresses as LitecoinWalletAddresses)
+          .getChangeAddress(isPegIn: isPegIn || isRegular);
       if (!hasMwebInput && !hasMwebOutput) {
         tx.isMweb = false;
         return tx;
@@ -971,7 +1030,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
           final addresses = <String>{};
           transaction.inputAddresses?.forEach((id) async {
             final utxo = mwebUtxosBox.get(id);
-            // await mwebUtxosBox.delete(id);// gets deleted in checkMwebUtxosSpent
+            await mwebUtxosBox.delete(id); // gets deleted in checkMwebUtxosSpent
             if (utxo == null) return;
             final addressRecord = walletAddresses.allAddresses
                 .firstWhere((addressRecord) => addressRecord.address == utxo.address);
@@ -990,6 +1049,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       print(e);
       print(s);
       if (e.toString().contains("commit failed")) {
+        print(e);
         throw Exception("Transaction commit failed (no peers responded), please try again.");
       }
       rethrow;
diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
index 0a20665bf..6154a0ead 100644
--- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
@@ -5,6 +5,7 @@ import 'dart:typed_data';
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:cw_bitcoin/bitcoin_address_record.dart';
+import 'package:cw_bitcoin/bitcoin_unspent.dart';
 import 'package:cw_bitcoin/electrum_wallet.dart';
 import 'package:cw_bitcoin/utils.dart';
 import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
@@ -142,14 +143,15 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
 
   @action
   @override
-  Future<String> getChangeAddress({List<BitcoinOutput>? outputs, UtxoDetails? utxoDetails}) async {
+  Future<String> getChangeAddress(
+      {List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
     // use regular change address on peg in, otherwise use mweb for change address:
 
-    if (!mwebEnabled) {
+    if (!mwebEnabled || isPegIn) {
       return super.getChangeAddress();
     }
 
-    if (outputs != null && utxoDetails != null) {
+    if (inputs != null && outputs != null) {
       // check if this is a PEGIN:
       bool outputsToMweb = false;
       bool comesFromMweb = false;
@@ -161,14 +163,18 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
           outputsToMweb = true;
         }
       }
-      // TODO: this doesn't respect coin control because it doesn't know which available inputs are selected
-      utxoDetails.availableInputs.forEach((element) {
+
+      inputs.forEach((element) {
+        if (!element.isSending || element.isFrozen) {
+          return;
+        }
         if (element.address.contains("mweb")) {
           comesFromMweb = true;
         }
       });
 
       bool isPegIn = !comesFromMweb && outputsToMweb;
+
       if (isPegIn && mwebEnabled) {
         return super.getChangeAddress();
       }
diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
index c722dc14f..5ed84dbf4 100644
--- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart
+++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
@@ -24,6 +24,7 @@ class PendingBitcoinTransaction with PendingTransaction {
     this.isSendAll = false,
     this.hasTaprootInputs = false,
     this.isMweb = false,
+    this.utxos = const [],
   }) : _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
 
   final WalletType type;
@@ -36,7 +37,9 @@ class PendingBitcoinTransaction with PendingTransaction {
   final bool isSendAll;
   final bool hasChange;
   final bool hasTaprootInputs;
+  List<UtxoWithAddress> utxos;
   bool isMweb;
+  String? changeAddressOverride;
   String? idOverride;
   String? hexOverride;
   List<String>? outputAddresses;
@@ -63,6 +66,9 @@ class PendingBitcoinTransaction with PendingTransaction {
   PendingChange? get change {
     try {
       final change = _tx.outputs.firstWhere((out) => out.isChange);
+      if (changeAddressOverride != null) {
+        return PendingChange(changeAddressOverride!, BtcUtils.fromSatoshi(change.amount));
+      }
       return PendingChange(change.scriptPubKey.toAddress(), BtcUtils.fromSatoshi(change.amount));
     } catch (_) {
       return null;
diff --git a/cw_mweb/lib/cw_mweb.dart b/cw_mweb/lib/cw_mweb.dart
index 39aa433cd..a1a592fb8 100644
--- a/cw_mweb/lib/cw_mweb.dart
+++ b/cw_mweb/lib/cw_mweb.dart
@@ -40,7 +40,7 @@ class CwMweb {
   }
 
   static Future<void> _initializeClient() async {
-    print("initialize client called!");
+    print("_initializeClient() called!");
     final appDir = await getApplicationSupportDirectory();
     const ltcNodeUri = "ltc-electrum.cakewallet.com:9333";
 
@@ -54,7 +54,7 @@ class CwMweb {
     log("Attempting to connect to server on port: $_port");
 
     // wait for the server to finish starting up before we try to connect to it:
-    await Future.delayed(const Duration(seconds: 5));
+    await Future.delayed(const Duration(seconds: 8));
 
     _clientChannel = ClientChannel('127.0.0.1', port: _port!, channelShutdownHandler: () {
       _rpcClient = null;
@@ -83,10 +83,13 @@ class CwMweb {
         log("Attempt $i failed: $e");
         log('Caught grpc error: ${e.message}');
         _rpcClient = null;
+        // necessary if the database isn't open:
+        await stop();
         await Future.delayed(const Duration(seconds: 3));
       } catch (e) {
         log("Attempt $i failed: $e");
         _rpcClient = null;
+        await stop();
         await Future.delayed(const Duration(seconds: 3));
       }
     }
diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart
index 91232792a..365d86be5 100644
--- a/lib/bitcoin/cw_bitcoin.dart
+++ b/lib/bitcoin/cw_bitcoin.dart
@@ -208,7 +208,7 @@ class CWBitcoin extends Bitcoin {
       {UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any}) {
     final bitcoinWallet = wallet as ElectrumWallet;
     return bitcoinWallet.unspentCoins.where((element) {
-      switch(coinTypeToSpendFrom) {
+      switch (coinTypeToSpendFrom) {
         case UnspentCoinType.mweb:
           return element.bitcoinAddressRecord.type == SegwitAddresType.mweb;
         case UnspentCoinType.nonMweb:
@@ -216,7 +216,6 @@ class CWBitcoin extends Bitcoin {
         case UnspentCoinType.any:
           return true;
       }
-
     }).toList();
   }
 
@@ -399,19 +398,21 @@ class CWBitcoin extends Bitcoin {
           final history = await electrumClient.getHistory(sh);
 
           final balance = await electrumClient.getBalance(sh);
-          dInfoCopy.balance = balance.entries.first.value.toString();
+          dInfoCopy.balance = balance.entries.firstOrNull?.value.toString() ?? "0";
           dInfoCopy.address = address;
           dInfoCopy.transactionsCount = history.length;
 
           list.add(dInfoCopy);
-        } catch (e) {
-          print(e);
+        } catch (e, s) {
+          print("derivationInfoError: $e");
+          print("derivationInfoStack: $s");
         }
       }
     }
 
     // sort the list such that derivations with the most transactions are first:
     list.sort((a, b) => b.transactionsCount.compareTo(a.transactionsCount));
+
     return list;
   }
 
@@ -682,4 +683,15 @@ class CWBitcoin extends Bitcoin {
       return null;
     }
   }
+
+  String? getUnusedSegwitAddress(Object wallet) {
+    try {
+      final electrumWallet = wallet as ElectrumWallet;
+      final segwitAddress = electrumWallet.walletAddresses.allAddresses
+          .firstWhere((element) => !element.isUsed && element.type == SegwitAddresType.p2wpkh);
+      return segwitAddress.address;
+    } catch (_) {
+      return null;
+    }
+  }
 }
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index 2b8c49631..198781cea 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -899,7 +899,9 @@ Future<void> changeDefaultBitcoinNode(
   final newCakeWalletBitcoinNode =
       Node(uri: newCakeWalletBitcoinUri, type: WalletType.bitcoin, useSSL: false);
 
-  await nodeSource.add(newCakeWalletBitcoinNode);
+  if (!nodeSource.values.any((element) => element.uriRaw == newCakeWalletBitcoinUri)) {
+    await nodeSource.add(newCakeWalletBitcoinNode);
+  }
 
   if (needToReplaceCurrentBitcoinNode) {
     await sharedPreferences.setInt(
@@ -931,6 +933,10 @@ Future<void> _addBitcoinNode({
   bool replaceExisting = false,
   bool useSSL = false,
 }) async {
+  bool isNodeExists = nodeSource.values.any((element) => element.uriRaw == nodeUri);
+  if (isNodeExists) {
+    return;
+  }
   const cakeWalletBitcoinNodeUriPattern = '.cakewallet.com';
   final currentBitcoinNodeId =
       sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart
index 708941023..84bdfd58b 100644
--- a/lib/src/screens/dashboard/pages/balance_page.dart
+++ b/lib/src/screens/dashboard/pages/balance_page.dart
@@ -17,7 +17,6 @@ import 'package:cake_wallet/src/widgets/standard_switch.dart';
 import 'package:cake_wallet/store/settings_store.dart';
 import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
 import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
-import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
 import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
 import 'package:cake_wallet/utils/feature_flag.dart';
 import 'package:cake_wallet/utils/payment_request.dart';
@@ -843,7 +842,7 @@ class BalanceRowWidget extends StatelessWidget {
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
                 Container(
-                  margin: const EdgeInsets.only(top: 0, left: 24, right: 8, bottom: 16),
+                  margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16),
                   child: Stack(
                     children: [
                       if (currency == CryptoCurrency.ltc)
@@ -851,17 +850,15 @@ class BalanceRowWidget extends StatelessWidget {
                           mainAxisAlignment: MainAxisAlignment.end,
                           children: [
                             Container(
-                              padding: EdgeInsets.only(right: 16, top: 16),
+                              padding: EdgeInsets.only(right: 16, top: 0),
                               child: Column(
                                 children: [
                                   Container(
-                                    decoration: BoxDecoration(
-                                      color: Colors.white,
-                                      shape: BoxShape.circle,
-                                    ),
                                     child: ImageIcon(
                                       AssetImage('assets/images/mweb_logo.png'),
-                                      color: Color.fromARGB(255, 11, 70, 129),
+                                      color: Theme.of(context)
+                                          .extension<BalancePageTheme>()!
+                                          .assetTitleColor,
                                       size: 40,
                                     ),
                                   ),
@@ -889,7 +886,6 @@ class BalanceRowWidget extends StatelessWidget {
                             Column(
                               crossAxisAlignment: CrossAxisAlignment.start,
                               children: [
-                                SizedBox(height: 24),
                                 Text(
                                   '${secondAvailableBalanceLabel}',
                                   textAlign: TextAlign.center,
@@ -907,9 +903,9 @@ class BalanceRowWidget extends StatelessWidget {
                                 AutoSizeText(
                                   secondAvailableBalance,
                                   style: TextStyle(
-                                    fontSize: 20,
+                                    fontSize: 24,
                                     fontFamily: 'Lato',
-                                    fontWeight: FontWeight.w400,
+                                    fontWeight: FontWeight.w900,
                                     color: Theme.of(context)
                                         .extension<BalancePageTheme>()!
                                         .assetTitleColor,
@@ -918,15 +914,15 @@ class BalanceRowWidget extends StatelessWidget {
                                   maxLines: 1,
                                   textAlign: TextAlign.center,
                                 ),
-                                SizedBox(height: 4),
+                                SizedBox(height: 6),
                                 if (!isTestnet)
                                   Text(
                                     '${secondAvailableFiatBalance}',
                                     textAlign: TextAlign.center,
                                     style: TextStyle(
-                                      fontSize: 12,
+                                      fontSize: 16,
                                       fontFamily: 'Lato',
-                                      fontWeight: FontWeight.w400,
+                                      fontWeight: FontWeight.w500,
                                       color: Theme.of(context)
                                           .extension<BalancePageTheme>()!
                                           .textColor,
@@ -1019,7 +1015,6 @@ class BalanceRowWidget extends StatelessWidget {
                                   paymentRequest =
                                       PaymentRequest.fromUri(Uri.parse("litecoin:${mwebAddress}"));
                                 }
-
                                 Navigator.pushNamed(
                                   context,
                                   Routes.send,
@@ -1030,11 +1025,10 @@ class BalanceRowWidget extends StatelessWidget {
                                 );
                               },
                               style: OutlinedButton.styleFrom(
-                                backgroundColor: Theme.of(context)
-                                    .extension<SendPageTheme>()!
-                                    .textFieldButtonIconColor
+                                backgroundColor: Colors.grey.shade400
                                     .withAlpha(50),
-                                side: BorderSide(color: Colors.grey.shade400, width: 0),
+                                side: BorderSide(color: Colors.grey.shade400
+                                      .withAlpha(50), width: 0),
                                 shape: RoundedRectangleBorder(
                                   borderRadius: BorderRadius.circular(20),
                                 ),
@@ -1058,7 +1052,7 @@ class BalanceRowWidget extends StatelessWidget {
                                       style: TextStyle(
                                         color: Theme.of(context)
                                             .extension<BalancePageTheme>()!
-                                            .assetTitleColor,
+                                            .textColor,
                                       ),
                                     ),
                                   ],
@@ -1074,13 +1068,12 @@ class BalanceRowWidget extends StatelessWidget {
                             child: OutlinedButton(
                               onPressed: () {
                                 final litecoinAddress =
-                                    bitcoin!.getAddress(dashboardViewModel.wallet);
+                                    bitcoin!.getUnusedSegwitAddress(dashboardViewModel.wallet);
                                 PaymentRequest? paymentRequest = null;
-                                if (litecoinAddress.isNotEmpty) {
+                                if ((litecoinAddress?.isNotEmpty ?? false)) {
                                   paymentRequest = PaymentRequest.fromUri(
                                       Uri.parse("litecoin:${litecoinAddress}"));
                                 }
-
                                 Navigator.pushNamed(
                                   context,
                                   Routes.send,
@@ -1091,11 +1084,10 @@ class BalanceRowWidget extends StatelessWidget {
                                 );
                               },
                               style: OutlinedButton.styleFrom(
-                                backgroundColor: Theme.of(context)
-                                    .extension<SendPageTheme>()!
-                                    .textFieldButtonIconColor
+                                backgroundColor: Colors.grey.shade400
                                     .withAlpha(50),
-                                side: BorderSide(color: Colors.grey.shade400, width: 0),
+                                side: BorderSide(color: Colors.grey.shade400
+                                      .withAlpha(50), width: 0),
                                 shape: RoundedRectangleBorder(
                                   borderRadius: BorderRadius.circular(20),
                                 ),
@@ -1119,7 +1111,7 @@ class BalanceRowWidget extends StatelessWidget {
                                       style: TextStyle(
                                         color: Theme.of(context)
                                             .extension<BalancePageTheme>()!
-                                            .assetTitleColor,
+                                            .textColor,
                                       ),
                                     ),
                                   ],
diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart
index ccf4a1dc4..d881d0341 100644
--- a/lib/src/screens/send/send_page.dart
+++ b/lib/src/screens/send/send_page.dart
@@ -28,6 +28,7 @@ import 'package:cake_wallet/utils/request_review_handler.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:cake_wallet/view_model/send/output.dart';
+import 'package:cw_core/unspent_coin_type.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:cake_wallet/view_model/send/send_view_model.dart';
 import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
@@ -508,6 +509,10 @@ class SendPage extends BasePage {
                                 if (state is TransactionCommitted) {
                                   newContactAddress =
                                       newContactAddress ?? sendViewModel.newContactAddress();
+                                  
+                                  if (sendViewModel.coinTypeToSpendFrom != UnspentCoinType.any) {
+                                    newContactAddress = null;
+                                  }
 
                                   final successMessage = S.of(_dialogContext).send_success(
                                       sendViewModel.selectedCryptoCurrency.toString());
diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart
index 90b4c5c3a..17a8d6d28 100644
--- a/lib/view_model/wallet_creation_vm.dart
+++ b/lib/view_model/wallet_creation_vm.dart
@@ -115,7 +115,9 @@ abstract class WalletCreationVMBase with Store {
       getIt.get<BackgroundTasks>().registerSyncTask();
       _appStore.authenticationStore.allowed();
       state = ExecutedSuccessfullyState();
-    } catch (e, _) {
+    } catch (e, s) {
+      print("error: $e");
+      print("stack: $s");
       state = FailureState(e.toString());
     }
   }
@@ -194,31 +196,29 @@ abstract class WalletCreationVMBase with Store {
     final walletType = restoreWallet.type;
     var appStore = getIt.get<AppStore>();
     var node = appStore.settingsStore.getCurrentNode(walletType);
-    
-      switch (walletType) {
-        case WalletType.bitcoin:
-        case WalletType.litecoin:
 
-          final derivationList = await bitcoin!.getDerivationsFromMnemonic(
-            mnemonic: restoreWallet.mnemonicSeed!,
-            node: node,
-            passphrase: restoreWallet.passphrase,
-          );
+    switch (walletType) {
+      case WalletType.bitcoin:
+      case WalletType.litecoin:
+        final derivationList = await bitcoin!.getDerivationsFromMnemonic(
+          mnemonic: restoreWallet.mnemonicSeed!,
+          node: node,
+          passphrase: restoreWallet.passphrase,
+        );
 
+        if (derivationList.firstOrNull?.transactionsCount == 0 && derivationList.length > 1)
+          return [];
+        return derivationList;
 
-          if (derivationList.first.transactionsCount == 0 && derivationList.length > 1) return [];
-          
-          return derivationList;
-
-        case WalletType.nano:
-          return nanoUtil!.getDerivationsFromMnemonic(
-            mnemonic: restoreWallet.mnemonicSeed!,
-            node: node,
-          );
-        default:
-          break;
-      }
-      return list;
+      case WalletType.nano:
+        return nanoUtil!.getDerivationsFromMnemonic(
+          mnemonic: restoreWallet.mnemonicSeed!,
+          node: node,
+        );
+      default:
+        break;
+    }
+    return list;
   }
 
   WalletCredentials getCredentials(dynamic options) => throw UnimplementedError();
diff --git a/tool/configure.dart b/tool/configure.dart
index ce079dd29..704b47526 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -231,6 +231,7 @@ abstract class Bitcoin {
   Future<void> setMwebEnabled(Object wallet, bool enabled);
   bool getMwebEnabled(Object wallet);
   String? getUnusedMwebAddress(Object wallet);
+  String? getUnusedSegwitAddress(Object wallet);
 }
   """;
 

From 34166c3a11af78c876f983131e2ea12809330692 Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Mon, 21 Oct 2024 13:03:53 +0300
Subject: [PATCH 10/50] v4.20.0 (#1759)

* new version

* fix android manifest [skip ci]

* fix sp scanning [skip ci]
---
 android/app/src/main/AndroidManifestBase.xml      |  2 +-
 assets/text/Monerocom_Release_Notes.txt           |  7 +++----
 assets/text/Release_Notes.txt                     | 15 ++++++---------
 cw_bitcoin/lib/electrum.dart                      |  6 +++---
 cw_bitcoin/lib/litecoin_wallet.dart               |  2 --
 cw_core/lib/wallet_addresses.dart                 |  2 +-
 lib/src/screens/dashboard/pages/balance_page.dart |  2 +-
 scripts/android/app_env.sh                        |  4 ++--
 scripts/ios/app_env.sh                            |  4 ++--
 scripts/linux/app_env.sh                          |  2 +-
 scripts/macos/app_env.sh                          |  4 ++--
 11 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml
index 1d0e2c93c..98bbb1236 100644
--- a/android/app/src/main/AndroidManifestBase.xml
+++ b/android/app/src/main/AndroidManifestBase.xml
@@ -14,7 +14,7 @@
 <!--     required for API 18 - 30 -->
     <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
-    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 
 <!--     required for API <= 29 -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt
index 2f79dd5c6..613ea4281 100644
--- a/assets/text/Monerocom_Release_Notes.txt
+++ b/assets/text/Monerocom_Release_Notes.txt
@@ -1,4 +1,3 @@
-Monero enhancements for sending and address generation
-StealthEx
-LetsExchange
-Visual enhancements and bug fixes
\ No newline at end of file
+Monero enhancements
+Introducing StealthEx and LetxExchange
+Bug fixes
\ No newline at end of file
diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt
index 868ae7954..d359d6e8a 100644
--- a/assets/text/Release_Notes.txt
+++ b/assets/text/Release_Notes.txt
@@ -1,9 +1,6 @@
-Add Litecoin MWEB
-Wallet groups (same seed, multiple wallets)
-Silent Payments enhancements
-Monero enhancements for sending and address generation
-StealthEx
-LetsExchange
-Replace-By-Fee improvements
-ERC20 tokens potential scam detection
-Visual enhancements and bug fixes
\ No newline at end of file
+Added Litecoin MWEB
+Added wallet groups
+Silent Payment enhancements for speed & reliability
+Monero enhancements
+Introducing StealthEx and LetxExchange
+Additional ERC20 tokens scam detection
\ No newline at end of file
diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart
index a8cb7ee9f..a18c038fa 100644
--- a/cw_bitcoin/lib/electrum.dart
+++ b/cw_bitcoin/lib/electrum.dart
@@ -423,7 +423,7 @@ class ElectrumClient {
   BehaviorSubject<T>? subscribe<T>(
       {required String id, required String method, List<Object> params = const []}) {
     try {
-      if (socket == null || !isConnected) {
+      if (socket == null) {
         return null;
       }
       final subscription = BehaviorSubject<T>();
@@ -439,7 +439,7 @@ class ElectrumClient {
 
   Future<dynamic> call(
       {required String method, List<Object> params = const [], Function(int)? idCallback}) async {
-    if (socket == null || !isConnected) {
+    if (socket == null) {
       return null;
     }
     final completer = Completer<dynamic>();
@@ -455,7 +455,7 @@ class ElectrumClient {
   Future<dynamic> callWithTimeout(
       {required String method, List<Object> params = const [], int timeout = 5000}) async {
     try {
-      if (socket == null || !isConnected) {
+      if (socket == null) {
         return null;
       }
       final completer = Completer<dynamic>();
diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart
index a09850f59..afa8cc388 100644
--- a/cw_bitcoin/lib/litecoin_wallet.dart
+++ b/cw_bitcoin/lib/litecoin_wallet.dart
@@ -7,7 +7,6 @@ import 'package:crypto/crypto.dart';
 import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
 import 'package:cw_core/cake_hive.dart';
 import 'package:cw_core/mweb_utxo.dart';
-import 'package:cw_core/unspent_coin_type.dart';
 import 'package:cw_mweb/mwebd.pbgrpc.dart';
 import 'package:fixnum/fixnum.dart';
 import 'package:bip39/bip39.dart' as bip39;
@@ -425,7 +424,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     bool? usingElectrs,
   }) async {
     _syncTimer?.cancel();
-    int oldHeight = walletInfo.restoreHeight;
     await walletInfo.updateRestoreHeight(height);
 
     // go through mwebUtxos and clear any that are above the new restore height:
diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart
index 4324823c5..714d229d9 100644
--- a/cw_core/lib/wallet_addresses.dart
+++ b/cw_core/lib/wallet_addresses.dart
@@ -23,7 +23,7 @@ abstract class WalletAddresses {
     return _localAddress ?? address;
   }
 
-  String get primaryAddress;
+  String get primaryAddress => address;
 
   String? _localAddress;
 
diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart
index 84bdfd58b..478f1a3c3 100644
--- a/lib/src/screens/dashboard/pages/balance_page.dart
+++ b/lib/src/screens/dashboard/pages/balance_page.dart
@@ -1061,7 +1061,7 @@ class BalanceRowWidget extends StatelessWidget {
                             ),
                           ),
                         ),
-                        SizedBox(width: 32),
+                        SizedBox(width: 24),
                         Expanded(
                           child: Semantics(
                             label: S.of(context).litecoin_mweb_pegout,
diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh
index 428891b2c..22fa7ef20 100644
--- a/scripts/android/app_env.sh
+++ b/scripts/android/app_env.sh
@@ -16,14 +16,14 @@ APP_ANDROID_TYPE=$1
 
 MONERO_COM_NAME="Monero.com"
 MONERO_COM_VERSION="1.17.0"
-MONERO_COM_BUILD_NUMBER=102
+MONERO_COM_BUILD_NUMBER=103
 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.20.0"
-CAKEWALLET_BUILD_NUMBER=230
+CAKEWALLET_BUILD_NUMBER=232
 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 d976f07fd..066b752cc 100644
--- a/scripts/ios/app_env.sh
+++ b/scripts/ios/app_env.sh
@@ -14,12 +14,12 @@ APP_IOS_TYPE=$1
 
 MONERO_COM_NAME="Monero.com"
 MONERO_COM_VERSION="1.17.0"
-MONERO_COM_BUILD_NUMBER=100
+MONERO_COM_BUILD_NUMBER=101
 MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
 CAKEWALLET_VERSION="4.20.0"
-CAKEWALLET_BUILD_NUMBER=269
+CAKEWALLET_BUILD_NUMBER=276
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 HAVEN_NAME="Haven"
diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh
index aaeb2bc2a..f1616d7c5 100755
--- a/scripts/linux/app_env.sh
+++ b/scripts/linux/app_env.sh
@@ -15,7 +15,7 @@ fi
 
 CAKEWALLET_NAME="Cake Wallet"
 CAKEWALLET_VERSION="1.10.0"
-CAKEWALLET_BUILD_NUMBER=35
+CAKEWALLET_BUILD_NUMBER=36
 
 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 af2dc1322..9c5fef1ff 100755
--- a/scripts/macos/app_env.sh
+++ b/scripts/macos/app_env.sh
@@ -17,12 +17,12 @@ fi
 
 MONERO_COM_NAME="Monero.com"
 MONERO_COM_VERSION="1.7.0"
-MONERO_COM_BUILD_NUMBER=33
+MONERO_COM_BUILD_NUMBER=34
 MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
 CAKEWALLET_VERSION="1.13.0"
-CAKEWALLET_BUILD_NUMBER=90
+CAKEWALLET_BUILD_NUMBER=92
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then

From 0a1e32c363fbf1a654b459665cfc7cbc6643080e Mon Sep 17 00:00:00 2001
From: omahs <73983677+omahs@users.noreply.github.com>
Date: Tue, 22 Oct 2024 02:29:00 +0200
Subject: [PATCH 11/50] Fix typos (#1760)

* fix typos

* fix typos

* fix typos

* fix typos
---
 build-guide-linux.md          | 4 ++--
 how_to_add_new_wallet_type.md | 6 +++---
 howto-build-ios.md            | 4 ++--
 howto-build-windows.md        | 6 +++---
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/build-guide-linux.md b/build-guide-linux.md
index e0158945b..50ecc76fe 100644
--- a/build-guide-linux.md
+++ b/build-guide-linux.md
@@ -15,7 +15,7 @@ These steps will help you configure and execute a build of CakeWallet from its s
 
 ### 1. Installing Package Dependencies
 
-CakeWallet requires some packages to be install on your build system. You may easily install them on your build system with the following command:
+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`
 
@@ -145,7 +145,7 @@ Path to executable file will be:
 
 # Flatpak
 
-For package the built application into flatpak you need fistly to install `flatpak` and `flatpak-builder`:
+For package the built application into flatpak you need firstly to install `flatpak` and `flatpak-builder`:
 
 `$ sudo apt install flatpak flatpak-builder`
 
diff --git a/how_to_add_new_wallet_type.md b/how_to_add_new_wallet_type.md
index 917e87cf4..d71e181e0 100644
--- a/how_to_add_new_wallet_type.md
+++ b/how_to_add_new_wallet_type.md
@@ -5,7 +5,7 @@
 **N:B** Throughout this guide, `walletx` refers to the specific wallet type you want to add. If you're adding `BNB` to CakeWallet, then `walletx` for you here is `bnb`.
 
 **Core Folder/Files Setup**
-- Idenitify your core component/package (major project component), which would power the integration e.g web3dart, solana, onchain etc
+- Identify your core component/package (major project component), which would power the integration e.g web3dart, solana, onchain etc
 - Add a new entry to `WalletType` class in `cw_core/wallet_type.dart`. 
 - Fill out the necessary information in the various functions in the files, concerning the wallet name, the native currency type, symbol etc.
 - Go to `cw_core/lib/currency_for_wallet_type.dart`, in the `currencyForWalletType` function, add a case for `walletx`, returning the native cryptocurrency for `walletx`. 
@@ -144,7 +144,7 @@ You can add as many node entries as desired.
 			}
 		}
 
-- Next, we’ll write the function to change walletX current node to default. An handy function we would make use of later on. Add a new preference key in `lib/entities/preference_key.dart` with the format `PreferencesKey.currentWalletXNodeIdKey`, we’ll use it to identify the current node id.
+- Next, we’ll write the function to change walletX current node to default. A handy function we would make use of later on. Add a new preference key in `lib/entities/preference_key.dart` with the format `PreferencesKey.currentWalletXNodeIdKey`, we’ll use it to identify the current node id.
 
 		Future<void> changeWalletXCurrentNodeToDefault(
 				{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
@@ -228,7 +228,7 @@ Now you can run the codebase and successfully create a wallet for type walletX s
 
 **Balance Screen**
 - Go to `lib/view_model/dashboard/balance_view_model.dart`
-- Modify the function to adjust the way the balance is being display on the app: `isHomeScreenSettingsEnabled` 
+- Modify the function to adjust the way the balance is being displayed on the app: `isHomeScreenSettingsEnabled` 
 - Add a case to the `availableBalanceLabel` getter to modify the text being displayed (Available or confirmed)
 - Same for `additionalBalanceLabel` 
 - Next, go to `lib/reactions/fiat_rate_update.dart`
diff --git a/howto-build-ios.md b/howto-build-ios.md
index 418fbc96b..544d4359e 100644
--- a/howto-build-ios.md
+++ b/howto-build-ios.md
@@ -57,7 +57,7 @@ Proceed into the source code before proceeding with the next steps:
 
 ### 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. 
+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.
 
@@ -92,7 +92,7 @@ Then we need to generate localization files and mobx models.
 
 `$ flutter build ios --release`
 
-Then you can open `ios/Runner.xcworkspace` with Xcode and you can to archive the application.
+Then you can open `ios/Runner.xcworkspace` with Xcode and you can archive the application.
 
 Or if you want to run to connected device:
 
diff --git a/howto-build-windows.md b/howto-build-windows.md
index 796cb3cc8..504f8f785 100644
--- a/howto-build-windows.md
+++ b/howto-build-windows.md
@@ -22,7 +22,7 @@ Then install `Desktop development with C++` packages via Visual Studio 2022, or
 - `C++ 2022 Redistributable Update`
 - `C++ core desktop features`
 - `MVC v143 - VS 2022 C++ x64/x86 build tools`
-- `C++ CMake tools for Windwos`
+- `C++ CMake tools for Windows`
 - `Testing tools core features - Build Tools`
 - `C++ AddressSanitizer`.
 
@@ -38,7 +38,7 @@ For building monero dependencies, it is required to install Windows WSL (https:/
 
 ### 5. Pull Cake Wallet source code
 
-You can downlaod CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git:
+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)
 
@@ -52,6 +52,6 @@ For that you need to run the shell (bash - typically same named utility should b
 
 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 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.
+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.

From 20efba43cb2e335bd75f88d05c6c00649a3239f0 Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Tue, 22 Oct 2024 15:23:42 +0300
Subject: [PATCH 12/50] enable ssl for btc-electrum (#1765)

---
 assets/bitcoin_electrum_server_list.yml      |  1 +
 lib/entities/default_settings_migration.dart | 12 ++++++++++++
 lib/main.dart                                |  2 +-
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/assets/bitcoin_electrum_server_list.yml b/assets/bitcoin_electrum_server_list.yml
index 305db38f5..20a28cd24 100644
--- a/assets/bitcoin_electrum_server_list.yml
+++ b/assets/bitcoin_electrum_server_list.yml
@@ -3,6 +3,7 @@
   useSSL: true
 -
   uri: btc-electrum.cakewallet.com:50002
+  useSSL: true
   isDefault: true
 -
   uri: electrs.cakewallet.com:50001
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index 198781cea..af6f1ce78 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -256,6 +256,9 @@ Future<void> defaultSettingsMigration(
           await _addSethNode(nodes, sharedPreferences);
           await updateTronNodesWithNowNodes(sharedPreferences: sharedPreferences, nodes: nodes);
           break;
+        case 42:
+          updateBtcElectrumNodeToUseSSL(nodes, sharedPreferences);
+          break;
         default:
           break;
       }
@@ -270,6 +273,15 @@ Future<void> defaultSettingsMigration(
   await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
 }
 
+void updateBtcElectrumNodeToUseSSL(Box<Node> nodes, SharedPreferences sharedPreferences) {
+  final btcElectrumNode = nodes.values.firstWhereOrNull((element) => element.uriRaw == newCakeWalletBitcoinUri);
+
+  if (btcElectrumNode != null) {
+    btcElectrumNode.useSSL = true;
+    btcElectrumNode.save();
+  }
+}
+
 void _deselectQuantex(SharedPreferences sharedPreferences) {
   final Map<String, dynamic> exchangeProvidersSelection =
       json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}")
diff --git a/lib/main.dart b/lib/main.dart
index 7237de8b9..2b5bef06c 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -192,7 +192,7 @@ Future<void> initializeAppConfigs() async {
     transactionDescriptions: transactionDescriptions,
     secureStorage: secureStorage,
     anonpayInvoiceInfo: anonpayInvoiceInfo,
-    initialMigrationVersion: 41,
+    initialMigrationVersion: 42,
   );
 }
 

From 3898208a6aad9f41b38eaca210c66178a38156f4 Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Tue, 22 Oct 2024 16:46:25 +0300
Subject: [PATCH 13/50] fix send all (#1766)

* shouldn't matter, but still investigating why this fixes it

* got it, but this change is just for consistency [skip ci]
---
 cw_bitcoin/lib/electrum_wallet.dart | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 893cff6f2..4d127c248 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -1063,7 +1063,7 @@ abstract class ElectrumWalletBase
 
       if (sendAll) {
         estimatedTx = await estimateSendAllTx(
-          outputs,
+          updatedOutputs,
           feeRateInt,
           memo: memo,
           credentialsAmount: credentialsAmount,
@@ -1115,7 +1115,7 @@ abstract class ElectrumWalletBase
       if (network is BitcoinCashNetwork) {
         txb = ForkedTransactionBuilder(
           utxos: estimatedTx.utxos,
-          outputs: outputs,
+          outputs: updatedOutputs,
           fee: BigInt.from(estimatedTx.fee),
           network: network,
           memo: estimatedTx.memo,

From 68b18f66bd6e604d09602c5ee26901837f9c70ba Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Tue, 22 Oct 2024 17:40:49 +0300
Subject: [PATCH 14/50] new versions (#1767)

---
 assets/text/Release_Notes.txt           | 3 ++-
 scripts/android/app_env.sh              | 4 ++--
 scripts/ios/app_env.sh                  | 4 ++--
 scripts/linux/app_env.sh                | 4 ++--
 scripts/macos/app_env.sh                | 4 ++--
 scripts/windows/build_exe_installer.iss | 2 +-
 6 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt
index d359d6e8a..61aafb6e4 100644
--- a/assets/text/Release_Notes.txt
+++ b/assets/text/Release_Notes.txt
@@ -3,4 +3,5 @@ Added wallet groups
 Silent Payment enhancements for speed & reliability
 Monero enhancements
 Introducing StealthEx and LetxExchange
-Additional ERC20 tokens scam detection
\ No newline at end of file
+Additional ERC20 tokens scam detection
+Bug fixes
\ No newline at end of file
diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh
index 22fa7ef20..8beffbcc2 100644
--- a/scripts/android/app_env.sh
+++ b/scripts/android/app_env.sh
@@ -22,8 +22,8 @@ MONERO_COM_PACKAGE="com.monero.app"
 MONERO_COM_SCHEME="monero.com"
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="4.20.0"
-CAKEWALLET_BUILD_NUMBER=232
+CAKEWALLET_VERSION="4.20.1"
+CAKEWALLET_BUILD_NUMBER=233
 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 066b752cc..bc3b39747 100644
--- a/scripts/ios/app_env.sh
+++ b/scripts/ios/app_env.sh
@@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=101
 MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="4.20.0"
-CAKEWALLET_BUILD_NUMBER=276
+CAKEWALLET_VERSION="4.20.1"
+CAKEWALLET_BUILD_NUMBER=277
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 HAVEN_NAME="Haven"
diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh
index f1616d7c5..2dabf083b 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.10.0"
-CAKEWALLET_BUILD_NUMBER=36
+CAKEWALLET_VERSION="1.10.1"
+CAKEWALLET_BUILD_NUMBER=37
 
 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 9c5fef1ff..026ea034b 100755
--- a/scripts/macos/app_env.sh
+++ b/scripts/macos/app_env.sh
@@ -21,8 +21,8 @@ MONERO_COM_BUILD_NUMBER=34
 MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="1.13.0"
-CAKEWALLET_BUILD_NUMBER=92
+CAKEWALLET_VERSION="1.13.1"
+CAKEWALLET_BUILD_NUMBER=93
 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 33cd11292..f65900cca 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.1.0"
+#define MyAppVersion "0.1.1"
 #define MyAppPublisher "Cake Labs LLC"
 #define MyAppURL "https://cakewallet.com/"
 #define MyAppExeName "CakeWallet.exe"

From e04185a7c1c96f2bd155a5a491d21b80a0f9b24f Mon Sep 17 00:00:00 2001
From: OmarHatem <omarh.ismail1@gmail.com>
Date: Tue, 22 Oct 2024 21:06:08 +0300
Subject: [PATCH 15/50] upload x86 arch to artifacts [skip ci]

---
 .github/workflows/pr_test_build_android.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 925f4e00d..c9021fac0 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -224,6 +224,7 @@ jobs:
           cd /opt/android/cake_wallet/build/app/outputs/flutter-apk
           mkdir test-apk
           cp app-arm64-v8a-release.apk test-apk/${{env.BRANCH_NAME}}.apk
+          cp app-x86_64-release.apk test-apk/${{env.BRANCH_NAME}}_x86.apk
 
       - name: Upload Artifact
         uses: kittaakos/upload-artifact-as-is@v0

From 68926c0a337700165b807e76f34a31c52a9d0b79 Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Wed, 23 Oct 2024 17:38:31 +0200
Subject: [PATCH 16/50] Cw 679 add ledger litecoin support (#1565)

* Add Litecoin Hardware Wallet Creation

* Add Litecoin Hardware Wallet Creation

* Fix Bitcoin not sending on Ledger

* Fixes to sending LTC using Ledger

* CW-679 Fix merge conflicts

* CW-679 Fix merge conflicts

* CW-679 Minor fixes

* CW-679 Add derivation Path of change address

* ledger flutter plus refactoring

* ledger flutter plus refactoring

* ledger flutter plus refactoring

* Ups :|

* Ups :| I forgot USB

* Handle BT Off

* Fix Issue with A14 and USB

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Pls work

* Pls work

* Pls work

* Pls work

* Fix overpopulation

* Fix ble device detection and support for Stax and Flex

* clean up pubspec

* clean up

* MWeb merge fix

* MWeb merge fix

* Fix Merge conflicts

* Fix Requested changes
---
 assets/images/hardware_wallet/ledger_flex.png | Bin 0 -> 1777 bytes
 .../images/hardware_wallet/ledger_nano_s.png  | Bin 0 -> 2639 bytes
 .../images/hardware_wallet/ledger_nano_x.png  | Bin 0 -> 2634 bytes
 assets/images/hardware_wallet/ledger_stax.png | Bin 0 -> 1612 bytes
 assets/images/ledger_nano.png                 | Bin 1463 -> 0 bytes
 .../lib/bitcoin_hardware_wallet_service.dart  |  21 +--
 cw_bitcoin/lib/bitcoin_wallet.dart            |  57 ++++----
 cw_bitcoin/lib/bitcoin_wallet_addresses.dart  |   1 +
 cw_bitcoin/lib/electrum_wallet.dart           |  69 ++++++---
 cw_bitcoin/lib/electrum_wallet_addresses.dart |  21 ++-
 .../lib/litecoin_hardware_wallet_service.dart |  46 ++++++
 cw_bitcoin/lib/litecoin_wallet.dart           | 102 +++++++++++--
 cw_bitcoin/lib/litecoin_wallet_addresses.dart |  29 ++--
 cw_bitcoin/lib/litecoin_wallet_service.dart   |  23 ++-
 cw_bitcoin/lib/psbt_transaction_builder.dart  |   4 -
 cw_bitcoin/pubspec.lock                       | 134 +++++++++++-------
 cw_bitcoin/pubspec.yaml                       |  19 +--
 .../lib/src/bitcoin_cash_wallet.dart          |   1 +
 .../src/bitcoin_cash_wallet_addresses.dart    |   1 +
 .../lib/hardware/device_connection_type.dart  |   1 +
 .../evm_chain_hardware_wallet_service.dart    |  18 +--
 .../evm_chain_transaction_credentials.dart    |   1 -
 cw_evm/lib/evm_ledger_credentials.dart        |  57 ++++----
 cw_evm/pubspec.yaml                           |   9 +-
 lib/bitcoin/cw_bitcoin.dart                   |  24 +++-
 .../hardware_wallet_device.dart               |  65 +++++++++
 lib/ethereum/cw_ethereum.dart                 |  16 +--
 lib/main.dart                                 |  14 +-
 lib/polygon/cw_polygon.dart                   |  15 +-
 .../connect_device/connect_device_page.dart   | 120 ++++++++++------
 .../connect_device/debug_device_page.dart     | 112 +++++++++------
 .../connect_device/widgets/device_tile.dart   |   2 +-
 .../screens/dashboard/pages/balance_page.dart |   2 +-
 .../screens/restore/restore_options_page.dart |   4 +-
 lib/src/screens/send/send_page.dart           |  11 +-
 .../dashboard/dashboard_view_model.dart       |   2 +-
 .../hardware_wallet/ledger_view_model.dart    | 109 ++++++++++----
 lib/view_model/send/send_view_model.dart      |  19 ++-
 .../wallet_hardware_restore_view_model.dart   |  13 +-
 macos/Flutter/GeneratedPluginRegistrant.swift |   2 +
 pubspec_base.yaml                             |   9 +-
 res/values/strings_de.arb                     |  74 +++++-----
 tool/configure.dart                           |  16 ++-
 .../flutter/generated_plugin_registrant.cc    |   3 +
 windows/flutter/generated_plugins.cmake       |   1 +
 45 files changed, 842 insertions(+), 405 deletions(-)
 create mode 100644 assets/images/hardware_wallet/ledger_flex.png
 create mode 100644 assets/images/hardware_wallet/ledger_nano_s.png
 create mode 100644 assets/images/hardware_wallet/ledger_nano_x.png
 create mode 100644 assets/images/hardware_wallet/ledger_stax.png
 delete mode 100644 assets/images/ledger_nano.png
 create mode 100644 cw_bitcoin/lib/litecoin_hardware_wallet_service.dart
 create mode 100644 lib/entities/hardware_wallet/hardware_wallet_device.dart

diff --git a/assets/images/hardware_wallet/ledger_flex.png b/assets/images/hardware_wallet/ledger_flex.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa39f241fccf109565a28f66c090bf57ca274fd0
GIT binary patch
literal 1777
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
ToY=F<00000NkvXXu0mjfR%KGE

literal 0
HcmV?d00001

diff --git a/assets/images/hardware_wallet/ledger_nano_s.png b/assets/images/hardware_wallet/ledger_nano_s.png
new file mode 100644
index 0000000000000000000000000000000000000000..02777aeb69b2e436d2b9bd96c3b5f39a773b7def
GIT binary patch
literal 2639
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

literal 0
HcmV?d00001

diff --git a/assets/images/hardware_wallet/ledger_nano_x.png b/assets/images/hardware_wallet/ledger_nano_x.png
new file mode 100644
index 0000000000000000000000000000000000000000..e9328a5ef787f64501b3fd393932fb9f393d0468
GIT binary patch
literal 2634
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

literal 0
HcmV?d00001

diff --git a/assets/images/hardware_wallet/ledger_stax.png b/assets/images/hardware_wallet/ledger_stax.png
new file mode 100644
index 0000000000000000000000000000000000000000..06c9c848e8336bacbe4378b5e5999604393821e6
GIT binary patch
literal 1612
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
KMNUMnLSTZg0^5E7

literal 0
HcmV?d00001

diff --git a/assets/images/ledger_nano.png b/assets/images/ledger_nano.png
deleted file mode 100644
index bb61ba1750728b5584680110bd90727c3e195eca..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1463
zcmV;o1xWgdP)<h;3K|Lk000e1NJLTq003YB003YJ1^@s6;+S_h00009a7bBm001mY
z001mY0i`{bsQ>@~0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH1x!gqK~#7F?VP=H
z8$}er-=034bZ#-sAj)87q6`+K!(cK46`BD%bSQs8oQBwyr2<4~l5})29oR4<ItntD
zJ7c?06NU~^kfB4Vu&v}?-paZeN73Exee6lTeZR`KR_D9-yW5ZV?hb%q7=~dOhG7_n
zNfiMTV&SvqqHx3~fKVRpNvD5;_dBiiE?C4w1T3uF*${yBai0kg_5H2e4X}h9q)bro
zhb+D}e+~Y5^xH02K&k>Xg70CCgwzCt2)>6E5>gQmA^0Admtb5#jNp4@T7ppl2?XCG
zvl5I6&<#GdX&}HZO+ObEO*1LMh=4G`-``rVKYsMEJvYB3Y?P3=fUv>$ez#RZq5`4@
z-@`@;i3x}sd=J|sBqAWG;Ct94A+~^|gYRLBgjfPh1>eI436TYu4!%d$B}5WX{=8Yr
zA+%KO;s)O%%Mv09c=gh?Iz{7ZP@ANJ?~zpr4n%;;XqSUOPd4}-hqO(kZL8W*oBBJ{
zMZ!5Ck^qg(A{ZiT5+Zd$ugrgVMbQNr?FO>c9Yq@h-ds8oLevz^Sb_$T1U&xZVRsr1
zJ_`~euLGv#;Lp2+SSw+c5TDq&AeIo1M6#hQAv%fG16V>d60L}_gzzL@6J`nFFmhJ}
zOVG!N00~Rb!<YaGOHgA}fP^IkV_blQCHRwy00~PNPig`rVGe%o($cQXx<ZEcLt>~R
z=8tYgi|P$ufI;;41FB$<)CEZN4j!Mt6zm5I=z&2dB0!=#cvm=Wn1cNP7usNuRL6i(
z{Q6>fSH<Dh+INr=LHlvAy}k(s5ikV|o|+%_wTRF<{As-n6X5MnzpgsYsf0=H2g5K7
zV+WxI;c~S;o1eK@6E0o`i$H;YgK&EA%<UvSFl!5_T>thapnDIPE+Dk~eQYH0ZX+!L
z2|n?jEf6;2ickuW4`UQu@fR>Yh@K;$@%xXrBlQl-R74&fqsgfA56-%Xccb14uM{BA
zEd!$@>hlN_OU7jpDdFAgcUHrECl4{80i;VglQv`=1SnB`qAa@`Ra+Nfqg-vabO+{G
z0%Y(Hw%2ZeB~+H1H4?EQh4{C^*+M})pda1`4Y&&mflN)GoE%-Dv;2NwLjj92!wVY3
zx&pGs*_Hla^-IN=(UotfRhJdA)yhhfx+DLx=`g+CR{c-D0*1)NW}$fDKS5JUI)iIe
zoY@eL*r_akvqOD)X|#R+<akw%fxa6Qj#f>Z1%P6uPu)qOD0bx4arV#hN<a*%C*y2o
z`77lV-g*IYrLU1@DHV$|FHJA|{o|Hg3HyEN88|FJh3-lpQM@<$x8YUL@%s*?C`zEf
zdI8!ieV<?oIavE{Tf7bmtQX*-(7f+Qw_P~+3P4o8c4vT3SAzj(IR;!E9@Yzx^L%wW
zMf7t0@iU&&6ouc{9OYHR(@-Lx!yEo{dg^-6y|p(cw<A*%f%zdSVS?&^0|R?M41)WH
z3@8e?NsF-4pd$W4Xa2o$!5^#(C@<u<O)2z1qkhZ+&M>?UaZ{&lp?Hykk0rm)b+g1Q
zASCk4FU(xHOA)RGweuS@MqvS(3<6)6sSdgwR4lNlSihG>JwWD3C|UIYvQG&$3o@rO
zCRgk1m&CmSN-}c@79c?HHFz|LH}*o@roz+E1Q|Tn5c2jEr2rI;axTk6e^sYaz|-UZ
zH-QO2^k{sz74<!-%14y`{j+^E_tpnbXmRopFfSnI`uRS7y#MpsuMiRKn{yXdnsr&G
z1M3;2CcaPV5vEYLr(dP&(Nij5*m!%oi_pzMu5+;cC69>=!!QiPFbu=Q;yG(reAP{&
RfT{oh002ovPDHLkV1g$1iR}OY

diff --git a/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart b/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart
index de339175d..a02c51c69 100644
--- a/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart
+++ b/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart
@@ -5,30 +5,31 @@ import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:cw_bitcoin/utils.dart';
 import 'package:cw_core/hardware/hardware_account_data.dart';
 import 'package:ledger_bitcoin/ledger_bitcoin.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
 
 class BitcoinHardwareWalletService {
-  BitcoinHardwareWalletService(this.ledger, this.device);
+  BitcoinHardwareWalletService(this.ledgerConnection);
 
-  final Ledger ledger;
-  final LedgerDevice device;
+  final LedgerConnection ledgerConnection;
 
-  Future<List<HardwareAccountData>> getAvailableAccounts({int index = 0, int limit = 5}) async {
-    final bitcoinLedgerApp = BitcoinLedgerApp(ledger);
+  Future<List<HardwareAccountData>> getAvailableAccounts(
+      {int index = 0, int limit = 5}) async {
+    final bitcoinLedgerApp = BitcoinLedgerApp(ledgerConnection);
 
-    final masterFp = await bitcoinLedgerApp.getMasterFingerprint(device);
-    print(masterFp);
+    final masterFp = await bitcoinLedgerApp.getMasterFingerprint();
 
     final accounts = <HardwareAccountData>[];
     final indexRange = List.generate(limit, (i) => i + index);
 
     for (final i in indexRange) {
       final derivationPath = "m/84'/0'/$i'";
-      final xpub = await bitcoinLedgerApp.getXPubKey(device, derivationPath: derivationPath);
+      final xpub =
+          await bitcoinLedgerApp.getXPubKey(derivationPath: derivationPath);
       Bip32Slip10Secp256k1 hd =
           Bip32Slip10Secp256k1.fromExtendedKey(xpub).childKey(Bip32KeyIndex(0));
 
-      final address = generateP2WPKHAddress(hd: hd, index: 0, network: BitcoinNetwork.mainnet);
+      final address = generateP2WPKHAddress(
+          hd: hd, index: 0, network: BitcoinNetwork.mainnet);
 
       accounts.add(HardwareAccountData(
         address: address,
diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart
index 30f04667a..908897845 100644
--- a/cw_bitcoin/lib/bitcoin_wallet.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet.dart
@@ -5,13 +5,13 @@ import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:cw_bitcoin/bitcoin_address_record.dart';
 import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
+import 'package:cw_bitcoin/psbt_transaction_builder.dart';
 import 'package:cw_core/encryption_file_utils.dart';
 import 'package:cw_bitcoin/electrum_derivations.dart';
 import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
 import 'package:cw_bitcoin/electrum_balance.dart';
 import 'package:cw_bitcoin/electrum_wallet.dart';
 import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
-import 'package:cw_bitcoin/psbt_transaction_builder.dart';
 import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/unspent_coins_info.dart';
 import 'package:cw_core/wallet_info.dart';
@@ -19,7 +19,7 @@ import 'package:cw_core/wallet_keys_file.dart';
 import 'package:flutter/foundation.dart';
 import 'package:hive/hive.dart';
 import 'package:ledger_bitcoin/ledger_bitcoin.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
 import 'package:mobx/mobx.dart';
 
 part 'bitcoin_wallet.g.dart';
@@ -61,8 +61,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
           initialBalance: initialBalance,
           seedBytes: seedBytes,
           encryptionFileUtils: encryptionFileUtils,
-          currency:
-              networkParam == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc,
+          currency: networkParam == BitcoinNetwork.testnet
+              ? CryptoCurrency.tbtc
+              : CryptoCurrency.btc,
           alwaysScan: alwaysScan,
         ) {
     // in a standard BIP44 wallet, mainHd derivation path = m/84'/0'/0'/0 (account 0, index unspecified here)
@@ -80,11 +81,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
       mainHd: hd,
       sideHd: accountHD.childKey(Bip32KeyIndex(1)),
       network: networkParam ?? network,
-      masterHd: seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null,
+      masterHd:
+          seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null,
+      isHardwareWallet: walletInfo.isHardwareWallet,
     );
 
     autorun((_) {
-      this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
+      this.walletAddresses.isEnabledAutoGenerateSubaddress =
+          this.isEnabledAutoGenerateSubaddress;
     });
   }
 
@@ -185,8 +189,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
     walletInfo.derivationInfo ??= DerivationInfo();
 
     // set the default if not present:
-    walletInfo.derivationInfo!.derivationPath ??= snp?.derivationPath ?? electrum_path;
-    walletInfo.derivationInfo!.derivationType ??= snp?.derivationType ?? DerivationType.electrum;
+    walletInfo.derivationInfo!.derivationPath ??=
+        snp?.derivationPath ?? electrum_path;
+    walletInfo.derivationInfo!.derivationType ??=
+        snp?.derivationType ?? DerivationType.electrum;
 
     Uint8List? seedBytes = null;
     final mnemonic = keysData.mnemonic;
@@ -228,15 +234,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
     );
   }
 
-  Ledger? _ledger;
-  LedgerDevice? _ledgerDevice;
+  LedgerConnection? _ledgerConnection;
   BitcoinLedgerApp? _bitcoinLedgerApp;
 
-  void setLedger(Ledger setLedger, LedgerDevice setLedgerDevice) {
-    _ledger = setLedger;
-    _ledgerDevice = setLedgerDevice;
-    _bitcoinLedgerApp =
-        BitcoinLedgerApp(_ledger!, derivationPath: walletInfo.derivationInfo!.derivationPath!);
+  @override
+  void setLedgerConnection(LedgerConnection connection) {
+    _ledgerConnection = connection;
+    _bitcoinLedgerApp = BitcoinLedgerApp(_ledgerConnection!,
+        derivationPath: walletInfo.derivationInfo!.derivationPath!);
   }
 
   @override
@@ -251,12 +256,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
     BitcoinOrdering inputOrdering = BitcoinOrdering.bip69,
     BitcoinOrdering outputOrdering = BitcoinOrdering.bip69,
   }) async {
-    final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint(_ledgerDevice!);
+    final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint();
 
     final psbtReadyInputs = <PSBTReadyUtxoWithAddress>[];
     for (final utxo in utxos) {
-      final rawTx = await electrumClient.getTransactionHex(hash: utxo.utxo.txHash);
-      final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
+      final rawTx =
+          await electrumClient.getTransactionHex(hash: utxo.utxo.txHash);
+      final publicKeyAndDerivationPath =
+          publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
 
       psbtReadyInputs.add(PSBTReadyUtxoWithAddress(
         utxo: utxo.utxo,
@@ -268,10 +275,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
       ));
     }
 
-    final psbt =
-        PSBTTransactionBuild(inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF);
+    final psbt = PSBTTransactionBuild(
+        inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF);
 
-    final rawHex = await _bitcoinLedgerApp!.signPsbt(_ledgerDevice!, psbt: psbt.psbt);
+    final rawHex = await _bitcoinLedgerApp!.signPsbt(psbt: psbt.psbt);
     return BtcTransaction.fromRaw(BytesUtils.toHexString(rawHex));
   }
 
@@ -279,14 +286,16 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
   Future<String> signMessage(String message, {String? address = null}) async {
     if (walletInfo.isHardwareWallet) {
       final addressEntry = address != null
-          ? walletAddresses.allAddresses.firstWhere((element) => element.address == address)
+          ? walletAddresses.allAddresses
+              .firstWhere((element) => element.address == address)
           : null;
       final index = addressEntry?.index ?? 0;
       final isChange = addressEntry?.isHidden == true ? 1 : 0;
       final accountPath = walletInfo.derivationInfo?.derivationPath;
-      final derivationPath = accountPath != null ? "$accountPath/$isChange/$index" : null;
+      final derivationPath =
+          accountPath != null ? "$accountPath/$isChange/$index" : null;
 
-      final signature = await _bitcoinLedgerApp!.signMessage(_ledgerDevice!,
+      final signature = await _bitcoinLedgerApp!.signMessage(
           message: ascii.encode(message), signDerivationPath: derivationPath);
       return base64Encode(signature);
     }
diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
index 697719894..04a3cae36 100644
--- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
@@ -15,6 +15,7 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
     required super.mainHd,
     required super.sideHd,
     required super.network,
+    required super.isHardwareWallet,
     super.initialAddresses,
     super.initialRegularAddressIndex,
     super.initialChangeAddressIndex,
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 4d127c248..4b80cb201 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -6,7 +6,6 @@ import 'dart:isolate';
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:cw_bitcoin/bitcoin_wallet.dart';
 import 'package:shared_preferences/shared_preferences.dart';
-import 'package:cw_core/encryption_file_utils.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:collection/collection.dart';
 import 'package:cw_bitcoin/address_from_output.dart';
@@ -26,6 +25,8 @@ import 'package:cw_bitcoin/exceptions.dart';
 import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
 import 'package:cw_bitcoin/utils.dart';
 import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/encryption_file_utils.dart';
+import 'package:cw_core/get_height_by_date.dart';
 import 'package:cw_core/node.dart';
 import 'package:cw_core/pathForWallet.dart';
 import 'package:cw_core/pending_transaction.dart';
@@ -37,10 +38,10 @@ import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_keys_file.dart';
 import 'package:cw_core/wallet_type.dart';
-import 'package:cw_core/get_height_by_date.dart';
 import 'package:cw_core/unspent_coin_type.dart';
 import 'package:flutter/foundation.dart';
 import 'package:hive/hive.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
 import 'package:mobx/mobx.dart';
 import 'package:rxdart/subjects.dart';
 import 'package:sp_scanner/sp_scanner.dart';
@@ -51,9 +52,10 @@ part 'electrum_wallet.g.dart';
 
 class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet;
 
-abstract class ElectrumWalletBase
-    extends WalletBase<ElectrumBalance, ElectrumTransactionHistory, ElectrumTransactionInfo>
-    with Store, WalletKeysFile {
+abstract class ElectrumWalletBase extends WalletBase<
+    ElectrumBalance,
+    ElectrumTransactionHistory,
+    ElectrumTransactionInfo> with Store, WalletKeysFile {
   ElectrumWalletBase({
     required String password,
     required WalletInfo walletInfo,
@@ -69,8 +71,8 @@ abstract class ElectrumWalletBase
     ElectrumBalance? initialBalance,
     CryptoCurrency? currency,
     this.alwaysScan,
-  })  : accountHD =
-            getAccountHDWallet(currency, network, seedBytes, xpub, walletInfo.derivationInfo),
+  })  : accountHD = getAccountHDWallet(
+            currency, network, seedBytes, xpub, walletInfo.derivationInfo),
         syncStatus = NotConnectedSyncStatus(),
         _password = password,
         _feeRates = <int>[],
@@ -105,8 +107,12 @@ abstract class ElectrumWalletBase
     sharedPrefs.complete(SharedPreferences.getInstance());
   }
 
-  static Bip32Slip10Secp256k1 getAccountHDWallet(CryptoCurrency? currency, BasedUtxoNetwork network,
-      Uint8List? seedBytes, String? xpub, DerivationInfo? derivationInfo) {
+  static Bip32Slip10Secp256k1 getAccountHDWallet(
+      CryptoCurrency? currency,
+      BasedUtxoNetwork network,
+      Uint8List? seedBytes,
+      String? xpub,
+      DerivationInfo? derivationInfo) {
     if (seedBytes == null && xpub == null) {
       throw Exception(
           "To create a Wallet you need either a seed or an xpub. This should not happen");
@@ -117,8 +123,9 @@ abstract class ElectrumWalletBase
         case CryptoCurrency.btc:
         case CryptoCurrency.ltc:
         case CryptoCurrency.tbtc:
-          return Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath(
-                  _hardenedDerivationPath(derivationInfo?.derivationPath ?? electrum_path))
+          return Bip32Slip10Secp256k1.fromSeed(seedBytes, getKeyNetVersion(network))
+                  .derivePath(_hardenedDerivationPath(
+                      derivationInfo?.derivationPath ?? electrum_path))
               as Bip32Slip10Secp256k1;
         case CryptoCurrency.bch:
           return bitcoinCashHDWallet(seedBytes);
@@ -127,15 +134,26 @@ abstract class ElectrumWalletBase
       }
     }
 
-    return Bip32Slip10Secp256k1.fromExtendedKey(xpub!);
+    return Bip32Slip10Secp256k1.fromExtendedKey(
+        xpub!, getKeyNetVersion(network));
   }
 
   static Bip32Slip10Secp256k1 bitcoinCashHDWallet(Uint8List seedBytes) =>
-      Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'") as Bip32Slip10Secp256k1;
+      Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'")
+          as Bip32Slip10Secp256k1;
 
   static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
       inputsCount * 68 + outputsCounts * 34 + 10;
 
+  static Bip32KeyNetVersions? getKeyNetVersion(BasedUtxoNetwork network) {
+    switch (network) {
+      case LitecoinNetwork.mainnet:
+        return Bip44Conf.litecoinMainNet.altKeyNetVer;
+      default:
+        return null;
+    }
+  }
+
   bool? alwaysScan;
 
   final Bip32Slip10Secp256k1 accountHD;
@@ -634,8 +652,9 @@ abstract class ElectrumWalletBase
       ECPrivate? privkey;
       bool? isSilentPayment = false;
 
-      final hd =
-          utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd;
+      final hd = utx.bitcoinAddressRecord.isHidden
+          ? walletAddresses.sideHd
+          : walletAddresses.mainHd;
 
       if (utx.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) {
         final unspentAddress = utx.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
@@ -833,7 +852,7 @@ abstract class ElectrumWalletBase
       inputs: utxoDetails.availableInputs,
       outputs: updatedOutputs,
     );
-    final address = RegexUtils.addressTypeFromStr(changeAddress, network);
+    final address = RegexUtils.addressTypeFromStr(changeAddress.address, network);
     updatedOutputs.add(BitcoinOutput(
       address: address,
       value: BigInt.from(amountLeftForChangeAndFee),
@@ -845,6 +864,14 @@ abstract class ElectrumWalletBase
       isChange: true,
     ));
 
+    // Get Derivation path for change Address since it is needed in Litecoin and BitcoinCash hardware Wallets
+    final changeDerivationPath =
+        "${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? "m/0'")}"
+        "/${changeAddress.isHidden ? "1" : "0"}"
+        "/${changeAddress.index}";
+    utxoDetails.publicKeys[address.pubKeyHash()] =
+        PublicKeyWithDerivationPath('', changeDerivationPath);
+
     // calcFee updates the silent payment outputs to calculate the tx size accounting
     // for taproot addresses, but if more inputs are needed to make up for fees,
     // the silent payment outputs need to be recalculated for the new inputs
@@ -1206,6 +1233,9 @@ abstract class ElectrumWalletBase
     }
   }
 
+  void setLedgerConnection(ledger.LedgerConnection connection) =>
+      throw UnimplementedError();
+
   Future<BtcTransaction> buildHardwareWalletTransaction({
     required List<BitcoinBaseOutput> outputs,
     required BigInt fee,
@@ -1563,7 +1593,9 @@ abstract class ElectrumWalletBase
 
         final btcAddress = RegexUtils.addressTypeFromStr(addressRecord.address, network);
         final privkey = generateECPrivate(
-            hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
+            hd: addressRecord.isHidden
+                ? walletAddresses.sideHd
+                : walletAddresses.mainHd,
             index: addressRecord.index,
             network: network);
 
@@ -1745,7 +1777,8 @@ abstract class ElectrumWalletBase
 
     if (height != null) {
       if (time == null && height > 0) {
-        time = (getDateByBitcoinHeight(height).millisecondsSinceEpoch / 1000).round();
+        time = (getDateByBitcoinHeight(height).millisecondsSinceEpoch / 1000)
+            .round();
       }
 
       if (confirmations == null) {
diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart
index 6c10dc615..2686d12cc 100644
--- a/cw_bitcoin/lib/electrum_wallet_addresses.dart
+++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart
@@ -36,6 +36,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
     required this.mainHd,
     required this.sideHd,
     required this.network,
+    required this.isHardwareWallet,
     List<BitcoinAddressRecord>? initialAddresses,
     Map<String, int>? initialRegularAddressIndex,
     Map<String, int>? initialChangeAddressIndex,
@@ -44,6 +45,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
     List<BitcoinAddressRecord>? initialMwebAddresses,
     Bip32Slip10Secp256k1? masterHd,
     BitcoinAddressType? initialAddressPageType,
+
   })  : _addresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? []).toSet()),
         addressesByReceiveType =
             ObservableList<BaseBitcoinAddressRecord>.of((<BitcoinAddressRecord>[]).toSet()),
@@ -112,6 +114,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
   final BasedUtxoNetwork network;
   final Bip32Slip10Secp256k1 mainHd;
   final Bip32Slip10Secp256k1 sideHd;
+  final bool isHardwareWallet;
 
   @observable
   SilentPaymentOwner? silentAddress;
@@ -240,15 +243,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
       await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
     } else if (walletInfo.type == WalletType.litecoin) {
       await _generateInitialAddresses(type: SegwitAddresType.p2wpkh);
-      if (Platform.isAndroid || Platform.isIOS) {
+      if ((Platform.isAndroid || Platform.isIOS) && !isHardwareWallet) {
         await _generateInitialAddresses(type: SegwitAddresType.mweb);
       }
     } else if (walletInfo.type == WalletType.bitcoin) {
       await _generateInitialAddresses();
-      await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
-      await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
-      await _generateInitialAddresses(type: SegwitAddresType.p2tr);
-      await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
+      if (!isHardwareWallet) {
+        await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
+        await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
+        await _generateInitialAddresses(type: SegwitAddresType.p2tr);
+        await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
+      }
     }
 
     updateAddressesByMatch();
@@ -267,7 +272,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
   }
 
   @action
-  Future<String> getChangeAddress({List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
+  Future<BitcoinAddressRecord> getChangeAddress({List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
     updateChangeAddresses();
 
     if (changeAddresses.isEmpty) {
@@ -282,7 +287,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
     }
 
     updateChangeAddresses();
-    final address = changeAddresses[currentChangeAddressIndex].address;
+    final address = changeAddresses[currentChangeAddressIndex];
     currentChangeAddressIndex += 1;
     return address;
   }
@@ -670,7 +675,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
   }
 
   Bip32Slip10Secp256k1 _getHd(bool isHidden) => isHidden ? sideHd : mainHd;
+
   bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) => addr.type == type;
+
   bool _isUnusedReceiveAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) =>
       !addr.isHidden && !addr.isUsed && addr.type == type;
 
diff --git a/cw_bitcoin/lib/litecoin_hardware_wallet_service.dart b/cw_bitcoin/lib/litecoin_hardware_wallet_service.dart
new file mode 100644
index 000000000..62840933c
--- /dev/null
+++ b/cw_bitcoin/lib/litecoin_hardware_wallet_service.dart
@@ -0,0 +1,46 @@
+import 'dart:async';
+
+import 'package:bitcoin_base/bitcoin_base.dart';
+import 'package:blockchain_utils/blockchain_utils.dart';
+import 'package:cw_bitcoin/utils.dart';
+import 'package:cw_core/hardware/hardware_account_data.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
+import 'package:ledger_litecoin/ledger_litecoin.dart';
+
+class LitecoinHardwareWalletService {
+  LitecoinHardwareWalletService(this.ledgerConnection);
+
+  final LedgerConnection ledgerConnection;
+
+  Future<List<HardwareAccountData>> getAvailableAccounts(
+      {int index = 0, int limit = 5}) async {
+    final litecoinLedgerApp = LitecoinLedgerApp(ledgerConnection);
+
+    await litecoinLedgerApp.getVersion();
+
+    final accounts = <HardwareAccountData>[];
+    final indexRange = List.generate(limit, (i) => i + index);
+    final xpubVersion = Bip44Conf.litecoinMainNet.altKeyNetVer;
+
+    for (final i in indexRange) {
+      final derivationPath = "m/84'/2'/$i'";
+      final xpub = await litecoinLedgerApp.getXPubKey(
+          accountsDerivationPath: derivationPath,
+          xPubVersion: int.parse(hex.encode(xpubVersion.public), radix: 16));
+      final hd = Bip32Slip10Secp256k1.fromExtendedKey(xpub, xpubVersion)
+          .childKey(Bip32KeyIndex(0));
+
+      final address = generateP2WPKHAddress(
+          hd: hd, index: 0, network: LitecoinNetwork.mainnet);
+
+      accounts.add(HardwareAccountData(
+        address: address,
+        accountIndex: i,
+        derivationPath: derivationPath,
+        xpub: xpub,
+      ));
+    }
+
+    return accounts;
+  }
+}
diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart
index afa8cc388..1fb39c878 100644
--- a/cw_bitcoin/lib/litecoin_wallet.dart
+++ b/cw_bitcoin/lib/litecoin_wallet.dart
@@ -1,5 +1,7 @@
 import 'dart:async';
 import 'dart:convert';
+import 'dart:typed_data';
+
 import 'package:convert/convert.dart' as convert;
 import 'dart:math';
 import 'package:collection/collection.dart';
@@ -37,6 +39,8 @@ import 'package:cw_core/wallet_keys_file.dart';
 import 'package:flutter/foundation.dart';
 import 'package:grpc/grpc.dart';
 import 'package:hive/hive.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
+import 'package:ledger_litecoin/ledger_litecoin.dart';
 import 'package:mobx/mobx.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:cw_mweb/cw_mweb.dart';
@@ -50,12 +54,13 @@ class LitecoinWallet = LitecoinWalletBase with _$LitecoinWallet;
 
 abstract class LitecoinWalletBase extends ElectrumWallet with Store {
   LitecoinWalletBase({
-    required String mnemonic,
     required String password,
     required WalletInfo walletInfo,
     required Box<UnspentCoinsInfo> unspentCoinsInfo,
-    required Uint8List seedBytes,
     required EncryptionFileUtils encryptionFileUtils,
+    Uint8List? seedBytes,
+    String? mnemonic,
+    String? xpub,
     String? passphrase,
     String? addressPageType,
     List<BitcoinAddressRecord>? initialAddresses,
@@ -68,6 +73,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
   }) : super(
           mnemonic: mnemonic,
           password: password,
+          xpub: xpub,
           walletInfo: walletInfo,
           unspentCoinsInfo: unspentCoinsInfo,
           network: LitecoinNetwork.mainnet,
@@ -78,8 +84,14 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
           currency: CryptoCurrency.ltc,
           alwaysScan: alwaysScan,
         ) {
-    mwebHd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/1000'") as Bip32Slip10Secp256k1;
-    mwebEnabled = alwaysScan ?? false;
+    if (seedBytes != null) {
+      mwebHd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath(
+          "m/1000'") as Bip32Slip10Secp256k1;
+      mwebEnabled = alwaysScan ?? false;
+    } else {
+      mwebHd = null;
+      mwebEnabled = false;
+    }
     walletAddresses = LitecoinWalletAddresses(
       walletInfo,
       initialAddresses: initialAddresses,
@@ -91,6 +103,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       network: network,
       mwebHd: mwebHd,
       mwebEnabled: mwebEnabled,
+      isHardwareWallet: walletInfo.isHardwareWallet,
     );
     autorun((_) {
       this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
@@ -126,7 +139,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       }
     });
   }
-  late final Bip32Slip10Secp256k1 mwebHd;
+  late final Bip32Slip10Secp256k1? mwebHd;
   late final Box<MwebUtxo> mwebUtxosBox;
   Timer? _syncTimer;
   Timer? _feeRatesTimer;
@@ -138,8 +151,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
   @observable
   SyncStatus mwebSyncStatus = NotConnectedSyncStatus();
 
-  List<int> get scanSecret => mwebHd.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
-  List<int> get spendSecret => mwebHd.childKey(Bip32KeyIndex(0x80000001)).privateKey.privKey.raw;
+  List<int> get scanSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
+  List<int> get spendSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000001)).privateKey.privKey.raw;
 
   static Future<LitecoinWallet> create(
       {required String mnemonic,
@@ -249,14 +262,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     }
 
     return LitecoinWallet(
-      mnemonic: keysData.mnemonic!,
+      mnemonic: keysData.mnemonic,
+      xpub: keysData.xPub,
       password: password,
       walletInfo: walletInfo,
       unspentCoinsInfo: unspentCoinsInfo,
       initialAddresses: snp?.addresses,
       initialMwebAddresses: snp?.mwebAddresses,
       initialBalance: snp?.balance,
-      seedBytes: seedBytes!,
+      seedBytes: seedBytes,
       passphrase: passphrase,
       encryptionFileUtils: encryptionFileUtils,
       initialRegularAddressIndex: snp?.regularAddressIndex,
@@ -935,7 +949,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
 
       if (!mwebEnabled) {
         tx.changeAddressOverride =
-            await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(isPegIn: false);
+            (await (walletAddresses as LitecoinWalletAddresses)
+                    .getChangeAddress(isPegIn: false))
+                .address;
         return tx;
       }
       await waitForMwebAddresses();
@@ -974,8 +990,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
 
       bool isPegIn = !hasMwebInput && hasMwebOutput;
       bool isRegular = !hasMwebInput && !hasMwebOutput;
-      tx.changeAddressOverride = await (walletAddresses as LitecoinWalletAddresses)
-          .getChangeAddress(isPegIn: isPegIn || isRegular);
+      tx.changeAddressOverride =
+          (await (walletAddresses as LitecoinWalletAddresses)
+                  .getChangeAddress(isPegIn: isPegIn || isRegular))
+              .address;
       if (!hasMwebInput && !hasMwebOutput) {
         tx.isMweb = false;
         return tx;
@@ -1215,4 +1233,64 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
 
     return false;
   }
+
+  LedgerConnection? _ledgerConnection;
+  LitecoinLedgerApp? _litecoinLedgerApp;
+
+  @override
+  void setLedgerConnection(LedgerConnection connection) {
+    _ledgerConnection = connection;
+    _litecoinLedgerApp =
+        LitecoinLedgerApp(_ledgerConnection!, derivationPath: walletInfo.derivationInfo!.derivationPath!);
+  }
+
+  @override
+  Future<BtcTransaction> buildHardwareWalletTransaction({
+    required List<BitcoinBaseOutput> outputs,
+    required BigInt fee,
+    required BasedUtxoNetwork network,
+    required List<UtxoWithAddress> utxos,
+    required Map<String, PublicKeyWithDerivationPath> publicKeys,
+    String? memo,
+    bool enableRBF = false,
+    BitcoinOrdering inputOrdering = BitcoinOrdering.bip69,
+    BitcoinOrdering outputOrdering = BitcoinOrdering.bip69,
+  }) async {
+    final readyInputs = <LedgerTransaction>[];
+    for (final utxo in utxos) {
+      final rawTx = await electrumClient.getTransactionHex(hash: utxo.utxo.txHash);
+      final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
+
+      readyInputs.add(LedgerTransaction(
+        rawTx: rawTx,
+        outputIndex: utxo.utxo.vout,
+        ownerPublicKey: Uint8List.fromList(hex.decode(publicKeyAndDerivationPath.publicKey)),
+        ownerDerivationPath: publicKeyAndDerivationPath.derivationPath,
+        // sequence: enableRBF ? 0x1 : 0xffffffff,
+        sequence: 0xffffffff,
+      ));
+    }
+
+    String? changePath;
+    for (final output in outputs) {
+      final maybeChangePath = publicKeys[(output as BitcoinOutput).address.pubKeyHash()];
+      if (maybeChangePath != null) changePath ??= maybeChangePath.derivationPath;
+    }
+
+
+    final rawHex = await _litecoinLedgerApp!.createTransaction(
+      inputs: readyInputs,
+      outputs: outputs
+          .map((e) => TransactionOutput.fromBigInt(
+              (e as BitcoinOutput).value, Uint8List.fromList(e.address.toScriptPubKey().toBytes())))
+          .toList(),
+      changePath: changePath,
+      sigHashType: 0x01,
+      additionals: ["bech32"],
+      isSegWit: true,
+      useTrustedInputForSegwit: true
+    );
+
+    return BtcTransaction.fromRaw(rawHex);
+  }
 }
diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
index 6154a0ead..c55f5fc76 100644
--- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
@@ -16,14 +16,17 @@ import 'package:mobx/mobx.dart';
 
 part 'litecoin_wallet_addresses.g.dart';
 
-class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses;
+class LitecoinWalletAddresses = LitecoinWalletAddressesBase
+    with _$LitecoinWalletAddresses;
 
-abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
+abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
+    with Store {
   LitecoinWalletAddressesBase(
     WalletInfo walletInfo, {
     required super.mainHd,
     required super.sideHd,
     required super.network,
+    required super.isHardwareWallet,
     required this.mwebHd,
     required this.mwebEnabled,
     super.initialAddresses,
@@ -37,20 +40,20 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
     print("initialized with ${mwebAddrs.length} mweb addresses");
   }
 
-  final Bip32Slip10Secp256k1 mwebHd;
+  final Bip32Slip10Secp256k1? mwebHd;
   bool mwebEnabled;
   int mwebTopUpIndex = 1000;
   List<String> mwebAddrs = [];
   bool generating = false;
 
-  List<int> get scanSecret => mwebHd.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
-
+  List<int> get scanSecret =>
+      mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
   List<int> get spendPubkey =>
-      mwebHd.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
+      mwebHd!.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
 
   @override
   Future<void> init() async {
-    await initMwebAddresses();
+    if (!isHardwareWallet) await initMwebAddresses();
     await super.init();
   }
 
@@ -94,6 +97,9 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
     print("Done generating MWEB addresses len: ${mwebAddrs.length}");
 
     // ensure mweb addresses are up to date:
+    // This is the Case if the Litecoin Wallet is a hardware Wallet
+    if (mwebHd == null) return;
+
     if (mwebAddresses.length < mwebAddrs.length) {
       List<BitcoinAddressRecord> addressRecords = mwebAddrs
           .asMap()
@@ -143,7 +149,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
 
   @action
   @override
-  Future<String> getChangeAddress(
+  Future<BitcoinAddressRecord> getChangeAddress(
       {List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
     // use regular change address on peg in, otherwise use mweb for change address:
 
@@ -187,7 +193,12 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
 
     if (mwebEnabled) {
       await ensureMwebAddressUpToIndexExists(1);
-      return mwebAddrs[0];
+      return BitcoinAddressRecord(
+        mwebAddrs[0],
+        index: 0,
+        type: SegwitAddresType.mweb,
+        network: network,
+      );
     }
 
     return super.getChangeAddress();
diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart
index c659dd658..7cc266f5b 100644
--- a/cw_bitcoin/lib/litecoin_wallet_service.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_service.dart
@@ -1,4 +1,5 @@
 import 'dart:io';
+import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
 import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
 import 'package:cw_core/encryption_file_utils.dart';
@@ -20,7 +21,7 @@ class LitecoinWalletService extends WalletService<
     BitcoinNewWalletCredentials,
     BitcoinRestoreWalletFromSeedCredentials,
     BitcoinRestoreWalletFromWIFCredentials,
-    BitcoinNewWalletCredentials> {
+    BitcoinRestoreWalletFromHardware> {
   LitecoinWalletService(
       this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan, this.isDirect);
 
@@ -147,9 +148,23 @@ class LitecoinWalletService extends WalletService<
   }
 
   @override
-  Future<LitecoinWallet> restoreFromHardwareWallet(BitcoinNewWalletCredentials credentials) {
-    throw UnimplementedError(
-        "Restoring a Litecoin wallet from a hardware wallet is not yet supported!");
+  Future<LitecoinWallet> restoreFromHardwareWallet(BitcoinRestoreWalletFromHardware credentials,
+      {bool? isTestnet}) async {
+    final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
+    credentials.walletInfo?.network = network.value;
+    credentials.walletInfo?.derivationInfo?.derivationPath =
+        credentials.hwAccountData.derivationPath;
+
+    final wallet = await LitecoinWallet(
+      password: credentials.password!,
+      xpub: credentials.hwAccountData.xpub,
+      walletInfo: credentials.walletInfo!,
+      unspentCoinsInfo: unspentCoinsInfoSource,
+      encryptionFileUtils: encryptionFileUtilsFor(isDirect),
+    );
+    await wallet.save();
+    await wallet.init();
+    return wallet;
   }
 
   @override
diff --git a/cw_bitcoin/lib/psbt_transaction_builder.dart b/cw_bitcoin/lib/psbt_transaction_builder.dart
index d8d2c9fac..81efb792e 100644
--- a/cw_bitcoin/lib/psbt_transaction_builder.dart
+++ b/cw_bitcoin/lib/psbt_transaction_builder.dart
@@ -16,10 +16,6 @@ class PSBTTransactionBuild {
     for (var i = 0; i < inputs.length; i++) {
       final input = inputs[i];
 
-      print(input.utxo.isP2tr());
-      print(input.utxo.isSegwit());
-      print(input.utxo.isP2shSegwit());
-
       psbt.setInputPreviousTxId(i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList()));
       psbt.setInputOutputIndex(i, input.utxo.vout);
       psbt.setInputSequence(i, enableRBF ? 0x1 : 0xffffffff);
diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock
index 36d762ea1..5cba9b734 100644
--- a/cw_bitcoin/pubspec.lock
+++ b/cw_bitcoin/pubspec.lock
@@ -101,6 +101,14 @@ packages:
       url: "https://github.com/cake-tech/blockchain_utils"
     source: git
     version: "3.3.0"
+  bluez:
+    dependency: transitive
+    description:
+      name: bluez
+      sha256: "203a1924e818a9dd74af2b2c7a8f375ab8e5edf0e486bba8f90a0d8a17ed9fce"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.8.2"
   boolean_selector:
     dependency: transitive
     description:
@@ -300,6 +308,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.3"
+  dbus:
+    dependency: transitive
+    description:
+      name: dbus
+      sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.7.10"
   encrypt:
     dependency: transitive
     description:
@@ -361,19 +377,19 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.2.1+1"
-  flutter_reactive_ble:
-    dependency: transitive
-    description:
-      name: flutter_reactive_ble
-      sha256: "247e2efa76de203d1ba11335c13754b5b9d0504b5423e5b0c93a600f016b24e0"
-      url: "https://pub.dev"
-    source: hosted
-    version: "5.3.1"
   flutter_test:
     dependency: "direct dev"
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_web_bluetooth:
+    dependency: transitive
+    description:
+      name: flutter_web_bluetooth
+      sha256: "52ce64f65d7321c4bf6abfe9dac02fb888731339a5e0ad6de59fb916c20c9f02"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.2.3"
   flutter_web_plugins:
     dependency: transitive
     description: flutter
@@ -387,14 +403,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "4.0.0"
-  functional_data:
-    dependency: transitive
-    description:
-      name: functional_data
-      sha256: "76d17dc707c40e552014f5a49c0afcc3f1e3f05e800cd6b7872940bfe41a5039"
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.2.0"
   glob:
     dependency: transitive
     description:
@@ -550,29 +558,37 @@ packages:
   ledger_bitcoin:
     dependency: "direct main"
     description:
-      path: "."
+      path: "packages/ledger-bitcoin"
       ref: HEAD
-      resolved-ref: f819d37e235e239c315e93856abbf5e5d3b71dab
-      url: "https://github.com/cake-tech/ledger-bitcoin"
+      resolved-ref: dbb5c4956949dc734af3fc8febdbabed89da72aa
+      url: "https://github.com/cake-tech/ledger-flutter-plus-plugins"
     source: git
-    version: "0.0.2"
-  ledger_flutter:
+    version: "0.0.3"
+  ledger_flutter_plus:
     dependency: "direct main"
     description:
-      path: "."
-      ref: cake-v3
-      resolved-ref: "66469ff9dffe2417c70ae7287c9d76d2fe7157a4"
-      url: "https://github.com/cake-tech/ledger-flutter.git"
-    source: git
-    version: "1.0.2"
-  ledger_usb:
-    dependency: transitive
-    description:
-      name: ledger_usb
-      sha256: "52c92d03a4cffe06c82921c8e2f79f3cdad6e1cf78e1e9ca35444196ff8f14c2"
+      name: ledger_flutter_plus
+      sha256: ea3ed586e1697776dacf42ac979095f1ca3bd143bf007cbe5c78e09cb6943f42
       url: "https://pub.dev"
     source: hosted
-    version: "1.0.0"
+    version: "1.2.5"
+  ledger_litecoin:
+    dependency: "direct main"
+    description:
+      path: "packages/ledger-litecoin"
+      ref: HEAD
+      resolved-ref: dbb5c4956949dc734af3fc8febdbabed89da72aa
+      url: "https://github.com/cake-tech/ledger-flutter-plus-plugins"
+    source: git
+    version: "0.0.2"
+  ledger_usb_plus:
+    dependency: transitive
+    description:
+      name: ledger_usb_plus
+      sha256: "21cc5d976cf7edb3518bd2a0c4164139cbb0817d2e4f2054707fc4edfdf9ce87"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.4"
   logging:
     dependency: transitive
     description:
@@ -701,6 +717,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.3.0"
+  petitparser:
+    dependency: transitive
+    description:
+      name: petitparser
+      sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
+      url: "https://pub.dev"
+    source: hosted
+    version: "6.0.2"
   platform:
     dependency: transitive
     description:
@@ -773,30 +797,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "3.2.2"
-  reactive_ble_mobile:
-    dependency: transitive
-    description:
-      name: reactive_ble_mobile
-      sha256: "9ec2b4c9c725e439950838d551579750060258fbccd5536d0543b4d07d225798"
-      url: "https://pub.dev"
-    source: hosted
-    version: "5.3.1"
-  reactive_ble_platform_interface:
-    dependency: transitive
-    description:
-      name: reactive_ble_platform_interface
-      sha256: "632c92401a2d69c9b94bd48f8fd47488a7013f3d1f9b291884350291a4a81813"
-      url: "https://pub.dev"
-    source: hosted
-    version: "5.3.1"
   rxdart:
     dependency: "direct main"
     description:
       name: rxdart
-      sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
+      sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
       url: "https://pub.dev"
     source: hosted
-    version: "0.27.7"
+    version: "0.28.0"
   shared_preferences:
     dependency: "direct main"
     description:
@@ -987,6 +995,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.2"
+  universal_ble:
+    dependency: transitive
+    description:
+      name: universal_ble
+      sha256: "0dfbd6b64bff3ad61ed7a895c232530d9614e9b01ab261a74433a43267edb7f3"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.12.0"
+  universal_platform:
+    dependency: transitive
+    description:
+      name: universal_platform
+      sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.0"
   unorm_dart:
     dependency: transitive
     description:
@@ -1043,6 +1067,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.1.0"
+  xml:
+    dependency: transitive
+    description:
+      name: xml
+      sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
+      url: "https://pub.dev"
+    source: hosted
+    version: "6.5.0"
   yaml:
     dependency: transitive
     description:
diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml
index 7e33d8260..9f1cee67d 100644
--- a/cw_bitcoin/pubspec.yaml
+++ b/cw_bitcoin/pubspec.yaml
@@ -24,16 +24,12 @@ dependencies:
     git:
       url: https://github.com/cake-tech/bitbox-flutter.git
       ref: Add-Support-For-OP-Return-data
-  rxdart: ^0.27.5
+  rxdart: ^0.28.0
   cryptography: ^2.0.5
   blockchain_utils:
     git:
       url: https://github.com/cake-tech/blockchain_utils
       ref: cake-update-v2
-  ledger_flutter: ^1.0.1
-  ledger_bitcoin:
-    git:
-      url: https://github.com/cake-tech/ledger-bitcoin
   cw_mweb:
     path: ../cw_mweb
   grpc: ^3.2.4
@@ -44,6 +40,15 @@ dependencies:
   bech32:
     git:
       url: https://github.com/cake-tech/bech32.git
+  ledger_flutter_plus: ^1.4.1
+  ledger_bitcoin:
+    git:
+      url: https://github.com/cake-tech/ledger-flutter-plus-plugins
+      path: packages/ledger-bitcoin
+  ledger_litecoin:
+    git:
+      url: https://github.com/cake-tech/ledger-flutter-plus-plugins
+      path: packages/ledger-litecoin
 
 dev_dependencies:
   flutter_test:
@@ -54,10 +59,6 @@ dev_dependencies:
   hive_generator: ^1.1.3
 
 dependency_overrides:
-  ledger_flutter:
-    git:
-      url: https://github.com/cake-tech/ledger-flutter.git
-      ref: cake-v3
   watcher: ^1.1.0
   protobuf: ^3.1.0
   bitcoin_base:
diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart
index 825c80d4a..d55914dcd 100644
--- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart
+++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart
@@ -58,6 +58,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
       sideHd: accountHD.childKey(Bip32KeyIndex(1)),
       network: network,
       initialAddressPageType: addressPageType,
+      isHardwareWallet: walletInfo.isHardwareWallet,
     );
     autorun((_) {
       this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart
index 7342dc7f5..fe0ebc828 100644
--- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart
+++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart
@@ -15,6 +15,7 @@ abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses wi
     required super.mainHd,
     required super.sideHd,
     required super.network,
+    required super.isHardwareWallet,
     super.initialAddresses,
     super.initialRegularAddressIndex,
     super.initialChangeAddressIndex,
diff --git a/cw_core/lib/hardware/device_connection_type.dart b/cw_core/lib/hardware/device_connection_type.dart
index 99fd5b1f0..9a3069552 100644
--- a/cw_core/lib/hardware/device_connection_type.dart
+++ b/cw_core/lib/hardware/device_connection_type.dart
@@ -8,6 +8,7 @@ enum DeviceConnectionType {
       [bool isIOS = false]) {
     switch (walletType) {
       case WalletType.bitcoin:
+      case WalletType.litecoin:
       case WalletType.ethereum:
       case WalletType.polygon:
         if (isIOS) return [DeviceConnectionType.ble];
diff --git a/cw_evm/lib/evm_chain_hardware_wallet_service.dart b/cw_evm/lib/evm_chain_hardware_wallet_service.dart
index 6f0d11f2e..d8f67c641 100644
--- a/cw_evm/lib/evm_chain_hardware_wallet_service.dart
+++ b/cw_evm/lib/evm_chain_hardware_wallet_service.dart
@@ -2,26 +2,26 @@ import 'dart:async';
 
 import 'package:cw_core/hardware/hardware_account_data.dart';
 import 'package:ledger_ethereum/ledger_ethereum.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
 
 class EVMChainHardwareWalletService {
-  EVMChainHardwareWalletService(this.ledger, this.device);
+  EVMChainHardwareWalletService(this.ledgerConnection);
 
-  final Ledger ledger;
-  final LedgerDevice device;
+  final LedgerConnection ledgerConnection;
 
-  Future<List<HardwareAccountData>> getAvailableAccounts({int index = 0, int limit = 5}) async {
-    final ethereumLedgerApp = EthereumLedgerApp(ledger);
+  Future<List<HardwareAccountData>> getAvailableAccounts(
+      {int index = 0, int limit = 5}) async {
+    final ethereumLedgerApp = EthereumLedgerApp(ledgerConnection);
 
-    final version = await ethereumLedgerApp.getVersion(device);
+    await ethereumLedgerApp.getVersion();
 
     final accounts = <HardwareAccountData>[];
     final indexRange = List.generate(limit, (i) => i + index);
 
     for (final i in indexRange) {
       final derivationPath = "m/44'/60'/$i'/0/0";
-      final address =
-          await ethereumLedgerApp.getAccounts(device, accountsDerivationPath: derivationPath);
+      final address = await ethereumLedgerApp.getAccounts(
+          accountsDerivationPath: derivationPath);
 
       accounts.add(HardwareAccountData(
         address: address.first,
diff --git a/cw_evm/lib/evm_chain_transaction_credentials.dart b/cw_evm/lib/evm_chain_transaction_credentials.dart
index 02927cb4d..5b5bdf170 100644
--- a/cw_evm/lib/evm_chain_transaction_credentials.dart
+++ b/cw_evm/lib/evm_chain_transaction_credentials.dart
@@ -1,7 +1,6 @@
 import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/output_info.dart';
 import 'package:cw_evm/evm_chain_transaction_priority.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
 
 class EVMChainTransactionCredentials {
   EVMChainTransactionCredentials(
diff --git a/cw_evm/lib/evm_ledger_credentials.dart b/cw_evm/lib/evm_ledger_credentials.dart
index 0d8de1736..a0b7788dc 100644
--- a/cw_evm/lib/evm_ledger_credentials.dart
+++ b/cw_evm/lib/evm_ledger_credentials.dart
@@ -1,17 +1,16 @@
 import 'dart:async';
 import 'dart:typed_data';
 
-import 'package:cw_core/hardware/device_not_connected_exception.dart';
+import 'package:cw_core/hardware/device_not_connected_exception.dart'
+    as exception;
 import 'package:ledger_ethereum/ledger_ethereum.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
 import 'package:web3dart/crypto.dart';
 import 'package:web3dart/web3dart.dart';
 
 class EvmLedgerCredentials extends CredentialsWithKnownAddress {
   final String _address;
 
-  Ledger? ledger;
-  LedgerDevice? ledgerDevice;
   EthereumLedgerApp? ethereumLedgerApp;
 
   EvmLedgerCredentials(this._address);
@@ -19,25 +18,25 @@ class EvmLedgerCredentials extends CredentialsWithKnownAddress {
   @override
   EthereumAddress get address => EthereumAddress.fromHex(_address);
 
-  void setLedger(Ledger setLedger, [LedgerDevice? setLedgerDevice, String? derivationPath]) {
-    ledger = setLedger;
-    ledgerDevice = setLedgerDevice;
-    ethereumLedgerApp =
-        EthereumLedgerApp(ledger!, derivationPath: derivationPath ?? "m/44'/60'/0'/0/0");
+  void setLedgerConnection(LedgerConnection connection,
+      [String? derivationPath]) {
+    ethereumLedgerApp = EthereumLedgerApp(connection,
+        derivationPath: derivationPath ?? "m/44'/60'/0'/0/0");
   }
 
   @override
-  MsgSignature signToEcSignature(Uint8List payload, {int? chainId, bool isEIP1559 = false}) =>
-    throw UnimplementedError("EvmLedgerCredentials.signToEcSignature");
+  MsgSignature signToEcSignature(Uint8List payload,
+          {int? chainId, bool isEIP1559 = false}) =>
+      throw UnimplementedError("EvmLedgerCredentials.signToEcSignature");
 
   @override
   Future<MsgSignature> signToSignature(Uint8List payload,
       {int? chainId, bool isEIP1559 = false}) async {
-    if (ledgerDevice == null && ledger?.devices.isNotEmpty != true) {
-      throw DeviceNotConnectedException();
+    if (ethereumLedgerApp == null) {
+      throw exception.DeviceNotConnectedException();
     }
 
-    final sig = await ethereumLedgerApp!.signTransaction(device, payload);
+    final sig = await ethereumLedgerApp!.signTransaction(payload);
 
     final v = sig[0].toInt();
     final r = bytesToHex(sig.sublist(1, 1 + 32));
@@ -65,14 +64,16 @@ class EvmLedgerCredentials extends CredentialsWithKnownAddress {
       chainIdV = chainId != null ? (parity + (chainId * 2 + 35)) : parity;
     }
 
-    return MsgSignature(BigInt.parse(r, radix: 16), BigInt.parse(s, radix: 16), chainIdV);
+    return MsgSignature(
+        BigInt.parse(r, radix: 16), BigInt.parse(s, radix: 16), chainIdV);
   }
 
   @override
-  Future<Uint8List> signPersonalMessage(Uint8List payload, {int? chainId}) async {
-    if (isNotConnected) throw DeviceNotConnectedException();
+  Future<Uint8List> signPersonalMessage(Uint8List payload,
+      {int? chainId}) async {
+    if (isNotConnected) throw exception.DeviceNotConnectedException();
 
-    final sig = await ethereumLedgerApp!.signMessage(device, payload);
+    final sig = await ethereumLedgerApp!.signMessage(payload);
 
     final r = sig.sublist(1, 1 + 32);
     final s = sig.sublist(1 + 32, 1 + 32 + 32);
@@ -84,20 +85,22 @@ class EvmLedgerCredentials extends CredentialsWithKnownAddress {
 
   @override
   Uint8List signPersonalMessageToUint8List(Uint8List payload, {int? chainId}) =>
-    throw UnimplementedError("EvmLedgerCredentials.signPersonalMessageToUint8List");
+      throw UnimplementedError(
+          "EvmLedgerCredentials.signPersonalMessageToUint8List");
 
-  Future<void> provideERC20Info(String erc20ContractAddress, int chainId) async {
-    if (isNotConnected) throw DeviceNotConnectedException();
+  Future<void> provideERC20Info(
+      String erc20ContractAddress, int chainId) async {
+    if (isNotConnected) throw exception.DeviceNotConnectedException();
 
     try {
-      await ethereumLedgerApp!.getAndProvideERC20TokenInformation(device,
+      await ethereumLedgerApp!.getAndProvideERC20TokenInformation(
           erc20ContractAddress: erc20ContractAddress, chainId: chainId);
-    } on LedgerException catch (e) {
-      if (e.errorCode != -28672) rethrow;
+    } catch (e) {
+      print(e);
+      rethrow;
+      // if (e.errorCode != -28672) rethrow;
     }
   }
 
-  bool get isNotConnected => (ledgerDevice ?? ledger?.devices.firstOrNull) == null;
-
-  LedgerDevice get device => ledgerDevice ?? ledger!.devices.first;
+  bool get isNotConnected => ethereumLedgerApp == null || ethereumLedgerApp!.connection.isDisconnected;
 }
diff --git a/cw_evm/pubspec.yaml b/cw_evm/pubspec.yaml
index 3e12834b1..326ff4dc9 100644
--- a/cw_evm/pubspec.yaml
+++ b/cw_evm/pubspec.yaml
@@ -25,20 +25,17 @@ dependencies:
   mobx: ^2.0.7+4
   cw_core:
     path: ../cw_core
-  ledger_flutter: ^1.0.1
+  ledger_flutter_plus: ^1.4.1
   ledger_ethereum:
     git:
-      url: https://github.com/cake-tech/ledger-ethereum.git
+      url: https://github.com/cake-tech/ledger-flutter-plus-plugins
+      path: packages/ledger-ethereum
 
 dependency_overrides:
   web3dart:
     git:
       url: https://github.com/cake-tech/web3dart.git
       ref: cake
-  ledger_flutter:
-    git:
-      url: https://github.com/cake-tech/ledger-flutter.git
-      ref: cake-v3
   watcher: ^1.1.0
 
 dev_dependencies:
diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart
index 365d86be5..60364c289 100644
--- a/lib/bitcoin/cw_bitcoin.dart
+++ b/lib/bitcoin/cw_bitcoin.dart
@@ -487,18 +487,30 @@ class CWBitcoin extends Bitcoin {
   }
 
   @override
-  void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device) {
-    (wallet as BitcoinWallet).setLedger(ledger, device);
+  void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection) {
+    (wallet as ElectrumWallet).setLedgerConnection(connection);
   }
 
   @override
-  Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM,
+  Future<List<HardwareAccountData>> getHardwareWalletBitcoinAccounts(LedgerViewModel ledgerVM,
       {int index = 0, int limit = 5}) async {
-    final hardwareWalletService = BitcoinHardwareWalletService(ledgerVM.ledger, ledgerVM.device);
+    final hardwareWalletService = BitcoinHardwareWalletService(ledgerVM.connection);
     try {
       return hardwareWalletService.getAvailableAccounts(index: index, limit: limit);
-    } on LedgerException catch (err) {
-      print(err.message);
+    } catch (err) {
+      print(err);
+      throw err;
+    }
+  }
+
+  @override
+  Future<List<HardwareAccountData>> getHardwareWalletLitecoinAccounts(LedgerViewModel ledgerVM,
+      {int index = 0, int limit = 5}) async {
+    final hardwareWalletService = LitecoinHardwareWalletService(ledgerVM.connection);
+    try {
+      return hardwareWalletService.getAvailableAccounts(index: index, limit: limit);
+    } catch (err) {
+      print(err);
       throw err;
     }
   }
diff --git a/lib/entities/hardware_wallet/hardware_wallet_device.dart b/lib/entities/hardware_wallet/hardware_wallet_device.dart
new file mode 100644
index 000000000..d3acc5d32
--- /dev/null
+++ b/lib/entities/hardware_wallet/hardware_wallet_device.dart
@@ -0,0 +1,65 @@
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
+
+class HardwareWalletDevice {
+  final String name;
+  final HardwareWalletDeviceType type;
+  final HardwareWalletConnectionType connectionType;
+
+  const HardwareWalletDevice({
+    required this.name,
+    required this.type,
+    required this.connectionType,
+  });
+
+  factory HardwareWalletDevice.fromLedgerDevice(ledger.LedgerDevice device) =>
+      HardwareWalletDevice(
+        name: device.name,
+        type: device.deviceInfo.toGeneric(),
+        connectionType: device.connectionType.toGeneric(),
+      );
+}
+
+enum HardwareWalletDeviceType {
+  ledgerBlue,
+  ledgerNanoS,
+  ledgerNanoX,
+  ledgerNanoSPlus,
+  ledgerStax,
+  ledgerFlex;
+}
+
+enum HardwareWalletConnectionType {
+  usb,
+  ble,
+  nfc;
+}
+
+extension ToGenericHardwareWalletDeviceType on ledger.LedgerDeviceType {
+  HardwareWalletDeviceType toGeneric() {
+    switch (this) {
+      case ledger.LedgerDeviceType.blue:
+        return HardwareWalletDeviceType.ledgerBlue;
+      case ledger.LedgerDeviceType.nanoS:
+        return HardwareWalletDeviceType.ledgerNanoS;
+      case ledger.LedgerDeviceType.nanoSP:
+        return HardwareWalletDeviceType.ledgerNanoSPlus;
+      case ledger.LedgerDeviceType.nanoX:
+        return HardwareWalletDeviceType.ledgerNanoX;
+      case ledger.LedgerDeviceType.stax:
+        return HardwareWalletDeviceType.ledgerStax;
+      case ledger.LedgerDeviceType.flex:
+        return HardwareWalletDeviceType.ledgerFlex;
+    }
+  }
+}
+
+extension ToGenericHardwareWalletConnectionType on ledger.ConnectionType {
+  HardwareWalletConnectionType toGeneric() {
+    switch (this) {
+      case ledger.ConnectionType.usb:
+        return HardwareWalletConnectionType.usb;
+      case ledger.ConnectionType.ble:
+        return HardwareWalletConnectionType.ble;
+    }
+  }
+}
diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart
index e2c3d1358..7a06a1679 100644
--- a/lib/ethereum/cw_ethereum.dart
+++ b/lib/ethereum/cw_ethereum.dart
@@ -191,21 +191,21 @@ class CWEthereum extends Ethereum {
   String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
 
   @override
-  void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device) {
-    ((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials).setLedger(
-        ledger,
-        device.connectionType == ConnectionType.usb ? device : null,
-        wallet.walletInfo.derivationInfo?.derivationPath);
+  void setLedgerConnection(
+      WalletBase wallet, ledger.LedgerConnection connection) {
+    ((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials)
+        .setLedgerConnection(
+            connection, wallet.walletInfo.derivationInfo?.derivationPath);
   }
 
   @override
   Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM,
       {int index = 0, int limit = 5}) async {
-    final hardwareWalletService = EVMChainHardwareWalletService(ledgerVM.ledger, ledgerVM.device);
+    final hardwareWalletService = EVMChainHardwareWalletService(ledgerVM.connection);
     try {
       return await hardwareWalletService.getAvailableAccounts(index: index, limit: limit);
-    } on LedgerException catch (err) {
-      print(err.message);
+    } catch (err) {
+      print(err);
       throw err;
     }
   }
diff --git a/lib/main.dart b/lib/main.dart
index 2b5bef06c..29b216b22 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,4 +1,5 @@
 import 'dart:async';
+import 'dart:io';
 import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
 import 'package:cake_wallet/app_scroll_behavior.dart';
 import 'package:cake_wallet/buy/order.dart';
@@ -43,6 +44,7 @@ import 'package:hive/hive.dart';
 import 'package:cw_core/root_dir.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:cw_core/window_size.dart';
+import 'package:logging/logging.dart';
 
 final navigatorKey = GlobalKey<NavigatorState>();
 final rootKey = GlobalKey<RootState>();
@@ -68,8 +70,18 @@ Future<void> runAppWithZone({Key? topLevelKey}) async {
     };
     await initializeAppAtRoot();
 
-    runApp(App(key: topLevelKey));
+    if (kDebugMode) {
+      final appDocDir = await getAppDir();
 
+      final ledgerFile = File('${appDocDir.path}/ledger_log.txt');
+      if (!ledgerFile.existsSync()) ledgerFile.createSync();
+      Logger.root.onRecord.listen((event) async {
+        final content = ledgerFile.readAsStringSync();
+        ledgerFile.writeAsStringSync("$content\n${event.message}");
+      });
+    }
+
+    runApp(App(key: topLevelKey));
     isAppRunning = true;
   }, (error, stackTrace) async {
     if (!isAppRunning) {
diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart
index 299c8278a..74b4026eb 100644
--- a/lib/polygon/cw_polygon.dart
+++ b/lib/polygon/cw_polygon.dart
@@ -190,20 +190,21 @@ class CWPolygon extends Polygon {
   String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
 
   @override
-  void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device) {
-    ((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials).setLedger(
-        ledger,
-        device.connectionType == ConnectionType.usb ? device : null,
-        wallet.walletInfo.derivationInfo?.derivationPath);
+  void setLedgerConnection(
+      WalletBase wallet, ledger.LedgerConnection connection) {
+    ((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials)
+        .setLedgerConnection(
+        connection, wallet.walletInfo.derivationInfo?.derivationPath);
   }
 
   @override
   Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM,
       {int index = 0, int limit = 5}) async {
-    final hardwareWalletService = EVMChainHardwareWalletService(ledgerVM.ledger, ledgerVM.device);
+    final hardwareWalletService = EVMChainHardwareWalletService(ledgerVM.connection);
     try {
       return await hardwareWalletService.getAvailableAccounts(index: index, limit: limit);
-    } on LedgerException catch (err) {
+    } catch (err) {
+      print(err);
       throw err;
     }
   }
diff --git a/lib/src/screens/connect_device/connect_device_page.dart b/lib/src/screens/connect_device/connect_device_page.dart
index a482b1c41..9e331e818 100644
--- a/lib/src/screens/connect_device/connect_device_page.dart
+++ b/lib/src/screens/connect_device/connect_device_page.dart
@@ -3,15 +3,14 @@ import 'dart:io';
 
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/src/screens/base_page.dart';
-import 'package:cake_wallet/src/screens/connect_device/debug_device_page.dart';
 import 'package:cake_wallet/src/screens/connect_device/widgets/device_tile.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/material.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
-import 'package:permission_handler/permission_handler.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
 
 typedef OnConnectDevice = void Function(BuildContext, LedgerViewModel);
 
@@ -19,7 +18,8 @@ class ConnectDevicePageParams {
   final WalletType walletType;
   final OnConnectDevice onConnectDevice;
 
-  ConnectDevicePageParams({required this.walletType, required this.onConnectDevice});
+  ConnectDevicePageParams(
+      {required this.walletType, required this.onConnectDevice});
 }
 
 class ConnectDevicePage extends BasePage {
@@ -35,7 +35,8 @@ class ConnectDevicePage extends BasePage {
   String get title => S.current.restore_title_from_hardware_wallet;
 
   @override
-  Widget body(BuildContext context) => ConnectDevicePageBody(walletType, onConnectDevice, ledgerVM);
+  Widget body(BuildContext context) =>
+      ConnectDevicePageBody(walletType, onConnectDevice, ledgerVM);
 }
 
 class ConnectDevicePageBody extends StatefulWidget {
@@ -43,47 +44,35 @@ class ConnectDevicePageBody extends StatefulWidget {
   final OnConnectDevice onConnectDevice;
   final LedgerViewModel ledgerVM;
 
-  const ConnectDevicePageBody(this.walletType, this.onConnectDevice, this.ledgerVM);
+  const ConnectDevicePageBody(
+      this.walletType, this.onConnectDevice, this.ledgerVM);
 
   @override
   ConnectDevicePageBodyState createState() => ConnectDevicePageBodyState();
 }
 
 class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
-  final imageLedger = 'assets/images/ledger_nano.png';
-
-  final ledger = Ledger(
-    options: LedgerOptions(
-      scanMode: ScanMode.balanced,
-      maxScanDuration: const Duration(minutes: 5),
-    ),
-    onPermissionRequest: (_) async {
-      Map<Permission, PermissionStatus> statuses = await [
-        Permission.bluetoothScan,
-        Permission.bluetoothConnect,
-        Permission.bluetoothAdvertise,
-      ].request();
-
-      return statuses.values.where((status) => status.isDenied).isEmpty;
-    },
-  );
-
-  var bleIsEnabled = true;
   var bleDevices = <LedgerDevice>[];
   var usbDevices = <LedgerDevice>[];
 
   late Timer? _usbRefreshTimer = null;
   late Timer? _bleRefreshTimer = null;
+  late Timer? _bleStateTimer = null;
   late StreamSubscription<LedgerDevice>? _bleRefresh = null;
 
   @override
   void initState() {
     super.initState();
     WidgetsBinding.instance.addPostFrameCallback((_) {
-      _bleRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshBleDevices());
+      _bleStateTimer = Timer.periodic(
+          Duration(seconds: 1), (_) => widget.ledgerVM.updateBleState());
+
+      _bleRefreshTimer =
+          Timer.periodic(Duration(seconds: 1), (_) => _refreshBleDevices());
 
       if (Platform.isAndroid) {
-        _usbRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices());
+        _usbRefreshTimer =
+            Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices());
       }
     });
   }
@@ -91,35 +80,59 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
   @override
   void dispose() {
     _bleRefreshTimer?.cancel();
+    _bleStateTimer?.cancel();
     _usbRefreshTimer?.cancel();
     _bleRefresh?.cancel();
     super.dispose();
   }
 
   Future<void> _refreshUsbDevices() async {
-    final dev = await ledger.listUsbDevices();
+    final dev = await widget.ledgerVM.ledgerPlusUSB.devices;
     if (usbDevices.length != dev.length) setState(() => usbDevices = dev);
+    // _usbRefresh = widget.ledgerVM
+    //     .scanForUsbDevices()
+    //     .listen((device) => setState(() => usbDevices.add(device)))
+    //   ..onError((e) {
+    //     throw e.toString();
+    //   });
+    // Keep polling until the lfp lib gets updated
+    // _usbRefreshTimer?.cancel();
+    // _usbRefreshTimer = null;
   }
 
   Future<void> _refreshBleDevices() async {
     try {
-      _bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device)))
+      _bleRefresh = widget.ledgerVM
+          .scanForBleDevices()
+          .listen((device) => setState(() => bleDevices.add(device)))
         ..onError((e) {
           throw e.toString();
         });
-      setState(() => bleIsEnabled = true);
       _bleRefreshTimer?.cancel();
       _bleRefreshTimer = null;
     } catch (e) {
-      setState(() => bleIsEnabled = false);
+      print(e);
     }
   }
 
   Future<void> _connectToDevice(LedgerDevice device) async {
-    await widget.ledgerVM.connectLedger(device);
+    await widget.ledgerVM.connectLedger(device, widget.walletType);
     widget.onConnectDevice(context, widget.ledgerVM);
   }
 
+  String _getDeviceTileLeading(LedgerDeviceType deviceInfo) {
+    switch (deviceInfo) {
+      case LedgerDeviceType.nanoX:
+        return 'assets/images/hardware_wallet/ledger_nano_x.png';
+      case LedgerDeviceType.stax:
+        return 'assets/images/hardware_wallet/ledger_stax.png';
+      case LedgerDeviceType.flex:
+        return 'assets/images/hardware_wallet/ledger_flex.png';
+      default:
+        return 'assets/images/hardware_wallet/ledger_nano_x.png';
+    }
+  }
+
   @override
   Widget build(BuildContext context) {
     return Center(
@@ -139,7 +152,9 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
                   style: TextStyle(
                       fontSize: 16,
                       fontWeight: FontWeight.w500,
-                      color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
+                      color: Theme.of(context)
+                          .extension<CakeTextTheme>()!
+                          .titleColor),
                   textAlign: TextAlign.center,
                 ),
               ),
@@ -152,18 +167,25 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
               //   title: "Debug Ledger",
               //   leading: imageLedger,
               // ),
-              if (!bleIsEnabled)
-                Padding(
-                  padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
-                  child: Text(
-                    S.of(context).ledger_please_enable_bluetooth,
-                    style: TextStyle(
-                        fontSize: 16,
-                        fontWeight: FontWeight.w500,
-                        color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
-                    textAlign: TextAlign.center,
+              Observer(
+                builder: (_) => Offstage(
+                  offstage: widget.ledgerVM.bleIsEnabled,
+                  child: Padding(
+                    padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
+                    child: Text(
+                      S.of(context).ledger_please_enable_bluetooth,
+                      style: TextStyle(
+                          fontSize: 16,
+                          fontWeight: FontWeight.w500,
+                          color: Theme.of(context)
+                              .extension<CakeTextTheme>()!
+                              .titleColor),
+                      textAlign: TextAlign.center,
+                    ),
                   ),
                 ),
+              ),
+
               if (bleDevices.length > 0) ...[
                 Padding(
                   padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
@@ -174,7 +196,9 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
                       style: TextStyle(
                         fontSize: 14,
                         fontWeight: FontWeight.w400,
-                        color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
+                        color: Theme.of(context)
+                            .extension<CakeTextTheme>()!
+                            .titleColor,
                       ),
                     ),
                   ),
@@ -186,7 +210,7 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
                         child: DeviceTile(
                           onPressed: () => _connectToDevice(device),
                           title: device.name,
-                          leading: imageLedger,
+                          leading: _getDeviceTileLeading(device.deviceInfo),
                           connectionType: device.connectionType,
                         ),
                       ),
@@ -203,7 +227,9 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
                       style: TextStyle(
                         fontSize: 14,
                         fontWeight: FontWeight.w400,
-                        color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
+                        color: Theme.of(context)
+                            .extension<CakeTextTheme>()!
+                            .titleColor,
                       ),
                     ),
                   ),
@@ -215,7 +241,7 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
                         child: DeviceTile(
                           onPressed: () => _connectToDevice(device),
                           title: device.name,
-                          leading: imageLedger,
+                          leading: _getDeviceTileLeading(device.deviceInfo),
                           connectionType: device.connectionType,
                         ),
                       ),
diff --git a/lib/src/screens/connect_device/debug_device_page.dart b/lib/src/screens/connect_device/debug_device_page.dart
index f5a9ef2a4..bed9d59a7 100644
--- a/lib/src/screens/connect_device/debug_device_page.dart
+++ b/lib/src/screens/connect_device/debug_device_page.dart
@@ -1,15 +1,15 @@
-// import 'dart:convert';
+// import 'dart:typed_data';
 //
+// import 'package:basic_utils/basic_utils.dart';
+// import 'package:bitcoin_base/bitcoin_base.dart';
 // import 'package:cake_wallet/src/screens/base_page.dart';
 // import 'package:cake_wallet/src/screens/connect_device/widgets/device_tile.dart';
 // import 'package:cake_wallet/src/widgets/primary_button.dart';
 // import 'package:cake_wallet/utils/responsive_layout_util.dart';
-// import 'package:convert/convert.dart';
 // import 'package:flutter/material.dart';
-// import 'package:ledger_bitcoin/ledger_bitcoin.dart';
-// import 'package:ledger_flutter/ledger_flutter.dart';
+// import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
+// import 'package:ledger_litecoin/ledger_litecoin.dart';
 // import 'package:permission_handler/permission_handler.dart';
-// import 'package:polyseed/polyseed.dart';
 //
 // class DebugDevicePage extends BasePage {
 //   @override
@@ -50,7 +50,9 @@
 //     },
 //   );
 //
-//   late BitcoinLedgerApp btc;
+//   // late BitcoinLedgerApp btc;
+//   late LitecoinLedgerApp ltc;
+//
 //   var devices = <LedgerDevice>[];
 //   var status = "";
 //   var counter = 0;
@@ -59,7 +61,8 @@
 //   @override
 //   void initState() {
 //     super.initState();
-//     btc = BitcoinLedgerApp(ledger);
+//     // btc = BitcoinLedgerApp(ledger);
+//     ltc = LitecoinLedgerApp(ledger);
 //   }
 //
 //   @override
@@ -81,7 +84,7 @@
 //
 //   @override
 //   Widget build(BuildContext context) {
-//     final imageLedger = 'assets/images/ledger_nano.png';
+//     final imageLedger = 'assets/images/hardware_wallet/ledger_nano_x.png';
 //
 //     return Center(
 //       child: Container(
@@ -99,40 +102,25 @@
 //                   DebugButton(
 //                     title: "Get Version",
 //                     method: "Version",
-//                     func: () async => await btc.getVersion(selectedDevice!),
-//                   ),
-//                   DebugButton(
-//                     title: "Get Master Fingerprint",
-//                     method: "Master Fingerprint",
-//                     func: () async => hex.encode(await btc.getMasterFingerprint(selectedDevice!)),
-//                   ),
-//                   DebugButton(
-//                     title: "Get XPub",
-//                     method: "XPub",
-//                     func: () async => await btc.getXPubKey(selectedDevice!, derivationPath: "m/84'/0'/$counter'"),
+//                     // func: () async => await btc.getVersion(selectedDevice!),
+//                     func: () async => await ltc.getVersion(selectedDevice!),
 //                   ),
 //                   DebugButton(
 //                     title: "Get Wallet Address",
 //                     method: "Wallet Address",
 //                     func: () async {
 //                       setState(() => counter++);
-//                       final derivationPath = "m/84'/0'/$counter'/0/0";
-//                       return await btc.getAccounts(selectedDevice!, accountsDerivationPath: derivationPath);
+//                       final derivationPath = "m/84'/2'/0'/0/0";
+//                       return await ltc.getAccounts(selectedDevice!,
+//                           accountsDerivationPath: derivationPath);
+//                       // return await btc.getAccounts(selectedDevice!, accountsDerivationPath: derivationPath);
 //                       // return await ethereum!.getHardwareWalletAccounts(selectedDevice!);
-//                       },
+//                     },
 //                   ),
 //                   DebugButton(
 //                     title: "Send Money",
-//                     method: "Sig",
-//                     func: () async {
-//                       final psbt = PsbtV2();
-//                       final psbtBuf = base64.decode(
-//                         "cHNidP8BAgQCAAAAAQQBAQEFAQIAAQ4gTW6k/cwKKu1u7m9oKr5ob7VcAC0IPkfaDitRi/FkD7sBDwQAAAAAARAE/////wEA/ekBAQAAAAABA9AYVQLI722H0osKMa/4dvMucrnKV1Myxtlp0l0BoOBDAQAAAAD/////ku6r2ABaHt9N26f/P4eMljX8t1f4lBcFfEwuNm/uXYoBAAAAAP////+YeAl8arEGKOcyrWJAYwSboyCstkhHN8zn7/vy7pkYTAEAAAAA/////wHlHgAAAAAAABYAFKdq0umSucBGVkl2MpT6Hgo/0a/xAkcwRAIgMkiJmNFbEi2I3CQYOwyV/JepCnFQRvj4xghkySpFcJMCIGAypkkWltfj+ucvqUIu27tusDAIAAB+rBhX/GV7hPlEASEDyLmWyTLjLfC9kn8pnW42jW5N6EJo5fObjWWEyfLDu9UCSDBFAiEAg9crVtwBPF+sWk+Th6pLwzDjJGItwsUCvoBPtmMTEb4CIDGuM7WOguV0TP21oidF3bSUZlEAjUHWfWzxLKw+3LofASEDfN16xKb70UZSeQyX5Tlh8iRq7np5Nlz9GYdcSU50sKwCSDBFAiEAvotOblaEiBptRWkvb6bj2MGyRjTphKLBLiHYmrRMTCgCIEKJH+z65uPSSz1NIb0d/u3bU9l0xcWk0idEsXjB+BIiASEDrAEiEtrSNKxbh6F/KPaCTafF2LVjCzb75WB+x4xSuoQAAAAAAQEf5R4AAAAAAAAWABSnatLpkrnARlZJdjKU+h4KP9Gv8SIGA3xMuxmPsBAm9aMEUBs3N46DB+Kdts3bZR/Wxt+uM0H4GKtN6bpUAACAAAAAgAAAAIAAAAAAAAAAAAABBBTk7bEOxYcdXDi1eeWraYDufm6eJgEDCOgDAAAAAAAAAAEEFDX3g/pnDXIfsRw8shK42NZn+SdpAQMIiBMAAAAAAAAiAgN8TLsZj7AQJvWjBFAbNzeOgwfinbbN22Uf1sbfrjNB+BirTem6VAAAgAAAAIAAAACAAAAAAAAAAAAA"
-//                       );
-//                       psbt.deserialize(psbtBuf);
-//                       final result = await btc.signPsbt(selectedDevice!, psbt: psbt);
-//                       return result.toHexString();
-//                     },
+//                     method: "Raw Tx",
+//                     func: sendMoney
 //                   ),
 //                   Padding(
 //                     padding: EdgeInsets.only(top: 20),
@@ -147,18 +135,18 @@
 //                   ...devices
 //                       .map(
 //                         (device) => Padding(
-//                       padding: EdgeInsets.only(bottom: 20),
-//                       child: DeviceTile(
-//                         onPressed: () {
-//                           setState(() => selectedDevice = device);
-//                           ledger.connect(device);
-//                         },
-//                         title: device.name,
-//                         leading: imageLedger,
-//                         connectionType: device.connectionType,
-//                       ),
-//                     ),
-//                   )
+//                           padding: EdgeInsets.only(bottom: 20),
+//                           child: DeviceTile(
+//                             onPressed: () {
+//                               setState(() => selectedDevice = device);
+//                               ledger.connect(device);
+//                             },
+//                             title: device.name,
+//                             leading: imageLedger,
+//                             connectionType: device.connectionType,
+//                           ),
+//                         ),
+//                       )
 //                       .toList(),
 //                   PrimaryButton(
 //                       text: "Refresh BLE",
@@ -188,6 +176,42 @@
 //     );
 //   }
 //
+//   Future<String> sendMoney() async {
+//     final readyInputs = [
+//       LedgerTransaction(
+//         rawTx: "010000000001018c055c85c3724c98842d27712771dd0de139711f5940bba2df4615c5522184740000000017160014faf7f6dfb4e70798b92c93f33b4c51024491829df0ffffff022b05c70000000000160014f489f947fd13a1fb44ac168427081d3f30b6ce0cde9dd82e0000000017a914d5eca376cb49d65031220ff9093b7d407073ed0d8702483045022100f648c9f6a9b8f35b6ec29bbfae312c95ed3d56ce6a3f177d994efe90562ec4bd02205b82ce2c94bc0c9d152c3afc668b200bd82f48d6a14e83c66ba0f154cd5f69190121038f1dca119420d4aa7ad04af1c0d65304723789cccc56d335b18692390437f35900000000",
+//         outputIndex: 0,
+//         ownerPublicKey:
+//             HexUtils.decode("03b2e67958ed3356e329e05cf94c3bee6b20c17175ac3b2a1278e073bf44f5d6ec"),
+//         ownerDerivationPath: "m/84'/2'/0'/0/0",
+//         sequence: 0xffffffff,
+//       )
+//     ];
+//
+//     final outputs = [
+//       BitcoinOutput(
+//           address: P2wpkhAddress.fromAddress(
+//               address: "ltc1qn0g5e36xaj07lqj6w9xn52ng07hud42g3jf5ps",
+//               network: LitecoinNetwork.mainnet),
+//           value: BigInt.from(1000000)),
+//       BitcoinOutput(
+//           address: P2wpkhAddress.fromAddress(
+//               address: "ltc1qrx29qz4ghu4j0xk37ptgk7034cwpmjyxhrcnk9",
+//               network: LitecoinNetwork.mainnet),
+//           value: BigInt.from(12042705)),
+//     ];
+//     return await ltc.createTransaction(selectedDevice!,
+//         inputs: readyInputs,
+//         outputs: outputs
+//             .map((e) => TransactionOutput.fromBigInt(
+//                 e.value, Uint8List.fromList(e.address.toScriptPubKey().toBytes())))
+//             .toList(),
+//         sigHashType: 0x01,
+//         additionals: ["bech32"],
+//         isSegWit: true,
+//         useTrustedInputForSegwit: true);
+//   }
+//
 //   Widget DebugButton(
 //       {required String title, required String method, required Future<dynamic> Function() func}) {
 //     return Padding(
diff --git a/lib/src/screens/connect_device/widgets/device_tile.dart b/lib/src/screens/connect_device/widgets/device_tile.dart
index 8367d1606..58f65c5de 100644
--- a/lib/src/screens/connect_device/widgets/device_tile.dart
+++ b/lib/src/screens/connect_device/widgets/device_tile.dart
@@ -1,6 +1,6 @@
 import 'package:cake_wallet/themes/extensions/option_tile_theme.dart';
 import 'package:flutter/material.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
 
 class DeviceTile extends StatelessWidget {
   const DeviceTile({
diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart
index 478f1a3c3..028b3cfcf 100644
--- a/lib/src/screens/dashboard/pages/balance_page.dart
+++ b/lib/src/screens/dashboard/pages/balance_page.dart
@@ -188,7 +188,7 @@ class CryptoBalanceWidget extends StatelessWidget {
                                       Padding(
                                         padding: const EdgeInsets.all(8.0),
                                         child: Image.asset(
-                                          'assets/images/ledger_nano.png',
+                                          'assets/images/hardware_wallet/ledger_nano_x.png',
                                           width: 24,
                                           color: Theme.of(context)
                                               .extension<DashboardPageTheme>()!
diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart
index d671230c4..57f5ec727 100644
--- a/lib/src/screens/restore/restore_options_page.dart
+++ b/lib/src/screens/restore/restore_options_page.dart
@@ -67,7 +67,7 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
     final mainImageColor = Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor;
     final brightImageColor = Theme.of(context).extension<InfoTheme>()!.textColor;
     final imageColor = widget.themeType == ThemeType.bright ? brightImageColor : mainImageColor;
-    final imageLedger = Image.asset('assets/images/ledger_nano.png', width: 40, color: imageColor);
+    final imageLedger = Image.asset('assets/images/hardware_wallet/ledger_nano_x.png', width: 40, color: imageColor);
     final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png', color: imageColor);
     final imageBackup = Image.asset('assets/images/backup.png', color: imageColor);
 
@@ -186,4 +186,4 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
       }
     }
   }
-}
\ No newline at end of file
+}
diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart
index d881d0341..bce82312d 100644
--- a/lib/src/screens/send/send_page.dart
+++ b/lib/src/screens/send/send_page.dart
@@ -395,16 +395,19 @@ class SendPage extends BasePage {
 
                         if (sendViewModel.wallet.isHardwareWallet) {
                           if (!sendViewModel.ledgerViewModel!.isConnected) {
-                            await Navigator.of(context).pushNamed(Routes.connectDevices,
+                            await Navigator.of(context).pushNamed(
+                                Routes.connectDevices,
                                 arguments: ConnectDevicePageParams(
                                   walletType: sendViewModel.walletType,
                                   onConnectDevice: (BuildContext context, _) {
-                                    sendViewModel.ledgerViewModel!.setLedger(sendViewModel.wallet);
+                                    sendViewModel.ledgerViewModel!
+                                        .setLedger(sendViewModel.wallet);
                                     Navigator.of(context).pop();
                                   },
                                 ));
                           } else {
-                            sendViewModel.ledgerViewModel!.setLedger(sendViewModel.wallet);
+                            sendViewModel.ledgerViewModel!
+                                .setLedger(sendViewModel.wallet);
                           }
                         }
 
@@ -509,7 +512,7 @@ class SendPage extends BasePage {
                                 if (state is TransactionCommitted) {
                                   newContactAddress =
                                       newContactAddress ?? sendViewModel.newContactAddress();
-                                  
+
                                   if (sendViewModel.coinTypeToSpendFrom != UnspentCoinType.any) {
                                     newContactAddress = null;
                                   }
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 26bc5ceb9..53a8277ab 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -435,7 +435,7 @@ abstract class DashboardViewModelBase with Store {
   }
 
   @computed
-  bool get hasMweb => wallet.type == WalletType.litecoin && (Platform.isIOS || Platform.isAndroid);
+  bool get hasMweb => wallet.type == WalletType.litecoin && (Platform.isIOS || Platform.isAndroid) && !wallet.isHardwareWallet;
 
   @computed
   bool get showMwebCard => hasMweb && settingsStore.mwebCardDisplay && !mwebEnabled;
diff --git a/lib/view_model/hardware_wallet/ledger_view_model.dart b/lib/view_model/hardware_wallet/ledger_view_model.dart
index f05b1c805..19b190fe3 100644
--- a/lib/view_model/hardware_wallet/ledger_view_model.dart
+++ b/lib/view_model/hardware_wallet/ledger_view_model.dart
@@ -1,3 +1,4 @@
+import 'dart:async';
 import 'dart:io';
 
 import 'package:cake_wallet/bitcoin/bitcoin.dart';
@@ -9,11 +10,19 @@ import 'package:cake_wallet/wallet_type_utils.dart';
 import 'package:cw_core/hardware/device_connection_type.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_type.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as sdk;
+import 'package:mobx/mobx.dart';
 import 'package:permission_handler/permission_handler.dart';
 
-class LedgerViewModel {
-  late final Ledger ledger;
+part 'ledger_view_model.g.dart';
+
+class LedgerViewModel = LedgerViewModelBase with _$LedgerViewModel;
+
+abstract class LedgerViewModelBase with Store {
+  // late final Ledger ledger;
+  late final sdk.LedgerInterface ledgerPlusBLE;
+  late final sdk.LedgerInterface ledgerPlusUSB;
 
   bool get _doesSupportHardwareWallets {
     if (!DeviceInfo.instance.isMobile) {
@@ -21,53 +30,97 @@ class LedgerViewModel {
     }
 
     if (isMoneroOnly) {
-      return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS)
+      return DeviceConnectionType.supportedConnectionTypes(
+              WalletType.monero, Platform.isIOS)
           .isNotEmpty;
     }
 
     return true;
   }
 
-  LedgerViewModel() {
+  LedgerViewModelBase() {
     if (_doesSupportHardwareWallets) {
-      ledger = Ledger(
-        options: LedgerOptions(
-          scanMode: ScanMode.balanced,
-          maxScanDuration: const Duration(minutes: 5),
-        ),
-        onPermissionRequest: (_) async {
-          Map<Permission, PermissionStatus> statuses = await [
-            Permission.bluetoothScan,
-            Permission.bluetoothConnect,
-            Permission.bluetoothAdvertise,
-          ].request();
+      reaction((_) => bleIsEnabled, (_) {
+        if (bleIsEnabled) _initBLE();
+      });
+      updateBleState();
 
-          return statuses.values.where((status) => status.isDenied).isEmpty;
-        },
-      );
+      if (!Platform.isIOS) {
+        ledgerPlusUSB = sdk.LedgerInterface.usb();
+      }
     }
   }
 
-  Future<void> connectLedger(LedgerDevice device) async {
-    await ledger.connect(device);
+  @observable
+  bool bleIsEnabled = false;
 
-    if (device.connectionType == ConnectionType.usb) _device = device;
+  bool _bleIsInitialized = false;
+  Future<void> _initBLE() async {
+    if (bleIsEnabled && !_bleIsInitialized) {
+      ledgerPlusBLE = sdk.LedgerInterface.ble(onPermissionRequest: (_) async {
+        Map<Permission, PermissionStatus> statuses = await [
+          Permission.bluetoothScan,
+          Permission.bluetoothConnect,
+          Permission.bluetoothAdvertise,
+        ].request();
+
+        return statuses.values.where((status) => status.isDenied).isEmpty;
+      });
+      _bleIsInitialized = true;
+    }
   }
 
-  LedgerDevice? _device;
+  Future<void> updateBleState() async {
+    final bleState = await sdk.UniversalBle.getBluetoothAvailabilityState();
 
-  bool get isConnected => ledger.devices.isNotEmpty || _device != null;
+    final newState = bleState == sdk.AvailabilityState.poweredOn;
 
-  LedgerDevice get device => _device ?? ledger.devices.first;
+    if (newState != bleIsEnabled) bleIsEnabled = newState;
+  }
+
+  Stream<sdk.LedgerDevice> scanForBleDevices() => ledgerPlusBLE.scan();
+
+  Stream<sdk.LedgerDevice> scanForUsbDevices() => ledgerPlusUSB.scan();
+
+  Future<void> connectLedger(sdk.LedgerDevice device, WalletType type) async {
+    if (isConnected) {
+      try {
+        await _connection!.disconnect();
+      } catch (_) {}
+    }
+    final ledger = device.connectionType == sdk.ConnectionType.ble
+        ? ledgerPlusBLE
+        : ledgerPlusUSB;
+
+    if (_connectionChangeListener == null) {
+      _connectionChangeListener = ledger.deviceStateChanges.listen((event) {
+        print('Ledger Device State Changed: $event');
+        if (event == sdk.BleConnectionState.disconnected) {
+          _connection = null;
+          _connectionChangeListener?.cancel();
+        }
+      });
+    }
+
+    _connection = await ledger.connect(device);
+  }
+
+  StreamSubscription<sdk.BleConnectionState>? _connectionChangeListener;
+  sdk.LedgerConnection? _connection;
+
+  bool get isConnected => _connection != null && !(_connection!.isDisconnected);
+
+  sdk.LedgerConnection get connection => _connection!;
 
   void setLedger(WalletBase wallet) {
     switch (wallet.type) {
       case WalletType.bitcoin:
-        return bitcoin!.setLedger(wallet, ledger, device);
+      case WalletType.litecoin:
+        return bitcoin!.setLedgerConnection(wallet, connection);
       case WalletType.ethereum:
-        return ethereum!.setLedger(wallet, ledger, device);
+        return ethereum!.setLedgerConnection(wallet, connection);
       case WalletType.polygon:
-        return polygon!.setLedger(wallet, ledger, device);
+        return polygon!.setLedgerConnection(wallet, connection);
       default:
         throw Exception('Unexpected wallet type: ${wallet.type}');
     }
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 4064a1258..24e83f364 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -24,7 +24,6 @@ import 'package:cw_core/unspent_coin_type.dart';
 import 'package:cake_wallet/view_model/send/output.dart';
 import 'package:cake_wallet/view_model/send/send_template_view_model.dart';
 import 'package:hive/hive.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
 import 'package:mobx/mobx.dart';
 import 'package:cake_wallet/entities/template.dart';
 import 'package:cake_wallet/core/address_validator.dart';
@@ -408,16 +407,16 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
       state = ExecutedSuccessfullyState();
       return pendingTransaction;
     } catch (e) {
-      if (e is LedgerException) {
-        final errorCode = e.errorCode.toRadixString(16);
-        final fallbackMsg =
-            e.message.isNotEmpty ? e.message : "Unexpected Ledger Error Code: $errorCode";
-        final errorMsg = ledgerViewModel!.interpretErrorCode(errorCode) ?? fallbackMsg;
-
-        state = FailureState(errorMsg);
-      } else {
+      // if (e is LedgerException) {
+      //   final errorCode = e.errorCode.toRadixString(16);
+      //   final fallbackMsg =
+      //       e.message.isNotEmpty ? e.message : "Unexpected Ledger Error Code: $errorCode";
+      //   final errorMsg = ledgerViewModel!.interpretErrorCode(errorCode) ?? fallbackMsg;
+      //
+      //   state = FailureState(errorMsg);
+      // } else {
         state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency));
-      }
+      // }
     }
     return null;
   }
diff --git a/lib/view_model/wallet_hardware_restore_view_model.dart b/lib/view_model/wallet_hardware_restore_view_model.dart
index 68bc95a00..91e0de685 100644
--- a/lib/view_model/wallet_hardware_restore_view_model.dart
+++ b/lib/view_model/wallet_hardware_restore_view_model.dart
@@ -13,7 +13,6 @@ import 'package:cw_core/wallet_credentials.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:hive/hive.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
 import 'package:mobx/mobx.dart';
 
 part 'wallet_hardware_restore_view_model.g.dart';
@@ -58,7 +57,11 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
       switch (type) {
         case WalletType.bitcoin:
         accounts = await bitcoin!
-            .getHardwareWalletAccounts(ledgerViewModel, index: _nextIndex, limit: limit);
+            .getHardwareWalletBitcoinAccounts(ledgerViewModel, index: _nextIndex, limit: limit);
+        break;
+      case WalletType.litecoin:
+        accounts = await bitcoin!
+            .getHardwareWalletLitecoinAccounts(ledgerViewModel, index: _nextIndex, limit: limit);
         break;
       case WalletType.ethereum:
         accounts = await ethereum!
@@ -74,9 +77,10 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
 
       availableAccounts.addAll(accounts);
       _nextIndex += limit;
-    } on LedgerException catch (e) {
-      error = ledgerViewModel.interpretErrorCode(e.errorCode.toRadixString(16));
+    // } on LedgerException catch (e) {
+    //   error = ledgerViewModel.interpretErrorCode(e.errorCode.toRadixString(16));
     } catch (e) {
+      print(e);
       error = S.current.ledger_connection_error;
     }
 
@@ -89,6 +93,7 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
     WalletCredentials credentials;
     switch (type) {
       case WalletType.bitcoin:
+      case WalletType.litecoin:
         credentials =
             bitcoin!.createBitcoinHardwareWalletCredentials(name: name, accountData: selectedAccount!);
         break;
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 86b3462ac..9895e6305 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -17,6 +17,7 @@ import package_info_plus
 import path_provider_foundation
 import share_plus
 import shared_preferences_foundation
+import universal_ble
 import url_launcher_macos
 import wakelock_plus
 
@@ -33,6 +34,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
   SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
   SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
+  UniversalBlePlugin.register(with: registry.registrar(forPlugin: "UniversalBlePlugin"))
   UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
   WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
 }
diff --git a/pubspec_base.yaml b/pubspec_base.yaml
index a2f19e596..d5fce76e9 100644
--- a/pubspec_base.yaml
+++ b/pubspec_base.yaml
@@ -12,7 +12,7 @@ dependencies:
       version: 4.0.2
   shared_preferences: ^2.0.15
   # provider: ^6.0.3
-  rxdart: ^0.27.4
+  rxdart: ^0.28.0
   yaml: ^3.1.1
   #barcode_scan: any
   barcode_scan2: ^4.2.1
@@ -97,7 +97,7 @@ dependencies:
   polyseed: ^0.0.6
   nostr_tools: ^1.0.9
   solana: ^0.30.1
-  ledger_flutter: ^1.0.1
+  ledger_flutter_plus: ^1.4.1
   hashlib: ^1.19.2
 
 dev_dependencies:
@@ -125,10 +125,6 @@ dependency_overrides:
   bech32:
     git:
       url: https://github.com/cake-tech/bech32.git
-  ledger_flutter:
-    git:
-      url: https://github.com/cake-tech/ledger-flutter.git
-      ref: cake-v3
   web3dart:
     git:
       url: https://github.com/cake-tech/web3dart.git
@@ -155,6 +151,7 @@ flutter:
   assets:
     - assets/images/
     - assets/images/flags/
+    - assets/images/hardware_wallet/
     - assets/node_list.yml
     - assets/haven_node_list.yml
     - assets/bitcoin_electrum_server_list.yml
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 80433ae0e..2ec59f349 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -97,7 +97,7 @@
   "cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!",
   "cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.",
   "cake_pay_save_order": "Die Karte sollte innerhalb von 1 Werktag an Ihre E-Mail gesendet werden, \n Ihre Bestell-ID zu speichern:",
-  "cake_pay_subtitle": "Kaufen Sie weltweite Prepaid -Karten und Geschenkkarten",
+  "cake_pay_subtitle": "Kaufen Sie weltweite Prepaid-Karten und Geschenkkarten",
   "cake_pay_web_cards_subtitle": "Kaufen Sie weltweit Prepaid-Karten und Geschenkkarten",
   "cake_pay_web_cards_title": "Cake Pay-Webkarten",
   "cake_wallet": "Cake Wallet",
@@ -114,7 +114,7 @@
   "change_currency": "Währung ändern",
   "change_current_node": "Möchten Sie den aktuellen Knoten wirklich zu ${node}? ändern?",
   "change_current_node_title": "Aktuellen Knoten ändern",
-  "change_exchange_provider": "Swap -Anbieter ändern",
+  "change_exchange_provider": "Swap-Anbieter ändern",
   "change_language": "Sprache ändern",
   "change_language_to": "Sprache zu ${language} ändern?",
   "change_password": "Passwort ändern",
@@ -131,7 +131,7 @@
   "choose_one": "Wähle ein",
   "choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus",
   "choose_wallet_currency": "Bitte wählen Sie die Währung der Wallet:",
-  "choose_wallet_group": "Wählen Sie Brieftaschengruppe",
+  "choose_wallet_group": "Wählen Sie Walletgruppe",
   "clear": "Zurücksetzen",
   "clearnet_link": "Clearnet-Link",
   "close": "Schließen",
@@ -179,7 +179,7 @@
   "create_invoice": "Rechnung erstellen",
   "create_new": "Neue Wallet erstellen",
   "create_new_account": "Neues Konto erstellen",
-  "create_new_seed": "Neue Samen erstellen",
+  "create_new_seed": "Neue Seed erstellen",
   "creating_new_wallet": "Neue Wallet erstellen",
   "creating_new_wallet_error": "Fehler: ${description}",
   "creation_date": "Erstellungsdatum",
@@ -189,9 +189,9 @@
   "custom_value": "Benutzerdefinierten Wert",
   "dark_theme": "Dunkel",
   "debit_card": "Debitkarte",
-  "debit_card_terms": "Die Speicherung und Nutzung Ihrer Zahlungskartennummer (und Ihrer Zahlungskartennummer entsprechenden Anmeldeinformationen) in dieser digitalen Geldbörse unterliegt den Allgemeinen Geschäftsbedingungen des geltenden Karteninhabervertrags mit dem Zahlungskartenaussteller, gültig ab von Zeit zu Zeit.",
+  "debit_card_terms": "Die Speicherung und Nutzung Ihrer Zahlungskartennummer (und Ihrer Zahlungskartennummer entsprechenden Anmeldeinformationen) in dieser digitalen Wallet unterliegt den Allgemeinen Geschäftsbedingungen des geltenden Karteninhabervertrags mit dem Zahlungskartenaussteller, gültig ab von Zeit zu Zeit.",
   "decimal_places_error": "Zu viele Nachkommastellen",
-  "decimals_cannot_be_zero": "Token -Dezimalzahl kann nicht Null sein.",
+  "decimals_cannot_be_zero": "Token-Dezimalzahl kann nicht Null sein.",
   "default_buy_provider": "Standard-Kaufanbieter",
   "default_sell_provider": "Standard-Verkaufsanbieter",
   "delete": "Löschen",
@@ -236,7 +236,7 @@
   "electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin",
   "email_address": "E-Mail-Adresse",
   "enable": "Aktivieren",
-  "enable_mempool_api": "Mempool -API für genaue Gebühren und Daten",
+  "enable_mempool_api": "Mempool-API für genaue Gebühren und Daten",
   "enable_replace_by_fee": "Aktivieren Sie Ersatz für Fee",
   "enable_silent_payments_scanning": "Scannen Sie stille Zahlungen, bis die Spitze erreicht ist",
   "enabled": "Ermöglicht",
@@ -245,7 +245,7 @@
   "enter_code": "Code eingeben",
   "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein",
   "enter_totp_code": "Bitte geben Sie den TOTP-Code ein.",
-  "enter_wallet_password": "Geben Sie das Brieftaschenkennwort ein",
+  "enter_wallet_password": "Geben Sie das Walletkennwort ein",
   "enter_your_note": "Geben Sie Ihre Bemerkung ein…",
   "enter_your_pin": "PIN eingeben",
   "enter_your_pin_again": "Geben Sie Ihre PIN erneut ein",
@@ -282,7 +282,7 @@
   "event": "Ereignis",
   "events": "Veranstaltungen",
   "exchange": "Tauschen",
-  "exchange_incorrect_current_wallet_for_xmr": "Wenn Sie XMR aus Ihrer Cake -Wallet Monero -Balance austauschen möchten, wechseln Sie zuerst zu Ihrer Monero -Brieftasche.",
+  "exchange_incorrect_current_wallet_for_xmr": "Wenn Sie XMR aus Ihrer CakeWallet Monero-Balance tauschen möchten, wechseln Sie zuerst zu Ihrer Monero-Wallet.",
   "exchange_new_template": "Neue Vorlage",
   "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!",
   "exchange_result_confirm": "Durch Drücken von \"Bestätigen\" wird ${fetchingLabel} ${from} von Ihrer Wallet namens ${walletName} an die unten angegebene Adresse gesendet. Alternativ können Sie von einer externen Wallet an die unten angegebene Adresse / QR-Code senden.\n\nBitte bestätigen Sie, um fortzufahren, oder gehen Sie zurück, um die Beträge zu ändern.",
@@ -309,7 +309,7 @@
   "fill_code": "Geben Sie den Bestätigungscode ein, den Sie per E-Mail erhalten haben",
   "filter_by": "Filtern nach",
   "first_wallet_text": "Eine großartige Wallet für Monero, Bitcoin, Ethereum, Litecoin, und Haven",
-  "fixed_pair_not_supported": "Dieses feste Paar wird nicht von den ausgewählten Swap -Diensten unterstützt",
+  "fixed_pair_not_supported": "Dieses feste Paar wird nicht von den ausgewählten Swap-Diensten unterstützt",
   "fixed_rate": "Feste Rate",
   "fixed_rate_alert": "Sie können den Empfangsbetrag eingeben, wenn der Festratenmodus aktiviert ist. Möchten Sie in den Festratenmodus wechseln?",
   "forgot_password": "Passwort vergessen",
@@ -349,9 +349,9 @@
   "incoming": "Eingehend",
   "incorrect_seed": "Der eingegebene Text ist ungültig.",
   "inputs": "Eingänge",
-  "insufficient_lamport_for_tx": "Sie haben nicht genug SOL, um die Transaktion und ihre Transaktionsgebühr abzudecken. Bitte fügen Sie Ihrer Brieftasche mehr Sol hinzu oder reduzieren Sie die SO -Menge, die Sie senden.",
-  "insufficient_lamports": "Sie haben nicht genug SOL, um die Transaktion und ihre Transaktionsgebühr abzudecken. Sie brauchen mindestens ${solValueNeeded} Sol. Bitte fügen Sie mehr Sol zu Ihrer Wallet hinzu oder reduzieren Sie den von Ihnen gesendeten Sol -Betrag",
-  "insufficientFundsForRentError": "Sie haben nicht genug SOL, um die Transaktionsgebühr und die Miete für das Konto zu decken. Bitte fügen Sie mehr Sol zu Ihrer Brieftasche hinzu oder reduzieren Sie den von Ihnen gesendeten Sol -Betrag",
+  "insufficient_lamport_for_tx": "Sie haben nicht genug SOL, um die Transaktion und ihre Transaktionsgebühr abzudecken. Bitte fügen Sie Ihrer Wallet mehr Sol hinzu oder reduzieren Sie die SOL-Menge, die Sie senden.",
+  "insufficient_lamports": "Sie haben nicht genug SOL, um die Transaktion und ihre Transaktionsgebühr abzudecken. Sie brauchen mindestens ${solValueNeeded} Sol. Bitte fügen Sie mehr Sol zu Ihrer Wallet hinzu oder reduzieren Sie den von Ihnen gesendeten Sol-Betrag",
+  "insufficientFundsForRentError": "Sie haben nicht genug SOL, um die Transaktionsgebühr und die Miete für das Konto zu decken. Bitte fügen Sie mehr Sol zu Ihrer Wallet hinzu oder reduzieren Sie den von Ihnen gesendeten Sol-Betrag",
   "introducing_cake_pay": "Einführung von Cake Pay!",
   "invalid_input": "Ungültige Eingabe",
   "invalid_password": "Ungültiges Passwort",
@@ -365,20 +365,20 @@
   "ledger_error_wrong_app": "Bitte stellen Sie sicher, dass Sie die richtige App auf Ihrem Ledger geöffnet haben",
   "ledger_please_enable_bluetooth": "Bitte aktivieren Sie Bluetooth um sich mit Ihren Ledger zu verbinden.",
   "light_theme": "Hell",
-  "litecoin_enable_mweb_sync": "Aktivieren Sie das MWEB -Scannen",
+  "litecoin_enable_mweb_sync": "Aktivieren Sie das MWEB-Scannen",
   "litecoin_mweb": "MWeb",
   "litecoin_mweb_always_scan": "Setzen Sie MWeb immer scannen",
-  "litecoin_mweb_description": "MWEB ist ein neues Protokoll, das schnellere, billigere und privatere Transaktionen zu Litecoin bringt",
+  "litecoin_mweb_description": "MWWB ist ein neues Protokoll, das schnellere, billigere und privatere Transaktionen zu Litecoin bringt",
   "litecoin_mweb_dismiss": "Zurückweisen",
-  "litecoin_mweb_display_card": "MWEB -Karte anzeigen",
+  "litecoin_mweb_display_card": "MWEB-Karte anzeigen",
   "litecoin_mweb_enable_later": "Sie können MWEB unter Anzeigeeinstellungen erneut aktivieren.",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Abstecken",
   "litecoin_mweb_scanning": "MWEB Scanning",
-  "litecoin_mweb_settings": "MWEB -Einstellungen",
-  "litecoin_mweb_warning": "Durch die Verwendung von MWEB wird zunächst ~ 600 MB Daten heruntergeladen und kann je nach Netzwerkgeschwindigkeit bis zu 30 Minuten dauern. Diese ersten Daten werden nur einmal heruntergeladen und für alle Litecoin -Brieftaschen verfügbar",
+  "litecoin_mweb_settings": "MWEB-Einstellungen",
+  "litecoin_mweb_warning": "Durch die Verwendung von MWEB wird zunächst ~ 600 MB Daten heruntergeladen und kann je nach Netzwerkgeschwindigkeit bis zu 30 Minuten dauern. Diese ersten Daten werden nur einmal heruntergeladen und für alle Litecoin-Wallets verfügbar",
   "litecoin_what_is_mweb": "Was ist MWeb?",
-  "live_fee_rates": "Live -Gebührenpreise über API",
+  "live_fee_rates": "Live-Gebührenpreise über API",
   "load_more": "Mehr laden",
   "loading_your_wallet": "Wallet wird geladen",
   "login": "Einloggen",
@@ -533,8 +533,8 @@
   "rename": "Umbenennen",
   "rep_warning": "Repräsentative Warnung",
   "rep_warning_sub": "Ihr Vertreter scheint nicht gut zu sein. Tippen Sie hier, um eine neue auszuwählen",
-  "repeat_wallet_password": "Wiederholen Sie das Brieftaschenkennwort",
-  "repeated_password_is_incorrect": "Wiederholtes Passwort ist falsch. Bitte wiederholen Sie das Brieftaschenkennwort erneut.",
+  "repeat_wallet_password": "Wiederholen Sie das Walletkennwort",
+  "repeated_password_is_incorrect": "Wiederholtes Passwort ist falsch. Bitte wiederholen Sie das Walletkennwort erneut.",
   "require_for_adding_contacts": "Erforderlich zum Hinzufügen von Kontakten",
   "require_for_all_security_and_backup_settings": "Für alle Sicherheits- und Sicherungseinstellungen erforderlich",
   "require_for_assessing_wallet": "Für den Zugriff auf die Wallet erforderlich",
@@ -576,7 +576,7 @@
   "restore_wallet": "Wallet wiederherstellen",
   "restore_wallet_name": "Walletname",
   "restore_wallet_restore_description": "Beschreibung zur Wallet-Wiederherstellung",
-  "robinhood_option_description": "Kaufen und übertragen Sie sofort mit Ihrem Debitkarten-, Bankkonto- oder Robinhood -Guthaben. Nur USA.",
+  "robinhood_option_description": "Kaufen und übertragen Sie sofort mit Ihrem Debitkarten-, Bankkonto- oder Robinhood-Guthaben. Nur USA.",
   "router_no_route": "Keine Route definiert für ${name}",
   "save": "Speichern",
   "save_backup_password": "Bitte stellen Sie sicher, dass Sie Ihr Sicherungskennwort gespeichert haben. Ohne dieses können Sie Ihre Sicherungsdateien nicht importieren.",
@@ -622,8 +622,8 @@
   "seed_share": "Seed teilen",
   "seed_title": "Seed",
   "seedtype": "Seedtyp",
-  "seedtype_alert_content": "Das Teilen von Samen mit anderen Brieftaschen ist nur mit bip39 Seedype möglich.",
-  "seedtype_alert_title": "Seedype -Alarm",
+  "seedtype_alert_content": "Das Teilen von Seeds mit anderen Wallet ist nur mit bip39 Seedype möglich.",
+  "seedtype_alert_title": "Seedype-Alarm",
   "seedtype_legacy": "Veraltet (25 Wörter)",
   "seedtype_polyseed": "Polyseed (16 Wörter)",
   "seedtype_wownero": "WOWNO (14 Wörter)",
@@ -691,7 +691,7 @@
   "setup_your_debit_card": "Richten Sie Ihre Debitkarte ein",
   "share": "Teilen",
   "share_address": "Adresse teilen ",
-  "shared_seed_wallet_groups": "Gemeinsame Samenbrieftaschengruppen",
+  "shared_seed_wallet_groups": "Gemeinsame Walletsseed Gruppen",
   "show_details": "Details anzeigen",
   "show_keys": "Seed/Schlüssel anzeigen",
   "show_market_place": "Marktplatz anzeigen",
@@ -711,12 +711,12 @@
   "silent_payments_disclaimer": "Neue Adressen sind keine neuen Identitäten. Es ist eine Wiederverwendung einer bestehenden Identität mit einem anderen Etikett.",
   "silent_payments_display_card": "Zeigen Sie stille Zahlungskarte",
   "silent_payments_scan_from_date": "Scan ab Datum",
-  "silent_payments_scan_from_date_or_blockheight": "Bitte geben Sie die Blockhöhe ein, die Sie für eingehende stille Zahlungen scannen möchten, oder verwenden Sie stattdessen das Datum. Sie können wählen, ob die Brieftasche jeden Block scannt oder nur die angegebene Höhe überprüft.",
+  "silent_payments_scan_from_date_or_blockheight": "Bitte geben Sie die Blockhöhe ein, die Sie für eingehende stille Zahlungen scannen möchten, oder verwenden Sie stattdessen das Datum. Sie können wählen, ob die Wallet jeden Block scannt oder nur die angegebene Höhe überprüft.",
   "silent_payments_scan_from_height": "Scan aus der Blockhöhe scannen",
   "silent_payments_scanned_tip": "Gescannt zum Trinkgeld! (${tip})",
   "silent_payments_scanning": "Stille Zahlungen scannen",
   "silent_payments_settings": "Einstellungen für stille Zahlungen",
-  "single_seed_wallets_group": "Einzelne Samenbriefen",
+  "single_seed_wallets_group": "Einzelne Wallets",
   "slidable": "Verschiebbar",
   "sort_by": "Sortiere nach",
   "spend_key_private": "Spend Key (geheim)",
@@ -755,11 +755,11 @@
   "syncing_wallet_alert_title": "Ihr Wallet wird synchronisiert",
   "template": "Vorlage",
   "template_name": "Vorlagenname",
-  "testnet_coins_no_value": "Testnet -Münzen haben keinen Wert",
+  "testnet_coins_no_value": "Testnet-Münzen haben keinen Wert",
   "third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!",
   "third_intro_title": "Yat spielt gut mit anderen",
   "thorchain_contract_address_not_supported": "Thorchain unterstützt das Senden an eine Vertragsadresse nicht",
-  "thorchain_taproot_address_not_supported": "Der Thorchain -Anbieter unterstützt keine Taproot -Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.",
+  "thorchain_taproot_address_not_supported": "Der Thorchain-Anbieter unterstützt keine Taproot-Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Hinweis:",
   "today": "Heute",
@@ -879,12 +879,12 @@
   "voting_weight": "Stimmgewicht",
   "waitFewSecondForTxUpdate": "Bitte warten Sie einige Sekunden, bis die Transaktion im Transaktionsverlauf angezeigt wird",
   "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung",
-  "wallet_group": "Brieftaschengruppe",
-  "wallet_group_description_four": "eine Brieftasche mit einem völlig neuen Samen schaffen.",
-  "wallet_group_description_one": "In Kuchenbrieftasche können Sie eine erstellen",
-  "wallet_group_description_three": "Sehen Sie den Bildschirm zur verfügbaren Brieftaschen und/oder Brieftaschengruppen. Oder wählen",
-  "wallet_group_description_two": "Durch die Auswahl einer vorhandenen Brieftasche, mit der ein Samen geteilt werden kann. Jede Brieftaschengruppe kann eine einzelne Brieftasche jedes Währungstyps enthalten. \n\n Sie können auswählen",
-  "wallet_group_empty_state_text_one": "Sieht so aus, als hätten Sie keine kompatiblen Brieftaschengruppen !\n\n TAP",
+  "wallet_group": "Walletgruppe",
+  "wallet_group_description_four": "eine Wallet mit einem völlig neuen Seed schaffen.",
+  "wallet_group_description_one": "In CakeWallet können Sie eine erstellen",
+  "wallet_group_description_three": "Sehen Sie den Bildschirm zur verfügbaren Wallet und/oder Walletgruppen. Oder wählen",
+  "wallet_group_description_two": "Durch die Auswahl einer vorhandenen Wallet, mit der ein Seed geteilt werden kann. Jede Walletgruppe kann eine einzelne Wallet jedes Währungstyps enthalten. \n\n Sie können auswählen",
+  "wallet_group_empty_state_text_one": "Sieht so aus, als hätten Sie keine kompatiblen Walletgruppen !\n\n TAP",
   "wallet_group_empty_state_text_two": "unten, um einen neuen zu machen.",
   "wallet_keys": "Wallet-Seed/-Schlüssel",
   "wallet_list_create_new_wallet": "Neue Wallet erstellen",
@@ -901,7 +901,7 @@
   "wallet_menu": "Wallet-Menü",
   "wallet_name": "Walletname",
   "wallet_name_exists": "Wallet mit diesem Namen existiert bereits",
-  "wallet_password_is_empty": "Brieftaschenkennwort ist leer. Brieftaschenkennwort sollte nicht leer sein",
+  "wallet_password_is_empty": "Walletkennwort ist leer. Walletkennwort sollte nicht leer sein",
   "wallet_recovery_height": "Erstellungshöhe",
   "wallet_restoration_store_incorrect_seed_length": "Falsche Seed-Länge",
   "wallet_seed": "Wallet-Seed",
@@ -941,4 +941,4 @@
   "you_will_get": "Konvertieren zu",
   "you_will_send": "Konvertieren von",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/tool/configure.dart b/tool/configure.dart
index 704b47526..97541c2fa 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -97,7 +97,7 @@ import 'package:cw_core/wallet_service.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:cw_core/get_height_by_date.dart';
 import 'package:hive/hive.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:bip39/bip39.dart' as bip39;
 """;
@@ -121,6 +121,7 @@ import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
 import 'package:cw_bitcoin/litecoin_wallet_service.dart';
 import 'package:cw_bitcoin/litecoin_wallet.dart';
 import 'package:cw_bitcoin/bitcoin_hardware_wallet_service.dart';
+import 'package:cw_bitcoin/litecoin_hardware_wallet_service.dart';
 import 'package:mobx/mobx.dart';
 """;
   const bitcoinCwPart = "part 'cw_bitcoin.dart';";
@@ -223,8 +224,9 @@ abstract class Bitcoin {
   void deleteSilentPaymentAddress(Object wallet, String address);
   Future<void> updateFeeRates(Object wallet);
   int getMaxCustomFeeRate(Object wallet);
-  void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device);
-  Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
+  void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection);
+  Future<List<HardwareAccountData>> getHardwareWalletBitcoinAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
+  Future<List<HardwareAccountData>> getHardwareWalletLitecoinAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
   List<Output> updateOutputs(PendingTransaction pendingTransaction, List<Output> outputs);
   bool txIsReceivedSilentPayment(TransactionInfo txInfo);
   bool txIsMweb(TransactionInfo txInfo);
@@ -819,7 +821,7 @@ import 'package:cw_core/wallet_credentials.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_service.dart';
 import 'package:hive/hive.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
 import 'package:web3dart/web3dart.dart';
 
 """;
@@ -885,7 +887,7 @@ abstract class Ethereum {
   Web3Client? getWeb3Client(WalletBase wallet);
   String getTokenAddress(CryptoCurrency asset);
   
-  void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device);
+  void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection);
   Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
 }
   """;
@@ -923,7 +925,7 @@ import 'package:cw_core/wallet_credentials.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_service.dart';
 import 'package:hive/hive.dart';
-import 'package:ledger_flutter/ledger_flutter.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
 import 'package:web3dart/web3dart.dart';
 
 """;
@@ -989,7 +991,7 @@ abstract class Polygon {
   Web3Client? getWeb3Client(WalletBase wallet);
   String getTokenAddress(CryptoCurrency asset);
   
-  void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device);
+  void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection);
   Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
 }
   """;
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index c6444e09c..ad540a359 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -11,6 +11,7 @@
 #include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
 #include <permission_handler_windows/permission_handler_windows_plugin.h>
 #include <share_plus/share_plus_windows_plugin_c_api.h>
+#include <universal_ble/universal_ble_plugin_c_api.h>
 #include <url_launcher_windows/url_launcher_windows.h>
 
 void RegisterPlugins(flutter::PluginRegistry* registry) {
@@ -24,6 +25,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
       registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
   SharePlusWindowsPluginCApiRegisterWithRegistrar(
       registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
+  UniversalBlePluginCApiRegisterWithRegistrar(
+      registry->GetRegistrarForPlugin("UniversalBlePluginCApi"));
   UrlLauncherWindowsRegisterWithRegistrar(
       registry->GetRegistrarForPlugin("UrlLauncherWindows"));
 }
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index 0a0b2f9eb..92431a6fb 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
   flutter_secure_storage_windows
   permission_handler_windows
   share_plus
+  universal_ble
   url_launcher_windows
 )
 

From 4372165b261bcb52818e56966e1295a24e1cf2a2 Mon Sep 17 00:00:00 2001
From: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Date: Thu, 24 Oct 2024 04:20:25 +0100
Subject: [PATCH 17/50] fix: Issue with prevent screenshots implementation on
 iOS (#1729)

---
 ios/Runner/AppDelegate.swift | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index 402f6556b..477d47f7b 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -110,12 +110,12 @@ import workmanager
     
     private func makeSecure() {
         if (!self.window.subviews.contains(textField)) {
+            let view = UIView(frame: CGRect(x: 0, y: 0, width: textField.frame.self.width, height: textField.frame.self.height))
             self.window.addSubview(textField)
-            textField.centerYAnchor.constraint(equalTo: self.window.centerYAnchor).isActive = true
-            textField.centerXAnchor.constraint(equalTo: self.window.centerXAnchor).isActive = true
             self.window.layer.superlayer?.addSublayer(textField.layer)
-            textField.layer.sublayers?.first?.addSublayer(self.window.layer)
+            textField.layer.sublayers?.last!.addSublayer(self.window.layer)
+            textField.leftView = view
+            textField.leftViewMode = .always
         }
     }
-
-}
+}
\ No newline at end of file

From 858e5cac523583ee37255b7eb033d13946686593 Mon Sep 17 00:00:00 2001
From: rottenwheel <92872541+rottenwheel@users.noreply.github.com>
Date: Fri, 25 Oct 2024 21:56:02 +0000
Subject: [PATCH 18/50] spanish: miscellaneous rewording (#1777)

---
 res/values/strings_es.arb | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index a8ad7549a..520c8ea78 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -78,7 +78,7 @@
   "billing_address_info": "Si se le solicita una dirección de facturación, proporcione su dirección de envío",
   "biometric_auth_reason": "Escanee su huella digital para autenticar",
   "bitcoin_dark_theme": "Tema oscuro de Bitcoin",
-  "bitcoin_light_theme": "Tema de la luz de Bitcoin",
+  "bitcoin_light_theme": "Tema claro de Bitcoin",
   "bitcoin_payments_require_1_confirmation": "Los pagos de Bitcoin requieren 1 confirmación, que puede demorar 20 minutos o más. ¡Gracias por su paciencia! Se le enviará un correo electrónico cuando se confirme el pago.",
   "block_remaining": "1 bloqueo restante",
   "Blocks_remaining": "${status} Bloques restantes",
@@ -93,7 +93,7 @@
   "buy_with": "Compra con",
   "by_cake_pay": "por Cake Pay",
   "cake_2fa_preset": "Pastel 2FA preestablecido",
-  "cake_dark_theme": "Tema oscuro del pastel",
+  "cake_dark_theme": "Tema oscuro",
   "cake_pay_account_note": "Regístrese con solo una dirección de correo electrónico para ver y comprar tarjetas. ¡Algunas incluso están disponibles con descuento!",
   "cake_pay_learn_more": "¡Compre y canjee tarjetas de regalo al instante en la aplicación!\nDeslice el dedo de izquierda a derecha para obtener más información.",
   "cake_pay_save_order": "La tarjeta debe enviarse a su correo electrónico dentro de 1 día hábil \n Guardar su ID de pedido:",
@@ -144,9 +144,9 @@
   "confirm_delete_wallet": "Esta acción eliminará esta billetera. ¿Desea continuar?",
   "confirm_fee_deduction": "Confirmar la deducción de la tarifa",
   "confirm_fee_deduction_content": "¿Acepta deducir la tarifa de la producción?",
-  "confirm_passphrase": "Confirmar la frase de pases",
+  "confirm_passphrase": "Confirmar la contraseña",
   "confirm_sending": "Confirmar envío",
-  "confirm_silent_payments_switch_node": "Su nodo actual no admite pagos silenciosos \\ ncake billet cambiará a un nodo compatible, solo para escanear",
+  "confirm_silent_payments_switch_node": "Su nodo actual no admite pagos silenciosos \\ nCake cambiará a un nodo compatible, solo para escanear",
   "confirmations": "Confirmaciones",
   "confirmed": "Saldo confirmado",
   "confirmed_tx": "Confirmado",
@@ -281,7 +281,7 @@
   "etherscan_history": "historia de etherscan",
   "event": "Evento",
   "events": "Eventos",
-  "exchange": "Intercambio",
+  "exchange": "Intercambiar",
   "exchange_incorrect_current_wallet_for_xmr": "Si desea intercambiar XMR desde su billetera de pastel Monero Balance, primero cambie a su billetera Monero.",
   "exchange_new_template": "Nueva plantilla",
   "exchange_provider_unsupported": "¡${providerName} ya no es compatible!",
@@ -826,7 +826,7 @@
   "transaction_priority_slow": "Lento",
   "transaction_sent": "Transacción enviada!",
   "transaction_sent_notice": "Si la pantalla no continúa después de 1 minuto, revisa un explorador de bloques y tu correo electrónico.",
-  "transactions": "Actas",
+  "transactions": "Transacciones",
   "transactions_by_date": "Transacciones por fecha",
   "trongrid_history": "Historia trongrid",
   "trusted": "de confianza",
@@ -939,4 +939,4 @@
   "you_will_get": "Convertir a",
   "you_will_send": "Convertir de",
   "yy": "YY"
-}
\ No newline at end of file
+}

From 54c41d41cd1cd3dec59fafad9fd56eeb0bda671b Mon Sep 17 00:00:00 2001
From: rottenwheel <92872541+rottenwheel@users.noreply.github.com>
Date: Fri, 25 Oct 2024 21:56:21 +0000
Subject: [PATCH 19/50] spanish (#1776)

---
 res/values/strings_es.arb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 520c8ea78..449557671 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -372,8 +372,8 @@
   "litecoin_mweb_dismiss": "Despedir",
   "litecoin_mweb_display_card": "Mostrar tarjeta MWEB",
   "litecoin_mweb_enable_later": "Puede elegir habilitar MWEB nuevamente en la configuración de visualización.",
-  "litecoin_mweb_pegin": "Meter",
-  "litecoin_mweb_pegout": "Estirar la pata",
+  "litecoin_mweb_pegin": "Convertir",
+  "litecoin_mweb_pegout": "Recuperar",
   "litecoin_mweb_scanning": "Escaneo mweb",
   "litecoin_mweb_settings": "Configuración de MWEB",
   "litecoin_mweb_warning": "El uso de MWEB inicialmente descargará ~ 600 MB de datos, y puede tomar hasta 30 minutos según la velocidad de la red. Estos datos iniciales solo se descargarán una vez y estarán disponibles para todas las billeteras de Litecoin",

From 5c206a8b7cf2a9279910a7c97bf2689099a26f0a Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Mon, 28 Oct 2024 02:37:38 +0200
Subject: [PATCH 20/50] fix MobX Exception: computed values issue (#1763)

---
 cw_bitcoin/lib/electrum_wallet_addresses.dart | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart
index 2686d12cc..c29579436 100644
--- a/cw_bitcoin/lib/electrum_wallet_addresses.dart
+++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart
@@ -331,7 +331,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
       );
 
       silentAddresses.add(address);
-      updateAddressesByMatch();
+      Future.delayed(Duration.zero, () => updateAddressesByMatch());
 
       return address;
     }
@@ -348,7 +348,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
       network: network,
     );
     _addresses.add(address);
-    updateAddressesByMatch();
+    Future.delayed(Duration.zero, () => updateAddressesByMatch());
     return address;
   }
 

From 198510533e854f437037573fe0575d73a9b21971 Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Wed, 30 Oct 2024 17:57:26 +0100
Subject: [PATCH 21/50] Fix disappearing recipientAddress for XMR Transactions
 (#1784)

---
 .../transaction_details_view_model.dart       | 29 ++++++++-----------
 1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart
index 1833a0f51..da6699ae6 100644
--- a/lib/view_model/transaction_details_view_model.dart
+++ b/lib/view_model/transaction_details_view_model.dart
@@ -83,18 +83,19 @@ abstract class TransactionDetailsViewModelBase with Store {
         break;
     }
 
-    if (showRecipientAddress && !isRecipientAddressShown) {
-      try {
-        final recipientAddress = transactionDescriptionBox.values
-            .firstWhere((val) => val.id == transactionInfo.txHash)
-            .recipientAddress;
+    final descriptionKey =
+        '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
+    final description = transactionDescriptionBox.values.firstWhere(
+        (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
+        orElse: () => TransactionDescription(id: descriptionKey));
 
-        if (recipientAddress?.isNotEmpty ?? false) {
-          items.add(StandartListItem(
-              title: S.current.transaction_details_recipient_address, value: recipientAddress!));
-        }
-      } catch (_) {
-        // FIX-ME: Unhandled exception
+    if (showRecipientAddress && !isRecipientAddressShown) {
+      final recipientAddress = description.recipientAddress;
+
+      if (recipientAddress?.isNotEmpty ?? false) {
+        items.add(StandartListItem(
+          title: S.current.transaction_details_recipient_address,
+          value: recipientAddress!));
       }
     }
 
@@ -110,12 +111,6 @@ abstract class TransactionDetailsViewModelBase with Store {
           } catch (e) {}
         }));
 
-    final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
-
-    final description = transactionDescriptionBox.values.firstWhere(
-            (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
-        orElse: () => TransactionDescription(id: descriptionKey));
-
     items.add(TextFieldListItem(
         title: S.current.note_tap_to_change,
         value: description.note,

From e501a4131444ea79e6db79348081e5945ee21490 Mon Sep 17 00:00:00 2001
From: tuxsudo <tuxsudo@tux.pizza>
Date: Wed, 30 Oct 2024 14:44:49 -0400
Subject: [PATCH 22/50] Fix the manifest once and for all (#1773)

---
 android/app/src/main/AndroidManifestBase.xml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml
index 98bbb1236..5b080e3ec 100644
--- a/android/app/src/main/AndroidManifestBase.xml
+++ b/android/app/src/main/AndroidManifestBase.xml
@@ -14,7 +14,8 @@
 <!--     required for API 18 - 30 -->
     <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
-    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
 
 <!--     required for API <= 29 -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />

From 5fc649023cda6a802802466559642c5707d16f73 Mon Sep 17 00:00:00 2001
From: oksanaphmn <oksanaphmn@gmail.com>
Date: Wed, 30 Oct 2024 20:50:04 +0200
Subject: [PATCH 23/50] Update README.md (#1770)

---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 1c28f92a2..ca3061e61 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@
 
 # Cake Wallet
 
-Cake Wallet is an open source, non-custodial, and private multi-currency crypto wallet for Android, iOS, macOS, and Linux.
+[Cake Wallet](https://cakewallet.com) is an open source, non-custodial, and private multi-currency crypto wallet for Android, iOS, macOS, and Linux.
 
 Cake Wallet includes support for several cryptocurrencies, including:
 * Monero (XMR)
@@ -26,7 +26,7 @@ Cake Wallet includes support for several cryptocurrencies, including:
 * Ethereum (ETH)
 * Litecoin (LTC)
 * Bitcoin Cash (BCH)
-* Polygon (MATIC)
+* Polygon (Pol)
 * Solana (SOL)
 * Nano (XNO)
 * Haven (XHV)

From 752b6bbebf7e975840f11ff569f13bff7600d1ea Mon Sep 17 00:00:00 2001
From: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Date: Thu, 31 Oct 2024 02:10:40 +0100
Subject: [PATCH 24/50] fix: Generic fixes of bugs from Support (#1774)

---
 cw_bitcoin/lib/electrum_wallet.dart                |  2 ++
 cw_haven/lib/haven_wallet_addresses.dart           |  2 ++
 lib/core/wallet_connect/web3wallet_service.dart    |  8 ++++++++
 lib/entities/fiat_currency.dart                    |  2 +-
 .../desktop_wallet_selection_dropdown.dart         |  8 ++++++--
 .../widgets/modals/bottom_sheet_listener.dart      |  4 +++-
 lib/src/widgets/cake_image_widget.dart             |  2 ++
 lib/src/widgets/services_updates_widget.dart       |  2 ++
 lib/utils/exception_handler.dart                   |  8 ++++++++
 lib/utils/image_utill.dart                         | 14 ++++++++++++--
 10 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 4b80cb201..c05095cf1 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -2270,6 +2270,8 @@ abstract class ElectrumWalletBase extends WalletBase<
       Timer(Duration(seconds: 5), () {
         if (this.syncStatus is NotConnectedSyncStatus ||
             this.syncStatus is LostConnectionSyncStatus) {
+          if (node == null) return;
+
           this.electrumClient.connectToUri(
                 node!.uri,
                 useSSL: node!.useSSL ?? false,
diff --git a/cw_haven/lib/haven_wallet_addresses.dart b/cw_haven/lib/haven_wallet_addresses.dart
index 06de44dff..c3d1ef46c 100644
--- a/cw_haven/lib/haven_wallet_addresses.dart
+++ b/cw_haven/lib/haven_wallet_addresses.dart
@@ -23,6 +23,8 @@ abstract class HavenWalletAddressesBase extends WalletAddressesWithAccount<Accou
   @observable
   String address;
   
+  String get primaryAddress => address;
+  
   // @override
   @observable
   Account? account;
diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart
index adb516817..ba4785643 100644
--- a/lib/core/wallet_connect/web3wallet_service.dart
+++ b/lib/core/wallet_connect/web3wallet_service.dart
@@ -267,6 +267,8 @@ abstract class Web3WalletServiceBase with Store {
 
     final keyForWallet = getKeyForStoringTopicsForWallet();
 
+    if (keyForWallet.isEmpty) return;
+
     final currentTopicsForWallet = getPairingTopicsForWallet(keyForWallet);
 
     final filteredPairings =
@@ -360,6 +362,10 @@ abstract class Web3WalletServiceBase with Store {
   String getKeyForStoringTopicsForWallet() {
     List<ChainKeyModel> chainKeys = walletKeyService.getKeysForChain(appStore.wallet!);
 
+    if (chainKeys.isEmpty) {
+      return '';
+    }
+
     final keyForPairingTopic =
         PreferencesKey.walletConnectPairingTopicsListForWallet(chainKeys.first.publicKey);
 
@@ -386,6 +392,8 @@ abstract class Web3WalletServiceBase with Store {
     // Get key specific to the current wallet
     final key = getKeyForStoringTopicsForWallet();
 
+    if (key.isEmpty) return;
+
     // Get all pairing topics attached to this key
     final pairingTopicsForWallet = getPairingTopicsForWallet(key);
 
diff --git a/lib/entities/fiat_currency.dart b/lib/entities/fiat_currency.dart
index a8e2829d8..1a031ee82 100644
--- a/lib/entities/fiat_currency.dart
+++ b/lib/entities/fiat_currency.dart
@@ -114,7 +114,7 @@ class FiatCurrency extends EnumerableItem<String> with Serializable<String> impl
     FiatCurrency.tur.raw: FiatCurrency.tur,
   };
 
-  static FiatCurrency deserialize({required String raw}) => _all[raw]!;
+  static FiatCurrency deserialize({required String raw}) => _all[raw] ?? FiatCurrency.usd;
 
   @override
   bool operator ==(Object other) => other is FiatCurrency && other.raw == raw;
diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart
index f8cbe9120..0fb629685 100644
--- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart
+++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart
@@ -10,7 +10,6 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/dropdown_item_
 import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart';
 import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
 import 'package:cake_wallet/store/settings_store.dart';
-import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
 import 'package:cake_wallet/themes/extensions/menu_theme.dart';
 import 'package:cake_wallet/utils/show_bar.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
@@ -100,6 +99,11 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
         ),
       ];
 
+      final selectedItem = dropDownItems.firstWhere(
+        (element) => element.isSelected,
+        orElse: () => dropDownItems.first,
+      );
+
       return DropdownButton<DesktopDropdownItem>(
         items: dropDownItems
             .map(
@@ -115,7 +119,7 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
         dropdownColor: themeData.extension<CakeMenuTheme>()!.backgroundColor,
         style: TextStyle(color: themeData.extension<CakeTextTheme>()!.titleColor),
         selectedItemBuilder: (context) => dropDownItems.map((item) => item.child).toList(),
-        value: dropDownItems.firstWhere((element) => element.isSelected),
+        value: selectedItem,
         underline: const SizedBox(),
         focusColor: Colors.transparent,
         borderRadius: BorderRadius.circular(15.0),
diff --git a/lib/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart b/lib/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart
index 30b6af7e0..42bef5135 100644
--- a/lib/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart
+++ b/lib/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart
@@ -52,7 +52,9 @@ class BottomSheetListenerState extends State<BottomSheetListener> {
           );
         },
       );
-      item.completer.complete(value);
+      if (!item.completer.isCompleted) {
+        item.completer.complete(value);
+      }
       widget.bottomSheetService.resetCurrentSheet();
     }
   }
diff --git a/lib/src/widgets/cake_image_widget.dart b/lib/src/widgets/cake_image_widget.dart
index ad02c48dd..2038030c0 100644
--- a/lib/src/widgets/cake_image_widget.dart
+++ b/lib/src/widgets/cake_image_widget.dart
@@ -25,6 +25,7 @@ class CakeImageWidget extends StatelessWidget {
           imageUrl!,
           height: height,
           width: width,
+          errorBuilder: (_, __, ___) => Icon(Icons.error),
         );
       }
 
@@ -33,6 +34,7 @@ class CakeImageWidget extends StatelessWidget {
           imageUrl!,
           height: height,
           width: width,
+          placeholderBuilder: (_) => Icon(Icons.error),
         );
       }
 
diff --git a/lib/src/widgets/services_updates_widget.dart b/lib/src/widgets/services_updates_widget.dart
index 1babd23d0..1787b7118 100644
--- a/lib/src/widgets/services_updates_widget.dart
+++ b/lib/src/widgets/services_updates_widget.dart
@@ -46,6 +46,7 @@ class _ServicesUpdatesWidgetState extends State<ServicesUpdatesWidget> {
           "assets/images/notification_icon.svg",
           color: Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
           width: 30,
+          placeholderBuilder: (_) => Icon(Icons.error),
         ),
       );
     }
@@ -136,6 +137,7 @@ class _ServicesUpdatesWidgetState extends State<ServicesUpdatesWidget> {
                   "assets/images/notification_icon.svg",
                   color: Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
                   width: 30,
+                  placeholderBuilder: (_) => Icon(Icons.error),
                 ),
                 if (state.hasData && state.data!.hasUpdates && !wasOpened)
                   Container(
diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart
index 91797c45e..41ae91d41 100644
--- a/lib/utils/exception_handler.dart
+++ b/lib/utils/exception_handler.dart
@@ -62,6 +62,14 @@ class ExceptionHandler {
 
       await _addDeviceInfo(_file!);
 
+      // Check if a mail client is available
+      final bool canSend = await FlutterMailer.canSendMail();
+
+      if (Platform.isIOS && !canSend) {
+        debugPrint('Mail app is not available');
+        return;
+      }
+
       final MailOptions mailOptions = MailOptions(
         subject: 'Mobile App Issue',
         recipients: ['support@cakewallet.com'],
diff --git a/lib/utils/image_utill.dart b/lib/utils/image_utill.dart
index a138df23a..ef3775e4c 100644
--- a/lib/utils/image_utill.dart
+++ b/lib/utils/image_utill.dart
@@ -53,8 +53,18 @@ class ImageUtil {
             );
     } else {
       return isSvg
-          ? SvgPicture.asset(imagePath, height: _height, width: _width)
-          : Image.asset(imagePath, height: _height, width: _width);
+          ? SvgPicture.asset(
+              imagePath,
+              height: _height,
+              width: _width,
+              placeholderBuilder: (_) => Icon(Icons.error),
+            )
+          : Image.asset(
+              imagePath,
+              height: _height,
+              width: _width,
+              errorBuilder: (_, __, ___) => Icon(Icons.error),
+            );
     }
   }
 }

From 740f466e77464090f1e4c9457f3c4abeb7c2181e Mon Sep 17 00:00:00 2001
From: Rafael <github@rafael.saes.dev>
Date: Fri, 1 Nov 2024 14:34:17 -0300
Subject: [PATCH 25/50] fix: sp filter option (#1780)

* fix: sp filter option

* fix: nullable
---
 .../dashboard/transaction_filter_store.dart      |  5 +++--
 .../dashboard/dashboard_view_model.dart          | 16 ++++++++++------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/lib/store/dashboard/transaction_filter_store.dart b/lib/store/dashboard/transaction_filter_store.dart
index fb9ee14cd..f28f7e915 100644
--- a/lib/store/dashboard/transaction_filter_store.dart
+++ b/lib/store/dashboard/transaction_filter_store.dart
@@ -91,8 +91,9 @@ abstract class TransactionFilterStoreBase with Store {
                 (displayOutgoing && item.transaction.direction == TransactionDirection.outgoing) ||
                     (displayIncoming &&
                         item.transaction.direction == TransactionDirection.incoming &&
-                        !bitcoin!.txIsReceivedSilentPayment(item.transaction)) ||
-                    (displaySilentPayments && bitcoin!.txIsReceivedSilentPayment(item.transaction));
+                        !(bitcoin?.txIsReceivedSilentPayment(item.transaction) ?? false)) ||
+                    (displaySilentPayments &&
+                        (bitcoin?.txIsReceivedSilentPayment(item.transaction) ?? false));
           } else if (item is AnonpayTransactionListItem) {
             allowed = displayIncoming;
           }
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 53a8277ab..423babefc 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -90,11 +90,12 @@ abstract class DashboardViewModelBase with Store {
                 value: () => transactionFilterStore.displayOutgoing,
                 caption: S.current.outgoing,
                 onChanged: transactionFilterStore.toggleOutgoing),
-            FilterItem(
-              value: () => transactionFilterStore.displaySilentPayments,
-              caption: S.current.silent_payments,
-              onChanged: transactionFilterStore.toggleSilentPayments,
-            ),
+            if (appStore.wallet!.type == WalletType.bitcoin)
+              FilterItem(
+                value: () => transactionFilterStore.displaySilentPayments,
+                caption: S.current.silent_payments,
+                onChanged: transactionFilterStore.toggleSilentPayments,
+              ),
             // FilterItem(
             //     value: () => false,
             //     caption: S.current.transactions_by_date,
@@ -435,7 +436,10 @@ abstract class DashboardViewModelBase with Store {
   }
 
   @computed
-  bool get hasMweb => wallet.type == WalletType.litecoin && (Platform.isIOS || Platform.isAndroid) && !wallet.isHardwareWallet;
+  bool get hasMweb =>
+      wallet.type == WalletType.litecoin &&
+      (Platform.isIOS || Platform.isAndroid) &&
+      !wallet.isHardwareWallet;
 
   @computed
   bool get showMwebCard => hasMweb && settingsStore.mwebCardDisplay && !mwebEnabled;

From 4916d1f4576e72542a57fcc8052e6a5038d25da2 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Fri, 1 Nov 2024 19:54:17 +0200
Subject: [PATCH 26/50]  fix the issue with updating sending outputs (#1785)

---
 lib/view_model/send/send_view_model.dart | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 24e83f364..1403eb109 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -400,7 +400,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
         final updatedOutputs = bitcoin!.updateOutputs(pendingTransaction!, outputs);
 
         if (outputs.length == updatedOutputs.length) {
-          outputs = ObservableList.of(updatedOutputs);
+          outputs.clear();
+          outputs.addAll(updatedOutputs);
         }
       }
 

From 72241d49114afeb61a8551b53b9853fd695884af Mon Sep 17 00:00:00 2001
From: rottenwheel <92872541+rottenwheel@users.noreply.github.com>
Date: Fri, 1 Nov 2024 21:57:17 +0000
Subject: [PATCH 27/50] spanish: tidy up and reword a lot of ES translations;
 catch missed unstralated strings (#1788)

---
 res/values/strings_es.arb | 312 +++++++++++++++++++-------------------
 1 file changed, 156 insertions(+), 156 deletions(-)

diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 449557671..25c9f95c1 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -1,5 +1,5 @@
 {
-  "about_cake_pay": "Cake Pay le permite comprar fácilmente tarjetas de regalo con activos virtuales, gastables instantáneamente en más de 150 000 comerciantes en los Estados Unidos.",
+  "about_cake_pay": "Cake Pay te permite comprar fácilmente tarjetas de regalo con activos virtuales, gastables instantáneamente en más de 150,000 comerciantes en los Estados Unidos.",
   "account": "Cuenta",
   "accounts": "Cuentas",
   "accounts_subaddresses": "Cuentas y subdirecciones",
@@ -21,13 +21,13 @@
   "add_token_disclaimer_check": "He confirmado la dirección del contrato del token y la información utilizando una fuente confiable. Agregar información maliciosa o incorrecta puede resultar en una pérdida de fondos.",
   "add_token_warning": "No edite ni agregue tokens según las instrucciones de los estafadores.\n¡Confirme siempre las direcciones de los tokens con fuentes acreditadas!",
   "add_value": "Añadir valor",
-  "address": "DIRECCIÓN",
+  "address": "Dirección",
   "address_book": "Libreta de direcciones",
   "address_book_menu": "Libreta de direcciones",
   "address_detected": "Dirección detectada",
   "address_from_domain": "Esta dirección es de ${domain} en Unstoppable Domains",
   "address_from_yat": "Esta dirección es de ${emoji} en Yat",
-  "address_label": "Address label",
+  "address_label": "Etiqueta de dirección",
   "address_remove_contact": "Remover contacto",
   "address_remove_content": "¿Estás seguro de que quieres eliminar el contacto seleccionado?",
   "addresses": "Direcciones",
@@ -37,12 +37,12 @@
   "agree_and_continue": "Aceptar y continuar",
   "agree_to": "Al crear una cuenta, aceptas ",
   "alert_notice": "Aviso",
-  "all": "TODOS",
+  "all": "Todos",
   "all_trades": "Todos los oficios",
   "all_transactions": "Todas las transacciones",
   "alphabetical": "Alfabético",
   "already_have_account": "¿Ya tienes una cuenta?",
-  "always": "siempre",
+  "always": "Siempre",
   "amount": "Cantidad: ",
   "amount_is_below_minimum_limit": "Su saldo después de las tarifas sería menor que la cantidad mínima necesaria para el intercambio (${min})",
   "amount_is_estimate": "El monto recibido es un estimado",
@@ -54,17 +54,17 @@
   "arrive_in_this_address": "${currency} ${tag}llegará a esta dirección",
   "ascending": "Ascendente",
   "ask_each_time": "Pregunta cada vez",
-  "auth_store_ban_timeout": "prohibición de tiempo de espera",
+  "auth_store_ban_timeout": "Prohibición de tiempo de espera",
   "auth_store_banned_for": "Prohibido para ",
   "auth_store_banned_minutes": " minutos",
   "auth_store_incorrect_password": "Contraseña PIN",
   "authenticated": "Autenticados",
   "authentication": "Autenticación",
-  "auto_generate_addresses": "Auto Generar direcciones",
+  "auto_generate_addresses": "Auto-generar nuevas direcciones",
   "auto_generate_subaddresses": "Generar subdirecciones automáticamente",
   "automatic": "Automático",
   "available_balance": "Balance disponible",
-  "available_balance_description": "Su saldo disponible es la cantidad de fondos que puede gastar. Los fondos que se muestran aquí se pueden gastar inmediatamente.",
+  "available_balance_description": "Tu saldo disponible es la cantidad de fondos que puedes gastar. Los fondos que se muestran aquí, se pueden gastar inmediatamente.",
   "avg_savings": "Ahorro promedio",
   "awaitDAppProcessing": "Espere a que la dApp termine de procesarse.",
   "awaiting_payment_confirmation": "Esperando confirmación de pago",
@@ -79,7 +79,7 @@
   "biometric_auth_reason": "Escanee su huella digital para autenticar",
   "bitcoin_dark_theme": "Tema oscuro de Bitcoin",
   "bitcoin_light_theme": "Tema claro de Bitcoin",
-  "bitcoin_payments_require_1_confirmation": "Los pagos de Bitcoin requieren 1 confirmación, que puede demorar 20 minutos o más. ¡Gracias por su paciencia! Se le enviará un correo electrónico cuando se confirme el pago.",
+  "bitcoin_payments_require_1_confirmation": "Los pagos de Bitcoin requieren 1 confirmación, que puede demorar 20 minutos o más. ¡Gracias por tu paciencia! Se te enviará un correo electrónico cuando se confirme el pago.",
   "block_remaining": "1 bloqueo restante",
   "Blocks_remaining": "${status} Bloques restantes",
   "bluetooth": "Bluetooth",
@@ -94,25 +94,25 @@
   "by_cake_pay": "por Cake Pay",
   "cake_2fa_preset": "Pastel 2FA preestablecido",
   "cake_dark_theme": "Tema oscuro",
-  "cake_pay_account_note": "Regístrese con solo una dirección de correo electrónico para ver y comprar tarjetas. ¡Algunas incluso están disponibles con descuento!",
-  "cake_pay_learn_more": "¡Compre y canjee tarjetas de regalo al instante en la aplicación!\nDeslice el dedo de izquierda a derecha para obtener más información.",
-  "cake_pay_save_order": "La tarjeta debe enviarse a su correo electrónico dentro de 1 día hábil \n Guardar su ID de pedido:",
-  "cake_pay_subtitle": "Compre tarjetas prepagas y tarjetas de regalo en todo el mundo",
-  "cake_pay_web_cards_subtitle": "Compre tarjetas de prepago y tarjetas de regalo en todo el mundo",
+  "cake_pay_account_note": "Regístrate con solo una dirección de correo electrónico para ver y comprar tarjetas. ¡Algunas incluso están disponibles con descuento!",
+  "cake_pay_learn_more": "¡Compra y canjea tarjetas de regalo al instante en la aplicación!\nDesliza el dedo de izquierda a derecha para obtener más información.",
+  "cake_pay_save_order": "La tarjeta debe enviarse a tu correo electrónico dentro de 1 día hábil \n Guardar su ID de pedido:",
+  "cake_pay_subtitle": "Compra tarjetas prepagadas y tarjetas de regalo en todo el mundo",
+  "cake_pay_web_cards_subtitle": "Compra tarjetas de prepago y tarjetas de regalo en todo el mundo",
   "cake_pay_web_cards_title": "Tarjetas Web Cake Pay",
   "cake_wallet": "Cake Wallet",
   "cakepay_prepaid_card": "Tarjeta de Débito Prepago CakePay",
-  "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulte su Política de privacidad para obtener más detalles.",
-  "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.",
+  "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulta tu Política de privacidad para obtener más detalles.",
+  "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítalo desde la configuración de la aplicación.",
   "cancel": "Cancelar",
   "card_address": "Dirección:",
   "cardholder_agreement": "Acuerdo del titular de la tarjeta",
   "cards": "Cartas",
   "chains": "Cadenas",
   "change": "Cambio",
-  "change_backup_password_alert": "Sus archivos de respaldo anteriores no estarán disponibles para importar con la nueva contraseña de respaldo. La nueva contraseña de respaldo se utilizará solo para los nuevos archivos de respaldo. ¿Está seguro de que desea cambiar la contraseña de respaldo?",
+  "change_backup_password_alert": "Tus archivos de respaldo anteriores no estarán disponibles para importar con la nueva contraseña de respaldo. La nueva contraseña de respaldo se utilizará solo para los nuevos archivos de respaldo. ¿Está seguro de que desea cambiar la contraseña de respaldo?",
   "change_currency": "Cambiar moneda",
-  "change_current_node": "¿Está seguro de cambiar el nodo actual a ${node}?",
+  "change_current_node": "¿Estás seguro de cambiar el nodo actual a ${node}?",
   "change_current_node_title": "Cambiar el nodo actual",
   "change_exchange_provider": "Cambiar proveedor de intercambio",
   "change_language": "Cambiar idioma",
@@ -125,38 +125,38 @@
   "change_wallet_alert_title": "Cambiar billetera actual",
   "choose_account": "Elegir cuenta",
   "choose_address": "\n\nPor favor elija la dirección:",
-  "choose_card_value": "Elija un valor de tarjeta",
-  "choose_derivation": "Elija la derivación de la billetera",
-  "choose_from_available_options": "Elija entre las opciones disponibles:",
+  "choose_card_value": "Elige un valor de tarjeta",
+  "choose_derivation": "Elige la derivación de la billetera",
+  "choose_from_available_options": "Elige entre las opciones disponibles:",
   "choose_one": "Elige uno",
-  "choose_relay": "Por favor elija un relé para usar",
-  "choose_wallet_currency": "Por favor, elija la moneda de la billetera:",
-  "choose_wallet_group": "Elija el grupo de billetera",
+  "choose_relay": "Por favor elige un relay para usar",
+  "choose_wallet_currency": "Por favor, elige la moneda de la billetera:",
+  "choose_wallet_group": "Elige el grupo de billetera",
   "clear": "Claro",
   "clearnet_link": "enlace Clearnet",
   "close": "Cerca",
   "coin_control": "Control de monedas (opcional)",
-  "cold_or_recover_wallet": "Agregue una billetera fría o recupere una billetera de papel",
+  "cold_or_recover_wallet": "Agrega una billetera fría o recupera una billetera de papel",
   "color_theme": "Tema de color",
   "commit_transaction_amount_fee": "Confirmar transacción\nCantidad: ${amount}\nCuota: ${fee}",
   "confirm": "Confirmar",
-  "confirm_delete_template": "Esta acción eliminará esta plantilla. ¿Desea continuar?",
-  "confirm_delete_wallet": "Esta acción eliminará esta billetera. ¿Desea continuar?",
+  "confirm_delete_template": "Esta acción eliminará esta plantilla. ¿Deseas continuar?",
+  "confirm_delete_wallet": "Esta acción eliminará esta billetera. ¿Deseas continuar?",
   "confirm_fee_deduction": "Confirmar la deducción de la tarifa",
-  "confirm_fee_deduction_content": "¿Acepta deducir la tarifa de la producción?",
+  "confirm_fee_deduction_content": "¿Aceptas deducir la tarifa de la producción?",
   "confirm_passphrase": "Confirmar la contraseña",
   "confirm_sending": "Confirmar envío",
-  "confirm_silent_payments_switch_node": "Su nodo actual no admite pagos silenciosos \\ nCake cambiará a un nodo compatible, solo para escanear",
+  "confirm_silent_payments_switch_node": "Tu nodo actual no admite pagos silenciosos \\ nCake cambiará a un nodo compatible, solo para escanear",
   "confirmations": "Confirmaciones",
   "confirmed": "Saldo confirmado",
   "confirmed_tx": "Confirmado",
   "congratulations": "Felicidades!",
   "connect_an_existing_yat": "Conectar un Yat existente",
   "connect_yats": "Conectar Yats",
-  "connect_your_hardware_wallet": "Conecte su billetera de hardware con Bluetooth o USB",
-  "connect_your_hardware_wallet_ios": "Conecte su billetera de hardware con Bluetooth",
+  "connect_your_hardware_wallet": "Conecta tu billetera de hardware con Bluetooth o USB",
+  "connect_your_hardware_wallet_ios": "Conecta tu billetera de hardware con Bluetooth",
   "connection_sync": "Conexión y sincronización",
-  "connectWalletPrompt": "Conecte su billetera con WalletConnect para realizar transacciones",
+  "connectWalletPrompt": "Conecte tu billetera con WalletConnect para realizar transacciones",
   "contact": "Contacto",
   "contact_list_contacts": "Contactos",
   "contact_list_wallets": "Mis billeteras",
@@ -187,7 +187,7 @@
   "custom_drag": "Custom (mantenía y arrastre)",
   "custom_redeem_amount": "Cantidad de canje personalizada",
   "custom_value": "Valor personalizado",
-  "dark_theme": "Oscura",
+  "dark_theme": "Oscuro",
   "debit_card": "Tarjeta de Débito",
   "debit_card_terms": "El almacenamiento y el uso de su número de tarjeta de pago (y las credenciales correspondientes a su número de tarjeta de pago) en esta billetera digital están sujetos a los Términos y condiciones del acuerdo del titular de la tarjeta aplicable con el emisor de la tarjeta de pago, en vigor desde tiempo al tiempo.",
   "decimal_places_error": "Demasiados lugares decimales",
@@ -197,21 +197,21 @@
   "delete": "Borrar",
   "delete_account": "Eliminar cuenta",
   "delete_wallet": "Eliminar billetera",
-  "delete_wallet_confirm_message": "¿Está seguro de que desea eliminar la billetera ${wallet_name}?",
-  "deleteConnectionConfirmationPrompt": "¿Está seguro de que desea eliminar la conexión a",
+  "delete_wallet_confirm_message": "¿Estás seguro de que deseas eliminar la billetera ${wallet_name}?",
+  "deleteConnectionConfirmationPrompt": "¿Estás seguro de que deseas eliminar la conexión a",
   "denominations": "Denominaciones",
   "derivationpath": "Ruta de derivación",
   "descending": "Descendente",
   "description": "Descripción",
   "destination_tag": "Etiqueta de destino:",
-  "dfx_option_description": "Compre criptografía con EUR y CHF. Para clientes minoristas y corporativos en Europa",
+  "dfx_option_description": "Compre cripto con EUR y CHF. Para clientes minoristas y corporativos en Europa",
   "didnt_get_code": "¿No recibiste el código?",
   "digit_pin": "-dígito PIN",
   "digital_and_physical_card": " tarjeta de débito prepago digital y física",
   "disable": "Desactivar",
   "disable_bulletin": "Desactivar el boletín de estado del servicio",
   "disable_buy": "Desactivar acción de compra",
-  "disable_cake_2fa": "Desactivar pastel 2FA",
+  "disable_cake_2fa": "Desactivar 2FA",
   "disable_exchange": "Deshabilitar 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",
@@ -224,7 +224,7 @@
   "displayable": "Visualizable",
   "do_not_have_enough_gas_asset": "No tienes suficiente ${currency} para realizar una transacción con las condiciones actuales de la red blockchain. Necesita más ${currency} para pagar las tarifas de la red blockchain, incluso si envía un activo diferente.",
   "do_not_send": "no enviar",
-  "do_not_share_warning_text": "No comparta estos con nadie más, incluido el soporte.\n\n¡Sus fondos pueden ser y serán robados!",
+  "do_not_share_warning_text": "No compartas estos con nadie más, incluido el soporte.\n\n¡Tus fondos pueden ser y serán robados!",
   "do_not_show_me": "no me muestres esto otra vez",
   "domain_looks_up": "Búsquedas de dominio",
   "donation_link_details": "Detalles del enlace de donación",
@@ -238,21 +238,21 @@
   "enable": "Permitir",
   "enable_mempool_api": "API de Mempool para tarifas y fechas precisas",
   "enable_replace_by_fee": "Habilitar reemplazar por tarea",
-  "enable_silent_payments_scanning": "Comience a escanear pagos silenciosos, hasta que se alcance la punta",
+  "enable_silent_payments_scanning": "Comienza a escanear pagos silenciosos, hasta que se alcance la altura actual",
   "enabled": "Activado",
-  "enter_amount": "Ingrese la cantidad",
-  "enter_backup_password": "Ingrese la contraseña de respaldo aquí",
+  "enter_amount": "Ingresa la cantidad",
+  "enter_backup_password": "Ingresa la contraseña de respaldo aquí",
   "enter_code": "Ingresar código",
-  "enter_seed_phrase": "Ingrese su frase de semillas",
-  "enter_totp_code": "Ingrese el código TOTP.",
-  "enter_wallet_password": "Ingrese la contraseña de la billetera",
+  "enter_seed_phrase": "Ingresa su frase de semillas",
+  "enter_totp_code": "Ingresa el código TOTP.",
+  "enter_wallet_password": "Ingresa la contraseña de la billetera",
   "enter_your_note": "Ingresa tu nota…",
   "enter_your_pin": "Introduce tu PIN",
-  "enter_your_pin_again": "Ingrese su PIN nuevamente",
-  "enterTokenID": "Ingrese el ID del token",
-  "enterWalletConnectURI": "Ingrese el URI de WalletConnect",
+  "enter_your_pin_again": "Ingresa su PIN nuevamente",
+  "enterTokenID": "Ingresa el ID del token",
+  "enterWalletConnectURI": "Ingresa el URI de WalletConnect",
   "error": "Error",
-  "error_dialog_content": "Vaya, tenemos un error.\n\nEnvíe el informe de bloqueo a nuestro equipo de soporte para mejorar la aplicación.",
+  "error_dialog_content": "Vaya, tenemos un error.\n\nEnvía el informe de error a nuestro equipo de soporte para mejorar la aplicación.",
   "error_text_account_name": "El nombre de la cuenta solo puede contener letras, números \ny debe tener entre 1 y 15 caracteres de longitud",
   "error_text_address": "La dirección de la billetera debe corresponder al tipo \nde criptomoneda",
   "error_text_amount": "La cantidad solo puede contener números",
@@ -304,14 +304,14 @@
   "fee_rate": "Tarifa",
   "fetching": "Cargando",
   "fiat_api": "Fiat API",
-  "fiat_balance": "Equilibrio Fiat",
+  "fiat_balance": "Balance fiat",
   "field_required": "Este campo es obligatorio",
-  "fill_code": "Por favor complete el código de verificación proporcionado a su correo electrónico",
+  "fill_code": "Por favor completa el código de verificación proporcionado en tu correo electrónico",
   "filter_by": "Filtrado por",
   "first_wallet_text": "Impresionante billetera para Monero, Bitcoin, Ethereum, Litecoin, y Haven",
   "fixed_pair_not_supported": "Este par fijo no es compatible con los servicios de intercambio seleccionados",
   "fixed_rate": "Tipo de interés fijo",
-  "fixed_rate_alert": "Podrá ingresar la cantidad recibida cuando el modo de tarifa fija esté marcado. ¿Quieres cambiar al modo de tarifa fija?",
+  "fixed_rate_alert": "Podrás ingresar la cantidad recibida cuando el modo de tarifa fija esté marcado. ¿Quieres cambiar al modo de tarifa fija?",
   "forgot_password": "Olvidé mi contraseña",
   "freeze": "Congelar",
   "frequently_asked_questions": "Preguntas frecuentes",
@@ -333,7 +333,7 @@
   "gross_balance": "Saldo bruto",
   "group_by_type": "Grupo por tipo",
   "haven_app": "Haven by Cake Wallet",
-  "haven_app_wallet_text": "Awesome wallet for Haven",
+  "haven_app_wallet_text": "Increíble billetera para Haven",
   "help": "ayuda",
   "hidden_balance": "Balance oculto",
   "hide_details": "Ocultar detalles",
@@ -349,9 +349,9 @@
   "incoming": "Entrante",
   "incorrect_seed": "El texto ingresado no es válido.",
   "inputs": "Entradas",
-  "insufficient_lamport_for_tx": "No tiene suficiente SOL para cubrir la transacción y su tarifa de transacción. Por favor, agregue más SOL a su billetera o reduzca la cantidad de sol que está enviando.",
-  "insufficient_lamports": "No tiene suficiente SOL para cubrir la transacción y su tarifa de transacción. Necesita al menos ${solValueNeeded} sol. Por favor, agregue más sol a su billetera o reduzca la cantidad de sol que está enviando",
-  "insufficientFundsForRentError": "No tiene suficiente SOL para cubrir la tarifa de transacción y alquilar para la cuenta. Por favor, agregue más sol a su billetera o reduzca la cantidad de sol que está enviando",
+  "insufficient_lamport_for_tx": "No tienes suficiente SOL para cubrir la transacción y su tarifa de transacción. Por favor, agrega más SOL a su billetera o reduce la cantidad de sol que está enviando.",
+  "insufficient_lamports": "No tienes suficiente SOL para cubrir la transacción y su tarifa de transacción. Necesita al menos ${solValueNeeded} sol. Por favor, agrega más sol a su billetera o reduzca la cantidad de sol que está enviando",
+  "insufficientFundsForRentError": "No tienes suficiente SOL para cubrir la tarifa de transacción y alquilar para la cuenta. Por favor, agrega más sol a su billetera o reduce la cantidad de sol que está enviando",
   "introducing_cake_pay": "¡Presentamos Cake Pay!",
   "invalid_input": "Entrada inválida",
   "invalid_password": "Contraseña invalida",
@@ -359,12 +359,12 @@
   "is_percentage": "es",
   "last_30_days": "Últimos 30 días",
   "learn_more": "Aprende más",
-  "ledger_connection_error": "No se pudo conectar con su libro mayor. Inténtalo de nuevo.",
-  "ledger_error_device_locked": "El libro mayor está bloqueado",
+  "ledger_connection_error": "No se pudo conectar con ledger. Inténtalo de nuevo.",
+  "ledger_error_device_locked": "Ledger está bloqueado",
   "ledger_error_tx_rejected_by_user": "Transacción rechazada en el dispositivo",
-  "ledger_error_wrong_app": "Por favor, asegúrese de abrir la aplicación correcta en su libro mayor.",
-  "ledger_please_enable_bluetooth": "Habilite Bluetooth para detectar su libro mayor",
-  "light_theme": "Ligera",
+  "ledger_error_wrong_app": "Por favor, asegúrate de abrir la aplicación correcta en su libro mayor.",
+  "ledger_please_enable_bluetooth": "Habilita tu Bluetooth para detectar tu ledger",
+  "light_theme": "Ligero",
   "litecoin_enable_mweb_sync": "Habilitar el escaneo mweb",
   "litecoin_mweb": "Mweb",
   "litecoin_mweb_always_scan": "Establecer mweb siempre escaneo",
@@ -401,9 +401,9 @@
   "min_value": "Min: ${value} ${currency}",
   "minutes_to_pin_code": "${minute} minutos",
   "mm": "mm",
-  "modify_2fa": "Modificar torta 2FA",
-  "monero_com": "Monero.com by Cake Wallet",
-  "monero_com_wallet_text": "Awesome wallet for Monero",
+  "modify_2fa": "Modificar 2FA",
+  "monero_com": "Monero.com por Cake Wallet",
+  "monero_com_wallet_text": "Increíble billetera para Monero",
   "monero_dark_theme": "Tema oscuro de Monero",
   "monero_light_theme": "Tema ligero de Monero",
   "moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}",
@@ -412,12 +412,12 @@
   "mweb_unconfirmed": "Mweb no confirmado",
   "name": "Nombre",
   "nano_current_rep": "Representante actual",
-  "nano_gpt_thanks_message": "¡Gracias por usar nanogpt! ¡Recuerde regresar al navegador después de que se complete su transacción!",
+  "nano_gpt_thanks_message": "¡Gracias por usar nanogpt! ¡Recuerda regresar al navegador después de que se complete su transacción!",
   "nano_pick_new_rep": "Elija un nuevo representante",
   "nanogpt_subtitle": "Todos los modelos más nuevos (GPT-4, Claude). \\nSin suscripción, pague con cripto.",
   "narrow": "Angosto",
-  "new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura",
-  "new_node_testing": "Prueba de nuevos nodos",
+  "new_first_wallet_text": "Mantén fácilmente tu criptomoneda segura",
+  "new_node_testing": "Prueba nuevos nodos",
   "new_subaddress_create": "Crear",
   "new_subaddress_label_name": "Nombre de etiqueta",
   "new_subaddress_title": "Nueva direccion",
@@ -426,10 +426,10 @@
   "newConnection": "Nueva conexión",
   "no_cards_found": "No se encuentran cartas",
   "no_id_needed": "¡No se necesita identificación!",
-  "no_id_required": "No se requiere identificación. Recargue y gaste en cualquier lugar",
-  "no_relay_on_domain": "No hay una retransmisión para el dominio del usuario o la retransmisión no está disponible. Elija un relé para usar.",
-  "no_relays": "Sin relevos",
-  "no_relays_message": "Encontramos un registro Nostr NIP-05 para este usuario, pero no contiene ningún relé. Indique al destinatario que agregue retransmisiones a su registro Nostr.",
+  "no_id_required": "No se requiere identificación. Recarga y gaste en cualquier lugar",
+  "no_relay_on_domain": "No hay una retransmisión para el dominio del usuario o la retransmisión no está disponible. Elige un relay para usar.",
+  "no_relays": "Sin relays",
+  "no_relays_message": "Encontramos un registro Nostr NIP-05 para este usuario, pero no contiene ningún relay. Indica al destinatario que agregue retransmisiones a su registro Nostr.",
   "node_address": "Dirección de nodo",
   "node_connection_failed": "La conexión falló",
   "node_connection_successful": "La conexión fue exitosa",
@@ -449,15 +449,15 @@
   "offline": "fuera de línea",
   "ok": "OK",
   "old_fee": "Tarifa antigua",
-  "onion_link": "Enlace de cebolla",
+  "onion_link": "Enlace de cebolla (Tor)",
   "online": "En línea",
-  "onramper_option_description": "Compre rápidamente cripto con muchos métodos de pago. Disponible en la mayoría de los países. Los diferenciales y las tarifas varían.",
+  "onramper_option_description": "Compra rápidamente cripto con muchos métodos de pago. Disponible en la mayoría de los países. Los diferenciales y las tarifas varían.",
   "open_gift_card": "Abrir tarjeta de regalo",
   "optional_description": "Descripción opcional",
   "optional_email_hint": "Correo electrónico de notificación del beneficiario opcional",
   "optional_name": "Nombre del destinatario opcional",
   "optionally_order_card": "Opcionalmente pide una tarjeta física.",
-  "orbot_running_alert": "Asegúrese de que Orbot se esté ejecutando antes de conectarse a este nodo.",
+  "orbot_running_alert": "Asegúrate de que Orbot se esté ejecutando antes de conectarte a este nodo.",
   "order_by": "Ordenar",
   "order_id": "Identificación del pedido",
   "order_physical_card": "Pedir tarjeta física",
@@ -466,7 +466,7 @@
   "outdated_electrum_wallet_receive_warning": "Si esta billetera tiene una semilla de 12 palabras y se creó en Cake, NO deposite Bitcoin en esta billetera. Cualquier BTC transferido a esta billetera se puede perder. Cree una nueva billetera de 24 palabras (toque el menú en la parte superior derecha, seleccione Monederos, elija Crear nueva billetera, luego seleccione Bitcoin) e INMEDIATAMENTE mueva su BTC allí. Las nuevas carteras BTC (24 palabras) de Cake son seguras",
   "outgoing": "Saliente",
   "outputs": "Salidas",
-  "overwrite_amount": "Overwrite amount",
+  "overwrite_amount": "Sobreescribir monto",
   "pairingInvalidEvent": "Evento de emparejamiento no válido",
   "passphrase": "Passfrase (opcional)",
   "passphrases_doesnt_match": "Las frases de contrato no coinciden, intente nuevamente",
@@ -482,18 +482,18 @@
   "pin_is_incorrect": "PIN es incorrecto",
   "pin_number": "Número PIN",
   "placeholder_contacts": "Tus contactos se mostrarán aquí",
-  "placeholder_transactions": "Sus transacciones se mostrarán aquí",
-  "please_fill_totp": "Complete el código de 8 dígitos presente en su otro dispositivo",
-  "please_make_selection": "Seleccione a continuación para crear o recuperar su billetera.",
-  "please_reference_document": "Consulte los documentos a continuación para obtener más información.",
-  "please_select": "Por favor seleccione:",
-  "please_select_backup_file": "Seleccione el archivo de respaldo e ingrese la contraseña de respaldo.",
+  "placeholder_transactions": "Tus transacciones se mostrarán aquí",
+  "please_fill_totp": "Completa el código de 8 dígitos presente en su otro dispositivo",
+  "please_make_selection": "Selecciona a continuación para crear o recuperar su billetera.",
+  "please_reference_document": "Consulta los documentos a continuación para obtener más información.",
+  "please_select": "Por favor selecciona:",
+  "please_select_backup_file": "Selecciona el archivo de respaldo e ingrese la contraseña de respaldo.",
   "please_try_to_connect_to_another_node": "Intenta conectarte a otro nodo",
-  "please_wait": "Espere por favor",
+  "please_wait": "Espera por favor",
   "polygonscan_history": "Historial de PolygonScan",
-  "powered_by": "Energizado por ${title}",
+  "powered_by": "Posible gracias a ${title}",
   "pre_seed_button_text": "Entiendo. Muéstrame mi semilla",
-  "pre_seed_description": "En la página siguiente verá una serie de ${words} palabras. Esta es su semilla única y privada y es la ÚNICA forma de recuperar su billetera en caso de pérdida o mal funcionamiento. Es SU responsabilidad escribirlo y guardarlo en un lugar seguro fuera de la aplicación Cake Wallet.",
+  "pre_seed_description": "En la página siguiente verás una serie de ${words} palabras. Esta es su semilla única y privada y es la ÚNICA forma de recuperar tu billetera en caso de pérdida o mal funcionamiento. Es TU responsabilidad escribirla y guardarla en un lugar seguro fuera de la aplicación Cake Wallet.",
   "pre_seed_title": "IMPORTANTE",
   "prepaid_cards": "Tajetas prepagadas",
   "prevent_screenshots": "Evitar capturas de pantalla y grabación de pantalla",
@@ -502,17 +502,17 @@
   "privacy_settings": "Configuración de privacidad",
   "private_key": "Clave privada",
   "proceed_after_one_minute": "Si la pantalla no continúa después de 1 minuto, revisa tu correo electrónico.",
-  "proceed_on_device": "Continúe con su dispositivo",
-  "proceed_on_device_description": "Siga las instrucciones solicitadas en su billetera de hardware",
+  "proceed_on_device": "Continúa con tu dispositivo",
+  "proceed_on_device_description": "Sigue las instrucciones solicitadas en su billetera de hardware",
   "profile": "Perfil",
   "provider_error": "${provider} error",
   "public_key": "Clave pública",
   "purchase_gift_card": "Comprar tarjeta de regalo",
   "purple_dark_theme": "Tema morado oscuro",
   "qr_fullscreen": "Toque para abrir el código QR en pantalla completa",
-  "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?",
+  "qr_payment_amount": "Este código QR contiene un monto de pago. ¿Quieres sobreescribirlo?",
   "quantity": "Cantidad",
-  "question_to_disable_2fa": "¿Está seguro de que desea deshabilitar Cake 2FA? Ya no se necesitará un código 2FA para acceder a la billetera y a ciertas funciones.",
+  "question_to_disable_2fa": "¿Estás seguro de que desea deshabilitar Cake 2FA? Ya no se necesitará un código 2FA para acceder a la billetera y a ciertas funciones.",
   "receivable_balance": "Saldo de cuentas por cobrar",
   "receive": "Recibir",
   "receive_amount": "Cantidad",
@@ -529,12 +529,12 @@
   "remaining": "restante",
   "remove": "Retirar",
   "remove_node": "Eliminar nodo",
-  "remove_node_message": "¿Está seguro de que desea eliminar el nodo seleccionado?",
-  "rename": "Rebautizar",
+  "remove_node_message": "¿Estás seguro de que desea eliminar el nodo seleccionado?",
+  "rename": "Renombrar",
   "rep_warning": "Advertencia representativa",
-  "rep_warning_sub": "Su representante no parece estar en buena posición. Toque aquí para seleccionar uno nuevo",
-  "repeat_wallet_password": "Repita la contraseña de billetera",
-  "repeated_password_is_incorrect": "La contraseña repetida es incorrecta. Repita la contraseña de la billetera nuevamente.",
+  "rep_warning_sub": "Tu representante no parece estar en buena posición. Toca aquí para seleccionar uno nuevo",
+  "repeat_wallet_password": "Repite la contraseña de billetera",
+  "repeated_password_is_incorrect": "La contraseña repetida es incorrecta. Repite la contraseña de la billetera nuevamente.",
   "require_for_adding_contacts": "Requerido para agregar contactos",
   "require_for_all_security_and_backup_settings": "Requerido para todas las configuraciones de seguridad y copia de seguridad",
   "require_for_assessing_wallet": "Requerido para acceder a la billetera",
@@ -566,17 +566,17 @@
   "restore_recover": "Recuperar",
   "restore_restore_wallet": "Recuperar Cartera",
   "restore_seed_keys_restore": "Restauración de semillas / llaves",
-  "restore_spend_key_private": "Spend clave (privado)",
+  "restore_spend_key_private": "Llave de gasto (privada)",
   "restore_title_from_backup": "Restaurar desde un archivo de respaldo",
-  "restore_title_from_hardware_wallet": "Restaurar desde la billetera de hardware",
-  "restore_title_from_keys": "De las claves",
-  "restore_title_from_seed": "De la semilla",
-  "restore_title_from_seed_keys": "Restaurar desde semilla/claves",
-  "restore_view_key_private": "View clave (privado)",
+  "restore_title_from_hardware_wallet": "Restaurar desde una cartera fría",
+  "restore_title_from_keys": "Usando las claves",
+  "restore_title_from_seed": "Usando la semilla",
+  "restore_title_from_seed_keys": "Restaurar usando semilla/claves",
+  "restore_view_key_private": "Llave de vista (privado)",
   "restore_wallet": "Restaurar billetera",
   "restore_wallet_name": "Nombre de la billetera",
   "restore_wallet_restore_description": "Restaurar billetera",
-  "robinhood_option_description": "Compre y transfiera instantáneamente utilizando su tarjeta de débito, cuenta bancaria o saldo de Robinhood. Solo EE. UU.",
+  "robinhood_option_description": "Compra y transfiere instantáneamente utilizando su tarjeta de débito, cuenta bancaria o saldo de Robinhood. Solo EE. UU.",
   "router_no_route": "No hay ruta definida para ${name}",
   "save": "Salvar",
   "save_backup_password": "Asegúrese de haber guardado su contraseña de respaldo. No podrá importar sus archivos de respaldo sin él.",
@@ -585,7 +585,7 @@
   "saved_the_trade_id": "He salvado comercial ID",
   "scan_one_block": "Escanear un bloque",
   "scan_qr_code": "Escanear código QR",
-  "scan_qr_code_to_get_address": "Escanee el código QR para obtener la dirección",
+  "scan_qr_code_to_get_address": "Escanea el código QR para obtener la dirección",
   "scan_qr_on_device": "Escanea este código QR en otro dispositivo",
   "search": "Búsqueda",
   "search_add_token": "Buscar/Agregar token",
@@ -612,25 +612,25 @@
   "seed_language_german": "Alemán",
   "seed_language_italian": "Italiana/Italiano",
   "seed_language_japanese": "Japonés",
-  "seed_language_korean": "coreano",
+  "seed_language_korean": "Coreano",
   "seed_language_next": "Próximo",
   "seed_language_portuguese": "Portugués",
   "seed_language_russian": "Ruso",
   "seed_language_spanish": "Español",
   "seed_phrase_length": "Longitud de la frase inicial",
-  "seed_reminder": "Anótelos en caso de que pierda o borre su teléfono",
+  "seed_reminder": "Anótalos en caso de que pierdas o borres tu aplicación",
   "seed_share": "Compartir semillas",
   "seed_title": "Semilla",
-  "seedtype": "Type de semillas",
-  "seedtype_alert_content": "Compartir semillas con otras billeteras solo es posible con Bip39 Seed Type.",
-  "seedtype_alert_title": "Alerta de type de semillas",
-  "seedtype_legacy": "Legado (25 palabras)",
-  "seedtype_polyseed": "Polieta (16 palabras)",
+  "seedtype": "Tipos de semillas",
+  "seedtype_alert_content": "Compartir semillas con otras billeteras solo es posible con semillas bip39 - un tipo específico de semilla.",
+  "seedtype_alert_title": "Alerta de tipo de semillas",
+  "seedtype_legacy": "Semilla clásica-legacy (25 palabras)",
+  "seedtype_polyseed": "Poli-semilla (16 palabras)",
   "seedtype_wownero": "Wownero (14 palabras)",
   "select_backup_file": "Seleccionar archivo de respaldo",
-  "select_buy_provider_notice": "Seleccione un proveedor de compra arriba. Puede omitir esta pantalla configurando su proveedor de compra predeterminado en la configuración de la aplicación.",
-  "select_destination": "Seleccione el destino del archivo de copia de seguridad.",
-  "select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.",
+  "select_buy_provider_notice": "Selecciona un proveedor de compra arriba. Puede omitir esta pantalla configurando su proveedor de compra predeterminado en la configuración de la aplicación.",
+  "select_destination": "Selecciona el destino del archivo de copia de seguridad.",
+  "select_sell_provider_notice": "Selecciona un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.",
   "sell": "Vender",
   "sell_alert_content": "Actualmente solo admitimos la venta de Bitcoin, Ethereum y Litecoin. Cree o cambie a su billetera Bitcoin, Ethereum o Litecoin.",
   "sell_monero_com_alert_content": "Aún no se admite la venta de Monero",
@@ -676,16 +676,16 @@
   "settings_only_transactions": "Solo transacciones",
   "settings_personal": "Personal",
   "settings_save_recipient_address": "Guardar dirección del destinatario",
-  "settings_support": "Apoyo",
+  "settings_support": "Ayuda",
   "settings_terms_and_conditions": "Términos y Condiciones",
   "settings_title": "Configuraciones",
   "settings_trades": "Comercia",
   "settings_transactions": "Transacciones",
   "settings_wallets": "Carteras",
-  "setup_2fa": "Configurar pastel 2FA",
-  "setup_2fa_text": "Cake 2FA funciona utilizando TOTP como segundo factor de autenticación.\n\nEl TOTP de Cake 2FA requiere SHA-512 y soporte de 8 dígitos; esto proporciona una mayor seguridad. Puede encontrar más información y aplicaciones compatibles en la guía.",
+  "setup_2fa": "Configurar 2FA",
+  "setup_2fa_text": "Cake 2FA funciona utilizando TOTP como segundo factor de autenticación.\n\nEl TOTP de Cake 2FA requiere SHA-512 y soporte de 8 dígitos; esto proporciona una mayor seguridad. Puedes encontrar más información y aplicaciones compatibles en la guía.",
   "setup_pin": "PIN de configuración",
-  "setup_successful": "Su PIN se ha configurado correctamente!",
+  "setup_successful": "Tu PIN se ha configurado correctamente!",
   "setup_totp_recommended": "Configurar TOTP",
   "setup_warning_2fa_text": "Deberá restaurar su billetera a partir de la semilla mnemotécnica.\n\nEl soporte de Cake no podrá ayudarlo si pierde el acceso a su 2FA o a sus semillas mnemotécnicas.\nCake 2FA es una segunda autenticación para ciertas acciones en la billetera. Antes de usar Cake 2FA, recomendamos leer la guía.NO es tan seguro como el almacenamiento en frío.\n\nSi pierde el acceso a su aplicación 2FA o a sus claves TOTP, perderá el acceso a esta billetera. ",
   "setup_your_debit_card": "Configura tu tarjeta de débito",
@@ -704,23 +704,23 @@
   "signature": "Firma",
   "signature_invalid_error": "La firma no es válida para el mensaje dado",
   "signTransaction": "Firmar transacción",
-  "signup_for_card_accept_terms": "Regístrese para obtener la tarjeta y acepte los términos.",
+  "signup_for_card_accept_terms": "Regístrate para obtener la tarjeta y acepte los términos.",
   "silent_payment": "Pago silencioso",
   "silent_payments": "Pagos silenciosos",
   "silent_payments_always_scan": "Establecer pagos silenciosos siempre escaneando",
   "silent_payments_disclaimer": "Las nuevas direcciones no son nuevas identidades. Es una reutilización de una identidad existente con una etiqueta diferente.",
   "silent_payments_display_card": "Mostrar tarjeta de pagos silenciosos",
   "silent_payments_scan_from_date": "Escanear desde la fecha",
-  "silent_payments_scan_from_date_or_blockheight": "Ingrese la altura del bloque que desea comenzar a escanear para pagos silenciosos entrantes, o use la fecha en su lugar. Puede elegir si la billetera continúa escaneando cada bloque, o verifica solo la altura especificada.",
-  "silent_payments_scan_from_height": "Escanear desde la altura del bloque",
-  "silent_payments_scanned_tip": "Escaneado hasta la punta! (${tip})",
+  "silent_payments_scan_from_date_or_blockheight": "Ingresa la altura de bloque que desea comenzar a escanear para pagos silenciosos entrantes, o usa la fecha en su lugar. Puedes elegir si la billetera continúa escaneando cada bloque, o verifica solo la altura especificada.",
+  "silent_payments_scan_from_height": "Escanear desde la altura de bloque específico",
+  "silent_payments_scanned_tip": "Escaneado hasta la altura actual! (${tip})",
   "silent_payments_scanning": "Escaneo de pagos silenciosos",
   "silent_payments_settings": "Configuración de pagos silenciosos",
   "single_seed_wallets_group": "Billeteras de semillas individuales",
   "slidable": "deslizable",
   "sort_by": "Ordenar por",
-  "spend_key_private": "Spend clave (privado)",
-  "spend_key_public": "Spend clave (público)",
+  "spend_key_private": "Llave de gasto (privada)",
+  "spend_key_public": "Llave de gasto (pública)",
   "status": "Estado: ",
   "string_default": "Por defecto",
   "subaddress_title": "Lista de subdirecciones",
@@ -729,14 +729,14 @@
   "successful": "Exitoso",
   "support_description_guides": "Documentación y apoyo para problemas comunes",
   "support_description_live_chat": "¡GRATIS y RÁPIDO! Los representantes de apoyo capacitado están disponibles para ayudar",
-  "support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos",
+  "support_description_other_links": "Únete a nuestras comunidades o comunícate con nosotros nuestros socios a través de otros métodos",
   "support_title_guides": "Guías de billetera para pastel",
-  "support_title_live_chat": "Soporte vital",
+  "support_title_live_chat": "Soporte en tiempo real",
   "support_title_other_links": "Otros enlaces de soporte",
-  "sweeping_wallet": "Billetera de barrido",
+  "sweeping_wallet": "Barrer billetera (gastar todos los fondos disponibles)",
   "sweeping_wallet_alert": "Esto no debería llevar mucho tiempo. NO DEJES ESTA PANTALLA O SE PUEDEN PERDER LOS FONDOS BARRIDOS",
-  "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.",
-  "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)",
+  "switchToETHWallet": "Cambia a una billetera Ethereum e inténtelo nuevamente.",
+  "switchToEVMCompatibleWallet": "Cambia a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)",
   "symbol": "Símbolo",
   "sync_all_wallets": "Sincronizar todas las billeteras",
   "sync_status_attempting_scan": "Intento de escaneo",
@@ -759,7 +759,7 @@
   "third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!",
   "third_intro_title": "Yat juega muy bien con otras",
   "thorchain_contract_address_not_supported": "Thorchain no admite enviar a una dirección de contrato",
-  "thorchain_taproot_address_not_supported": "El proveedor de Thorchain no admite las direcciones de Taproot. Cambie la dirección o seleccione un proveedor diferente.",
+  "thorchain_taproot_address_not_supported": "El proveedor de Thorchain no admite las direcciones de Taproot. Cambia la dirección o selecciona un proveedor diferente.",
   "time": "${minutes}m ${seconds}s",
   "tip": "Consejo:",
   "today": "Hoy",
@@ -772,8 +772,8 @@
   "tor_only": "solo Tor",
   "total": "Total",
   "total_saving": "Ahorro Total",
-  "totp_2fa_failure": "Código incorrecto. Intente con un código diferente o genere una nueva clave secreta. Use una aplicación 2FA compatible que admita códigos de 8 dígitos y SHA512.",
-  "totp_2fa_success": "¡Éxito! Cake 2FA habilitado para esta billetera. Recuerde guardar su semilla mnemotécnica en caso de que pierda el acceso a la billetera.",
+  "totp_2fa_failure": "Código incorrecto. Intente con un código diferente o genere una nueva clave secreta. Usa una aplicación 2FA compatible que admita códigos de 8 dígitos y SHA512.",
+  "totp_2fa_success": "¡Éxito! Cake 2FA habilitado para esta billetera. Recuerda guardar tu semilla mnemotécnica en caso de que pierdas el acceso a la billetera.",
   "totp_auth_url": "URL de autenticación TOTP",
   "totp_code": "Código TOTP",
   "totp_secret_code": "Código secreto TOTP",
@@ -831,16 +831,16 @@
   "trongrid_history": "Historia trongrid",
   "trusted": "de confianza",
   "tx_commit_exception_no_dust_on_change": "La transacción se rechaza con esta cantidad. Con estas monedas puede enviar ${min} sin cambios o ${max} que devuelve el cambio.",
-  "tx_commit_failed": "La confirmación de transacción falló. Póngase en contacto con el soporte.",
-  "tx_commit_failed_no_peers": "La transacción no se transmitió, intente nuevamente en un segundo más o menos",
+  "tx_commit_failed": "La confirmación de transacción falló. Ponte en contacto con el soporte.",
+  "tx_commit_failed_no_peers": "La transacción no se transmitió, intenta nuevamente en un segundo más o menos",
   "tx_invalid_input": "Está utilizando el tipo de entrada incorrecto para este tipo de pago",
   "tx_no_dust_exception": "La transacción se rechaza enviando una cantidad demasiado pequeña. Intente aumentar la cantidad.",
-  "tx_not_enough_inputs_exception": "No hay suficientes entradas disponibles. Seleccione más bajo control de monedas",
+  "tx_not_enough_inputs_exception": "No hay suficientes entradas disponibles. Selecciona más bajo control de monedas",
   "tx_rejected_bip68_final": "La transacción tiene entradas no confirmadas y no ha podido reemplazar por tarifa.",
-  "tx_rejected_dust_change": "Transacción rechazada por reglas de red, bajo cambio de cambio (polvo). Intente enviar todo o reducir la cantidad.",
-  "tx_rejected_dust_output": "Transacción rechazada por reglas de red, baja cantidad de salida (polvo). Aumente la cantidad.",
+  "tx_rejected_dust_change": "Transacción rechazada por reglas de red, bajo cambio de cambio (polvo). Intenta enviar todo o reducir la cantidad.",
+  "tx_rejected_dust_output": "Transacción rechazada por reglas de red, baja cantidad de salida (polvo). Aumenta la cantidad.",
   "tx_rejected_dust_output_send_all": "Transacción rechazada por reglas de red, baja cantidad de salida (polvo). Verifique el saldo de monedas seleccionadas bajo control de monedas.",
-  "tx_rejected_vout_negative": "No es suficiente saldo para pagar las tarifas de esta transacción. Verifique el saldo de monedas bajo control de monedas.",
+  "tx_rejected_vout_negative": "No es suficiente saldo para pagar las tarifas de esta transacción. Verifica el saldo de monedas bajo control de monedas.",
   "tx_wrong_balance_exception": "No tiene suficiente ${currency} para enviar esta cantidad.",
   "tx_wrong_balance_with_amount_exception": "No tiene suficiente ${currency} para enviar la cantidad total de ${amount}",
   "tx_zero_fee_exception": "No se puede enviar transacciones con 0 tarifa. Intente aumentar la tasa o verificar su conexión para las últimas estimaciones.",
@@ -849,7 +849,7 @@
   "unconfirmed": "Saldo no confirmado",
   "understand": "Entiendo",
   "unlock": "desbloquear",
-  "unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado",
+  "unmatched_currencies": "La moneda de tu billetera actual no coincide con la del QR escaneado",
   "unspent_change": "Cambiar",
   "unspent_coins_details_title": "Detalles de monedas no gastadas",
   "unspent_coins_title": "Monedas no gastadas",
@@ -858,11 +858,11 @@
   "upto": "hasta ${value}",
   "usb": "USB",
   "use": "Utilizar a ",
-  "use_card_info_three": "Utilice la tarjeta digital en línea o con métodos de pago sin contacto.",
+  "use_card_info_three": "Utiliza la tarjeta digital en línea o con métodos de pago sin contacto.",
   "use_card_info_two": "Los fondos se convierten a USD cuando se mantienen en la cuenta prepaga, no en monedas digitales.",
-  "use_ssl": "Utilice SSL",
+  "use_ssl": "Utiliza SSL",
   "use_suggested": "Usar sugerido",
-  "use_testnet": "Use TestNet",
+  "use_testnet": "Usar TestNet",
   "value": "Valor",
   "value_type": "Tipo de valor",
   "variable_pair_not_supported": "Este par de variables no es compatible con los intercambios seleccionados",
@@ -871,17 +871,17 @@
   "verify_with_2fa": "Verificar con Cake 2FA",
   "version": "Versión ${currentVersion}",
   "view_all": "Ver todo",
-  "view_in_block_explorer": "View in Block Explorer",
-  "view_key_private": "View clave (privado)",
-  "view_key_public": "View clave (público)",
-  "view_transaction_on": "View Transaction on ",
+  "view_in_block_explorer": "Ver en explorador de bloques",
+  "view_key_private": "Llave de vista (privada)",
+  "view_key_public": "Llave de vista (pública)",
+  "view_transaction_on": "Ver transacción en ",
   "voting_weight": "Peso de votación",
-  "waitFewSecondForTxUpdate": "Espere unos segundos para que la transacción se refleje en el historial de transacciones.",
+  "waitFewSecondForTxUpdate": "Espera unos segundos para que la transacción se refleje en el historial de transacciones.",
   "wallet_group": "Grupo de billetera",
-  "wallet_group_description_four": "para crear una billetera con una semilla completamente nueva.",
+  "wallet_group_description_four": "Para crear una billetera con una semilla completamente nueva.",
   "wallet_group_description_one": "En la billetera de pastel, puedes crear un",
   "wallet_group_description_three": "Para ver las billeteras disponibles y/o la pantalla de grupos de billeteras. O elegir",
-  "wallet_group_description_two": "seleccionando una billetera existente para compartir una semilla con. Cada grupo de billetera puede contener una sola billetera de cada tipo de moneda. \n\n puede seleccionar",
+  "wallet_group_description_two": "Seleccionando una billetera existente para compartir una semilla con. Cada grupo de billetera puede contener una sola billetera de cada tipo de moneda. \n\n puedes seleccionar",
   "wallet_group_empty_state_text_one": "Parece que no tienes ningún grupo de billetera compatible !\n\n toque",
   "wallet_group_empty_state_text_two": "a continuación para hacer uno nuevo.",
   "wallet_keys": "Billetera semilla/claves",
@@ -889,7 +889,7 @@
   "wallet_list_edit_group_name": "Editar nombre de grupo",
   "wallet_list_edit_wallet": "Editar billetera",
   "wallet_list_failed_to_load": "No se pudo cargar  ${wallet_name} la billetera. ${error}",
-  "wallet_list_failed_to_remove": "Error al elimina ${wallet_name} billetera. ${error}",
+  "wallet_list_failed_to_remove": "Error al eliminar ${wallet_name} billetera. ${error}",
   "wallet_list_load_wallet": "Billetera de carga",
   "wallet_list_loading_wallet": "Billetera ${wallet_name} de carga",
   "wallet_list_removing_wallet": "Retirar ${wallet_name} billetera",
@@ -898,8 +898,8 @@
   "wallet_list_wallet_name": "Nombre de la billetera",
   "wallet_menu": "Menú de billetera",
   "wallet_name": "Nombre de la billetera",
-  "wallet_name_exists": "Wallet con ese nombre ya ha existido",
-  "wallet_password_is_empty": "La contraseña de billetera está vacía. La contraseña de la billetera no debe estar vacía",
+  "wallet_name_exists": "Cartera con ese nombre ya existe, escoge otro",
+  "wallet_password_is_empty": "La contraseña de billetera está vacía. La contraseña de la billetera no puede estar vacía",
   "wallet_recovery_height": "Altura de recuperación",
   "wallet_restoration_store_incorrect_seed_length": "Longitud de semilla incorrecta",
   "wallet_seed": "Semilla de billetera",
@@ -913,28 +913,28 @@
   "what_is_silent_payments": "¿Qué son los pagos silenciosos?",
   "widgets_address": "Dirección",
   "widgets_or": "o",
-  "widgets_restore_from_blockheight": "Restaurar desde blockheight",
+  "widgets_restore_from_blockheight": "Restaurar desde altura de bloque",
   "widgets_restore_from_date": "Restaurar desde fecha",
   "widgets_seed": "Semilla",
   "wouoldLikeToConnect": "quisiera conectar",
-  "write_down_backup_password": "Escriba su contraseña de respaldo, que se utiliza para la importación de sus archivos de respaldo.",
-  "xlm_extra_info": "No olvide especificar el ID de nota al enviar la transacción XLM para el intercambio",
+  "write_down_backup_password": "Escribe su contraseña de respaldo, que se utiliza para la importación de sus archivos de respaldo.",
+  "xlm_extra_info": "No olvides especificar el ID de nota al enviar la transacción XLM para el intercambio",
   "xmr_available_balance": "Saldo disponible",
   "xmr_full_balance": "Balance total",
   "xmr_hidden": "Oculto",
   "xmr_to_error": "Error de XMR.TO",
   "xmr_to_error_description": "Monto invalido. Límite máximo de 8 dígitos después del punto decimal",
-  "xrp_extra_info": "No olvide especificar la etiqueta de destino al enviar la transacción XRP para el intercambio",
+  "xrp_extra_info": "No olvides especificar la etiqueta de destino al enviar la transacción XRP para el intercambio",
   "yat": "Yat",
   "yat_address": "Dirección de Yat",
   "yat_alert_content": "Los usuarios de Cake Wallet ahora pueden enviar y recibir todas sus monedas favoritas con un nombre de usuario único basado en emoji.",
-  "yat_alert_title": "Envíe y reciba criptomonedas más fácilmente con Yat",
+  "yat_alert_title": "Envía y recibe criptomonedas más fácilmente con Yat",
   "yat_error": "Error de Yat",
   "yat_error_content": "No hay direcciones vinculadas con este Yat. Prueba con otro Yat",
-  "yat_popup_content": "Ahora puede enviar y recibir criptografía en Cake Wallet con su Yat, un nombre de usuario corto basado en emoji. Administre Yats en cualquier momento en la pantalla de configuración",
-  "yat_popup_title": "La dirección de su billetera se puede emojificar.",
+  "yat_popup_content": "Ahora puede enviar y recibir criptografía en Cake Wallet con su Yat, un nombre de usuario corto basado en emoji. Administra Yats en cualquier momento en la pantalla de configuración",
+  "yat_popup_title": "La dirección de tu billetera se puede emojificar.",
   "yesterday": "Ayer",
-  "you_now_have_debit_card": "Ahora tiene una tarjeta de débito",
+  "you_now_have_debit_card": "Ahora tienes una tarjeta de débito",
   "you_pay": "Tú pagas",
   "you_will_get": "Convertir a",
   "you_will_send": "Convertir de",

From b8ffd47f0624a35b987038e6217c3ea140a9d694 Mon Sep 17 00:00:00 2001
From: Elias Rad <146735585+nnsW3@users.noreply.github.com>
Date: Mon, 4 Nov 2024 04:51:19 +0200
Subject: [PATCH 28/50] Docs spelling issues (#1789)

* Update PRIVACY.md

* Update README.md

* Update SECURITY.md

* Update build-guide-linux.md
---
 PRIVACY.md           | 4 ++--
 README.md            | 6 +++---
 SECURITY.md          | 2 +-
 build-guide-linux.md | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/PRIVACY.md b/PRIVACY.md
index 76cfcc4d3..a5c8eddfb 100644
--- a/PRIVACY.md
+++ b/PRIVACY.md
@@ -5,7 +5,7 @@ Last modified: January 24, 2024
 Introduction
 ============
 
-	Cake Labs LLC ("Cake Labs", "Company", or "We") respect your privacy and are committed to protecting it through our compliance with this policy.
+	Cake Labs LLC ("Cake Labs", "Company", or "We") respects your privacy and are committed to protecting it through our compliance with this policy.
 
 	This policy describes the types of information we may collect from you or that you may provide when you use the App (our "App") and our practices for collecting, using, maintaining, protecting, and disclosing that information.
 
@@ -13,7 +13,7 @@ Introduction
 		- On this App.
 		- In email, text, and other electronic messages between you and this App.
 	It does not apply to information collected by:
-		- Us offline or through any other means, including on any other App operated by Company or any third party (including our affiliates and subsidiaries); or 
+		- Us offline or through any other means, including on any other App operated by the Company or any third party (including our affiliates and subsidiaries); or 
 		- Any third party (including our affiliates and subsidiaries), including through any application or content (including advertising) that may link to or be accessible from or on the App.
 	Please read this policy carefully to understand our policies and practices regarding your information and how we will treat it. If you do not agree with our policies and practices, you have the choice to not use the App. By accessing or using this App, you agree to this privacy policy. This policy may change from time to time. Your continued use of this App after we make changes is deemed to be acceptance of those changes, so please check the policy periodically for updates.
 
diff --git a/README.md b/README.md
index ca3061e61..078c4437e 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@
 
 # Cake Wallet
 
-[Cake Wallet](https://cakewallet.com) is an open source, non-custodial, and private multi-currency crypto wallet for Android, iOS, macOS, and Linux.
+[Cake Wallet](https://cakewallet.com) is an open-source, non-custodial, and private multi-currency crypto wallet for Android, iOS, macOS, and Linux.
 
 Cake Wallet includes support for several cryptocurrencies, including:
 * Monero (XMR)
@@ -44,7 +44,7 @@ Cake Wallet includes support for several cryptocurrencies, including:
 * Create several wallets
 * Select your own custom nodes/servers
 * Address book
-* Backup to external location or iCloud
+* Backup to an external location or iCloud
 * Send to OpenAlias, Unstoppable Domains, Yats, and FIO Crypto Handles
 * Set desired network fee level
 * Store local transaction notes
@@ -161,7 +161,7 @@ The only parts to be translated, if needed, are the values m and s after the var
 
 4. Add the language to `lib/entities/language_service.dart` under both `supportedLocales` and `localeCountryCode`. Use the name of the language in the local language and in English in parentheses after for `supportedLocales`. Use the [ISO 3166-1 alpha-3 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) for `localeCountryCode`. You must choose one country, so choose the country with the most native speakers of this language or is otherwise best associated with this language.
 
-5. Add a relevant flag to `assets/images/flags/XXXX.png`, replacing XXXX with the 3 letters localeCountryCode. The image must be 42x26 pixels with a 3 pixels of transparent margin on all 4 sides. You can resize the flag with [paint.net](https://www.getpaint.net/) to 36x20 pixels, expand the canvas to 42x26 pixels with the flag anchored in the middle, and then manually delete the 3 pixels on each side to make transparent. Or you can use another program like Photoshop.
+5. Add a relevant flag to `assets/images/flags/XXXX.png`, replacing XXXX with the 3 letters localeCountryCode. The image must be 42x26 pixels with 3 pixels of transparent margin on all 4 sides. You can resize the flag with [paint.net](https://www.getpaint.net/) to 36x20 pixels, expand the canvas to 42x26 pixels with the flag anchored in the middle, and then manually delete the 3 pixels on each side to make it transparent. Or you can use another program like Photoshop.
 
 6. Add the new language code to `tool/utils/translation/translation_constants.dart`
 
diff --git a/SECURITY.md b/SECURITY.md
index a1b489b76..e7c6baa02 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -9,4 +9,4 @@ If you need to report a vulnerability, please either:
 
 ## Supported Versions
 
-As we don't maintain prevoius versions of the app, only the latest release for each platform is supported and any updates will bump the version number.
+As we don't maintain previous versions of the app, only the latest release for each platform is supported and any updates will bump the version number.
diff --git a/build-guide-linux.md b/build-guide-linux.md
index 50ecc76fe..55264fbfa 100644
--- a/build-guide-linux.md
+++ b/build-guide-linux.md
@@ -55,7 +55,7 @@ Need to install flutter. For this please check section [How to install flutter o
 
 ### 3. Verify Installations
 
-Verify that the Flutter have been correctly installed on your system with the following command:
+Verify that the Flutter has been correctly installed on your system with the following command:
 
 `$ flutter doctor`
 
@@ -163,7 +163,7 @@ And then export bundle:
 
 `$ flatpak build-bundle export cake_wallet.flatpak com.cakewallet.CakeWallet`
 
-Result file: `cake_wallet.flatpak` should be generated in current directory.
+Result file: `cake_wallet.flatpak` should be generated in the current directory.
 
 For install generated flatpak file use:
 

From 459f0d352d92150a3b6b96cf94106d060ebd92dd Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Tue, 5 Nov 2024 11:33:24 +0200
Subject: [PATCH 29/50] Cw 805 fix bch refund address (#1782)

* fix bch address format for exolix, stealth, thorchain, simpleswap

* exclude SP and MWEB from the exchange address book

* address pr review comments
---
 lib/core/address_validator.dart                   |  3 +--
 .../provider/exolix_exchange_provider.dart        |  7 +++++--
 .../provider/simpleswap_exchange_provider.dart    |  7 +++++--
 .../provider/stealth_ex_exchange_provider.dart    |  7 +++++--
 .../provider/thorchain_exchange.provider.dart     | 11 ++++++-----
 .../contact_list/contact_list_view_model.dart     | 15 ++++++++++-----
 6 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart
index 21726fab8..9ca8a41ad 100644
--- a/lib/core/address_validator.dart
+++ b/lib/core/address_validator.dart
@@ -106,8 +106,7 @@ class AddressValidator extends TextValidator {
       case CryptoCurrency.wow:
         pattern = '[0-9a-zA-Z]+';
       case CryptoCurrency.bch:
-        pattern =
-            '(?!bitcoincash:)[0-9a-zA-Z]*|(?!bitcoincash:)q|p[0-9a-zA-Z]{41}|(?!bitcoincash:)q|p[0-9a-zA-Z]{42}|bitcoincash:q|p[0-9a-zA-Z]{41}|bitcoincash:q|p[0-9a-zA-Z]{42}';
+        pattern = '^(bitcoincash:)?(q|p)[0-9a-zA-Z]{41,42}';
       case CryptoCurrency.bnb:
         pattern = '[0-9a-zA-Z]+';
       case CryptoCurrency.hbar:
diff --git a/lib/exchange/provider/exolix_exchange_provider.dart b/lib/exchange/provider/exolix_exchange_provider.dart
index 8f2d5c241..5eeb6f9cf 100644
--- a/lib/exchange/provider/exolix_exchange_provider.dart
+++ b/lib/exchange/provider/exolix_exchange_provider.dart
@@ -141,8 +141,8 @@ class ExolixExchangeProvider extends ExchangeProvider {
       'coinTo': _normalizeCurrency(request.toCurrency),
       'networkFrom': _networkFor(request.fromCurrency),
       'networkTo': _networkFor(request.toCurrency),
-      'withdrawalAddress': request.toAddress,
-      'refundAddress': request.refundAddress,
+      'withdrawalAddress': _normalizeAddress(request.toAddress),
+      'refundAddress': _normalizeAddress(request.refundAddress),
       'rateType': _getRateType(isFixedRateMode),
       'apiToken': apiKey,
     };
@@ -275,4 +275,7 @@ class ExolixExchangeProvider extends ExchangeProvider {
         return tag;
     }
   }
+
+  String _normalizeAddress(String address) =>
+      address.startsWith('bitcoincash:') ? address.replaceFirst('bitcoincash:', '') : address;
 }
diff --git a/lib/exchange/provider/simpleswap_exchange_provider.dart b/lib/exchange/provider/simpleswap_exchange_provider.dart
index be52b73fe..2a72ac793 100644
--- a/lib/exchange/provider/simpleswap_exchange_provider.dart
+++ b/lib/exchange/provider/simpleswap_exchange_provider.dart
@@ -129,8 +129,8 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
       "currency_to": _normalizeCurrency(request.toCurrency),
       "amount": request.fromAmount,
       "fixed": isFixedRateMode,
-      "user_refund_address": request.refundAddress,
-      "address_to": request.toAddress
+      "user_refund_address": _normalizeAddress(request.refundAddress),
+      "address_to": _normalizeAddress(request.toAddress)
     };
     final uri = Uri.https(apiAuthority, createExchangePath, params);
 
@@ -243,4 +243,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
         return currency.title.toLowerCase();
     }
   }
+
+  String _normalizeAddress(String address) =>
+      address.startsWith('bitcoincash:') ? address.replaceFirst('bitcoincash:', '') : address;
 }
diff --git a/lib/exchange/provider/stealth_ex_exchange_provider.dart b/lib/exchange/provider/stealth_ex_exchange_provider.dart
index 601735595..123f759ef 100644
--- a/lib/exchange/provider/stealth_ex_exchange_provider.dart
+++ b/lib/exchange/provider/stealth_ex_exchange_provider.dart
@@ -129,8 +129,8 @@ class StealthExExchangeProvider extends ExchangeProvider {
         if (isFixedRateMode) 'rate_id': rateId,
         'amount':
             isFixedRateMode ? double.parse(request.toAmount) : double.parse(request.fromAmount),
-        'address': request.toAddress,
-        'refund_address': request.refundAddress,
+        'address': _normalizeAddress(request.toAddress),
+        'refund_address': _normalizeAddress(request.refundAddress),
         'additional_fee_percent': _additionalFeePercent,
       };
 
@@ -296,4 +296,7 @@ class StealthExExchangeProvider extends ExchangeProvider {
 
     return currency.tag!.toLowerCase();
   }
+
+  String _normalizeAddress(String address) =>
+      address.startsWith('bitcoincash:') ? address.replaceFirst('bitcoincash:', '') : address;
 }
diff --git a/lib/exchange/provider/thorchain_exchange.provider.dart b/lib/exchange/provider/thorchain_exchange.provider.dart
index 897c2fdb9..99b9dcf9f 100644
--- a/lib/exchange/provider/thorchain_exchange.provider.dart
+++ b/lib/exchange/provider/thorchain_exchange.provider.dart
@@ -116,9 +116,7 @@ class ThorChainExchangeProvider extends ExchangeProvider {
     required bool isFixedRateMode,
     required bool isSendAll,
   }) async {
-    String formattedToAddress = request.toAddress.startsWith('bitcoincash:')
-        ? request.toAddress.replaceFirst('bitcoincash:', '')
-        : request.toAddress;
+
 
     final formattedFromAmount = double.parse(request.fromAmount);
 
@@ -126,11 +124,11 @@ class ThorChainExchangeProvider extends ExchangeProvider {
       'from_asset': _normalizeCurrency(request.fromCurrency),
       'to_asset': _normalizeCurrency(request.toCurrency),
       'amount': _doubleToThorChainString(formattedFromAmount),
-      'destination': formattedToAddress,
+      'destination': _normalizeAddress(request.toAddress),
       'affiliate': _affiliateName,
       'affiliate_bps': _affiliateBps,
       'refund_address':
-          isRefundAddressSupported.contains(request.fromCurrency) ? request.refundAddress : '',
+          isRefundAddressSupported.contains(request.fromCurrency) ? _normalizeAddress(request.refundAddress) : '',
     };
 
     final responseJSON = await _getSwapQuote(params);
@@ -288,4 +286,7 @@ class ThorChainExchangeProvider extends ExchangeProvider {
 
     return currentState;
   }
+
+  String _normalizeAddress(String address) =>
+      address.startsWith('bitcoincash:') ? address.replaceFirst('bitcoincash:', '') : address;
 }
diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart
index 4089d988b..89192583e 100644
--- a/lib/view_model/contact_list/contact_list_view_model.dart
+++ b/lib/view_model/contact_list/contact_list_view_model.dart
@@ -99,18 +99,23 @@ abstract class ContactListViewModelBase with Store {
 
   Future<void> delete(ContactRecord contact) async => contact.original.delete();
 
-  @computed
-  List<ContactRecord> get contactsToShow =>
-      contacts.where((element) => _isValidForCurrency(element)).toList();
+  ObservableList<ContactRecord> get contactsToShow =>
+      ObservableList.of(contacts.where((element) => _isValidForCurrency(element)));
 
   @computed
   List<WalletContact> get walletContactsToShow =>
       walletContacts.where((element) => _isValidForCurrency(element)).toList();
 
   bool _isValidForCurrency(ContactBase element) {
+    if (element.name.contains('Silent Payments')) return false;
+    if (element.name.contains('MWEB')) return false;
+
     return _currency == null ||
         element.type == _currency ||
-        element.type.title == _currency!.tag ||
-        element.type.tag == _currency!.tag;
+        (element.type.tag != null &&
+            _currency?.tag != null &&
+            element.type.tag == _currency?.tag) ||
+        _currency?.toString() == element.type.tag ||
+        _currency?.tag == element.type.toString();
   }
 }

From 109d9b458eac30534dd93492173145a3fc48b948 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Thu, 7 Nov 2024 03:26:14 +0200
Subject: [PATCH 30/50] Cw 514 add sort functionality for addressbook 
 mywallets and contacts (#1309)

* add sort function to contact list

* fix UI

* prevent duplicate contact names

* dispose contact source subscription

* fix custom order issue

* update the address book UI

* fix saving custom order

* fix merge conflict issue

* review fixes [skip ci]

* revert to single scroll for entire page

* tabBarView address book

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 lib/entities/contact.dart                     |   9 +-
 lib/entities/contact_record.dart              |  23 +-
 lib/entities/preferences_key.dart             |   2 +
 lib/entities/wallet_list_order_types.dart     |  10 +-
 .../screens/contact/contact_list_page.dart    | 388 ++++++++++++++----
 .../dashboard/widgets/filter_list_widget.dart |  26 +-
 .../screens/wallet_list/filtered_list.dart    |  46 ++-
 .../screens/wallet_list/wallet_list_page.dart |   2 +-
 .../widgets/collapsible_standart_list.dart    |  39 --
 lib/store/settings_store.dart                 |  40 +-
 .../contact_list/contact_list_view_model.dart |  84 +++-
 .../contact_list/contact_view_model.dart      |  24 +-
 .../wallet_list/wallet_list_view_model.dart   |  14 +-
 res/values/strings_ar.arb                     |   5 +-
 res/values/strings_bg.arb                     |   5 +-
 res/values/strings_cs.arb                     |   5 +-
 res/values/strings_en.arb                     |   5 +-
 res/values/strings_es.arb                     |   3 +-
 res/values/strings_fr.arb                     |   5 +-
 res/values/strings_ha.arb                     |   5 +-
 res/values/strings_hi.arb                     |   5 +-
 res/values/strings_hr.arb                     |   5 +-
 res/values/strings_id.arb                     |   5 +-
 res/values/strings_it.arb                     |   5 +-
 res/values/strings_ja.arb                     |   5 +-
 res/values/strings_ko.arb                     |   5 +-
 res/values/strings_my.arb                     |   5 +-
 res/values/strings_nl.arb                     |   5 +-
 res/values/strings_pl.arb                     |   5 +-
 res/values/strings_pt.arb                     |   2 +-
 res/values/strings_ru.arb                     |   5 +-
 res/values/strings_th.arb                     |   5 +-
 res/values/strings_tl.arb                     |   2 +-
 res/values/strings_tr.arb                     |   5 +-
 res/values/strings_uk.arb                     |   5 +-
 res/values/strings_ur.arb                     |   5 +-
 res/values/strings_yo.arb                     |   5 +-
 res/values/strings_zh.arb                     |   5 +-
 38 files changed, 588 insertions(+), 236 deletions(-)
 delete mode 100644 lib/src/widgets/collapsible_standart_list.dart

diff --git a/lib/entities/contact.dart b/lib/entities/contact.dart
index cd4fa55a2..901993f43 100644
--- a/lib/entities/contact.dart
+++ b/lib/entities/contact.dart
@@ -7,7 +7,8 @@ part 'contact.g.dart';
 
 @HiveType(typeId: Contact.typeId)
 class Contact extends HiveObject with Keyable {
-  Contact({required this.name, required this.address, CryptoCurrency? type}) {
+  Contact({required this.name, required this.address, CryptoCurrency? type, DateTime? lastChange})
+      : lastChange = lastChange ?? DateTime.now() {
     if (type != null) {
       raw = type.raw;
     }
@@ -25,6 +26,9 @@ class Contact extends HiveObject with Keyable {
   @HiveField(2, defaultValue: 0)
   late int raw;
 
+  @HiveField(3)
+  DateTime lastChange;
+
   CryptoCurrency get type => CryptoCurrency.deserialize(raw: raw);
 
   @override
@@ -36,6 +40,5 @@ class Contact extends HiveObject with Keyable {
   @override
   int get hashCode => key.hashCode;
 
-  void updateCryptoCurrency({required CryptoCurrency currency}) =>
-      raw = currency.raw;
+  void updateCryptoCurrency({required CryptoCurrency currency}) => raw = currency.raw;
 }
diff --git a/lib/entities/contact_record.dart b/lib/entities/contact_record.dart
index 50a432727..4b0e120ba 100644
--- a/lib/entities/contact_record.dart
+++ b/lib/entities/contact_record.dart
@@ -1,22 +1,21 @@
+import 'package:cake_wallet/entities/contact.dart';
+import 'package:cake_wallet/entities/contact_base.dart';
+import 'package:cake_wallet/entities/record.dart';
+import 'package:cw_core/crypto_currency.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
-import 'package:cake_wallet/entities/contact.dart';
-import 'package:cw_core/crypto_currency.dart';
-import 'package:cake_wallet/entities/record.dart';
-import 'package:cake_wallet/entities/contact_base.dart';
 
 part 'contact_record.g.dart';
 
 class ContactRecord = ContactRecordBase with _$ContactRecord;
 
-abstract class ContactRecordBase extends Record<Contact>
-    with Store
-    implements ContactBase {
+abstract class ContactRecordBase extends Record<Contact> with Store implements ContactBase {
   ContactRecordBase(Box<Contact> source, Contact original)
       : name = original.name,
         address = original.address,
         type = original.type,
-      super(source, original);
+        lastChange = original.lastChange,
+        super(source, original);
 
   @override
   @observable
@@ -30,14 +29,14 @@ abstract class ContactRecordBase extends Record<Contact>
   @observable
   CryptoCurrency type;
 
+  DateTime? lastChange;
+
   @override
   void toBind(Contact original) {
     reaction((_) => name, (String name) => original.name = name);
     reaction((_) => address, (String address) => original.address = address);
-    reaction(
-        (_) => type,
-        (CryptoCurrency currency) =>
-            original.updateCryptoCurrency(currency: currency));
+    reaction((_) => type,
+        (CryptoCurrency currency) => original.updateCryptoCurrency(currency: currency));
   }
 
   @override
diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart
index 4fbe358e5..73556452c 100644
--- a/lib/entities/preferences_key.dart
+++ b/lib/entities/preferences_key.dart
@@ -25,7 +25,9 @@ class PreferencesKey {
   static const disableBulletinKey = 'disable_bulletin';
   static const defaultBuyProvider = 'default_buy_provider';
   static const walletListOrder = 'wallet_list_order';
+  static const contactListOrder = 'contact_list_order';
   static const walletListAscending = 'wallet_list_ascending';
+  static const contactListAscending = 'contact_list_ascending';
   static const currentFiatApiModeKey = 'current_fiat_api_mode';
   static const failedTotpTokenTrials = 'failed_token_trials';
   static const disableExchangeKey = 'disable_exchange';
diff --git a/lib/entities/wallet_list_order_types.dart b/lib/entities/wallet_list_order_types.dart
index f848170f4..751569e9e 100644
--- a/lib/entities/wallet_list_order_types.dart
+++ b/lib/entities/wallet_list_order_types.dart
@@ -1,6 +1,6 @@
 import 'package:cake_wallet/generated/i18n.dart';
 
-enum WalletListOrderType {
+enum FilterListOrderType {
   CreationDate,
   Alphabetical,
   GroupByType,
@@ -9,13 +9,13 @@ enum WalletListOrderType {
   @override
   String toString() {
     switch (this) {
-      case WalletListOrderType.CreationDate:
+      case FilterListOrderType.CreationDate:
         return S.current.creation_date;
-      case WalletListOrderType.Alphabetical:
+      case FilterListOrderType.Alphabetical:
         return S.current.alphabetical;
-      case WalletListOrderType.GroupByType:
+      case FilterListOrderType.GroupByType:
         return S.current.group_by_type;
-      case WalletListOrderType.Custom:
+      case FilterListOrderType.Custom:
         return S.current.custom_drag;
     }
   }
diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart
index 99f2aa251..130380b09 100644
--- a/lib/src/screens/contact/contact_list_page.dart
+++ b/lib/src/screens/contact/contact_list_page.dart
@@ -1,21 +1,24 @@
 import 'package:cake_wallet/core/auth_service.dart';
 import 'package:cake_wallet/entities/contact_base.dart';
 import 'package:cake_wallet/entities/contact_record.dart';
+import 'package:cake_wallet/entities/wallet_list_order_types.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/routes.dart';
+import 'package:cake_wallet/src/screens/base_page.dart';
+import 'package:cake_wallet/src/screens/dashboard/widgets/filter_list_widget.dart';
+import 'package:cake_wallet/src/screens/wallet_list/filtered_list.dart';
+import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
+import 'package:cake_wallet/src/widgets/standard_list.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
 import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
 import 'package:cake_wallet/utils/show_bar.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_mobx/flutter_mobx.dart';
-import 'package:flutter_slidable/flutter_slidable.dart';
-import 'package:cake_wallet/routes.dart';
-import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cake_wallet/src/screens/base_page.dart';
-import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
 import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
-import 'package:cake_wallet/src/widgets/collapsible_standart_list.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_slidable/flutter_slidable.dart';
 
 class ContactListPage extends BasePage {
   ContactListPage(this.contactListViewModel, this.authService);
@@ -74,45 +77,101 @@ class ContactListPage extends BasePage {
   }
 
   @override
-  Widget body(BuildContext context) {
-    return Container(
-        padding: EdgeInsets.all(20.0),
-        child: Observer(builder: (_) {
-          final contacts = contactListViewModel.contactsToShow;
-          final walletContacts = contactListViewModel.walletContactsToShow;
-          return CollapsibleSectionList(
-            sectionCount: 2,
-            sectionTitleBuilder: (int sectionIndex) {
-              var title = S.current.contact_list_contacts;
+  Widget body(BuildContext context) => ContactPageBody(contactListViewModel: contactListViewModel);
+}
 
-              if (sectionIndex == 0) {
-                title = S.current.contact_list_wallets;
-              }
+class ContactPageBody extends StatefulWidget {
+  const ContactPageBody({required this.contactListViewModel});
 
-              return Container(
-                  padding: EdgeInsets.only(bottom: 10),
-                  child: Text(title, style: TextStyle(fontSize: 36)));
-            },
-            itemCounter: (int sectionIndex) =>
-                sectionIndex == 0 ? walletContacts.length : contacts.length,
-            itemBuilder: (int sectionIndex, index) {
-              if (sectionIndex == 0) {
-                final walletInfo = walletContacts[index];
-                return generateRaw(context, walletInfo);
-              }
+  final ContactListViewModel contactListViewModel;
 
-              final contact = contacts[index];
-              final content = generateRaw(context, contact);
-              return contactListViewModel.isEditable
-                  ? Slidable(
-                      key: Key('${contact.key}'),
-                      endActionPane: _actionPane(context, contact),
-                      child: content,
-                    )
-                  : content;
-            },
-          );
-        }));
+  @override
+  State<ContactPageBody> createState() => _ContactPageBodyState();
+}
+
+class _ContactPageBodyState extends State<ContactPageBody> with SingleTickerProviderStateMixin {
+  late TabController _tabController;
+
+  @override
+  void initState() {
+    super.initState();
+    _tabController = TabController(length: 2, vsync: this);
+  }
+
+  @override
+  void dispose() {
+    _tabController.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(left: 24),
+      child: Column(
+        children: [
+          Align(
+            alignment: Alignment.centerLeft,
+            child: TabBar(
+              controller: _tabController,
+              splashFactory: NoSplash.splashFactory,
+              indicatorSize: TabBarIndicatorSize.label,
+              isScrollable: true,
+              labelStyle: TextStyle(
+                fontSize: 18,
+                fontFamily: 'Lato',
+                fontWeight: FontWeight.w600,
+                color: Theme.of(context).appBarTheme.titleTextStyle!.color,
+              ),
+              unselectedLabelStyle: TextStyle(
+                  fontSize: 18,
+                  fontFamily: 'Lato',
+                  fontWeight: FontWeight.w600,
+                  color: Theme.of(context).appBarTheme.titleTextStyle!.color?.withOpacity(0.5)),
+              labelColor: Theme.of(context).appBarTheme.titleTextStyle!.color,
+              indicatorColor: Theme.of(context).appBarTheme.titleTextStyle!.color,
+              indicatorPadding: EdgeInsets.zero,
+              labelPadding: EdgeInsets.only(right: 24),
+              tabAlignment: TabAlignment.center,
+              dividerColor: Colors.transparent,
+              padding: EdgeInsets.zero,
+              tabs: [
+                Tab(text: S.of(context).wallets),
+                Tab(text: S.of(context).contact_list_contacts),
+              ],
+            ),
+          ),
+          Expanded(
+            child: TabBarView(
+              controller: _tabController,
+              children: [
+                _buildWalletContacts(context),
+                ContactListBody(
+                    contactListViewModel: widget.contactListViewModel,
+                    tabController: _tabController),
+              ],
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildWalletContacts(BuildContext context) {
+    final walletContacts = widget.contactListViewModel.walletContactsToShow;
+
+    return ListView.builder(
+      shrinkWrap: true,
+      itemCount: walletContacts.length * 2,
+      itemBuilder: (context, index) {
+        if (index.isOdd) {
+          return StandardListSeparator();
+        } else {
+          final walletInfo = walletContacts[index ~/ 2];
+          return generateRaw(context, walletInfo);
+        }
+      },
+    );
   }
 
   Widget generateRaw(BuildContext context, ContactBase contact) {
@@ -123,7 +182,7 @@ class ContactListPage extends BasePage {
 
     return GestureDetector(
       onTap: () async {
-        if (!contactListViewModel.isEditable) {
+        if (!widget.contactListViewModel.isEditable) {
           Navigator.of(context).pop(contact);
           return;
         }
@@ -143,8 +202,7 @@ class ContactListPage extends BasePage {
           mainAxisAlignment: MainAxisAlignment.start,
           children: <Widget>[
             currencyIcon,
-            Expanded(
-                child: Padding(
+            Padding(
               padding: EdgeInsets.only(left: 12),
               child: Text(
                 contact.name,
@@ -154,13 +212,215 @@ class ContactListPage extends BasePage {
                   color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
                 ),
               ),
-            ))
+            ),
           ],
         ),
       ),
     );
   }
 
+  Future<bool> showNameAndAddressDialog(BuildContext context, String name, String address) async {
+    return await showPopUp<bool>(
+            context: context,
+            builder: (BuildContext context) {
+              return AlertWithTwoActions(
+                  alertTitle: name,
+                  alertContent: address,
+                  rightButtonText: S.of(context).copy,
+                  leftButtonText: S.of(context).cancel,
+                  actionRightButton: () => Navigator.of(context).pop(true),
+                  actionLeftButton: () => Navigator.of(context).pop(false));
+            }) ??
+        false;
+  }
+}
+
+class ContactListBody extends StatefulWidget {
+  ContactListBody({required this.contactListViewModel, required this.tabController});
+
+  final ContactListViewModel contactListViewModel;
+  final TabController tabController;
+
+  @override
+  State<ContactListBody> createState() => _ContactListBodyState();
+}
+
+class _ContactListBodyState extends State<ContactListBody> {
+  bool _isContactsTabActive = false;
+
+  @override
+  void initState() {
+    super.initState();
+    widget.tabController.addListener(_handleTabChange);
+  }
+
+  void _handleTabChange() {
+    setState(() {
+      _isContactsTabActive = widget.tabController.index == 1;
+    });
+  }
+
+  @override
+  void dispose() {
+    widget.tabController.removeListener(_handleTabChange);
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final contacts = widget.contactListViewModel.contacts;
+    return Scaffold(
+      body: Container(
+        child: FilteredList(
+          list: contacts,
+          updateFunction: widget.contactListViewModel.reorderAccordingToContactList,
+          canReorder: widget.contactListViewModel.isEditable,
+          shrinkWrap: true,
+          itemBuilder: (context, index) {
+            final contact = contacts[index];
+            final contactContent =
+                generateContactRaw(context, contact, contacts.length == index + 1);
+            return GestureDetector(
+              key: Key('${contact.name}'),
+              onTap: () async {
+                if (!widget.contactListViewModel.isEditable) {
+                  Navigator.of(context).pop(contact);
+                  return;
+                }
+
+                final isCopied =
+                    await showNameAndAddressDialog(context, contact.name, contact.address);
+
+                if (isCopied) {
+                  await Clipboard.setData(ClipboardData(text: contact.address));
+                  await showBar<void>(context, S.of(context).copied_to_clipboard);
+                }
+              },
+              behavior: HitTestBehavior.opaque,
+              child: widget.contactListViewModel.isEditable
+                  ? Slidable(
+                      key: Key('${contact.key}'),
+                      endActionPane: _actionPane(context, contact),
+                      child: contactContent)
+                  : contactContent,
+            );
+          },
+        ),
+      ),
+      floatingActionButton:
+          _isContactsTabActive ? filterButtonWidget(context, widget.contactListViewModel) : null,
+    );
+  }
+
+  Widget generateContactRaw(BuildContext context, ContactRecord contact, bool isLast) {
+    final image = contact.type.iconPath;
+    final currencyIcon = image != null
+        ? Image.asset(image, height: 24, width: 24)
+        : const SizedBox(height: 24, width: 24);
+    return Column(
+      children: [
+        Container(
+          key: Key('${contact.name}'),
+          padding: const EdgeInsets.only(top: 16, bottom: 16, right: 24),
+          child: Row(
+            mainAxisSize: MainAxisSize.min,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: <Widget>[
+              currencyIcon,
+              Expanded(
+                  child: Padding(
+                padding: EdgeInsets.only(left: 12),
+                child: Text(
+                  contact.name,
+                  style: TextStyle(
+                    fontSize: 14,
+                    fontWeight: FontWeight.normal,
+                    color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
+                  ),
+                ),
+              ))
+            ],
+          ),
+        ),
+        StandardListSeparator()
+      ],
+    );
+  }
+
+  ActionPane _actionPane(BuildContext context, ContactRecord contact) => ActionPane(
+        motion: const ScrollMotion(),
+        extentRatio: 0.4,
+        children: [
+          SlidableAction(
+            onPressed: (_) async => await Navigator.of(context)
+                .pushNamed(Routes.addressBookAddContact, arguments: contact),
+            backgroundColor: Colors.blue,
+            foregroundColor: Colors.white,
+            icon: Icons.edit,
+            label: S.of(context).edit,
+          ),
+          SlidableAction(
+            onPressed: (_) async {
+              final isDelete = await showAlertDialog(context);
+
+              if (isDelete) {
+                await widget.contactListViewModel.delete(contact);
+              }
+            },
+            backgroundColor: Colors.red,
+            foregroundColor: Colors.white,
+            icon: CupertinoIcons.delete,
+            label: S.of(context).delete,
+          ),
+        ],
+      );
+
+  Widget filterButtonWidget(BuildContext context, ContactListViewModel contactListViewModel) {
+    final filterIcon = Image.asset('assets/images/filter_icon.png',
+        color: Theme.of(context).appBarTheme.titleTextStyle!.color);
+    return MergeSemantics(
+      child: SizedBox(
+        height: 58,
+        width: 58,
+        child: ButtonTheme(
+          minWidth: double.minPositive,
+          child: Semantics(
+            container: true,
+            child: GestureDetector(
+              onTap: () async {
+                await showPopUp<void>(
+                  context: context,
+                  builder: (context) => FilterListWidget(
+                    initalType: contactListViewModel.orderType,
+                    initalAscending: contactListViewModel.ascending,
+                    onClose: (bool ascending, FilterListOrderType type) async {
+                      contactListViewModel.setAscending(ascending);
+                      await contactListViewModel.setOrderType(type);
+                    },
+                  ),
+                );
+              },
+              child: Semantics(
+                label: 'Transaction Filter',
+                button: true,
+                enabled: true,
+                child: Container(
+                  height: 36,
+                  width: 36,
+                  decoration: BoxDecoration(
+                    shape: BoxShape.circle,
+                    color: Theme.of(context).extension<ExchangePageTheme>()!.buttonBackgroundColor,
+                  ),
+                  child: filterIcon,
+                ),
+              ),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
   Future<bool> showAlertDialog(BuildContext context) async {
     return await showPopUp<bool>(
             context: context,
@@ -190,32 +450,4 @@ class ContactListPage extends BasePage {
             }) ??
         false;
   }
-
-  ActionPane _actionPane(BuildContext context, ContactRecord contact) => ActionPane(
-        motion: const ScrollMotion(),
-        extentRatio: 0.4,
-        children: [
-          SlidableAction(
-            onPressed: (_) async => await Navigator.of(context)
-                .pushNamed(Routes.addressBookAddContact, arguments: contact),
-            backgroundColor: Colors.blue,
-            foregroundColor: Colors.white,
-            icon: Icons.edit,
-            label: S.of(context).edit,
-          ),
-          SlidableAction(
-            onPressed: (_) async {
-              final isDelete = await showAlertDialog(context);
-
-              if (isDelete) {
-                await contactListViewModel.delete(contact);
-              }
-            },
-            backgroundColor: Colors.red,
-            foregroundColor: Colors.white,
-            icon: CupertinoIcons.delete,
-            label: S.of(context).delete,
-          ),
-        ],
-      );
 }
diff --git a/lib/src/screens/dashboard/widgets/filter_list_widget.dart b/lib/src/screens/dashboard/widgets/filter_list_widget.dart
index cda4f5f10..8e95de2af 100644
--- a/lib/src/screens/dashboard/widgets/filter_list_widget.dart
+++ b/lib/src/screens/dashboard/widgets/filter_list_widget.dart
@@ -18,9 +18,9 @@ class FilterListWidget extends StatefulWidget {
     required this.onClose,
   });
 
-  final WalletListOrderType? initalType;
+  final FilterListOrderType? initalType;
   final bool initalAscending;
-  final Function(bool, WalletListOrderType) onClose;
+  final Function(bool, FilterListOrderType) onClose;
 
   @override
   FilterListWidgetState createState() => FilterListWidgetState();
@@ -28,7 +28,7 @@ class FilterListWidget extends StatefulWidget {
 
 class FilterListWidgetState extends State<FilterListWidget> {
   late bool ascending;
-  late WalletListOrderType? type;
+  late FilterListOrderType? type;
 
   @override
   void initState() {
@@ -37,7 +37,7 @@ class FilterListWidgetState extends State<FilterListWidget> {
     type = widget.initalType;
   }
 
-  void setSelectedOrderType(WalletListOrderType? orderType) {
+  void setSelectedOrderType(FilterListOrderType? orderType) {
     setState(() {
       type = orderType;
     });
@@ -72,7 +72,7 @@ class FilterListWidgetState extends State<FilterListWidget> {
                     ),
                   ),
                 ),
-                if (type != WalletListOrderType.Custom) ...[
+                if (type != FilterListOrderType.Custom) ...[
                   sectionDivider,
                   SettingsChoicesCell(
                     ChoicesListItem<ListOrderMode>(
@@ -89,10 +89,10 @@ class FilterListWidgetState extends State<FilterListWidget> {
                 ],
                 sectionDivider,
                 RadioListTile(
-                  value: WalletListOrderType.CreationDate,
+                  value: FilterListOrderType.CreationDate,
                   groupValue: type,
                   title: Text(
-                    WalletListOrderType.CreationDate.toString(),
+                    FilterListOrderType.CreationDate.toString(),
                     style: TextStyle(
                         color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
                         fontSize: 16,
@@ -104,10 +104,10 @@ class FilterListWidgetState extends State<FilterListWidget> {
                   activeColor: Theme.of(context).primaryColor,
                 ),
                 RadioListTile(
-                  value: WalletListOrderType.Alphabetical,
+                  value: FilterListOrderType.Alphabetical,
                   groupValue: type,
                   title: Text(
-                    WalletListOrderType.Alphabetical.toString(),
+                    FilterListOrderType.Alphabetical.toString(),
                     style: TextStyle(
                         color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
                         fontSize: 16,
@@ -119,10 +119,10 @@ class FilterListWidgetState extends State<FilterListWidget> {
                   activeColor: Theme.of(context).primaryColor,
                 ),
                 RadioListTile(
-                  value: WalletListOrderType.GroupByType,
+                  value: FilterListOrderType.GroupByType,
                   groupValue: type,
                   title: Text(
-                    WalletListOrderType.GroupByType.toString(),
+                    FilterListOrderType.GroupByType.toString(),
                     style: TextStyle(
                         color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
                         fontSize: 16,
@@ -134,10 +134,10 @@ class FilterListWidgetState extends State<FilterListWidget> {
                   activeColor: Theme.of(context).primaryColor,
                 ),
                 RadioListTile(
-                  value: WalletListOrderType.Custom,
+                  value: FilterListOrderType.Custom,
                   groupValue: type,
                   title: Text(
-                    WalletListOrderType.Custom.toString(),
+                    FilterListOrderType.Custom.toString(),
                     style: TextStyle(
                         color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
                         fontSize: 16,
diff --git a/lib/src/screens/wallet_list/filtered_list.dart b/lib/src/screens/wallet_list/filtered_list.dart
index 63a1ae392..5316c8472 100644
--- a/lib/src/screens/wallet_list/filtered_list.dart
+++ b/lib/src/screens/wallet_list/filtered_list.dart
@@ -7,13 +7,17 @@ class FilteredList extends StatefulWidget {
     required this.list,
     required this.itemBuilder,
     required this.updateFunction,
+    this.canReorder = true,
     this.shrinkWrap = false,
+    this.physics,
   });
 
   final ObservableList<dynamic> list;
   final Widget Function(BuildContext, int) itemBuilder;
   final Function updateFunction;
+  final bool canReorder;
   final bool shrinkWrap;
+  final ScrollPhysics? physics;
 
   @override
   FilteredListState createState() => FilteredListState();
@@ -22,21 +26,31 @@ class FilteredList extends StatefulWidget {
 class FilteredListState extends State<FilteredList> {
   @override
   Widget build(BuildContext context) {
-    return Observer(
-      builder: (_) => ReorderableListView.builder(
-        shrinkWrap: widget.shrinkWrap,
-        physics: const BouncingScrollPhysics(),
-        itemBuilder: widget.itemBuilder,
-        itemCount: widget.list.length,
-        onReorder: (int oldIndex, int newIndex) {
-          if (oldIndex < newIndex) {
-            newIndex -= 1;
-          }
-          final dynamic item = widget.list.removeAt(oldIndex);
-          widget.list.insert(newIndex, item);
-          widget.updateFunction();
-        },
-      ),
-    );
+    if (widget.canReorder) {
+      return Observer(
+        builder: (_) => ReorderableListView.builder(
+          shrinkWrap: widget.shrinkWrap,
+          physics: widget.physics ?? const BouncingScrollPhysics(),
+          itemBuilder: widget.itemBuilder,
+          itemCount: widget.list.length,
+          onReorder: (int oldIndex, int newIndex) {
+            if (oldIndex < newIndex) {
+              newIndex -= 1;
+            }
+            final dynamic item = widget.list.removeAt(oldIndex);
+            widget.list.insert(newIndex, item);
+            widget.updateFunction();
+          },
+        ),
+      );
+    } else {
+      return Observer(
+        builder: (_) => ListView.builder(
+          physics: widget.physics ?? const BouncingScrollPhysics(),
+          itemBuilder: widget.itemBuilder,
+          itemCount: widget.list.length,
+        ),
+      );
+    }
   }
 }
diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart
index d17534f6b..afb86cf0a 100644
--- a/lib/src/screens/wallet_list/wallet_list_page.dart
+++ b/lib/src/screens/wallet_list/wallet_list_page.dart
@@ -59,7 +59,7 @@ class WalletListPage extends BasePage {
                   builder: (context) => FilterListWidget(
                     initalType: walletListViewModel.orderType,
                     initalAscending: walletListViewModel.ascending,
-                    onClose: (bool ascending, WalletListOrderType type) async {
+                    onClose: (bool ascending, FilterListOrderType type) async {
                       walletListViewModel.setAscending(ascending);
                       await walletListViewModel.setOrderType(type);
                     },
diff --git a/lib/src/widgets/collapsible_standart_list.dart b/lib/src/widgets/collapsible_standart_list.dart
deleted file mode 100644
index 83e4daee2..000000000
--- a/lib/src/widgets/collapsible_standart_list.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-import 'package:cake_wallet/src/widgets/standard_list.dart';
-import 'package:flutter/material.dart';
-
-class CollapsibleSectionList extends SectionStandardList {
-  CollapsibleSectionList(
-      {required int sectionCount,
-      required int Function(int sectionIndex) itemCounter,
-      required Widget Function(int sectionIndex, int itemIndex) itemBuilder,
-      Widget Function(int sectionIndex)? sectionTitleBuilder,
-      bool hasTopSeparator = false})
-      : super(
-            hasTopSeparator: hasTopSeparator,
-            sectionCount: sectionCount,
-            itemCounter: itemCounter,
-            itemBuilder: itemBuilder,
-            sectionTitleBuilder: sectionTitleBuilder);
-
-  @override
-  Widget buildTitle(List<Widget> items, int sectionIndex) {
-    if (sectionTitleBuilder == null) {
-      throw Exception('Cannot to build title. sectionTitleBuilder is null');
-    }
-    return sectionTitleBuilder!.call(sectionIndex);
-  }
-
-  @override
-  List<Widget> buildSection(int itemCount, List<Widget> items, int sectionIndex) {
-    final List<Widget> section = [];
-
-    for (var itemIndex = 0; itemIndex < itemCount; itemIndex++) {
-      final item = itemBuilder(sectionIndex, itemIndex);
-
-      section.add(StandardListSeparator());
-
-      section.add(item);
-    }
-    return section;
-  }
-}
diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart
index 9f03c95c3..2eadbd8a9 100644
--- a/lib/store/settings_store.dart
+++ b/lib/store/settings_store.dart
@@ -62,9 +62,11 @@ abstract class SettingsStoreBase with Store {
       required bool initialAppSecure,
       required bool initialDisableBuy,
       required bool initialDisableSell,
+      required FilterListOrderType initialWalletListOrder,
+      required FilterListOrderType initialContactListOrder,
       required bool initialDisableBulletin,
-      required WalletListOrderType initialWalletListOrder,
       required bool initialWalletListAscending,
+      required bool initialContactListAscending,
       required FiatApiMode initialFiatMode,
       required bool initialAllowBiometricalAuthentication,
       required String initialTotpSecretKey,
@@ -149,7 +151,9 @@ abstract class SettingsStoreBase with Store {
         disableSell = initialDisableSell,
         disableBulletin = initialDisableBulletin,
         walletListOrder = initialWalletListOrder,
+        contactListOrder = initialContactListOrder,
         walletListAscending = initialWalletListAscending,
+        contactListAscending = initialContactListAscending,
         shouldShowMarketPlaceInDashboard = initialShouldShowMarketPlaceInDashboard,
         exchangeStatus = initialExchangeStatus,
         currentTheme = initialTheme,
@@ -324,14 +328,24 @@ abstract class SettingsStoreBase with Store {
 
     reaction(
         (_) => walletListOrder,
-        (WalletListOrderType walletListOrder) =>
+        (FilterListOrderType walletListOrder) =>
             sharedPreferences.setInt(PreferencesKey.walletListOrder, walletListOrder.index));
 
+    reaction(
+            (_) => contactListOrder,
+            (FilterListOrderType contactListOrder) =>
+            sharedPreferences.setInt(PreferencesKey.contactListOrder, contactListOrder.index));
+
     reaction(
         (_) => walletListAscending,
         (bool walletListAscending) =>
             sharedPreferences.setBool(PreferencesKey.walletListAscending, walletListAscending));
 
+    reaction(
+            (_) => contactListAscending,
+            (bool contactListAscending) =>
+            sharedPreferences.setBool(PreferencesKey.contactListAscending, contactListAscending));
+
     reaction(
         (_) => autoGenerateSubaddressStatus,
         (AutoGenerateSubaddressStatus autoGenerateSubaddressStatus) => sharedPreferences.setInt(
@@ -645,15 +659,21 @@ abstract class SettingsStoreBase with Store {
   @observable
   bool disableSell;
 
+  @observable
+  FilterListOrderType contactListOrder;
+
   @observable
   bool disableBulletin;
 
   @observable
-  WalletListOrderType walletListOrder;
+  FilterListOrderType walletListOrder;
 
   @observable
   bool walletListAscending;
 
+  @observable
+  bool contactListAscending;
+
   @observable
   bool allowBiometricalAuthentication;
 
@@ -907,9 +927,13 @@ abstract class SettingsStoreBase with Store {
     final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false;
     final disableBulletin = sharedPreferences.getBool(PreferencesKey.disableBulletinKey) ?? false;
     final walletListOrder =
-        WalletListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0];
+        FilterListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0];
+    final contactListOrder =
+    FilterListOrderType.values[sharedPreferences.getInt(PreferencesKey.contactListOrder) ?? 0];
     final walletListAscending =
         sharedPreferences.getBool(PreferencesKey.walletListAscending) ?? true;
+    final contactListAscending =
+        sharedPreferences.getBool(PreferencesKey.contactListAscending) ?? true;
     final currentFiatApiMode = FiatApiMode.deserialize(
         raw: sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ??
             FiatApiMode.enabled.raw);
@@ -1200,6 +1224,8 @@ abstract class SettingsStoreBase with Store {
       initialDisableBulletin: disableBulletin,
       initialWalletListOrder: walletListOrder,
       initialWalletListAscending: walletListAscending,
+      initialContactListOrder: contactListOrder,
+      initialContactListAscending: contactListAscending,
       initialFiatMode: currentFiatApiMode,
       initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
       initialCake2FAPresetOptions: selectedCake2FAPreset,
@@ -1348,9 +1374,11 @@ abstract class SettingsStoreBase with Store {
     disableBulletin =
         sharedPreferences.getBool(PreferencesKey.disableBulletinKey) ?? disableBulletin;
     walletListOrder =
-        WalletListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0];
+        FilterListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0];
+    contactListOrder =
+    FilterListOrderType.values[sharedPreferences.getInt(PreferencesKey.contactListOrder) ?? 0];
     walletListAscending = sharedPreferences.getBool(PreferencesKey.walletListAscending) ?? true;
-
+    contactListAscending = sharedPreferences.getBool(PreferencesKey.contactListAscending) ?? true;
     shouldShowMarketPlaceInDashboard =
         sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ??
             shouldShowMarketPlaceInDashboard;
diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart
index 89192583e..0015463a5 100644
--- a/lib/view_model/contact_list/contact_list_view_model.dart
+++ b/lib/view_model/contact_list/contact_list_view_model.dart
@@ -1,18 +1,20 @@
 import 'dart:async';
+
 import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
+import 'package:cake_wallet/entities/contact.dart';
 import 'package:cake_wallet/entities/contact_base.dart';
+import 'package:cake_wallet/entities/contact_record.dart';
 import 'package:cake_wallet/entities/wallet_contact.dart';
+import 'package:cake_wallet/entities/wallet_list_order_types.dart';
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/store/settings_store.dart';
+import 'package:cake_wallet/utils/mobx.dart';
+import 'package:collection/collection.dart';
+import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
-import 'package:cake_wallet/entities/contact_record.dart';
-import 'package:cake_wallet/entities/contact.dart';
-import 'package:cake_wallet/utils/mobx.dart';
-import 'package:cw_core/crypto_currency.dart';
-import 'package:collection/collection.dart';
 
 part 'contact_list_view_model.g.dart';
 
@@ -75,6 +77,8 @@ abstract class ContactListViewModelBase with Store {
     _subscription = contactSource.bindToListWithTransform(
         contacts, (Contact contact) => ContactRecord(contactSource, contact),
         initialFire: true);
+
+    setOrderType(settingsStore.contactListOrder);
   }
 
   String _createName(String walletName, String label, {int? key = null}) {
@@ -93,6 +97,10 @@ abstract class ContactListViewModelBase with Store {
 
   bool get isEditable => _currency == null;
 
+  FilterListOrderType? get orderType => settingsStore.contactListOrder;
+
+  bool get ascending => settingsStore.contactListAscending;
+
   @computed
   bool get shouldRequireTOTP2FAForAddingContacts =>
       settingsStore.shouldRequireTOTP2FAForAddingContacts;
@@ -118,4 +126,70 @@ abstract class ContactListViewModelBase with Store {
         _currency?.toString() == element.type.tag ||
         _currency?.tag == element.type.toString();
   }
+
+  void dispose() async {
+    _subscription?.cancel();
+    final List<Contact> contactsSourceCopy = contacts.map((e) => e.original).toList();
+    await reorderContacts(contactsSourceCopy);
+  }
+
+  void reorderAccordingToContactList() =>
+      settingsStore.contactListOrder = FilterListOrderType.Custom;
+
+  Future<void> reorderContacts(List<Contact> contactCopy) async {
+    await contactSource.deleteAll(contactCopy.map((e) => e.key).toList());
+    await contactSource.addAll(contactCopy);
+  }
+
+  Future<void> sortGroupByType() async {
+    List<Contact> contactsSourceCopy = contactSource.values.toList();
+
+    contactsSourceCopy.sort((a, b) => ascending
+        ? a.type.toString().compareTo(b.type.toString())
+        : b.type.toString().compareTo(a.type.toString()));
+
+    await reorderContacts(contactsSourceCopy);
+  }
+
+  Future<void> sortAlphabetically() async {
+    List<Contact> contactsSourceCopy = contactSource.values.toList();
+
+    contactsSourceCopy
+        .sort((a, b) => ascending ? a.name.compareTo(b.name) : b.name.compareTo(a.name));
+
+    await reorderContacts(contactsSourceCopy);
+  }
+
+  Future<void> sortByCreationDate() async {
+    List<Contact> contactsSourceCopy = contactSource.values.toList();
+
+    contactsSourceCopy.sort((a, b) =>
+        ascending ? a.lastChange.compareTo(b.lastChange) : b.lastChange.compareTo(a.lastChange));
+
+    await reorderContacts(contactsSourceCopy);
+  }
+
+  void setAscending(bool ascending) => settingsStore.contactListAscending = ascending;
+
+  Future<void> setOrderType(FilterListOrderType? type) async {
+    if (type == null) return;
+
+    settingsStore.contactListOrder = type;
+
+    switch (type) {
+      case FilterListOrderType.CreationDate:
+        await sortByCreationDate();
+        break;
+      case FilterListOrderType.Alphabetical:
+        await sortAlphabetically();
+        break;
+      case FilterListOrderType.GroupByType:
+        await sortGroupByType();
+        break;
+      case FilterListOrderType.Custom:
+      default:
+        reorderAccordingToContactList();
+        break;
+    }
+  }
 }
diff --git a/lib/view_model/contact_list/contact_view_model.dart b/lib/view_model/contact_list/contact_view_model.dart
index 053cfe4c5..93abfb11c 100644
--- a/lib/view_model/contact_list/contact_view_model.dart
+++ b/lib/view_model/contact_list/contact_view_model.dart
@@ -2,7 +2,7 @@ import 'package:cake_wallet/entities/contact_record.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 import 'package:cake_wallet/core/execution_state.dart';
-import 'package:cw_core/wallet_base.dart';
+import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/entities/contact.dart';
 import 'package:cw_core/crypto_currency.dart';
 
@@ -17,7 +17,9 @@ abstract class ContactViewModelBase with Store {
         _contact = contact,
         name = contact?.name ?? '',
         address = contact?.address ?? '',
-        currency = contact?.type;
+        currency = contact?.type,
+        lastChange = contact?.lastChange;
+
 
   @observable
   ExecutionState state;
@@ -31,6 +33,8 @@ abstract class ContactViewModelBase with Store {
   @observable
   CryptoCurrency? currency;
 
+  DateTime? lastChange;
+
   @computed
   bool get isReady =>
       name.isNotEmpty &&
@@ -51,20 +55,32 @@ abstract class ContactViewModelBase with Store {
   Future<void> save() async {
     try {
       state = IsExecutingState();
+      final now = DateTime.now();
+
+      if (doesContactNameExist(name)) {
+        state = FailureState(S.current.contact_name_exists);
+        return;
+      }
 
       if (_contact != null && _contact!.original.isInBox) {
         _contact?.name = name;
         _contact?.address = address;
         _contact?.type = currency!;
+        _contact?.lastChange = now;
         await _contact?.save();
       } else {
         await _contacts
-            .add(Contact(name: name, address: address, type: currency!));
+            .add(Contact(name: name, address: address, type: currency!, lastChange: now));
       }
 
+            lastChange = now;
       state = ExecutedSuccessfullyState();
     } catch (e) {
       state = FailureState(e.toString());
     }
   }
-}
+
+  bool doesContactNameExist(String name) {
+    return _contacts.values.any((contact) => contact.name == name);
+  }
+}
\ No newline at end of file
diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart
index 0ae6b75a5..725af843f 100644
--- a/lib/view_model/wallet_list/wallet_list_view_model.dart
+++ b/lib/view_model/wallet_list/wallet_list_view_model.dart
@@ -76,7 +76,7 @@ abstract class WalletListViewModelBase with Store {
     await _appStore.changeCurrentWallet(wallet);
   }
 
-  WalletListOrderType? get orderType => _appStore.settingsStore.walletListOrder;
+  FilterListOrderType? get orderType => _appStore.settingsStore.walletListOrder;
 
   bool get ascending => _appStore.settingsStore.walletListAscending;
 
@@ -108,7 +108,7 @@ abstract class WalletListViewModelBase with Store {
       return;
     }
 
-    _appStore.settingsStore.walletListOrder = WalletListOrderType.Custom;
+    _appStore.settingsStore.walletListOrder = FilterListOrderType.Custom;
 
     // make a copy of the walletInfoSource:
     List<WalletInfo> walletInfoSourceCopy = _walletInfoSource.values.toList();
@@ -186,22 +186,22 @@ abstract class WalletListViewModelBase with Store {
     _appStore.settingsStore.walletListAscending = ascending;
   }
 
-  Future<void> setOrderType(WalletListOrderType? type) async {
+  Future<void> setOrderType(FilterListOrderType? type) async {
     if (type == null) return;
 
     _appStore.settingsStore.walletListOrder = type;
 
     switch (type) {
-      case WalletListOrderType.CreationDate:
+      case FilterListOrderType.CreationDate:
         await sortByCreationDate();
         break;
-      case WalletListOrderType.Alphabetical:
+      case FilterListOrderType.Alphabetical:
         await sortAlphabetically();
         break;
-      case WalletListOrderType.GroupByType:
+      case FilterListOrderType.GroupByType:
         await sortGroupByType();
         break;
-      case WalletListOrderType.Custom:
+      case FilterListOrderType.Custom:
       default:
         await reorderAccordingToWalletList();
         break;
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index 81fe3cc2c..c2be1504a 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -937,5 +937,6 @@
   "you_pay": "انت تدفع",
   "you_will_get": "حول الى",
   "you_will_send": "تحويل من",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "                   .ﻒﻠﺘﺨﻣ ﻢﺳﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ .ﻞﻌﻔﻟﺎﺑ ﺓﺩﻮﺟﻮﻣ ﻢﺳﻻﺍ ﺍﺬﻬﺑ ﻝﺎﺼﺗﺍ ﺔﻬﺟ"
+}
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index 50db1610a..8b68d0d1e 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -937,5 +937,6 @@
   "you_pay": "Вие плащате",
   "you_will_get": "Обръщане в",
   "you_will_send": "Обръщане от",
-  "yy": "гг"
-}
\ No newline at end of file
+  "yy": "гг",
+  "contact_name_exists": "Вече съществува контакт с това име. Моля, изберете друго име."
+}
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index ddc91340b..9b48ebdc7 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -937,5 +937,6 @@
   "you_pay": "Zaplatíte",
   "you_will_get": "Směnit na",
   "you_will_send": "Směnit z",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "Kontakt s tímto jménem již existuje. Vyberte prosím jiný název."
+}
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index d6a0ee9af..4f5fd23b3 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -940,5 +940,6 @@
   "you_pay": "You Pay",
   "you_will_get": "Convert to",
   "you_will_send": "Convert from",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "A contact with that name already exists. Please choose a different name."
+}
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 25c9f95c1..fd20a8b30 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -938,5 +938,6 @@
   "you_pay": "Tú pagas",
   "you_will_get": "Convertir a",
   "you_will_send": "Convertir de",
-  "yy": "YY"
+  "yy": "YY",
+  "contact_name_exists": "Ya existe un contacto con ese nombre. Elija un nombre diferente."
 }
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index be5b48dd8..50aceb2f1 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -937,5 +937,6 @@
   "you_pay": "Vous payez",
   "you_will_get": "Convertir vers",
   "you_will_send": "Convertir depuis",
-  "yy": "AA"
-}
\ No newline at end of file
+  "yy": "AA",
+  "contact_name_exists": "Un contact portant ce nom existe déjà. Veuillez choisir un autre nom."
+}
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index 4deb0df1d..e66859531 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -939,5 +939,6 @@
   "you_pay": "Ka Bayar",
   "you_will_get": "Maida zuwa",
   "you_will_send": "Maida daga",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "An riga an sami lamba tare da wannan sunan. Da fatan za a zaɓi suna daban."
+}
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index 5161250fc..bc8b81211 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -939,5 +939,6 @@
   "you_pay": "आप भुगतान करते हैं",
   "you_will_get": "में बदलें",
   "you_will_send": "से रूपांतरित करें",
-  "yy": "वाईवाई"
-}
\ No newline at end of file
+  "yy": "वाईवाई",
+  "contact_name_exists": "उस नाम का एक संपर्क पहले से मौजूद है. कृपया कोई भिन्न नाम चुनें."
+}
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 8ef92aaf0..9ff57707d 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -937,5 +937,6 @@
   "you_pay": "Vi plaćate",
   "you_will_get": "Razmijeni u",
   "you_will_send": "Razmijeni iz",
-  "yy": "GG"
-}
\ No newline at end of file
+  "yy": "GG",
+  "contact_name_exists": "Kontakt s tim imenom već postoji. Odaberite drugo ime."
+}
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index 5f93082ec..2858fa193 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -940,5 +940,6 @@
   "you_pay": "Anda Membayar",
   "you_will_get": "Konversi ke",
   "you_will_send": "Konversi dari",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "Kontak dengan nama tersebut sudah ada. Silakan pilih nama lain."
+}
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index 08ae928af..034376a6c 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -940,5 +940,6 @@
   "you_pay": "Tu paghi",
   "you_will_get": "Converti a",
   "you_will_send": "Conveti da",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "Esiste già un contatto con quel nome. Scegli un nome diverso."
+}
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index d70eca31b..7f0792063 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -938,5 +938,6 @@
   "you_pay": "あなたが支払う",
   "you_will_get": "に変換",
   "you_will_send": "から変換",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "その名前の連絡先はすでに存在します。別の名前を選択してください。"
+}
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 133ca1838..6ba402ce3 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -939,5 +939,6 @@
   "you_will_get": "로 변환하다",
   "you_will_send": "다음에서 변환",
   "YY": "YY",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "해당 이름을 가진 연락처가 이미 존재합니다. 다른 이름을 선택하세요."
+}
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index 1727f0d71..69b888b5a 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -937,5 +937,6 @@
   "you_pay": "သင်ပေးချေပါ။",
   "you_will_get": "သို့ပြောင်းပါ။",
   "you_will_send": "မှပြောင်းပါ။",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "ထိုအမည်နှင့် အဆက်အသွယ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ။"
+}
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 3f2df531b..2c259bf80 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -938,5 +938,6 @@
   "you_pay": "U betaalt",
   "you_will_get": "Converteren naar",
   "you_will_send": "Converteren van",
-  "yy": "JJ"
-}
\ No newline at end of file
+  "yy": "JJ",
+  "contact_name_exists": "Er bestaat al een contact met die naam. Kies een andere naam."
+}
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index 91b265144..936339708 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -937,5 +937,6 @@
   "you_pay": "Płacisz",
   "you_will_get": "Konwertuj na",
   "you_will_send": "Konwertuj z",
-  "yy": "RR"
-}
\ No newline at end of file
+  "yy": "RR",
+  "contact_name_exists": "Kontakt o tej nazwie już istnieje. Proszę wybrać inną nazwę."
+}
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index 524dbcace..0cc0cc00a 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -941,4 +941,4 @@
   "you_will_get": "Converter para",
   "you_will_send": "Converter de",
   "yy": "aa"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index 1a8c2447f..8aeb56a86 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -938,5 +938,6 @@
   "you_pay": "Вы платите",
   "you_will_get": "Конвертировать в",
   "you_will_send": "Конвертировать из",
-  "yy": "ГГ"
-}
\ No newline at end of file
+  "yy": "ГГ",
+  "contact_name_exists": "Контакт с таким именем уже существует. Пожалуйста, выберите другое имя."
+}
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index 213f74530..736eb8762 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -937,5 +937,6 @@
   "you_pay": "คุณจ่าย",
   "you_will_get": "แปลงเป็น",
   "you_will_send": "แปลงจาก",
-  "yy": "ปี"
-}
\ No newline at end of file
+  "yy": "ปี",
+  "contact_name_exists": "มีผู้ติดต่อชื่อนั้นอยู่แล้ว โปรดเลือกชื่ออื่น"
+}
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index 0ca8ee665..e68bd0b22 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -938,4 +938,4 @@
   "you_will_get": "I-convert sa",
   "you_will_send": "I-convert mula sa",
   "yy": "YY"
-}
\ No newline at end of file
+}
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index b23f64d60..83e8f6cbc 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -937,5 +937,6 @@
   "you_pay": "Şu kadar ödeyeceksin: ",
   "you_will_get": "Biçimine dönüştür:",
   "you_will_send": "Biçiminden dönüştür:",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "Bu isimde bir kişi zaten mevcut. Lütfen farklı bir ad seçin."
+}
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index 79dc0543f..909d9c01f 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -938,5 +938,6 @@
   "you_pay": "Ви платите",
   "you_will_get": "Конвертувати в",
   "you_will_send": "Конвертувати з",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "Контакт із такою назвою вже існує. Виберіть інше ім'я."
+}
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index 0a136d140..2dbc97102 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -939,5 +939,6 @@
   "you_pay": "تم ادا کرو",
   "you_will_get": "میں تبدیل کریں۔",
   "you_will_send": "سے تبدیل کریں۔",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": " ۔ﮟﯾﺮﮐ ﺐﺨﺘﻨﻣ ﻡﺎﻧ ﻒﻠﺘﺨﻣ ﮏﯾﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮯﮨ ﺩﻮﺟﻮﻣ ﮯﺳ ﮯﻠﮩﭘ ﮧﻄﺑﺍﺭ ﮏﯾﺍ ﮫﺗﺎﺳ ﮯﮐ ﻡﺎﻧ ﺱﺍ"
+}
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 14270120c..03c7c95ef 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -938,5 +938,6 @@
   "you_pay": "Ẹ sàn",
   "you_will_get": "Ṣe pàṣípààrọ̀ sí",
   "you_will_send": "Ṣe pàṣípààrọ̀ láti",
-  "yy": "Ọd"
-}
\ No newline at end of file
+  "yy": "Ọd",
+  "contact_name_exists": "Olubasọrọ pẹlu orukọ yẹn ti wa tẹlẹ. Jọwọ yan orukọ ti o yatọ."
+}
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index 65047b4fe..5c8d708f4 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -937,5 +937,6 @@
   "you_pay": "你付钱",
   "you_will_get": "转换到",
   "you_will_send": "转换自",
-  "yy": "YY"
-}
\ No newline at end of file
+  "yy": "YY",
+  "contact_name_exists": "已存在具有该名称的联系人。请选择不同的名称。"
+}

From c8cfc2cff1026c4c433d0f9e683a2c4cbb4023eb Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Wed, 6 Nov 2024 18:57:36 -0800
Subject: [PATCH 31/50] Mweb enhancements 4 (#1768)

* [skip-ci] show mweb confirmations, show last mweb balance while syncing

* potential send-all fix

* [skip-ci] undo fix that didn't work

* [skip-ci] undo unnecessary changes

* [skip ci] add export mweb logs screen

* [skip ci] cleanup

* confirmation fixes

* catch electrum call errors

* [skip ci] undo some changes

* potential electrum fixes + mweb logs display only last 10000 characters

* Add question mark and link to MWEB card

* updates

* show negative unconfirmed mweb balanaces + other fixes [skip ci]

* error handling

* [skip ci] [wip] check if node supports mweb

* check fee before building tx

* [skip ci] minor

* [skip ci] minor

* mweb node setting [wip] [skip ci]

* prioritize mweb coins when selecting inputs from the pool

* potential connection edgecase fix

* translations + mweb node fixes

* don't use mweb for exchange refund address

* add peg in / out labels and make 6 confs only show up for peg in / out

* bump bitcoin_base version to v9

* [skip ci] fix logs page

* don't fetch txinfo for non-mweb addresses [skip ci]

* fix non-mweb confirmations

* rename always scan to enable mweb

* Update litecoin_wallet_addresses.dart

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* Update cw_mweb.dart

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* [skip ci] review updates pt.1

* [skip ci] minor code cleanup

* [skip ci] use exception handler

* exception handling [skip ci]

* [skip ci] exception handling

* trigger build

* pegout label fixes

* fix showing change transactions on peg-out

* minor code cleanup and minor peg-out fix

* final balance fixes

* non-mweb confirmations potential fix

* [skip ci] wip

* trigger build

---------

Co-authored-by: tuxpizza <tuxsudo@tux.pizza>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 cw_bitcoin/lib/electrum.dart                  |   2 +
 cw_bitcoin/lib/electrum_balance.dart          |  12 +-
 cw_bitcoin/lib/electrum_transaction_info.dart |   9 +-
 cw_bitcoin/lib/electrum_wallet.dart           | 130 +++++---
 cw_bitcoin/lib/litecoin_wallet.dart           | 310 ++++++++++++------
 cw_bitcoin/lib/litecoin_wallet_addresses.dart |  17 +-
 cw_bitcoin/lib/litecoin_wallet_service.dart   |   4 +
 .../lib/pending_bitcoin_transaction.dart      |   3 +-
 cw_bitcoin/pubspec.yaml                       |   2 +-
 cw_bitcoin_cash/pubspec.yaml                  |   2 +-
 cw_core/lib/mweb_utxo.dart                    |   4 +
 cw_core/lib/node.dart                         |   3 +
 cw_core/lib/transaction_info.dart             |   3 +-
 cw_mweb/lib/cw_mweb.dart                      |  28 +-
 lib/di.dart                                   |   6 +
 lib/entities/preferences_key.dart             |   1 +
 lib/router.dart                               |  10 +
 lib/routes.dart                               |   2 +
 .../screens/dashboard/pages/balance_page.dart |  42 ++-
 lib/src/screens/settings/mweb_logs_page.dart  | 127 +++++++
 lib/src/screens/settings/mweb_node_page.dart  |  56 ++++
 lib/src/screens/settings/mweb_settings.dart   |  10 +-
 lib/store/settings_store.dart                 |  25 +-
 .../dashboard/balance_view_model.dart         |   2 +-
 .../dashboard/transaction_list_item.dart      |  52 ++-
 .../settings/mweb_settings_view_model.dart    |  50 +++
 pubspec_base.yaml                             |   2 +-
 res/values/strings_ar.arb                     |   4 +
 res/values/strings_bg.arb                     |   4 +
 res/values/strings_cs.arb                     |   4 +
 res/values/strings_de.arb                     |   6 +-
 res/values/strings_en.arb                     |   4 +
 res/values/strings_es.arb                     |   4 +
 res/values/strings_fr.arb                     |   4 +
 res/values/strings_ha.arb                     |   4 +
 res/values/strings_hi.arb                     |   4 +
 res/values/strings_hr.arb                     |   4 +
 res/values/strings_hy.arb                     |   4 +
 res/values/strings_id.arb                     |   4 +
 res/values/strings_it.arb                     |   4 +
 res/values/strings_ja.arb                     |   4 +
 res/values/strings_ko.arb                     |   4 +
 res/values/strings_my.arb                     |   4 +
 res/values/strings_nl.arb                     |   4 +
 res/values/strings_pl.arb                     |   4 +
 res/values/strings_pt.arb                     |   4 +
 res/values/strings_ru.arb                     |   4 +
 res/values/strings_th.arb                     |   4 +
 res/values/strings_tl.arb                     |   4 +
 res/values/strings_tr.arb                     |   4 +
 res/values/strings_uk.arb                     |   4 +
 res/values/strings_ur.arb                     |   4 +
 res/values/strings_vi.arb                     |   4 +
 res/values/strings_yo.arb                     |   4 +
 res/values/strings_zh.arb                     |   4 +
 55 files changed, 821 insertions(+), 207 deletions(-)
 create mode 100644 lib/src/screens/settings/mweb_logs_page.dart
 create mode 100644 lib/src/screens/settings/mweb_node_page.dart

diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart
index a18c038fa..df8e14119 100644
--- a/cw_bitcoin/lib/electrum.dart
+++ b/cw_bitcoin/lib/electrum.dart
@@ -124,6 +124,7 @@ class ElectrumClient {
         final errorMsg = error.toString();
         print(errorMsg);
         unterminatedString = '';
+        socket = null;
       },
       onDone: () {
         print("SOCKET CLOSED!!!!!");
@@ -132,6 +133,7 @@ class ElectrumClient {
           if (host == socket?.address.host || socket == null) {
             _setConnectionStatus(ConnectionStatus.disconnected);
             socket?.destroy();
+            socket = null;
           }
         } catch (e) {
           print("onDone: $e");
diff --git a/cw_bitcoin/lib/electrum_balance.dart b/cw_bitcoin/lib/electrum_balance.dart
index 4e37f40b1..ebd2f06ae 100644
--- a/cw_bitcoin/lib/electrum_balance.dart
+++ b/cw_bitcoin/lib/electrum_balance.dart
@@ -24,9 +24,12 @@ class ElectrumBalance extends Balance {
     final decoded = json.decode(jsonSource) as Map;
 
     return ElectrumBalance(
-        confirmed: decoded['confirmed'] as int? ?? 0,
-        unconfirmed: decoded['unconfirmed'] as int? ?? 0,
-        frozen: decoded['frozen'] as int? ?? 0);
+      confirmed: decoded['confirmed'] as int? ?? 0,
+      unconfirmed: decoded['unconfirmed'] as int? ?? 0,
+      frozen: decoded['frozen'] as int? ?? 0,
+      secondConfirmed: decoded['secondConfirmed'] as int? ?? 0,
+      secondUnconfirmed: decoded['secondUnconfirmed'] as int? ?? 0,
+    );
   }
 
   int confirmed;
@@ -36,8 +39,7 @@ class ElectrumBalance extends Balance {
   int secondUnconfirmed = 0;
 
   @override
-  String get formattedAvailableBalance =>
-      bitcoinAmountToString(amount: confirmed - frozen);
+  String get formattedAvailableBalance => bitcoinAmountToString(amount: confirmed - frozen);
 
   @override
   String get formattedAdditionalBalance => bitcoinAmountToString(amount: unconfirmed);
diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart
index 1ab7799e3..7a8b3b951 100644
--- a/cw_bitcoin/lib/electrum_transaction_info.dart
+++ b/cw_bitcoin/lib/electrum_transaction_info.dart
@@ -41,6 +41,7 @@ class ElectrumTransactionInfo extends TransactionInfo {
     String? to,
     this.unspents,
     this.isReceivedSilentPayment = false,
+    Map<String, dynamic>? additionalInfo,
   }) {
     this.id = id;
     this.height = height;
@@ -54,6 +55,7 @@ class ElectrumTransactionInfo extends TransactionInfo {
     this.isReplaced = isReplaced;
     this.confirmations = confirmations;
     this.to = to;
+    this.additionalInfo = additionalInfo ?? {};
   }
 
   factory ElectrumTransactionInfo.fromElectrumVerbose(Map<String, Object> obj, WalletType type,
@@ -212,6 +214,7 @@ class ElectrumTransactionInfo extends TransactionInfo {
               BitcoinSilentPaymentsUnspent.fromJSON(null, unspent as Map<String, dynamic>))
           .toList(),
       isReceivedSilentPayment: data['isReceivedSilentPayment'] as bool? ?? false,
+      additionalInfo: data['additionalInfo'] as Map<String, dynamic>?,
     );
   }
 
@@ -246,7 +249,8 @@ class ElectrumTransactionInfo extends TransactionInfo {
         isReplaced: isReplaced ?? false,
         inputAddresses: inputAddresses,
         outputAddresses: outputAddresses,
-        confirmations: info.confirmations);
+        confirmations: info.confirmations,
+        additionalInfo: additionalInfo);
   }
 
   Map<String, dynamic> toJson() {
@@ -265,10 +269,11 @@ class ElectrumTransactionInfo extends TransactionInfo {
     m['inputAddresses'] = inputAddresses;
     m['outputAddresses'] = outputAddresses;
     m['isReceivedSilentPayment'] = isReceivedSilentPayment;
+    m['additionalInfo'] = additionalInfo;
     return m;
   }
 
   String toString() {
-    return 'ElectrumTransactionInfo(id: $id, height: $height, amount: $amount, fee: $fee, direction: $direction, date: $date, isPending: $isPending, isReplaced: $isReplaced, confirmations: $confirmations, to: $to, unspent: $unspents, inputAddresses: $inputAddresses, outputAddresses: $outputAddresses)';
+    return 'ElectrumTransactionInfo(id: $id, height: $height, amount: $amount, fee: $fee, direction: $direction, date: $date, isPending: $isPending, isReplaced: $isReplaced, confirmations: $confirmations, to: $to, unspent: $unspents, inputAddresses: $inputAddresses, outputAddresses: $outputAddresses, additionalInfo: $additionalInfo)';
   }
 }
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index c05095cf1..7988a4479 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -5,6 +5,7 @@ import 'dart:isolate';
 
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:cw_bitcoin/bitcoin_wallet.dart';
+import 'package:cw_bitcoin/litecoin_wallet.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:collection/collection.dart';
@@ -52,10 +53,9 @@ part 'electrum_wallet.g.dart';
 
 class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet;
 
-abstract class ElectrumWalletBase extends WalletBase<
-    ElectrumBalance,
-    ElectrumTransactionHistory,
-    ElectrumTransactionInfo> with Store, WalletKeysFile {
+abstract class ElectrumWalletBase
+    extends WalletBase<ElectrumBalance, ElectrumTransactionHistory, ElectrumTransactionInfo>
+    with Store, WalletKeysFile {
   ElectrumWalletBase({
     required String password,
     required WalletInfo walletInfo,
@@ -71,8 +71,8 @@ abstract class ElectrumWalletBase extends WalletBase<
     ElectrumBalance? initialBalance,
     CryptoCurrency? currency,
     this.alwaysScan,
-  })  : accountHD = getAccountHDWallet(
-            currency, network, seedBytes, xpub, walletInfo.derivationInfo),
+  })  : accountHD =
+            getAccountHDWallet(currency, network, seedBytes, xpub, walletInfo.derivationInfo),
         syncStatus = NotConnectedSyncStatus(),
         _password = password,
         _feeRates = <int>[],
@@ -107,12 +107,8 @@ abstract class ElectrumWalletBase extends WalletBase<
     sharedPrefs.complete(SharedPreferences.getInstance());
   }
 
-  static Bip32Slip10Secp256k1 getAccountHDWallet(
-      CryptoCurrency? currency,
-      BasedUtxoNetwork network,
-      Uint8List? seedBytes,
-      String? xpub,
-      DerivationInfo? derivationInfo) {
+  static Bip32Slip10Secp256k1 getAccountHDWallet(CryptoCurrency? currency, BasedUtxoNetwork network,
+      Uint8List? seedBytes, String? xpub, DerivationInfo? derivationInfo) {
     if (seedBytes == null && xpub == null) {
       throw Exception(
           "To create a Wallet you need either a seed or an xpub. This should not happen");
@@ -123,9 +119,8 @@ abstract class ElectrumWalletBase extends WalletBase<
         case CryptoCurrency.btc:
         case CryptoCurrency.ltc:
         case CryptoCurrency.tbtc:
-          return Bip32Slip10Secp256k1.fromSeed(seedBytes, getKeyNetVersion(network))
-                  .derivePath(_hardenedDerivationPath(
-                      derivationInfo?.derivationPath ?? electrum_path))
+          return Bip32Slip10Secp256k1.fromSeed(seedBytes, getKeyNetVersion(network)).derivePath(
+                  _hardenedDerivationPath(derivationInfo?.derivationPath ?? electrum_path))
               as Bip32Slip10Secp256k1;
         case CryptoCurrency.bch:
           return bitcoinCashHDWallet(seedBytes);
@@ -134,13 +129,11 @@ abstract class ElectrumWalletBase extends WalletBase<
       }
     }
 
-    return Bip32Slip10Secp256k1.fromExtendedKey(
-        xpub!, getKeyNetVersion(network));
+    return Bip32Slip10Secp256k1.fromExtendedKey(xpub!, getKeyNetVersion(network));
   }
 
   static Bip32Slip10Secp256k1 bitcoinCashHDWallet(Uint8List seedBytes) =>
-      Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'")
-          as Bip32Slip10Secp256k1;
+      Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'") as Bip32Slip10Secp256k1;
 
   static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
       inputsCount * 68 + outputsCounts * 34 + 10;
@@ -250,7 +243,7 @@ abstract class ElectrumWalletBase extends WalletBase<
       }
 
       if (tip > walletInfo.restoreHeight) {
-        _setListeners(walletInfo.restoreHeight, chainTipParam: _currentChainTip);
+        _setListeners(walletInfo.restoreHeight, chainTipParam: currentChainTip);
       }
     } else {
       alwaysScan = false;
@@ -265,23 +258,23 @@ abstract class ElectrumWalletBase extends WalletBase<
     }
   }
 
-  int? _currentChainTip;
+  int? currentChainTip;
 
   Future<int> getCurrentChainTip() async {
-    if ((_currentChainTip ?? 0) > 0) {
-      return _currentChainTip!;
+    if ((currentChainTip ?? 0) > 0) {
+      return currentChainTip!;
     }
-    _currentChainTip = await electrumClient.getCurrentBlockChainTip() ?? 0;
+    currentChainTip = await electrumClient.getCurrentBlockChainTip() ?? 0;
 
-    return _currentChainTip!;
+    return currentChainTip!;
   }
 
   Future<int> getUpdatedChainTip() async {
     final newTip = await electrumClient.getCurrentBlockChainTip();
-    if (newTip != null && newTip > (_currentChainTip ?? 0)) {
-      _currentChainTip = newTip;
+    if (newTip != null && newTip > (currentChainTip ?? 0)) {
+      currentChainTip = newTip;
     }
-    return _currentChainTip ?? 0;
+    return currentChainTip ?? 0;
   }
 
   @override
@@ -357,7 +350,7 @@ abstract class ElectrumWalletBase extends WalletBase<
           isSingleScan: doSingleScan ?? false,
         ));
 
-    _receiveStream?.cancel();
+    await _receiveStream?.cancel();
     _receiveStream = receivePort.listen((var message) async {
       if (message is Map<String, ElectrumTransactionInfo>) {
         for (final map in message.entries) {
@@ -618,7 +611,7 @@ abstract class ElectrumWalletBase extends WalletBase<
     bool spendsUnconfirmedTX = false;
 
     int leftAmount = credentialsAmount;
-    final availableInputs = unspentCoins.where((utx) {
+    var availableInputs = unspentCoins.where((utx) {
       if (!utx.isSending || utx.isFrozen) {
         return false;
       }
@@ -634,6 +627,9 @@ abstract class ElectrumWalletBase extends WalletBase<
     }).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);
+
     for (int i = 0; i < availableInputs.length; i++) {
       final utx = availableInputs[i];
       if (!spendsUnconfirmedTX) spendsUnconfirmedTX = utx.confirmations == 0;
@@ -652,9 +648,8 @@ abstract class ElectrumWalletBase extends WalletBase<
       ECPrivate? privkey;
       bool? isSilentPayment = false;
 
-      final hd = utx.bitcoinAddressRecord.isHidden
-          ? walletAddresses.sideHd
-          : walletAddresses.mainHd;
+      final hd =
+          utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd;
 
       if (utx.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) {
         final unspentAddress = utx.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
@@ -1233,8 +1228,7 @@ abstract class ElectrumWalletBase extends WalletBase<
     }
   }
 
-  void setLedgerConnection(ledger.LedgerConnection connection) =>
-      throw UnimplementedError();
+  void setLedgerConnection(ledger.LedgerConnection connection) => throw UnimplementedError();
 
   Future<BtcTransaction> buildHardwareWalletTransaction({
     required List<BitcoinBaseOutput> outputs,
@@ -1593,9 +1587,7 @@ abstract class ElectrumWalletBase extends WalletBase<
 
         final btcAddress = RegexUtils.addressTypeFromStr(addressRecord.address, network);
         final privkey = generateECPrivate(
-            hd: addressRecord.isHidden
-                ? walletAddresses.sideHd
-                : walletAddresses.mainHd,
+            hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
             index: addressRecord.index,
             network: network);
 
@@ -1777,8 +1769,7 @@ abstract class ElectrumWalletBase extends WalletBase<
 
     if (height != null) {
       if (time == null && height > 0) {
-        time = (getDateByBitcoinHeight(height).millisecondsSinceEpoch / 1000)
-            .round();
+        time = (getDateByBitcoinHeight(height).millisecondsSinceEpoch / 1000).round();
       }
 
       if (confirmations == null) {
@@ -1847,6 +1838,7 @@ abstract class ElectrumWalletBase extends WalletBase<
             .map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
       } else if (type == WalletType.litecoin) {
         await Future.wait(LITECOIN_ADDRESS_TYPES
+            .where((type) => type != SegwitAddresType.mweb)
             .map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
       }
 
@@ -1958,6 +1950,20 @@ abstract class ElectrumWalletBase extends WalletBase<
 
               // Got a new transaction fetched, add it to the transaction history
               // instead of waiting all to finish, and next time it will be faster
+
+              if (this is LitecoinWallet) {
+                // if we have a peg out transaction with the same value
+                // that matches this received transaction, mark it as being from a peg out:
+                for (final tx2 in transactionHistory.transactions.values) {
+                  final heightDiff = ((tx2.height ?? 0) - (tx.height ?? 0)).abs();
+                  // this isn't a perfect matching algorithm since we don't have the right input/output information from these transaction models (the addresses are in different formats), but this should be more than good enough for now as it's extremely unlikely a user receives the EXACT same amount from 2 different sources and one of them is a peg out and the other isn't WITHIN 5 blocks of each other
+                  if (tx2.additionalInfo["isPegOut"] == true &&
+                      tx2.amount == tx.amount &&
+                      heightDiff <= 5) {
+                    tx.additionalInfo["fromPegOut"] = true;
+                  }
+                }
+              }
               transactionHistory.addOne(tx);
               await transactionHistory.save();
             }
@@ -1984,18 +1990,28 @@ abstract class ElectrumWalletBase extends WalletBase<
       if (_isTransactionUpdating) {
         return;
       }
-      await getCurrentChainTip();
+      currentChainTip = await getUpdatedChainTip();
 
+      bool updated = false;
       transactionHistory.transactions.values.forEach((tx) {
-        if (tx.unspents != null &&
-            tx.unspents!.isNotEmpty &&
-            tx.height != null &&
-            tx.height! > 0 &&
-            (_currentChainTip ?? 0) > 0) {
-          tx.confirmations = _currentChainTip! - tx.height! + 1;
+        if ((tx.height ?? 0) > 0 && (currentChainTip ?? 0) > 0) {
+          var confirmations = currentChainTip! - tx.height! + 1;
+          if (confirmations < 0) {
+            // if our chain tip is outdated then it could lead to negative confirmations so this is just a failsafe:
+            confirmations = 0;
+          }
+          if (confirmations != tx.confirmations) {
+            updated = true;
+            tx.confirmations = confirmations;
+            transactionHistory.addOne(tx);
+          }
         }
       });
 
+      if (updated) {
+        await transactionHistory.save();
+      }
+
       _isTransactionUpdating = true;
       await fetchTransactions();
       walletAddresses.updateReceiveAddresses();
@@ -2043,6 +2059,8 @@ abstract class ElectrumWalletBase extends WalletBase<
             library: this.runtimeType.toString(),
           ));
         }
+      }, onError: (e, s) {
+        print("sub_listen error: $e $s");
       });
     }));
   }
@@ -2092,6 +2110,13 @@ abstract class ElectrumWalletBase extends WalletBase<
 
     final balances = await Future.wait(balanceFutures);
 
+    if (balances.isNotEmpty && balances.first['confirmed'] == null) {
+      // if we got null balance responses from the server, set our connection status to lost and return our last known balance:
+      print("got null balance responses from the server, setting connection status to lost");
+      syncStatus = LostConnectionSyncStatus();
+      return balance[currency] ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0);
+    }
+
     for (var i = 0; i < balances.length; i++) {
       final addressRecord = addresses[i];
       final balance = balances[i];
@@ -2197,10 +2222,10 @@ abstract class ElectrumWalletBase extends WalletBase<
   Future<void> _setInitialHeight() async {
     if (_chainTipUpdateSubject != null) return;
 
-    _currentChainTip = await getUpdatedChainTip();
+    currentChainTip = await getUpdatedChainTip();
 
-    if ((_currentChainTip == null || _currentChainTip! == 0) && walletInfo.restoreHeight == 0) {
-      await walletInfo.updateRestoreHeight(_currentChainTip!);
+    if ((currentChainTip == null || currentChainTip! == 0) && walletInfo.restoreHeight == 0) {
+      await walletInfo.updateRestoreHeight(currentChainTip!);
     }
 
     _chainTipUpdateSubject = electrumClient.chainTipSubscribe();
@@ -2209,7 +2234,7 @@ abstract class ElectrumWalletBase extends WalletBase<
       final height = int.tryParse(event['height'].toString());
 
       if (height != null) {
-        _currentChainTip = height;
+        currentChainTip = height;
 
         if (alwaysScan == true && syncStatus is SyncedSyncStatus) {
           _setListeners(walletInfo.restoreHeight);
@@ -2223,7 +2248,6 @@ abstract class ElectrumWalletBase extends WalletBase<
 
   @action
   void _onConnectionStatusChange(ConnectionStatus status) {
-
     switch (status) {
       case ConnectionStatus.connected:
         if (syncStatus is NotConnectedSyncStatus ||
@@ -2270,8 +2294,6 @@ abstract class ElectrumWalletBase extends WalletBase<
       Timer(Duration(seconds: 5), () {
         if (this.syncStatus is NotConnectedSyncStatus ||
             this.syncStatus is LostConnectionSyncStatus) {
-          if (node == null) return;
-
           this.electrumClient.connectToUri(
                 node!.uri,
                 useSSL: node!.useSSL ?? false,
diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart
index 1fb39c878..86228fc83 100644
--- a/cw_bitcoin/lib/litecoin_wallet.dart
+++ b/cw_bitcoin/lib/litecoin_wallet.dart
@@ -9,6 +9,7 @@ import 'package:crypto/crypto.dart';
 import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
 import 'package:cw_core/cake_hive.dart';
 import 'package:cw_core/mweb_utxo.dart';
+import 'package:cw_core/node.dart';
 import 'package:cw_mweb/mwebd.pbgrpc.dart';
 import 'package:fixnum/fixnum.dart';
 import 'package:bip39/bip39.dart' as bip39;
@@ -47,6 +48,7 @@ import 'package:cw_mweb/cw_mweb.dart';
 import 'package:bitcoin_base/src/crypto/keypair/sign_utils.dart';
 import 'package:pointycastle/ecc/api.dart';
 import 'package:pointycastle/ecc/curves/secp256k1.dart';
+import 'package:shared_preferences/shared_preferences.dart';
 
 part 'litecoin_wallet.g.dart';
 
@@ -85,8 +87,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
           alwaysScan: alwaysScan,
         ) {
     if (seedBytes != null) {
-      mwebHd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath(
-          "m/1000'") as Bip32Slip10Secp256k1;
+      mwebHd =
+          Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/1000'") as Bip32Slip10Secp256k1;
       mwebEnabled = alwaysScan ?? false;
     } else {
       mwebHd = null;
@@ -287,6 +289,16 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     await (walletAddresses as LitecoinWalletAddresses).ensureMwebAddressUpToIndexExists(1020);
   }
 
+  @action
+  @override
+  Future<void> connectToNode({required Node node}) async {
+    await super.connectToNode(node: node);
+
+    final prefs = await SharedPreferences.getInstance();
+    final mwebNodeUri = prefs.getString("mwebNodeUri") ?? "ltc-electrum.cakewallet.com:9333";
+    await CwMweb.setNodeUriOverride(mwebNodeUri);
+  }
+
   @action
   @override
   Future<void> startSync() async {
@@ -349,6 +361,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
         return;
       }
 
+      // update the current chain tip so that confirmation calculations are accurate:
+      currentChainTip = nodeHeight;
+
       final resp = await CwMweb.status(StatusRequest());
 
       try {
@@ -361,22 +376,46 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
         } else if (resp.mwebUtxosHeight < nodeHeight) {
           mwebSyncStatus = SyncingSyncStatus(1, 0.999);
         } else {
+          bool confirmationsUpdated = false;
           if (resp.mwebUtxosHeight > walletInfo.restoreHeight) {
             await walletInfo.updateRestoreHeight(resp.mwebUtxosHeight);
             await checkMwebUtxosSpent();
             // update the confirmations for each transaction:
-            for (final transaction in transactionHistory.transactions.values) {
-              if (transaction.isPending) continue;
-              int txHeight = transaction.height ?? resp.mwebUtxosHeight;
-              final confirmations = (resp.mwebUtxosHeight - txHeight) + 1;
-              if (transaction.confirmations == confirmations) continue;
-              if (transaction.confirmations == 0) {
-                updateBalance();
+            for (final tx in transactionHistory.transactions.values) {
+              if (tx.height == null || tx.height == 0) {
+                // update with first confirmation on next block since it hasn't been confirmed yet:
+                tx.height = resp.mwebUtxosHeight;
+                continue;
               }
-              transaction.confirmations = confirmations;
-              transactionHistory.addOne(transaction);
+
+              final confirmations = (resp.mwebUtxosHeight - tx.height!) + 1;
+
+              // if the confirmations haven't changed, skip updating:
+              if (tx.confirmations == confirmations) continue;
+
+
+              // if an outgoing tx is now confirmed, delete the utxo from the box (delete the unspent coin):
+              if (confirmations >= 2 &&
+                  tx.direction == TransactionDirection.outgoing &&
+                  tx.unspents != null) {
+                for (var coin in tx.unspents!) {
+                  final utxo = mwebUtxosBox.get(coin.address);
+                  if (utxo != null) {
+                    print("deleting utxo ${coin.address} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+                    await mwebUtxosBox.delete(coin.address);
+                  }
+                }
+              }
+
+              tx.confirmations = confirmations;
+              tx.isPending = false;
+              transactionHistory.addOne(tx);
+              confirmationsUpdated = true;
+            }
+            if (confirmationsUpdated) {
+              await transactionHistory.save();
+              await updateTransactions();
             }
-            await transactionHistory.save();
           }
 
           // prevent unnecessary reaction triggers:
@@ -501,13 +540,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
         outputAddresses: [utxo.outputId],
         isReplaced: false,
       );
-    }
-
-    // don't update the confirmations if the tx is updated by electrum:
-    if (tx.confirmations == 0 || utxo.height != 0) {
-      tx.height = utxo.height;
-      tx.isPending = utxo.height == 0;
-      tx.confirmations = confirmations;
+    } else {
+      if (tx.confirmations != confirmations || tx.height != utxo.height) {
+        tx.height = utxo.height;
+        tx.confirmations = confirmations;
+        tx.isPending = utxo.height == 0;
+      }
     }
 
     bool isNew = transactionHistory.transactions[tx.id] == null;
@@ -557,56 +595,88 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     if (responseStream == null) {
       throw Exception("failed to get utxos stream!");
     }
-    _utxoStream = responseStream.listen((Utxo sUtxo) async {
-      // we're processing utxos, so our balance could still be innacurate:
-      if (mwebSyncStatus is! SyncronizingSyncStatus && mwebSyncStatus is! SyncingSyncStatus) {
-        mwebSyncStatus = SyncronizingSyncStatus();
-        processingUtxos = true;
-        _processingTimer?.cancel();
-        _processingTimer = Timer.periodic(const Duration(seconds: 2), (timer) async {
-          processingUtxos = false;
-          timer.cancel();
-        });
-      }
-
-      final utxo = MwebUtxo(
-        address: sUtxo.address,
-        blockTime: sUtxo.blockTime,
-        height: sUtxo.height,
-        outputId: sUtxo.outputId,
-        value: sUtxo.value.toInt(),
-      );
-
-      if (mwebUtxosBox.containsKey(utxo.outputId)) {
-        // we've already stored this utxo, skip it:
-        // but do update the utxo height if it's somehow different:
-        final existingUtxo = mwebUtxosBox.get(utxo.outputId);
-        if (existingUtxo!.height != utxo.height) {
-          print(
-              "updating utxo height for $utxo.outputId: ${existingUtxo.height} -> ${utxo.height}");
-          existingUtxo.height = utxo.height;
-          await mwebUtxosBox.put(utxo.outputId, existingUtxo);
+    _utxoStream = responseStream.listen(
+      (Utxo sUtxo) async {
+        // we're processing utxos, so our balance could still be innacurate:
+        if (mwebSyncStatus is! SyncronizingSyncStatus && mwebSyncStatus is! SyncingSyncStatus) {
+          mwebSyncStatus = SyncronizingSyncStatus();
+          processingUtxos = true;
+          _processingTimer?.cancel();
+          _processingTimer = Timer.periodic(const Duration(seconds: 2), (timer) async {
+            processingUtxos = false;
+            timer.cancel();
+          });
         }
-        return;
-      }
 
-      await updateUnspent();
-      await updateBalance();
+        final utxo = MwebUtxo(
+          address: sUtxo.address,
+          blockTime: sUtxo.blockTime,
+          height: sUtxo.height,
+          outputId: sUtxo.outputId,
+          value: sUtxo.value.toInt(),
+        );
 
-      final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
+        if (mwebUtxosBox.containsKey(utxo.outputId)) {
+          // we've already stored this utxo, skip it:
+          // but do update the utxo height if it's somehow different:
+          final existingUtxo = mwebUtxosBox.get(utxo.outputId);
+          if (existingUtxo!.height != utxo.height) {
+            print(
+                "updating utxo height for $utxo.outputId: ${existingUtxo.height} -> ${utxo.height}");
+            existingUtxo.height = utxo.height;
+            await mwebUtxosBox.put(utxo.outputId, existingUtxo);
+          }
+          return;
+        }
 
-      // don't process utxos with addresses that are not in the mwebAddrs list:
-      if (utxo.address.isNotEmpty && !mwebAddrs.contains(utxo.address)) {
-        return;
-      }
+        await updateUnspent();
+        await updateBalance();
 
-      await mwebUtxosBox.put(utxo.outputId, utxo);
+        final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
 
-      await handleIncoming(utxo);
-    });
+        // don't process utxos with addresses that are not in the mwebAddrs list:
+        if (utxo.address.isNotEmpty && !mwebAddrs.contains(utxo.address)) {
+          return;
+        }
+
+        await mwebUtxosBox.put(utxo.outputId, utxo);
+
+        await handleIncoming(utxo);
+      },
+      onError: (error) {
+        print("error in utxo stream: $error");
+        mwebSyncStatus = FailedSyncStatus(error: error.toString());
+      },
+      cancelOnError: true,
+    );
+  }
+
+  Future<void> deleteSpentUtxos() async {
+    print("deleteSpentUtxos() called!");
+    final chainHeight = await electrumClient.getCurrentBlockChainTip();
+    final status = await CwMweb.status(StatusRequest());
+    if (chainHeight == null || status.blockHeaderHeight != chainHeight) return;
+    if (status.mwebUtxosHeight != chainHeight) return; // we aren't synced
+
+    // delete any spent utxos with >= 2 confirmations:
+    final spentOutputIds = mwebUtxosBox.values
+        .where((utxo) => utxo.spent && (chainHeight - utxo.height) >= 2)
+        .map((utxo) => utxo.outputId)
+        .toList();
+
+    if (spentOutputIds.isEmpty) return;
+
+    final resp = await CwMweb.spent(SpentRequest(outputId: spentOutputIds));
+    final spent = resp.outputId;
+    if (spent.isEmpty) return;
+
+    for (final outputId in spent) {
+      await mwebUtxosBox.delete(outputId);
+    }
   }
 
   Future<void> checkMwebUtxosSpent() async {
+    print("checkMwebUtxosSpent() called!");
     if (!mwebEnabled) {
       return;
     }
@@ -620,15 +690,17 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       updatedAny = await isConfirmed(tx) || updatedAny;
     }
 
+    await deleteSpentUtxos();
+
     // get output ids of all the mweb utxos that have > 0 height:
-    final outputIds =
-        mwebUtxosBox.values.where((utxo) => utxo.height > 0).map((utxo) => utxo.outputId).toList();
+    final outputIds = mwebUtxosBox.values
+        .where((utxo) => utxo.height > 0 && !utxo.spent)
+        .map((utxo) => utxo.outputId)
+        .toList();
 
     final resp = await CwMweb.spent(SpentRequest(outputId: outputIds));
     final spent = resp.outputId;
-    if (spent.isEmpty) {
-      return;
-    }
+    if (spent.isEmpty) return;
 
     final status = await CwMweb.status(StatusRequest());
     final height = await electrumClient.getCurrentBlockChainTip();
@@ -739,7 +811,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     mwebUtxosBox.keys.forEach((dynamic oId) {
       final String outputId = oId as String;
       final utxo = mwebUtxosBox.get(outputId);
-      if (utxo == null) {
+      if (utxo == null || utxo.spent) {
         return;
       }
       if (utxo.address.isEmpty) {
@@ -789,15 +861,23 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     int unconfirmedMweb = 0;
     try {
       mwebUtxosBox.values.forEach((utxo) {
-        if (utxo.height > 0) {
+        bool isConfirmed = utxo.height > 0;
+
+        print(
+            "utxo: ${isConfirmed ? "confirmed" : "unconfirmed"} ${utxo.spent ? "spent" : "unspent"} ${utxo.outputId} ${utxo.height} ${utxo.value}");
+
+        if (isConfirmed) {
           confirmedMweb += utxo.value.toInt();
-        } else {
+        }
+
+        if (isConfirmed && utxo.spent) {
+          unconfirmedMweb -= utxo.value.toInt();
+        }
+
+        if (!isConfirmed && !utxo.spent) {
           unconfirmedMweb += utxo.value.toInt();
         }
       });
-      if (unconfirmedMweb > 0) {
-        unconfirmedMweb = -1 * (confirmedMweb - unconfirmedMweb);
-      }
     } catch (_) {}
 
     for (var addressRecord in walletAddresses.allAddresses) {
@@ -829,7 +909,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     // update the txCount for each address using the tx history, since we can't rely on mwebd
     // to have an accurate count, we should just keep it in sync with what we know from the tx history:
     for (final tx in transactionHistory.transactions.values) {
-      // if (tx.isPending) continue;
       if (tx.inputAddresses == null || tx.outputAddresses == null) {
         continue;
       }
@@ -908,7 +987,26 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     // https://github.com/ltcmweb/mwebd?tab=readme-ov-file#fee-estimation
     final preOutputSum =
         outputs.fold<BigInt>(BigInt.zero, (acc, output) => acc + output.toOutput.amount);
-    final fee = utxos.sumOfUtxosValue() - preOutputSum;
+    var fee = utxos.sumOfUtxosValue() - preOutputSum;
+
+    // determines if the fee is correct:
+    BigInt _sumOutputAmounts(List<TxOutput> outputs) {
+      BigInt sum = BigInt.zero;
+      for (final e in outputs) {
+        sum += e.amount;
+      }
+      return sum;
+    }
+
+    final sum1 = _sumOutputAmounts(outputs.map((e) => e.toOutput).toList()) + fee;
+    final sum2 = utxos.sumOfUtxosValue();
+    if (sum1 != sum2) {
+      print("@@@@@ WE HAD TO ADJUST THE FEE! @@@@@@@@");
+      final diff = sum2 - sum1;
+      // add the difference to the fee (abs value):
+      fee += diff.abs();
+    }
+
     final txb =
         BitcoinTransactionBuilder(utxos: utxos, outputs: outputs, fee: fee, network: network);
     final resp = await CwMweb.create(CreateRequest(
@@ -949,8 +1047,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
 
       if (!mwebEnabled) {
         tx.changeAddressOverride =
-            (await (walletAddresses as LitecoinWalletAddresses)
-                    .getChangeAddress(isPegIn: false))
+            (await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(isPegIn: false))
                 .address;
         return tx;
       }
@@ -969,15 +1066,25 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
 
       bool hasMwebInput = false;
       bool hasMwebOutput = false;
+      bool hasRegularOutput = false;
 
       for (final output in transactionCredentials.outputs) {
-        if (output.extractedAddress?.toLowerCase().contains("mweb") ?? false) {
+        final address = output.address.toLowerCase();
+        final extractedAddress = output.extractedAddress?.toLowerCase();
+
+        if (address.contains("mweb")) {
           hasMwebOutput = true;
-          break;
         }
-        if (output.address.toLowerCase().contains("mweb")) {
-          hasMwebOutput = true;
-          break;
+        if (!address.contains("mweb")) {
+          hasRegularOutput = true;
+        }
+        if (extractedAddress != null && extractedAddress.isNotEmpty) {
+          if (extractedAddress.contains("mweb")) {
+            hasMwebOutput = true;
+          }
+          if (!extractedAddress.contains("mweb")) {
+            hasRegularOutput = true;
+          }
         }
       }
 
@@ -989,11 +1096,11 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       }
 
       bool isPegIn = !hasMwebInput && hasMwebOutput;
+      bool isPegOut = hasMwebInput && hasRegularOutput;
       bool isRegular = !hasMwebInput && !hasMwebOutput;
-      tx.changeAddressOverride =
-          (await (walletAddresses as LitecoinWalletAddresses)
-                  .getChangeAddress(isPegIn: isPegIn || isRegular))
-              .address;
+      tx.changeAddressOverride = (await (walletAddresses as LitecoinWalletAddresses)
+              .getChangeAddress(isPegIn: isPegIn || isRegular))
+          .address;
       if (!hasMwebInput && !hasMwebOutput) {
         tx.isMweb = false;
         return tx;
@@ -1046,8 +1153,11 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
           final addresses = <String>{};
           transaction.inputAddresses?.forEach((id) async {
             final utxo = mwebUtxosBox.get(id);
-            await mwebUtxosBox.delete(id); // gets deleted in checkMwebUtxosSpent
+            // await mwebUtxosBox.delete(id); // gets deleted in checkMwebUtxosSpent
             if (utxo == null) return;
+            // mark utxo as spent so we add it to the unconfirmed balance (as negative):
+            utxo.spent = true;
+            await mwebUtxosBox.put(id, utxo);
             final addressRecord = walletAddresses.allAddresses
                 .firstWhere((addressRecord) => addressRecord.address == utxo.address);
             if (!addresses.contains(utxo.address)) {
@@ -1056,7 +1166,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
             addressRecord.balance -= utxo.value.toInt();
           });
           transaction.inputAddresses?.addAll(addresses);
-
+          print("isPegIn: $isPegIn, isPegOut: $isPegOut");
+          transaction.additionalInfo["isPegIn"] = isPegIn;
+          transaction.additionalInfo["isPegOut"] = isPegOut;
           transactionHistory.addOne(transaction);
           await updateUnspent();
           await updateBalance();
@@ -1240,8 +1352,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
   @override
   void setLedgerConnection(LedgerConnection connection) {
     _ledgerConnection = connection;
-    _litecoinLedgerApp =
-        LitecoinLedgerApp(_ledgerConnection!, derivationPath: walletInfo.derivationInfo!.derivationPath!);
+    _litecoinLedgerApp = LitecoinLedgerApp(_ledgerConnection!,
+        derivationPath: walletInfo.derivationInfo!.derivationPath!);
   }
 
   @override
@@ -1277,19 +1389,17 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       if (maybeChangePath != null) changePath ??= maybeChangePath.derivationPath;
     }
 
-
     final rawHex = await _litecoinLedgerApp!.createTransaction(
-      inputs: readyInputs,
-      outputs: outputs
-          .map((e) => TransactionOutput.fromBigInt(
-              (e as BitcoinOutput).value, Uint8List.fromList(e.address.toScriptPubKey().toBytes())))
-          .toList(),
-      changePath: changePath,
-      sigHashType: 0x01,
-      additionals: ["bech32"],
-      isSegWit: true,
-      useTrustedInputForSegwit: true
-    );
+        inputs: readyInputs,
+        outputs: outputs
+            .map((e) => TransactionOutput.fromBigInt((e as BitcoinOutput).value,
+                Uint8List.fromList(e.address.toScriptPubKey().toBytes())))
+            .toList(),
+        changePath: changePath,
+        sigHashType: 0x01,
+        additionals: ["bech32"],
+        isSegWit: true,
+        useTrustedInputForSegwit: true);
 
     return BtcTransaction.fromRaw(rawHex);
   }
diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
index c55f5fc76..062c590ba 100644
--- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
@@ -16,11 +16,9 @@ import 'package:mobx/mobx.dart';
 
 part 'litecoin_wallet_addresses.g.dart';
 
-class LitecoinWalletAddresses = LitecoinWalletAddressesBase
-    with _$LitecoinWalletAddresses;
+class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses;
 
-abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
-    with Store {
+abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
   LitecoinWalletAddressesBase(
     WalletInfo walletInfo, {
     required super.mainHd,
@@ -46,8 +44,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
   List<String> mwebAddrs = [];
   bool generating = false;
 
-  List<int> get scanSecret =>
-      mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
+  List<int> get scanSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
   List<int> get spendPubkey =>
       mwebHd!.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
 
@@ -203,4 +200,12 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
 
     return super.getChangeAddress();
   }
+
+  @override
+  String get addressForExchange {
+    // don't use mweb addresses for exchange refund address:
+    final addresses = receiveAddresses
+        .where((element) => element.type == SegwitAddresType.p2wpkh && !element.isUsed);
+    return addresses.first.address;
+  }
 }
diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart
index 7cc266f5b..d519f4d0a 100644
--- a/cw_bitcoin/lib/litecoin_wallet_service.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_service.dart
@@ -112,6 +112,7 @@ class LitecoinWalletService extends WalletService<
       File neturinoDb = File('$appDirPath/neutrino.db');
       File blockHeaders = File('$appDirPath/block_headers.bin');
       File regFilterHeaders = File('$appDirPath/reg_filter_headers.bin');
+      File mwebdLogs = File('$appDirPath/logs/debug.log');
       if (neturinoDb.existsSync()) {
         neturinoDb.deleteSync();
       }
@@ -121,6 +122,9 @@ class LitecoinWalletService extends WalletService<
       if (regFilterHeaders.existsSync()) {
         regFilterHeaders.deleteSync();
       }
+      if (mwebdLogs.existsSync()) {
+        mwebdLogs.deleteSync();
+      }
     }
   }
 
diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
index 5ed84dbf4..140965655 100644
--- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart
+++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
@@ -118,8 +118,7 @@ class PendingBitcoinTransaction with PendingTransaction {
 
   Future<void> _ltcCommit() async {
     try {
-      final stub = await CwMweb.stub();
-      final resp = await stub.broadcast(BroadcastRequest(rawTx: BytesUtils.fromHexString(hex)));
+      final resp = await CwMweb.broadcast(BroadcastRequest(rawTx: BytesUtils.fromHexString(hex)));
       idOverride = resp.txid;
     } on GrpcError catch (e) {
       throw BitcoinTransactionCommitFailed(errorMessage: e.message);
diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml
index 9f1cee67d..7a1576a98 100644
--- a/cw_bitcoin/pubspec.yaml
+++ b/cw_bitcoin/pubspec.yaml
@@ -64,7 +64,7 @@ dependency_overrides:
   bitcoin_base:
     git:
       url: https://github.com/cake-tech/bitcoin_base
-      ref: cake-update-v8
+      ref: cake-update-v9
   pointycastle: 3.7.4
   ffi: 2.1.0
 
diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml
index cd1e52f51..14ff407e2 100644
--- a/cw_bitcoin_cash/pubspec.yaml
+++ b/cw_bitcoin_cash/pubspec.yaml
@@ -42,7 +42,7 @@ dependency_overrides:
   bitcoin_base:
     git:
       url: https://github.com/cake-tech/bitcoin_base
-      ref: cake-update-v8
+      ref: cake-update-v9
 
 # For information on the generic Dart part of this file, see the
 # following page: https://dart.dev/tools/pub/pubspec
diff --git a/cw_core/lib/mweb_utxo.dart b/cw_core/lib/mweb_utxo.dart
index f8dfab395..5eab11734 100644
--- a/cw_core/lib/mweb_utxo.dart
+++ b/cw_core/lib/mweb_utxo.dart
@@ -11,6 +11,7 @@ class MwebUtxo extends HiveObject {
     required this.address,
     required this.outputId,
     required this.blockTime,
+    this.spent = false,
   });
 
   static const typeId = MWEB_UTXO_TYPE_ID;
@@ -30,4 +31,7 @@ class MwebUtxo extends HiveObject {
 
   @HiveField(4)
   int blockTime;
+
+  @HiveField(5, defaultValue: false)
+  bool spent;
 }
diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart
index e19d2a54b..1094b6402 100644
--- a/cw_core/lib/node.dart
+++ b/cw_core/lib/node.dart
@@ -79,6 +79,9 @@ class Node extends HiveObject with Keyable {
   @HiveField(9)
   bool? supportsSilentPayments;
 
+  @HiveField(10)
+  bool? supportsMweb;
+
   bool get isSSL => useSSL ?? false;
 
   bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
diff --git a/cw_core/lib/transaction_info.dart b/cw_core/lib/transaction_info.dart
index 9d0c968d8..3e34af75f 100644
--- a/cw_core/lib/transaction_info.dart
+++ b/cw_core/lib/transaction_info.dart
@@ -25,6 +25,5 @@ abstract class TransactionInfo extends Object with Keyable {
   @override
   dynamic get keyIndex => id;
 
-  late Map<String, dynamic> additionalInfo;
+  Map<String, dynamic> additionalInfo = {};
 }
-
diff --git a/cw_mweb/lib/cw_mweb.dart b/cw_mweb/lib/cw_mweb.dart
index a1a592fb8..75cc0bcca 100644
--- a/cw_mweb/lib/cw_mweb.dart
+++ b/cw_mweb/lib/cw_mweb.dart
@@ -13,8 +13,18 @@ class CwMweb {
   static RpcClient? _rpcClient;
   static ClientChannel? _clientChannel;
   static int? _port;
-  static const TIMEOUT_DURATION = Duration(seconds: 5);
+  static const TIMEOUT_DURATION = Duration(seconds: 15);
   static Timer? logTimer;
+  static String? nodeUriOverride;
+
+
+  static Future<void> setNodeUriOverride(String uri) async {
+    nodeUriOverride = uri;
+    if (_rpcClient != null) {
+      await stop();
+      // will be re-started automatically when the next rpc call is made
+    }
+  }
 
   static void readFileWithTimer(String filePath) {
     final file = File(filePath);
@@ -47,7 +57,7 @@ class CwMweb {
     String debugLogPath = "${appDir.path}/logs/debug.log";
     readFileWithTimer(debugLogPath);
 
-    _port = await CwMwebPlatform.instance.start(appDir.path, ltcNodeUri);
+    _port = await CwMwebPlatform.instance.start(appDir.path, nodeUriOverride ?? ltcNodeUri);
     if (_port == null || _port == 0) {
       throw Exception("Failed to start server");
     }
@@ -197,4 +207,18 @@ class CwMweb {
     }
     return null;
   }
+
+  static Future<BroadcastResponse> broadcast(BroadcastRequest request) async {
+    log("mweb.broadcast() called");
+    try {
+      _rpcClient = await stub();
+      return await _rpcClient!.broadcast(request, options: CallOptions(timeout: TIMEOUT_DURATION));
+    } on GrpcError catch (e) {
+      log('Caught grpc error: ${e.message}');
+      throw "error from broadcast mweb: $e";
+    } catch (e) {
+      log("Error getting create: $e");
+      rethrow;
+    }
+  }
 }
diff --git a/lib/di.dart b/lib/di.dart
index 13ffd839e..14fdbd56d 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -35,6 +35,8 @@ import 'package:cake_wallet/entities/parse_address_from_domain.dart';
 import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
 import 'package:cake_wallet/entities/wallet_manager.dart';
 import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
+import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart';
+import 'package:cake_wallet/src/screens/settings/mweb_node_page.dart';
 import 'package:cake_wallet/view_model/link_view_model.dart';
 import 'package:cake_wallet/tron/tron.dart';
 import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
@@ -945,6 +947,10 @@ Future<void> setup({
 
   getIt.registerFactory(() => MwebSettingsPage(getIt.get<MwebSettingsViewModel>()));
 
+  getIt.registerFactory(() => MwebLogsPage(getIt.get<MwebSettingsViewModel>()));
+
+  getIt.registerFactory(() => MwebNodePage(getIt.get<MwebSettingsViewModel>()));
+
   getIt.registerFactory(() => OtherSettingsPage(getIt.get<OtherSettingsViewModel>()));
 
   getIt.registerFactory(() => NanoChangeRepPage(
diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart
index 73556452c..8e8bfb6ed 100644
--- a/lib/entities/preferences_key.dart
+++ b/lib/entities/preferences_key.dart
@@ -54,6 +54,7 @@ class PreferencesKey {
   static const mwebEnabled = 'mwebEnabled';
   static const hasEnabledMwebBefore = 'hasEnabledMwebBefore';
   static const mwebAlwaysScan = 'mwebAlwaysScan';
+  static const mwebNodeUri = 'mwebNodeUri';
   static const shouldShowReceiveWarning = 'should_show_receive_warning';
   static const shouldShowYatPopup = 'should_show_yat_popup';
   static const shouldShowRepWarning = 'should_show_rep_warning';
diff --git a/lib/router.dart b/lib/router.dart
index 3b4c38546..6c234ff80 100644
--- a/lib/router.dart
+++ b/lib/router.dart
@@ -72,6 +72,8 @@ import 'package:cake_wallet/src/screens/settings/desktop_settings/desktop_settin
 import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
 import 'package:cake_wallet/src/screens/settings/domain_lookups_page.dart';
 import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
+import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart';
+import 'package:cake_wallet/src/screens/settings/mweb_node_page.dart';
 import 'package:cake_wallet/src/screens/settings/mweb_settings.dart';
 import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
 import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
@@ -461,6 +463,14 @@ Route<dynamic> createRoute(RouteSettings settings) {
       return CupertinoPageRoute<void>(
           fullscreenDialog: true, builder: (_) => getIt.get<MwebSettingsPage>());
 
+    case Routes.mwebLogs:
+      return CupertinoPageRoute<void>(
+          fullscreenDialog: true, builder: (_) => getIt.get<MwebLogsPage>());
+
+    case Routes.mwebNode:
+      return CupertinoPageRoute<void>(
+          fullscreenDialog: true, builder: (_) => getIt.get<MwebNodePage>());
+
     case Routes.connectionSync:
       return CupertinoPageRoute<void>(
           fullscreenDialog: true, builder: (_) => getIt.get<ConnectionSyncPage>());
diff --git a/lib/routes.dart b/lib/routes.dart
index 0529d7c6f..5f11b11a3 100644
--- a/lib/routes.dart
+++ b/lib/routes.dart
@@ -74,6 +74,8 @@ class Routes {
   static const webViewPage = '/web_view_page';
   static const silentPaymentsSettings = '/silent_payments_settings';
   static const mwebSettings = '/mweb_settings';
+  static const mwebLogs = '/mweb_logs';
+  static const mwebNode = '/mweb_node';
   static const connectionSync = '/connection_sync_page';
   static const securityBackupPage = '/security_and_backup_page';
   static const privacyPage = '/privacy_page';
diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart
index 028b3cfcf..b16a7b090 100644
--- a/lib/src/screens/dashboard/pages/balance_page.dart
+++ b/lib/src/screens/dashboard/pages/balance_page.dart
@@ -886,17 +886,37 @@ class BalanceRowWidget extends StatelessWidget {
                             Column(
                               crossAxisAlignment: CrossAxisAlignment.start,
                               children: [
-                                Text(
-                                  '${secondAvailableBalanceLabel}',
-                                  textAlign: TextAlign.center,
-                                  style: TextStyle(
-                                    fontSize: 12,
-                                    fontFamily: 'Lato',
-                                    fontWeight: FontWeight.w400,
-                                    color: Theme.of(context)
-                                        .extension<BalancePageTheme>()!
-                                        .labelTextColor,
-                                    height: 1,
+                                GestureDetector(
+                                  behavior: HitTestBehavior.opaque,
+                                  onTap: () => launchUrl(
+                                    Uri.parse(
+                                        "https://guides.cakewallet.com/docs/cryptos/litecoin/#mweb"),
+                                    mode: LaunchMode.externalApplication,
+                                  ),
+                                  child: Row(
+                                    children: [
+                                      Text(
+                                        '${secondAvailableBalanceLabel}',
+                                        textAlign: TextAlign.center,
+                                        style: TextStyle(
+                                          fontSize: 12,
+                                          fontFamily: 'Lato',
+                                          fontWeight: FontWeight.w400,
+                                          color: Theme.of(context)
+                                              .extension<BalancePageTheme>()!
+                                              .labelTextColor,
+                                          height: 1,
+                                        ),
+                                      ),
+                                      Padding(
+                                        padding: const EdgeInsets.symmetric(horizontal: 4),
+                                        child: Icon(Icons.help_outline,
+                                            size: 16,
+                                            color: Theme.of(context)
+                                                .extension<BalancePageTheme>()!
+                                                .labelTextColor),
+                                      )
+                                    ],
                                   ),
                                 ),
                                 SizedBox(height: 8),
diff --git a/lib/src/screens/settings/mweb_logs_page.dart b/lib/src/screens/settings/mweb_logs_page.dart
new file mode 100644
index 000000000..3c5470214
--- /dev/null
+++ b/lib/src/screens/settings/mweb_logs_page.dart
@@ -0,0 +1,127 @@
+import 'dart:io';
+import 'package:cake_wallet/src/screens/base_page.dart';
+import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
+import 'package:cake_wallet/src/widgets/primary_button.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/utils/exception_handler.dart';
+import 'package:cake_wallet/utils/share_util.dart';
+import 'package:cake_wallet/utils/show_pop_up.dart';
+import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart';
+import 'package:cw_core/root_dir.dart';
+import 'package:file_picker/file_picker.dart';
+import 'package:flutter/material.dart';
+import 'package:path_provider/path_provider.dart';
+
+class MwebLogsPage extends BasePage {
+  MwebLogsPage(this.mwebSettingsViewModelBase);
+
+  final MwebSettingsViewModelBase mwebSettingsViewModelBase;
+
+  @override
+  String get title => S.current.litecoin_mweb_logs;
+
+  @override
+  Widget body(BuildContext context) {
+    return Stack(
+      fit: StackFit.expand,
+      children: [
+        FutureBuilder<String>(
+          future: mwebSettingsViewModelBase.getAbbreviatedLogs(),
+          builder: (context, snapshot) {
+            if (snapshot.connectionState == ConnectionState.waiting) {
+              return Center(child: CircularProgressIndicator());
+            } else if (snapshot.hasError || !snapshot.hasData || snapshot.data!.isEmpty) {
+              return Center(child: Text('No logs found'));
+            } else {
+              return SingleChildScrollView(
+                child: Padding(
+                  padding: EdgeInsets.all(16.0),
+                  child: Text(
+                    snapshot.data!,
+                    style: TextStyle(fontFamily: 'Monospace'),
+                  ),
+                ),
+              );
+            }
+          },
+        ),
+        Positioned(
+          child: LoadingPrimaryButton(
+            onPressed: () => onExportLogs(context),
+            text: S.of(context).export_logs,
+            color: Theme.of(context).primaryColor,
+            textColor: Colors.white,
+          ),
+          bottom: 24,
+          left: 24,
+          right: 24,
+        )
+      ],
+    );
+  }
+
+  void onExportLogs(BuildContext context) {
+    if (Platform.isAndroid) {
+      onExportAndroid(context);
+    } else if (Platform.isIOS) {
+      share(context);
+    } else {
+      _saveFile();
+    }
+  }
+
+  void onExportAndroid(BuildContext context) {
+    showPopUp<void>(
+        context: context,
+        builder: (dialogContext) {
+          return AlertWithTwoActions(
+              alertTitle: S.of(context).export_backup,
+              alertContent: S.of(context).select_destination,
+              rightButtonText: S.of(context).save_to_downloads,
+              leftButtonText: S.of(context).share,
+              actionRightButton: () async {
+                const downloadDirPath = "/storage/emulated/0/Download";
+                final filePath = downloadDirPath + "/debug.log";
+                await mwebSettingsViewModelBase.saveLogsLocally(filePath);
+                Navigator.of(dialogContext).pop();
+              },
+              actionLeftButton: () async {
+                Navigator.of(dialogContext).pop();
+                try {
+                  await share(context);
+                } catch (e, s) {
+                  ExceptionHandler.onError(FlutterErrorDetails(
+                    exception: e,
+                    stack: s,
+                    library: "Export Logs",
+                  ));
+                }
+              });
+        });
+  }
+
+  Future<void> share(BuildContext context) async {
+    final filePath = (await getAppDir()).path + "/debug.log";
+    bool success = await mwebSettingsViewModelBase.saveLogsLocally(filePath);
+    if (!success) return;
+    await ShareUtil.shareFile(filePath: filePath, fileName: "debug.log", context: context);
+    await mwebSettingsViewModelBase.removeLogsLocally(filePath);
+  }
+
+  Future<void> _saveFile() async {
+    String? outputFile = await FilePicker.platform
+        .saveFile(dialogTitle: 'Save Your File to desired location', fileName: "debug.log");
+
+    try {
+      final filePath = (await getApplicationSupportDirectory()).path + "/debug.log";
+      File debugLogFile = File(filePath);
+      await debugLogFile.copy(outputFile!);
+    } catch (exception, stackTrace) {
+      ExceptionHandler.onError(FlutterErrorDetails(
+        exception: exception,
+        stack: stackTrace,
+        library: "Export Logs",
+      ));
+    }
+  }
+}
diff --git a/lib/src/screens/settings/mweb_node_page.dart b/lib/src/screens/settings/mweb_node_page.dart
new file mode 100644
index 000000000..801ab3ac7
--- /dev/null
+++ b/lib/src/screens/settings/mweb_node_page.dart
@@ -0,0 +1,56 @@
+import 'package:cake_wallet/src/screens/base_page.dart';
+import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
+import 'package:cake_wallet/src/widgets/primary_button.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+
+class MwebNodePage extends BasePage {
+  MwebNodePage(this.mwebSettingsViewModelBase)
+      : _nodeUriController = TextEditingController(text: mwebSettingsViewModelBase.mwebNodeUri),
+        super();
+
+  final MwebSettingsViewModelBase mwebSettingsViewModelBase;
+  final TextEditingController _nodeUriController;
+
+  @override
+  String get title => S.current.litecoin_mweb_node;
+
+  @override
+  Widget body(BuildContext context) {
+    return Stack(
+      fit: StackFit.expand,
+      children: [
+        Container(
+          padding: EdgeInsets.symmetric(horizontal: 24),
+          child: Row(
+            children: <Widget>[
+              Expanded(
+                child: BaseTextFormField(controller: _nodeUriController),
+              )
+            ],
+          ),
+        ),
+        Positioned(
+          child: Observer(
+            builder: (_) => LoadingPrimaryButton(
+              onPressed: () => save(context),
+              text: S.of(context).save,
+              color: Theme.of(context).primaryColor,
+              textColor: Colors.white,
+            ),
+          ),
+          bottom: 24,
+          left: 24,
+          right: 24,
+        )
+      ],
+    );
+  }
+
+  void save(BuildContext context) {
+    mwebSettingsViewModelBase.setMwebNodeUri(_nodeUriController.text);
+    Navigator.pop(context);
+  }
+}
diff --git a/lib/src/screens/settings/mweb_settings.dart b/lib/src/screens/settings/mweb_settings.dart
index 722ffa9aa..e78fdf596 100644
--- a/lib/src/screens/settings/mweb_settings.dart
+++ b/lib/src/screens/settings/mweb_settings.dart
@@ -31,7 +31,7 @@ class MwebSettingsPage extends BasePage {
                 },
               ),
               SettingsSwitcherCell(
-                title: S.current.litecoin_mweb_always_scan,
+                title: S.current.litecoin_mweb_enable,
                 value: _mwebSettingsViewModel.mwebEnabled,
                 onValueChange: (_, bool value) {
                   _mwebSettingsViewModel.setMwebEnabled(value);
@@ -41,6 +41,14 @@ class MwebSettingsPage extends BasePage {
                 title: S.current.litecoin_mweb_scanning,
                 handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.rescan),
               ),
+            SettingsCellWithArrow(
+                title: S.current.litecoin_mweb_logs,
+                handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.mwebLogs),
+              ),
+              SettingsCellWithArrow(
+                title: S.current.litecoin_mweb_node,
+                handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.mwebNode),
+              ),
             ],
           ),
         );
diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart
index 2eadbd8a9..c966420db 100644
--- a/lib/store/settings_store.dart
+++ b/lib/store/settings_store.dart
@@ -120,6 +120,7 @@ abstract class SettingsStoreBase with Store {
       required this.mwebCardDisplay,
       required this.mwebEnabled,
       required this.hasEnabledMwebBefore,
+      required this.mwebNodeUri,
       TransactionPriority? initialBitcoinTransactionPriority,
       TransactionPriority? initialMoneroTransactionPriority,
       TransactionPriority? initialWowneroTransactionPriority,
@@ -358,8 +359,8 @@ abstract class SettingsStoreBase with Store {
 
     reaction(
         (_) => bitcoinSeedType,
-        (BitcoinSeedType bitcoinSeedType) => sharedPreferences.setInt(
-            PreferencesKey.bitcoinSeedType, bitcoinSeedType.raw));
+        (BitcoinSeedType bitcoinSeedType) =>
+            sharedPreferences.setInt(PreferencesKey.bitcoinSeedType, bitcoinSeedType.raw));
 
     reaction(
         (_) => nanoSeedType,
@@ -442,8 +443,10 @@ abstract class SettingsStoreBase with Store {
     reaction((_) => useTronGrid,
         (bool useTronGrid) => _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid));
 
-    reaction((_) => useMempoolFeeAPI,
-        (bool useMempoolFeeAPI) => _sharedPreferences.setBool(PreferencesKey.useMempoolFeeAPI, useMempoolFeeAPI));
+    reaction(
+        (_) => useMempoolFeeAPI,
+        (bool useMempoolFeeAPI) =>
+            _sharedPreferences.setBool(PreferencesKey.useMempoolFeeAPI, useMempoolFeeAPI));
 
     reaction((_) => defaultNanoRep,
         (String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep));
@@ -591,6 +594,11 @@ abstract class SettingsStoreBase with Store {
         (bool hasEnabledMwebBefore) =>
             _sharedPreferences.setBool(PreferencesKey.hasEnabledMwebBefore, hasEnabledMwebBefore));
 
+    reaction(
+        (_) => mwebNodeUri,
+        (String mwebNodeUri) =>
+            _sharedPreferences.setString(PreferencesKey.mwebNodeUri, mwebNodeUri));
+
     this.nodes.observe((change) {
       if (change.newValue != null && change.key != null) {
         _saveCurrentNode(change.newValue!, change.key!);
@@ -822,6 +830,9 @@ abstract class SettingsStoreBase with Store {
   @observable
   bool hasEnabledMwebBefore;
 
+  @observable
+  String mwebNodeUri;
+
   final SecureStorage _secureStorage;
   final SharedPreferences _sharedPreferences;
   final BackgroundTasks _backgroundTasks;
@@ -988,6 +999,8 @@ abstract class SettingsStoreBase with Store {
     final mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
     final hasEnabledMwebBefore =
         sharedPreferences.getBool(PreferencesKey.hasEnabledMwebBefore) ?? false;
+    final mwebNodeUri = sharedPreferences.getString(PreferencesKey.mwebNodeUri) ??
+        "ltc-electrum.cakewallet.com:9333";
 
     // If no value
     if (pinLength == null || pinLength == 0) {
@@ -1259,6 +1272,7 @@ abstract class SettingsStoreBase with Store {
       mwebAlwaysScan: mwebAlwaysScan,
       mwebCardDisplay: mwebCardDisplay,
       mwebEnabled: mwebEnabled,
+      mwebNodeUri: mwebNodeUri,
       hasEnabledMwebBefore: hasEnabledMwebBefore,
       initialMoneroTransactionPriority: moneroTransactionPriority,
       initialWowneroTransactionPriority: wowneroTransactionPriority,
@@ -1686,7 +1700,8 @@ abstract class SettingsStoreBase with Store {
         deviceName = windowsInfo.productName;
       } catch (e) {
         print(e);
-        print('likely digitalProductId is null wait till https://github.com/fluttercommunity/plus_plugins/pull/3188 is merged');
+        print(
+            'likely digitalProductId is null wait till https://github.com/fluttercommunity/plus_plugins/pull/3188 is merged');
         deviceName = "Windows Device";
       }
     }
diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart
index 56a5935c9..20dca292c 100644
--- a/lib/view_model/dashboard/balance_view_model.dart
+++ b/lib/view_model/dashboard/balance_view_model.dart
@@ -381,7 +381,7 @@ abstract class BalanceViewModelBase with Store {
 
   bool _hasSecondAdditionalBalanceForWalletType(WalletType type) {
     if (wallet.type == WalletType.litecoin) {
-      if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) > 0) {
+      if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) != 0) {
         return true;
       }
     }
diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart
index 47fc32ab6..b218c8e9f 100644
--- a/lib/view_model/dashboard/transaction_list_item.dart
+++ b/lib/view_model/dashboard/transaction_list_item.dart
@@ -56,25 +56,53 @@ class TransactionListItem extends ActionListItem with Keyable {
   }
 
   String get formattedPendingStatus {
-    if (balanceViewModel.wallet.type == WalletType.monero ||
-        balanceViewModel.wallet.type == WalletType.haven) {
-      if (transaction.confirmations >= 0 && transaction.confirmations < 10) {
-        return ' (${transaction.confirmations}/10)';
-      }
-    } else if (balanceViewModel.wallet.type == WalletType.wownero) {
-      if (transaction.confirmations >= 0 && transaction.confirmations < 3) {
-        return ' (${transaction.confirmations}/3)';
-      }
+    switch (balanceViewModel.wallet.type) {
+      case WalletType.monero:
+      case WalletType.haven:
+        if (transaction.confirmations >= 0 && transaction.confirmations < 10) {
+          return ' (${transaction.confirmations}/10)';
+        }
+        break;
+      case WalletType.wownero:
+        if (transaction.confirmations >= 0 && transaction.confirmations < 3) {
+          return ' (${transaction.confirmations}/3)';
+        }
+        break;
+      case WalletType.litecoin:
+        bool isPegIn = (transaction.additionalInfo["isPegIn"] as bool?) ?? false;
+        bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false;
+        bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false;
+        String str = '';
+        if (transaction.confirmations <= 0) {
+          str = S.current.pending;
+        }
+        if ((isPegOut || fromPegOut) && transaction.confirmations >= 0 && transaction.confirmations < 6) {
+          str = " (${transaction.confirmations}/6)";
+        }
+        if (isPegIn) {
+          str += " (Peg In)";
+        }
+        if (isPegOut) {
+          str += " (Peg Out)";
+        }
+        return str;
+      default:
+        return '';
     }
+
     return '';
   }
 
   String get formattedStatus {
-    if (balanceViewModel.wallet.type == WalletType.monero ||
-        balanceViewModel.wallet.type == WalletType.wownero ||
-        balanceViewModel.wallet.type == WalletType.haven) {
+    if ([
+      WalletType.monero,
+      WalletType.haven,
+      WalletType.wownero,
+      WalletType.litecoin,
+    ].contains(balanceViewModel.wallet.type)) {
       return formattedPendingStatus;
     }
+
     return transaction.isPending ? S.current.pending : '';
   }
 
diff --git a/lib/view_model/settings/mweb_settings_view_model.dart b/lib/view_model/settings/mweb_settings_view_model.dart
index c6370e23f..11e4c8177 100644
--- a/lib/view_model/settings/mweb_settings_view_model.dart
+++ b/lib/view_model/settings/mweb_settings_view_model.dart
@@ -1,7 +1,12 @@
+import 'dart:io';
+
 import 'package:cake_wallet/bitcoin/bitcoin.dart';
 import 'package:cake_wallet/store/settings_store.dart';
+import 'package:cake_wallet/utils/exception_handler.dart';
 import 'package:cw_core/wallet_base.dart';
+import 'package:flutter/widgets.dart';
 import 'package:mobx/mobx.dart';
+import 'package:path_provider/path_provider.dart';
 
 part 'mweb_settings_view_model.g.dart';
 
@@ -22,15 +27,60 @@ abstract class MwebSettingsViewModelBase with Store {
   @observable
   late bool mwebEnabled;
 
+  @computed
+  String get mwebNodeUri => _settingsStore.mwebNodeUri;
+
   @action
   void setMwebCardDisplay(bool value) {
     _settingsStore.mwebCardDisplay = value;
   }
 
+  @action
+  void setMwebNodeUri(String value) {
+    _settingsStore.mwebNodeUri = value;
+  }
+
   @action
   void setMwebEnabled(bool value) {
     mwebEnabled = value;
     bitcoin!.setMwebEnabled(_wallet, value);
     _settingsStore.mwebAlwaysScan = value;
   }
+
+  Future<bool> saveLogsLocally(String filePath) async {
+    try {
+      final appSupportPath = (await getApplicationSupportDirectory()).path;
+      final logsFile = File("$appSupportPath/logs/debug.log");
+      if (!logsFile.existsSync()) {
+        throw Exception('Logs file does not exist');
+      }
+      await logsFile.copy(filePath);
+      return true;
+    } catch (e, s) {
+      ExceptionHandler.onError(FlutterErrorDetails(
+        exception: e,
+        stack: s,
+        library: "Export Logs",
+      ));
+      return false;
+    }
+  }
+
+  Future<String> getAbbreviatedLogs() async {
+    final appSupportPath = (await getApplicationSupportDirectory()).path;
+    final logsFile = File("$appSupportPath/logs/debug.log");
+    if (!logsFile.existsSync()) {
+      return "";
+    }
+    final logs = logsFile.readAsStringSync();
+    // return last 10000 characters:
+    return logs.substring(logs.length > 10000 ? logs.length - 10000 : 0);
+  }
+
+  Future<void> removeLogsLocally(String filePath) async {
+    final logsFile = File(filePath);
+    if (logsFile.existsSync()) {
+      await logsFile.delete();
+    }
+  }
 }
diff --git a/pubspec_base.yaml b/pubspec_base.yaml
index d5fce76e9..2abd8401a 100644
--- a/pubspec_base.yaml
+++ b/pubspec_base.yaml
@@ -134,7 +134,7 @@ dependency_overrides:
   bitcoin_base:
     git:
       url: https://github.com/cake-tech/bitcoin_base
-      ref: cake-update-v8
+      ref: cake-update-v9
   ffi: 2.1.0
 
 flutter_icons:
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index c2be1504a..0db2031dd 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -295,6 +295,7 @@
   "expiresOn": "ﻲﻓ ﻪﺘﻴﺣﻼﺻ ﻲﻬﺘﻨﺗ",
   "expiry_and_validity": "انتهاء الصلاحية والصلاحية",
   "export_backup": "تصدير نسخة احتياطية",
+  "export_logs": "سجلات التصدير",
   "extra_id": "معرف إضافي:",
   "extracted_address_content": "سوف ترسل الأموال إلى\n${recipient_name}",
   "failed_authentication": "${state_error} فشل المصادقة.",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB هو بروتوكول جديد يجلب معاملات أسرع وأرخص وأكثر خصوصية إلى Litecoin",
   "litecoin_mweb_dismiss": "رفض",
   "litecoin_mweb_display_card": "عرض بطاقة mweb",
+  "litecoin_mweb_enable": "تمكين MWEB",
   "litecoin_mweb_enable_later": "يمكنك اختيار تمكين MWEB مرة أخرى ضمن إعدادات العرض.",
+  "litecoin_mweb_logs": "سجلات MWEB",
+  "litecoin_mweb_node": "عقدة MWEB",
   "litecoin_mweb_pegin": "ربط في",
   "litecoin_mweb_pegout": "ربط",
   "litecoin_mweb_scanning": "MWEB المسح الضوئي",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index 8b68d0d1e..7e78dd69a 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Изтича на",
   "expiry_and_validity": "Изтичане и валидност",
   "export_backup": "Експортиране на резервно копие",
+  "export_logs": "Експортни дневници",
   "extra_id": "Допълнително ID:",
   "extracted_address_content": "Ще изпратите средства на \n${recipient_name}",
   "failed_authentication": "Неуспешно удостоверяване. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWeb е нов протокол, който носи по -бърз, по -евтин и повече частни транзакции на Litecoin",
   "litecoin_mweb_dismiss": "Уволнение",
   "litecoin_mweb_display_card": "Показване на MWEB карта",
+  "litecoin_mweb_enable": "Активирайте MWeb",
   "litecoin_mweb_enable_later": "Можете да изберете да активирате MWEB отново под настройките на дисплея.",
+  "litecoin_mweb_logs": "MWeb logs",
+  "litecoin_mweb_node": "MWEB възел",
   "litecoin_mweb_pegin": "PEG в",
   "litecoin_mweb_pegout": "PEG OUT",
   "litecoin_mweb_scanning": "Сканиране на MWEB",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index 9b48ebdc7..f17466a9f 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Vyprší dne",
   "expiry_and_validity": "Vypršení a platnost",
   "export_backup": "Exportovat zálohu",
+  "export_logs": "Vývozní protokoly",
   "extra_id": "Extra ID:",
   "extracted_address_content": "Prostředky budete posílat na\n${recipient_name}",
   "failed_authentication": "Ověřování selhalo. ${state_error}",
@@ -371,7 +372,10 @@
   "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",
   "litecoin_mweb_display_card": "Zobrazit kartu MWeb",
+  "litecoin_mweb_enable": "Povolit mWeb",
   "litecoin_mweb_enable_later": "V nastavení zobrazení můžete vybrat znovu povolit MWeb.",
+  "litecoin_mweb_logs": "Protokoly mWeb",
+  "litecoin_mweb_node": "Uzel mWeb",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Zkrachovat",
   "litecoin_mweb_scanning": "Skenování mWeb",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 2ec59f349..cb0a59574 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Läuft aus am",
   "expiry_and_validity": "Ablauf und Gültigkeit",
   "export_backup": "Sicherung exportieren",
+  "export_logs": "Exportprotokolle",
   "extra_id": "Extra ID:",
   "extracted_address_content": "Sie senden Geld an\n${recipient_name}",
   "failed_authentication": "Authentifizierung fehlgeschlagen. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWWB ist ein neues Protokoll, das schnellere, billigere und privatere Transaktionen zu Litecoin bringt",
   "litecoin_mweb_dismiss": "Zurückweisen",
   "litecoin_mweb_display_card": "MWEB-Karte anzeigen",
+  "litecoin_mweb_enable": "Aktivieren Sie MWeb",
   "litecoin_mweb_enable_later": "Sie können MWEB unter Anzeigeeinstellungen erneut aktivieren.",
+  "litecoin_mweb_logs": "MWEB -Protokolle",
+  "litecoin_mweb_node": "MWEB -Knoten",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Abstecken",
   "litecoin_mweb_scanning": "MWEB Scanning",
@@ -941,4 +945,4 @@
   "you_will_get": "Konvertieren zu",
   "you_will_send": "Konvertieren von",
   "yy": "YY"
-}
+}
\ No newline at end of file
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index 4f5fd23b3..40be8fd08 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Expires on",
   "expiry_and_validity": "Expiry and Validity",
   "export_backup": "Export backup",
+  "export_logs": "Export logs",
   "extra_id": "Extra ID:",
   "extracted_address_content": "You will be sending funds to\n${recipient_name}",
   "failed_authentication": "Failed authentication. ${state_error}",
@@ -373,7 +374,10 @@
   "litecoin_mweb_description": "MWEB is a new protocol that brings faster, cheaper, and more private transactions to Litecoin",
   "litecoin_mweb_dismiss": "Dismiss",
   "litecoin_mweb_display_card": "Show MWEB card",
+  "litecoin_mweb_enable": "Enable MWEB",
   "litecoin_mweb_enable_later": "You can choose to enable MWEB again under Display Settings.",
+  "litecoin_mweb_logs": "MWEB Logs",
+  "litecoin_mweb_node": "MWEB Node",
   "litecoin_mweb_pegin": "Peg In",
   "litecoin_mweb_pegout": "Peg Out",
   "litecoin_mweb_scanning": "MWEB Scanning",
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index fd20a8b30..5a693cf32 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Expira el",
   "expiry_and_validity": "Vencimiento y validez",
   "export_backup": "Exportar copia de seguridad",
+  "export_logs": "Registros de exportación",
   "extra_id": "ID adicional:",
   "extracted_address_content": "Enviará fondos a\n${recipient_name}",
   "failed_authentication": "Autenticación fallida. ${state_error}",
@@ -371,7 +372,10 @@
   "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",
   "litecoin_mweb_display_card": "Mostrar tarjeta MWEB",
+  "litecoin_mweb_enable": "Habilitar mweb",
   "litecoin_mweb_enable_later": "Puede elegir habilitar MWEB nuevamente en la configuración de visualización.",
+  "litecoin_mweb_logs": "Registros de mweb",
+  "litecoin_mweb_node": "Nodo mweb",
   "litecoin_mweb_pegin": "Convertir",
   "litecoin_mweb_pegout": "Recuperar",
   "litecoin_mweb_scanning": "Escaneo mweb",
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index 50aceb2f1..1865e41f2 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Expire le",
   "expiry_and_validity": "Expiration et validité",
   "export_backup": "Exporter la sauvegarde",
+  "export_logs": "Journaux d'exportation",
   "extra_id": "ID supplémentaire :",
   "extracted_address_content": "Vous allez envoyer des fonds à\n${recipient_name}",
   "failed_authentication": "Échec d'authentification. ${state_error}",
@@ -371,7 +372,10 @@
   "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",
   "litecoin_mweb_display_card": "Afficher la carte MWeb",
+  "litecoin_mweb_enable": "Activer Mweb",
   "litecoin_mweb_enable_later": "Vous pouvez choisir d'activer à nouveau MWEB sous Paramètres d'affichage.",
+  "litecoin_mweb_logs": "Journaux MWEB",
+  "litecoin_mweb_node": "Node MWEB",
   "litecoin_mweb_pegin": "Entraver",
   "litecoin_mweb_pegout": "Crever",
   "litecoin_mweb_scanning": "Scann mweb",
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index e66859531..52cf14128 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Yana ƙarewa",
   "expiry_and_validity": "Karewa da inganci",
   "export_backup": "Ajiyayyen fitarwa",
+  "export_logs": "Injin fitarwa",
   "extra_id": "Karin ID:",
   "extracted_address_content": "Za ku aika da kudade zuwa\n${recipient_name}",
   "failed_authentication": "Binne wajen shiga. ${state_error}",
@@ -371,7 +372,10 @@
   "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",
   "litecoin_mweb_display_card": "Nuna katin Mweb",
+  "litecoin_mweb_enable": "Kunna Mweb",
   "litecoin_mweb_enable_later": "Kuna iya zaɓar kunna Mweb kuma a ƙarƙashin saitunan nuni.",
+  "litecoin_mweb_logs": "Jagoran Mweb",
+  "litecoin_mweb_node": "Mweb Node",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Peg fita",
   "litecoin_mweb_scanning": "Mweb scanning",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index bc8b81211..64f112a42 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -295,6 +295,7 @@
   "expiresOn": "पर समय सीमा समाप्त",
   "expiry_and_validity": "समाप्ति और वैधता",
   "export_backup": "निर्यात बैकअप",
+  "export_logs": "निर्यात लॉग",
   "extra_id": "अतिरिक्त आईडी:",
   "extracted_address_content": "आपको धनराशि भेजी जाएगी\n${recipient_name}",
   "failed_authentication": "प्रमाणीकरण विफल. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB एक नया प्रोटोकॉल है जो लिटकोइन के लिए तेजी से, सस्ता और अधिक निजी लेनदेन लाता है",
   "litecoin_mweb_dismiss": "नकार देना",
   "litecoin_mweb_display_card": "MWEB कार्ड दिखाएं",
+  "litecoin_mweb_enable": "MWEB सक्षम करें",
   "litecoin_mweb_enable_later": "आप प्रदर्शन सेटिंग्स के तहत फिर से MWEB को सक्षम करने के लिए चुन सकते हैं।",
+  "litecoin_mweb_logs": "MWEB लॉग",
+  "litecoin_mweb_node": "MWEB नोड",
   "litecoin_mweb_pegin": "खूंटी",
   "litecoin_mweb_pegout": "मरना",
   "litecoin_mweb_scanning": "MWEB स्कैनिंग",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 9ff57707d..4bbf4f141 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Istječe",
   "expiry_and_validity": "Istek i valjanost",
   "export_backup": "Izvezi sigurnosnu kopiju",
+  "export_logs": "Izvozni trupci",
   "extra_id": "Dodatni ID:",
   "extracted_address_content": "Poslat ćete sredstva primatelju\n${recipient_name}",
   "failed_authentication": "Autentifikacija neuspješna. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB je novi protokol koji u Litecoin donosi brže, jeftinije i privatnije transakcije",
   "litecoin_mweb_dismiss": "Odbaciti",
   "litecoin_mweb_display_card": "Prikaži MWeb karticu",
+  "litecoin_mweb_enable": "Omogući MWeb",
   "litecoin_mweb_enable_later": "Možete odabrati da MWEB ponovo omogućite pod postavkama zaslona.",
+  "litecoin_mweb_logs": "MWEB trupci",
+  "litecoin_mweb_node": "MWEB čvor",
   "litecoin_mweb_pegin": "Uvući se",
   "litecoin_mweb_pegout": "Odapeti",
   "litecoin_mweb_scanning": "MWEB skeniranje",
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index 40ed1e116..cbaf3a548 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Վավերականությունը լրանում է",
   "expiry_and_validity": "Վավերականություն և լրացում",
   "export_backup": "Արտահանել կրկնօրինակը",
+  "export_logs": "Արտահանման տեղեկամատյաններ",
   "extra_id": "Լրացուցիչ ID",
   "extracted_address_content": "Դուք կուղարկեք գումար ${recipient_name}",
   "failed_authentication": "Վավերացումը ձախողվեց. ${state_error}",
@@ -367,7 +368,10 @@
   "light_theme": "Լուսավոր",
   "litecoin_mweb_description": "Mweb- ը նոր արձանագրություն է, որը բերում է ավելի արագ, ավելի էժան եւ ավելի մասնավոր գործարքներ դեպի LITECOIN",
   "litecoin_mweb_dismiss": "Հեռացնել",
+  "litecoin_mweb_enable": "Միացնել Mweb- ը",
   "litecoin_mweb_enable_later": "Կարող եք ընտրել Mweb- ը կրկին միացնել ցուցադրման պարամետրերը:",
+  "litecoin_mweb_logs": "Mweb տեղեկամատյաններ",
+  "litecoin_mweb_node": "Mweb հանգույց",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Հափշտակել",
   "live_fee_rates": "Ապակի վարձավճարներ API- ի միջոցով",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index 2858fa193..273087eec 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Kadaluarsa pada",
   "expiry_and_validity": "Kedaluwarsa dan validitas",
   "export_backup": "Ekspor cadangan",
+  "export_logs": "Log ekspor",
   "extra_id": "ID tambahan:",
   "extracted_address_content": "Anda akan mengirim dana ke\n${recipient_name}",
   "failed_authentication": "Otentikasi gagal. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB adalah protokol baru yang membawa transaksi yang lebih cepat, lebih murah, dan lebih pribadi ke Litecoin",
   "litecoin_mweb_dismiss": "Membubarkan",
   "litecoin_mweb_display_card": "Tunjukkan kartu mWeb",
+  "litecoin_mweb_enable": "Aktifkan MWEB",
   "litecoin_mweb_enable_later": "Anda dapat memilih untuk mengaktifkan MWEB lagi di bawah pengaturan tampilan.",
+  "litecoin_mweb_logs": "Log MWeb",
+  "litecoin_mweb_node": "Node MWEB",
   "litecoin_mweb_pegin": "Pasak masuk",
   "litecoin_mweb_pegout": "Mati",
   "litecoin_mweb_scanning": "Pemindaian MWEB",
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index 034376a6c..917315aa6 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -296,6 +296,7 @@
   "expiresOn": "Scade il",
   "expiry_and_validity": "Scadenza e validità",
   "export_backup": "Esporta backup",
+  "export_logs": "Registri di esportazione",
   "extra_id": "Extra ID:",
   "extracted_address_content": "Invierai i tuoi fondi a\n${recipient_name}",
   "failed_authentication": "Autenticazione fallita. ${state_error}",
@@ -372,7 +373,10 @@
   "litecoin_mweb_description": "MWeb è un nuovo protocollo che porta transazioni più veloci, più economiche e più private a Litecoin",
   "litecoin_mweb_dismiss": "Congedare",
   "litecoin_mweb_display_card": "Mostra la scheda MWeb",
+  "litecoin_mweb_enable": "Abilita mWeb",
   "litecoin_mweb_enable_later": "È possibile scegliere di abilitare nuovamente MWeb nelle impostazioni di visualizzazione.",
+  "litecoin_mweb_logs": "Registri mWeb",
+  "litecoin_mweb_node": "Nodo MWeb",
   "litecoin_mweb_pegin": "Piolo in",
   "litecoin_mweb_pegout": "PEG OUT",
   "litecoin_mweb_scanning": "Scansione MWeb",
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index 7f0792063..ae3e32ea8 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -295,6 +295,7 @@
   "expiresOn": "有効期限は次のとおりです",
   "expiry_and_validity": "有効期限と有効性",
   "export_backup": "バックアップのエクスポート",
+  "export_logs": "ログをエクスポートします",
   "extra_id": "追加ID:",
   "extracted_address_content": "に送金します\n${recipient_name}",
   "failed_authentication": "認証失敗. ${state_error}",
@@ -372,7 +373,10 @@
   "litecoin_mweb_description": "MWEBは、Litecoinにより速く、より安価で、よりプライベートなトランザクションをもたらす新しいプロトコルです",
   "litecoin_mweb_dismiss": "却下する",
   "litecoin_mweb_display_card": "MWEBカードを表示します",
+  "litecoin_mweb_enable": "MWEBを有効にします",
   "litecoin_mweb_enable_later": "表示設定の下で、MWEBを再度有効にすることを選択できます。",
+  "litecoin_mweb_logs": "MWEBログ",
+  "litecoin_mweb_node": "MWEBノード",
   "litecoin_mweb_pegin": "ペグイン",
   "litecoin_mweb_pegout": "ペグアウト",
   "litecoin_mweb_scanning": "MWEBスキャン",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 6ba402ce3..2dc1a2dfc 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -295,6 +295,7 @@
   "expiresOn": "만료 날짜",
   "expiry_and_validity": "만료와 타당성",
   "export_backup": "백업 내보내기",
+  "export_logs": "내보내기 로그",
   "extra_id": "추가 ID:",
   "extracted_address_content": "당신은에 자금을 보낼 것입니다\n${recipient_name}",
   "failed_authentication": "인증 실패. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB는 Litecoin에 더 빠르고 저렴하며 개인 거래를 제공하는 새로운 프로토콜입니다.",
   "litecoin_mweb_dismiss": "해고하다",
   "litecoin_mweb_display_card": "mweb 카드를 보여주십시오",
+  "litecoin_mweb_enable": "mweb 활성화",
   "litecoin_mweb_enable_later": "디스플레이 설정에서 MWEB를 다시 활성화하도록 선택할 수 있습니다.",
+  "litecoin_mweb_logs": "mweb 로그",
+  "litecoin_mweb_node": "mweb 노드",
   "litecoin_mweb_pegin": "페그를 입력하십시오",
   "litecoin_mweb_pegout": "죽다",
   "litecoin_mweb_scanning": "mweb 스캔",
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index 69b888b5a..f42af6863 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -295,6 +295,7 @@
   "expiresOn": "သက်တမ်းကုန်သည်။",
   "expiry_and_validity": "သက်တမ်းကုန်ဆုံးခြင်းနှင့်တရားဝင်မှု",
   "export_backup": "အရန်ကူးထုတ်ရန်",
+  "export_logs": "ပို့ကုန်မှတ်တမ်းများ",
   "extra_id": "အပို ID-",
   "extracted_address_content": "သင်သည် \n${recipient_name} သို့ ရန်ပုံငွေများ ပေးပို့ပါမည်",
   "failed_authentication": "အထောက်အထားစိစစ်ခြင်း မအောင်မြင်ပါ။. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "Mweb သည် Protocol အသစ်ဖြစ်ပြီး LitCoin သို့ပိုမိုဈေးချိုသာသော, စျေးသက်သက်သာသာသုံးခြင်းနှင့်ပိုမိုများပြားသောပုဂ္ဂလိကငွေပို့ဆောင်မှုများကိုဖြစ်ပေါ်စေသည်",
   "litecoin_mweb_dismiss": "ထုတ်ပစ်",
   "litecoin_mweb_display_card": "MweB ကဒ်ကိုပြပါ",
+  "litecoin_mweb_enable": "mweb enable",
   "litecoin_mweb_enable_later": "သင် MweB ကို display settings အောက်ရှိ ထပ်မံ. ခွင့်ပြုရန်ရွေးချယ်နိုင်သည်။",
+  "litecoin_mweb_logs": "Mweb မှတ်တမ်းများ",
+  "litecoin_mweb_node": "mweb node ကို",
   "litecoin_mweb_pegin": "တံစို့",
   "litecoin_mweb_pegout": "တံစို့",
   "litecoin_mweb_scanning": "mweb scanning",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 2c259bf80..73e3df6b6 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Verloopt op",
   "expiry_and_validity": "Vervallen en geldigheid",
   "export_backup": "Back-up exporteren",
+  "export_logs": "Exporteer logboeken",
   "extra_id": "Extra ID:",
   "extracted_address_content": "U stuurt geld naar\n${recipient_name}",
   "failed_authentication": "Mislukte authenticatie. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB is een nieuw protocol dat snellere, goedkopere en meer privé -transacties naar Litecoin brengt",
   "litecoin_mweb_dismiss": "Afwijzen",
   "litecoin_mweb_display_card": "Toon MWEB -kaart",
+  "litecoin_mweb_enable": "MWEB inschakelen",
   "litecoin_mweb_enable_later": "U kunt ervoor kiezen om MWeb opnieuw in te schakelen onder weergave -instellingen.",
+  "litecoin_mweb_logs": "MWEB -logboeken",
+  "litecoin_mweb_node": "MWEB -knooppunt",
   "litecoin_mweb_pegin": "Vastmaken",
   "litecoin_mweb_pegout": "Uithakken",
   "litecoin_mweb_scanning": "MWEB -scanning",
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index 936339708..aaa82a3bf 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Upływa w dniu",
   "expiry_and_validity": "Wygaśnięcie i ważność",
   "export_backup": "Eksportuj kopię zapasową",
+  "export_logs": "Dzienniki eksportu",
   "extra_id": "Dodatkowy ID:",
   "extracted_address_content": "Wysyłasz środki na\n${recipient_name}",
   "failed_authentication": "Nieudane uwierzytelnienie. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB to nowy protokół, który przynosi szybciej, tańsze i bardziej prywatne transakcje do Litecoin",
   "litecoin_mweb_dismiss": "Odrzucać",
   "litecoin_mweb_display_card": "Pokaż kartę MWEB",
+  "litecoin_mweb_enable": "Włącz MWEB",
   "litecoin_mweb_enable_later": "Możesz ponownie włączyć MWEB w ustawieniach wyświetlania.",
+  "litecoin_mweb_logs": "Dzienniki MWEB",
+  "litecoin_mweb_node": "Węzeł MWEB",
   "litecoin_mweb_pegin": "Kołek",
   "litecoin_mweb_pegout": "Palikować",
   "litecoin_mweb_scanning": "Skanowanie MWEB",
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index 0cc0cc00a..194307a3d 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Expira em",
   "expiry_and_validity": "Expiração e validade",
   "export_backup": "Backup de exportação",
+  "export_logs": "Exportar logs",
   "extra_id": "ID extra:",
   "extracted_address_content": "Você enviará fundos para\n${recipient_name}",
   "failed_authentication": "Falha na autenticação. ${state_error}",
@@ -371,7 +372,10 @@
   "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",
   "litecoin_mweb_display_card": "Mostre o cartão MWEB",
+  "litecoin_mweb_enable": "Ativar Mweb",
   "litecoin_mweb_enable_later": "Você pode optar por ativar o MWEB novamente em Configurações de exibição.",
+  "litecoin_mweb_logs": "Logs MWeb",
+  "litecoin_mweb_node": "Nó MWeb",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Peg fora",
   "litecoin_mweb_scanning": "MWEB Scanning",
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index 8aeb56a86..f42c28c15 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Годен до",
   "expiry_and_validity": "Истечение и достоверность",
   "export_backup": "Экспорт резервной копии",
+  "export_logs": "Экспортные журналы",
   "extra_id": "Дополнительный ID:",
   "extracted_address_content": "Вы будете отправлять средства\n${recipient_name}",
   "failed_authentication": "Ошибка аутентификации. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB - это новый протокол, который приносит быстрее, дешевле и более частные транзакции в Litecoin",
   "litecoin_mweb_dismiss": "Увольнять",
   "litecoin_mweb_display_card": "Показать карту MWEB",
+  "litecoin_mweb_enable": "Включить MWEB",
   "litecoin_mweb_enable_later": "Вы можете снова включить MWEB в настройках отображения.",
+  "litecoin_mweb_logs": "MWEB журналы",
+  "litecoin_mweb_node": "Узел MWEB",
   "litecoin_mweb_pegin": "Внедрять",
   "litecoin_mweb_pegout": "Выкрикивать",
   "litecoin_mweb_scanning": "MWEB сканирование",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index 736eb8762..9d8fb0af2 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -295,6 +295,7 @@
   "expiresOn": "หมดอายุวันที่",
   "expiry_and_validity": "หมดอายุและถูกต้อง",
   "export_backup": "ส่งออกข้อมูลสำรอง",
+  "export_logs": "บันทึกการส่งออก",
   "extra_id": "ไอดีเพิ่มเติม:",
   "extracted_address_content": "คุณกำลังจะส่งเงินไปยัง\n${recipient_name}",
   "failed_authentication": "การยืนยันสิทธิ์ล้มเหลว ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB เป็นโปรโตคอลใหม่ที่นำการทำธุรกรรมที่เร็วกว่าราคาถูกกว่าและเป็นส่วนตัวมากขึ้นไปยัง Litecoin",
   "litecoin_mweb_dismiss": "อนุญาตให้ออกไป",
   "litecoin_mweb_display_card": "แสดงการ์ด mweb",
+  "litecoin_mweb_enable": "เปิดใช้งาน mweb",
   "litecoin_mweb_enable_later": "คุณสามารถเลือกเปิดใช้งาน MWEB อีกครั้งภายใต้การตั้งค่าการแสดงผล",
+  "litecoin_mweb_logs": "บันทึก MWEB",
+  "litecoin_mweb_node": "โหนด MWEB",
   "litecoin_mweb_pegin": "หมุด",
   "litecoin_mweb_pegout": "ตรึง",
   "litecoin_mweb_scanning": "การสแกน MWEB",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index e68bd0b22..ca35e7997 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Mag-e-expire sa",
   "expiry_and_validity": "Pag-expire at Bisa",
   "export_backup": "I-export ang backup",
+  "export_logs": "Mga log ng pag -export",
   "extra_id": "Dagdag na ID:",
   "extracted_address_content": "Magpapadala ka ng pondo sa\n${recipient_name}",
   "failed_authentication": "Nabigo ang pagpapatunay. ${state_error}",
@@ -371,7 +372,10 @@
   "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",
   "litecoin_mweb_display_card": "Ipakita ang MWEB Card",
+  "litecoin_mweb_enable": "Paganahin ang MWeb",
   "litecoin_mweb_enable_later": "Maaari kang pumili upang paganahin muli ang MWeb sa ilalim ng mga setting ng pagpapakita.",
+  "litecoin_mweb_logs": "MWEB log",
+  "litecoin_mweb_node": "Mweb node",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Peg out",
   "litecoin_mweb_scanning": "Pag -scan ng Mweb",
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index 83e8f6cbc..1fee66369 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Tarihinde sona eriyor",
   "expiry_and_validity": "Sona erme ve geçerlilik",
   "export_backup": "Yedeği dışa aktar",
+  "export_logs": "Dışa aktarma günlükleri",
   "extra_id": "Ekstra ID:",
   "extracted_address_content": "Parayı buraya gönderceksin:\n${recipient_name}",
   "failed_authentication": "Doğrulama başarısız oldu. ${state_error}",
@@ -371,7 +372,10 @@
   "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",
   "litecoin_mweb_display_card": "MWEB kartını göster",
+  "litecoin_mweb_enable": "MWEB'i etkinleştir",
   "litecoin_mweb_enable_later": "Ekran ayarlarının altında MWEB'yi tekrar etkinleştirmeyi seçebilirsiniz.",
+  "litecoin_mweb_logs": "MWEB günlükleri",
+  "litecoin_mweb_node": "MWEB düğümü",
   "litecoin_mweb_pegin": "Takılmak",
   "litecoin_mweb_pegout": "Çiğnemek",
   "litecoin_mweb_scanning": "MWEB taraması",
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index 909d9c01f..5d9a56c1e 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -295,6 +295,7 @@
   "expiresOn": "Термін дії закінчується",
   "expiry_and_validity": "Закінчення та обгрунтованість",
   "export_backup": "Експортувати резервну копію",
+  "export_logs": "Експортні журнали",
   "extra_id": "Додатковий ID:",
   "extracted_address_content": "Ви будете відправляти кошти\n${recipient_name}",
   "failed_authentication": "Помилка аутентифікації. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB - це новий протокол, який приносить швидкі, дешевші та більш приватні транзакції Litecoin",
   "litecoin_mweb_dismiss": "Звільнити",
   "litecoin_mweb_display_card": "Показати карту MWeb",
+  "litecoin_mweb_enable": "Увімкнути mweb",
   "litecoin_mweb_enable_later": "Ви можете знову ввімкнути MWEB в налаштуваннях дисплея.",
+  "litecoin_mweb_logs": "Журнали MWeb",
+  "litecoin_mweb_node": "Вузол MWeb",
   "litecoin_mweb_pegin": "Подякувати",
   "litecoin_mweb_pegout": "Подякувати",
   "litecoin_mweb_scanning": "Сканування Mweb",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index 2dbc97102..106f00f96 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -295,6 +295,7 @@
   "expiresOn": "ﺩﺎﻌﯿﻣ ﯽﻣﺎﺘﺘﺧﺍ",
   "expiry_and_validity": "میعاد ختم اور صداقت",
   "export_backup": "بیک اپ برآمد کریں۔",
+  "export_logs": "نوشتہ جات برآمد کریں",
   "extra_id": "اضافی ID:",
   "extracted_address_content": "آپ فنڈز بھیج رہے ہوں گے\n${recipient_name}",
   "failed_authentication": "ناکام تصدیق۔ ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB ایک نیا پروٹوکول ہے جو لیٹیکوئن میں تیز ، سستا اور زیادہ نجی لین دین لاتا ہے",
   "litecoin_mweb_dismiss": "خارج",
   "litecoin_mweb_display_card": "MWEB کارڈ دکھائیں",
+  "litecoin_mweb_enable": "MWEB کو فعال کریں",
   "litecoin_mweb_enable_later": "آپ ڈسپلے کی ترتیبات کے تحت MWEB کو دوبارہ فعال کرنے کا انتخاب کرسکتے ہیں۔",
+  "litecoin_mweb_logs": "MWEB لاگز",
+  "litecoin_mweb_node": "MWEB نوڈ",
   "litecoin_mweb_pegin": "پیگ میں",
   "litecoin_mweb_pegout": "پیگ آؤٹ",
   "litecoin_mweb_scanning": "MWEB اسکیننگ",
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index 8d28d48a2..a95f32aaa 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -296,6 +296,7 @@
   "expiresOn": "Hết hạn vào",
   "expiry_and_validity": "Hạn và hiệu lực",
   "export_backup": "Xuất sao lưu",
+  "export_logs": "Nhật ký xuất khẩu",
   "extra_id": "ID bổ sung:",
   "extracted_address_content": "Bạn sẽ gửi tiền cho\n${recipient_name}",
   "failed_authentication": "Xác thực không thành công. ${state_error}",
@@ -368,7 +369,10 @@
   "light_theme": "Chủ đề sáng",
   "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",
+  "litecoin_mweb_enable": "Bật MWEB",
   "litecoin_mweb_enable_later": "Bạn có thể chọn bật lại MWEB trong cài đặt hiển thị.",
+  "litecoin_mweb_logs": "Nhật ký MWEB",
+  "litecoin_mweb_node": "Nút MWEB",
   "litecoin_mweb_pegin": "Chốt vào",
   "litecoin_mweb_pegout": "Chốt ra",
   "live_fee_rates": "Tỷ lệ phí hiện tại qua API",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 03c7c95ef..1a1583da5 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -296,6 +296,7 @@
   "expiresOn": "Ipari lori",
   "expiry_and_validity": "Ipari ati idaniloju",
   "export_backup": "Sún ẹ̀dà nípamọ́ síta",
+  "export_logs": "Wọle si okeere",
   "extra_id": "Àmì ìdánimọ̀ tó fikún:",
   "extracted_address_content": "Ẹ máa máa fi owó ránṣẹ́ sí\n${recipient_name}",
   "failed_authentication": "Ìfẹ̀rílàdí pipòfo. ${state_error}",
@@ -372,7 +373,10 @@
   "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",
   "litecoin_mweb_display_card": "Fihan kaadi Mweb",
+  "litecoin_mweb_enable": "Mu mweb",
   "litecoin_mweb_enable_later": "O le yan lati ṣiṣẹ Mweb lẹẹkansi labẹ awọn eto ifihan.",
+  "litecoin_mweb_logs": "MTweb logs",
+  "litecoin_mweb_node": "Alweb joko",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Peg jade",
   "litecoin_mweb_scanning": "Mweb scanning",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index 5c8d708f4..79fe8faa5 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -295,6 +295,7 @@
   "expiresOn": "到期",
   "expiry_and_validity": "到期和有效性",
   "export_backup": "导出备份",
+  "export_logs": "导出日志",
   "extra_id": "额外ID:",
   "extracted_address_content": "您将汇款至\n${recipient_name}",
   "failed_authentication": "身份验证失败. ${state_error}",
@@ -371,7 +372,10 @@
   "litecoin_mweb_description": "MWEB是一项新协议,它将更快,更便宜和更多的私人交易带给Litecoin",
   "litecoin_mweb_dismiss": "解雇",
   "litecoin_mweb_display_card": "显示MWEB卡",
+  "litecoin_mweb_enable": "启用MWEB",
   "litecoin_mweb_enable_later": "您可以选择在显示设置下再次启用MWEB。",
+  "litecoin_mweb_logs": "MWEB日志",
+  "litecoin_mweb_node": "MWEB节点",
   "litecoin_mweb_pegin": "钉进",
   "litecoin_mweb_pegout": "昏倒",
   "litecoin_mweb_scanning": "MWEB扫描",

From 48457fdd6d3b15beacdbe170117dcbc2cbce25dc Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Thu, 7 Nov 2024 07:50:48 +0200
Subject: [PATCH 32/50] cake pay country picker (#1779)

* cake pay country picker

* UI changes

* hide picker after the country is set

* Revert "hide picker after the country is set"

This reverts commit cce358b94f55c22e0807b4d3641a13ebd299106c.

* show country picker initially

* flags

* minor ui fixes

* Update lib/view_model/cake_pay/cake_pay_cards_list_view_model.dart

---------

Co-authored-by: tuxpizza <tuxsudo@tux.pizza>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 assets/images/flags/abw.png                   | Bin 0 -> 607 bytes
 assets/images/flags/afg.png                   | Bin 0 -> 1848 bytes
 assets/images/flags/ago.png                   | Bin 0 -> 1159 bytes
 assets/images/flags/aia.png                   | Bin 0 -> 1357 bytes
 assets/images/flags/and.png                   | Bin 0 -> 1966 bytes
 assets/images/flags/asm.png                   | Bin 0 -> 503 bytes
 assets/images/flags/atf.png                   | Bin 0 -> 1311 bytes
 assets/images/flags/atg.png                   | Bin 0 -> 963 bytes
 assets/images/flags/aut.png                   | Bin 0 -> 125 bytes
 assets/images/flags/aze.png                   | Bin 0 -> 717 bytes
 assets/images/flags/bel.png                   | Bin 0 -> 127 bytes
 assets/images/flags/bes.png                   | Bin 0 -> 236 bytes
 assets/images/flags/bhr.png                   | Bin 0 -> 567 bytes
 assets/images/flags/blz.png                   | Bin 0 -> 1777 bytes
 assets/images/flags/bmu.png                   | Bin 0 -> 1518 bytes
 assets/images/flags/bol.png                   | Bin 0 -> 668 bytes
 assets/images/flags/brn.png                   | Bin 0 -> 1957 bytes
 assets/images/flags/btn.png                   | Bin 0 -> 4013 bytes
 assets/images/flags/bvt.png                   | Bin 0 -> 147 bytes
 assets/images/flags/bwa.png                   | Bin 0 -> 134 bytes
 assets/images/flags/cck.png                   | Bin 0 -> 1139 bytes
 assets/images/flags/cmr.png                   | Bin 0 -> 402 bytes
 assets/images/flags/cok.png                   | Bin 0 -> 1416 bytes
 assets/images/flags/cpv.png                   | Bin 0 -> 297 bytes
 assets/images/flags/cri.png                   | Bin 0 -> 136 bytes
 assets/images/flags/cuw.png                   | Bin 0 -> 481 bytes
 assets/images/flags/cxr.png                   | Bin 0 -> 1202 bytes
 assets/images/flags/cyp.png                   | Bin 0 -> 1128 bytes
 assets/images/flags/dji.png                   | Bin 0 -> 387 bytes
 assets/images/flags/dma.png                   | Bin 0 -> 1224 bytes
 assets/images/flags/dza.png                   | Bin 0 -> 518 bytes
 assets/images/flags/ecu.png                   | Bin 0 -> 1238 bytes
 assets/images/flags/est.png                   | Bin 0 -> 130 bytes
 assets/images/flags/eth.png                   | Bin 0 -> 1584 bytes
 assets/images/flags/fin.png                   | Bin 0 -> 131 bytes
 assets/images/flags/fji.png                   | Bin 0 -> 1571 bytes
 assets/images/flags/flk.png                   | Bin 0 -> 1591 bytes
 assets/images/flags/fro.png                   | Bin 0 -> 147 bytes
 assets/images/flags/fsm.png                   | Bin 0 -> 340 bytes
 assets/images/flags/gab.png                   | Bin 0 -> 130 bytes
 assets/images/flags/geo.png                   | Bin 0 -> 187 bytes
 assets/images/flags/ggi.png                   | Bin 0 -> 892 bytes
 assets/images/flags/ggy.png                   | Bin 0 -> 192 bytes
 assets/images/flags/glp.png                   | Bin 0 -> 1820 bytes
 assets/images/flags/gmb.png                   | Bin 0 -> 278 bytes
 assets/images/flags/grc.png                   | Bin 0 -> 436 bytes
 assets/images/flags/grd.png                   | Bin 0 -> 892 bytes
 assets/images/flags/grl.png                   | Bin 0 -> 407 bytes
 assets/images/flags/guf.png                   | Bin 0 -> 581 bytes
 assets/images/flags/gum.png                   | Bin 0 -> 1259 bytes
 assets/images/flags/guy.png                   | Bin 0 -> 635 bytes
 assets/images/flags/hmd.png                   | Bin 0 -> 780 bytes
 assets/images/flags/iot.png                   | Bin 0 -> 2415 bytes
 assets/images/flags/irl.png                   | Bin 0 -> 127 bytes
 assets/images/flags/jam.png                   | Bin 0 -> 526 bytes
 assets/images/flags/jey.png                   | Bin 0 -> 914 bytes
 assets/images/flags/jor.png                   | Bin 0 -> 3131 bytes
 assets/images/flags/kaz.png                   | Bin 0 -> 1740 bytes
 assets/images/flags/ken.png                   | Bin 0 -> 2074 bytes
 assets/images/flags/kir.png                   | Bin 0 -> 2113 bytes
 assets/images/flags/kwt.png                   | Bin 0 -> 372 bytes
 assets/images/flags/lbn.png                   | Bin 0 -> 960 bytes
 assets/images/flags/lie.png                   | Bin 0 -> 844 bytes
 assets/images/flags/lka.png                   | Bin 0 -> 1757 bytes
 assets/images/flags/ltu.png                   | Bin 0 -> 130 bytes
 assets/images/flags/lux.png                   | Bin 0 -> 130 bytes
 assets/images/flags/lva.png                   | Bin 0 -> 124 bytes
 assets/images/flags/mco.png                   | Bin 0 -> 204 bytes
 assets/images/flags/mlt.png                   | Bin 0 -> 485 bytes
 assets/images/flags/mnp.png                   | Bin 0 -> 2078 bytes
 assets/images/flags/mrt.png                   | Bin 0 -> 509 bytes
 assets/images/flags/msr.png                   | Bin 0 -> 1502 bytes
 assets/images/flags/mtq.png                   | Bin 0 -> 1512 bytes
 assets/images/flags/mwi.png                   | Bin 0 -> 754 bytes
 assets/images/flags/myt.png                   | Bin 0 -> 2003 bytes
 assets/images/flags/ner.png                   | Bin 0 -> 494 bytes
 assets/images/flags/nfk.png                   | Bin 0 -> 1422 bytes
 assets/images/flags/niu.png                   | Bin 0 -> 1095 bytes
 assets/images/flags/omn.png                   | Bin 0 -> 711 bytes
 assets/images/flags/per.png                   | Bin 0 -> 123 bytes
 assets/images/flags/plw.png                   | Bin 0 -> 608 bytes
 assets/images/flags/pri.png                   | Bin 0 -> 1880 bytes
 assets/images/flags/pyf.png                   | Bin 0 -> 1256 bytes
 assets/images/flags/qat.png                   | Bin 0 -> 2021 bytes
 assets/images/flags/slb.png                   | Bin 0 -> 403 bytes
 assets/images/flags/slv.png                   | Bin 0 -> 642 bytes
 assets/images/flags/svk.png                   | Bin 0 -> 521 bytes
 assets/images/flags/svn.png                   | Bin 0 -> 1963 bytes
 assets/images/flags/tkm.png                   | Bin 0 -> 1620 bytes
 assets/images/flags/ton.png                   | Bin 0 -> 139 bytes
 assets/images/flags/tuv.png                   | Bin 0 -> 1456 bytes
 assets/images/flags/ury.png                   | Bin 0 -> 1017 bytes
 assets/images/flags/vat.png                   | Bin 0 -> 851 bytes
 assets/images/flags/vir.png                   | Bin 0 -> 1987 bytes
 assets/images/flags/vut.png                   | Bin 0 -> 1267 bytes
 lib/cake_pay/cake_pay_api.dart                |  10 +-
 lib/cake_pay/cake_pay_service.dart            |   3 +-
 lib/di.dart                                   |   3 +-
 lib/entities/country.dart                     | 386 ++++++++++++++++++
 lib/entities/preferences_key.dart             |   1 +
 .../cake_pay/cards/cake_pay_cards_page.dart   | 156 +++++--
 .../screens/cake_pay/widgets/card_item.dart   |   2 +-
 lib/store/settings_store.dart                 |  25 +-
 .../cake_pay_cards_list_view_model.dart       |  65 +--
 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 +
 132 files changed, 601 insertions(+), 78 deletions(-)
 create mode 100644 assets/images/flags/abw.png
 create mode 100644 assets/images/flags/afg.png
 create mode 100644 assets/images/flags/ago.png
 create mode 100644 assets/images/flags/aia.png
 create mode 100644 assets/images/flags/and.png
 create mode 100644 assets/images/flags/asm.png
 create mode 100644 assets/images/flags/atf.png
 create mode 100644 assets/images/flags/atg.png
 create mode 100644 assets/images/flags/aut.png
 create mode 100644 assets/images/flags/aze.png
 create mode 100644 assets/images/flags/bel.png
 create mode 100644 assets/images/flags/bes.png
 create mode 100644 assets/images/flags/bhr.png
 create mode 100644 assets/images/flags/blz.png
 create mode 100644 assets/images/flags/bmu.png
 create mode 100644 assets/images/flags/bol.png
 create mode 100644 assets/images/flags/brn.png
 create mode 100644 assets/images/flags/btn.png
 create mode 100644 assets/images/flags/bvt.png
 create mode 100644 assets/images/flags/bwa.png
 create mode 100644 assets/images/flags/cck.png
 create mode 100644 assets/images/flags/cmr.png
 create mode 100644 assets/images/flags/cok.png
 create mode 100644 assets/images/flags/cpv.png
 create mode 100644 assets/images/flags/cri.png
 create mode 100644 assets/images/flags/cuw.png
 create mode 100644 assets/images/flags/cxr.png
 create mode 100644 assets/images/flags/cyp.png
 create mode 100644 assets/images/flags/dji.png
 create mode 100644 assets/images/flags/dma.png
 create mode 100644 assets/images/flags/dza.png
 create mode 100644 assets/images/flags/ecu.png
 create mode 100644 assets/images/flags/est.png
 create mode 100644 assets/images/flags/eth.png
 create mode 100644 assets/images/flags/fin.png
 create mode 100644 assets/images/flags/fji.png
 create mode 100644 assets/images/flags/flk.png
 create mode 100644 assets/images/flags/fro.png
 create mode 100644 assets/images/flags/fsm.png
 create mode 100644 assets/images/flags/gab.png
 create mode 100644 assets/images/flags/geo.png
 create mode 100644 assets/images/flags/ggi.png
 create mode 100644 assets/images/flags/ggy.png
 create mode 100644 assets/images/flags/glp.png
 create mode 100644 assets/images/flags/gmb.png
 create mode 100644 assets/images/flags/grc.png
 create mode 100644 assets/images/flags/grd.png
 create mode 100644 assets/images/flags/grl.png
 create mode 100644 assets/images/flags/guf.png
 create mode 100644 assets/images/flags/gum.png
 create mode 100644 assets/images/flags/guy.png
 create mode 100644 assets/images/flags/hmd.png
 create mode 100644 assets/images/flags/iot.png
 create mode 100644 assets/images/flags/irl.png
 create mode 100644 assets/images/flags/jam.png
 create mode 100644 assets/images/flags/jey.png
 create mode 100644 assets/images/flags/jor.png
 create mode 100644 assets/images/flags/kaz.png
 create mode 100644 assets/images/flags/ken.png
 create mode 100644 assets/images/flags/kir.png
 create mode 100644 assets/images/flags/kwt.png
 create mode 100644 assets/images/flags/lbn.png
 create mode 100644 assets/images/flags/lie.png
 create mode 100644 assets/images/flags/lka.png
 create mode 100644 assets/images/flags/ltu.png
 create mode 100644 assets/images/flags/lux.png
 create mode 100644 assets/images/flags/lva.png
 create mode 100644 assets/images/flags/mco.png
 create mode 100644 assets/images/flags/mlt.png
 create mode 100644 assets/images/flags/mnp.png
 create mode 100644 assets/images/flags/mrt.png
 create mode 100644 assets/images/flags/msr.png
 create mode 100644 assets/images/flags/mtq.png
 create mode 100644 assets/images/flags/mwi.png
 create mode 100644 assets/images/flags/myt.png
 create mode 100644 assets/images/flags/ner.png
 create mode 100644 assets/images/flags/nfk.png
 create mode 100644 assets/images/flags/niu.png
 create mode 100644 assets/images/flags/omn.png
 create mode 100644 assets/images/flags/per.png
 create mode 100644 assets/images/flags/plw.png
 create mode 100644 assets/images/flags/pri.png
 create mode 100644 assets/images/flags/pyf.png
 create mode 100644 assets/images/flags/qat.png
 create mode 100644 assets/images/flags/slb.png
 create mode 100644 assets/images/flags/slv.png
 create mode 100644 assets/images/flags/svk.png
 create mode 100644 assets/images/flags/svn.png
 create mode 100644 assets/images/flags/tkm.png
 create mode 100644 assets/images/flags/ton.png
 create mode 100644 assets/images/flags/tuv.png
 create mode 100644 assets/images/flags/ury.png
 create mode 100644 assets/images/flags/vat.png
 create mode 100644 assets/images/flags/vir.png
 create mode 100644 assets/images/flags/vut.png
 create mode 100644 lib/entities/country.dart

diff --git a/assets/images/flags/abw.png b/assets/images/flags/abw.png
new file mode 100644
index 0000000000000000000000000000000000000000..d049d3a4348416d1826a4236ce7218e6807669b9
GIT binary patch
literal 607
zcmV-l0-*hgP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0003yP)t-sM{rE<
zC@NQhyH|j_SAe=zf4We8x>$j``PLRzf4Wb7x>|$0RDQWte!7{p*<p#mqPyE>jKX1y
z!eETUQhm8ug1qOjw|tetVvE63e!A+Xt%jGuPJ_X$nzmViy#HBMiJ-}ap2@Ys++&Nu
zRerfmg223(uWY5+R)D*=n6PD$#{X1MPJq6;oU~JZxowfd{3IdfdxA`a!svN_{Uab)
zjmYwqn2w;w+J%r#e!RED+=Q&xZIs8unyrzTzW+x<PlCWye!BBCHBWuJ@);WP8yn($
zgl3GvyO^&~gu(ADF84%4hnK)zk;+kp!l$jvU6ae2p~GU8%;|D>_fAgsl$B42#r8-@
z@F^?$ARf(;q3|6Z?<y?id4Q3w)bSi1>~3@MEG<!dx%60A|3W>(l&J43E%0P!`5PIB
zRyK|R0004WQchC<K<3zH0002eNkl<ZSi@sr7zLwX6hHwx1pw6mP6`bWm0+RB02O^D
zNs0_`wlmXWrNjWgRC{wS3JgdJ3XZfj;v~}mPBzZ~fA9DNYf~K&7BUQwbNBIx4QGr=
zOtz2}=Vv0>08VAA(3FhmG%rRM6L~Q{W+swdz@lLj7?mEu=wz&>AjC^nAnI9$#f7*U
zs>^V(k{b(-zHSD(s+6Py2Tg57HcAX&la>;uC?#?V3h+>vow+G3511)6fPK_}fir-E
t0x(Dn7>$L|SQs^cN(PLAQ7{UC0055fRc;z8VCw(?002ovPDHLkV1l;f6z%{3

literal 0
HcmV?d00001

diff --git a/assets/images/flags/afg.png b/assets/images/flags/afg.png
new file mode 100644
index 0000000000000000000000000000000000000000..f2ea25144b2c5bf758a134ae00ca05e99cc9581b
GIT binary patch
literal 1848
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
OBXmEe@8Drx!T$m5@IgcX

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ago.png b/assets/images/flags/ago.png
new file mode 100644
index 0000000000000000000000000000000000000000..b04d7dfa6652e1e029f4dbeefc4db104382764af
GIT binary patch
literal 1159
zcmV;21bF+2P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0007!P)t-sM{rF4
z>=?}qCd>#Y4*>(e5F^eICIA2c&JiZk5hu+HCd~~d$^a<M3MLK!1OMw7%?>77O$hAF
z760fMzYil00R#Q&6wC%E&Jrff3Mc*O744xLy$2-w;uTm-2>ja@KsN@Lf(>X{35$FU
zLO2E>90Sj`69fYQ6A%Kpo)CU)3tLVI0RaF}Mh8|(2nq-R2?znMmJb2~06sPbUr`9#
zycEZ-5*8Bzxt|fptP-1q4%<v2zN8UzVhW~@5B=vA*TEF-p&HBwC;#mj5Do#rr4hZP
z5!_HA+)p9wnj2(M3IhcId}|Bvsu}0U6}|@~>ysN|R0;On7XIoK@T(c`s2bN-AI=XZ
z(GVw=felee2mRX?`r8)%>lFOj7X9fI&Iu>rRUzq%9LohKy`mA&1}OaI71Aao-(Vo{
ztQzBR9=-@9rH&8w%ok);3GSmBLNEvJq8iIPARHJ1<$E4^XbW&)3Xy#c2nhhYq7lIt
zBhVTp4h#XOln;@74G0GTcxMaY!W7%R6CMu)qKgh^SqaS#CjaUf8WsZGRU!Q375LE>
z>zEtfSRh?c2-GYj{N)wvmmAa>CcqOTi+BuDMhE=a7S%5#2nqo4(-q)jANJH1eQXPS
zYzuZ}3h2odGAjiC^cnx@7oLa?!5AYW9|N0(4p~hI{@WJ$*cSHK7Vy#)|JxT$LI;0t
z3$~vS=Y|}+p%J5y4(G`gI4}h^F9kI&1*47+*t!#?jSsn)5+oi2|J@eR93{{kCD=eB
z$^a+lf*sKwCD=bA=!zWFD<tQG9q*|c_RALw00Qok91;No<#`?4KqJ#AB;#=&(G(`n
z6eim{B>LPH=6@aTr5gI%752#&#U~-|ksQ7iBmEcE+5i9m0d!JMQvg8b*k%9#0i;Pp
zK~z}7V_+BsqhJ(30S5(O)PNCW02@UHu!&1DF;iebcy(`Qp*t5F*#_`VpCBcc$<4(?
zt^or3W=-tw%J;NpBF_NH!}|}2_xDHzJ2J76VSt1H&#@ys++55h_P%Vqq#Mw-_lorO
z6Ve9{aXAH~g?KQN?gH*}S7l|7ALZuYP0tkz6<{OT05+cUm#>}Sk>KD+PKwVU(gmDI
z;NpdwXD^+a6v4@vni!jv02U)?04p4bOx|$gmW<4jDiK!J?4p>sFn^FJ76aH(01F(5
zHqYF3`Xmb<ABbHL9pnXKu%N2OVgM4TXk4^u29zDe=;Mt=34R0E%lT*5bwHSr{DJJG
z8{kqYJb&i`5X;<;(Z+~$1K8{5u3ouuDv)6%Y^Fzs3xHtv_EkIP)s#6~>a&w<fJyCA
z5VdXn=4GW07CIywpl--7w0QZJt!vj!X-cs*W+&YR2Cj_ljB8dfE^H~bGu6@{-2ir7
zx4edFd*-y}u(NAxs;Q6{h=P3(T2)y{kSqfbKuKPKG6UEZ<tQ|Ooqg1RL2SS%7zLvM
Z2ml<!oxHgb?CAgi002ovPDHLkV1ik@*$)5!

literal 0
HcmV?d00001

diff --git a/assets/images/flags/aia.png b/assets/images/flags/aia.png
new file mode 100644
index 0000000000000000000000000000000000000000..193f0ff418ac5ff731ed35c4a02f26222f1194e4
GIT binary patch
literal 1357
zcmV-T1+w~yP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0007uP)t-sM{rC4
za=a%}sRK2d0CT<14-fn5>HssD|NsBY0013IrOVIO&(hiAhl<i29qy>819ZO9=JWjh
z{@hVf`TG5PmCE37asK}Q@2;+9g~9-O$TnWD*Eu=AtHL2orr6-`&=nQRr??3^oypYc
z)F&r|oz8xc!vHds0CmCLS62XZzW@IH-BeWm`1Jnz_w>G;^SG1s#isxM{^Vm304s9<
zDs}*KzXN*5(&qF7biLB&^haBQ{`~sS4i5kQ{N-g6?wV!gW)=G4()!@f{O#lImtg+(
z@%{4bcazB3MMWDqbOA?%0Y-!XcEZsZ7~S6B9659VO^N_ais9nq056OHak&68mH=_O
z0W)#T(ANPki^9gv0D8#*GI0PglmIGn0Xug9Fp*nqjubU_0X1>~Hgf<fanRG+0Cd0r
zFpvXPlL0+=0DH;9$IqUowg7a$(dP6PH+KV9l>mFnVR4abd6dP;(rkK_%+J@Pth-2D
zf=FD0%Ffo$)7k@dzWw#^(&_m5-pyupk^nK2XLgbUb-w^Hk^^?Y>x@tM*~aXTQ`7GM
z?U`f$@8I&YiwrS(tFgZQ^X<~*^7Y234KaJIv%mS<$k5*B_t3cRoM-8KHT$}e=yxyt
z@8|ya^6i#i{PF2*dzkR4eE9kK`TF{5d6wvQF7?Eu=y);ZXBYOGVEW_L_R6mEwT}Pi
z*5zm!|NZ^>+{*H|k^AP^^u3wypKS50fc^CE=XNdr`Ss^<Ci&dS^0A2Lawp_v6z6g%
z^S6=ipKR`%X6%w#^uC+#q;%|)TJyP;`r*;;ooV#Hp6!`r@1Sn;yO#93m+Od0?2uOQ
zrg!wbnCN&g>xoP2icJ3a_2gs{@vMQ5Ne83=0004WQchC<K<3zH0007TNkl<ZSi|kr
zRdd@w6b0baZhWuPKpk`(W+#q0%-p1qGBYzXGcz+YGcz;e&*_RSt92#6bw=kwqaAy{
zd)69{0s_>iQNt!%7a64mHZg&E4B{5CA)#U5Gc*vLY{WE;6i7^nkI;q705mD-LJ0w&
z#$!^P3;?v5LJ1CF#%H908~}in$Yn~ffUNNzfKY-4WRCX)_!1P*D093Rph`3w5ed*F
zb36y2C<G8i22if|751BLyHVE_+YTS!xRko<(@6k)?k{J7u6?J^EnT+#7~;`QOG@X=
z9N+P8N6-g~mN6_al3lmqKIkp^5mPh5brDT8U~G=g)QS%q%xr)6_4}_n`nHuf5SN5u
zp&^YF5EZG*O;6ECfghjT-`;=u{Bnm?0?^~*6B2_c05oZ6Ocs|Qz~)2FpC230)o^|5
z;tDT-86OM40HBqWAi%D(uiYQe;;298eFSbi@Bm0k5a5Wj%KZlM)veQ2HW9#&_XOw?
z*+Pk6JaGQfwL5Ps(02J$rCkK@<3#{hf(Q0H@b;5>*R$uYlhvy%o&Z1I3t&p{fbHN_
z#F|GB9^=h@Ys#dL@gJFw=s0oX-qY%bchS0MHR3FVz&ymV-IW*bzo<pDud^V|PzcN>
zPtICXTZdQd&J7F6VuC_o8v7TxaAxm%`eukiU~);3fy&M;YZsLm3`LWMDg;JPDJ*VH
zvU2$XaxE?#Ggu)2Bg_RY_!Nv92ucAMJ~gK$n~CFwfpTEL*nVbazu7b>%MSpudi6As
z5;>;s{d<5v06>1{4knYiOa7nV3$jY&wQHZ31^xp*-%Kj-e*<dNs3G|c5vi-dQ6`o%
P00000NkvXXu0mjfwOYRS

literal 0
HcmV?d00001

diff --git a/assets/images/flags/and.png b/assets/images/flags/and.png
new file mode 100644
index 0000000000000000000000000000000000000000..fc5d9a89be3fe0c181438caa47b8717186a2589f
GIT binary patch
literal 1966
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
A^8f$<

literal 0
HcmV?d00001

diff --git a/assets/images/flags/asm.png b/assets/images/flags/asm.png
new file mode 100644
index 0000000000000000000000000000000000000000..fd3818eda60ec1e2727de66410c7cf1411ddfe19
GIT binary patch
literal 503
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+Kpx~JR
zpAc8~0-yatI^3F74BGV&w1rO*h|USBK@f*#^%+4mpcIhHrd1<s-BCSpFPCwPap(+5
z`))S<reo(HvFJD2#Lo52UKW_Q+%a)}Qq6{v?wzvEeTr`VVzyoPpS(|R-2Cv_hf6nK
zFzYt3>Nj#4HG5?)*>>obm|Yi_NlW|eLo9lY51zhf)T!UF@4BQzH=99|Pu5a-*S_+;
z-OILKlCbZVcI;`JeQ5c%%V(}W{r~^JLGW~b^EMH)=B~L%L`<8RbQ?AwxH)0z-b$dq
zcuRu(f*I=T%j@4~<iD>kfB*ja-w-yS#12mv$B>A_Z?7E{I%FWw@GxoV2{X|<UAuR`
z{=HwgmC4y+iemM{4fhp`eyYEG65y%SGC_U*{od=sMZ(*d86Pb9p}S(;l=BX{@s}RY
zU`Sald4+QUuWR*|BTQ#E8ec!%xy2*ll6>Es&~-rqoF!3rk84f4;=<J1SU7*V?HP9#
zi}UF_7&4@^HXPo2q;;p^^cf8s@5OyvF@1%6`2IM>L-%BFbl%?lzHvoY0k?+80tVK9
kDhlj^DZgx$TK2>+R;6a|2@RTk2j~X|Pgg&ebxsLQ0C#!O3jhEB

literal 0
HcmV?d00001

diff --git a/assets/images/flags/atf.png b/assets/images/flags/atf.png
new file mode 100644
index 0000000000000000000000000000000000000000..af77e45d56cffeac7204d977b30278c46b2335de
GIT binary patch
literal 1311
zcmV+)1>pLLP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00004XF*Lt006O%
z3;baP00001b5ch_0Itp)=>Px%Pf$!$MF0Q*03wtCB9#Cllu&20l$4Z|86yA_QvelR
z?PzlV6H@>plmH@?03($EBa{FmlmH@>03wqBB9#CYT>v7K02_AzB9#Cll>i)i03nh9
z9DV>Il>j1?03wnAB9s6kl>j4@02*@uAB6xSlmH`?03wwD9D4vBf&e0u03Cmll9QB^
zlQ2JT?P+uXB9xRxOHpXEi+_cbA1IS6GX)x7X>f!9BbDy%?(Hc#|NsBFz}m*n=efb!
z?ZU+dD3<{wmHz(zfRf7Y@b^AhuPjNYJXfx~#M=TTmKQgk5i*<<G@VUmwa(S*&D81}
zI-oF2sRJgKL0hor>h(HRt!#k8=IQj8rqoVmwXeF}9Xz45zTZ7pt{OU^2r8IIV6rw*
ztMT*s3@w`NYIW_<(^6@(%h2H%IG@qj?7_<AaD>A+Q>^3X^Cm>4h?&ieozLj&^>v8G
zg_g{Gj>u$rzOlUCKw7VPjK|N`>yDk!&eiLzxZF);wN`GqbB4w9_4<&X(E0lOzQ^P-
zO{vAr=fTP4yTaNWJD?djpSi-}Cq$(aG@W;e#<#)YCq<<MCYIpj@&zcDiki+cPO4OF
zxEVR0@A3GOq0$~bp;~deeU8aUVY6?8!&Pj!5HXvwz26NknxU@PJ65gs_xp&L&HerU
zQ){;xIiQuJ)AIBA4lkOEo6q|C{b+o^L|(C}wcDPn*4^Uqn5NX#+wBrEoa5&6XMDfY
z+3fA__m-v8bce<1?Dp8*?uM4k@bdV;$>sX{{dkJUc8SJsg2Oykt!I3|MqB#U0000s
zbW%=J0Qc1X`y3n`9QzZAiTL#Rnq~A8W*qnFBw;0*n_*$<>KrB1X8s%{VH_MB9R2DX
z{U07593FzAMaBRC0xU^HK~z}7V_+BsqW}(sIXF0Uv{<1)Tb~UIjEoIUO*pUuVT5jV
zX+1L_U@?aSP763Nw=%;4<Ykl~`UM#w0;C#XX2z%j(l4uOMy>&7%yJA2qC#fm8(_w#
z$-rYqi2-KZ3`~?6z{J2ynF0I^W|SFVHfq4A0mIJ#1B3y(NCvbLZ9odbfFvXX+z1$8
z0|%)H1Cnjw0AWC`H4>NuH^7__fE(cH<K*PD$kK8JkXm4m#S3_WH<Wg?v~)%hBF=yu
z*L0UQm;qbk<CmG4^_Kd&_z`VDR<>ocAItzt%k7b7X0D-@8EM3Op~SZvNG5^}*s=34
zkYU#2lS#Z6>|N~x&CEPDc|yV<dY`?SdoW0d_&@}Kb(ZVF2E^{RJYq&_EC4~cgM-6b
zkO6xv9rnhMZotYdtJgSeSY>H>X#cJQmJy^Iu-tOv<|xYqOCUPvwas!VsRk@uVu=Dm
z=aOi^?65dHJG;d|tqveYNZ2fr0}%w~2U%Lq!<C&00y`iswruExGD$a}42a#!>w%<8
zI2i``7vvY#n3)B8n#G1hG}d~NY=C{9Wn~wH*;MCH4R--A(IymCbO6anU{TWEQWXtv
zU@#GFfQOk!pPAXrNoHnV0cNnItc=viA_h!}n%X~Y0!kxGQHUfH{4Im*kehjG3=ERY
zq!=)H#>DAJ4NVQ?rY=#y-OMZi&Jh!VG?pa<#LdV63IbAy20Ir!$$)FLlQaqt001|j
VkQQ>_vPJ*^002ovPDHLkV1h&LS9<^e

literal 0
HcmV?d00001

diff --git a/assets/images/flags/atg.png b/assets/images/flags/atg.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9a3d9f9e106261f8cd7e740df225aa703bf0b5d
GIT binary patch
literal 963
zcmV;!13dhRP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<STu@9@MMrQ<*F8=x0|+Yv2hI^DuMQyAJWb9KCIA2c&JiX60001T
z#?BEY|NsB|(H4Wc<AS4W>z=0m{{G%#aL*Vl_0rY=H($pPBvS?thYJ`A00PxBMf~#f
zuMQw40|$pPT?%Zy0CB~~6f09og(hF8uOB@M2mt)i75mT?J23@CIR+050pYq6o`Vey
z3jwhpJ%O&*CMQLJp=<om7FS3I8WjQw2LMVv2Kdbtntu%@9|PdJ69fYQX;%p<BLm5&
z5%kIx6%he-VG05P0HcQvrHKyJu@WL20}2TM`Og*j&K10z5b?+r+O-pJTnTPl2?RS}
zE?r|@g=hpiU@cr@U4&>33jsVb1riSdIxq!oS_w!z2I|5T5e@;Mg%0b(6l_@upo9&b
zf(@L34Si<{NjwJ5s}h-i4bQ6*d}j)qfDLqD3UgozpMwpRdkx>Y6PA1pp@j|)4FREs
z4i8Tz9RL6T3UpFVQvjcpm6h+G@1LKF$KMzL00H+&L_t(o!|m2rPXa+0g<*RcKSx(U
z?1%``?O0Gj#g4uA-n;()#05cicG?1WhI6qA4D&*sD~gH=E9{@Fq$-b<s)6zrl=E83
z)j(x)?t$jYL;#uuADNyO95%skz}mq)4vni1uUCDHhnOGeu%-gg&SnVAA~Z9D&}@JW
z&<^PUuo+_O2+hqQv>syvKqf#j4Bx7cwfF*>pGOPvHTA{uFa@9uPz;Z+U&w=3f=f%m
z73@L2zzq$c4Nwddk+64h8GmE^iI*3>?~w@_fCx|wQ&IQFDo$?o%^jU$0FVI<gKNm+
zLg)pj*Msr1`tIS7iv-XGGz_PgqYqD${=e(kKRI?cdUl`#&;<yFk#OSbARhet8U7Ip
zKp!9&eE06uw<qTw^U(lQAj1&!TwI@E&Caim_V@Gvbimr*sBU{_cc7lJfvwGr#CgA!
z8vti#jdYz(;0M5Fm)*D9KokInEZ_ifpsQPazq?BkkT4Jc?0}Gg1mFZj3=S|7;4|m|
zcme3`t7ERO7mNkK)KJS<g9(fVKw$+GFdi^l==&CP76E8&)8B7vg=_*80}DVH&@(8I
zZGdE80*C_y0~<gR&@gZSWPuEW0=Wg!3_Jj7AjQB1kOz_sd;kN11cL(k1k4rzKq^pH
lEm}pf@VKn-N4>EBvLAb1mlYUv-wgl&002ovPDHLkV1lw*cfSAt

literal 0
HcmV?d00001

diff --git a/assets/images/flags/aut.png b/assets/images/flags/aut.png
new file mode 100644
index 0000000000000000000000000000000000000000..1be1ff483baf9d14483c3c5fea30ca5c21c6b406
GIT binary patch
literal 125
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSoB=)|uI>dsZ#6Cd|NsB@@7-pg
zAY)08UoeBivm0qZj*_Q~V~EA+<OB(~22&AM79MTJb)gyw2R8^wTr+G}H0WVqIQ)@=
UU2^j289>zxp00i_>zopr0P6cAp#T5?

literal 0
HcmV?d00001

diff --git a/assets/images/flags/aze.png b/assets/images/flags/aze.png
new file mode 100644
index 0000000000000000000000000000000000000000..834b1e696beb647bb499338ce6c9c8a0fa0e7aae
GIT binary patch
literal 717
zcmV;;0y6!HP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0004HP)t-sM{rE)
z0yXLbHt7H{>I66G1ULWx{{Wc7-~coLu4U>0HR%8?=>Rb4059nPH0S^=>H|0F050kR
zHt7H?>H{_D04w#5rRxqp{`dLm12p~a@#+FJ>>Ehw0W|MFX7h24>=#7q6-DU-Ht#)T
z>IFFYw8QEFH0laG?lN2a-sSUZhw2YL@J(*&05b1FY5d&e??h_p0y6lmz4xQG_^!X{
z04nJPH~;?r^^K$G04Mc?o$o_v@nM1ODpmZ~;O;wN^LUf$05R$bIp_c^>l#S$Sa<3Q
zI_dy3>?Km`6GQyc-2VCd>IppR2R7;hGU^FC>>W$;VuJa&$LRw%@m_uF6G8s=`055Z
z?m1xhp|tm)wD*~<`L)FDC{+8_-v9mm``6$0l&bZEoazTT=>RD0CsOo%m-1?e^L3H>
z!_WNU=k<)E@mziFELZxy%I-8-@m6>Gz|HPBT>RbS_^!VC%hl~CQ^!7EaR2}S0d!JM
zQvg8b*k%9#0TxL_K~z}7?b1b0LqQP0@$SCu0MCUA6fH%HyL(HK;!xb(t-$AJX-Ieh
z60)z?`Jd*n`#Vg==fg1UtAad2009JCK;h5)xz@CV-YXg9epkPq{td9th_baiH`?7;
zMc8)&08vj4VRdS(y){Ir7r?myxO5y<o3^Pf6JbC)55w^p|3{ZX?{|x{#iBsq3c~vu
zAE<VFoqb)N5CxPSI69U2Q1bWyQ2I1UMS*QN*vtVh&m34!i2{Lf*qBlIU|PYqo4uqY
zyu^_-1P5%sgZa$;%0jj95=~_g`i6THNo|o$RwsKnq>g@o&gO=iiY9M|#E3Q2)fTU<
zEQ@$MWyYeG5v$h?o&5_G<q-l1Am9Qp4C8$OOpah-4>aVl00000NkvXXu0mjfDHme4

literal 0
HcmV?d00001

diff --git a/assets/images/flags/bel.png b/assets/images/flags/bel.png
new file mode 100644
index 0000000000000000000000000000000000000000..1c06c5fa7ddf179f6268274f97472fd677063e2f
GIT binary patch
literal 127
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>dsK<1yjj$bs)bJzm?
zfgHw?AirP+hi5m^fE-0n7sn8b)5!@EZVjd)9E-vj5B~b^@F6iIAtb?oi$|G(VfNX+
V2HlN6-GGW2JYD@<);T3K0RT*xB8UJ0

literal 0
HcmV?d00001

diff --git a/assets/images/flags/bes.png b/assets/images/flags/bes.png
new file mode 100644
index 0000000000000000000000000000000000000000..b00bfb1f57e3f511ccbc3f1ad8fff2ba78c98185
GIT binary patch
literal 236
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|e&H|6fVg?4jBOuH;Rhv&5C}<Gi
z6XNP#;G^i)y-r30LjM2%AHsO}?EROAkJrg+LZpD=UmiVq{QSd|RxwkcUha}0zhH*>
z^WVRJKXodQP~q;|2o(1Aba4#vIG&s!!TN>ijaP*uBlGFJJqHp)82^eCJPhB^(D+$4
z&Y-dJt6rRd!K#KjE{lJUS$TQRq<>&)4rFciV4STGH^Ct4>IGf~1~dC>r_YBR*#tC}
N!PC{xWt~$(698IAS2_Ry

literal 0
HcmV?d00001

diff --git a/assets/images/flags/bhr.png b/assets/images/flags/bhr.png
new file mode 100644
index 0000000000000000000000000000000000000000..135c254cb496638361bf40c707acac022ac8ab8f
GIT binary patch
literal 567
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+Kpy2ZW
zpAc8~0-tk&YM)P>{dD-m|NsC0{rd+bfg%v{ilOsW6E_I^=hNr!x9on}-1p<|gL5Jp
z->%)f<s19$>Wy3ealf9wJTIpG_s5SP_aEH}PrKzGf5pJ*l7{uu#-4LRYL6>hFKgPI
z6H@>8>-Y2SsTY;Z?#1W+`}6lsXv!5mhYNB>=Y%zWK7RJFu=ZK!<bS_@eZP74<K9E>
zH|_lM<?EXzYySQDbHgp{!>$AG)^9s6se4hy9O$IGvDu%Go&vh|`;FU=tK09Vm;U|v
z^ViGQ@78R2w|2`-_wbwU5$8p<&WUQhm^kaj#M#zeY!855<|zsC3ub8R2ZFZ#_wW1r
zb(*VPf#UZ(T^vIq4!@mtl#khv$7Q>Z-%KDVJpK3o`^<0G!fZ=SCsv*O-4K{`{zjNc
zr;8HD>Yt+B7gH}cHgey1Irn2pY3lw*Ka>sx%6t1XWNf~7UXju2j9SNmvh57}3}og`
zRQh&{_n1KAy9L)$5~QQ&TD@Ri^-VkQ47<xj0~LYq&l<&#^qpi1Xm(h~Q>rL(#%M$D
zJ|C&x;)|0%G#9FsYku`-{J@<c_|a^U+od%%O>1-%e3%~b@QLIsIp{1Z_xe`S&IN^R
z;j=rQcC9P_+9xCN=g7{NT91xTOf7n4yGcc;Q(#^LQ(g0PnUW7cpE7v5`njxgN@xNA
DZE7OE

literal 0
HcmV?d00001

diff --git a/assets/images/flags/blz.png b/assets/images/flags/blz.png
new file mode 100644
index 0000000000000000000000000000000000000000..06b23f161a3adf4e224848390dae6b9cb6ced71e
GIT binary patch
literal 1777
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
TYF3V$00000NkvXXu0mjfnM18k

literal 0
HcmV?d00001

diff --git a/assets/images/flags/bmu.png b/assets/images/flags/bmu.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e253a8e64a0ccb0499c4f7a901aa0f1416afb1a
GIT binary patch
literal 1518
zcmV<K1rhp*P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00093P)t-sM{rCh
zQmGwEr2{pZ&kqm#>gw$5?92cF05h5Y|Nn+lQ~CS-{r&#_{{PY)9pZ<I?x?8TQBix9
z%HVKu(G?Z%uC8W<!Zu#7*Eu;MO{TxA!r0*N2|At1r?|<~>C`7Dgq_ZQki*?qSHu7S
zFO?&&mX^E#0LRJ8F_|Wv1Ov$c0NqqnHBS@y`T4j20EPhps09Gb&d~h-|Iq*dxT2!2
znVGbppz7`IEngRWPED@@0f$so&khbLnI^NDnLBnTER!KHj~|^xL?)gjTcuK8yxd|j
z3wNcl(b3cD)!1UV**SL@ZUO*VKPGW!Tj%TRc19$u0R^3$i*!>wjvfq+wuxt^rgxLb
zZI^*^XEfPGMWvpev!0$KejaWh2d<l&C~X>n6a~Qn0Kb}=hz<kV)zwEp4qqt-hY$ph
z4gx5WBsEqOu1ZS4006^`j3SvHQ(7@9q$wJ6Cn1w0n+gG89|x(7j8riU%$b?71qCaU
zAV51HE=DKx_4P+ZAbtb{DT*bdRaN-$@MJ?)E1D*ahJk{8ZZ=RcEMqMkX)I5kN95|}
zXq%|3V`h*cDM(pBHE<#9@$s>DcUD?gv{g&mq@}a~03>P_)0LH~9vxDMjc<8;UaZM?
z9}?yO0MgXfKan;+IyIxGq|yKYy}-J3Iwwp~5B2BfTP_c1IT^LRw@gkufp%|~j)`D?
zN|O)(m!6ucsGYvMx_p0Vjv5_=h;d&?FpPO@)XK_JI4gi{VUm`VMq3tXw$pz#7hyIV
zV5+pK4Gn`>9~3M&Za5RSwz**{9o^;IX1?K-aCz_6)h%0Xi9QgO5fPF{6LUx{RaQjK
zy1I6>rEPUeQJA)qQXE}S4t8{Acz9WQYdF-_%xRBRl8=O_sjQYuPFkIzxL83fOkaMq
zv&O`~x<p2ben?+HFTqq%FH1|Qs%TjY8Lh(0l$T+yrAnA97rCxYzA-e`y1HXoFG)ly
zT}>U5n321wR*|o_iFY}mvU+}iPSv<fc!qGoZf-(fTl?$)lf*4X00001bW%=J06^y0
zW&i*JoJmAMR9M4fU>F6XU=%=s5-Yb5GY1s#vaoY9!8l_4d;;uv0oVXx5m8P#Moa@F
zr6dGdd5AE8QC1$|2!sJ3>p7*xi7<eJSrOp~m;n&$6=XPwF@S>u=m>3yBcKLAtp`dG
zX8^(xU<2UR6K??A5g-G?;ntI40MrqjKm(%S))Qv{Ckg->fC7jxz=oZC05$-x3aIIp
zY+zuXmy>J`W<}%l0y_%|mlvYY8p5lnRMSiavrI4pQAUA>RWJ%{fT)PDA~Q-La)EW#
zI_cN@*nyd57zT(-a|-bBhl30d;%3#Bmu18>V8=l<eKjXt5HkkN0I>BEQj$y{12`Dv
z5RO1L;Nn?hW2;6Z5HlXt0EqQs92^h>IG7QRfE%#<l#!=?pq^$gXOkx{rzx@lFzY$s
z25=x80XN{}tLG1{o;!1B-;};)ZWIIH)*~ALc7zhp5pV-u{|k<|A8{${fZyaET~1Xb
z1K`%97yxqw%mAM6VLx9!dU)l8m#eEgssV88(F}k%0%m~GpI^Vfym@hY?;NjL{r)Hh
z5R+uNI6r=P_x{t5%ZC@vcAq<Q5;y4v{51}F8~N0CzgzICka^Q4+L3I)6Q9rDB5wu+
ztX#2X^?I!tW+WP5&3W(H*T>iIoIkRC?WPUewoEl4(E!Wi{<nhE?;85;Qdc+J7__9j
zj6?%`T|z@|-?(s8eZI%m&FdC)xfGCSK&i8X_ceoKyFCmSEj4iSuF6j*(Ew!~=bd_i
zdnUBDO<%Uypt{f^i9`d~bIUv1J6as=?HwEHYKqeI*hw{jU8_XLRz<}@MMa}nCsT`^
zbOV6i$gr^0(8$V8Q6{BOMFDDYu?dOFq?O8OK+}rUVx8i8VblOR888Y)!6*O%07V4R
UT)P=S+yDRo07*qoM6N<$f`F%)+yDRo

literal 0
HcmV?d00001

diff --git a/assets/images/flags/bol.png b/assets/images/flags/bol.png
new file mode 100644
index 0000000000000000000000000000000000000000..4996ddbcc30eda9b529fea925dc6f10456e3efec
GIT binary patch
literal 668
zcmV;N0%QG&P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0004TP)t-sM{rEg
z!WsDM760oL_~R7$<P-Sg6WAUF_u>=)dOi8<75L&5`s)?!-4*}p6!P5^`Rf(_>J-|e
z5&G&C_~aDs-WB=d6YAF+`05q><`eef6!z&CxvdxR-WT-X694NHw=@aIvJ}r$3I6F6
z-K-Jo*&F`n6Y|~{)WaJ6=MlxWD*ELVkAxTE)gzvt8PHM*!7T#9tPqwj2eD@k!&?lt
zH3`SD6!_{E)M5(EzZ~M&B(=F2$hj)2ZWSab8}8W^_vRzilL*uw081tn;hh5i>=eDI
z5y3J8)L99ZFbCBd0Dg%vst^I|z7|ARBQY)!sd*gAk}b4u55!>%Z;fQxp9xMW5@LW-
z;-LYjqc7Au11u~lWMC71cqE~R7|3D;oS;Rj9Rf~WRA7HgLyd5X!AYfd9g56}jM0#!
z!C)|yes_~%Ig@ixo_n&pC})gCL!*Kvm48Q$c-b}qMxT6putP?dWk;iatDG2WkVuZX
zcyyBGL;wH)0d!JMQvg8b*k%9#0NF`IK~z}7V_+BsqhJ(30Xqd?)PPX~Mh!qRfP(@+
z$N)(-4sCfp7P1YH(y(^5*OTFAA=3aBO-sKRe>)vHR`LvBQ@8SsO^Wt*(3NE)#{e-^
zn}GPVqLhR{TP<-`a$H~@lvq)oo>36zV=PUU7r26pOAAvovnstzn8-4K$s;PSq$)or
z(n()}JQrBFM`Y)gg}4|f36N!gu!^Z?SaP_tk%ABpSq89(GMc%CIvOf6^0JVbkVKT3
zxw)AISy;%<3&dq6P71)N0iy<t8h~WLC>RB!00;o`?qpIZDJ@R`0000<MNUMnLSTZd
CQy`oG

literal 0
HcmV?d00001

diff --git a/assets/images/flags/brn.png b/assets/images/flags/brn.png
new file mode 100644
index 0000000000000000000000000000000000000000..bd1d1cc9a2443c1d49897f676f7640a5daf1f7cd
GIT binary patch
literal 1957
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

literal 0
HcmV?d00001

diff --git a/assets/images/flags/btn.png b/assets/images/flags/btn.png
new file mode 100644
index 0000000000000000000000000000000000000000..962e5e5bb46e90ea42ebceaeb754a7c7ad57b26b
GIT binary patch
literal 4013
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
KreCb*6#g%F1Oa{k

literal 0
HcmV?d00001

diff --git a/assets/images/flags/bvt.png b/assets/images/flags/bvt.png
new file mode 100644
index 0000000000000000000000000000000000000000..4acde7fbf2e00cbbbd9de5ff2716f3428bfd3fe2
GIT binary patch
literal 147
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>ds|NsAIP)q)zVSa4)
zIZvQCV@Z%-FoVOh8)-m}si%u$h{fsT1PQkWpu+!&tC#(2Z{j~3-C$~BBBCL{#meZy
qQLxsDkvl`#q3y6+*co1B1_s~BH_RBfiG%<RVDNPHb6Mw<&;$U|_AFok

literal 0
HcmV?d00001

diff --git a/assets/images/flags/bwa.png b/assets/images/flags/bwa.png
new file mode 100644
index 0000000000000000000000000000000000000000..5b7eff92a31f28695c645d39181c4aecdc408f3c
GIT binary patch
literal 134
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>dsrK@fOdH?_aS1!Ha
z4rDQw1o;IsI6S+N2IOdXx;TbdoK8-VaBDCXVP)wtVEp%A;{h}CbuEz%2@6;ZWXujJ
cXGt(JaPDB{xf%0S45){})78&qol`;+0JQidng9R*

literal 0
HcmV?d00001

diff --git a/assets/images/flags/cck.png b/assets/images/flags/cck.png
new file mode 100644
index 0000000000000000000000000000000000000000..d255ab91ab79c85cdfa733e57159c80c0a231976
GIT binary patch
literal 1139
zcmYk4c{Cda0LH(F7>UHHT0vP|sbeeReAabX(0FD+>KWFiuA#0{Gu?Yc#1$E#bDu53
zv^qMp9d)1MIa+a4jBV}Owc5>E+q`+R^uPV_{eIv3{{HegKAu#vE*SuoeTwC$u*>VH
z5*4hymAR#mTH>jXlL6Z3>kvvUX?lQ?GRK?i?wRPlzX@U{l=wg*py2-sfsbb^KnB#Z
zU?|2L0t`<<MSw?3AZ3D<4SGKQ-GF%!&bPv=2Koi~uolXh(9DHL70imjD8!jYq_!ip
z8O~)0x{9Q0_(_J|agYRfCCA_ED7_77Kd9MI%>r477pw5E$K448UV%XYs=kA1A#RW1
zk2O4AMpO%A^LV)iBQe}6aOno#DnQRDI)@P<MYt5n*PxpZoqTBLVPg@TI`BKtbQeF%
zP}_^|XOMFf1C#huj_4LN_an3k^?f*$hl9BYXu$e?aO<Iw4RRLVDaPU)3cIl|3->CB
zzQx`TI9U#-QVdPv^LAKBKoR1DN=#0}@hjXM!S)(PrV!HtmkRKj@JS<rucD|MtV;OQ
zVs{;H<{<uSY^~zy3Z5+Ep$v7sh;2n*Cc09fE5eUGc&{AQKIk6BjvVbnsPV(nJhmU;
z`6?_W_-h@5lh~7^H3^QT7?{8}!+1K2y$yIvpeKS`6#6I7H;%P?u)2t2g}6S5NGY^(
zp_zlqJ5U#5c>%5!5O%`41Z2OQRK-ci7yW$vvA@3`mAaph@taBTt|36!XR}<nfg@o&
zI;oMTC03&I9yOptiMkoyh(sejo^y(Tv8!Uup7}I9yvy#qX~PIHmtb_C|3HV@^3hhp
zL`&`R*y`zn)r644VzFf`U3;#Fw`DsK#?M3JWr73Io30agT|3C?faBrNt<f-kZ&7*m
zF$W^UhIu@wxh0{$D*A=DjsFQo9>s!3Au{5|(^Le0)2n4koxfUFNen15aZseZEWlEG
zMpO1YBG!#;$F{d;pLtt1Vm^dJ5@kh{BuCOyY?*Dt+zYZrCbR8v?ia~dqRS7RF7c#h
zxk(600sf5C3$~)|p+$Qp(}63nqrB{}G1eQbkyHs{_(sO`SA11!1yjw#!_eF;*n(xE
zdCuihPKA%Mh%n=Nv^`GW#m$n^CK@O#UQm^q+B!MYrqpbrx1-E`9kg3--N`QQbfHOG
z1;w2Pzx=+!8gB~UOLOJ0RilJG$4|iJB>$hBFRd)Zy!eNjb5qkEC6=M#cH>gd#i0Y9
zpLr0+#A3O(HBCb!L_WJz=R_1{rdy1Z8Sm`m+49?!pD2_3yiC+NG&@&cdPO`bZBnsv
z^#dnWg<hARDe)M-z5xN}LX9_Y&nv<Rw$(>sdW>X9Kl^?L!%JPF!PDAoG*jmio6RY#
s^rJ`S0|#S3d6&eG=t{FAdkmTJi8!kslkBA(6{0u@*zP{88*V(of5vX4od5s;

literal 0
HcmV?d00001

diff --git a/assets/images/flags/cmr.png b/assets/images/flags/cmr.png
new file mode 100644
index 0000000000000000000000000000000000000000..2bc6ad13c4606109b4ab2a5e128aebc378c477c5
GIT binary patch
literal 402
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+KpkP;k
zPl&5~fzKI1HTy`PHxs4*TogMesCG_Jm7yvQ$Oe)S21Fdlc8K(OJ5~CEwCcO*QhzRr
zo)=U7eL?Jwzrr~Y)z`h!=Y&;1ERy_rOzgU)(#sZ^Tds<~&x)OwR6Q@D`m{*)X`$@%
zYT5Ims?Td=KQ5E}xK#3SmfYh^xj#S?d=&3^E5^lII{{tAQxfDC%rGAe-oKweb?Vu)
z1v7x+(>z@qLn02py=KmT$Uva&;f33hLesyvy?FcozwIVNnaTc19QUm&Hp$(brV}fm
zU^3yF_Pq*|<g@C*_m;7XMc?zQ)l|7B1T<$q)3>z(9m$FlmKhxoYyHYLsrlN@g)y)7
zK3X4q`J#ho=jN~b4!w3fX3Lr%@V(kcmtobjvV5(2h22xUrd~fI-LdF=*Lxm@1M&=y
e9EBG;eqr0w+_Y1+?$Q#V$qb&ZelF{r5}E)C5~Z^M

literal 0
HcmV?d00001

diff --git a/assets/images/flags/cok.png b/assets/images/flags/cok.png
new file mode 100644
index 0000000000000000000000000000000000000000..49386516dc346dd150a2175918135f2fd6621b29
GIT binary patch
literal 1416
zcmV;31$X+1P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<TYEVp6MMrQ<03?0v;_1>OH~=4Q&lD@q6e|E9Z2%;F03>}DH;B+2
zG7v0)@YvqdWq2n>k>6%@zQNZMG=>~Ji_zET>YAkg|NrX2%KrWR)ig-iNLtO*<?ZkG
z4lso8w7ghvsdIz003?0S6f6J#|Jg@b@U^`D`}_Os?hP-4&(-D(E`wKZsRJi}8$65D
zFhmhEh6X8sI#!!{jk|)BzZN%$2`qvyO_lP)$p|Zf0wsO~D1RYAjv6|OElZRsNRoMn
zw%L%M+l-s%>hsepK<w`I@bdTDPhi|uX7tO@c!##yPG9rH%Gi*g$P_L9{{G0&;}9~1
z+1~4fmB0=#gbFNz@w~%4Sep_whD2YWafP;PfV3GoiGGm1RBfos(&QgMjU+>lCPa`n
zQkdM~?Q(^;fsDBJ)7R|p_0=^=dW^f(lcYXboQ|HwGEbM1p~nFweb(ISLtUQ~HHWpp
z*(*ttNn@g=veB`;*N~vb)7j|m@b*Vxp{%#mTyw1b{r;!3(&_B<ue#R6&Ebfc!t?d{
z5i^ByhPTnz=Vf}ZVRx?7Ph$P{_i=)>_Vo8ZTAlOe>TQ9vPG_Zyo5YEl!*7GNPiUoh
zi@MI$=G)-xb&0u?qR1FHiK4I19zKj_e6e$fxLtItvc1<>aH<F@fuF6;KwF(?eX`~0
z@|&s5Ol6}qQJ3A~?WwiX_4fL_#@)BU+I5JyY=E@E%HQGT@FPNwt+>@vYNpTD=Iq4G
z@3XquMpzv^jDnB5_xSqy>Fd}-RpaOJ?WnQt-sJb&-qnnq>6oJZ`T5N&Lgj&t-(_^*
zYI*Ibu;1hE$j#uZ;Pt2g001F$QchC<cYl9qfA4Sae}8{}e}8{}e}8{}cYp7H@9*#L
z@9*#L0fFMR0007)Nkl<ZSi@sr7zLwX6pR8G5S0)U5$1#dE+%GHZeD&UPe@RJm5+xL
zA7BI;AgL1S=W5)l2m)GaN=i!Vx?r}3r;nbOxw0Z&zyUNsAu9uHgg%M^Q0?hPgbm;@
z?SUHsGXSn#16@ZS76TL&;YRER8(@cByP={*Vnkq}wFQucY=FEr5OkhBee!6xatqji
zLnls|D=W8mfF!gL1}v$Wsa39AW?|e|fntE1DiYWUG~ghzfGSL>)x0X@SjC(mW5o{T
zh6OrE2CymN1rUWR6QdNDwZ&QmD+XJ{#w=2tA74tE0g-j};npz6=*%@)Sl0<RKuQG(
z>;h`pk1U`9Ru@v<u)+{2JeQU&uQz}hAgu`k$;!&ghtu|f15sJ|SXx^58L+q}ScA1<
z#43~+DNItdMv6v7jZ7D1Z#O-MJzxWxos>P?ogGv4VaoH1f$l~z0LUvw7y#35uK`U+
zrYR^!<OV9Y+o2^Wpjc%I!~j{icBG_?YQ$v!X&8yP+20820vWh=l+0w>1~CG}HUmO*
z01*QjAl`NSh&?pXhV=US`u5vEIHoBF_U`BcN1}lph5@!#Q;-4?KPZ~vVv8YYST#L>
zNCONaXS6K95Z$=8Aj*nJ7bwPrM`MUZ>uw<03yL-dThRTGWD{aSya5JHo0HIlB37@n
zB;Ek6?aGabC?X~6m75k5Z$LuARz*cal)_18O=3Lp1}G|;*lybtRs`kD4vVX{GeIsB
zi2(7H%0ZT;`QeKCI@LOP%5gS|BpRStGpklH$3I9hFD^zgs$z~JsRmdED+XxKP&QJW
zq+BqyRWX2M1HfS7gzV@rqioE2fmmPyih2Wm@(sXIwNYvS3p)jXWwd!T3P!;wfCB(7
W4pLx#hQQ4L0000<MNUMnLSTa3lC0?f

literal 0
HcmV?d00001

diff --git a/assets/images/flags/cpv.png b/assets/images/flags/cpv.png
new file mode 100644
index 0000000000000000000000000000000000000000..0683d931f40253e3cf325b609554383517f8224b
GIT binary patch
literal 297
zcmV+^0oMMBP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0000yP)t-sM{rCk
zP<#LP)&KCcEmC<)WN6j282|tO&JiX6IFtYO(*M*dz^5d`sUr+Oj0ruC|NZm-*+2jN
z_W#&C`WJ&Q00001bW%=J06^y0W&i*Hn@L1LR9M69l-mk`AP_`LQ@daP|6dD?5?xW$
zUSiIZEX$dNVyX%NaMNV~0R#|)1Wl7C5Ys491v*>Gs5=OO&R*(zj=6)nKxez}Sb@%V
z-(P-4_0spsfto#70)A}VUZG}Qff@#Phno2WJ7cT8Ld`5eo55cM_z%i=qS->}jTGCA
v{zfvJF{P2rW=w0OV0J(d&Mw)B0Dy}VO50DxlNzXC00000NkvXXu0mjfuugvy

literal 0
HcmV?d00001

diff --git a/assets/images/flags/cri.png b/assets/images/flags/cri.png
new file mode 100644
index 0000000000000000000000000000000000000000..029bbfc4981c51c45fa2c46419cffc3eff64a0f2
GIT binary patch
literal 136
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>ds|NsAI(5^oxsFtat
ze-S9oSQ6wH%;50sMjDW#<>}%WVsSb-LBg#eTa+upL7nkhfQW#DG~>Vj8V?SC5L@6s
ggD;>-(v5*3dclmcD_e?Wfw~wxUHx3vIVCg!02gv5{r~^~

literal 0
HcmV?d00001

diff --git a/assets/images/flags/cuw.png b/assets/images/flags/cuw.png
new file mode 100644
index 0000000000000000000000000000000000000000..92a36b728ad8bfae0f3b1e5cbcbaa61322b18f3c
GIT binary patch
literal 481
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+Kpx~|m
zpAc8~0-qnxMJ}FH`T0VGLA%~JHI`Ak4#)r^s7PAurBf>Z|Nr;OSW?ur!#rZvzkmM}
zT>F3i`m^ukJ!aj8_n*GA=ruM?Kfq<&a{l^rDTki$;#F)0O^iDAs$LUCZ9D6x>^pn)
zX?fo+*OY~VmhEN{v(&sM#Z;{2GjF^5=-t_?&o1435nr|L>$hK36ZSCaG?e!26t?b|
zy8PtS<)<`#Cttt&YWA8lv)7z`{NiKvq`e;Li@$#VRX=54qEpK(pf9*eg8YIR-oO7p
z_5J(#@84@2bFu)6ZufL?42d}W_L@6ivw?_fpn^lgk!9Dv+^f$2eLrlD?uQ8-7xp{z
z_x;g5y-6i7#5L%(!zu<I?h_h(9Dxr?85@5KGhQnG*0)LJ-2Ubt$8NAoJuIn}5lEQ7
z<oMnE#HM@AjqFU>(hN~^&fgV%{@6hMg6vP9EhV4&4elC==`<LBh?&oNLh;t&n`*C^
z9d;*2+Ad%6y`iCqQI@fUQNvfkl_8Dy#2;=4H-<=tC}xkvt9={-8U9>cvcl^NYti21
VoW(DSeSltI@O1TaS?83{1ORaM)>i-k

literal 0
HcmV?d00001

diff --git a/assets/images/flags/cxr.png b/assets/images/flags/cxr.png
new file mode 100644
index 0000000000000000000000000000000000000000..e644a49ea96be08fe5e2865520ecd6583398964b
GIT binary patch
literal 1202
zcmV;j1Wo&iP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<TI#5hhMMrQ<8;L>>U2gy(tQ?9$034Sbib4P!mmG>h03odiJ#`z2
zLL7=h03oga#yJ#hU>k`-1~--d#W@Zwu@*G6ABsUflR$W)J{^id%D6l7!Z|FCK^}@h
zytF%Tpg#Bb`~oAbAU(G~Six$2&rO#=9Ew3BKe*k!I(DHxCX7L$tvptlKME(PP*sR?
zp+1IpZ&z7`<i9#<o<34mhm5B^Z=gPTqCWh@IU$Qd@xnRq!Z}c9#{?y=2Pd!A-0})3
zu#=(OBtf_ZC9b2bJUmsvm8v~Nlt6u>J~NO(FONaZxH?prKcukXil;qKX2!|4JHxg+
zQfbHg`~4+Bxg0sRc8AhVmq4w!<OC$HFG{?WsXcUt(lk%L5;3y1zvmJ#vJo({yv6C$
zx;kN;Kk4lFaD&nG_4|XRJ#~lD{{H@{wBuZH$_y*83@fo`ojw&av%16S8aTCEnm^pU
zI#`)MUYkGf@%p*K=wh5dUz<N!nm;*_Ky05rMwLM5w?k`w&t#oH&bc}dF0s7C>GAXW
zCyYTuTf(!kJPawP{KYv)l|U|zLF>6fU0s5hsy)ZIJJ!28Dvd$WxjIjmKZd3~zqLE}
z!#S+5JgToe<-a=GygDU}L5Ze4jeKl{r9Hj0JGHVqA8%h4LXKi!fRBA^ji^2S#W~`>
zI>oj-!nHf}!#PQnK%1*PnyWnOxkBl;LT{fwTADwXsy&vfJ@~{qIFUedpgym#JfN&R
z*t<F{jzK7mK_ZJmnX5g|WJI<A000bhQchC<e|PWiXm@Xa?`ZFU&cE{j00IU{L_t(o
z!((6=1*2dTi~<;7V&otnumKHV7UUP;Aq8kkAlNKG12}nkNi(8BwiVp~(u|OpHK`lJ
z0FsO_;hP|hX#fdE%(mj|7sX-#@kYoA@fl$?fUps@vQs9@@bFCM>%(S%0ue@Nbn?wK
zlbFHRj>Q1AjO={EMra%I@l93dYs6xJQf8VWnn$F?wY0>g(bAF0G(J8)DN#%V3JbDC
zP{Tq_iVvh#4$To=Ku7SUdzYx9he1v*YH*qgf%Gq1A!~~64Uo9HPz9D)Kn9B}B|!>T
zTCBF5h-!d1P*}*Tln1*334y{8#$vt&^CXwA-OaOgl^%+I(PE(_Uoq_I00=^Z;vkGA
zd}d%pd$tR$LDnzk9}tF?7n+0-`V~^;ed58ax$~FK5d)^09ejLy5!yYYB$Lszvs!bx
zBEp2&kYEU-7Zd_k+jw^J@onI-Fsi9iQ7LkFcJ)AZ4a9)9mNF%%ZYLzabo78s*t}~C
z-@1hYJgU`|dK!6dGN{1`^+LTeRF9*B3z7-O=0F2BZR9gI#+f?N15wz{8aX_5>p*T;
zuZuf@qZ?prV~-LeItKds20D0hD&B;I2{4Ty(Ev;%NHzf72vh?iL`XIQ#Q>4;#7I(I
zfnq>Rio74G9zpejax}?dK}H~=8bOf(AS1Ye2C%YI0Juh*N26dAi~=|S0A|UcQ9Kn$
Q#Q*>R07*qoM6N<$g2g8g?f?J)

literal 0
HcmV?d00001

diff --git a/assets/images/flags/cyp.png b/assets/images/flags/cyp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ba5246809c95c86c26bf5a529ca841abdb95e69d
GIT binary patch
literal 1128
zcmV-u1eg1XP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0006;P)t-sM{rF4
z|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0|Ns53G5-Dg|Nj2{{r$1JrvCo^jhcP^(Te@g
zh5p%|{{8y>wLt#r$^EuN{`TqpvN`_u>;1Jt{{H>`;<o<Vr2V~B{^GU$yi?QI&Ai03
zS86}H!m)LQVz|Jr=<DVEu{e{UgzN3-uD7H9+M@l&ZT-%G{`TnoyHNi7_Wje3{^r2_
z&V&8MYyR-r{@9%Tx=sDhg#E~J{`c(u?9TnTNd3!s{j)s&{Q3Ugs{Zuk{@S7au{ZwN
zpZ&d7{_N2H`S1STto^`U{k~ZJxl8@dg8j5V{`v6zx=;PUUj55^{{H;^wL$*%=l<rt
z{kKN`<huUp$Nu>3{^Pj)$8Y_@WB%Qz{^!BV(Zl}k)&10x{`l_w#AyEe_5I0p{l#hi
z*P8viQU2(~{QUfnoPT$QWY5*fo2QMx#<pQ|OMi}SsIr`Bc~hjWm;KR+{@ti*d{(~2
zwC3sK{j)p$!C?K(fByUQ{QUc`xTJK1VT_r4S!_Yn+0L1zi_g`_^7HU~i)!uf>VlAQ
z`TF>Tl5$#YL&VFxgpzZLn0n*p-+GB>hLm;B)W~;-WXaINuD7CvlXUR%?zX<GQf4}o
zp@ngQUEAN*ae`iuoq)2tsJX$f`uq8(v77Gj>{e+$`}_KNiD&!!`}X(sn52r8p@w&d
zW&O!>{neEI<hk77*WKaR-s0M}zO2sF$XRScJyRjR#kFU7QvUSf(bmhBqKMw%*<El(
zg_CuXpM&IFf7Sp1019+cPE!Ec+W*gihS%Q&<L)gs0005UNkl<ZSi@sr7zLwX6bu)@
z$;!e`Heg}pWME^a2(U3QlBgpg8->fnz(I=cv}DE1XcQ3+QVd9n&yr3-6C=R@?g}oh
zSSe<54X9U8<dT==W+vVMS!V=0GCft3i>sU)i!$5>xNupD`dAC<3JV2AZ~;M0Ee|tE
z26%CyfD9Sz%5WQCg=#<)Gw}v^*c<Ab+lrzZpg^PnHayIZc3fCMXc%z@Son#VabX4S
z21FSUAc;-0gDaP$ydH635Qs&;Ff+H4C$p3YQ3eEKF+dDY3dJyhI}TmDv=BEb1~AK^
zY8Q8tz?(-f4dB_hUK66%-&D}p#E3v9!<rIzZ>Wn27x$GQCYNFwps@w&6>qdq=S?Ke
zfXzF$?F4%z1U38cbvF@b0I!a~R&5M*tCp=%n?$4m`}ZE)wFh0@ytz7a)QJtmeOd?B
z&hJ4I;9sq-wQ?!(v9M|Tx<$QxC2;;Mm4ypbmkW>(jr>d6+xS$K%L;+)jw!RJPo23~
zdj&H|B~n*z9$#reQ9d*O<cXbXGo~q%mXN?eNlB%+y1B8xWkM@2sVNZ-1ga`E2&P1Q
um1_=j1EHkMNO|>6aRXx%jDk@xTmS%+KWr^)MU)Ky0000<MNUMnLSTaO`;GPh

literal 0
HcmV?d00001

diff --git a/assets/images/flags/dji.png b/assets/images/flags/dji.png
new file mode 100644
index 0000000000000000000000000000000000000000..185c5322b4f9c75c872460a3ec00e6d3949a304e
GIT binary patch
literal 387
zcmV-}0et?6P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0000{P)t-sM{rEE
z<-B9bbD7HTcDU*D`TZueJZiG%|Ns9Itt;#J?#|}-{{R60;o<*RSO3h+%;oq0_V)ia
zHvj7C|MT<zAtC=rNdJU{|0*i~($fFc)fsTZ7XSbN0d!JMQvg8b*k%9#0N_bPK~z}7
z?a;{*f-n#SP*l{QS(IJ>|3jrLNoB?9;hH{h<8@D}s-&dkmq&eN=L?AQX(u2Ad&CN`
zM_7P6!U1?ATtJ9>y%S)J2mpLU1fU~g034A5pb<#`8Ib|#BXR(FL>?fH@PYRW9^nJi
z1dnh4Wz0Mqqp%SU(2a7**kL2Q6SR~%e9GIg*^CFY!_Wr*A1)0YP`dB6Lh1wHX+PBZ
z@C5Aoe*mR^1EAIC0b+d)AlGLAdVLZ=>Qewz9|K^01fcZ+fY<u~quvEr^$x(Rw*a?(
h1=#f~P*PH|<OBZoOMkfqd>;S+002ovPDHLkV1iqMu^RvY

literal 0
HcmV?d00001

diff --git a/assets/images/flags/dma.png b/assets/images/flags/dma.png
new file mode 100644
index 0000000000000000000000000000000000000000..7f61af95e6fadfa4470974e4d8458453e325d924
GIT binary patch
literal 1224
zcmV;(1ULJMP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0007`P)t-sM{rEr
z886iwFx40?|NsBg8!*!xFaQ7m0Bb+|(H7SmFxeU~*c&j`8!*xtF4Y<@-x)B_6E8qV
zGwBsC(-|(%8!pomDB2k>%^EE!Pc+jOFx4C{*cvOs7%SNoG13|@!5Az1&=&sv{o5BX
z+!!w2MONMyF5O5fvK%KhN;6eUIkg}zt{f~$LNY8)G}{_59#b{g88D+IF3TG(#TF~Y
z7c0&jF3=e*)*3JXT`-U<FEUFs+7~GuQZ%9`FBVcUnqt&*H8ARcjQ6%0>vtov9W1UL
zCcqRf%^EMj5+qnYG5FKh>2D;`9WWeYJ;)j@)(|Gw882fwFeYI@dNMF~Gcd#xFZZw-
z)e|v6Q#&M5HHs}S+dwN)O*z6GEwvvlSv)b`88H3#_%mBRUP(FZi<X5hFUAoh`r6*u
z7AqlPJiZ<-sv<3xDKFnpVEfJ&C|*4F$jwbpIn)>}N>Do56e=!UJRoC0`pg$dQ99=q
zFa7%ZEnPnKts9&tF1H{q-%Vck&(qZuDdu~I-9Rh!rySB1E6y1%=W-*}7ctlrFQp_d
z))gwTA}-ArF6V`i))g_)6)NRwC9xbVv>+}mQ8la_CdL{qp(ZZc8Zf3ME~+Fhh%PVJ
z8ZN9PF47w<))**AMKX{oEQu~K(;6zeCrj5ED%Be?pHr-zD=*O<IXF#3qDhsOCn$nd
zv6M!ZmsPdQ89F&kG<RaPk6E_WASqs1p1fy6*C8#yBt)iAsvTNUh+VqEDO931b}?I9
zs8=G>9y&T-cE}zt(j6!VSuP7!I7CoeSW|D;8#1Lf5W^!Tq$V$!C@#G#Qg}sf0An)U
z8Zet6Fq$?CtRgO)Bro7WC2cqvYDX;ADk>3SFTHIOg)=J0t`THh4;frq1YR}YH;<qI
z0004WQchC<K<3zH0005gNkl<ZSi@sr7zLwX6hHw7F2Kpj$qoc8EG#&cj2bX%038g-
zukDy-YO2%USWTV*1?rtr7V~EFi}f_rkYhkmahE7BpS7Mjm+?eqEz%8$6z<lXr9XG=
zBDTailJ!+3q#EF-%vd*dhWN(42W7adgtTX>W#Kk}6AMsOmt*3Y&b@W}mJK_X@w9Vu
zDaR;cQ-{+4XE}d)CLY!u2lj7UZ!XQnlpP-tPLcsG?wUc&OsqEh4((pIREAeXC@Rbc
zrvdC(fSZS|BO|Nyl3klESFhq_<&F-O*TAL@rvVDSf%0su((_mBIcB*sk(F(x3Y!9H
z2C!b#XJchuu*Tu|1zj~(Hhyk4S&|IU5lPE6WMy4;&f&ySTTx!d5HC?zoCdI90jcQ*
zLd?9ZCvDE(w>L26DNfMybi$?%rvVvaIohmT%TFJ<bL)Zq;h9VxaRJ^W8K9I`%EirR
zc<S=)yZ5ehOK>w~sw&|$0Bag8SD86w;aPsOo7ZkwUD;$bQ!SX(%v34dYp_^=_v$67
zi!&sRgkwq1&RWcU##|!Sl6*X7ZN(|%6ewja6Quah*zt=ssV0+Gq*b&|(l9ld++3J6
mS}%+mFcb_J1*2dT0098Pi?3eDJ`{TZ0000<MNUMnLSTZh#P1vc

literal 0
HcmV?d00001

diff --git a/assets/images/flags/dza.png b/assets/images/flags/dza.png
new file mode 100644
index 0000000000000000000000000000000000000000..34228422334bbf6807ad5b7e2b68288aa1f81ec2
GIT binary patch
literal 518
zcmV+h0{Q)kP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0002SP)t-sM{rCG
zbUe%wCbk_Zc|0!%c03AoJpcdy0D3*n5hj%`EVLdeT}w0Rm7es=&;0T7;&Xrf^!5Gs
z_vVC;_0QCzCo82UD=lL<TuU<~XE_~fIu>s`{{8*@@bUin`Sr}v{rLFfd4&4u>+Pwr
z<9CD9EkNF1ZPO|}AZj`E%FaquHTBKW&lf9lKrr~*-YI1`&lD--dx!0%t<fJd_SM<<
z*xUa6{Qmp=cReubm!ac!g6f*1`sV27hmq%rl=jlr`Qzp1jFteE1i1hJ00DGTPE!Ct
z=GbNc008buL_t(o!|j#F5`r)ghDCu0HU#Xwiw%3P@BdQ9was{N++@bnekTsuZ<73*
zB@iG8;z9T;>?<T7!A}CscWrS&cNj7_t;tA8psj<(gYnkJ3koTyHDmEaA|7kju>vi9
zE009=`@&?SiWI0&-+QM}!3pwk{^%>lK4T@605)LiPr<InSQ#aN{IbwUhs&uyu#hPz
zkU$0m=NbQO^TkVqAO`~F-pW(xCTCHU5_Ft-QSb=+=Mh$dm*^Z_4}FQBF>cT?em0Va
zZ6xVdmVZpr&zbK*eGe4NmKkXs!I1{&zMG^!6AAt!AP9nU1$0JHKlNx0jsO4v07*qo
IM6N<$g1J%n$N&HU

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ecu.png b/assets/images/flags/ecu.png
new file mode 100644
index 0000000000000000000000000000000000000000..efb3acb43c117fc506f992468e2cc69f46b666bc
GIT binary patch
literal 1238
zcmV;{1S$K8P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0008bP)t-sM{rC6
zO`-u!qWjta?b8bYN2&hZ00T~<|J?xX93<`24EWao1Wux{uP*>dsQudj`q=^f+yL&=
z3k*`922Y{!&;SuspdwtIo`x0xN~aH0qaItN07a}raC-tyqv*^J|K<P>P@?tK1Fw)N
z_t^q58yxJ>3aYC!07S0;?EuT3708|y@z(~~rx2`H2<E>ASU($Qd}6MzFw4Rlb(ELC
z!6q3|kif$vRV#4mG%jE)ZNXwi<i!R@GAFg3Bks=!^U?r0BPNxBFaSuZkts<4N2GKv
zS=GNO-M#{dcuF%IAkDH6F=d%=h+5LXH`>E5x0?tkVu^w-R9J#wZaZ8zYJN_AWsiF<
zx0xzbKP56{m~e?$T0<J%%@j&EGKQB)^VA1^Z&;IpN<1YV*~2RK)c`CN7x2^*oRDqS
zvjMEI4nJ^rcRX3v#~s<pC5V_v_u~R-h+O~Z0DxFf$iWFFia5%x1=7DX&%py_Q&zyL
zUoaUM>&pR@T_Uc95t(Hkes@3T%@<mPWPEx=!nie6frO}l6tZy*sFH-6ct$rKAi<>u
zc7`kfhCi=u4O=%Zo}^HMXF;k{N*8aSwU#Sghhs--a0FmyxvEu1n6<~mA3vS39dw;R
zev{rMDt2W`u2f1PGm#*Dq&k;+I)9X{a!*ZvieRNcVyaNZ!yyuMlZR<(YmlD2m=_^_
zrbCW`NtT&-P$N?^a%EkVMuC&jA1ffN);5o@XsAfDR#_jf+*Gbms*ee4$V9DHTt78>
z%NsHed7P7<qP@T-#}+U<mVQZ;d_gpORFqOrFmq<ZLg&u}yS^*8rU{{e2ac*6Pn(%v
zlWmNeorJ1fsd!9y%j<opVX>!L-t+&6$=Z92lV_qbYL=akj4rOc4RL^E!?hERsTogV
zgkP~xGloHvZfItxiBqG4X@iF%TV_sumR_j5Lz=nk_xt1kqK;>r8vp<R0d!JMQvg8b
z*k%9#0k=s+K~z}7V_+BsqhJ(30S5(O)PPX~Xl?+vcX(n(Ivc;gr<0ux8|em!N<=1C
zcXd`J#i@EZ+DZtJYyca-U`@9{e@A6nOn`@jC>!ZsNRS75V~?sqSt<vIygkWYVCLXf
z<~}WOZlg8_n+mtG00%#b1_-1mtv&zn!Tk#xCJ2;dX)C!4km`l<DQ9orz5eFf<(V^j
zN;4z;*hn=%Q0v~4M|WO7dp_G_T5pB6AnCE7Yy9%n&9^tM?%K9xy0I?4SP){t1YBHd
z`e#l)eR1p3p*2fZZ!*<a<Kn`iObBcMJ2oJvVPtA`<?+Q6%Xh3;YGrPuA%|5NZUfj^
zc@JAypE|mI@$S9W7N)$c?4%p8^0?)(gL9XyT5q|37C8o}>zEzcw`lU5bvqB3>8O)#
zfK0yT)XnoI85%Cwy0A$zUWRlR$SO3NOw?=d)0^L_q99AM3z)>DqjOst>T2uTn)70P
zrNx*?G=Nc<hc!yEupp<nC|l8ok4Ko1R4*_xic3j`h6RNL2l7dYGcl4J2JAc{Oze`b
zE^f|}>`Wp!)Ibd2qyUT>Flqqx3>XEYU=#oW066Ei|7lqACjbBd07*qoM6N<$g8Y*s
AD*ylh

literal 0
HcmV?d00001

diff --git a/assets/images/flags/est.png b/assets/images/flags/est.png
new file mode 100644
index 0000000000000000000000000000000000000000..c2e417b93016d9acfdc636f69f9065c42e6e8dd2
GIT binary patch
literal 130
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>ds3`OVv|NjpZ&^JC0
z(!f{}<QL4~@a#q!kfY-1;uvCaIyphYt-(};m4!!}@!x-q2ZuKZJ&0;$6648lOk`p3
XzTelNGWn%GP(6dEtDnm{r-UW|?oT7%

literal 0
HcmV?d00001

diff --git a/assets/images/flags/eth.png b/assets/images/flags/eth.png
new file mode 100644
index 0000000000000000000000000000000000000000..5b4970a6779c099b5ded6d86689b13eb00674a09
GIT binary patch
literal 1584
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

literal 0
HcmV?d00001

diff --git a/assets/images/flags/fin.png b/assets/images/flags/fin.png
new file mode 100644
index 0000000000000000000000000000000000000000..b6bc2f9a9f572470302bd09888ffbe96060b5474
GIT binary patch
literal 131
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSoB=)|uI>ds3?`NT|NjqhzIPEQ
z$XF8O7tG-B>_!@pqv7e|7-DfcIYGj$A^Ym8P;ckOVU7ozCh8rK>SAJI^GYy@3t(*%
aWMHs&2+T0Q%Hj{y!{F)a=d#Wzp$PznE+jet

literal 0
HcmV?d00001

diff --git a/assets/images/flags/fji.png b/assets/images/flags/fji.png
new file mode 100644
index 0000000000000000000000000000000000000000..4700ad579f01011218eca0ade84690d701f28496
GIT binary patch
literal 1571
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
V--yx6DwF^K002ovPDHLkV1k_c9MS*)

literal 0
HcmV?d00001

diff --git a/assets/images/flags/flk.png b/assets/images/flags/flk.png
new file mode 100644
index 0000000000000000000000000000000000000000..66ff172c28c6efd1a7afd7396d809392bcedb848
GIT binary patch
literal 1591
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

literal 0
HcmV?d00001

diff --git a/assets/images/flags/fro.png b/assets/images/flags/fro.png
new file mode 100644
index 0000000000000000000000000000000000000000..2c3ed5f6bc5ee4851653d4286c3d2da300a1ecbe
GIT binary patch
literal 147
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>ds|NsAIC_46DTX*}y
z6|q2Z#*!evU<QY0H`0I{Q%@Ji5R22v2@-A%rY0sOU;l?M3=lBb!@47EZ4|3W1S>0d
rhromX{Y-Wj+!}b=d)Lg6c4J`ZpBJ#t;AhndpaBe?u6{1-oD!M<#Fj2C

literal 0
HcmV?d00001

diff --git a/assets/images/flags/fsm.png b/assets/images/flags/fsm.png
new file mode 100644
index 0000000000000000000000000000000000000000..b8aedd34e42d168ffc18f294864d9a2292e97a96
GIT binary patch
literal 340
zcmV-a0jvIrP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0000yP)t-sM{rD;
z#^$Nd>doWx`TPBiz~j5w?sc-=|NsBU;PL44`HH^cxYzCU`TT;p;Dx*4wAJmO%IBWR
z=lcBq=M0Rc00001bW%=J06^y0W&i*H#z{m$R9M69mdOr;AP_`VwgzPX|9>5v%w^1&
zbSw`}q>cn$=!I&gX=rHZBLnCW0Hr{H)*!$+05DrCh=jHC*&8g9y5w>`1mF6359A<i
zH%I^=hf+fZ0BbZRu7B9dhh?9c0DDmQ#c~1Cr@Twunv<7YfFMaBey_zqjRXgvwA;F;
z?zfh0)oH~Als%ww0q+pnuMi|Jge#H=ml1BHJJ~w?oO7rJG8EX-e7EHWm?~=P_+UXt
m+a<#l9`6tNBMl7=b-e%*FGCSDjgT||0000<MNUMnLSTZlubhbh

literal 0
HcmV?d00001

diff --git a/assets/images/flags/gab.png b/assets/images/flags/gab.png
new file mode 100644
index 0000000000000000000000000000000000000000..c8e1cbd1fd83875e7a74f46db2c29f231c50d0dc
GIT binary patch
literal 130
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>dsR;5S&TohxNmyp}@
zSpX=`SQ6wH%;50sMjDW#;_2cTVsSb-LBg%!zdhFvgEcHW!WK5L9`<T56=7xJ$!|<#
ZVR-zmvo%T2z5}S9!PC{xWt~$(6980fB`p8|

literal 0
HcmV?d00001

diff --git a/assets/images/flags/geo.png b/assets/images/flags/geo.png
new file mode 100644
index 0000000000000000000000000000000000000000..46c83a5894551fe8074afe0d906b6c7bdd42c8e6
GIT binary patch
literal 187
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|ep#Yx{SN8&+|3JXNa86L|%Zal$
zoI}3u*%S?wWh@Eu3ubV5b|VeQ3HNky4DmRgoFKv4%+8_2tg7H3xL`5U!~pjYRs+Tz
zoX1|MNi3eB!1TmgNxOmDL9|0kTACfi6j<G`K$Jz+v&Ed<OmE7EriqIaOyYZ<ai_2@
cPT0V}V9{3c&`auB2G9xyPgg&ebxsLQ0F|^j-~a#s

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ggi.png b/assets/images/flags/ggi.png
new file mode 100644
index 0000000000000000000000000000000000000000..fbc403f1616681ad5cc69721774a075166817c11
GIT binary patch
literal 892
zcmV-?1B3jDP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<SfKW_SMMrQ<{{H^rIYa;d|Jncyz5ojU|Np)K3jhEA|NsBm01V<e
zLI3~&!3`I_01BM|2;bS-&unqO01B`Y8pJ3Hp#TWgl$h863&}!B*#HZ=01BP}2&n)G
zxc~}#00y)G3B^AO=hfE3ZF1nn$FB$xog*o*Y;e`6s>q$7;KatO6&;`f3E#oP{{H@-
z00^ZC63&vAwEzkc0065wKrH|QtpEwM9ww3i2!a3yK>!1l00=q&11SIkt}Qg+#m2P)
z49G%BivS0?dVa~CpsNZJ0RRBW5*#%E0?)Csh5!dY00YK^hsYBh%9WU~MogzGGR~^3
z#Day<$H%+?3akJLzyJ!>01I>g1|t9gxg83*p$e%^3AKX?$2JSVF$&WF3(NouyhaMF
zSqaD#3$7yxzCQ}q01LMr3bHQ=y)p{X0Sm8C3Df`!y*Uc9O$oO~3eExxd;kWSQV6(A
z3XMSrqDLrqKnt?~34|;SQ8fgaJtK@D2bLrVK_>$*1p+Pu0{0lA6aWAK3UpFVQvmPp
z|L<sbZ-4JS$S|A$00E3iL_t(o!|m2bQ^HUXz;O^PtjkLP4PB&&ic*vgqF6u_!4BAa
z@4f3+H#(yygh?_Em;4WTli4@F!=9c*A|@s#_ESTXfErjpArp||zk!iVE|(eM2iUuP
zgQIz~!C=mh4*I(7oPkd7(Af0c{KCTg-1OLxx05sAP7pFnn~FsfJxfT!&3y+t0ES+q
zs70Cq(D7KJZo<US`cg?xGo}eXKr%JS&;`T-%}l0}oPn<15RPYO%!uZh>^O#cyEp<J
zE)p3|Pic)t?NoX=LR=jj0jq<MAl3RE6(q!A<+=kU0I1=+uR|%T0ie~Z;UOBefLgER
z1N8L=3=l_*gCWr0#{+0XG{OMl02mRk_yH8WBYpsd*v1)f_IRjp%<}s5_F{>JDNm2{
zPe59BVpFM9evL-+c+Y<P?2oPNH7N_!HCO8Hx#GBv1?2E|mp8Z97pE02$g2RyXXhtJ
z`vL%f!-I<B>Ogx-ZGnx=Jz>Ds_OdWweRowDu(P(ZR28Ui6i~hRJQ5QV`|T6pBV05k
SBomYX0000<MNUMnLSTa6dui<e

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ggy.png b/assets/images/flags/ggy.png
new file mode 100644
index 0000000000000000000000000000000000000000..a882b4a5951429aabdee7bd4c90bcc2fa96fce7f
GIT binary patch
literal 192
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|e{s5m4SN8&+|NsBL5Y+v7SL{Qs
za)H`x9-tIsNswPKgTu2MX+TcAr;B5V$MNI@3D#zI4kboKRfPZ-G07gTIlaBUAG87t
z&B_ktw{F~ci6eAD3sVDE0E1H_*D5A;9@bNSC%8g-3`8XsH#7!1oS4Y6x6^uoTd;^_
kWPidl*)^^gG$eF@j#4iR=bZ8{31}6Ar>mdKI;Vst0C7?}y#N3J

literal 0
HcmV?d00001

diff --git a/assets/images/flags/glp.png b/assets/images/flags/glp.png
new file mode 100644
index 0000000000000000000000000000000000000000..8bd0a69bf663de4fba86d0c6bbd02078e59f5281
GIT binary patch
literal 1820
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

literal 0
HcmV?d00001

diff --git a/assets/images/flags/gmb.png b/assets/images/flags/gmb.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa641ca1a08d685d06cf8097e9a342c6912f44f7
GIT binary patch
literal 278
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+KprBKL
zPl&5~fsa+W#yLT?qMBVml1HZJ-@ktl5g_^W?W2OK-9H{YJ}0CO<N{@ZYX1NKUs$#K
z*}Er&)w_N?d_3doMKz#ld?i7C!3<NUz6XN&^Fic$29NKvfiel6E{-7)hu>b?F4|xq
z;v6W=UZAx3|Ed*9jDdd_n;%#ka>8<HkBP2}aKjE^S4O5c49$#e4gUm68Gb69Vz}jb
zg<(mr2ImH*mf0GA44+mBhBBn8YB8~J{9v#bu9PiJT`C@SY<hZ|z?IcNyBIuO{an^L
HB{Ts5qQGjI

literal 0
HcmV?d00001

diff --git a/assets/images/flags/grc.png b/assets/images/flags/grc.png
new file mode 100644
index 0000000000000000000000000000000000000000..d7b37b0c70a4966b898520cd6351b21c3772442d
GIT binary patch
literal 436
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+KpkQNw
zPl&5~fzRK+|0Zm`_4nUD-njMu|Noar-2`Mn*!N$4*>U0d`TOq=U3<kJzg{SDgHF-T
zniZG(x7^x({`vh^U-)1ufhLHjY<lqOD^UH#2Oo~#dZP_gx%@Iv%dg*m&)s|X@b%Ys
zUw&SH^6}%hU(eos0~#WbutC3MS9sJ>psN_fN`m}?8Q#BtKXv~5`9SLZd>{bP@81io
zoz4POvE9?fF(l&f+iS=9nhkgw65X7bO85_Dcz>_@&%S19(-me9zgmXKpLvdt>=T+l
z*c?xETCx6Sh?nI|ZEYqdtL!(uhP%)7$rUef=&WLPZx#w-{;0updRJj1cmKB!X9B|n
zI;=0N|B-0tZ<%sHjH%oCG0*qAw+`=ix%nYt$-4uqogz2?Q+mjp`P*Tgz>e^;OZUnT
zJ~(bsqoBz->AvP4=g%B0mW~IKC)Ri!Xm<z^aIq2d)L?p8cSTmu&QRq3!Djg@u|O{{
Nc)I$ztaD0e0ssKr*8Tth

literal 0
HcmV?d00001

diff --git a/assets/images/flags/grd.png b/assets/images/flags/grd.png
new file mode 100644
index 0000000000000000000000000000000000000000..7138a28d7cb74b2396fa5dd130eaeb3ad4e8f2ec
GIT binary patch
literal 892
zcmV-?1B3jDP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0004HP)t-sM{rEp
zJ|f*vA?9=*(<LO<Gb7_^AN<i4&JiX6dS2yl9tM0|7=l;%#uxg?7XW!*HH=S3lS*`=
zJ?+dIaiKog#US?27}dlfN|Z_D$sO>`8Je#$$G;`Yz$5^7VCHuo@uC{sOd-w_CetV+
z?2jAQHzP8OP$Y&_!WSvBw<{-yQ(~M#i>fvce_DvCH?_Db41Qanu`r#mF#vaA&=@6~
zD>Tw0B%UfW&>AK3s2S2BCG@cw@0%OsZXWiy7+;%1T$)4xd0q#6TzPvuKaflUdR`ZU
zR|b7t6n<F%e_sH2UjTSu0Cr(`cs)=;Ngjh&0(f9FkWZ|=EfIiO0Ci#odS1f5CgaE*
zI*m^J#23rMBGSSlCx}zAw=15WF$#QK|JV`#*Af2D75dW_dwV<o*%Hn$CZ{Pd{LU8h
zrx{+FL;v3o*Tx_NdR`5GTJ_Hu+sqyF(;3`AAq{?8#1<)idOOxJBWyb6(f|Me0d!JM
zQvg8b*k%9#0mVr~K~z}7?Uq+l0x=YYL6GDMO793r#|DZbh`smTd+)vdeiuP@2eL_g
z@@3EL!=1^w-)!b2ccM}$QlzLXT&?<gc3l=3(9poHDS)~rgc|GUHT@6N2&q{$6`<2-
zbgY^R(Efb%ngDRw(H~@Y)c`<m@$j~LEPAK~02sRY`nwE*nFIhZHM85BO+QvL0HDoH
zZ+EwqjdB3!Xm`lBJK8&d1psJG$@QmNMHdACK#tVzl6t5BQl!P`Sb&UCTrWi$Y|(04
zf|cm#fYGsu#|;TWh%|ulmoNhYztPbF#>xG?yG_5u^BKZ;a1i6r1pp7=Y5VkKYk6Mu
z^o66*LLnLr_i_RJ@#nLf`@<E{ljt8PZhxRZ!3Q`v-+jA%U6%kbjvy4l_=9f?#}AiR
z*K1RfEnu7<8p>nLw*|=Tyc{jfOpBhyP&ksyMZ%$RJ^(Ddug=a@95EjX^b}Wm0>~HR
z0)SBr(cmo|q-?fykh}&SfOwQ`*6O2dwdwf*W+&+~InA7acv9{<C*vG|bSG_~bf#H=
z5!Of>rUHcMnDWUF)lzh9dC6m)5S^Tgk=6jn(aFharadr}7s@}pP!uUrB<LGsHfu0^
SMrlp}0000<MNUMnLSTY$`ig)6

literal 0
HcmV?d00001

diff --git a/assets/images/flags/grl.png b/assets/images/flags/grl.png
new file mode 100644
index 0000000000000000000000000000000000000000..53e45988b667fb6ea5727482080e46c2262b069e
GIT binary patch
literal 407
zcmV;I0cie-P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00012P)t-sM{rF0
z?C;bcL)S7>-B4`pq_X(g-_Q&*|NsB;yT;;YfaG(D(-}VV!_D7VbMUjj>zJwBNM-!;
z^xjr+(iJ-KwZZ-N_|_{;>5ic0eUka$<@)C8)g?&D<t4}f0004WQchC<K<3zH0002)
zNkl<ZSi|kpM-qcD5JXXepe=IF_dlmuxEw%3HQ3(iubEerG;$o9&GzW_MHcuUP_?7#
zo2FM|TU`L$qQtYZaL)od!$+Au2LwJg`N0_=Sg>mectHCw<ZBjiGZ@QU5-1>4a6nZ`
zKv_{h3$d00Mj03>K*@ljfL;cA3TR}YIRIW?b@I-3W_JTjGB8oV!MoEGFv!3_0ksU&
z6p*CSe40=IVhM=B0bXvN&pi@=3QhB&xZ^tj(Y&9ZBk%yC-9Lo#ya|BXoI`%_MvVZx
z`0X~+*uz<1-G_S6Q`b#;s1x7<z-NJ90XCa$?G7PANeNLSMSB1M002ovPDHLkV1mCV
Bxkms1

literal 0
HcmV?d00001

diff --git a/assets/images/flags/guf.png b/assets/images/flags/guf.png
new file mode 100644
index 0000000000000000000000000000000000000000..07a2d5070e8125cdcfefab15d566901832640fb3
GIT binary patch
literal 581
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+Kpy0*;
zpAc8~0-xxmN-wVQ{JG1?-f18+L1*njQ3xAIM)s;a*~<qMUuZ19YKz$KJDl_Oh_iR<
z15xohIUpCJ@|KX4VwEnCn;NXPQdj<lkd#b~Zgzm`x82<DC-UDClYHzWdRJBA=V>m%
zW<8-My{91}-w$*Dy3F~03jg<m+`lez_Sh=jmX&-KEBy03*8?-LH%$UJg`^&Pi3Y`K
zY*v?j+bnQSLRzIl=V_=&zwYu*pyNeLg8YIRe*c~N{_pSk^WXpZJN4i1`IF|qpY;BT
zAb%YL1EZv;i(^Q{;kVZ!^P3zbS`%}(cIU?4s^j6%n0<9y*7vXf|8M9MD!Adb@38F5
z;=@;MDivq8___P9SKU2x&coeP4!rfe-*A2M0ZZ9ZX(pEf7p4P(nhkCm3}OqJ0$jux
zl!_Sa7cmqlcQF_*;z@9w!ZfFY%c0Z2m&3xvXSu=zmm6kWM+DbB-l4G}E|%xaOabHI
zcYF-*=DTd#ewL|{wd%&P=lkt9<U4%%vB~=X&*TLRd*3%`GqcUB6>K{s|1I!<u%ig;
zq1F3jO%Hs!s<dfe-Rk_~{~JvE=NGU3)OD@)$Sv(tj9$tS4v{Rv8g2!RPAu{#Tp1k9
zn3%3`@B}CYDD*Zosw`p@a5rK6CU}-XvQW42ad6GzjsF6#XP^GZ(3NoZT2$z!S-?<a
N@O1TaS?83{1OTO7?fC!z

literal 0
HcmV?d00001

diff --git a/assets/images/flags/gum.png b/assets/images/flags/gum.png
new file mode 100644
index 0000000000000000000000000000000000000000..828c5f3d927602f145bc41d23c01bd52882b8a34
GIT binary patch
literal 1259
zcmV<H1Qh#;P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0008?P)t-sM{rEU
zF-gH6JH$0jv-JP9=>N6z|J68108q#`LZEjoYr;}%LOz#}CRnxP`+X~Cz-4{3@Bg*w
z{{m3Q7fQEbGkv!1|Fh=&WHfxV?Ei8tZ(TNmEJdfh>;Dc+zP^5!u^dKvEo`G8O1bU-
zN3d$dF-yE4Kf2)fUAu|Cz1YXE#X_xQ|L{z?@c*&#|F7u$SFvnGK9m_swZ9)ay&gI~
zK$<T^rnth|xWU=JfSGhIZW2qoH$R`iX@NaJnxP|7z-)xXGfT^4OP(Q2s^RXvBtWzE
z|G{8*v-khD<odbS@6BvXz+-!;BTcsJ|E%oxq^zN{?EbIF(XQn1yW{<TDrtVsxLG)c
zzU%)aN3OZr@WM@H!NAt(l}SE4no>E7h}O!$gPy+6=Dg77r{L(oNM63f+Al+;X1|uh
zAURBlIsfTXgVDc*&%AG{eUR4ByeK%!Cpf>{@~xqoV={f0B~$<FRI%**yv*dwB{$k&
zLhG1F@Tf}bo=Lgp|Ivz`zS!@vv$lrO!ld5ghttEzrn^O;RA<1He#^6;>+8fXNGC_D
zhbd#mAU8j(VZ|akE|fL6_y50qlUlihytT`Q&$_V2*I2fHfiG#i)a$zH|De<J``|^x
zTu}eeP4ntr#<R|4zLT8l>b%<Wrr+tP<M6PPjI8hZx69zWywDz-HI387!utQgh@qn0
z<_?h?#J0;Ppg=^fXG*beYr&bZ^Z$9tu8`r?VXAZg<Vr<ysKFyXy_{<3XgYazi%hLx
zxsZ_m<4L&Q^`74SHgvuJ>{6$&e|JiK0+#Tx#DQwLuey&fz`|_2*y{(7?3UU5((wP2
zyONH&ldZ9^ZL+EblIa(Y-YkW*?ezb<=K686s#9-+0EpvYevciK-$kOoYOJ77lb@bb
z1i8w6L8<P2u$Axo|6ZzSbb5cm=KKtm=Tc^33Xk4myM6EZ|DeanE1J+Xh^&3Jo;_i7
zE_S3TYLt+ab6sZ=Du%maZgjA<xA*)1`$x_^00001bW%=J06^y0W&i*IrAb6VR9M4f
zU>F6XU=%<BI|YDR25^uGMh&2k0h~&uGL#q~(Z6;QQ#knsD5|bpv~>!j6uAbJFs@j$
zY2ET^s-ol>klw4geT()s4L!|F8FCB|R+68%Wc6n4g_AoIorTFTz>ZP9MMGuP#;F}S
zA&#bG7{DvflG5C_etLUu1dAmv=>~|HScu7HG)-vBS8)+DH#Q>K03K#fR`KA3th_K;
zaUnitLy`@U;1*<+RQ3-D3iOi{66BU3*#Is9HqV%(qT<GeiZm}40WOja;CFC~YSmh>
z?10vW`eYAVev%E4@?m40dFbrrUpLhk*Ri=<k!*l;wC*hB3%c*W>FMh)El-su*#OS2
z*@w^Hc=z`Ea|46@I|?{SHb748$hjxae!u+j`qi7OyVT@JPl+>*-?@GF=Zi02KVLgF
zSCNdQ+`aqQgNN5YKK=CQ^t{SQa<X&J-lLCiUHNeD%$%xFvdRMyrhO;wU%Gg5ezk%%
zc_mVu!XBN2J9TQ9Y{)GW;|pucvSVF&$S;*SeZ8IR%|`3Sp<%#4x6($zC>RAm003O^
Vz<1{)+#3J@002ovPDHLkV1oWGr`iAj

literal 0
HcmV?d00001

diff --git a/assets/images/flags/guy.png b/assets/images/flags/guy.png
new file mode 100644
index 0000000000000000000000000000000000000000..5845c6db9c8281966eb57e50b531404cb9be61ba
GIT binary patch
literal 635
zcmV->0)+jEP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0002kP)t-sM{rCk
zu4mQn;n?uw|Ns90001YgW&F_=0G>(C5hi}lqk+$*|M%Jc^u_(?iT&k!{MR@9)hy@0
z6om^JxDO&h1q=)U0>ls`QU?zk0tJ=~9ITHI6bu4VKnSLa4igLlPdx|f>goak0GSOO
z6b}!suC5dg52&c9L%4Z7wRFMf(>1bh`270${rgF}eZJ<<iqorzaSVND3xv?8*0B=U
zvlBco1w=Im7y<-HOGrdVLkj@{biI~#zL!=|QBX@uR!&8&o?R3T1W!jg=fyIomr)Z8
z1LwmiJ@KYR00001bW%=J06^y0W&i*IQAtEWR9M69*4JXfAQ%N;Z9$q&Yxi!n)$YBQ
z)vot{qY_Av06zh|<-b4QIms2ZTD*Ai@_T-3Oobi;@WJ84bYmO<<Bt@D84Orj#dHKh
zAqE4I<rO;OGerRg2a+TkF&xYyZ=(SCh@J0wUqb+V#P$|x`WX_Ck7yAuLk7eM;$f75
z(FkWl0pt;Gh6a>II2byhjHoh9fI7lz7y*3*Yyf~^1YkgbafHc$0Y2jKo`A;fsU4sr
zUNLT869O7%mq%8h^F)Cg1F*O-$AI&b3k$HePCwz{4opv89a}%4vw`v6E|{LF+kYaf
z-)~i<VPI3QH>Dv!uLsfqpw`1_BcRk<(<Y!)UzOGYx!xhI0i$}iv;v5F=X4p!>wVHP
z!0Z3~(h`u>|Ni)<1;FaRQtxyDWcA%%Kw5g@^wW^E0J^=fbOF4)*T;M2#fuk@-ai;=
VSDSEy8L$8V002ovPDHLkV1oHp5<UO`

literal 0
HcmV?d00001

diff --git a/assets/images/flags/hmd.png b/assets/images/flags/hmd.png
new file mode 100644
index 0000000000000000000000000000000000000000..8c2931c4e5e7e9d568dfe49857235dcbabe402e1
GIT binary patch
literal 780
zcmV+n1M~ceP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0002hP)t-sM{rC7
zHJZ;45Buus9!sVC{r(R>p8zwN|NsBY000$4p)*{qCsL^$N~H-poyO7Vftt;4jK#gm
z<#mzB*x>Kthl<i29qy>8+)+{a`u%&A%4vtg;BayN{{Qc;u4aY8HeRpSIXS<p!XZtj
z&=nQRr?|<~>C`7Dgq_ZQki)dY;fkTqDpjh$&F1#_``uSp-BeWG<?_$j>@ZoZ7)GO$
zsniBIn+!dkmaEm7t=5O1&#u1T%+~Ae@%TAmu+I(-cazB3MMcpV7(8RKKV`C4dAwSC
zy^y4r%K!iX0d!JMQvg8b*k%9#0p&?VK~z}7?UmV9gD?<=MV3hcTic>m(Q2)B0g6lA
zx7PLjA4w7*Y#~kY#tZ(#4IJj1Kbgs7W208BT9Gc~{R0Ui9c?zyR{V0jv%3de5y0VD
zAC1f+V0b#{$*KUrJRc_}5&%w*tP=qMNYlhb3<%RtnjiuI2uxgtCL(}P`V=5BK>(ce
zioym^6Bw{8O|Nygx4Rk}fK7b#5efkB<*RQa)Gjzc83llhGVw-BRa-_LuxRj<b)a`T
zdcgrVev#WlO;c7Zp|P2HJrXQqpyouCd+!9$|2UjV+`zb+DZq(^_I7uc7;vyJUyjes
z^6;dZ6hP7sPKR3<0Oknw&v+(iHDf@S{um$xfW$YER5Jv`>45^EU?SVXw3-A!)29K%
z#6@f(-@>$-1VGbg0I>;n3unqm)8_!8i9!qCE6P2y54cLT@XgiL&H8{;3(v2w=j#K~
z`uqYOAUASA{47MW?dkv>Pa(&_ovl{_+|67?dVQ4?cXn5837(H;D0qCY>K@qP6tOFB
z;+v1-{kPSVgbDDT<3aZ9t(qh(fbsD7V&QP><?+D)@p~ct;RmTI`Yv4n`(8-@@q}y}
zJqaBuHo$QKTu10ou>rTi43loFp9P6rsm(tfruFns0JUn>3iJyVE?uFkcDWJ&0000<
KMNUMnLSTY}s&oth

literal 0
HcmV?d00001

diff --git a/assets/images/flags/iot.png b/assets/images/flags/iot.png
new file mode 100644
index 0000000000000000000000000000000000000000..2863320f58639484d1bce5ae2d1829c8012b5d79
GIT binary patch
literal 2415
zcmds3=Q|s07Y|i6S|zm}t7_GzT2!lQlc?Aut<h?!DuQaQ5)rKx)ZSaI*r{2&lp3Lw
zAa+z9HDc9D8c&}0z21M~{oU7DAI>@V`CaG3i86&4Tw>v40RRA(K!&>JG^_cqFrB06
zoF>F3%`kfzLSF#@Y`y;qU5X4FKLBtJVEVvP&%o;el}a^ylEiV-4<G}d!r^T_vlbT@
z&(6*OV!^Fl!#t{yG)LPhe|vs)d-rIRQ-)P3ysK}F?Z)e+mw~hpr(xz7-3;|XKM%!>
z;)vs-x5osOuInfKIX)592~Ey#p_S_B#(l>Te`OZ)YoSh0DWp$r;-G}quXD?5J5f1b
zDw=<M8(;lHrJj;0*_9&^Sv?1XqqNV^5^42m-DeD-)HCW%LmRzZD62ejd*_f@HjGLp
zGb)C$+zMw?eNW!nrlp5xbnosTGsq)|8~dE<QCd&(ejlEUPOecXe}HO{AxRyRbH88_
zO-3(1e*854scVK`Jtm`K*wmwRZe^?gJ3+=I#RgW+dp~BsckqXzu7Y{$@d>%Df4-&-
zXXR5qII%i1xi*uK-#xT+RWDxcVYa?=As*rw829;2Y^$ij2mgph32<U;{#Vy9Oyb9Z
zF&uIA@7<@twNh{yHZQh~?caGdqemyF95>%1QoDSjo1=4jxqP`C1FC11Hg8&G&}M)5
zrn0eT7Ma{RXYJC5U49wfFh29Q(mN%=070MdMvxCm(m096)xpqMnHi@M>d|i7mz2`M
z_`-g(bhE8}(!wf<#wQ}SWkN<1kIFinz>V?WP`A&a9R8+JJ*f=h*N#o@N?zYOm`p0}
zz;(L7>kI40o))+;c`!=^OA2U&y9T0`p1-k(_K`A0t)~}i#%bkNW04I={}R;em^@wI
z5PJvjuhXMe{#o`JFI2*`?cI_3PMOnF*bx|OM@L6@sxa1q3H+B4R+<4n<UVkj?sR=)
zTE}XutZsW@^$5T46A`;rR*N1%KT3R6g{_((OgJP2`d0d`Z4(Jw1S9vnis1^|99xeP
z?~u&u`|nH~<B@kGw7`krx2d0?Z__a?LwB9xqH<rPeJ*GVvkEuYS!@XgNQaC~EVR^U
zHB{YSYz`drH5yKE8+KH#_k&<CnA!$(6$TxRvYRfu4b?M8aLB%4S7=9Q;EHv>SBcP;
z|HP4l2LPZ0_?km303;ZU<N<@h;V?Lf1gAZkPx=qwG{9hfaJb)p<Ns;eivHgKK;0kJ
z1^~`8gLJhlZNF@#9zB|{;r!armpUaqJ6kayL<$1o6~43IG;{(gg^KBGU(t_bXBK6U
z6up=tZYmizTmMjUz<gsN$d}Z9v=DS};T1`hS>5C+`SL2I=X%5|hwWfei|T_6V4PRD
zr~sl_MQJZ{omiW$v7ZP{!?wxptp8HOtl0?#v^GaG+4+v@0A~g-FtFcXEh;MF5m$7`
z&24j+a^a|HvQA-BtiCQQ=Om!Vu%<zEH5C!-YT|L8{8-`r+Cf%?18tPF#2Fvy1MOfi
zQt}j|C(79hCNnWH;GZ%SPf6(;7Pw1z6bga|)hxf1YjOw+vonYT%QPWn_QLt__#tq2
z^SDfXV?&?MEH*KS@W*GMXh!$(0uV@@C8}zCk8!qK${?yFwiAPvd5l)n<A#eLHWKJZ
zy`EH`yz5Cr3?(V0%&1;L@NZ}F>MpH=n5XXKZ=85Fu@F3Ba}-V-eAO;a%EB*jG%KEd
zTBak#TK5K9);Tv-b~=sWO1xle*#X*#sw2m6x?W`&Ii_zp(Iq_z#x=)x_%c<v8fPLE
zxShFpw1|(LKBSgPh?m)vNwA?~gAU_VEN{7&yT1LcT$K1zYiXsAU7|k!`RCkX38%JN
zG}=#YL;*5k1@&NLmjBDMtjyJYbBF7&Q~p}tnqAi9dULE`k+1}sNx?ofyCavykg$V9
z3xzzpmjiLJ9-Q)9z-t_@J$fg2>5sIDaU-;6ugL<TN#5fP`M_Pt2AZB!Z0GL1cJLK1
z`lU8J$2vR^^&xFUlpcfJx}vWphPV}2lM5MH^9#OvgxdC)Rox4@a#A)HB*?cTEIqBU
zu5?~39hy;|7`9bp97+Ch6!mlm=^?lMA<C}?3~|h0*U`b$e*PSkkad>N1&rcuXM9my
zyMV=Vx3BC6=atvBGT89jIrUo2gBeP|o3m|T>MYpW6>m(Z;)cidi~^M<l(#lQ&*aTG
zAhG~!D?+&!>cB8*c+4VMS1konBjlMNdi6H;yq!h-Zf7&#*H5bd0GbFyFg5Z&`<9X_
z<=;37dY#EETO!7{xH}Z(*xx^+S2+&CWOXAWv$>O?Lrofu-IiH>m<i4FH1DQ#H_T;<
z_vYvoxFFv7mUD8Hj>N*pu)eZAcf~sGK_Ml|fC<zZlD<FaO6@0Hhu;sN1T{x#OQ}mo
zKkCxWc61M?hrSgEphVk*=6eB?SfQ6G^94m`0{0G_L%bbXc)4Nb$SAXr(>boOC^^DX
zOUya>a?t>9?qHCWPS@<!xVL1yszHbFMT3hMystkH!N=M;dJepFkp=JZPOUz89O8a>
zRh_cGj3i6--<jeC+W*ki3&<<b?*%&<G2cu}u$^t{?#3{tlifDEOjK@^D?nDXC9tKe
z^7;L#pa@rcLI1gPI^o7GU0_}jJ2f$(mwNK8Ghl_bgT0d<y$F=Q&)vxreIL-fWb_28
zyemaZzA$_5waked?|>p*DIb}!t9Qfb+g?t<fui`%r4>(;g3W8$Nrq5+h+AfpHDSTJ
z@_nGujUX$S2tBTDUeZ_2r6{J(>bdF#A-R_s^X{bOepxcXI!NNa%gmcsj`GT8$yt&=
zW!Q-($$MOe+s3k0EIaIkI%_qN-w*j&GHw?MO*xfx+*wyOtP+|wuCZaXw}kL*u7~gd
zx3syN9TGJfHT|bbb4FGu7_2&>^LP&Qwp+JjW$?u^Jidn`&WnM-d2#L8@MBX^GVOu_
Nfb<}`)!L84{s9N8KobA}

literal 0
HcmV?d00001

diff --git a/assets/images/flags/irl.png b/assets/images/flags/irl.png
new file mode 100644
index 0000000000000000000000000000000000000000..2126054d32f58c1d32626bfecece011150e4f8b3
GIT binary patch
literal 127
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>ds|NsAInC1DulHs(s
z(_f%CV@Z%-FoVOh8)-m}qNj^vh{fsT1PQl>Y*7InUe=}`{~bOgh9ra}7;y0@GcY`V
W(${cKziSszF@vY8pUXO@geCwr?<If$

literal 0
HcmV?d00001

diff --git a/assets/images/flags/jam.png b/assets/images/flags/jam.png
new file mode 100644
index 0000000000000000000000000000000000000000..97bce2de3f98a2d497b6298f66117028816b7945
GIT binary patch
literal 526
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+KpkRA|
zPl&5~fe*uM%X`}x{#|5%kU$1QyAi`|E1;6U7Z^NNX*#de`f!fv?OEn?o0-ifs~JvG
zzqo~IW*x(-9){Ju472JPfQmu77#RLsVEA#K@y8j4Kj#_b7aFbDCoC_?puNOEdx`$c
z-QqKVsFq<x7lXDk15o?QZU$`?hLu1yQVg6i6P^O~i<boX1vAuVl;_vK2cq}&K#&gv
z?}4B{^PVmP10$EGi(^Q{;kVb0i!~Vtv?hwW9=zAgrS<L8zw_yj7A`r%bJDJS?*C@i
z=PhBU&!0cPKIXz>Y5v>H%eT4<Uu2cxn0e#f<b2sOyLbO0Pc+Uj3}19cvfFZl&4x)9
z&+;s-b1Ver=9ymnBUbe9j~kPRP_@(9$x9e=IBlmhNFO>Qx}dY6h<5>pg*ijdfg*+m
z4jXpHxeJO|0ys78XQ~T2C|+1Txxr1rlGEm0ChwB<+m#nQVQFLt+IN343&)9{s;Ae9
zFfwH6*{O6HFc>fA<ZUSK3Sh7~&dIr;xMxMfGZ{6m1A6Tp_6hT6w=jh1?etr-diO=E
z@XifPGDR~59G0KnKI5yb`TVYRkL&yY{Q0x$FN1=_PUrF&ckhEj-qY33Wt~$(6993H
B(7ylx

literal 0
HcmV?d00001

diff --git a/assets/images/flags/jey.png b/assets/images/flags/jey.png
new file mode 100644
index 0000000000000000000000000000000000000000..e144d060e6bf143d7e77859926628ee66e1e9f99
GIT binary patch
literal 914
zcmV;D18w|?P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<SYfwy7MMrQ<`rP2(7c%gYpZ@;--w`d}5iS4!|NsC0-w`eEjhpe9
zq~8=T-xV?Nlc3)dFW(d}`rYB*7&H3Y;NKTB|NsBr5iR}p_y7L>=vQm#R%+lFGy2}*
z?uM1$7&H3b;o~q!?uL~0w!h;qNA<P7@85Fv@y_wxPxbTR{QUa#>7DQAtM1-x@#dH9
z+EMZ4jq~0{=yM?ESR?Z7%<=8a_TS?2-Q4oQ$M)dk)j&7oQ)J~HIP}}z@7?0<s<86I
z$?lw|>wAjggMR0bj@~RN_1)m@tr^;J9ottf*hMAfA354yY1Xv6?XDT%Bq`M(G1`(D
z$b2B#9WL5lAnu;2+$t>Fa~;k+BI1ab)<7i3WhvzzD&3GB=zfjmh#b*ICEGkC-;^EB
zP9NWBAI3^A;;I+Ws3PB&8P{kY<(eAgcZk53Bg{-I;~gsG6)V+m9nexA)JZ18Ml0SM
zE!(0P;zA|e9WKpo8qY)_MjZ%~0000LbW%=J0PpXQkB0A$?~jj<kB^U!kMHmA?_>YS
z2><{AtVu*cR9M69mQ{PgFcgM?0i$zE=@|3j&Rm(hySuw@KYyj{S=*442H9QDRpsQ(
z_a!G{FzBI&9(f82$CVeE3o{OLSp~;gM1YkS!_kPy;dTQ*oVCezRuNE@eBc|J?W8nc
zFz6$Fx7XK6&1ytIrG(=7);0ml>Tr1jkx0PnYR7&EElsI54x<RL$*;H%PbeIXhC?2r
zdZ|lW5+Do0efSq*@px>~PgE}@{{mD{Meh90_2cu_;t)~2B=--1h(5NT?ryFwHphtS
zks3hsar<)i_WE%?iog^lfZ*fc{_ElNdv64RBGrJjl=a=qllT3#VFV5n2Eav5tR8<J
zEsYN#aH7%xSVwa!hs#razz_ofRr28U#!PP)Fv$==B{wnK-wl-+3{d*$=>!X%22l6_
z)zbm8587g<0%RYQ?dD$rIa<hd5EYdpWHF6c<z!k&gf25GWnwb>Vglu|EobV0F>EMK
z`jlyHX|%y+*i`A$t-Y;lsMk7J7}V2_Hb(W};c8@6Px4VM0!-}c(|wpUuQ(b$tf@;@
oNkKN3tm4wtB})%I^vFy60K~=CZtW2sApigX07*qoM6N<$f{GH)!vFvP

literal 0
HcmV?d00001

diff --git a/assets/images/flags/jor.png b/assets/images/flags/jor.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e5d2bbb897ac0929d76c6582445690f40258eac
GIT binary patch
literal 3131
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
bv-1!XC1>BWYBYyEx<Tt`7^qjF9j^Zih?`i#

literal 0
HcmV?d00001

diff --git a/assets/images/flags/kaz.png b/assets/images/flags/kaz.png
new file mode 100644
index 0000000000000000000000000000000000000000..db52cf0788cef4aea4b92172780e36b8589f7a21
GIT binary patch
literal 1740
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

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ken.png b/assets/images/flags/ken.png
new file mode 100644
index 0000000000000000000000000000000000000000..2570c185d3f427cf78fc4cc033bcb7ff7a085d99
GIT binary patch
literal 2074
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
Ef@dU`QUCw|

literal 0
HcmV?d00001

diff --git a/assets/images/flags/kir.png b/assets/images/flags/kir.png
new file mode 100644
index 0000000000000000000000000000000000000000..c8b69d702b5f4f1a399441f6f4bcd0be6396e8fe
GIT binary patch
literal 2113
zcmd^Bi96Jb0{t<T!kE<zMi^wdNlLWH8rio=iuYo;yy2;rLg)_PP`4zNxn+wo*Ofxn
z7E7)e%Z%~+&6q)v2_f59W;7MTJn!##=ljk%f5184`Oa;BUpKglwh90Ma1VDE(vCa+
zkGo(y`nWND5ddI-zjvUkTbwr+VZ6!50oF9&Fb%Ly2drpZl(9@E0~~HCIAsF1zbl{2
z((uWF;0B7$x4FtDfK3LdK;WW{7goOUcAN0jOr#u)Q(So;Oba-gvB^{6!i|H{Y8NHn
zXWCF7CKlZjo_i%${PCiXUeyOG>D+zZi}boD@0f}8zQ4dk69OI-)N$vQq(kE(!0zVY
z*n-JFA8`>zat^n6ALk0|xko9C?QPk}<dSfD`P7wXkTG#Txp?E}7FX3I_I|TxQl(!?
zRc;OFdbvEm77_+U!QHYa=OqUto(Mk8|J>YaWD6lJBM7xuHh=@Q3|BcANZojmjb83X
zLrNwf)(EuFTk1mbh4UL<=J<M6N%?I)NtN@<(w_^W;+Oqf<L4$5(h(ka?^STNwzhMs
zI9mc7gxxD)VL>My=!EVDPXkmn{=vg?42bis80Z#a@G6e<TQ%rTSOAezt;l{I%kd}J
z$p#eOk1ixd)N~9lSHFJI{(-N1C^7f%C$ITgPgy@!!OXvUMyHk~-_~O8H64yBF$*nv
z(<A&M`r6d{iIUwYeusrrjQhj2z#y&fAa;O`UhG7J=QY{USittiV5$bc7y)?^IAmO}
z5pn7ra;^#8e_nf~6SFpe9cx4gD4I(w^!s16Cpy*VI^b+G-Szj_;fq?E{b()?wOrM(
zP*6JR8#ddjP}eykh4>q@^OA|e6;NL$Taayv#9!C8rju5`tzV?SZQ+cuJha&^gkD!d
zPaFo^W5~AMGf;>GFKIvyx+A5iu|n)X7G@wGFUUiQYBl;#=#4cYz<tE8{g@AQEX#V&
z`wSeUYsfvS_lc&-I!Sn6hJ=!_vmC^93ko6{LIK)+F*q?Fy&yn*{1Y`?jQ(7XndwFf
zY>0z?x<g@vK5ISJA)U1$EE|KH&nsCdD%%`1oa=;d4j6pn4ajy<tSFIf%x<sLaMbZB
z1@A=d#B~W*+Q*wKf4nWOTd8aOL^l*m*P44j?UcV-<x(yH$N>o?-_yWO>Hm)bnB)@b
zcXmPS;o=l{uJc#2rs7{@tfQRmWg4nT-xt>9vJ}ZUuDRsm>Z+&^NxgCV2rVFarL7Lu
zmP#ZZT1@>jJh;&6na<cdw*q=H-ZF&uOTp!6fpl-9bJj|}@NK<#^F*xHDN?Jx;V&0b
zukl|$MNsS>y<6>_@;c_&n1fYn_ZOFh#J!C0?af%-`?aRrYI0XFwO;>1>UU1o+aq~F
zCkhS@<?FzPqZY4N9B7HRJz(OmNfDwwl}m~8@>jF7v!}J%*%nhGp6OJH#r08zR;98Z
z>w5FNK6ABi2r1D-O`+isLU-kH+N&hyL+4mq0UXILvXl)M3mJ^tPgkGi@!nvJA>dR=
zVfcd#yh601a;)Ms*Dj@WJpUEgrFre3p@U<nS7>NkpqD*a(rhkJL*felK5j~G$P2Q;
zoc<nJEv7YpIKa+{a3o6xRv9#_$+Q@6@0c_UUdcS~zyWn5;*pPbRp(F^C7)ReN@;Sd
z55iukbr%utuB~O~#0yr3F2OwG2lSOJqw<x^_a$50ECb4QBY=|1vVijs>19Ygmps2Y
zui=vYpG8m4I!SB)2z5y5Yh>ofr7$*38Q0F(XUaK8i9)wB@BAkFXzh81<nE4U%SK)$
zj{bmlUn=XEIM19Zzxa<L`=FupFK0xR@Bfp1XSC@}rMJd~_DAmOro&QO{*X1QLne)N
zb7tP->5(_t+BsAoqYQ)%&?Sr+X?P6V{i;+V3klio?zyGOm?$lSI#0*s{u`kGE`D7d
z$e`MpScU}zBYMs%e0?m{S1ORy)mdIgoqd~H$+56XE2diMkLz~K9)S_snauKVQzBmu
zO@UpZWvX&0>Ed8V>d6Fqe2$z=I~2U1nRmStH%Ce|!{MBc>@y7uHrvhg`>r5?lQcRu
zjk*J2ntB&#wgwkkTF#Jc>FZ<9sYxq=f%fJ&m#alB30H|m5lKZ0$sz-ZY@Q)be4Cii
zk{Dj!FPLDfUU}3~dglpV*)7ZU#KYRiO5igqT7I4M2-%kJ+={-Thp7c@Xty-b$qe#R
zTwGncB$!P7mu5-fxDu0+{+u$C-X&jD?{hz-A=MU7P~E4BbXwQl)ux;?esdx|<yA$+
z>y+p^rwFIg5hKM#E0}e+r-g+N#dKVF8p_JQa|h48AALhiFa$fO4^B~%NjK$=!C)wP
z>aj@sL7*8P78NCm{oG;RK-A6+gU_&-hKgPHYjEk>$gn^&b`OWsQ>ir-i6#)zyOQK2
zKH=0*w>|pfE-X48#7`$4RwT4@j^D+oH3bJ}4-Hvct_v;gtulGp6E8F16E5-_Lg7Z4
n_@J7;hChoIV5xFS4haB-O`b-I-J>%**8uQv^>wLnCTIK?y8eos

literal 0
HcmV?d00001

diff --git a/assets/images/flags/kwt.png b/assets/images/flags/kwt.png
new file mode 100644
index 0000000000000000000000000000000000000000..f21563b5f414f41b7fa843432667a3992114654a
GIT binary patch
literal 372
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!S^|7RT-^(N_6sOWFtOBdi8IVB
z=VxTLVCDM%|36UvoS@oLKDpxps%ad;>dfryjEtN46({mY2e9)qI2tjuW-zd_Fj#0a
zOe$p1S79iQV(83b5a4By7G-EiW?*My$O&PXQp}L-%b+385aq@YXwOg?#~>!ipdiV>
z%f&FgjKRy2frXi&FMqfE)@Y!8j3q&S!3+-1ZlnP@^E_P~Ln02pz39$&C_sQEu$l92
zLQ$XE?1KNl8wI2fi+|d&J(#^>c9+um&vw4cwqDxHILBY9;ddZQ!(S(s3AwHe63dht
zu12vK*mW=%RCh2;D;8wP3l}_)s={>RjSEAD*f~aanIFt0$zpmeA<<JB+**YuOyCN5
zAIxNB>vdp(FYAUo+>Fbr84r}b7x(aBHMswq>CN{~4xQDN2R`o!_y4um`S}M1TTP%#
O89ZJ6T-G@yGywompK)OT

literal 0
HcmV?d00001

diff --git a/assets/images/flags/lbn.png b/assets/images/flags/lbn.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a9ae1dd0e14b5a158493bb2cf3a35fa918274dd
GIT binary patch
literal 960
zcmV;x13&zUP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<S)KE-RMMrQ<@?&ZL|NreAB<&m|{{H^*VrcCgB>(^a?HnZXVrT%S
zQ98PK-16rGr&Id<`~Lp^F}HI4{{9B2RTHdU<n`_S{{8s;`WCHVht;hlvT7-`Z92Mn
zQ^Sgc)T`R^<ubQ(=JxLU{rnuSWO2=&4y#)Nrcx}mZ|C;zSj3GzyL(Z>hzO}xaLt~n
z;lz>Hw9W0^(N|IKVP)rEV1Lr5>G$wo$CBms?E$7z@M34%^5>`E!?@<oH@SDq?c2QP
z(W>FaGq-dIsaK!fy+*!(_51kdUSQ7d-t_zU&+gvY@#QtRbuG1Tx#rKX<H@Mt#CFf2
zIk|VT<jM}JTJZYyIk|XY$dlsr>w?p%p5482&7KFSRkh{KO230AvukS0nZfDQli9Vy
z>ee5yX20mu@A>o;tX|gf<LmhGTgHzGsaGenY&^Ppqu#*M@8I3@=!Mj*Nxy<OxpsEX
zqAj&>l-afmsaQk3eqP6sS;daq^5&e}yQtv9lG(LGy?+?4VJ^0COu&RHv~3ivUm&q(
zPr-+z-@s$Yl=l4jP{N4a^XISQ$Wp?I?D+D<>et5W*bl2)AF*cP^y<6k(T>-$J-d2+
z(WbTK%qz8S5v*KFz=IyJWxl5il>h($3UpFVQvmP(|CR6WpYQKfeRC5400DeSL_t(o
z!((6=1*2e?02X!%01MCnPG$-K=coar20#s9<iZEs@XB&A0u5kg!UH^H<nc)}u>uX?
zz$331$Q>6Gf=2-d0R#NGfj~IQm0SZPdAPaxxVf_;$uxjJLOD4%r@W*nGn^~~gu=L0
zvO#{R(8wUifCL38K?UwY9-e|S=_)b|5GbxKjg<h}ucj@`ty--_h8Oxl&QAkktxheu
z8j=m@oi>4+TQJ%updMt7a=Sc<258I>nbIc$)G8qiBm~>KI!H8Nx}M_1ncNW2)2gGR
zB1Ebe^k#E&t2YJnSa5SUwsdPYRHl+-fRHZt)LGokJl?i^U`J>wrHGPZfIz(L<Vo6U
zs$k77p+G|2mozVkCDw`P=JU&d4B!>u%}e)lG!rMufS@FhdRdSG=8%k`&r5o4^aKZh
z4cX;^mz12ngA=#3DSiWR6=|Z*lI}pt&f3bv0B@1ThNHYRwuG^a3~?5!Y@;>Pr~%Y6
ifZ~ScC>RC90ssKTcvU~5#16Co0000<MNUMnLSTaLarMmr

literal 0
HcmV?d00001

diff --git a/assets/images/flags/lie.png b/assets/images/flags/lie.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b8c77442d3925650f728e78dbf6020c7081c0a6
GIT binary patch
literal 844
zcmV-S1GD^zP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0005$P)t-sM{rC4
zD1-ngg8(gs04jk1E{6aoga9jl&JiX6D}Vqkh5#vo04ak2DS-eefZ@M3v6d><wlkiF
zCIBpf0V#k0Erb9pe*i3k3o&^BAb0>Gga9Uk049MQH)H@RfJID4PD?6KT2=rYWdtgF
z6*Or86-NLaZ~zlSHb`3mC42xSgD*s002D+jJXio2R-B4A>BB7{IAH)6P$?q{02*EZ
z7D@mof{%D011x(3D|izyZviTQB|BXVFmZ`=AwfD75exth3IL;!IXX{d03?0Ywl4eE
zJG-4J8x;W$3IOxbI}i&1orEIj#5b0JBNh<=mVYBJK~w-Ifv%G%hkQRG90iVhAg+=n
z8a8F$y*1&$HuBFjPEkQ>VJ}QiJ|8(@3@vt<fh4}6EwYv?<G(h5ZXlY2C6<CEw3sTY
zktwv8EC1|6x0@_uQy03PEyATQE<aKTDSG3;HuusyRaHL!@I=h3E0ljEpNA%KWGb$c
zDX5MpMoK%jnkynYU!#a3KuuH5t}%~!AOI+ZUtBk%h##7QC9IMuxSTA`uQ98TC0a}q
zabzi>j3=p(D1UP^vX?4vT^O>KDzKF*W>y!#qb_=BB7STma$p;ZcOVoqYXBvAcxD}f
zZXbYc9}6yaYG5seaUh?EC1*?p7ytkO0d!JMQvg8b*k%9#0TD?=K~z}7V_+BsqhJ(3
z0XqeN1_rQjQf2^;tpz6~2CyW=1zK~GYXA!)WApr)0$xTo9!_!$;I@pfn>D+?p)kTm
zg^!bT1GueXn`Ta1FukWTHOx+4gp*_g%wk$6O<2@Dcgn;nfnal4CQ=RH<ZJ2bm^@Wz
z;k??MtPCGrHj-TsR8rq2FlR<zMQ&PVqMsq@E^rAcEAMRYt<Fo&PYQ6=kS5s$TF&A8
zje?~@g4xMl?)u6sBpV>7=@eaD6vZEz;_GIhC`Cp(VAHk_^>=je^!6}Tkl-c505KUg
z6C+i19aB9eNfz?*f;cl5D=RA(v#9VumIni300#wN)PPX~MhzG>V7M7D3P!;w00IDs
WWObVo)C4a80000<MNUMnLSTYZL?;LU

literal 0
HcmV?d00001

diff --git a/assets/images/flags/lka.png b/assets/images/flags/lka.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b6492daa9b79a194b0a84a3eb02bd51903d9eef
GIT binary patch
literal 1757
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

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ltu.png b/assets/images/flags/ltu.png
new file mode 100644
index 0000000000000000000000000000000000000000..dec6babea8788cd571a499454b5ed876cb19487f
GIT binary patch
literal 130
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>ds2i0{MvRwY|6gFyl
z!v+**ED7=pW^j0RBMrz=@pN$vu{fQaAmP^V-=6D-!5WqwVGA2r4|_G3im<Zq<Toa=
ZFg$+O*_xzh-vLz5;OXk;vd$@?2>|$LBo6=p

literal 0
HcmV?d00001

diff --git a/assets/images/flags/lux.png b/assets/images/flags/lux.png
new file mode 100644
index 0000000000000000000000000000000000000000..9cc1c65b5fda9060c2b7b60596700a01192a3a7f
GIT binary patch
literal 130
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uI>ds|NsAISn%MBhB^Dk
zN$Y^(j3q&S!3+-1ZlnP@DxNNmAr_~T6C~Uk{@Zi?Fj&J9;T-62V1v+us8%L1p8Uo{
a76uv9z6R0XeoKMs89ZJ6T-G@yGywqDC?<md

literal 0
HcmV?d00001

diff --git a/assets/images/flags/lva.png b/assets/images/flags/lva.png
new file mode 100644
index 0000000000000000000000000000000000000000..b3312700d81424ed2071c632ccdaf19aa462c9cf
GIT binary patch
literal 124
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSoB=)|uI>ds|NsAAY+!L}3tt&f
zkg+7lFPOpM*^M+HN72*8F~s6@a)N|gL$)Yagux}&2<JeD0}h-$$GBG=FkoVsx;Smc
Uy|Yp0fQlJBUHx3vIVCg!0GMVZM*si-

literal 0
HcmV?d00001

diff --git a/assets/images/flags/mco.png b/assets/images/flags/mco.png
new file mode 100644
index 0000000000000000000000000000000000000000..6c12bd624c047058d63686549bd829330e7a6cfc
GIT binary patch
literal 204
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|e&H|6fVg?4jBOuH;Rhv&5D5x0V
z6XNP#;Pe0g|8s(B$mGAjf6oc4Lj>pk5pe;TP!i-9%&>p|`}dnSzkh#hs)jF6(8kln
zF~s9|a)N|pgD<DPM?%8PPH~GKEs0PA9?^ma;TH}Z*vF->k&tj~{egs#gDaX6S2TnQ
f=yOOYe$`^g`ZJ%o=$rI6pg9blu6{1-oD!M<taM42

literal 0
HcmV?d00001

diff --git a/assets/images/flags/mlt.png b/assets/images/flags/mlt.png
new file mode 100644
index 0000000000000000000000000000000000000000..12809815f7b20a0774facd4765cc04a83335fb4d
GIT binary patch
literal 485
zcmV<B0UG{^P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0002<P)t-sM{rEZ
z!ou#t$lb5B_SV|wv%1E_#Q*>Q&lD@l$;tE0((b{>-K?_m&C=biv-8Z+-K(+YwY$Z{
z#PZA0->|mdvbX8Ezr?+~-><aiyu#nEwCA+D<hQ-VzrXY1<LS4)=eoe+vbp;0?!~>m
z#J#=4wzmBB_UXUG>Au9nx47iEzU{!q?!U(2v$^=}?a0H#%%7srqNS&#p~%F<%ATOs
zqo=sIx5&lCvaztvo}tQ~p|h^4jDUHrtg6Ju#<a4rt*E54u&mdns>jI4!@<GF$H=Xu
zpToexrJb13pQOCJyUEGPv9PYm%F3*%r;&z!mW+jMwhu@E0004WQchC<K<3zH0001>
zNkl<ZSi|kpH5S595JuqylEA~=-QC^YZU3u*f^+Cn%rq4LUBFk2ND@Nmn@KmbZa+X#
z-Ch=u%;!QZpel<B2PpK1_jZE{D5>J+@VKp7rLdg@sO7G<e7**|X52*rqS@>Ia+=Mz
zLUWJ+XQY0fjymf}+GnK>F*80cdI`=NYqE&3?jR8K_*sC(W;Cz>_A>zh000000Dl7@
bgg(6i&?iv9w}`s+00000NkvXXu0mjf1E?3O

literal 0
HcmV?d00001

diff --git a/assets/images/flags/mnp.png b/assets/images/flags/mnp.png
new file mode 100644
index 0000000000000000000000000000000000000000..3e6c538e43fd388aefbf9c9ad5e6f170e50813ec
GIT binary patch
literal 2078
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
IM6N<$g2i$GIRF3v

literal 0
HcmV?d00001

diff --git a/assets/images/flags/mrt.png b/assets/images/flags/mrt.png
new file mode 100644
index 0000000000000000000000000000000000000000..0fd8d757ed1598b116b13ff2a14935240c2843df
GIT binary patch
literal 509
zcmV<Z0RsMsP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0001iP)t-sM{rCY
zZY}D(1kA7s`N9Flt_#4d4FF;@|HJ@4dL{;BGVQ$tRDvQocqrJl2+y(#EpsY|mKY~-
zEB3(xW{DretqekYCWMt4fs`3Db}2A)DHm%l+qMT5YA=408e@nbBycR!vkASc4I6AO
zHg_m{ks1SIGTyfbkeL>-rVx0L8+$zql>h($0d!JMQvg8b*k%9#0V+vEK~z}7?UiY7
zgD?z+3rWZu?yK}z*ZcneKXAYZ9Rh8pl_pin`vu#PA1RJ)CKDqgqek)t8Nho0;`l|t
zdi^3`w|fHc`QrvaJb3Uc;N$y~?isrP7smE!=io1ZavQ^%qSn-E0<Izf5)F{&Yn6XJ
zYu`;s0O!z}_X==t-Gf5{*hOm!+-?x9Ti7H3KWWR#aw+pnmq4C44G?K7sH>j_+K*@e
z8)~>~6lhm)z=i<~v?3-zK9rvWv}aU6cI@XLGoYZgatL_6GAIuSiL>CB-NQHC*oK!u
zpE}O<3^>6f5I9vtkoUpXu7@a`sil-lH4AIk-qII};^>L1F&n8WSy!GKx6&-p%@@|_
zo#?L~=_~)KrMj4l2#CadVg8K<@DBhZBcoDZ3e`to#GLn%00000NkvXXu0mjfyDigb

literal 0
HcmV?d00001

diff --git a/assets/images/flags/msr.png b/assets/images/flags/msr.png
new file mode 100644
index 0000000000000000000000000000000000000000..2d2af3aef0785bc9e2d99bb772716267a512bf4f
GIT binary patch
literal 1502
zcmV<41tI#0P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0008tP)t-sM{rF0
z>goeEnguqR0HVDBp1aQv4*)Zn|NsBY001XasU1qCRj9oOH<bl9n$jH|;)javsHpt?
z{@hVf`TG5PmCE37aRfG+{{H_6IG69Pu2rbM3OSZ$g~B#ouUDwP2{@D2IXS<p!XZtj
z*x>Kb6&1>-xCuI)racGA)aleGCxo5OevrdfslEm_l>s!F-B(utqP_sA#0E5%0yLRa
zsJ#j~m<TzUraA-wrN;oN$pE9l-BeTnf*}Ytm<l?U2{e@jHk1Z6nFlqORj0jGrn~@}
zxe7X$mWh~=mauz}yqZ7}oGk#RDFCoH0HZkw0G_(f4h{f$9sqh80HM7AdLaORA^@ku
z0H?)OrnmsF&Ucf@*+oUs7#M-D#ZIWa2sD&{uEa4~tWT%ASa`Kve7hb*oj6~uPpZOF
ztHP#+d!}bbYk{_@d1QW+oTzP4eUzOSMWLEA0iG@ZT6(uKS*THSw3|K;qm!AUGXQ3R
zxlm_aqmq|5Ua6&PO{RQmrH6l<FaS+yV5DnMqACEPE&!fA4xT*^ra1?sJ`PfFW3Dy;
zP;qAftI^JSS$JC?t~v&gNfWDN4OVbwt2+mnKL-(M767EebxaM2Mhvzz0C$vLt4{~E
zSO;2jU9U?6k3s_geIXKoBmk(&pGp7~bsCFR1g(c4KyOf^R0aT@xB!J@Az~E(nwkKc
zvH+T-SEPUds>nTR63fr00Dwx5Dgd0jq(Kk?D4Lo}TuA_+yIh%50HD7Bbcl40kxg+@
zkGik`d=UVo$UItF7=(;fPfQS~#0EMHX;L0yeGLFM2p^uKK{+L#iafQflTj4_O=t*Z
ziCQ{ND;|<qMV(9lHbwxSyZ~u?BeBK^LQMcG004cGDuRMInME2<Q71Gt06$GsR8T|;
z2{~$S069Y#K1u*eR{$Fz1w~LPIXMC}3jlJ409I!lO;#g3Kf!QdOh`)5&Ao!o)Vb2l
z0G<zGXpE=;0004WQchC<K<3zH00085Nkl<ZSi@sr7zLwX6hMIiqlhRII}}K;adL3O
zII;r#g6wz!*Z?tADGp68Oaqja6onauh%kUlO$*@&gaIJyIaK6`Fo2y&2jK{q0TAo8
z)!B(LfSn!a2pfnapau|SJ(2+kM}Q3=(t2bA;En(p5RKb<ecT3s91$zU!2vWN2AB2X
zeCCqo%=+jCaG(I70Vn`THJ_P`f`W{hIJyCWocI8;0YLpg6PVErz^gwHrZmx&2LvJ`
z!IWzpPA_n>p>QQ&1|++&23SW#J$MrpVI9Eg7LOT->e@n#!ZBb2q+-Q%n9u^yg_XtV
z`jZzgpTE7i*NBBx7sCKK6%IjufoPBcq9TkoT54Pv286$U_W0rb_m6IeV;TUqUQtPz
z8)N`GmnMglDw-ptSy@8DH-36|@8g|t77PO**2}W9LkwVN!gK`C02Y>OpFh01dwG{3
zngKBD+2IDTV>&_?WI)J`r?;+bTL&~i8p!~-^~eT*9btgv2(SxSHeS87dBZB80rE%&
zz^z9y0Okmo0j6LBj_o_Qd$lDCssV88(F}k%0>ywm2acXPxWyXH1?)rtkO7BIpFMHh
zHgx@Tatz3@v|7C5;*tFq!h+ZKT3Ke2Y(PO%&%EV351%<17PMk=S9KoA26*`Tb<bb2
z_53E=&;_&nd_71sK;JpX+d{*C&dTj;Y=dS_vGA@U(E!PWv@9PD4ga~zmM#pQF~O&y
zkR$_~oh0?lQnHIRG&&|Nnl`(?rLN4$nG^$z9n5)o%~ErVDlIxEPVH-}FL8IUBgFs{
z8GA`RUcMyH{PM=u_GZsgcYA2TMr;_E@QI5{I_f#6dsWnU)k^Y-^D&bgjX*<q^&EM5
zc_q!6u-6Mj#H9%zAD_4hu8M^$FlxZ?F<=yof>8hj0CKX<%~H=me*gdg07*qoM6N<$
Eg5{WNbN~PV

literal 0
HcmV?d00001

diff --git a/assets/images/flags/mtq.png b/assets/images/flags/mtq.png
new file mode 100644
index 0000000000000000000000000000000000000000..1897c94e7fba5ea55209a8eef53a28a736083a42
GIT binary patch
literal 1512
zcmV<E1sD2>P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<TUQkR_MMrQ<4J(KZD~KF8kN^Mw|NsC0|Njjuhz%=<4J(NK{r)UQ
zm;V0#^!E8GM3(mV`YcA5_xStx`THqDl`cq_|Ns9DD~KaLlN&dWDn*w5{{ApZnOSbF
z6*7z%HH{H2iV-i0!^+`zh`bLiiIkzr`uqK@x7W76+xhzZ5H5+!(&ZO4jpgX_wZ7U=
zW~uG(_SxO+4lIa1R-iLXni(~YsI$~gWT>C3&_i3I`~3YAFpFt>wPty<=<4$wIglnn
zlp#HmQfR6-P@TQS-u(Uj^7Q!X?DV9s((?28)7k0${r=wK@1Cm9Hcy;yfw<x1@GVD|
zv%J~C$>7%8>RWHFB|wyimc(6guP8&6`T6{VlfpGlo8jf~w7uGmo5yyCybmmiJXD}y
zbFh`7%WHkMEJl}^rOiZJqs`Oi#LMDJVWuufnC9v7ikQV8I+2&8%z}}@+1~6%U8Hb>
zx$Exr7c-28mBXT~(ck0mrm@p!dbIHJ_l1<hPi3e&Ql785*!ueV_V@bp^!Z$HujA+O
z+u!Zz>+{^;?fw1z!N}l1SfS6==k@pcfsw(Do5r}o+|}CZkDbU&Vy9trvC!7&yTjer
z-0R2A<H^wERcfnPZLJ$PkNy7sa)i1LD~MKWtf;coeT~0tezy4e`!Y+KKv$ukprCt<
zzM7hvRB5ZAtkCA^^Yr!kdyBqrfVbM-?eFpT$<O4ov$IiWss8@|#mwTbudn+1{F0x^
z&eY}{IFEphv^Y_nQD&+8{QO>Wuy%y9$j;=5mc+is-y=VhevZGLsm|i&@sXa%bcVap
zI(#+&000$qQchC<hL!K{kDu?KkMHmAkB^_9kDs59dw|v}0009INkl<ZSi|ksS6353
z7zSXPqJZ6ZfenEqL_!IK5`oZ*5PFj)RYU=4B3%I~f+#g~#V+>Vv7lH{{*{yDC?sY!
z7u<1pZ+4UY_Bm%}GV{g6WFs3{Co$VX&7K{bNp|m~SC|pNlKC6Qv>>L|o>_@4G_n2n
zh1}1PslC0b!g4k6^f45v^Xx4;5Yhv-dLM2Y1|06Qp-NHa+<q$Hf48eKKor>~F$~lp
zw47lo6?EV#Vk;RY(3Ju>mGBuRcpgWofKM{1m~e%NG6(8-qm*kBN!*cim=0WvLzodj
zien5ND2J<n8;C-J9S6{Y42Byh#e0SWNW?26z$9|GfKYfO*GW|U87V##;3Tq=^G3Z>
zUp#R#1gMa~V({Bo51J{!3}#qNwr9(5LI<eQKE42`{K<6$Dt*9DTTuv1dy(r;^y&c7
z0X(;?9P&P<iyBhK+91&fTwKoZa~HppkE!C~<=-+0b%3CD8F@6H?p5R-M{Zm_!}S4Y
zQMLL(;dq`fmIV$;?DghAaOXjwTyxj-BRt5^DmX863^;0Q!y=qkR>9hy8ec8oORumd
zfDP6V8v<CY1+Z8jfYn+6D*~9?QNz<#@#q!iI-BWCrtgRPSpmm(uKJWOSnzT)yq%pt
zvYPU2I`HK)K#E2T1HmuPPZy7;#dK1Evv0c!h8^-{qZA<FcpAf`u=KtV!p27t=0G9k
zL{bl}8SHiX5Y(G(nMDXkUwDQFBggt6@;J^!=NLp70b)7(f)~1-xPd?@JU9Rscp5p@
zA8L;>dS4h&w^<K55RVQnpa8ZLF254+JU~tXypbE(a<H3yR3<kBxI>CLW#&XHloUXS
zL@3fv2e;ye4&b0^+5E4-l=`$SLcc!Xujy58(ZHL0ax)C64j`^LQW9CyOMdA?Q%OtF
z3Y^jh#207%>hF2uHR966?>gtS)4ei;OF{+MzU-{UC1KyW#`v11|Aye;egz0E<%K9K
zq%lLSWnubrzz<)&z=l@gGA}~ELJgR1rDprKO(eVa(ko0i{-|$cz2py>q(XXyhR6*7
O0000<MNUMnLSTa6?Gjx8

literal 0
HcmV?d00001

diff --git a/assets/images/flags/mwi.png b/assets/images/flags/mwi.png
new file mode 100644
index 0000000000000000000000000000000000000000..7ddfbb17be5387d81a23b5a02c7dc7aa739685a1
GIT binary patch
literal 754
zcmV<O0uB9%P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0004uP)t-sM{rD?
z4IK{w1Je;F*b*q54IPdQ8UO$Q&JiXvo;5NA35E+91ONeq3mA<I8XyA(3jqR!3mMN5
zCJX@r(h(;R0Rtri2h|cMVh9oq0RoT=8z%z?4gmv}3>=yb95e(8n++VB4INkq5J?6O
zRtFFu0tRad6kZ4s7y<>83>%3H8K4avRR<3t0|ucD9i9yxatRet2M;j>2_6CkbO{v`
z0RvnI5l{vXGXx1D0|qPv2nqoLq7EK`3m9$*6nhF6;}a^03>l9M8Y=?`mkk_M2M}Ng
z63`JQOa=}w1PCbv2vP?R+Y%_;5-GnBBU=a&<P$151q*@;7|9VO9|H!B3mViBCk_Du
z2mu0g3Keh(6;KBcoDCe93><k17JmvCehL>|2oX623&#*7zz`%H0tI9U5{e8NgbNwX
z5hf-B2a60EO9l>g3KiE9C{G3tnG76P2M{?03O)r3iVGTh3KlvA3yTXHnhYF#3KvNR
z4Lt=50{{VO2^5wL8-EKIfD0IC2osJA8j%bedQ95&00001bW%=J06^y0W&i*I6iGxu
zR9M69)5TW9P!xsXMs9A1*WDd2?(XjHP~6@1#bMCJ>WrI);rSon8|`f}K@gM+8|W`U
zOQ~u~D-`fOeY|n$H23~;WiJ3&h|2e2|JSGDc?|``fo8pcy0&tD_mD_NV#&nK^(ty_
z)CUYINIAK<ja#K>Eq)nWoDFvgdVry$khr@=W4G`a4bpgi(j^DDCUU^Of%Z4OIJ-XP
zWLf9V)C_iv%c!-M7>H1NE-yab9%U>%Z?TO`FJnhvCsjuZRC7H`L40;P$LC_$UM#fv
zJ!OPIh7yN;hX)M*o2|dwU2m=^B?GMH@|p$-O|W@&v`AHzCB?MfDU*GHHxK{-0FVb1
k83+IX0QgS;f}o$i0h%dmrr`Jm$^ZZW07*qoM6N<$f-M~1c>n+a

literal 0
HcmV?d00001

diff --git a/assets/images/flags/myt.png b/assets/images/flags/myt.png
new file mode 100644
index 0000000000000000000000000000000000000000..c149a2a7915e8f29470c49d149045f3ec42d7d58
GIT binary patch
literal 2003
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

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ner.png b/assets/images/flags/ner.png
new file mode 100644
index 0000000000000000000000000000000000000000..87bb8211f7ac853a62d28d6b0cf4f93cf28eb1f1
GIT binary patch
literal 494
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I14-?iy0XBj({-ZRBb+Kpy0*;
zpAc8~0-yh2aKxRJcZ2qWAT}W4Y*B!4feZ-y_uoH%|NVWEqy6vi-+%x9J;~8g+GeY~
z-43V~s2-?MahuJPY^{Gl>2IH(<{LZ+<$79V^7rSr2O*pvHuU}d`tk4A4^J{R-Y>0t
zoGkz6)0+>g+y4VqfBW<}Md5L}%DV;Szn<Ru{p#V<eElaGYESbGKdfm7TJ$(W?dScA
zzn<QFoTB(RUG?3<@(8`?Dxl*<OM?7@8Q$LyzW@HdfBbt_ugLrF-vin2?{l6he+5)<
z$kW9!B;xSf>)ZL74FnnzFID%?Wof^6sk;6@`{@QD<<rwX`0{*T&p!W1A{!6$;jWPF
zD<fSQvO+dnF>xp;u(ENVJ;r39^r>c<1P|*1mE9UY_h{6*H|B($W3+knrSQGK#DpXJ
zTU&Wp-uyfjE|9SI=>Z|8A2X-Fo5heYnNf$sp-g6jqj!(RgT{sjf9@}2w)SW@*!#bP
zWuD8Sb>i1I*{Yupe5bun^7Ar@FDwa0*K@QO*3L`|Wf5?2;3|=twe{n72JMjeFITor
Ua`K*e8|WJbPgg&ebxsLQ0Iw|U=Kufz

literal 0
HcmV?d00001

diff --git a/assets/images/flags/nfk.png b/assets/images/flags/nfk.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e68aee4f51473519b3cd5c1a72425ad9eb9f7d6
GIT binary patch
literal 1422
zcmV;91#$X`P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00093P)t-sM{rC6
zdOHPtJ^*z!{{Q|1dp!_>LI8R_|NsB>`u7TdKmd3*|Ns3BfI$FyI}?OOK$>0#eLnd6
z_yKx6-R<G+_V4KO=pBhjTc~hYrfnI8MMRuqSf_Inf<p*;IskSzFp*UYd^}#NcW1AD
zD2+`okyB-@c>ezV=kn;w<I(i_^yKj7@%Ql9>)Y$}>(l7hv)8>+q;Tx@?Bej^2!23d
zt8|gWpvU3MtkbvX^XmY1IY*vk4uC!2@8bOZ`^DhN@%Zvys&pELM1Z`JCX7x>pJXYI
zQCO#NVyk&Ilv!)Ac@=|00C+Pum0c2mKOKlm41Yi$iAR0Aj0k)<e!7lKp=V{Sdpnm`
z2zx$AonHWWI%BMMDvwM-nO#YrX#j9BGn7_)xrYdSJ~x$AB8x~FghT>(IUtBgJC{==
zi%4y;fq}e<8-_qZnqXb2Yb%XTERau7qG|d3`CzDdZL)>{a4h5S;{5&j<?-hLc{mz}
zOeT(1P@{5HrD`CGQ9GAnyxYOi=hd0WrwD#N1bjcX*uOiNTeaA}Tc~m>kXEzTya01E
zYOsHe!kpFV+Eb%!c(sWsjYwv%f^oBiW375^vVw@fn8Dt~Sfp^U)wJB~-dU)21$#M`
z$f1hCo}<pLL7QV&qil-7mXO4sh`ySt(X?W$bD_<xYp-{CxR5=XVm_HvM4Mu0u6$st
zbpUxfJeXZzsdY4zQ9P7cB8yMZ=F<*+KrNA0KAB#e%BO6ve*ktkABjwbzKu|$Z+W<e
zQ=@Kzyp|e;M@*hqMV(?nmRtjOFjJ##snW8j(Xeo`ffj^EB8*I2s&ls2ym_~Ys?x7D
zlv=piy`apfE|OS#xQvX!mH=!gb+m^^ooZF3a8;pcMVePZnOSzWhEAbr&E?ZKlvr!9
zeTBS})achGhe<JxQiQ&eVXAM1zKnjlh6{Z@7=%7$t#o9pZz_#WO`>d4qhxxygBgWL
zK9y2xu6t0TVqvLwE00iQt#>DiKLB$sM4VbBi%LP7S0IQ&Xb8?z00001bW%=J06^y0
zW&i*JJV``BR9M4fU>F6XU=%<BI|kt7<iG+rIWbk@FaSxHojMYS90QEYC^LYi!JIM!
z%H4a^DKdaZT81JQY`vVTG)t5M11`LHlYDq4*#@ZdynI&>b7wybxdv!tMgGYwcze%*
zTmwWCzx>O|NN?6B(*X4kzyAxQt4Mw{CewfiU%waTseb<U>p7VQJc-SZQ~R6yGxg~S
zvJ5C+{4BpvA?=4+*4hKJ^~f+l=d7Gc_9rR+gd};zN#wX-{?X{X>{st!^D|kwO=u_G
z0PUq-+z}5Y0%c<Zxt;o*g-A9)GnkuCSVbUJYSSEcR#vA*(!CILj5#GiLDoBlQFz;`
z>0NrH8XyvKSNhg**F$XL^6PhaDooQN)qs<?!(<d>j(Df<UFWjJW8-pCy`XOYc*>)s
zcxJ{urvA*Tp=)<KkZ6F|Dd*_>;i0~)Hmk#Zx!AUEo=c(uM#_%K!SbiAW&M_gtx4P9
zwPKMFX$D-ncHUjdU+xGS6BDzKQ=-Sh#iSWve?vJaC&DB^kexSBm^H=IaKQ`<QVg&>
zcU6&>H7d$Yf}hQriIrb2ZtCP-OX3aS*?0X4TRhvD-MgoB^0o;x2}DXtI7(`h-~y3@
zH!muMgu7U=x3F_FciT*K?QpC$A|(vEb_w_e@QQOa3k%oO8|sR*Hkla|kzzpKl9lr;
zY(;eK1?zYys@g;atIH`eK*OX;i!uYaxHKp-prW!=lOh9jN{aO<YvP~)`WZlCGj9}(
cf>8hj03A)(@>(8DN&o-=07*qoM6N<$f^I;i3;+NC

literal 0
HcmV?d00001

diff --git a/assets/images/flags/niu.png b/assets/images/flags/niu.png
new file mode 100644
index 0000000000000000000000000000000000000000..acb36780d835e0a31b796d3ee1abde693b0b20d4
GIT binary patch
literal 1095
zcmV-N1i1T&P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<TB2Y|JMMrQ<&lD@q6f6AE762${04QkOwiDd86a3K@{LvQr%^=}!
zauz#v-)40uNq@e=((u^b?BeIp95Ng~c>B;66F76yBRJ96<NyEv>YAkf{r&XF#?>@P
z*+^RL@bnHeaLv`>SaO{2w7heLsr=Cv04QkB6f5wxyxB)t|Ns97EoINv;#YB-`|R%i
z`}@=|L=iS}8$WmqGH(qtaPq^+2{3I9GjD>Hwea%x+D>2Cke>ej{@aY2c!{goke>0p
z!_zB3+fQKg#LDOE@!VEs^vlqCkFd}gDtU>k?C<n)h^v8)uGKY3?C<l{l%jf$u-sH%
z{r30px4hCMDdTD(`_L9~gs9+UR`$}@(<Lb)M0NDa$rCqh`|Ica{rCR)^y}^H6*z6&
zl9|;pKY@>_>6oGsHEU&kq<M{~(AeYOWpw@d`S;u2&lD=wH7DR|dF`mM(jzIz&fMKl
zBw>1?+)X6kVOHN@R@~w0_S4teL?zWPC*ECFhnl$EPbA@ABHmOZf|0T1fsN1_D%d+F
z;A2+TI40j&Bj4ogDN2AHKzaMk7W(Py>FV&}-Q(CtS=~}3I6QB_6)y!VW>qUrs+ure
zUP)anODsBY0x4%<Wk_moMadK_vlcS3pDw}`E~J(+p_DTpBwmdqJ=i)Xf`+E67d6u-
zDCvV9lZrT!ia4ehHrhrd0VihwCuj5Z`1#Kk?%w0k94h(97MG1Sk&molVZ4w4001O(
zQchC<fA4pH?`UuDe}8{}e}8{}e}8}Pe}8{}cYp8i@9*#L@9*#Cdvn_W00EmxL_t(o
z!((6=1*2dTi~<;tl#&n^W`O`6K`}-l0X`^Cl%JQ8n~M`4U<Mi>qhW7tVQ!!b0!Dgj
z&1$-aV78g9mA<8krV3ub0W?6_&j)UVkzU)17O(+O?VfIg4PZ45gBxL_w`B7gpaF30
z#;QaZpsETtqDwDw({kNTgmzUT3{cbof|8<wtkgiw^?J(|uh!kzly9P`nVAlf&>?Jq
zk~#<kfl2kPYgesXs*Wr|*Z?LqAP5c#22pdSt=zC>)_f4NFeEY;L=$O1X=pKsnly8P
z%Dl;QLCmVqb~WM*kktT!^6)Ycr7>~g?5Q*QL9CkaR<H<R0~EADph8nqGbf^_clx3!
zeVUrtl@Wm*U~z4tqEXe%-&fPgQQxjn59ny!T4zmH7Y7?}aOxz+0GM_UV_;IA08GlJ
zUI-%y8z2wY4ob=m-SwcPj4*<*0djEdAOouF@*tTBW&~jaqyv(ZQWCYmAST}3-90u6
z!b!_Wh>H#&Y=DRg1ps6K$EX3L28<doNDN?OrvR{xHjhTZC>RBB003-GJDtd6z_b7W
N002ovPDHLkV1h723KReU

literal 0
HcmV?d00001

diff --git a/assets/images/flags/omn.png b/assets/images/flags/omn.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b6cd8b3b898d8791457cf9979f55756f568e8aa
GIT binary patch
literal 711
zcmV;&0yzDNP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0004WP)t-sM{rEq
z5f<7H6xj?B+Y}kv5*OPS9RL6S+ZG!DfB@PP7}^jO+Z7ty7aQ6V7~n88*$EEX5f|JW
zAlV2F>vwtGBq-h`D(GNi*$WWpW@z3hEazHW^sB7g9U|*^dh(v2+Y=b^mzeH~i}kRv
z;4d@ZDlYcCz1a&9-6JRCMM&vwaNQpy@}Q#PJ3ibVBiRZM-6AI4Bq``&WA?tj;W<6p
z4HNUFrtzJh*$NQ;>FD4yH`oUa_rbx~0|@3+SM#T+*$ooe2oCR&lJ1F%`_$9yczW6m
z65AOb?~sw-C@lHS%;;rk?R|dXIzIf~-Tvq1``Fm)dVJn0FWC(f=1^1G4ioX4o$!{J
z?SO*&+uHin)9{j%;4CobSX=wZ$Kf?N)&Kzh<>d3KtK1kJ`o6vSzP<U&%j#@y{MFOw
zUt#4}TKwDF<xo@UW@*;|1^m|4>ThxQy1D$y$okLE<3vaDoSo}-dG@li^|G_`q^0`3
zyz6*-I-G?z00001bW%=J06^y0W&i*I0ZBwbR9M4fU>F6XU=%<B2Nu9iBtRIzBgnzQ
z&CSBb%0iw2tSY(=f)Qcvru_V@WEsGsXCEY779A>Nrpia27aRkV^0EpN!aW4Y^8!~e
zOIl88MM;#X8y7hSu!zNrWfm4^r=}-+8t{-|fWEVTWOZeJM!86Ur4BP02C$mA`o!j@
zRK<we8ENv7VE~u5xr<+7QJl9evpN$mS<%QS<m46NYa=2|W<pXB&@#5NwlGvvVqzpK
z7GxEbHJI7hn0V!7q`1g1fLmIQgPRQ$noN@7j2y%RL>Ndw{LaC{%*aNL0px;F14a!P
t<OXmO2}TVVHDJ^LY8o&KM!_fm0sxo=Wg}O5c*Xz#002ovPDHLkV1j_hPXGV_

literal 0
HcmV?d00001

diff --git a/assets/images/flags/per.png b/assets/images/flags/per.png
new file mode 100644
index 0000000000000000000000000000000000000000..490a26441ee935007fff2056dc8c2d7042ee60a9
GIT binary patch
literal 123
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSoB=)|uI>ds|NsBLB_#FOEh-l%
z$XF8O7tG-B>_!@pqu}Y{7-DfcIYGj$AzM^HhnKZULm>O$iUTVSB#213F)-)|`$*)Z
Sd(Q)^W$<+Mb6Mw<&;$T7r69Bb

literal 0
HcmV?d00001

diff --git a/assets/images/flags/plw.png b/assets/images/flags/plw.png
new file mode 100644
index 0000000000000000000000000000000000000000..6f6ff993a1377710bb411730b1bf47ece87c3571
GIT binary patch
literal 608
zcmV-m0-ybfP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<R^H5AwMMrQ<|K0#ft<_7d)Hi{kK$p8pt=3Ad);EEmK$p9l!*%}M
z0B*LctjA%?&^*G;M^>=Mi@u0Vt<#*tbgjr=g}smQ+7P?TP+YRWg}ji>&^utWyRpby
z`P>HV*cOeyhRx7AO|H?*&^+eX99yx$qs44tv$}e^oci1aQm@R<(KqYZ7pKN&{oMlm
z-2%DGQjoxc#?C^6ypo>7a=pw=ugG1?&po2VZQRr-_uB~W*%M;3xZu?z*V8U%w6o>b
z9&5I)p~P-buFh+<u41#f#Lh(f+yuAERMOEjS+T@evBbN}PhGOVce$VT+X_#v&uX==
zTfOks0000AbW%=J0RR90N?HH!PhaKSQicEk0R2fsK~z}7?bcUQ!cY)~VKxZ_LrWnb
zN>QZQP*f~{GzFyl|9_2)afS)(#cp!LjOV@oo|~MUBoGjZL{7mY9|bpn8uF1UfWroK
z`{pj4yl;C1J`!X2E%N>#@qzQ$Eo?h0ae>P#aCP0~0p<zplwYubGVJvwGl0|FJ^%&-
z$Rc~_NMyiFVE{zQKos4>BN-^*z!Mp;aG*#AG#rSN0Rso-WT1}&8X1sVDDX``NHJ{x
zN<T=U<2MAza9$?lIXp`oKpySxFJ`<8W!-S^dll}LCJ$=cc_g8GxKuwUD`#GhFFjuC
u!>W~RzSvXoZTu&I684cIev?I_zkUF37e7s?&h>Es0000<MNUMnLSTZNQzPgA

literal 0
HcmV?d00001

diff --git a/assets/images/flags/pri.png b/assets/images/flags/pri.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb0c54cd634d4bc546c3dd02bf5fbf084019aaf6
GIT binary patch
literal 1880
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
SCijv60000<MNUMnLSTYByLe^*

literal 0
HcmV?d00001

diff --git a/assets/images/flags/pyf.png b/assets/images/flags/pyf.png
new file mode 100644
index 0000000000000000000000000000000000000000..66a5da6b82ffc63d15dbe66b821fd4f36a021983
GIT binary patch
literal 1256
zcmV<E1Q+{>P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<T&`?ZNMMrQ<-CJq@|NqVrCe9Hi{{H^mTWZb`CjbBc&JiZvTWSBC
z5C}b-J!i51r6)FFuK&k)|G;R=YITaE(Es=B|McbW^7u4gt<&7?Pj$GyEIbK5od400
zU4Xu9jKra}+5f?5|IUhKhQa^Lg#XHc%@8I3qay#zh5wupydpEX4<Y^i{_*tr^7Q%s
z{{GI`>-hTo%+~7v_2=j8^&L&5qqo|px!b?Z<t|&R|Ns8~_UW*}-^|zQowC=`-0i$6
zIi<MUMsBtL{{GjYr@F}FVuQf!+0Osx$GQ?EzA8HZwN12dcD^e+$`B?0+NJ-;djICc
z{QLX=q96ahWB=W*|I32cs;>XrsQ<%nYl_3qf{JX5#GbR*#}Fh>bhw(Y*8lR~P<6Qf
zvqzn4hX2Zd|JtXILP^FECI85L|LDm7;<~;qJ^!pY|D6>7tvSnqiL_~Y|JkIYw%Ve$
z+W(vqk*U+5X>LAev7fZqsIbkDPgQxA$)dK|zAio?QKnUSx*<@e(TkHxakguT!DEEL
z<Id1~m&*RAF1k5Mu!4sF`0oGNrIxGH$&i+}jgZBorqQ>#PIR~jJ)HfsOb$YxbCJgX
zxmSgj!vDBc&a$-s&WSr^u+zG|yUF6cmzu*7CI727$*QcpM^*o&D79~aqoluqnaEpy
zy~WYz{;4zn!fXGrL#I1N|FlZ~)0M1AQvc74|G8HG*P#BsWAdm<|DhbjOj+^7kEA3q
z|DYPIR%*x)B>%;8|EVzlyIU$$q=Ydzs46$aqNVD(iOY?a(6X<*Au-#hk=vz<&a$=K
zteChWGTXzyP*{@x$$s0CW89i>>Zo129xwmRhu6Ww#BqB6zGVN*gYdn9@ufwz5F)pZ
zk-HBf%B!x*q?^X1r}U;n>cE$?hl|Rrul3BD>#}p%!N32!U!iJm^2Lw46eirr$+!<8
z)498!XKcrLfv)Tg>;M1&3UpFVQvmP(|CR6WpYQKfeRC5400F2;L_t(o!((6=1*2e?
z02X!%01MCnPG$-K=coar20#s9<Dvkt0S#bfq5!Z04dB2j>lC2qZ13$B;ckgj2?ss{
zL^FfDq&xz{x%2!)$uS^-FGnTV(>F}HL?)NdigW`+x;OF(WcV<r=g(NJCg3kZvH^nJ
zhu61fNij1Et=h6?GPeS$26V04d-33A!EB%bTW{=GIW5(QL<2VL6g+Wy-=<oi0oR`1
z+P;=shC~DQsA-%(rl8W=xb5omhj(sjEDj~n0L634$2HF!?Vow&@x5nSFRu%vkZ8aH
zZte@3Cl_|kdwcuQ>o*U$xsymVpm5gZQ<vuSl}$MG?*3h^C+g}UBpTpSH2duQ-m0{o
zr3YTTf3<&kjWvk|7)#2}?NE&^m^gLOZq;2Y+FW%>O-RDB{FPD3%}PqsmmFEfA1zFB
zO4Kot=8fZ#uIHUJMYfK|LYwr=q-W~L8(&)9Brn$>X=gxAcGfp@h?Fa?XsM2|H6*J%
zU}7>C=Sk$}5w~H&TcF@A(!?Yr#0V8>jFc3rjH5Nvr~%Y6fZ~ScC>RC90ssI#){;<h
S1YsZm0000<MNUMnLSTZI;k5q%

literal 0
HcmV?d00001

diff --git a/assets/images/flags/qat.png b/assets/images/flags/qat.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e8461e918b676d6b06ef7dc202530a61b7d9fcf
GIT binary patch
literal 2021
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
DVNT%K

literal 0
HcmV?d00001

diff --git a/assets/images/flags/slb.png b/assets/images/flags/slb.png
new file mode 100644
index 0000000000000000000000000000000000000000..d63061a0bdbae2d2f63096e88d2884ac3022baef
GIT binary patch
literal 403
zcmV;E0c`$>P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0000*P)t-sM{rE%
z#w5<T9Eg)8|Ns9aTr;MnP9a+}08zU9(H2m8hV;!BLTxV<T&x>o!F8e9JbKE0r`%ME
z(JgSsgsa~0_51Vp{C?QMe*gdg0d!JMQvg8b*k%9#0Q^ZrK~z}7?UTt4!ypVqyU<d)
zWo`feQ(HA9m|zCuGou_VIeIS|#k*ZgOUpkOU9NlQoF4EvI~M__DJ<!X^v)duU>L%d
z&Pabdo;+ZD8}k~MEuFFcZteO7y)nJt(;4b50d(`+`8Vhc^%U^@Jxk~e^%NlNKh`q<
z-2Yae01Evl`t%D>|BOBbfc`ms3dr`)>mvZXg^WG|fLqAw2>{(fUT-D0fb^1Efco++
z6!grmEG=IIDC;pmphp0a9sp$eEI_Ky0mOP9P@!i5HF^e6r%wTu`YoVZzX8<iBY;Lv
x0V;g}DD^8qtM>r4-UHNn0?_F_prxhdn-4c(NzPq;_HO_H002ovPDHLkV1h~uug(Af

literal 0
HcmV?d00001

diff --git a/assets/images/flags/slv.png b/assets/images/flags/slv.png
new file mode 100644
index 0000000000000000000000000000000000000000..e597e45b35c16ab3347d0ba96a8c69c1023aa335
GIT binary patch
literal 642
zcmV-|0)737P)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00009a7bBm000ie
z000ie0hKEb8vp<SK2S_lMMrQ<(cJIQ+wTuYumAu54L+F;LZl5onGQmv4@a;6|Nqk5
z@Y3Ax|Ni~|`Q-ol=>Puy|M}x;e5?QY;{Wo%`|rB{`s)Ajy#Mvj|M=Yh?yUCfxc~g|
z|MSNF`R0$Qhwtjcw#2Rf@U_6ty8r$8|M}tZ>Aknfwg2<P`|-qyqk;eT*rT<W|M}(p
z_~ifZuvU6ea*k}Ev9n}`Vyn8l-Qmi*#ICixvsidsrLn^P`Qv4SU}%JQOms(Bd0J_T
zX#e!c;@`7mfMoyp-T(2r_w(GXxu9r(gJ5){SbJRk?5D7|vQBPb=jrWIkA(L2^pv8z
zu(!*tx6A9vw70aMT6Sfjq@3^5$XJnrLx6eE)8DhW!`r_j=-|OcgnPEU(AvN{?86S~
z&aJ1hWbyLz>&mT$mcE>(!ghk0*v_w(9@1_A000VfQchC<@9+QbXlQS5?|*P*1ONa4
z)Ja4^R9M4fU>F6XU=$1%z{WuVU;`S!$xH#@95rCnfI(vbBR4+4!-H3v5oiDl7f!&d
z?c!yn&yQOH7Ykkk1T>tvqWpOUCCN2F*VQ{EGuGE!Pl8MX9Nf~PQ<KsI%#?V^GC<Wa
zR461kJWR+*O^hr9R7`y`ViFUQJuDRX$TC1i)7mp4GS1J=P)>lnFp$-;4~h@8G*%QL
zGZ6WtwQSvO4CF=m$uxjVSW4Z*NLgGEe>z~omyqEE4!|^89*i0=d<<Y^rvR{yHW5d`
cC>S&V0B1l$f=6x+FaQ7m07*qoM6N<$g4exNn*aa+

literal 0
HcmV?d00001

diff --git a/assets/images/flags/svk.png b/assets/images/flags/svk.png
new file mode 100644
index 0000000000000000000000000000000000000000..06bed756e409718851e95508f471888f930c72bd
GIT binary patch
literal 521
zcmV+k0`~ohP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0002AP)t-sM{rF0
z#>nzjTZO05?HnWuPNDXWlI|QO|Ns9BPNMEAGWe>k?<zBer_g7S#Ti+r^l^6ZM@{*v
ztw(yf8d<1Ug}#_CQ;ITM(9qz*(&+Vngu>J3Id8PlA~gNu<k8;k{_*nq#>w@7h4NKg
z?$_RYHDg0Ug0jcrHARY}yxjV@yYATD?8?wMZ?oRa*i&1T@kdVIA1rM+YUhHCDP*l*
zJ8~vSkt$@aScbp%oS*Y!Xzw^bVs7Wy00001bW%=J06^y0W&i*I14%?dR9M69(%Ejp
zFc3gd?Ao5#VF_iYrDbiQ3v_|5|Nmcg9Ml99AY)$VDpKafCnGDR5=Bwlf-@q3fLws7
z-Ozv%F2<r{7-E6`76^WlVT1*^J@hL?Xa{4QQ~=Ov7u+3UH}T_UeY^uex{Vi5H$nyO
z<p(ImxxE7(eb@Z}mc3CQAPkjaf&Gb?ClD9kLGnW&fv^4^@Pq_DLwD?T)#$jv+#><q
zHG|FDU@oQXwC~y?s$zla`-e=MJvOm`?yWOG<<tT>!1Yz_|9oqq@jyms^_s;1*zINc
zoa}#DhLhz1P=2V?WTQI<@B{!R)7v7SKMdF{0L}w|00OW8MNzgt4R%dpI>-2;00000
LNkvXXu0mjf!>IX0

literal 0
HcmV?d00001

diff --git a/assets/images/flags/svn.png b/assets/images/flags/svn.png
new file mode 100644
index 0000000000000000000000000000000000000000..a791163bdb7a8b51b179b37b375547fd808b8496
GIT binary patch
literal 1963
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

literal 0
HcmV?d00001

diff --git a/assets/images/flags/tkm.png b/assets/images/flags/tkm.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c3ff87556a0be9719ba1a55b8f806c673345076
GIT binary patch
literal 1620
zcmV-a2CMmrP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP00093P)t-sM{rC4
zVMMz^C;(_r0BKDCXiE!WO#o_60BcVGY)$}XNdRL;0A)w29y6LoFt`{r4rfcU6E6&8
zORy9)i7GjmLof<&Rn|oxt1B;ZEi({lN|7=((M2K7KqJIAB@}gAW~G#?5Hk>EOS?lS
zqZ~DyNiN4%9<m!T!!#+?LLtB^DxVW8$vh{(Q6j%BEnF-vS2ZvXa##p!Pa}V4GKX=L
zz_cxeZ9k5A8+u@}(#rk*{sV1M5MoRbY)HODCJA3olPNg3JSu=KIpSv&rX?`NAS@tb
zMwC1=o=q$kXh_jKB%3TTgE2n47%zM*Eu<PPydf>N5i+$NGPM;m>1PbZS8k~<K(Av`
ztSmXLBQ{EufLWi61!+yl-`Tm=&YUJTxjretOC!D}F0d;wsz@yWW>BIoGB#d9?|=$w
zK0dQGD~V??YDqk^F(Pw9H_j?3WlbrlEj{>s33E##$3`J?9w>=BHriDgb2crfCpWqt
zFw8S0lQ%5HE+l>#CygOBa6(JBB`cm`GR;UJe`Z5JQ%_NMP~1x!WLZ?sa)9E9df9m@
z+o_}3z^dx5a{uSZ?7(^dtu%A3op!IFiMp<Yx2oXn>VmeZ-RtPl<=~{sz~b)fkV`SG
zGck=QJx*3WdO<e;Yf@ZMI?+QGIBr5ZZ$cbzNN-s#kQyrHaS{252bdZy!ABlTTu*>I
zLfeg#SXxkdPcnxvH_v)5?0`yxD>95eKCF9Th)o@5DkyzTBTzXnP&h2JCq2|jRmVqN
z&r&?xmY=^&WPUP6a&kR*T{gsH8jyK8t5+&kOisE-DYa%Lr#~i;V=S9EE2bDWWqwe;
zKqE+OUyE*1qjE>HJyqFqYSmy7#Bnm-m^HLcN`+r!%~D9&Um3@FZozduZ(~mFu(5zm
zRkVyZL2y{PC@70WOX#1a+-WJmK2*haVU%EN!fjW=VMx44LBfuNy@i6iU@_E;INNv&
z-?FZvTTD<JF}`zH=70yBRZRM}aplq2+r!D?ekA(6e*kDrSsNkF00001bW%=J06^y0
zW&i*K0!c(cR9M4fU>F6XU=%<BI~Z`zDalm{i;z%}uuBnOCl(+Xz$~g0+WGKJce$J#
z6B{QP25{DdKED^<&~|0>VhI5bkO&JaNd~ZsbiI<i{ql9|<t>$97qEzlu>dJ97Ghl>
z(tiI*$D?Ou*VY#bfeheQn8L%wYG{Jj1Y{S8*4};b_(50C!O&c=7g*#i#7vDDqbG3_
z8;F{XPsQ(a9@?v;%my@oi_65^NWp?DCf1yXI4^j3=>!Wa3JPk-D%-NNSewN}Pv+ra
zWoI<CWF*oB;#KD*nzK}bWPvVVmA5qJ0*f<FpT^EYR2cA81$0~pIew{8JpmL3hCB*W
zL2hTXoI#ucoSRObKAX~f>gcfz4objSU}ZHn111D+3#(bgd4a>J^~9Nrx+Ujy*NWJH
zQz91+3oD~hoRtZYf#~j|d!(hksZDKNniM!1#Vicvqh?wuFcKM!eEETgTSA%|gk9~}
zzy=sana0kJGiM|=C8~;R1p5a02I|Q$LGl7SkF~rQ4-e6qNmWyhU!9kiA83FSRGNjA
zm4xifSFK%VuxEFvwid(-Bxh%L|DF0y+qO#Tub3-EjsfgG6+0yNZ9h=It74uFIRy%b
zk6*E*Uikj{0zYs<BHaai>UH`C1_t`2+KvJoWR;1UyxM+}lB@lJ*_o^|(ZfrY9|XYJ
znH(>OiU$Y_@(K!9$tsf-jqH4`-qLx?^Q5JH6NJc02ht1Nay$z>b37Nh2#^(x4(Zm}
zOP4LlUT7OnRyyExPn)0VR_vCUUY1N=H1g%EyLfN(cHwm;FAzc5Sy(VISU3ruok=x7
zQ%(_BJ1c6*Doc@7JM&c+zW+Vp$Bi&8GE-vB)!zP|@a~B>C6dX?&Kx4|`hI==_VZug
zEnXpVT#(9l{nNz1-@o+tzFlKamH{3`5g$KK`17GMM2##1n5Bzk6eA-e6}475l4Ssg
zh<Jvcu&}WDN@o=z@(kd2cGl35E6+$G(*P&lEH&N4L^USfcoGd51*2dT0097q^zg8J
ST*{sR0000<MNUMnLSTZ78?H$J

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ton.png b/assets/images/flags/ton.png
new file mode 100644
index 0000000000000000000000000000000000000000..84cf20ef5c2f712f2c66e49bf7bbe8c0a37be123
GIT binary patch
literal 139
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSoB=)|uI>ds|Ns9#$iPsxcz!5Q
zkg+7lFPOpM*^M+H$H3FYF~s6@a)N|ggQ*BpnBxJaHB5o4SLjb*U9$XAOoN)Ax=2#Y
j>VN|)7(`jx1Q{59v1QBn&Na~j>SgeB^>bP0l+XkKsbnVU

literal 0
HcmV?d00001

diff --git a/assets/images/flags/tuv.png b/assets/images/flags/tuv.png
new file mode 100644
index 0000000000000000000000000000000000000000..15478f1914ef86b45bace3e01667bafe221e5617
GIT binary patch
literal 1456
zcmV;h1yA~kP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0006yP)t-sM{rDa
zs@%^H4|A#B%m4s%s@!y{-F2$l05h5Y|Nr~y>T#*z4nd&<HJTktr6*FUa;e~Rs@`y^
z;?f-*;)jadQBnE&{d<+lf33}Ss@ig?-|w!j?x?8z{r+Z!!r*Xm{{H{hIXS<p!XZtj
z*x>Kb6%~Z8#eJ;McB<KLsN<Bgum98t2|At1r?|<~>C`7Dgq_ZQki#}!uXCy2d#uxO
zso;65)qJecajD{+wxNEk&v&cXYp3drvAT+|ywk-~bE(~Rs@iO)>2IjykFvITtJZ3#
z>vyWy?#(K2spHJUTx_T4=F2ydvazwdg_5(eYp3bi$4HvBrvK9php)o_(+khUS7@g1
zX{YSnS6AIsRE4j^fvw7ovACGDsF1R>|JDGTwWRXTBD}wHgRaNW#a3>p<+r_R|J4J^
z!eF<(d$zrO!og~YufX}y7I>@IskxA-xRP_K-SEyOptqZ(xR&C|JDjzn_s|=+y?m*;
zk7uUv@y;fdv#q1Im*B}hqqmsv_4{{|$k|0j(HI!fVQ1i|uBNz@fv(Ez^ZGq!w1Te4
zv%G)*(h<?dPU*}s&cs;LcYVRYY^}P9mb0t)&>H>H66wq^!@+3n%`CdUcI3=5_Rk;M
z$U(QgdgseDqPLlIs^9$47j3BL+Q&%x&>C;4<Hf;c$HHUS$4c+bD4DgUpSGQ|ynt}1
z;?>4ZFkG+u(HEVzqL{R){?ZYkx196P8i=sKth$T#&>h&vNyH!~!W0_M4i0qa4c`C&
z00DGTPE!Ct=GbNc00SgRL_t(o!|m1ATiQ?<25@6MIe}CKTntBDfZ!GZaqm5G@BO&<
zXsxSi_p-Zo?`3QEu;YJg24E1Op_hGlZ+Ol{e&2hNli=p&iYu;|(!}=<@Wf3y?C!zy
zGB1LCeNIA$p@EP{886n`76=au_2Zx60C>m5?UmRA$nk-^h_f63+%sXXgc+d62gOGp
z;sW3}S)!RKVFH-(i8yW_K-s`v2^uhu#~lDztAq_$N>IR>dAtLl|H+^s4PygTi47T#
zM*{2S@pb`BQ*rCr=6!h*4e+c&0_+?=xPY)@Yhdgl05tI1!$E!>3;^Qky$50evjs=j
zd;GMyR)P|QFsnDEzcSARSZ~3@-ToE;gb0Ft|CT->MMQwWteyfM9UsK^Tc-ipMo5C^
z0XMO5Cs~l%xUjqXC2ik9B9j=w3-s|_qksT^esf%mw+*mUGif-gsQsZ<XSSgG0D63A
zShyDj;NG!3StL_}4TyA$U+Wu|mRG8m%d@NjW_&P?GXU;sDZv7SijmLi=~ex))sGFy
zR$DNS$1MPEDZvI>Qf@EK%xkB{3$0%!%Xl_GmuQNMdCz`*a$1Meq5uSdT1gQzU>R=(
zm`Yr>J_M-<^NXNF*LV_O0L%D&0A1q5zL&ssAo9iHGL=HZ9A)Ti0Kl|8MHjkD&Y@fZ
zAc6#HULZ;d6c$%^PU{HB5kTebIeBdYW<fN}RyGzJ`erseI0Kll`eNB>6QJ6jE7{J_
zC~{I;G0qLrFLhq;!ssU;T`H@qdp9aTvoREM1g3PuC66<ETBP)<p<?WVs)~J(INZeC
z;y!UHk_|+d2*TlvngzX+0C*%Pj{tG49i0%9k0eTx%^g6<odb=sDoF?Qty_08OR3Ka
zfZPE<0!h6u^F}J4r&in;xLGc=`Db!;xwK04DNTTtzEZy~%&omTc=!A%E#?FOGScfa
z(=(Jq-Nqv?#K{HnD+RgGnFiAG6{B%Zr5tT5ny)orP@(|PDF7Cv80%&m5rJqjUyo65
zF?13j-o8m0qP|~Qi2c8JM}S1T6P2%|o+kV^;BWa~09Rabh0GtgpTCXfl!Nd90000<
KMNUMnLSTZW74L8W

literal 0
HcmV?d00001

diff --git a/assets/images/flags/ury.png b/assets/images/flags/ury.png
new file mode 100644
index 0000000000000000000000000000000000000000..c41e2780a85f64e8a507342a73468d8149819e59
GIT binary patch
literal 1017
zcmV<V0|xwwP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0006~P)t-sM{rEt
z-QE2B{J6Qh{{H^h*x38~`~Uy{063`q{r&j(_lkpMiGg1I{r|_J0JxnXx|$HhxrM);
z5rl3G$E6YAx)jo`62hSn^~)9f{QdIt_4)exyu82O-rnu*@8aU(;^N-#@ACTk`sC&1
z{{R2@`1$$y`uh6&+St_H-QJ#?kKy6t?d|RU{{N4NYvkkP?(g#I>+J9D?d$62jfZKk
zu(70|li}do>gwvcx2^g4`QhT^>FVsUuA{rPpZ50n`1$*_v!=eeqW1Rns-uUkshW+3
zX_|*Ok%(jH=ik@Qs-BB7@9*%Nn2Ooez@v{g;M~aK-_)3gJF~2g>+9;?*uUlD*p`xh
z=H%Yh&$y<LGQzZSyO{{7jvT0t9Kf@9#G??soDayU9q{n*%cv5%nh(mR48x-l<>J@k
z+`7cMhTYe{y{uxup%<l*JD`q0zOj1L%%{AZ5x=l+*3h}OnH<f+kE4eTz^`Pal0u<{
z4Zffrs+dWhi!k)`^w!Oz<KND^nhn{~u)UxZ%c&OG)xzA@zoC#u;oj1<mJ#vt^u(hN
z*s~MYvlHp*==aYSwU-gKm>$KuklE6)%BK;hk~PSv6Q+$GqlXO1rxWSI6u6lY>%$er
zx{k)VgXH1Q%D;==*S)!!59Q#@!J{3gjULCR6QhO<r-}{3p8>(Nd%?1Bx|<T2e+=fn
z6vwC`xt9mIm<`aa63VC%$fyy%uWZn)62!QF$fgmyoDYg}48)%R%BKy$pAp2P5}tz$
zyq_b!of4XV4CTHQx|$Nms2kkBe&GNB00DGTPE!Ct=GbNc00C7=L_t(o!((6=1*2dT
zKmj`ifa(S?QDT6a4LhePivuesxdxbrvvYay20Oy!IEVoV16Zwj^UIQ>Lh?e{wOPqA
zz=EeFJEovCKCvN^M~8F+fd0;it4L~0NvqC@4Rh9zCe;8<*QU&3zJ#ju@*=+IdUrE9
zl3n0b)12EW(9_>5Ak>oTMS3i#+eZj?uMiTRBfNLUge*@ZB@zu_V|J_MUnU|UI!jby
z$25L#6J|D&(?OTuqP6S9c8MK6v}ax)ISFaOhV>%i+qP^HKX_p0R2NlJ1JTg8ec|er
zYnE@`zi;=}`2m))q#D3v%-*_m)siVQj~v}T-H)uKtk2!Cc=p_hlQvEc<d!GL07e7$
zwn`uWy22nUMMiQAU}tBswbRw(V%Jh2H#>7GtFXwhuuDk}Xpu&q0UQ*7Q3FsD(%`7t
nMibI#LK?~jjDk@x3V;9rg1U^iIWS=v00000NkvXXu0mjfiLp5y

literal 0
HcmV?d00001

diff --git a/assets/images/flags/vat.png b/assets/images/flags/vat.png
new file mode 100644
index 0000000000000000000000000000000000000000..d6c99cc1fa8f9c2e59007f7eea3372c248f0fb70
GIT binary patch
literal 851
zcmV-Z1FZasP)<h;3K|Lk000e1NJLTq002M$002M;0{{R3owtGP0005_P)t-sM{rE7
zt*zL#SJJdt`19@G&YA!H_W%F?|KI@q{`~&;`1<<#_2S$3?dbjY`uOe5_~WVl{r&Fj
z=l%Nd;p5`Pr-<j}=GCgI`tQ;F`0e!L;`Z$4`tZ`*wYBo*!sO=V(7%uP?c(vjIppNz
z?d|RN?9J+`0o$dbz^$;;*4F;{`t;q|@z~h)<F51R(de@z&$Vdt>eBe^-_gE@_~o(q
z`T6ta!`P-#^y99?U|_(&!0oy*w0mvnwzSUB(DK^a&8kc8#ZlP2YvRq3%yV<-)3wgF
zXt=el-=~-M=eF_Hf#<MD&Z$e~<>l<E0K==G`02d<`~U3U#LBHv-mx+M`uyk8v%0&#
z^xxjp%(K_LZN<jM%db_^t3>YJy6w0lxw4(*%#GN+ZvOuM-MypTo}Tpd_3zGY?#5Ql
zcqHVqx8KW~*S&GnwtM5sfVjH5(yK${t*yVq#=EGd@bdKKv9$B><m10=$CfSd^7YoZ
zdD6<U>FVpp$jRThlK%et;;Kmd^yL5i{_V|f*T0SY{r|_7Ec5W_>&%$@@zcDxtKg<M
z>%zwG!aUJ?d(G0(-kg-<l^@7lT+C~5^z!V{&%?5clg!Gj=g3&_(rdqQOXjyT%Er_E
z{`<_*(Co~Y{Qdj((OdZQ<NWj3)rX15c|+Ebm+i%HjTg%;00001bW%=J06^y0W&i*I
z2}wjjR9M4fU>F6XU=&~g4lIBj3m7$E)PSLEfQ$rX25=hcaZ+M{k(-Z$fg-sE2(y{7
zL@_ZrvB(K>lVyOaF>6>%L2R%qtAY?&2AH}>#^o?GCj~j{OOj)NidA?*c2!$NZeobF
z5<eLRC^JUqSGUaXD9?*`R1+Y_3%-oC?NjG0Z!XL5(<Lt&Yg*aoE}gZ2oh^X8Xbf#y
zylCOXY4fI325OOIKtx0D>=_f5P46o5*CxvV&-D7vnUg2=mn7TClVyN~7kgv(lD^_J
zc1;no43IMS&aCSxO|j7s<sr)eK4}w=tin`VbunHpva_?ji=_@_1&XZrXrVf4z=$zm
d6pVrq3;>9FVF(zeEEfO(002ovPDHLkV1io13+?~_

literal 0
HcmV?d00001

diff --git a/assets/images/flags/vir.png b/assets/images/flags/vir.png
new file mode 100644
index 0000000000000000000000000000000000000000..a57f924b23e263813f2978b22e903aaaca667425
GIT binary patch
literal 1987
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
VuPKmh{mcLW002ovPDHLkV1je&7L@=1

literal 0
HcmV?d00001

diff --git a/assets/images/flags/vut.png b/assets/images/flags/vut.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c4d6e42954adcf6210e991cba9fdba76a392691
GIT binary patch
literal 1267
zcmWlZdo)xD9LIn6UNd**y7L|(gci+Y<uPSNWSA+FvPh(mOhQtT8q<TxY4gaVBebHI
zlN@S2N?}{H^pIDlBoymWvS-gk(Uw-*UHixP`~Bzh=jVJge0|olh{Xf|uoPZ0|Alq`
zKMZW4FVvsV0-#~O8w2F)4{R*^3BGngNitA9K)n<&ad^gExqv}|=ch+ds0L6wo{WVr
zkKtVl+$)Cc1mKWRl?}7^0n%Lg902FVbQ+KZxX?I9l~B#HMge)>3ibKmPZu_`Z6BAy
z<XuPz0i`ccV?t^|2xmPY#~rqd!B7`s?KFg0JI4Xobnr40qBOv<IEIl3BhKks5(v6{
zDa34nSGCZ01D=$_*d3ty1sDnj0$64S5;1^?Z*ByzT;S~rMvGvr1T0Ko^$OUg06iYq
zEdwuS2#|pe2HI90H7a!c9tLZ;C<=@CC{BYV1`rd7r^YY|2C~M17UE40_M+QZfV~Lw
zlY%}U<*|_7YL3_(lR43bZgHsr!QpU5*(uUu2^zHpH_=DW9oOx+#yK5Nr0-{PNW^0m
zgnGkV2Y>zv-(IW}xE}xTh(FQHO9*FBLjvlBz<Mc0y%C1_;39MEM=4F)#;eICsYzk&
z8CF>)IdYrpE2SsxWT<vB<W4jefsh2EQZoB*a!OKkV}lrZYC>d&ZIRP0Ofc%LFjzrv
zC}8o~2u=rA2c08ICKE^YZD;J?#-IiT4q~0hSJ`<g;&V4YIf`j(g;Bly^T&0qOtBL&
z%-XZ8@h0BL9qtNC%*GNkHAFYM(ewq#P#xDzLbEhM3y<i|_V8OTvL{-&o7`w4zj1kN
zq$-DGlZbQ`jT#qTODFdP;u0|y6@c&E%IGR*NBH8Q-gw(3wtd(=(*==`M1P;n;Qn@C
z_kwnw3Yj!uYumemi6Eh$!NUyIi^*q}sUlHrY(2kosa2-*<?!$@F<>(g$~dg5rwZ<N
z4Gmw=D>|B1J$tNZ_2k8Q7fFlDv_vWmys`D^vu01D-Wc?<vb^UPGz;i|Pxle<fJFZJ
zw33r<MJ%C{2GNVo7#pthtIg0biz{U$+j2v9T~SR1qS3A_{d#D|u?a4>E8c`y$M$kS
zI4LOW&c9WGnTaI@qQt9Nn_MCNbarV?yHk9z+r6pK?LXM4c6g^|lpf5J#U;4EZgPp*
zqb&~VIy91-ZQfyG8@(BO-V(nix<UQ={P79nC%svn-)%6p*|nLL|26)Yng|GMjNDQB
zYkP-Trme810&Nzr9iftD-hcXXz2nrE<-Zr^xtotE$+$|*NKW<K+?8?Xz4M)gA20>U
zxpFdpSDmrm`_6C7{X70>N<{i{`kEj3eUKRj(@@RirIw)P<dX-}a<#*a9Vv}#E|8_@
zinT{SkJ}&kxGPjX7?Glhx-Wx<xxc;*_TGNvV>~pqZS+-7+R&Vy#$>*7L+&N#8hNl&
zfvq}r9RqF*Hca|fco$XK2;W4@`>SkX#mQ}TiT^rAJ{87M+K@e!FR$>jGSJ=PDz)U;
z%<NF)NE5Cc*D%kPZ+dQ$GQBVKXVPpG)ApBJD`&tBT{ra&AN7p>vq}xs2%_pnl6cI<
zd3`&@bq}fP1cW_oo%#sV)8R=v%H43$)c;P2i>szYesk)hCc^8kZocT9565oIhf@>r
bAk!rUX)G!uoFj`v|9>fk+(%aB5uW-V^z7Ux

literal 0
HcmV?d00001

diff --git a/lib/cake_pay/cake_pay_api.dart b/lib/cake_pay/cake_pay_api.dart
index f403ebc63..1f91b338d 100644
--- a/lib/cake_pay/cake_pay_api.dart
+++ b/lib/cake_pay/cake_pay_api.dart
@@ -3,6 +3,7 @@ import 'dart:convert';
 import 'package:cake_wallet/cake_pay/cake_pay_order.dart';
 import 'package:cake_wallet/cake_pay/cake_pay_user_credentials.dart';
 import 'package:cake_wallet/cake_pay/cake_pay_vendor.dart';
+import 'package:cake_wallet/entities/country.dart';
 import 'package:http/http.dart' as http;
 
 class CakePayApi {
@@ -171,7 +172,7 @@ class CakePayApi {
   }
 
   /// Get Countries
-  Future<List<String>> getCountries(
+  Future<List<Country>> getCountries(
       {required String CSRFToken, required String authorization}) async {
     final uri = Uri.https(baseCakePayUri, countriesPath);
 
@@ -188,8 +189,11 @@ class CakePayApi {
     }
 
     final bodyJson = json.decode(response.body) as List;
-
-    return bodyJson.map<String>((country) => country['name'] as String).toList();
+    return bodyJson
+        .map<String>((country) => country['name'] as String)
+        .map((name) => Country.fromCakePayName(name))
+        .whereType<Country>()
+        .toList();
   }
 
   /// Get Vendors
diff --git a/lib/cake_pay/cake_pay_service.dart b/lib/cake_pay/cake_pay_service.dart
index be8e1d189..39f2ca77a 100644
--- a/lib/cake_pay/cake_pay_service.dart
+++ b/lib/cake_pay/cake_pay_service.dart
@@ -3,6 +3,7 @@ import 'package:cake_wallet/cake_pay/cake_pay_api.dart';
 import 'package:cake_wallet/cake_pay/cake_pay_order.dart';
 import 'package:cake_wallet/cake_pay/cake_pay_vendor.dart';
 import 'package:cake_wallet/core/secure_storage.dart';
+import 'package:cake_wallet/entities/country.dart';
 
 class CakePayService {
   CakePayService(this.secureStorage, this.cakePayApi);
@@ -23,7 +24,7 @@ class CakePayService {
   final CakePayApi cakePayApi;
 
   /// Get Available Countries
-  Future<List<String>> getCountries() async =>
+  Future<List<Country>> getCountries() async =>
       await cakePayApi.getCountries(CSRFToken: CSRFToken, authorization: authorization);
 
   /// Get Vendors
diff --git a/lib/di.dart b/lib/di.dart
index 14fdbd56d..540a546fd 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -1271,7 +1271,8 @@ Future<void> setup({
       () => CakePayService(getIt.get<SecureStorage>(), getIt.get<CakePayApi>()));
 
   getIt.registerFactory(
-      () => CakePayCardsListViewModel(cakePayService: getIt.get<CakePayService>()));
+      () => CakePayCardsListViewModel(cakePayService: getIt.get<CakePayService>(),
+          settingsStore: getIt.get<SettingsStore>()));
 
   getIt.registerFactory(() => CakePayAuthViewModel(cakePayService: getIt.get<CakePayService>()));
 
diff --git a/lib/entities/country.dart b/lib/entities/country.dart
new file mode 100644
index 000000000..63eee9a18
--- /dev/null
+++ b/lib/entities/country.dart
@@ -0,0 +1,386 @@
+import 'package:cw_core/enumerable_item.dart';
+import 'package:collection/collection.dart';
+
+class Country extends EnumerableItem<String> with Serializable<String> {
+  const Country({required String code, required this.fullName, required this.countryCode})
+      : super(title: fullName, raw: code);
+
+  final String fullName;
+  final String countryCode;
+
+  static List<Country> get all => _all.values.toList();
+
+  static const afghanistan = Country(code: 'afg', countryCode: 'AF', fullName: "Afghanistan");
+  static const andorra = Country(code: 'and', countryCode: 'AD', fullName: "Andorra");
+  static const angola = Country(code: 'ago', countryCode: 'AO', fullName: "Angola");
+  static const anguilla = Country(code: 'aia', countryCode: 'AI', fullName: "Anguilla");
+  static const antigua_and_barbuda =
+      Country(code: 'atg', countryCode: 'AG', fullName: "Antigua and Barbuda");
+  static const are = Country(code: 'are', countryCode: 'AE', fullName: "United Arab Emirates");
+  static const arg = Country(code: 'arg', countryCode: 'AR', fullName: "Argentina");
+  static const arm = Country(code: 'arm', countryCode: 'AM', fullName: "Armenia");
+  static const aruba = Country(code: 'abw', countryCode: 'AW', fullName: "Aruba");
+  static const aus = Country(code: 'aus', countryCode: 'AU', fullName: "Australia");
+  static const aut = Country(code: 'aut', countryCode: 'AT', fullName: "Austria");
+  static const aze = Country(code: 'aze', countryCode: 'AZ', fullName: "Azerbaijan");
+  static const belize = Country(code: 'blz', countryCode: 'BZ', fullName: "Belize");
+  static const bfa = Country(code: 'bfa', countryCode: 'BF', fullName: "Burkina Faso");
+  static const bel = Country(code: 'bel', countryCode: 'BE', fullName: "Belgium");
+  static const bgd = Country(code: 'bgd', countryCode: 'BD', fullName: "Bangladesh");
+  static const bhr = Country(code: 'bhr', countryCode: 'BH', fullName: "Bahrain");
+  static const bhs = Country(code: 'bhs', countryCode: 'BS', fullName: "Bahamas");
+  static const bhutan = Country(code: 'btn', countryCode: 'BT', fullName: "Bhutan");
+  static const bol = Country(code: 'bol', countryCode: 'BO', fullName: "Bolivia");
+  static const bra = Country(code: 'bra', countryCode: 'BR', fullName: "Brazil");
+  static const brn = Country(code: 'brn', countryCode: 'BN', fullName: "Brunei");
+  static const bwa = Country(code: 'bwa', countryCode: 'BW', fullName: "Botswana");
+  static const cad = Country(code: 'cad', countryCode: 'CA', fullName: "Canada");
+  static const che = Country(code: 'che', countryCode: 'CH', fullName: "Switzerland");
+  static const chl = Country(code: 'chl', countryCode: 'CL', fullName: "Chile");
+  static const chn = Country(code: 'chn', countryCode: 'CN', fullName: "China");
+  static const col = Country(code: 'col', countryCode: 'CO', fullName: "Colombia");
+  static const cri = Country(code: 'cri', countryCode: 'CR', fullName: "Costa Rica");
+  static const cyp = Country(code: 'cyp', countryCode: 'CY', fullName: "Cyprus");
+  static const czk = Country(code: 'czk', countryCode: 'CZ', fullName: "Czech Republic");
+  static const deu = Country(code: 'deu', countryCode: 'DE', fullName: "Germany");
+  static const dji = Country(code: 'dji', countryCode: 'DJ', fullName: "Djibouti");
+  static const dnk = Country(code: 'dnk', countryCode: 'DK', fullName: "Denmark");
+  static const dza = Country(code: 'dza', countryCode: 'DZ', fullName: "Algeria");
+  static const ecu = Country(code: 'ecu', countryCode: 'EC', fullName: "Ecuador");
+  static const egy = Country(code: 'egy', countryCode: 'EG', fullName: "Egypt");
+  static const esp = Country(code: 'esp', countryCode: 'ES', fullName: "Spain");
+  static const est = Country(code: 'est', countryCode: 'EE', fullName: "Estonia");
+  static const eur = Country(code: 'eur', countryCode: 'EU', fullName: "European Union");
+  static const fin = Country(code: 'fin', countryCode: 'FI', fullName: "Finland");
+  static const fji = Country(code: 'fji', countryCode: 'FJ', fullName: "Fiji");
+  static const flk = Country(code: 'flk', countryCode: 'FK', fullName: "Falkland Islands");
+  static const fra = Country(code: 'fra', countryCode: 'FR', fullName: "France");
+  static const fsm = Country(code: 'fsm', countryCode: 'FM', fullName: "Micronesia");
+  static const gab = Country(code: 'gab', countryCode: 'GA', fullName: "Gabon");
+  static const gbr = Country(code: 'gbr', countryCode: 'GB', fullName: "United Kingdom");
+  static const geo = Country(code: 'geo', countryCode: 'GE', fullName: "Georgia");
+  static const gha = Country(code: 'gha', countryCode: 'GH', fullName: "Ghana");
+  static const grc = Country(code: 'grc', countryCode: 'GR', fullName: "Greece");
+  static const grd = Country(code: 'grd', countryCode: 'GD', fullName: "Grenada");
+  static const grl = Country(code: 'grl', countryCode: 'GL', fullName: "Greenland");
+  static const gtm = Country(code: 'gtm', countryCode: 'GT', fullName: "Guatemala");
+  static const guy = Country(code: 'guy', countryCode: 'GY', fullName: "Guyana");
+  static const hkg = Country(code: 'hkg', countryCode: 'HK', fullName: "Hong Kong");
+  static const hrv = Country(code: 'hrv', countryCode: 'HR', fullName: "Croatia");
+  static const hun = Country(code: 'hun', countryCode: 'HU', fullName: "Hungary");
+  static const idn = Country(code: 'idn', countryCode: 'ID', fullName: "Indonesia");
+  static const ind = Country(code: 'ind', countryCode: 'IN', fullName: "India");
+  static const irl = Country(code: 'irl', countryCode: 'IE', fullName: "Ireland");
+  static const irn = Country(code: 'irn', countryCode: 'IR', fullName: "Iran");
+  static const isl = Country(code: 'isl', countryCode: 'IS', fullName: "Iceland");
+  static const isr = Country(code: 'isr', countryCode: 'IL', fullName: "Israel");
+  static const ita = Country(code: 'ita', countryCode: 'IT', fullName: "Italy");
+  static const jam = Country(code: 'jam', countryCode: 'JM', fullName: "Jamaica");
+  static const jor = Country(code: 'jor', countryCode: 'JO', fullName: "Jordan");
+  static const jpn = Country(code: 'jpn', countryCode: 'JP', fullName: "Japan");
+  static const kaz = Country(code: 'kaz', countryCode: 'KZ', fullName: "Kazakhstan");
+  static const ken = Country(code: 'ken', countryCode: 'KE', fullName: "Kenya");
+  static const kir = Country(code: 'kir', countryCode: 'KI', fullName: "Kiribati");
+  static const kor = Country(code: 'kor', countryCode: 'KR', fullName: "South Korea");
+  static const kwt = Country(code: 'kwt', countryCode: 'KW', fullName: "Kuwait");
+  static const lie = Country(code: 'lie', countryCode: 'LI', fullName: "Liechtenstein");
+  static const lka = Country(code: 'lka', countryCode: 'LK', fullName: "Sri Lanka");
+  static const ltu = Country(code: 'ltu', countryCode: 'LT', fullName: "Lithuania");
+  static const lux = Country(code: 'lux', countryCode: 'LU', fullName: "Luxembourg");
+  static const lva = Country(code: 'lva', countryCode: 'LV', fullName: "Latvia");
+  static const mar = Country(code: 'mar', countryCode: 'MA', fullName: "Morocco");
+  static const mex = Country(code: 'mex', countryCode: 'MX', fullName: "Mexico");
+  static const mlt = Country(code: 'mlt', countryCode: 'MT', fullName: "Malta");
+  static const mnp = Country(code: 'mnp', countryCode: 'MP', fullName: "Northern Mariana Islands");
+  static const mtq = Country(code: 'mtq', countryCode: 'MQ', fullName: "Martinique");
+  static const mys = Country(code: 'mys', countryCode: 'MY', fullName: "Malaysia");
+  static const mwi = Country(code: 'mwi', countryCode: 'MW', fullName: "Malawi");
+  static const nga = Country(code: 'nga', countryCode: 'NG', fullName: "Nigeria");
+  static const niu = Country(code: 'niu', countryCode: 'NU', fullName: "Niue");
+  static const nld = Country(code: 'nld', countryCode: 'NL', fullName: "Netherlands");
+  static const nor = Country(code: 'nor', countryCode: 'NO', fullName: "Norway");
+  static const nzl = Country(code: 'nzl', countryCode: 'NZ', fullName: "New Zealand");
+  static const omn = Country(code: 'omn', countryCode: 'OM', fullName: "Oman");
+  static const pak = Country(code: 'pak', countryCode: 'PK', fullName: "Pakistan");
+  static const per = Country(code: 'per', countryCode: 'PE', fullName: "Peru");
+  static const phl = Country(code: 'phl', countryCode: 'PH', fullName: "Philippines");
+  static const pol = Country(code: 'pol', countryCode: 'PL', fullName: "Poland");
+  static const pri = Country(code: 'pri', countryCode: 'PR', fullName: "Puerto Rico");
+  static const prt = Country(code: 'prt', countryCode: 'PT', fullName: "Portugal");
+  static const qat = Country(code: 'qat', countryCode: 'QA', fullName: "Qatar");
+  static const rou = Country(code: 'rou', countryCode: 'RO', fullName: "Romania");
+  static const rus = Country(code: 'rus', countryCode: 'RU', fullName: "Russia");
+  static const saf = Country(code: 'saf', countryCode: 'ZA', fullName: "South Africa");
+  static const sau = Country(code: 'sau', countryCode: 'SA', fullName: "Saudi Arabia");
+  static const sgp = Country(code: 'sgp', countryCode: 'SG', fullName: "Singapore");
+  static const slb = Country(code: 'slb', countryCode: 'SB', fullName: "Solomon Islands");
+  static const svk = Country(code: 'svk', countryCode: 'SK', fullName: "Slovakia");
+  static const svn = Country(code: 'svn', countryCode: 'SI', fullName: "Slovenia");
+  static const swe = Country(code: 'swe', countryCode: 'SE', fullName: "Sweden");
+  static const tha = Country(code: 'tha', countryCode: 'TH', fullName: "Thailand");
+  static const tkm = Country(code: 'tkm', countryCode: 'TM', fullName: "Turkmenistan");
+  static const ton = Country(code: 'ton', countryCode: 'TO', fullName: "Tonga");
+  static const tur = Country(code: 'tur', countryCode: 'TR', fullName: "Turkey");
+  static const tuv = Country(code: 'tuv', countryCode: 'TV', fullName: "Tuvalu");
+  static const twn = Country(code: 'twn', countryCode: 'TW', fullName: "Taiwan");
+  static const ukr = Country(code: 'ukr', countryCode: 'UA', fullName: "Ukraine");
+  static const ury = Country(code: 'ury', countryCode: 'UY', fullName: "Uruguay");
+  static const usa = Country(code: 'usa', countryCode: 'US', fullName: "USA");
+  static const ven = Country(code: 'ven', countryCode: 'VE', fullName: "Venezuela");
+  static const vnm = Country(code: 'vnm', countryCode: 'VN', fullName: "Vietnam");
+  static const vut = Country(code: 'vut', countryCode: 'VU', fullName: "Vanuatu");
+  static const btn = Country(code: 'btn', countryCode: 'BT', fullName: "Bhutan");
+  static const bgr = Country(code: 'bgr', countryCode: 'BG', fullName: "Bulgaria");
+  static const guf = Country(code: 'guf', countryCode: 'GF', fullName: "French Guiana");
+  static const bes = Country(code: 'bes', countryCode: 'BQ', fullName: "Caribbean Netherlands");
+  static const fro = Country(code: 'fro', countryCode: 'FO', fullName: "Faroe Islands");
+  static const cuw = Country(code: 'cuw', countryCode: 'CW', fullName: "Curacao");
+  static const msr = Country(code: 'msr', countryCode: 'MS', fullName: "Montserrat");
+  static const cpv = Country(code: 'cpv', countryCode: 'CV', fullName: "Cabo Verde");
+  static const nfk = Country(code: 'nfk', countryCode: 'NF', fullName: "Norfolk Island");
+  static const bmu = Country(code: 'bmu', countryCode: 'BM', fullName: "Bermuda");
+  static const vat = Country(code: 'vat', countryCode: 'VA', fullName: "Vatican City");
+  static const aia = Country(code: 'aia', countryCode: 'AI', fullName: "Anguilla");
+  static const gum = Country(code: 'gum', countryCode: 'GU', fullName: "Guam");
+  static const myt = Country(code: 'myt', countryCode: 'YT', fullName: "Mayotte");
+  static const mrt = Country(code: 'mrt', countryCode: 'MR', fullName: "Mauritania");
+  static const ggy = Country(code: 'ggy', countryCode: 'GG', fullName: "Guernsey");
+  static const cck = Country(code: 'cck', countryCode: 'CC', fullName: "Cocos (Keeling) Islands");
+  static const blz = Country(code: 'blz', countryCode: 'BZ', fullName: "Belize");
+  static const cxr = Country(code: 'cxr', countryCode: 'CX', fullName: "Christmas Island");
+  static const mco = Country(code: 'mco', countryCode: 'MC', fullName: "Monaco");
+  static const ner = Country(code: 'ner', countryCode: 'NE', fullName: "Niger");
+  static const jey = Country(code: 'jey', countryCode: 'JE', fullName: "Jersey");
+  static const asm = Country(code: 'asm', countryCode: 'AS', fullName: "American Samoa");
+  static const gmb = Country(code: 'gmb', countryCode: 'GM', fullName: "Gambia");
+  static const dma = Country(code: 'dma', countryCode: 'DM', fullName: "Dominica");
+  static const glp = Country(code: 'glp', countryCode: 'GP', fullName: "Guadeloupe");
+  static const ggi = Country(code: 'ggi', countryCode: 'GI', fullName: "Gibraltar");
+  static const cmr = Country(code: 'cmr', countryCode: 'CM', fullName: "Cameroon");
+  static const atg = Country(code: 'atg', countryCode: 'AG', fullName: "Antigua and Barbuda");
+  static const slv = Country(code: 'slv', countryCode: 'SV', fullName: "El Salvador");
+  static const pyf = Country(code: 'pyf', countryCode: 'PF', fullName: "French Polynesia");
+  static const iot =
+      Country(code: 'iot', countryCode: 'IO', fullName: "British Indian Ocean Territory");
+  static const vir = Country(code: 'vir', countryCode: 'VI', fullName: "Virgin Islands (U.S.)");
+  static const abw = Country(code: 'abw', countryCode: 'AW', fullName: "Aruba");
+  static const ago = Country(code: 'ago', countryCode: 'AO', fullName: "Angola");
+  static const afg = Country(code: 'afg', countryCode: 'AF', fullName: "Afghanistan");
+  static const lbn = Country(code: 'lbn', countryCode: 'LB', fullName: "Lebanon");
+  static const hmd =
+      Country(code: 'hmd', countryCode: 'HM', fullName: "Heard Island and McDonald Islands");
+  static const cok = Country(code: 'cok', countryCode: 'CK', fullName: "Cook Islands");
+  static const bvt = Country(code: 'bvt', countryCode: 'BV', fullName: "Bouvet Island");
+  static const atf =
+      Country(code: 'atf', countryCode: 'TF', fullName: "French Southern Territories");
+  static const eth = Country(code: 'eth', countryCode: 'ET', fullName: "Ethiopia");
+  static const plw = Country(code: 'plw', countryCode: 'PW', fullName: "Palau");
+  static const ata = Country(code: 'ata', countryCode: 'AQ', fullName: "Antarctica");
+
+  static final _all = {
+    Country.afghanistan.raw: Country.afghanistan,
+    Country.andorra.raw: Country.andorra,
+    Country.angola.raw: Country.angola,
+    Country.anguilla.raw: Country.anguilla,
+    Country.antigua_and_barbuda.raw: Country.antigua_and_barbuda,
+    Country.are.raw: Country.are,
+    Country.arg.raw: Country.arg,
+    Country.arm.raw: Country.arm,
+    Country.aruba.raw: Country.aruba,
+    Country.aus.raw: Country.aus,
+    Country.aut.raw: Country.aut,
+    Country.aze.raw: Country.aze,
+    Country.belize.raw: Country.belize,
+    Country.bfa.raw: Country.bfa,
+    Country.bel.raw: Country.bel,
+    Country.bgd.raw: Country.bgd,
+    Country.bhr.raw: Country.bhr,
+    Country.bhs.raw: Country.bhs,
+    Country.bhutan.raw: Country.bhutan,
+    Country.bol.raw: Country.bol,
+    Country.bra.raw: Country.bra,
+    Country.brn.raw: Country.brn,
+    Country.bwa.raw: Country.bwa,
+    Country.cad.raw: Country.cad,
+    Country.che.raw: Country.che,
+    Country.chl.raw: Country.chl,
+    Country.chn.raw: Country.chn,
+    Country.col.raw: Country.col,
+    Country.cri.raw: Country.cri,
+    Country.cyp.raw: Country.cyp,
+    Country.czk.raw: Country.czk,
+    Country.deu.raw: Country.deu,
+    Country.dji.raw: Country.dji,
+    Country.dnk.raw: Country.dnk,
+    Country.dza.raw: Country.dza,
+    Country.ecu.raw: Country.ecu,
+    Country.egy.raw: Country.egy,
+    Country.esp.raw: Country.esp,
+    Country.est.raw: Country.est,
+    Country.eur.raw: Country.eur,
+    Country.fin.raw: Country.fin,
+    Country.fji.raw: Country.fji,
+    Country.flk.raw: Country.flk,
+    Country.fra.raw: Country.fra,
+    Country.fsm.raw: Country.fsm,
+    Country.gab.raw: Country.gab,
+    Country.gbr.raw: Country.gbr,
+    Country.geo.raw: Country.geo,
+    Country.gha.raw: Country.gha,
+    Country.grc.raw: Country.grc,
+    Country.grd.raw: Country.grd,
+    Country.grl.raw: Country.grl,
+    Country.gtm.raw: Country.gtm,
+    Country.guy.raw: Country.guy,
+    Country.hkg.raw: Country.hkg,
+    Country.hrv.raw: Country.hrv,
+    Country.hun.raw: Country.hun,
+    Country.idn.raw: Country.idn,
+    Country.ind.raw: Country.ind,
+    Country.irl.raw: Country.irl,
+    Country.irn.raw: Country.irn,
+    Country.isl.raw: Country.isl,
+    Country.isr.raw: Country.isr,
+    Country.ita.raw: Country.ita,
+    Country.jam.raw: Country.jam,
+    Country.jor.raw: Country.jor,
+    Country.jpn.raw: Country.jpn,
+    Country.kaz.raw: Country.kaz,
+    Country.ken.raw: Country.ken,
+    Country.kir.raw: Country.kir,
+    Country.kor.raw: Country.kor,
+    Country.kwt.raw: Country.kwt,
+    Country.lie.raw: Country.lie,
+    Country.lka.raw: Country.lka,
+    Country.ltu.raw: Country.ltu,
+    Country.lux.raw: Country.lux,
+    Country.lva.raw: Country.lva,
+    Country.mar.raw: Country.mar,
+    Country.mex.raw: Country.mex,
+    Country.mlt.raw: Country.mlt,
+    Country.mnp.raw: Country.mnp,
+    Country.mtq.raw: Country.mtq,
+    Country.mys.raw: Country.mys,
+    Country.mwi.raw: Country.mwi,
+    Country.nga.raw: Country.nga,
+    Country.niu.raw: Country.niu,
+    Country.nld.raw: Country.nld,
+    Country.nor.raw: Country.nor,
+    Country.nzl.raw: Country.nzl,
+    Country.omn.raw: Country.omn,
+    Country.pak.raw: Country.pak,
+    Country.per.raw: Country.per,
+    Country.phl.raw: Country.phl,
+    Country.pol.raw: Country.pol,
+    Country.pri.raw: Country.pri,
+    Country.prt.raw: Country.prt,
+    Country.qat.raw: Country.qat,
+    Country.rou.raw: Country.rou,
+    Country.rus.raw: Country.rus,
+    Country.saf.raw: Country.saf,
+    Country.sau.raw: Country.sau,
+    Country.sgp.raw: Country.sgp,
+    Country.slb.raw: Country.slb,
+    Country.svk.raw: Country.svk,
+    Country.svn.raw: Country.svn,
+    Country.swe.raw: Country.swe,
+    Country.tha.raw: Country.tha,
+    Country.tkm.raw: Country.tkm,
+    Country.ton.raw: Country.ton,
+    Country.tur.raw: Country.tur,
+    Country.tuv.raw: Country.tuv,
+    Country.twn.raw: Country.twn,
+    Country.ukr.raw: Country.ukr,
+    Country.ury.raw: Country.ury,
+    Country.usa.raw: Country.usa,
+    Country.ven.raw: Country.ven,
+    Country.vnm.raw: Country.vnm,
+    Country.vut.raw: Country.vut,
+    Country.btn.raw: Country.btn,
+    Country.bgr.raw: Country.bgr,
+    Country.guf.raw: Country.guf,
+    Country.bes.raw: Country.bes,
+    Country.fro.raw: Country.fro,
+    Country.cuw.raw: Country.cuw,
+    Country.msr.raw: Country.msr,
+    Country.cpv.raw: Country.cpv,
+    Country.nfk.raw: Country.nfk,
+    Country.bmu.raw: Country.bmu,
+    Country.vat.raw: Country.vat,
+    Country.aia.raw: Country.aia,
+    Country.gum.raw: Country.gum,
+    Country.myt.raw: Country.myt,
+    Country.mrt.raw: Country.mrt,
+    Country.ggy.raw: Country.ggy,
+    Country.cck.raw: Country.cck,
+    Country.blz.raw: Country.blz,
+    Country.cxr.raw: Country.cxr,
+    Country.mco.raw: Country.mco,
+    Country.ner.raw: Country.ner,
+    Country.jey.raw: Country.jey,
+    Country.asm.raw: Country.asm,
+    Country.gmb.raw: Country.gmb,
+    Country.dma.raw: Country.dma,
+    Country.glp.raw: Country.glp,
+    Country.ggi.raw: Country.ggi,
+    Country.cmr.raw: Country.cmr,
+    Country.atg.raw: Country.atg,
+    Country.slv.raw: Country.slv,
+    Country.pyf.raw: Country.pyf,
+    Country.iot.raw: Country.iot,
+    Country.vir.raw: Country.vir,
+    Country.abw.raw: Country.abw,
+    Country.ago.raw: Country.ago,
+    Country.afg.raw: Country.afg,
+    Country.lbn.raw: Country.lbn,
+    Country.hmd.raw: Country.hmd,
+    Country.cok.raw: Country.cok,
+    Country.bvt.raw: Country.bvt,
+    Country.atf.raw: Country.atf,
+    Country.eth.raw: Country.eth,
+    Country.plw.raw: Country.plw,
+    Country.ata.raw: Country.ata,
+  };
+
+  static final Map<String, String> _cakePayNames = {
+    'Slovak Republic': 'Slovakia',
+    'Brunei Darussalam': 'Brunei',
+    'Federated States of Micronesia': 'Micronesia',
+    'Sri lanka': 'Sri Lanka',
+    'UAE': 'United Arab Emirates',
+    'UK': 'United Kingdom',
+    'Curaçao': "Curacao",
+  };
+
+  static Country deserialize({required String raw}) => _all[raw]!;
+
+  static final Map<String, Country> countryByName = {
+    for (var country in _all.values) country.fullName: country,
+  };
+
+  static Country? fromCakePayName(String name) {
+    final normalizedName = _cakePayNames[name] ?? name;
+    return countryByName[normalizedName];
+  }
+
+  static String getCakePayName(Country country) {
+    return _cakePayNames.entries
+        .firstWhere(
+          (entry) => entry.value == country.fullName,
+          orElse: () => MapEntry(country.fullName, country.fullName),
+        )
+        .key;
+  }
+
+  static Country? fromCode(String countryCode) {
+    return _all.values.firstWhereOrNull((element) => element.raw == countryCode.toLowerCase());
+  }
+
+  @override
+  bool operator ==(Object other) => other is Country && other.raw == raw;
+
+  @override
+  int get hashCode => raw.hashCode ^ title.hashCode;
+
+  String get iconPath => "assets/images/flags/$raw.png";
+}
diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart
index 8e8bfb6ed..0bb526e5d 100644
--- a/lib/entities/preferences_key.dart
+++ b/lib/entities/preferences_key.dart
@@ -12,6 +12,7 @@ class PreferencesKey {
   static const currentBananoNodeIdKey = 'current_node_id_banano';
   static const currentBananoPowNodeIdKey = 'current_node_id_banano_pow';
   static const currentFiatCurrencyKey = 'current_fiat_currency';
+  static const currentCakePayCountry = 'current_cake_pay_country';
   static const currentBitcoinCashNodeIdKey = 'current_node_id_bch';
   static const currentSolanaNodeIdKey = 'current_node_id_sol';
   static const currentTronNodeIdKey = 'current_node_id_trx';
diff --git a/lib/src/screens/cake_pay/cards/cake_pay_cards_page.dart b/lib/src/screens/cake_pay/cards/cake_pay_cards_page.dart
index 35a58ce0a..31eaa23ff 100644
--- a/lib/src/screens/cake_pay/cards/cake_pay_cards_page.dart
+++ b/lib/src/screens/cake_pay/cards/cake_pay_cards_page.dart
@@ -1,5 +1,6 @@
 import 'package:cake_wallet/cake_pay/cake_pay_states.dart';
 import 'package:cake_wallet/cake_pay/cake_pay_vendor.dart';
+import 'package:cake_wallet/entities/country.dart';
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/src/screens/base_page.dart';
@@ -8,6 +9,7 @@ import 'package:cake_wallet/src/screens/cake_pay/widgets/card_menu.dart';
 import 'package:cake_wallet/src/screens/dashboard/widgets/filter_widget.dart';
 import 'package:cake_wallet/src/widgets/cake_scrollbar.dart';
 import 'package:cake_wallet/src/widgets/gradient_background.dart';
+import 'package:cake_wallet/src/widgets/picker.dart';
 import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
 import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
 import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
@@ -20,6 +22,7 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:cake_wallet/view_model/cake_pay/cake_pay_cards_list_view_model.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:mobx/mobx.dart';
 
 class CakePayCardsPage extends BasePage {
   CakePayCardsPage(this._cardsListViewModel) : searchFocusNode = FocusNode() {
@@ -80,9 +83,25 @@ class CakePayCardsPage extends BasePage {
 
   @override
   Widget body(BuildContext context) {
+
+    if (_cardsListViewModel.settingsStore.selectedCakePayCountry == null) {
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      reaction((_) => _cardsListViewModel.shouldShowCountryPicker, (bool shouldShowCountryPicker) async {
+        if (shouldShowCountryPicker) {
+          _cardsListViewModel.storeInitialFilterStates();
+          await showCountryPicker(context, _cardsListViewModel);
+          if (_cardsListViewModel.hasFiltersChanged) {
+            _cardsListViewModel.resetLoadingNextPageState();
+            _cardsListViewModel.getVendors();
+          }
+        }
+      });
+    });
+    }
+
     final filterButton = Semantics(
       label: S.of(context).filter_by,
-      child: InkWell(
+      child: GestureDetector(
           onTap: () async {
             _cardsListViewModel.storeInitialFilterStates();
             await showFilterWidget(context);
@@ -92,50 +111,87 @@ class CakePayCardsPage extends BasePage {
             }
           },
           child: Container(
-            width: 32,
-            padding: EdgeInsets.all(8),
-            decoration: BoxDecoration(
-              color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
-              border: Border.all(
-                color: Colors.white.withOpacity(0.2),
+              width: 32,
+              padding: EdgeInsets.all(8),
+              decoration: BoxDecoration(
+                color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
+                border: Border.all(
+                  color: Colors.transparent,
+                ),
+                borderRadius: BorderRadius.circular(10),
               ),
-              borderRadius: BorderRadius.circular(10),
+              child: Image.asset(
+                'assets/images/filter.png',
+                color: Theme.of(context).extension<FilterTheme>()!.iconColor,
+              ))),
+    );
+    final _countryPicker = Semantics(
+      label: S.of(context).filter_by,
+      child: GestureDetector(
+        onTap: () async {
+          _cardsListViewModel.storeInitialFilterStates();
+          await showCountryPicker(context, _cardsListViewModel);
+          if (_cardsListViewModel.hasFiltersChanged) {
+            _cardsListViewModel.resetLoadingNextPageState();
+            _cardsListViewModel.getVendors();
+          }
+        },
+        child: Container(
+          padding: EdgeInsets.symmetric(horizontal: 6),
+          decoration: BoxDecoration(
+            color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
+            border: Border.all(color: Colors.transparent),
+            borderRadius: BorderRadius.circular(10),
+          ),
+          child: Container(
+            margin: EdgeInsets.symmetric(vertical: 2),
+            child: Row(
+              children: [
+                Image.asset(
+                  _cardsListViewModel.selectedCountry.iconPath,
+                  width: 24,
+                  height: 24,
+                  errorBuilder: (context, error, stackTrace) => Container(
+                    width: 24,
+                    height: 24,
+                  ),
+                ),
+                SizedBox(width: 6),
+                Text(
+                  _cardsListViewModel.selectedCountry.countryCode,
+                  style: TextStyle(
+                    color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
+                    fontSize: 16,
+                    fontWeight: FontWeight.w700,
+                  ),
+                ),
+              ],
             ),
-            child: Image.asset(
-              'assets/images/filter.png',
-              color: Theme.of(context).extension<FilterTheme>()!.iconColor,
-            ),
-          )),
+          ),
+        ),
+      ),
     );
 
     return Padding(
-      padding: const EdgeInsets.all(14.0),
-      child: Column(
-        children: [
+        padding: const EdgeInsets.all(14.0),
+        child: Column(children: [
           Container(
-            padding: EdgeInsets.only(left: 2, right: 22),
-            height: 32,
-            child: Row(
-              children: [
+              padding: EdgeInsets.only(left: 2, right: 22),
+              height: 32,
+              child: Row(children: [
                 Expanded(
                     child: _SearchWidget(
                   controller: _searchController,
                   focusNode: searchFocusNode,
                 )),
-                SizedBox(width: 10),
-                filterButton
-              ],
-            ),
-          ),
+                SizedBox(width: 5),
+                filterButton,
+                SizedBox(width: 5),
+                _countryPicker
+              ])),
           SizedBox(height: 8),
-          Expanded(
-            child: CakePayCardsPageBody(
-              cardsListViewModel: _cardsListViewModel,
-            ),
-          ),
-        ],
-      ),
-    );
+          Expanded(child: CakePayCardsPageBody(cardsListViewModel: _cardsListViewModel))
+        ]));
   }
 
   Future<void> showFilterWidget(BuildContext context) async {
@@ -148,6 +204,32 @@ class CakePayCardsPage extends BasePage {
   }
 }
 
+
+Future<void> showCountryPicker(BuildContext context, CakePayCardsListViewModel cardsListViewModel) async {
+  await showPopUp<void>(
+      context: context,
+      builder: (_) => Picker(
+        title: S.of(context).select_your_country,
+          items: cardsListViewModel.availableCountries,
+          images: cardsListViewModel.availableCountries
+              .map((e) => Image.asset(
+            e.iconPath,
+            errorBuilder: (context, error, stackTrace) => Container(
+              width: 58,
+              height: 58,
+            ),
+          ))
+              .toList(),
+          selectedAtIndex: cardsListViewModel.availableCountries
+              .indexOf(cardsListViewModel.selectedCountry),
+          onItemSelected: (Country country) =>
+              cardsListViewModel.setSelectedCountry(country),
+          isSeparated: false,
+          hintText: S.of(context).search,
+          matchingCriteria: (Country country, String searchText) =>
+              country.fullName.toLowerCase().contains(searchText.toLowerCase())));
+}
+
 class CakePayCardsPageBody extends StatefulWidget {
   const CakePayCardsPageBody({
     Key? key,
@@ -304,15 +386,9 @@ class _SearchWidget extends StatelessWidget {
           alignLabelWithHint: true,
           floatingLabelBehavior: FloatingLabelBehavior.never,
           suffixIcon: searchIcon,
-          border: OutlineInputBorder(
-            borderSide: BorderSide(
-              color: Colors.white.withOpacity(0.2),
-            ),
-            borderRadius: BorderRadius.circular(10),
-          ),
           enabledBorder: OutlineInputBorder(
             borderSide: BorderSide(
-              color: Colors.white.withOpacity(0.2),
+              color: Colors.transparent,
             ),
             borderRadius: BorderRadius.circular(10),
           ),
diff --git a/lib/src/screens/cake_pay/widgets/card_item.dart b/lib/src/screens/cake_pay/widgets/card_item.dart
index ce804adc2..1234c0a1f 100644
--- a/lib/src/screens/cake_pay/widgets/card_item.dart
+++ b/lib/src/screens/cake_pay/widgets/card_item.dart
@@ -9,7 +9,7 @@ class CardItem extends StatelessWidget {
     required this.backgroundColor,
     required this.titleColor,
     required this.subtitleColor,
-    this.hideBorder = false,
+    this.hideBorder = true,
     this.discount = 0.0,
     this.isAmount = false,
     this.discountBackground,
diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart
index c966420db..50d51d2ed 100644
--- a/lib/store/settings_store.dart
+++ b/lib/store/settings_store.dart
@@ -9,6 +9,7 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
 import 'package:cake_wallet/entities/background_tasks.dart';
 import 'package:cake_wallet/entities/balance_display_mode.dart';
 import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
+import 'package:cake_wallet/entities/country.dart';
 import 'package:cake_wallet/entities/exchange_api_mode.dart';
 import 'package:cake_wallet/entities/fiat_api_mode.dart';
 import 'package:cake_wallet/entities/fiat_currency.dart';
@@ -128,7 +129,8 @@ abstract class SettingsStoreBase with Store {
       TransactionPriority? initialLitecoinTransactionPriority,
       TransactionPriority? initialEthereumTransactionPriority,
       TransactionPriority? initialPolygonTransactionPriority,
-      TransactionPriority? initialBitcoinCashTransactionPriority})
+      TransactionPriority? initialBitcoinCashTransactionPriority,
+      Country? initialCakePayCountry})
       : nodes = ObservableMap<WalletType, Node>.of(nodes),
         powNodes = ObservableMap<WalletType, Node>.of(powNodes),
         _secureStorage = secureStorage,
@@ -213,6 +215,10 @@ abstract class SettingsStoreBase with Store {
       priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority;
     }
 
+    if (initialCakePayCountry != null) {
+      selectedCakePayCountry = initialCakePayCountry;
+    }
+
     initializeTrocadorProviderStates();
 
     WalletType.values.forEach((walletType) {
@@ -244,6 +250,15 @@ abstract class SettingsStoreBase with Store {
         (FiatCurrency fiatCurrency) => sharedPreferences.setString(
             PreferencesKey.currentFiatCurrencyKey, fiatCurrency.serialize()));
 
+    reaction(
+            (_) => selectedCakePayCountry,
+            (Country? country) {
+              if (country != null) {
+                sharedPreferences.setString(
+                    PreferencesKey.currentCakePayCountry, country.raw);
+              }
+            });
+
     reaction(
         (_) => shouldShowYatPopup,
         (bool shouldShowYatPopup) =>
@@ -625,6 +640,9 @@ abstract class SettingsStoreBase with Store {
   @observable
   FiatCurrency fiatCurrency;
 
+  @observable
+  Country? selectedCakePayCountry;
+
   @observable
   bool shouldShowYatPopup;
 
@@ -880,6 +898,10 @@ abstract class SettingsStoreBase with Store {
     final backgroundTasks = getIt.get<BackgroundTasks>();
     final currentFiatCurrency = FiatCurrency.deserialize(
         raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!);
+    final savedCakePayCountryRaw = sharedPreferences.getString(PreferencesKey.currentCakePayCountry);
+    final currentCakePayCountry = savedCakePayCountryRaw != null
+        ? Country.deserialize(raw: savedCakePayCountryRaw)
+        : null;
 
     TransactionPriority? moneroTransactionPriority = monero?.deserializeMoneroTransactionPriority(
         raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!);
@@ -1225,6 +1247,7 @@ abstract class SettingsStoreBase with Store {
       deviceName: deviceName,
       isBitcoinBuyEnabled: isBitcoinBuyEnabled,
       initialFiatCurrency: currentFiatCurrency,
+      initialCakePayCountry: currentCakePayCountry,
       initialBalanceDisplayMode: currentBalanceDisplayMode,
       initialSaveRecipientAddress: shouldSaveRecipientAddress,
       initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus,
diff --git a/lib/view_model/cake_pay/cake_pay_cards_list_view_model.dart b/lib/view_model/cake_pay/cake_pay_cards_list_view_model.dart
index d0483596e..8585da9da 100644
--- a/lib/view_model/cake_pay/cake_pay_cards_list_view_model.dart
+++ b/lib/view_model/cake_pay/cake_pay_cards_list_view_model.dart
@@ -1,8 +1,10 @@
 import 'package:cake_wallet/cake_pay/cake_pay_service.dart';
 import 'package:cake_wallet/cake_pay/cake_pay_states.dart';
 import 'package:cake_wallet/cake_pay/cake_pay_vendor.dart';
+import 'package:cake_wallet/entities/country.dart';
+import 'package:cake_wallet/entities/fiat_currency.dart';
 import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cake_wallet/view_model/dashboard/dropdown_filter_item.dart';
+import 'package:cake_wallet/store/settings_store.dart';
 import 'package:cake_wallet/view_model/dashboard/filter_item.dart';
 import 'package:mobx/mobx.dart';
 
@@ -13,11 +15,11 @@ class CakePayCardsListViewModel = CakePayCardsListViewModelBase with _$CakePayCa
 abstract class CakePayCardsListViewModelBase with Store {
   CakePayCardsListViewModelBase({
     required this.cakePayService,
+    required this.settingsStore,
   })  : cardState = CakePayCardsStateNoCards(),
         cakePayVendors = [],
         availableCountries = [],
         page = 1,
-        selectedCountry = 'USA',
         displayPrepaidCards = true,
         displayGiftCards = true,
         displayDenominationsCards = true,
@@ -30,13 +32,20 @@ abstract class CakePayCardsListViewModelBase with Store {
     initialization();
   }
 
+  static Country _getInitialCountry(FiatCurrency fiatCurrency) {
+    if (fiatCurrency.countryCode == 'eur') {
+      return Country.deu;
+    }
+    return Country.fromCode(fiatCurrency.countryCode) ?? Country.usa;
+  }
+
   void initialization() async {
     await getCountries();
-    selectedCountry = availableCountries.first;
     getVendors();
   }
 
   final CakePayService cakePayService;
+  final SettingsStore settingsStore;
 
   List<CakePayVendor> CakePayVendorList;
 
@@ -61,28 +70,15 @@ abstract class CakePayCardsListViewModelBase with Store {
               caption: S.current.custom_value,
               onChanged: toggleCustomValueCards),
         ],
-        S.current.countries: [
-          DropdownFilterItem(
-            items: availableCountries,
-            caption: '',
-            selectedItem: selectedCountry,
-            onItemSelected: (String value) => setSelectedCountry(value),
-          ),
-        ]
       };
 
   String searchString;
-
   int page;
 
-  late String _initialSelectedCountry;
-
+  late Country _initialSelectedCountry;
   late bool _initialDisplayPrepaidCards;
-
   late bool _initialDisplayGiftCards;
-
   late bool _initialDisplayDenominationsCards;
-
   late bool _initialDisplayCustomValueCards;
 
   @observable
@@ -107,7 +103,7 @@ abstract class CakePayCardsListViewModelBase with Store {
   List<CakePayVendor> cakePayVendors;
 
   @observable
-  List<String> availableCountries;
+  List<Country> availableCountries;
 
   @observable
   bool displayPrepaidCards;
@@ -121,15 +117,22 @@ abstract class CakePayCardsListViewModelBase with Store {
   @observable
   bool displayCustomValueCards;
 
-  @observable
-  String selectedCountry;
+  @computed
+  Country get selectedCountry =>
+      settingsStore.selectedCakePayCountry ?? _getInitialCountry(settingsStore.fiatCurrency);
+
+  @computed
+  bool get shouldShowCountryPicker => settingsStore.selectedCakePayCountry == null && availableCountries.isNotEmpty;
+
+
+  bool get hasFiltersChanged {
+    return selectedCountry != _initialSelectedCountry ||
+        displayPrepaidCards != _initialDisplayPrepaidCards ||
+        displayGiftCards != _initialDisplayGiftCards ||
+        displayDenominationsCards != _initialDisplayDenominationsCards ||
+        displayCustomValueCards != _initialDisplayCustomValueCards;
+  }
 
-  bool get hasFiltersChanged =>
-      selectedCountry != _initialSelectedCountry ||
-      displayPrepaidCards != _initialDisplayPrepaidCards ||
-      displayGiftCards != _initialDisplayGiftCards ||
-      displayDenominationsCards != _initialDisplayDenominationsCards ||
-      displayCustomValueCards != _initialDisplayCustomValueCards;
 
   Future<void> getCountries() async {
     availableCountries = await cakePayService.getCountries();
@@ -143,7 +146,7 @@ abstract class CakePayCardsListViewModelBase with Store {
     vendorsState = CakePayVendorLoadingState();
     searchString = text ?? '';
     var newVendors = await cakePayService.getVendors(
-        country: selectedCountry,
+        country: Country.getCakePayName(selectedCountry),
         page: currentPage ?? page,
         search: searchString,
         giftCards: displayGiftCards,
@@ -152,20 +155,20 @@ abstract class CakePayCardsListViewModelBase with Store {
         onDemand: displayDenominationsCards);
 
     cakePayVendors = CakePayVendorList = newVendors;
-
     vendorsState = CakePayVendorLoadedState();
   }
 
   @action
   Future<void> fetchNextPage() async {
-    if (vendorsState is CakePayVendorLoadingState || !hasMoreDataToFetch || isLoadingNextPage)
+    if (vendorsState is CakePayVendorLoadingState || !hasMoreDataToFetch || isLoadingNextPage) {
       return;
+    }
 
     isLoadingNextPage = true;
     page++;
     try {
       var newVendors = await cakePayService.getVendors(
-          country: selectedCountry,
+          country: Country.getCakePayName(selectedCountry),
           page: page,
           search: searchString,
           giftCards: displayGiftCards,
@@ -201,7 +204,7 @@ abstract class CakePayCardsListViewModelBase with Store {
   }
 
   @action
-  void setSelectedCountry(String country) => selectedCountry = country;
+  void setSelectedCountry(Country country) => settingsStore.selectedCakePayCountry = country;
 
   @action
   void togglePrepaidCards() => displayPrepaidCards = !displayPrepaidCards;
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index 0db2031dd..b8c933a2e 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "حدد مزود شراء أعلاه. يمكنك تخطي هذه الشاشة عن طريق تعيين مزود شراء الافتراضي في إعدادات التطبيق.",
   "select_destination": ".ﻲﻃﺎﻴﺘﺣﻻﺍ ﺦﺴﻨﻟﺍ ﻒﻠﻣ ﺔﻬﺟﻭ ﺪﻳﺪﺤﺗ ءﺎﺟﺮﻟﺍ",
   "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ",
+  "select_your_country": "الرجاء تحديد بلدك",
   "sell": "بيع",
   "sell_alert_content": ".ﺎﻬﻴﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ Litecoin ﻭﺃ Ethereum ﻭﺃ Bitcoin ﺔﻈﻔﺤﻣ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .Litecoin ﻭ",
   "sell_monero_com_alert_content": "بيع Monero غير مدعوم حتى الآن",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index 7e78dd69a..2fd644d01 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "Изберете доставчик на покупка по -горе. Можете да пропуснете този екран, като зададете вашия доставчик по подразбиране по подразбиране в настройките на приложението.",
   "select_destination": "Моля, изберете дестинация за архивния файл.",
   "select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.",
+  "select_your_country": "Моля, изберете вашата страна",
   "sell": "Продаване",
   "sell_alert_content": "В момента поддържаме само продажбата на Bitcoin, Ethereum и Litecoin. Моля, създайте или превключете към своя портфейл Bitcoin, Ethereum или Litecoin.",
   "sell_monero_com_alert_content": "Продажбата на Monero все още не се поддържа",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index f17466a9f..8f3b5bf28 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "Vyberte výše uvedeného poskytovatele nákupu. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele nákupu v nastavení aplikace.",
   "select_destination": "Vyberte cíl pro záložní soubor.",
   "select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.",
+  "select_your_country": "Vyberte prosím svou zemi",
   "sell": "Prodat",
   "sell_alert_content": "V současné době podporujeme pouze prodej bitcoinů, etherea a litecoinů. Vytvořte nebo přepněte na svou bitcoinovou, ethereum nebo litecoinovou peněženku.",
   "sell_monero_com_alert_content": "Prodej Monero zatím není podporován",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index cb0a59574..77a531d1b 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -635,6 +635,7 @@
   "select_buy_provider_notice": "Wählen Sie oben einen Anbieter kaufen. Sie können diese Seite überspringen, indem Sie Ihren Standard-Kaufanbieter in den App-Einstellungen festlegen.",
   "select_destination": "Bitte wählen Sie das Ziel für die Sicherungsdatei aus.",
   "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.",
+  "select_your_country": "Bitte wählen Sie Ihr Land aus",
   "sell": "Verkaufen",
   "sell_alert_content": "Wir unterstützen derzeit nur den Verkauf von Bitcoin, Ethereum und Litecoin. Bitte erstellen Sie Ihr Bitcoin-, Ethereum- oder Litecoin-Wallet oder wechseln Sie zu diesem.",
   "sell_monero_com_alert_content": "Der Verkauf von Monero wird noch nicht unterstützt",
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index 40be8fd08..4fe375ff9 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -636,6 +636,7 @@
   "select_buy_provider_notice": "Select a buy provider above. You can skip this screen by setting your default buy provider in app settings.",
   "select_destination": "Please select destination for the backup file.",
   "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.",
+  "select_your_country": "Please select your country",
   "sell": "Sell",
   "sell_alert_content": "We currently only support the sale of Bitcoin, Ethereum and Litecoin. Please create or switch to your Bitcoin, Ethereum or Litecoin wallet.",
   "sell_monero_com_alert_content": "Selling Monero is not supported yet",
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 5a693cf32..31498df2d 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -635,6 +635,7 @@
   "select_buy_provider_notice": "Selecciona un proveedor de compra arriba. Puede omitir esta pantalla configurando su proveedor de compra predeterminado en la configuración de la aplicación.",
   "select_destination": "Selecciona el destino del archivo de copia de seguridad.",
   "select_sell_provider_notice": "Selecciona un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.",
+  "select_your_country": "Seleccione su país",
   "sell": "Vender",
   "sell_alert_content": "Actualmente solo admitimos la venta de Bitcoin, Ethereum y Litecoin. Cree o cambie a su billetera Bitcoin, Ethereum o Litecoin.",
   "sell_monero_com_alert_content": "Aún no se admite la venta de Monero",
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index 1865e41f2..f96e9e304 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.",
   "select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.",
   "select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.",
+  "select_your_country": "Veuillez sélectionner votre pays",
   "sell": "Vendre",
   "sell_alert_content": "Nous ne prenons actuellement en charge que la vente de Bitcoin, Ethereum et Litecoin. Veuillez créer ou basculer vers votre portefeuille Bitcoin, Ethereum ou Litecoin.",
   "sell_monero_com_alert_content": "La vente de Monero n'est pas encore prise en charge",
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index 52cf14128..5fc64e0b3 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -636,6 +636,7 @@
   "select_buy_provider_notice": "Zaɓi mai ba da kyauta a sama. Zaka iya tsallake wannan allon ta hanyar saita mai ba da isasshen busasshen mai ba da isasshen busasshiyar saiti.",
   "select_destination": "Da fatan za a zaɓi wurin da za a yi wa madadin fayil ɗin.",
   "select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.",
+  "select_your_country": "Da fatan za a zabi ƙasarku",
   "sell": "sayar",
   "sell_alert_content": "A halin yanzu muna tallafawa kawai siyar da Bitcoin, Ethereum da Litecoin. Da fatan za a ƙirƙiri ko canza zuwa walat ɗin ku na Bitcoin, Ethereum ko Litecoin.",
   "sell_monero_com_alert_content": "Selling Monero bai sami ƙarshen mai bukatar samun ba",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index 64f112a42..fb3b78900 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -636,6 +636,7 @@
   "select_buy_provider_notice": "ऊपर एक खरीद प्रदाता का चयन करें। आप इस स्क्रीन को ऐप सेटिंग्स में अपना डिफ़ॉल्ट बाय प्रदाता सेट करके छोड़ सकते हैं।",
   "select_destination": "कृपया बैकअप फ़ाइल के लिए गंतव्य का चयन करें।",
   "select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।",
+  "select_your_country": "कृपया अपने देश का चयन करें",
   "sell": "बेचना",
   "sell_alert_content": "हम वर्तमान में केवल बिटकॉइन, एथेरियम और लाइटकॉइन की बिक्री का समर्थन करते हैं। कृपया अपना बिटकॉइन, एथेरियम या लाइटकॉइन वॉलेट बनाएं या उसमें स्विच करें।",
   "sell_monero_com_alert_content": "मोनेरो बेचना अभी तक समर्थित नहीं है",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 4bbf4f141..230aa955b 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "Odaberite gornji davatelj kupnje. Ovaj zaslon možete preskočiti postavljanjem zadanog davatelja usluga kupnje u postavkama aplikacija.",
   "select_destination": "Odaberite odredište za datoteku sigurnosne kopije.",
   "select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.",
+  "select_your_country": "Odaberite svoju zemlju",
   "sell": "Prodavati",
   "sell_alert_content": "Trenutno podržavamo samo prodaju Bitcoina, Ethereuma i Litecoina. Izradite ili prijeđite na svoj Bitcoin, Ethereum ili Litecoin novčanik.",
   "sell_monero_com_alert_content": "Prodaja Monera još nije podržana",
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index cbaf3a548..63a986103 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -626,6 +626,7 @@
   "select_buy_provider_notice": "Ընտրեք գնման մատակարարը վերևում։ Դուք կարող եք բաց թողնել այս էկրանը ձեր լռելայն գնման մատակարարը հավելվածի կարգավորումներում սահմանելով",
   "select_destination": "Խնդրում ենք ընտրել կրկնօրինակ ֆայլի նպատակակետը",
   "select_sell_provider_notice": "Ընտրեք վաճառքի մատակարարը վերևում։ Դուք կարող եք բաց թողնել այս էկրանը ձեր լռելայն վաճառքի մատակարարը հավելվածի կարգավորումներում սահմանելով",
+  "select_your_country": "Խնդրում ենք ընտրել ձեր երկիրը",
   "sell": "Ծախել",
   "sell_alert_content": "Մենք ներկայումս պաշտպանում ենք միայն Bitcoin, Ethereum և Litecoin վաճառքը։ Խնդրում ենք ստեղծել կամ միացնել ձեր Bitcoin, Ethereum կամ Litecoin դրամապանակը",
   "sell_monero_com_alert_content": "Monero-ի վաճառքը դեռ չի պաշտպանվում",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index 273087eec..3fa3a958f 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -637,6 +637,7 @@
   "select_buy_provider_notice": "Pilih penyedia beli di atas. Anda dapat melewatkan layar ini dengan mengatur penyedia pembelian default Anda di pengaturan aplikasi.",
   "select_destination": "Silakan pilih tujuan untuk file cadangan.",
   "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.",
+  "select_your_country": "Pilih negara Anda",
   "sell": "Jual",
   "sell_alert_content": "Saat ini kami hanya mendukung penjualan Bitcoin, Ethereum, dan Litecoin. Harap buat atau alihkan ke dompet Bitcoin, Ethereum, atau Litecoin Anda.",
   "sell_monero_com_alert_content": "Menjual Monero belum didukung",
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index 917315aa6..aab18d434 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -636,6 +636,7 @@
   "select_buy_provider_notice": "Seleziona un fornitore di acquisto sopra. È possibile saltare questa schermata impostando il provider di acquisto predefinito nelle impostazioni dell'app.",
   "select_destination": "Seleziona la destinazione per il file di backup.",
   "select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.",
+  "select_your_country": "Seleziona il tuo paese",
   "sell": "Vendere",
   "sell_alert_content": "Al momento supportiamo solo la vendita di Bitcoin, Ethereum e Litecoin. Crea o passa al tuo portafoglio Bitcoin, Ethereum o Litecoin.",
   "sell_monero_com_alert_content": "La vendita di Monero non è ancora supportata",
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index ae3e32ea8..f1fd0acd3 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -635,6 +635,7 @@
   "select_buy_provider_notice": "上記の購入プロバイダーを選択してください。デフォルトの購入プロバイダーをアプリ設定で設定して、この画面をスキップできます。",
   "select_destination": "バックアップファイルの保存先を選択してください。",
   "select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。",
+  "select_your_country": "あなたの国を選択してください",
   "sell": "売る",
   "sell_alert_content": "現在、ビットコイン、イーサリアム、ライトコインの販売のみをサポートしています。ビットコイン、イーサリアム、またはライトコインのウォレットを作成するか、これらのウォレットに切り替えてください。",
   "sell_monero_com_alert_content": "モネロの販売はまだサポートされていません",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 2dc1a2dfc..7e3467cf2 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -635,6 +635,7 @@
   "select_buy_provider_notice": "위의 구매 제공자를 선택하십시오. 앱 설정에서 기본 구매 제공자를 설정 하여이 화면을 건너 뛸 수 있습니다.",
   "select_destination": "백업 파일의 대상을 선택하십시오.",
   "select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.",
+  "select_your_country": "국가를 선택하십시오",
   "sell": "팔다",
   "sell_alert_content": "현재 Bitcoin, Ethereum 및 Litecoin의 판매만 지원합니다. Bitcoin, Ethereum 또는 Litecoin 지갑을 생성하거나 전환하십시오.",
   "sell_monero_com_alert_content": "지원되지 않습니다.",
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index f42af6863..10c13cfef 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "အပေါ်ကဝယ်သူတစ် ဦး ကိုရွေးချယ်ပါ။ သင်၏ default 0 ယ်သူအား app settings တွင် setting လုပ်ခြင်းဖြင့်ဤ screen ကိုကျော်သွားနိုင်သည်။",
   "select_destination": "အရန်ဖိုင်အတွက် ဦးတည်ရာကို ရွေးပါ။",
   "select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။",
+  "select_your_country": "ကျေးဇူးပြု. သင့်နိုင်ငံကိုရွေးချယ်ပါ",
   "sell": "ရောင်း",
   "sell_alert_content": "ကျွန်ုပ်တို့သည် လက်ရှိတွင် Bitcoin၊ Ethereum နှင့် Litecoin ရောင်းချခြင်းကိုသာ ပံ့ပိုးပေးပါသည်။ သင်၏ Bitcoin၊ Ethereum သို့မဟုတ် Litecoin ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။",
   "sell_monero_com_alert_content": "Monero ရောင်းချခြင်းကို မပံ့ပိုးရသေးပါ။",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 73e3df6b6..9552f2439 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "Selecteer hierboven een koopprovider. U kunt dit scherm overslaan door uw standaard kopenprovider in te stellen in app -instellingen.",
   "select_destination": "Selecteer de bestemming voor het back-upbestand.",
   "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.",
+  "select_your_country": "Selecteer uw land",
   "sell": "Verkopen",
   "sell_alert_content": "We ondersteunen momenteel alleen de verkoop van Bitcoin, Ethereum en Litecoin. Maak of schakel over naar uw Bitcoin-, Ethereum- of Litecoin-portemonnee.",
   "sell_monero_com_alert_content": "Het verkopen van Monero wordt nog niet ondersteund",
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index aaa82a3bf..f3c3e4810 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "Wybierz powyższe dostawcę zakupu. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę zakupu w ustawieniach aplikacji.",
   "select_destination": "Wybierz miejsce docelowe dla pliku kopii zapasowej.",
   "select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.",
+  "select_your_country": "Wybierz swój kraj",
   "sell": "Sprzedać",
   "sell_alert_content": "Obecnie obsługujemy tylko sprzedaż Bitcoin, Ethereum i Litecoin. Utwórz lub przełącz się na swój portfel Bitcoin, Ethereum lub Litecoin.",
   "sell_monero_com_alert_content": "Sprzedaż Monero nie jest jeszcze obsługiwana",
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index 194307a3d..410e8cb1c 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -636,6 +636,7 @@
   "select_buy_provider_notice": "Selecione um provedor de compra acima. Você pode pular esta tela definindo seu provedor de compra padrão nas configurações de aplicativos.",
   "select_destination": "Selecione o destino para o arquivo de backup.",
   "select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.",
+  "select_your_country": "Selecione seu país",
   "sell": "Vender",
   "sell_alert_content": "Atualmente, oferecemos suporte apenas à venda de Bitcoin, Ethereum e Litecoin. Crie ou troque para sua carteira Bitcoin, Ethereum ou Litecoin.",
   "sell_monero_com_alert_content": "A venda de Monero ainda não é suportada",
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index f42c28c15..a8ee5a309 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -635,6 +635,7 @@
   "select_buy_provider_notice": "Выберите поставщика покупки выше. Вы можете пропустить этот экран, установив поставщика покупки по умолчанию в настройках приложения.",
   "select_destination": "Пожалуйста, выберите место для файла резервной копии.",
   "select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.",
+  "select_your_country": "Пожалуйста, выберите свою страну",
   "sell": "Продавать",
   "sell_alert_content": "В настоящее время мы поддерживаем только продажу биткойнов, эфириума и лайткойна. Пожалуйста, создайте или переключитесь на свой кошелек Bitcoin, Ethereum или Litecoin.",
   "sell_monero_com_alert_content": "Продажа Monero пока не поддерживается",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index 9d8fb0af2..5102e150c 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "เลือกผู้ให้บริการซื้อด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการซื้อเริ่มต้นในการตั้งค่าแอป",
   "select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรอง",
   "select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป",
+  "select_your_country": "กรุณาเลือกประเทศของคุณ",
   "sell": "ขาย",
   "sell_alert_content": "ขณะนี้เรารองรับการขาย Bitcoin, Ethereum และ Litecoin เท่านั้น โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงิน Bitcoin, Ethereum หรือ Litecoin ของคุณ",
   "sell_monero_com_alert_content": "ยังไม่รองรับการขาย Monero",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index ca35e7997..eb78c8d3c 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "Pumili ng provider ng pagbili sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na provider ng pagbili sa mga setting ng app.",
   "select_destination": "Mangyaring piliin ang patutunguhan para sa backup na file.",
   "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.",
+  "select_your_country": "Mangyaring piliin ang iyong bansa",
   "sell": "Ibenta",
   "sell_alert_content": "Kasalukuyan lamang naming sinusuportahan ang pagbebenta ng Bitcoin, Ethereum at Litecoin. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum o Litecoin wallet.",
   "sell_monero_com_alert_content": "Ang pagbebenta ng Monero ay hindi pa suportado",
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index 1fee66369..0b4700397 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "Yukarıda bir satın alma sağlayıcısı seçin. App ayarlarında varsayılan satın alma sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.",
   "select_destination": "Lütfen yedekleme dosyası için hedef seçin.",
   "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.",
+  "select_your_country": "Lütfen ülkenizi seçin",
   "sell": "Satış",
   "sell_alert_content": "Şu anda yalnızca Bitcoin, Ethereum ve Litecoin satışını destekliyoruz. Lütfen Bitcoin, Ethereum veya Litecoin cüzdanınızı oluşturun veya cüzdanınıza geçin.",
   "sell_monero_com_alert_content": "Monero satışı henüz desteklenmiyor",
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index 5d9a56c1e..c9afde7be 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -635,6 +635,7 @@
   "select_buy_provider_notice": "Виберіть постачальника купівлі вище. Ви можете пропустити цей екран, встановивши свого постачальника купівлі за замовчуванням у налаштуваннях додатків.",
   "select_destination": "Виберіть місце призначення для файлу резервної копії.",
   "select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.",
+  "select_your_country": "Будь ласка, виберіть свою країну",
   "sell": "Продати",
   "sell_alert_content": "Наразі ми підтримуємо лише продаж Bitcoin, Ethereum і Litecoin. Створіть або перейдіть на свій гаманець Bitcoin, Ethereum або Litecoin.",
   "sell_monero_com_alert_content": "Продаж Monero ще не підтримується",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index 106f00f96..50c6f1889 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -636,6 +636,7 @@
   "select_buy_provider_notice": "اوپر خریدنے والا خریدنے والا منتخب کریں۔ آپ ایپ کی ترتیبات میں اپنے پہلے سے طے شدہ خریدنے والے کو ترتیب دے کر اس اسکرین کو چھوڑ سکتے ہیں۔",
   "select_destination": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﻝﺰﻨﻣ ﮯﯿﻟ ﮯﮐ ﻞﺋﺎﻓ ﭖﺍ ﮏﯿﺑ ﻡﺮﮐ ﮦﺍﺮﺑ",
   "select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ",
+  "select_your_country": "براہ کرم اپنے ملک کو منتخب کریں",
   "sell": "بیچنا",
   "sell_alert_content": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﭧﯿﻟﺍﻭ Litecoin ﺎﯾ Bitcoin، Ethereum ﺎﻨﭘﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔",
   "sell_monero_com_alert_content": "Monero فروخت کرنا ابھی تک تعاون یافتہ نہیں ہے۔",
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index a95f32aaa..e3ffbef3e 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -627,6 +627,7 @@
   "select_buy_provider_notice": "Chọn nhà cung cấp mua ở trên. Bạn có thể bỏ qua màn hình này bằng cách thiết lập nhà cung cấp mua mặc định trong cài đặt ứng dụng.",
   "select_destination": "Vui lòng chọn đích cho tệp sao lưu.",
   "select_sell_provider_notice": "Chọn nhà cung cấp bán ở trên. Bạn có thể bỏ qua màn hình này bằng cách thiết lập nhà cung cấp bán mặc định trong cài đặt ứng dụng.",
+  "select_your_country": "Vui lòng chọn quốc gia của bạn",
   "sell": "Bán",
   "sell_alert_content": "Hiện tại chúng tôi chỉ hỗ trợ bán Bitcoin, Ethereum và Litecoin. Vui lòng tạo hoặc chuyển sang ví Bitcoin, Ethereum hoặc Litecoin của bạn.",
   "sell_monero_com_alert_content": "Bán Monero chưa được hỗ trợ",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 1a1583da5..19dc9f110 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -635,6 +635,7 @@
   "select_buy_provider_notice": "Yan olupese Ra loke. O le skii iboju yii nipa ṣiṣeto olupese rẹ ni awọn eto App.",
   "select_destination": "Jọwọ yan ibi ti o nlo fun faili afẹyinti.",
   "select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.",
+  "select_your_country": "Jọwọ yan orilẹ-ede rẹ",
   "sell": "Tà",
   "sell_alert_content": "Lọwọlọwọ a ṣe atilẹyin tita Bitcoin, Ethereum ati Litecoin nikan. Jọwọ ṣẹda tabi yipada si Bitcoin, Ethereum tabi apamọwọ Litecoin rẹ.",
   "sell_monero_com_alert_content": "Kọ ju lọwọ Monero ko ṣe ni ibamu",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index 79fe8faa5..009a31d86 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -634,6 +634,7 @@
   "select_buy_provider_notice": "在上面选择买入提供商。您可以通过在应用程序设置中设置默认的购买提供商来跳过此屏幕。",
   "select_destination": "请选择备份文件的目的地。",
   "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。",
+  "select_your_country": "请选择你的国家",
   "sell": "卖",
   "sell_alert_content": "我们目前仅支持比特币、以太坊和莱特币的销售。请创建或切换到您的比特币、以太坊或莱特币钱包。",
   "sell_monero_com_alert_content": "尚不支持出售门罗币",

From 0fcfd76afd75b91665e25804859497aa46a051aa Mon Sep 17 00:00:00 2001
From: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Date: Thu, 7 Nov 2024 15:46:08 +0100
Subject: [PATCH 33/50] Automated Integration Tests Flows (#1686)

* feat: Integration tests setup and tests for Disclaimer, Welcome and Setup Pin Code pages

* feat: Integration test flow from start to restoring a wallet successfully done

* test: Dashboard view test and linking to flow

* feat: Testing the Exchange flow section, selecting sending and receiving currencies

* test: Successfully create an exchange section

* feat: Implement flow up to sending section

* test: Complete Exchange flow

* fix dependency issue

* test: Final cleanups

* feat: Add CI to run automated integration tests withan android emulator

* feat: Adjust Automated integration test CI to run on ubuntu 20.04-a

* fix: Move integration test CI into PR test build CI

* ci: Add automated test ci which is a streamlined replica of pr test build ci

* ci: Re-add step to access branch name

* ci: Add KVM

* ci: Add filepath to trigger the test run from

* ci: Add required key

* ci: Add required key

* ci: Add missing secret key

* ci: Add missing secret key

* ci: Add nano secrets to workflow

* ci: Switch step to free space on runner

* ci: Remove timeout from workflow

* ci: Confirm impact that removing copy_monero_deps would have on entire workflow time

* ci: Update CI and temporarily remove cache related to emulator

* ci: Remove dynamic java version

* ci: Temporarily switch CI

* ci: Switch to 11.x jdk

* ci: Temporarily switch CI

* ci: Revert ubuntu version

* ci: Add more api levels

* ci: Add more target options

* ci: Settled on stable emulator matrix options

* ci: Add more target options

* ci: Modify flow

* ci: Streamline api levels to 28 and 29

* ci: One more trial

* ci: Switch to flutter drive

* ci: Reduce options

* ci: Remove haven from test

* ci: Check for solana in list

* ci: Adjust amounts and currencies for exchange flow

* ci: Set write response on failure to true

* ci: Split ci to funds and non funds related tests

* test: Test for Send flow scenario and minor restructuring for test folders and files

* chore: cleanup

* ci: Pause CI for now

* ci: Pause CI for now

* ci: Pause CI for now

* test: Restore wallets integration automated tests

* Fix: Add keys back to currency amount textfield widget

* fix: Switch variable name

* fix: remove automation for now

* tests: Automated tests for Create wallets flow

* tests: Further optimize common flows

* tests: Add missing await for call

* tests: Confirm Seeds Display Properly WIP

* tests: Confirm Seeds Display Correctly Automated Tests

* fix: Add missing pubspec params for bitcoin and bitcoin_cash

* feat: Automated Tests for Transaction History Flow

* fix: Add missing pubspec parameter

* feat: Automated Integration Tests for Transaction History flow

* test: Updating send page robot and also syncing branch with main

* test: Modifying tests to flow with wallet grouping implementation

* fix: Issue with transaction history test

* fix: Modifications to the PR and add automated confirmation for checking that all wallet types are restored or created correctly

* test: Attempting automation for testing

* fix: Issue from merge conflicts

* test: Remove automation of test in this PR

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
---
 cw_bitcoin/pubspec.yaml                       |   1 +
 cw_bitcoin_cash/pubspec.yaml                  |   1 +
 cw_core/pubspec.yaml                          |   1 +
 .../components/common_test_cases.dart         | 121 ++++-
 .../components/common_test_constants.dart     |   2 +-
 .../components/common_test_flows.dart         | 291 +++++++++++-
 integration_test/funds_related_tests.dart     |   9 +-
 .../robots/dashboard_menu_widget_robot.dart   |  39 ++
 .../robots/dashboard_page_robot.dart          |  62 ++-
 .../robots/exchange_page_robot.dart           |   4 +-
 .../robots/new_wallet_page_robot.dart         |  35 ++
 .../robots/pin_code_widget_robot.dart         |  11 +-
 .../robots/pre_seed_page_robot.dart           |  20 +
 .../restore_from_seed_or_key_robot.dart       |  17 +
 .../robots/restore_options_page_robot.dart    |   6 +-
 .../security_and_backup_page_robot.dart       |  24 +
 integration_test/robots/send_page_robot.dart  |   9 +-
 .../robots/transactions_page_robot.dart       | 286 +++++++++++
 .../wallet_group_description_page_robot.dart  |  32 ++
 .../robots/wallet_keys_robot.dart             | 162 +++++++
 .../robots/wallet_list_page_robot.dart        |  27 ++
 .../robots/wallet_seed_page_robot.dart        |  57 +++
 .../test_suites/confirm_seeds_flow_test.dart  | 107 +++++
 .../test_suites/create_wallet_flow_test.dart  |  57 +++
 .../test_suites/exchange_flow_test.dart       |  61 +--
 ...estore_wallet_through_seeds_flow_test.dart |  63 +++
 .../test_suites/send_flow_test.dart           |  37 +-
 .../transaction_history_flow_test.dart        |  70 +++
 ios/Podfile.lock                              |  12 +-
 lib/src/screens/InfoPage.dart                 |  13 +-
 lib/src/screens/dashboard/dashboard_page.dart |   2 +-
 .../dashboard/pages/nft_details_page.dart     |   5 +-
 .../dashboard/pages/transactions_page.dart    | 214 +++++----
 .../widgets/anonpay_transaction_row.dart      |   1 +
 .../dashboard/widgets/date_section_raw.dart   |  41 +-
 .../screens/dashboard/widgets/header_row.dart |   3 +-
 .../dashboard/widgets/menu_widget.dart        |   3 +-
 .../screens/dashboard/widgets/order_row.dart  |  78 ++-
 .../screens/dashboard/widgets/trade_row.dart  |   1 +
 .../dashboard/widgets/transaction_raw.dart    | 103 ++--
 .../screens/new_wallet/new_wallet_page.dart   |  18 +-
 .../wallet_group_description_page.dart        |   2 +
 .../screens/restore/restore_options_page.dart |  38 +-
 .../wallet_restore_from_seed_form.dart        |   2 +
 lib/src/screens/seed/pre_seed_page.dart       |  10 +-
 lib/src/screens/seed/wallet_seed_page.dart    |  95 ++--
 .../settings/security_backup_page.dart        |  50 +-
 .../widgets/settings_cell_with_arrow.dart     |   7 +-
 .../widgets/settings_picker_cell.dart         |  24 +-
 .../widgets/settings_switcher_cell.dart       |   3 +-
 .../setup_2fa/setup_2fa_info_page.dart        |   8 +-
 .../blockexplorer_list_item.dart              |   9 +-
 .../rbf_details_list_fee_picker_item.dart     |  26 +-
 .../standart_list_item.dart                   |   7 +-
 .../textfield_list_item.dart                  |  10 +-
 .../transaction_details_list_item.dart        |   7 +-
 .../transaction_details_page.dart             |  60 +--
 .../transaction_expandable_list_item.dart     |   9 +-
 .../widgets/textfield_list_row.dart           |  14 +-
 .../screens/wallet_keys/wallet_keys_page.dart |  36 +-
 .../screens/wallet_list/wallet_list_page.dart |   2 +
 lib/src/widgets/blockchain_height_widget.dart |   3 +
 lib/src/widgets/dashboard_card_widget.dart    |   1 +
 lib/src/widgets/option_tile.dart              |  18 +-
 lib/src/widgets/picker.dart                   |   3 +
 lib/src/widgets/seed_language_selector.dart   |  11 +-
 lib/src/widgets/setting_actions.dart          |  12 +
 lib/src/widgets/standard_list.dart            |   8 +-
 .../anonpay/anonpay_transactions_store.dart   |   6 +-
 lib/store/dashboard/orders_store.dart         |  24 +-
 lib/store/dashboard/trades_store.dart         |  19 +-
 lib/utils/date_formatter.dart                 |  26 +-
 lib/utils/image_utill.dart                    |   4 +
 .../dashboard/action_list_item.dart           |   5 +
 .../anonpay_transaction_list_item.dart        |   2 +-
 .../dashboard/dashboard_view_model.dart       | 106 +++--
 .../dashboard/date_section_item.dart          |   2 +-
 .../dashboard/formatted_item_list.dart        |  15 +-
 lib/view_model/dashboard/order_list_item.dart |   4 +-
 lib/view_model/dashboard/trade_list_item.dart |   6 +-
 .../dashboard/transaction_list_item.dart      |   8 +-
 .../transaction_details_view_model.dart       | 449 ++++++++++++++----
 lib/view_model/wallet_keys_view_model.dart    | 181 ++++---
 tool/utils/secret_key.dart                    |  23 +
 84 files changed, 2716 insertions(+), 745 deletions(-)
 create mode 100644 integration_test/robots/dashboard_menu_widget_robot.dart
 create mode 100644 integration_test/robots/new_wallet_page_robot.dart
 create mode 100644 integration_test/robots/pre_seed_page_robot.dart
 create mode 100644 integration_test/robots/security_and_backup_page_robot.dart
 create mode 100644 integration_test/robots/transactions_page_robot.dart
 create mode 100644 integration_test/robots/wallet_group_description_page_robot.dart
 create mode 100644 integration_test/robots/wallet_keys_robot.dart
 create mode 100644 integration_test/robots/wallet_list_page_robot.dart
 create mode 100644 integration_test/robots/wallet_seed_page_robot.dart
 create mode 100644 integration_test/test_suites/confirm_seeds_flow_test.dart
 create mode 100644 integration_test/test_suites/create_wallet_flow_test.dart
 create mode 100644 integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
 create mode 100644 integration_test/test_suites/transaction_history_flow_test.dart

diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml
index 7a1576a98..bff6104ac 100644
--- a/cw_bitcoin/pubspec.yaml
+++ b/cw_bitcoin/pubspec.yaml
@@ -73,6 +73,7 @@ dependency_overrides:
 
 # The following section is specific to Flutter.
 flutter:
+    uses-material-design: true
 
   # To add assets to your package, add an assets section, like this:
   # assets:
diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml
index 14ff407e2..9a5c4f14f 100644
--- a/cw_bitcoin_cash/pubspec.yaml
+++ b/cw_bitcoin_cash/pubspec.yaml
@@ -49,6 +49,7 @@ dependency_overrides:
 
 # The following section is specific to Flutter packages.
 flutter:
+    uses-material-design: true
 
 # To add assets to your package, add an assets section, like this:
 # assets:
diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml
index 070779caa..6e32c2ba1 100644
--- a/cw_core/pubspec.yaml
+++ b/cw_core/pubspec.yaml
@@ -47,6 +47,7 @@ dependency_overrides:
 
 # The following section is specific to Flutter.
 flutter:
+    uses-material-design: true
 
   # To add assets to your package, add an assets section, like this:
   # assets:
diff --git a/integration_test/components/common_test_cases.dart b/integration_test/components/common_test_cases.dart
index 2e2991804..83bbb0449 100644
--- a/integration_test/components/common_test_cases.dart
+++ b/integration_test/components/common_test_cases.dart
@@ -10,10 +10,16 @@ class CommonTestCases {
     hasType<T>();
   }
 
-  Future<void> tapItemByKey(String key, {bool shouldPumpAndSettle = true}) async {
+  Future<void> tapItemByKey(
+    String key, {
+    bool shouldPumpAndSettle = true,
+    int pumpDuration = 100,
+  }) async {
     final widget = find.byKey(ValueKey(key));
     await tester.tap(widget);
-    shouldPumpAndSettle ? await tester.pumpAndSettle() : await tester.pump();
+    shouldPumpAndSettle
+        ? await tester.pumpAndSettle(Duration(milliseconds: pumpDuration))
+        : await tester.pump();
   }
 
   Future<void> tapItemByFinder(Finder finder, {bool shouldPumpAndSettle = true}) async {
@@ -31,6 +37,11 @@ class CommonTestCases {
     expect(typeWidget, findsOneWidget);
   }
 
+  bool isKeyPresent(String key) {
+    final typeWidget = find.byKey(ValueKey(key));
+    return typeWidget.tryEvaluate();
+  }
+
   void hasValueKey(String key) {
     final typeWidget = find.byKey(ValueKey(key));
     expect(typeWidget, findsOneWidget);
@@ -53,33 +64,86 @@ class CommonTestCases {
     await tester.pumpAndSettle();
   }
 
-  Future<void> scrollUntilVisible(String childKey, String parentScrollableKey,
-      {double delta = 300}) async {
-    final scrollableWidget = find.descendant(
-      of: find.byKey(Key(parentScrollableKey)),
+  Future<void> dragUntilVisible(String childKey, String parentKey) async {
+    await tester.pumpAndSettle();
+
+    final itemFinder = find.byKey(ValueKey(childKey));
+    final listFinder = find.byKey(ValueKey(parentKey));
+
+    // Check if the widget is already in the widget tree
+    if (tester.any(itemFinder)) {
+      // Widget is already built and in the tree
+      tester.printToConsole('Child is already present');
+      return;
+    }
+
+    // We can adjust this as needed
+    final maxScrolls = 200;
+
+    int scrolls = 0;
+    bool found = false;
+
+    // We start by scrolling down
+    bool scrollDown = true;
+
+    // Flag to check if we've already reversed direction
+    bool reversedDirection = false;
+
+    // Find the Scrollable associated with the Parent Ad
+    final scrollableFinder = find.descendant(
+      of: listFinder,
       matching: find.byType(Scrollable),
     );
 
-    final isAlreadyVisibile = isWidgetVisible(find.byKey(ValueKey(childKey)));
-
-    if (isAlreadyVisibile) return;
-
-    await tester.scrollUntilVisible(
-      find.byKey(ValueKey(childKey)),
-      delta,
-      scrollable: scrollableWidget,
+    // Ensure that the Scrollable is found
+    expect(
+      scrollableFinder,
+      findsOneWidget,
+      reason: 'Scrollable descendant of the Parent Widget not found.',
     );
-  }
 
-  bool isWidgetVisible(Finder finder) {
-    try {
-      final Element element = finder.evaluate().single;
-      final RenderBox renderBox = element.renderObject as RenderBox;
-      return renderBox.paintBounds
-          .shift(renderBox.localToGlobal(Offset.zero))
-          .overlaps(tester.binding.renderViews.first.paintBounds);
-    } catch (e) {
-      return false;
+    // Get the initial scroll position
+    final scrollableState = tester.state<ScrollableState>(scrollableFinder);
+    double previousScrollPosition = scrollableState.position.pixels;
+
+    while (!found && scrolls < maxScrolls) {
+      tester.printToConsole('Scrolling ${scrollDown ? 'down' : 'up'}, attempt $scrolls');
+
+      // Perform the drag in the current direction
+      await tester.drag(
+        scrollableFinder,
+        scrollDown ? const Offset(0, -100) : const Offset(0, 100),
+      );
+      await tester.pumpAndSettle();
+      scrolls++;
+
+      // Update the scroll position after the drag
+      final currentScrollPosition = scrollableState.position.pixels;
+
+      if (currentScrollPosition == previousScrollPosition) {
+        // Cannot scroll further in this direction
+        if (reversedDirection) {
+          // We've already tried both directions
+          tester.printToConsole('Cannot scroll further in both directions. Widget not found.');
+          break;
+        } else {
+          // Reverse the scroll direction
+          scrollDown = !scrollDown;
+          reversedDirection = true;
+          tester.printToConsole('Reached the end, reversing direction');
+        }
+      } else {
+        // Continue scrolling in the current direction
+        previousScrollPosition = currentScrollPosition;
+      }
+
+      // Check if the widget is now in the widget tree
+      found = tester.any(itemFinder);
+    }
+
+    if (!found) {
+      tester.printToConsole('Widget not found after scrolling in both directions.');
+      return;
     }
   }
 
@@ -91,6 +155,15 @@ class CommonTestCases {
     await tester.pumpAndSettle();
   }
 
+  void findWidgetViaDescendant({
+    required FinderBase<Element> of,
+    required FinderBase<Element> matching,
+  }) {
+    final textWidget = find.descendant(of: of, matching: matching);
+
+    expect(textWidget, findsOneWidget);
+  }
+
   Future<void> defaultSleepTime({int seconds = 2}) async =>
       await Future.delayed(Duration(seconds: seconds));
 }
diff --git a/integration_test/components/common_test_constants.dart b/integration_test/components/common_test_constants.dart
index d8381973e..302d52189 100644
--- a/integration_test/components/common_test_constants.dart
+++ b/integration_test/components/common_test_constants.dart
@@ -9,5 +9,5 @@ class CommonTestConstants {
   static final String testWalletName = 'Integrated Testing Wallet';
   static final CryptoCurrency testReceiveCurrency = CryptoCurrency.sol;
   static final CryptoCurrency testDepositCurrency = CryptoCurrency.usdtSol;
-  static final String testWalletAddress = 'An2Y2fsUYKfYvN1zF89GAqR1e6GUMBg3qA83Y5ZWDf8L';
+  static final String testWalletAddress = '5v9gTW1yWPffhnbNKuvtL2frevAf4HpBMw8oYnfqUjhm';
 }
diff --git a/integration_test/components/common_test_flows.dart b/integration_test/components/common_test_flows.dart
index 807509de9..82f714da0 100644
--- a/integration_test/components/common_test_flows.dart
+++ b/integration_test/components/common_test_flows.dart
@@ -1,41 +1,65 @@
-import 'package:flutter/foundation.dart';
+import 'package:cake_wallet/entities/seed_type.dart';
+import 'package:cake_wallet/reactions/bip39_wallet_utils.dart';
+import 'package:cake_wallet/wallet_types.g.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import 'package:cake_wallet/.secrets.g.dart' as secrets;
 import 'package:cake_wallet/main.dart' as app;
 
+import '../robots/dashboard_page_robot.dart';
 import '../robots/disclaimer_page_robot.dart';
+import '../robots/new_wallet_page_robot.dart';
 import '../robots/new_wallet_type_page_robot.dart';
+import '../robots/pre_seed_page_robot.dart';
 import '../robots/restore_from_seed_or_key_robot.dart';
 import '../robots/restore_options_page_robot.dart';
 import '../robots/setup_pin_code_robot.dart';
+import '../robots/wallet_group_description_page_robot.dart';
+import '../robots/wallet_list_page_robot.dart';
+import '../robots/wallet_seed_page_robot.dart';
 import '../robots/welcome_page_robot.dart';
 import 'common_test_cases.dart';
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
+
 import 'common_test_constants.dart';
 
 class CommonTestFlows {
   CommonTestFlows(this._tester)
       : _commonTestCases = CommonTestCases(_tester),
         _welcomePageRobot = WelcomePageRobot(_tester),
+        _preSeedPageRobot = PreSeedPageRobot(_tester),
         _setupPinCodeRobot = SetupPinCodeRobot(_tester),
+        _dashboardPageRobot = DashboardPageRobot(_tester),
+        _newWalletPageRobot = NewWalletPageRobot(_tester),
         _disclaimerPageRobot = DisclaimerPageRobot(_tester),
+        _walletSeedPageRobot = WalletSeedPageRobot(_tester),
+        _walletListPageRobot = WalletListPageRobot(_tester),
         _newWalletTypePageRobot = NewWalletTypePageRobot(_tester),
         _restoreOptionsPageRobot = RestoreOptionsPageRobot(_tester),
-        _restoreFromSeedOrKeysPageRobot = RestoreFromSeedOrKeysPageRobot(_tester);
+        _restoreFromSeedOrKeysPageRobot = RestoreFromSeedOrKeysPageRobot(_tester),
+        _walletGroupDescriptionPageRobot = WalletGroupDescriptionPageRobot(_tester);
 
   final WidgetTester _tester;
   final CommonTestCases _commonTestCases;
 
   final WelcomePageRobot _welcomePageRobot;
+  final PreSeedPageRobot _preSeedPageRobot;
   final SetupPinCodeRobot _setupPinCodeRobot;
+  final NewWalletPageRobot _newWalletPageRobot;
+  final DashboardPageRobot _dashboardPageRobot;
   final DisclaimerPageRobot _disclaimerPageRobot;
+  final WalletSeedPageRobot _walletSeedPageRobot;
+  final WalletListPageRobot _walletListPageRobot;
   final NewWalletTypePageRobot _newWalletTypePageRobot;
   final RestoreOptionsPageRobot _restoreOptionsPageRobot;
   final RestoreFromSeedOrKeysPageRobot _restoreFromSeedOrKeysPageRobot;
+  final WalletGroupDescriptionPageRobot _walletGroupDescriptionPageRobot;
 
+  //* ========== Handles flow to start the app afresh and accept disclaimer =============
   Future<void> startAppFlow(Key key) async {
     await app.main(topLevelKey: ValueKey('send_flow_test_app_key'));
-    
+
     await _tester.pumpAndSettle();
 
     // --------- Disclaimer Page ------------
@@ -46,56 +70,275 @@ class CommonTestFlows {
     await _disclaimerPageRobot.tapAcceptButton();
   }
 
-  Future<void> restoreWalletThroughSeedsFlow() async {
-    await _welcomeToRestoreFromSeedsPath();
-    await _restoreFromSeeds();
+  //* ========== Handles flow from welcome to creating a new wallet ===============
+  Future<void> welcomePageToCreateNewWalletFlow(
+    WalletType walletTypeToCreate,
+    List<int> walletPin,
+  ) async {
+    await _welcomeToCreateWalletPath(walletTypeToCreate, walletPin);
+
+    await _generateNewWalletDetails();
+
+    await _confirmPreSeedInfo();
+
+    await _confirmWalletDetails();
   }
 
-  Future<void> restoreWalletThroughKeysFlow() async {
-    await _welcomeToRestoreFromSeedsPath();
+  //* ========== Handles flow from welcome to restoring wallet from seeds ===============
+  Future<void> welcomePageToRestoreWalletThroughSeedsFlow(
+    WalletType walletTypeToRestore,
+    String walletSeed,
+    List<int> walletPin,
+  ) async {
+    await _welcomeToRestoreFromSeedsOrKeysPath(walletTypeToRestore, walletPin);
+    await _restoreFromSeeds(walletTypeToRestore, walletSeed);
+  }
+
+  //* ========== Handles flow from welcome to restoring wallet from keys ===============
+  Future<void> welcomePageToRestoreWalletThroughKeysFlow(
+    WalletType walletTypeToRestore,
+    List<int> walletPin,
+  ) async {
+    await _welcomeToRestoreFromSeedsOrKeysPath(walletTypeToRestore, walletPin);
     await _restoreFromKeys();
   }
 
-  Future<void> _welcomeToRestoreFromSeedsPath() async {
-    // --------- Welcome Page ---------------
-    await _welcomePageRobot.navigateToRestoreWalletPage();
+  //* ========== Handles switching to wallet list or menu from dashboard ===============
+  Future<void> switchToWalletMenuFromDashboardPage() async {
+    _tester.printToConsole('Switching to Wallet Menu');
+    await _dashboardPageRobot.openDrawerMenu();
 
-    // ----------- Restore Options Page -----------
-    // Route to restore from seeds page to continue flow
-    await _restoreOptionsPageRobot.navigateToRestoreFromSeedsPage();
+    await _dashboardPageRobot.dashboardMenuWidgetRobot.navigateToWalletMenu();
+  }
 
+  void confirmAllAvailableWalletTypeIconsDisplayCorrectly() {
+    for (var walletType in availableWalletTypes) {
+      final imageUrl = walletTypeToCryptoCurrency(walletType).iconPath;
+
+      final walletIconFinder = find.image(
+        Image.asset(
+          imageUrl!,
+          width: 32,
+          height: 32,
+        ).image,
+      );
+
+      expect(walletIconFinder, findsAny);
+    }
+  }
+
+  //* ========== Handles creating new wallet flow from wallet list/menu ===============
+  Future<void> createNewWalletFromWalletMenu(WalletType walletTypeToCreate) async {
+    _tester.printToConsole('Creating ${walletTypeToCreate.name} Wallet');
+    await _walletListPageRobot.navigateToCreateNewWalletPage();
+    await _commonTestCases.defaultSleepTime();
+
+    await _selectWalletTypeForWallet(walletTypeToCreate);
+    await _commonTestCases.defaultSleepTime();
+
+    // ---- Wallet Group/New Seed Implementation Comes here
+    await _walletGroupDescriptionPageFlow(true, walletTypeToCreate);
+
+    await _generateNewWalletDetails();
+
+    await _confirmPreSeedInfo();
+
+    await _confirmWalletDetails();
+    await _commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> _walletGroupDescriptionPageFlow(bool isNewSeed, WalletType walletType) async {
+    if (!isBIP39Wallet(walletType)) return;
+
+    await _walletGroupDescriptionPageRobot.isWalletGroupDescriptionPage();
+
+    if (isNewSeed) {
+      await _walletGroupDescriptionPageRobot.navigateToCreateNewSeedPage();
+    } else {
+      await _walletGroupDescriptionPageRobot.navigateToChooseWalletGroup();
+    }
+  }
+
+  //* ========== Handles restore wallet flow from wallet list/menu ===============
+  Future<void> restoreWalletFromWalletMenu(WalletType walletType, String walletSeed) async {
+    _tester.printToConsole('Restoring ${walletType.name} Wallet');
+    await _walletListPageRobot.navigateToRestoreWalletOptionsPage();
+    await _commonTestCases.defaultSleepTime();
+
+    await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage();
+    await _commonTestCases.defaultSleepTime();
+
+    await _selectWalletTypeForWallet(walletType);
+    await _commonTestCases.defaultSleepTime();
+
+    await _restoreFromSeeds(walletType, walletSeed);
+    await _commonTestCases.defaultSleepTime();
+  }
+
+  //* ========== Handles setting up pin code for wallet on first install ===============
+  Future<void> setupPinCodeForWallet(List<int> pin) async {
     // ----------- SetupPinCode Page -------------
     // Confirm initial defaults - Widgets to be displayed etc
     await _setupPinCodeRobot.isSetupPinCodePage();
 
-    await _setupPinCodeRobot.enterPinCode(CommonTestConstants.pin, true);
-    await _setupPinCodeRobot.enterPinCode(CommonTestConstants.pin, false);
+    await _setupPinCodeRobot.enterPinCode(pin);
+    await _setupPinCodeRobot.enterPinCode(pin);
     await _setupPinCodeRobot.tapSuccessButton();
+  }
 
+  Future<void> _welcomeToCreateWalletPath(
+    WalletType walletTypeToCreate,
+    List<int> pin,
+  ) async {
+    await _welcomePageRobot.navigateToCreateNewWalletPage();
+
+    await setupPinCodeForWallet(pin);
+
+    await _selectWalletTypeForWallet(walletTypeToCreate);
+  }
+
+  Future<void> _welcomeToRestoreFromSeedsOrKeysPath(
+    WalletType walletTypeToRestore,
+    List<int> pin,
+  ) async {
+    await _welcomePageRobot.navigateToRestoreWalletPage();
+
+    await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage();
+
+    await setupPinCodeForWallet(pin);
+
+    await _selectWalletTypeForWallet(walletTypeToRestore);
+  }
+
+  //* ============ Handles New Wallet Type Page ==================
+  Future<void> _selectWalletTypeForWallet(WalletType type) async {
     // ----------- NewWalletType Page -------------
     // Confirm scroll behaviour works properly
-    await _newWalletTypePageRobot
-        .findParticularWalletTypeInScrollableList(CommonTestConstants.testWalletType);
+    await _newWalletTypePageRobot.findParticularWalletTypeInScrollableList(type);
 
     // Select a wallet and route to next page
-    await _newWalletTypePageRobot.selectWalletType(CommonTestConstants.testWalletType);
+    await _newWalletTypePageRobot.selectWalletType(type);
     await _newWalletTypePageRobot.onNextButtonPressed();
   }
 
-  Future<void> _restoreFromSeeds() async {
+  //* ============ Handles New Wallet Page ==================
+  Future<void> _generateNewWalletDetails() async {
+    await _newWalletPageRobot.isNewWalletPage();
+
+    await _newWalletPageRobot.generateWalletName();
+
+    await _newWalletPageRobot.onNextButtonPressed();
+  }
+
+  //* ============ Handles Pre Seed Page =====================
+  Future<void> _confirmPreSeedInfo() async {
+    await _preSeedPageRobot.isPreSeedPage();
+
+    await _preSeedPageRobot.onConfirmButtonPressed();
+  }
+
+  //* ============ Handles Wallet Seed Page ==================
+  Future<void> _confirmWalletDetails() async {
+    await _walletSeedPageRobot.isWalletSeedPage();
+
+    _walletSeedPageRobot.confirmWalletDetailsDisplayCorrectly();
+
+    _walletSeedPageRobot.confirmWalletSeedReminderDisplays();
+
+    await _walletSeedPageRobot.onCopySeedsButtonPressed();
+
+    await _walletSeedPageRobot.onNextButtonPressed();
+
+    await _walletSeedPageRobot.onConfirmButtonOnSeedAlertDialogPressed();
+  }
+
+  //* Main Restore Actions - On the RestoreFromSeed/Keys Page - Restore from Seeds Action
+  Future<void> _restoreFromSeeds(WalletType type, String walletSeed) async {
     // ----------- RestoreFromSeedOrKeys Page -------------
-    await _restoreFromSeedOrKeysPageRobot.enterWalletNameText(CommonTestConstants.testWalletName);
-    await _restoreFromSeedOrKeysPageRobot.enterSeedPhraseForWalletRestore(secrets.solanaTestWalletSeeds);
+
+    await _restoreFromSeedOrKeysPageRobot.selectWalletNameFromAvailableOptions();
+    await _restoreFromSeedOrKeysPageRobot.enterSeedPhraseForWalletRestore(walletSeed);
+
+    final numberOfWords = walletSeed.split(' ').length;
+
+    if (numberOfWords == 25 && (type == WalletType.monero)) {
+      await _restoreFromSeedOrKeysPageRobot
+          .chooseSeedTypeForMoneroOrWowneroWallets(MoneroSeedType.legacy);
+
+      // Using a constant value of 2831400 for the blockheight as its the restore blockheight for our testing wallet
+      await _restoreFromSeedOrKeysPageRobot
+          .enterBlockHeightForWalletRestore(secrets.moneroTestWalletBlockHeight);
+    }
+
     await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
   }
 
+  //* Main Restore Actions - On the RestoreFromSeed/Keys Page - Restore from Keys Action
   Future<void> _restoreFromKeys() async {
     await _commonTestCases.swipePage();
     await _commonTestCases.defaultSleepTime();
 
-    await _restoreFromSeedOrKeysPageRobot.enterWalletNameText(CommonTestConstants.testWalletName);
+    await _restoreFromSeedOrKeysPageRobot.selectWalletNameFromAvailableOptions(
+      isSeedFormEntry: false,
+    );
 
     await _restoreFromSeedOrKeysPageRobot.enterSeedPhraseForWalletRestore('');
     await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
   }
+
+  //* ====== Utility Function to get test wallet seeds for each wallet type ========
+  String getWalletSeedsByWalletType(WalletType walletType) {
+    switch (walletType) {
+      case WalletType.monero:
+        return secrets.moneroTestWalletSeeds;
+      case WalletType.bitcoin:
+        return secrets.bitcoinTestWalletSeeds;
+      case WalletType.ethereum:
+        return secrets.ethereumTestWalletSeeds;
+      case WalletType.litecoin:
+        return secrets.litecoinTestWalletSeeds;
+      case WalletType.bitcoinCash:
+        return secrets.bitcoinCashTestWalletSeeds;
+      case WalletType.polygon:
+        return secrets.polygonTestWalletSeeds;
+      case WalletType.solana:
+        return secrets.solanaTestWalletSeeds;
+      case WalletType.tron:
+        return secrets.tronTestWalletSeeds;
+      case WalletType.nano:
+        return secrets.nanoTestWalletSeeds;
+      case WalletType.wownero:
+        return secrets.wowneroTestWalletSeeds;
+      default:
+        return '';
+    }
+  }
+
+  //* ====== Utility Function to get test receive address for each wallet type ========
+  String getReceiveAddressByWalletType(WalletType walletType) {
+    switch (walletType) {
+      case WalletType.monero:
+        return secrets.moneroTestWalletReceiveAddress;
+      case WalletType.bitcoin:
+        return secrets.bitcoinTestWalletReceiveAddress;
+      case WalletType.ethereum:
+        return secrets.ethereumTestWalletReceiveAddress;
+      case WalletType.litecoin:
+        return secrets.litecoinTestWalletReceiveAddress;
+      case WalletType.bitcoinCash:
+        return secrets.bitcoinCashTestWalletReceiveAddress;
+      case WalletType.polygon:
+        return secrets.polygonTestWalletReceiveAddress;
+      case WalletType.solana:
+        return secrets.solanaTestWalletReceiveAddress;
+      case WalletType.tron:
+        return secrets.tronTestWalletReceiveAddress;
+      case WalletType.nano:
+        return secrets.nanoTestWalletReceiveAddress;
+      case WalletType.wownero:
+        return secrets.wowneroTestWalletReceiveAddress;
+      default:
+        return '';
+    }
+  }
 }
diff --git a/integration_test/funds_related_tests.dart b/integration_test/funds_related_tests.dart
index 9d97d47f8..db24fbc0b 100644
--- a/integration_test/funds_related_tests.dart
+++ b/integration_test/funds_related_tests.dart
@@ -9,6 +9,7 @@ import 'robots/dashboard_page_robot.dart';
 import 'robots/exchange_confirm_page_robot.dart';
 import 'robots/exchange_page_robot.dart';
 import 'robots/exchange_trade_page_robot.dart';
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
 
 void main() {
   IntegrationTestWidgetsFlutterBinding.ensureInitialized();
@@ -32,7 +33,11 @@ void main() {
 
       await commonTestFlows.startAppFlow(ValueKey('funds_exchange_test_app_key'));
 
-      await commonTestFlows.restoreWalletThroughSeedsFlow();
+      await commonTestFlows.welcomePageToRestoreWalletThroughSeedsFlow(
+        CommonTestConstants.testWalletType,
+        secrets.solanaTestWalletSeeds,
+        CommonTestConstants.pin,
+      );
 
       // ----------- RestoreFromSeedOrKeys Page -------------
       await dashboardPageRobot.navigateToExchangePage();
@@ -59,7 +64,7 @@ void main() {
 
       final onAuthPage = authPageRobot.onAuthPage();
       if (onAuthPage) {
-        await authPageRobot.enterPinCode(CommonTestConstants.pin, false);
+        await authPageRobot.enterPinCode(CommonTestConstants.pin);
       }
 
       // ----------- Exchange Confirm Page -------------
diff --git a/integration_test/robots/dashboard_menu_widget_robot.dart b/integration_test/robots/dashboard_menu_widget_robot.dart
new file mode 100644
index 000000000..f48033dda
--- /dev/null
+++ b/integration_test/robots/dashboard_menu_widget_robot.dart
@@ -0,0 +1,39 @@
+import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import '../components/common_test_cases.dart';
+
+class DashboardMenuWidgetRobot {
+  DashboardMenuWidgetRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  late CommonTestCases commonTestCases;
+
+  Future<void> hasMenuWidget() async {
+    commonTestCases.hasType<MenuWidget>();
+  }
+
+  void displaysTheCorrectWalletNameAndSubName() {
+    final menuWidgetState = tester.state<MenuWidgetState>(find.byType(MenuWidget));
+
+    final walletName = menuWidgetState.widget.dashboardViewModel.name;
+    commonTestCases.hasText(walletName);
+
+    final walletSubName = menuWidgetState.widget.dashboardViewModel.subname;
+    if (walletSubName.isNotEmpty) {
+      commonTestCases.hasText(walletSubName);
+    }
+  }
+
+  Future<void> navigateToWalletMenu() async {
+    await commonTestCases.tapItemByKey('dashboard_page_menu_widget_wallet_menu_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> navigateToSecurityAndBackupPage() async {
+    await commonTestCases.tapItemByKey(
+      'dashboard_page_menu_widget_security_and_backup_button_key',
+    );
+    await commonTestCases.defaultSleepTime();
+  }
+}
diff --git a/integration_test/robots/dashboard_page_robot.dart b/integration_test/robots/dashboard_page_robot.dart
index fc917c3b2..bc5f411ad 100644
--- a/integration_test/robots/dashboard_page_robot.dart
+++ b/integration_test/robots/dashboard_page_robot.dart
@@ -1,20 +1,44 @@
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart';
+import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import '../components/common_test_cases.dart';
+import 'dashboard_menu_widget_robot.dart';
 
 class DashboardPageRobot {
-  DashboardPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+  DashboardPageRobot(this.tester)
+      : commonTestCases = CommonTestCases(tester),
+        dashboardMenuWidgetRobot = DashboardMenuWidgetRobot(tester);
 
   final WidgetTester tester;
+  final DashboardMenuWidgetRobot dashboardMenuWidgetRobot;
   late CommonTestCases commonTestCases;
 
   Future<void> isDashboardPage() async {
     await commonTestCases.isSpecificPage<DashboardPage>();
   }
 
+  Future<void> confirmWalletTypeIsDisplayedCorrectly(
+    WalletType type, {
+    bool isHaven = false,
+  }) async {
+    final cryptoBalanceWidget =
+        tester.widget<CryptoBalanceWidget>(find.byType(CryptoBalanceWidget));
+    final hasAccounts = cryptoBalanceWidget.dashboardViewModel.balanceViewModel.hasAccounts;
+
+    if (hasAccounts) {
+      final walletName = cryptoBalanceWidget.dashboardViewModel.name;
+      commonTestCases.hasText(walletName);
+    } else {
+      final walletName = walletTypeToString(type);
+      final assetName = isHaven ? '$walletName Assets' : walletName;
+      commonTestCases.hasText(assetName);
+    }
+    await commonTestCases.defaultSleepTime(seconds: 5);
+  }
+
   void confirmServiceUpdateButtonDisplays() {
     commonTestCases.hasValueKey('dashboard_page_services_update_button_key');
   }
@@ -27,30 +51,40 @@ class DashboardPageRobot {
     commonTestCases.hasValueKey('dashboard_page_wallet_menu_button_key');
   }
 
-  Future<void> confirmRightCryptoAssetTitleDisplaysPerPageView(WalletType type,
-      {bool isHaven = false}) async {
+  Future<void> confirmRightCryptoAssetTitleDisplaysPerPageView(
+    WalletType type, {
+    bool isHaven = false,
+  }) async {
     //Balance Page
-    final walletName = walletTypeToString(type);
-    final assetName = isHaven ? '$walletName Assets' : walletName;
-    commonTestCases.hasText(assetName);
+    await confirmWalletTypeIsDisplayedCorrectly(type, isHaven: isHaven);
 
     // Swipe to Cake features Page
-    await commonTestCases.swipeByPageKey(key: 'dashboard_page_view_key', swipeRight: false);
-    await commonTestCases.defaultSleepTime();
+    await swipeDashboardTab(false);
     commonTestCases.hasText('Cake ${S.current.features}');
 
     // Swipe back to balance
-    await commonTestCases.swipeByPageKey(key: 'dashboard_page_view_key');
-    await commonTestCases.defaultSleepTime();
+    await swipeDashboardTab(true);
 
     // Swipe to Transactions Page
-    await commonTestCases.swipeByPageKey(key: 'dashboard_page_view_key');
-    await commonTestCases.defaultSleepTime();
+    await swipeDashboardTab(true);
     commonTestCases.hasText(S.current.transactions);
 
     // Swipe back to balance
-    await commonTestCases.swipeByPageKey(key: 'dashboard_page_view_key', swipeRight: false);
-    await commonTestCases.defaultSleepTime(seconds: 5);
+    await swipeDashboardTab(false);
+    await commonTestCases.defaultSleepTime(seconds: 3);
+  }
+
+  Future<void> swipeDashboardTab(bool swipeRight) async {
+    await commonTestCases.swipeByPageKey(
+      key: 'dashboard_page_view_key',
+      swipeRight: swipeRight,
+    );
+    await commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> openDrawerMenu() async {
+    await commonTestCases.tapItemByKey('dashboard_page_wallet_menu_button_key');
+    await commonTestCases.defaultSleepTime();
   }
 
   Future<void> navigateToBuyPage() async {
diff --git a/integration_test/robots/exchange_page_robot.dart b/integration_test/robots/exchange_page_robot.dart
index b439e4791..e01b2df9c 100644
--- a/integration_test/robots/exchange_page_robot.dart
+++ b/integration_test/robots/exchange_page_robot.dart
@@ -123,7 +123,7 @@ class ExchangePageRobot {
       return;
     }
 
-    await commonTestCases.scrollUntilVisible(
+    await commonTestCases.dragUntilVisible(
       'picker_items_index_${depositCurrency.name}_button_key',
       'picker_scrollbar_key',
     );
@@ -149,7 +149,7 @@ class ExchangePageRobot {
       return;
     }
 
-    await commonTestCases.scrollUntilVisible(
+    await commonTestCases.dragUntilVisible(
       'picker_items_index_${receiveCurrency.name}_button_key',
       'picker_scrollbar_key',
     );
diff --git a/integration_test/robots/new_wallet_page_robot.dart b/integration_test/robots/new_wallet_page_robot.dart
new file mode 100644
index 000000000..f8deb00ae
--- /dev/null
+++ b/integration_test/robots/new_wallet_page_robot.dart
@@ -0,0 +1,35 @@
+import 'package:cake_wallet/src/screens/new_wallet/new_wallet_page.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import '../components/common_test_cases.dart';
+
+class NewWalletPageRobot {
+  NewWalletPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  late CommonTestCases commonTestCases;
+
+  Future<void> isNewWalletPage() async {
+    await commonTestCases.isSpecificPage<NewWalletPage>();
+  }
+
+  Future<void> enterWalletName(String walletName) async {
+    await commonTestCases.enterText(
+      walletName,
+      'new_wallet_page_wallet_name_textformfield_key',
+    );
+    await commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> generateWalletName() async {
+    await commonTestCases.tapItemByKey(
+      'new_wallet_page_wallet_name_textformfield_generate_name_button_key',
+    );
+    await commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> onNextButtonPressed() async {
+    await commonTestCases.tapItemByKey('new_wallet_page_confirm_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+}
diff --git a/integration_test/robots/pin_code_widget_robot.dart b/integration_test/robots/pin_code_widget_robot.dart
index b6805e9e0..18dc5fba4 100644
--- a/integration_test/robots/pin_code_widget_robot.dart
+++ b/integration_test/robots/pin_code_widget_robot.dart
@@ -24,13 +24,12 @@ class PinCodeWidgetRobot {
     commonTestCases.hasValueKey('pin_code_button_0_key');
   }
 
-  Future<void> pushPinButton(int index) async {
-    await commonTestCases.tapItemByKey('pin_code_button_${index}_key');
-  }
-
-  Future<void> enterPinCode(List<int> pinCode, bool isFirstEntry) async {
+  Future<void> enterPinCode(List<int> pinCode, {int pumpDuration = 100}) async {
     for (int pin in pinCode) {
-      await pushPinButton(pin);
+      await commonTestCases.tapItemByKey(
+        'pin_code_button_${pin}_key',
+        pumpDuration: pumpDuration,
+      );
     }
 
     await commonTestCases.defaultSleepTime();
diff --git a/integration_test/robots/pre_seed_page_robot.dart b/integration_test/robots/pre_seed_page_robot.dart
new file mode 100644
index 000000000..01be1249c
--- /dev/null
+++ b/integration_test/robots/pre_seed_page_robot.dart
@@ -0,0 +1,20 @@
+import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import '../components/common_test_cases.dart';
+
+class PreSeedPageRobot {
+  PreSeedPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  late CommonTestCases commonTestCases;
+
+  Future<void> isPreSeedPage() async {
+    await commonTestCases.isSpecificPage<PreSeedPage>();
+  }
+
+  Future<void> onConfirmButtonPressed() async {
+    await commonTestCases.tapItemByKey('pre_seed_page_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+}
diff --git a/integration_test/robots/restore_from_seed_or_key_robot.dart b/integration_test/robots/restore_from_seed_or_key_robot.dart
index 43a65095d..9d973061b 100644
--- a/integration_test/robots/restore_from_seed_or_key_robot.dart
+++ b/integration_test/robots/restore_from_seed_or_key_robot.dart
@@ -1,3 +1,4 @@
+import 'package:cake_wallet/entities/seed_type.dart';
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
 import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart';
@@ -70,6 +71,22 @@ class RestoreFromSeedOrKeysPageRobot {
     await tester.pumpAndSettle();
   }
 
+  Future<void> enterBlockHeightForWalletRestore(String blockHeight) async {
+    await commonTestCases.enterText(
+      blockHeight,
+      'wallet_restore_from_seed_blockheight_textfield_key',
+    );
+    await tester.pumpAndSettle();
+  }
+
+  Future<void> chooseSeedTypeForMoneroOrWowneroWallets(MoneroSeedType selectedType) async {
+    await commonTestCases.tapItemByKey('wallet_restore_from_seed_seedtype_picker_button_key');
+
+    await commonTestCases.defaultSleepTime();
+
+    await commonTestCases.tapItemByKey('picker_items_index_${selectedType.title}_button_key');
+  }
+
   Future<void> onPasteSeedPhraseButtonPressed() async {
     await commonTestCases.tapItemByKey('wallet_restore_from_seed_wallet_seeds_paste_button_key');
   }
diff --git a/integration_test/robots/restore_options_page_robot.dart b/integration_test/robots/restore_options_page_robot.dart
index b3cefc90c..cd1919609 100644
--- a/integration_test/robots/restore_options_page_robot.dart
+++ b/integration_test/robots/restore_options_page_robot.dart
@@ -14,14 +14,14 @@ class RestoreOptionsPageRobot {
   }
 
   void hasRestoreOptionsButton() {
-    commonTestCases.hasValueKey('restore_options_from_seeds_button_key');
+    commonTestCases.hasValueKey('restore_options_from_seeds_or_keys_button_key');
     commonTestCases.hasValueKey('restore_options_from_backup_button_key');
     commonTestCases.hasValueKey('restore_options_from_hardware_wallet_button_key');
     commonTestCases.hasValueKey('restore_options_from_qr_button_key');
   }
 
-  Future<void> navigateToRestoreFromSeedsPage() async {
-    await commonTestCases.tapItemByKey('restore_options_from_seeds_button_key');
+  Future<void> navigateToRestoreFromSeedsOrKeysPage() async {
+    await commonTestCases.tapItemByKey('restore_options_from_seeds_or_keys_button_key');
     await commonTestCases.defaultSleepTime();
   }
 
diff --git a/integration_test/robots/security_and_backup_page_robot.dart b/integration_test/robots/security_and_backup_page_robot.dart
new file mode 100644
index 000000000..eb7c1bc87
--- /dev/null
+++ b/integration_test/robots/security_and_backup_page_robot.dart
@@ -0,0 +1,24 @@
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/settings/security_backup_page.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import '../components/common_test_cases.dart';
+
+class SecurityAndBackupPageRobot {
+  SecurityAndBackupPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  final CommonTestCases commonTestCases;
+
+  Future<void> isSecurityAndBackupPage() async {
+    await commonTestCases.isSpecificPage<SecurityBackupPage>();
+  }
+
+  void hasTitle() {
+    commonTestCases.hasText(S.current.security_and_backup);
+  }
+
+  Future<void> navigateToShowKeysPage() async {
+    await commonTestCases.tapItemByKey('security_backup_page_show_keys_button_key');
+  }
+}
diff --git a/integration_test/robots/send_page_robot.dart b/integration_test/robots/send_page_robot.dart
index 971556620..20cef948d 100644
--- a/integration_test/robots/send_page_robot.dart
+++ b/integration_test/robots/send_page_robot.dart
@@ -84,7 +84,7 @@ class SendPageRobot {
       return;
     }
 
-    await commonTestCases.scrollUntilVisible(
+    await commonTestCases.dragUntilVisible(
       'picker_items_index_${receiveCurrency.name}_button_key',
       'picker_scrollbar_key',
     );
@@ -117,7 +117,7 @@ class SendPageRobot {
       return;
     }
 
-    await commonTestCases.scrollUntilVisible(
+    await commonTestCases.dragUntilVisible(
       'picker_items_index_${priority.title}_button_key',
       'picker_scrollbar_key',
     );
@@ -198,7 +198,7 @@ class SendPageRobot {
       tester.printToConsole('Starting inner _handleAuth loop checks');
 
       try {
-        await authPageRobot.enterPinCode(CommonTestConstants.pin, false);
+        await authPageRobot.enterPinCode(CommonTestConstants.pin, pumpDuration: 500);
         tester.printToConsole('Auth done');
 
         await tester.pump();
@@ -213,6 +213,7 @@ class SendPageRobot {
   }
 
   Future<void> handleSendResult() async {
+    await tester.pump();
     tester.printToConsole('Inside handle function');
 
     bool hasError = false;
@@ -287,6 +288,8 @@ class SendPageRobot {
       // Loop to wait for the operation to commit transaction
       await _waitForCommitTransactionCompletion();
 
+      await tester.pump();
+
       await commonTestCases.defaultSleepTime(seconds: 4);
     } else {
       await commonTestCases.defaultSleepTime();
diff --git a/integration_test/robots/transactions_page_robot.dart b/integration_test/robots/transactions_page_robot.dart
new file mode 100644
index 000000000..40a49928f
--- /dev/null
+++ b/integration_test/robots/transactions_page_robot.dart
@@ -0,0 +1,286 @@
+import 'dart:async';
+
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart';
+import 'package:cake_wallet/utils/date_formatter.dart';
+import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
+import 'package:cake_wallet/view_model/dashboard/date_section_item.dart';
+import 'package:cake_wallet/view_model/dashboard/order_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/sync_status.dart';
+import 'package:cw_core/transaction_direction.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:intl/intl.dart';
+
+import '../components/common_test_cases.dart';
+
+class TransactionsPageRobot {
+  TransactionsPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  late CommonTestCases commonTestCases;
+
+  Future<void> isTransactionsPage() async {
+    await commonTestCases.isSpecificPage<TransactionsPage>();
+  }
+
+  Future<void> confirmTransactionsPageConstantsDisplayProperly() async {
+    await commonTestCases.defaultSleepTime();
+
+    final transactionsPage = tester.widget<TransactionsPage>(find.byType(TransactionsPage));
+    final dashboardViewModel = transactionsPage.dashboardViewModel;
+    if (dashboardViewModel.status is SyncingSyncStatus) {
+      commonTestCases.hasValueKey('transactions_page_syncing_alert_card_key');
+      commonTestCases.hasText(S.current.syncing_wallet_alert_title);
+      commonTestCases.hasText(S.current.syncing_wallet_alert_content);
+    }
+
+    commonTestCases.hasValueKey('transactions_page_header_row_key');
+    commonTestCases.hasText(S.current.transactions);
+    commonTestCases.hasValueKey('transactions_page_header_row_transaction_filter_button_key');
+  }
+
+  Future<void> confirmTransactionHistoryListDisplaysCorrectly(bool hasTxHistoryWhileSyncing) async {
+    // Retrieve the TransactionsPage widget and its DashboardViewModel
+    final transactionsPage = tester.widget<TransactionsPage>(find.byType(TransactionsPage));
+    final dashboardViewModel = transactionsPage.dashboardViewModel;
+
+    // Define a timeout to prevent infinite loops
+    // Putting at one hour for cases like monero that takes time to sync
+    final timeout = Duration(hours: 1);
+    final pollingInterval = Duration(seconds: 2);
+    final endTime = DateTime.now().add(timeout);
+
+    while (DateTime.now().isBefore(endTime)) {
+      final isSynced = dashboardViewModel.status is SyncedSyncStatus;
+      final itemsLoaded = dashboardViewModel.items.isNotEmpty;
+
+      // Perform item checks if items are loaded
+      if (itemsLoaded) {
+        await _performItemChecks(dashboardViewModel);
+      } else {
+        // Verify placeholder when items are not loaded
+        _verifyPlaceholder();
+      }
+
+      // Determine if we should exit the loop
+      if (_shouldExitLoop(hasTxHistoryWhileSyncing, isSynced, itemsLoaded)) {
+        break;
+      }
+
+      // Pump the UI and wait for the next polling interval
+      await tester.pump(pollingInterval);
+    }
+
+    // After the loop, verify that both status is synced and items are loaded
+    if (!_isFinalStateValid(dashboardViewModel)) {
+      throw TimeoutException('Dashboard did not sync and load items within the allotted time.');
+    }
+  }
+
+  bool _shouldExitLoop(bool hasTxHistoryWhileSyncing, bool isSynced, bool itemsLoaded) {
+    if (hasTxHistoryWhileSyncing) {
+      // When hasTxHistoryWhileSyncing is true, exit when status is synced
+      return isSynced;
+    } else {
+      // When hasTxHistoryWhileSyncing is false, exit when status is synced and items are loaded
+      return isSynced && itemsLoaded;
+    }
+  }
+
+  void _verifyPlaceholder() {
+    commonTestCases.hasValueKey('transactions_page_placeholder_transactions_text_key');
+    commonTestCases.hasText(S.current.placeholder_transactions);
+  }
+
+  bool _isFinalStateValid(DashboardViewModel dashboardViewModel) {
+    final isSynced = dashboardViewModel.status is SyncedSyncStatus;
+    final itemsLoaded = dashboardViewModel.items.isNotEmpty;
+    return isSynced && itemsLoaded;
+  }
+
+  Future<void> _performItemChecks(DashboardViewModel dashboardViewModel) async {
+    List<ActionListItem> items = dashboardViewModel.items;
+    for (var item in items) {
+      final keyId = (item.key as ValueKey<String>).value;
+      tester.printToConsole('\n');
+      tester.printToConsole(keyId);
+
+      await commonTestCases.dragUntilVisible(keyId, 'transactions_page_list_view_builder_key');
+      await tester.pump();
+
+      final isWidgetVisible = tester.any(find.byKey(ValueKey(keyId)));
+      if (!isWidgetVisible) {
+        tester.printToConsole('Moving to next visible item on list');
+        continue;
+      }
+      ;
+      await tester.pump();
+
+      if (item is DateSectionItem) {
+        await _verifyDateSectionItem(item);
+      } else if (item is TransactionListItem) {
+        tester.printToConsole(item.formattedTitle);
+        tester.printToConsole(item.formattedFiatAmount);
+        tester.printToConsole('\n');
+        await _verifyTransactionListItemDisplay(item, dashboardViewModel);
+      } else if (item is AnonpayTransactionListItem) {
+        await _verifyAnonpayTransactionListItemDisplay(item);
+      } else if (item is TradeListItem) {
+        await _verifyTradeListItemDisplay(item);
+      } else if (item is OrderListItem) {
+        await _verifyOrderListItemDisplay(item);
+      }
+    }
+  }
+
+  Future<void> _verifyDateSectionItem(DateSectionItem item) async {
+    final title = DateFormatter.convertDateTimeToReadableString(item.date);
+    tester.printToConsole(title);
+    await tester.pump();
+
+    commonTestCases.findWidgetViaDescendant(
+      of: find.byKey(item.key),
+      matching: find.text(title),
+    );
+  }
+
+  Future<void> _verifyTransactionListItemDisplay(
+    TransactionListItem item,
+    DashboardViewModel dashboardViewModel,
+  ) async {
+    final keyId =
+        '${dashboardViewModel.type.name}_transaction_history_item_${item.transaction.id}_key';
+
+    if (item.hasTokens && item.assetOfTransaction == null) return;
+
+    //* ==============Confirm it has the right key for this item ========
+    commonTestCases.hasValueKey(keyId);
+
+    //* ======Confirm it displays the properly formatted amount==========
+    commonTestCases.findWidgetViaDescendant(
+      of: find.byKey(ValueKey(keyId)),
+      matching: find.text(item.formattedCryptoAmount),
+    );
+
+    //* ======Confirm it displays the properly formatted title===========
+    final transactionType = dashboardViewModel.getTransactionType(item.transaction);
+
+    final title = item.formattedTitle + item.formattedStatus + transactionType;
+
+    commonTestCases.findWidgetViaDescendant(
+      of: find.byKey(ValueKey(keyId)),
+      matching: find.text(title),
+    );
+
+    //* ======Confirm it displays the properly formatted date============
+    final formattedDate = DateFormat('HH:mm').format(item.transaction.date);
+    commonTestCases.findWidgetViaDescendant(
+      of: find.byKey(ValueKey(keyId)),
+      matching: find.text(formattedDate),
+    );
+
+    //* ======Confirm it displays the properly formatted fiat amount=====
+    final formattedFiatAmount =
+        dashboardViewModel.balanceViewModel.isFiatDisabled ? '' : item.formattedFiatAmount;
+    if (formattedFiatAmount.isNotEmpty) {
+      commonTestCases.findWidgetViaDescendant(
+        of: find.byKey(ValueKey(keyId)),
+        matching: find.text(formattedFiatAmount),
+      );
+    }
+
+    //* ======Confirm it displays the right image based on the transaction direction=====
+    final imageToUse = item.transaction.direction == TransactionDirection.incoming
+        ? 'assets/images/down_arrow.png'
+        : 'assets/images/up_arrow.png';
+
+    find.widgetWithImage(Container, AssetImage(imageToUse));
+  }
+
+  Future<void> _verifyAnonpayTransactionListItemDisplay(AnonpayTransactionListItem item) async {
+    final keyId = 'anonpay_invoice_transaction_list_item_${item.transaction.invoiceId}_key';
+
+    //* ==============Confirm it has the right key for this item ========
+    commonTestCases.hasValueKey(keyId);
+
+    //* ==============Confirm it displays the correct provider =========================
+    commonTestCases.hasText(item.transaction.provider);
+
+    //* ===========Confirm it displays the properly formatted amount with currency ========
+    final currency = item.transaction.fiatAmount != null
+        ? item.transaction.fiatEquiv ?? ''
+        : CryptoCurrency.fromFullName(item.transaction.coinTo).name.toUpperCase();
+
+    final amount =
+        item.transaction.fiatAmount?.toString() ?? (item.transaction.amountTo?.toString() ?? '');
+
+    final amountCurrencyText = amount + ' ' + currency;
+
+    commonTestCases.hasText(amountCurrencyText);
+
+    //* ======Confirm it displays the properly formatted date=================
+    final formattedDate = DateFormat('HH:mm').format(item.transaction.createdAt);
+    commonTestCases.hasText(formattedDate);
+
+    //* ===============Confirm it displays the right image====================
+    find.widgetWithImage(ClipRRect, AssetImage('assets/images/trocador.png'));
+  }
+
+  Future<void> _verifyTradeListItemDisplay(TradeListItem item) async {
+    final keyId = 'trade_list_item_${item.trade.id}_key';
+
+    //* ==============Confirm it has the right key for this item ========
+    commonTestCases.hasValueKey(keyId);
+
+    //* ==============Confirm it displays the correct provider =========================
+    final conversionFlow = '${item.trade.from.toString()} → ${item.trade.to.toString()}';
+
+    commonTestCases.hasText(conversionFlow);
+
+    //* ===========Confirm it displays the properly formatted amount with its crypto tag ========
+
+    final amountCryptoText = item.tradeFormattedAmount + ' ' + item.trade.from.toString();
+
+    commonTestCases.hasText(amountCryptoText);
+
+    //* ======Confirm it displays the properly formatted date=================
+    final createdAtFormattedDate =
+        item.trade.createdAt != null ? DateFormat('HH:mm').format(item.trade.createdAt!) : null;
+
+    if (createdAtFormattedDate != null) {
+      commonTestCases.hasText(createdAtFormattedDate);
+    }
+
+    //* ===============Confirm it displays the right image====================
+    commonTestCases.hasValueKey(item.trade.provider.image);
+  }
+
+  Future<void> _verifyOrderListItemDisplay(OrderListItem item) async {
+    final keyId = 'order_list_item_${item.order.id}_key';
+
+    //* ==============Confirm it has the right key for this item ========
+    commonTestCases.hasValueKey(keyId);
+
+    //* ==============Confirm it displays the correct provider =========================
+    final orderFlow = '${item.order.from!} → ${item.order.to}';
+
+    commonTestCases.hasText(orderFlow);
+
+    //* ===========Confirm it displays the properly formatted amount with its crypto tag ========
+
+    final amountCryptoText = item.orderFormattedAmount + ' ' + item.order.to!;
+
+    commonTestCases.hasText(amountCryptoText);
+
+    //* ======Confirm it displays the properly formatted date=================
+    final createdAtFormattedDate = DateFormat('HH:mm').format(item.order.createdAt);
+
+    commonTestCases.hasText(createdAtFormattedDate);
+  }
+}
diff --git a/integration_test/robots/wallet_group_description_page_robot.dart b/integration_test/robots/wallet_group_description_page_robot.dart
new file mode 100644
index 000000000..57500dc3c
--- /dev/null
+++ b/integration_test/robots/wallet_group_description_page_robot.dart
@@ -0,0 +1,32 @@
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/new_wallet/wallet_group_description_page.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import '../components/common_test_cases.dart';
+
+class WalletGroupDescriptionPageRobot {
+  WalletGroupDescriptionPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  final CommonTestCases commonTestCases;
+
+  Future<void> isWalletGroupDescriptionPage() async {
+    await commonTestCases.isSpecificPage<WalletGroupDescriptionPage>();
+  }
+
+  void hasTitle() {
+    commonTestCases.hasText(S.current.wallet_group);
+  }
+
+  Future<void> navigateToCreateNewSeedPage() async {
+    await commonTestCases.tapItemByKey(
+      'wallet_group_description_page_create_new_seed_button_key',
+    );
+  }
+
+  Future<void> navigateToChooseWalletGroup() async {
+    await commonTestCases.tapItemByKey(
+      'wallet_group_description_page_choose_wallet_group_button_key',
+    );
+  }
+}
diff --git a/integration_test/robots/wallet_keys_robot.dart b/integration_test/robots/wallet_keys_robot.dart
new file mode 100644
index 000000000..f6aeb3a66
--- /dev/null
+++ b/integration_test/robots/wallet_keys_robot.dart
@@ -0,0 +1,162 @@
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/reactions/wallet_connect.dart';
+import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
+import 'package:cake_wallet/store/app_store.dart';
+import 'package:cw_core/monero_wallet_keys.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:cw_monero/monero_wallet.dart';
+import 'package:cw_wownero/wownero_wallet.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:polyseed/polyseed.dart';
+
+import '../components/common_test_cases.dart';
+
+class WalletKeysAndSeedPageRobot {
+  WalletKeysAndSeedPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  final CommonTestCases commonTestCases;
+
+  Future<void> isWalletKeysAndSeedPage() async {
+    await commonTestCases.isSpecificPage<WalletKeysPage>();
+  }
+
+  void hasTitle() {
+    final walletKeysPage = tester.widget<WalletKeysPage>(find.byType(WalletKeysPage));
+    final walletKeysViewModel = walletKeysPage.walletKeysViewModel;
+    commonTestCases.hasText(walletKeysViewModel.title);
+  }
+
+  void hasShareWarning() {
+    commonTestCases.hasText(S.current.do_not_share_warning_text.toUpperCase());
+  }
+
+  Future<void> confirmWalletCredentials(WalletType walletType) async {
+    final walletKeysPage = tester.widget<WalletKeysPage>(find.byType(WalletKeysPage));
+    final walletKeysViewModel = walletKeysPage.walletKeysViewModel;
+
+    final appStore = walletKeysViewModel.appStore;
+    final walletName = walletType.name;
+    bool hasSeed = appStore.wallet!.seed != null;
+    bool hasHexSeed = appStore.wallet!.hexSeed != null;
+    bool hasPrivateKey = appStore.wallet!.privateKey != null;
+
+    if (walletType == WalletType.monero) {
+      final moneroWallet = appStore.wallet as MoneroWallet;
+      final lang = PolyseedLang.getByPhrase(moneroWallet.seed);
+      final legacySeed = moneroWallet.seedLegacy(lang.nameEnglish);
+
+      _confirmMoneroWalletCredentials(
+        appStore,
+        walletName,
+        moneroWallet.seed,
+        legacySeed,
+      );
+    }
+
+    if (walletType == WalletType.wownero) {
+      final wowneroWallet = appStore.wallet as WowneroWallet;
+      final lang = PolyseedLang.getByPhrase(wowneroWallet.seed);
+      final legacySeed = wowneroWallet.seedLegacy(lang.nameEnglish);
+
+      _confirmMoneroWalletCredentials(
+        appStore,
+        walletName,
+        wowneroWallet.seed,
+        legacySeed,
+      );
+    }
+
+    if (walletType == WalletType.bitcoin ||
+        walletType == WalletType.litecoin ||
+        walletType == WalletType.bitcoinCash) {
+      commonTestCases.hasText(appStore.wallet!.seed!);
+      tester.printToConsole('$walletName wallet has seeds properly displayed');
+    }
+
+    if (isEVMCompatibleChain(walletType) ||
+        walletType == WalletType.solana ||
+        walletType == WalletType.tron) {
+      if (hasSeed) {
+        commonTestCases.hasText(appStore.wallet!.seed!);
+        tester.printToConsole('$walletName wallet has seeds properly displayed');
+      }
+      if (hasPrivateKey) {
+        commonTestCases.hasText(appStore.wallet!.privateKey!);
+        tester.printToConsole('$walletName wallet has private key properly displayed');
+      }
+    }
+
+    if (walletType == WalletType.nano || walletType == WalletType.banano) {
+      if (hasSeed) {
+        commonTestCases.hasText(appStore.wallet!.seed!);
+        tester.printToConsole('$walletName wallet has seeds properly displayed');
+      }
+      if (hasHexSeed) {
+        commonTestCases.hasText(appStore.wallet!.hexSeed!);
+        tester.printToConsole('$walletName wallet has hexSeed properly displayed');
+      }
+      if (hasPrivateKey) {
+        commonTestCases.hasText(appStore.wallet!.privateKey!);
+        tester.printToConsole('$walletName wallet has private key properly displayed');
+      }
+    }
+
+    await commonTestCases.defaultSleepTime(seconds: 5);
+  }
+
+  void _confirmMoneroWalletCredentials(
+    AppStore appStore,
+    String walletName,
+    String seed,
+    String legacySeed,
+  ) {
+    final keys = appStore.wallet!.keys as MoneroWalletKeys;
+
+    final hasPublicSpendKey = commonTestCases.isKeyPresent(
+      '${walletName}_wallet_public_spend_key_item_key',
+    );
+    final hasPrivateSpendKey = commonTestCases.isKeyPresent(
+      '${walletName}_wallet_private_spend_key_item_key',
+    );
+    final hasPublicViewKey = commonTestCases.isKeyPresent(
+      '${walletName}_wallet_public_view_key_item_key',
+    );
+    final hasPrivateViewKey = commonTestCases.isKeyPresent(
+      '${walletName}_wallet_private_view_key_item_key',
+    );
+    final hasSeeds = seed.isNotEmpty;
+    final hasSeedLegacy = Polyseed.isValidSeed(seed);
+
+    if (hasPublicSpendKey) {
+      commonTestCases.hasText(keys.publicSpendKey);
+      tester.printToConsole('$walletName wallet has public spend key properly displayed');
+    }
+    if (hasPrivateSpendKey) {
+      commonTestCases.hasText(keys.privateSpendKey);
+      tester.printToConsole('$walletName wallet has private spend key properly displayed');
+    }
+    if (hasPublicViewKey) {
+      commonTestCases.hasText(keys.publicViewKey);
+      tester.printToConsole('$walletName wallet has public view key properly displayed');
+    }
+    if (hasPrivateViewKey) {
+      commonTestCases.hasText(keys.privateViewKey);
+      tester.printToConsole('$walletName wallet has private view key properly displayed');
+    }
+    if (hasSeeds) {
+      commonTestCases.hasText(seed);
+      tester.printToConsole('$walletName wallet has seeds properly displayed');
+    }
+    if (hasSeedLegacy) {
+      commonTestCases.hasText(legacySeed);
+      tester.printToConsole('$walletName wallet has legacy seeds properly displayed');
+    }
+  }
+
+  Future<void> backToDashboard() async {
+    tester.printToConsole('Going back to dashboard from credentials page');
+    await commonTestCases.goBack();
+    await commonTestCases.goBack();
+  }
+}
diff --git a/integration_test/robots/wallet_list_page_robot.dart b/integration_test/robots/wallet_list_page_robot.dart
new file mode 100644
index 000000000..b46d4ca95
--- /dev/null
+++ b/integration_test/robots/wallet_list_page_robot.dart
@@ -0,0 +1,27 @@
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import '../components/common_test_cases.dart';
+
+class WalletListPageRobot {
+  WalletListPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  late CommonTestCases commonTestCases;
+
+  Future<void> isWalletListPage() async {
+    await commonTestCases.isSpecificPage<WalletListPageRobot>();
+  }
+
+  void displaysCorrectTitle() {
+    commonTestCases.hasText(S.current.wallets);
+  }
+
+  Future<void> navigateToCreateNewWalletPage() async {
+    commonTestCases.tapItemByKey('wallet_list_page_create_new_wallet_button_key');
+  }
+
+  Future<void> navigateToRestoreWalletOptionsPage() async {
+    commonTestCases.tapItemByKey('wallet_list_page_restore_wallet_button_key');
+  }
+}
diff --git a/integration_test/robots/wallet_seed_page_robot.dart b/integration_test/robots/wallet_seed_page_robot.dart
new file mode 100644
index 000000000..d52f3b1ec
--- /dev/null
+++ b/integration_test/robots/wallet_seed_page_robot.dart
@@ -0,0 +1,57 @@
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import '../components/common_test_cases.dart';
+
+class WalletSeedPageRobot {
+  WalletSeedPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
+
+  final WidgetTester tester;
+  late CommonTestCases commonTestCases;
+
+  Future<void> isWalletSeedPage() async {
+    await commonTestCases.isSpecificPage<WalletSeedPage>();
+  }
+
+  Future<void> onNextButtonPressed() async {
+    await commonTestCases.tapItemByKey('wallet_seed_page_next_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> onConfirmButtonOnSeedAlertDialogPressed() async {
+    await commonTestCases.tapItemByKey('wallet_seed_page_seed_alert_confirm_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> onBackButtonOnSeedAlertDialogPressed() async {
+    await commonTestCases.tapItemByKey('wallet_seed_page_seed_alert_back_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+
+  void confirmWalletDetailsDisplayCorrectly() {
+    final walletSeedPage = tester.widget<WalletSeedPage>(find.byType(WalletSeedPage));
+
+    final walletSeedViewModel = walletSeedPage.walletSeedViewModel;
+
+    final walletName = walletSeedViewModel.name;
+    final walletSeeds = walletSeedViewModel.seed;
+
+    commonTestCases.hasText(walletName);
+    commonTestCases.hasText(walletSeeds);
+  }
+
+  void confirmWalletSeedReminderDisplays() {
+    commonTestCases.hasText(S.current.seed_reminder);
+  }
+
+  Future<void> onSaveSeedsButtonPressed() async {
+    await commonTestCases.tapItemByKey('wallet_seed_page_save_seeds_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+
+  Future<void> onCopySeedsButtonPressed() async {
+    await commonTestCases.tapItemByKey('wallet_seed_page_copy_seeds_button_key');
+    await commonTestCases.defaultSleepTime();
+  }
+}
diff --git a/integration_test/test_suites/confirm_seeds_flow_test.dart b/integration_test/test_suites/confirm_seeds_flow_test.dart
new file mode 100644
index 000000000..bf6fd5a5f
--- /dev/null
+++ b/integration_test/test_suites/confirm_seeds_flow_test.dart
@@ -0,0 +1,107 @@
+import 'package:cake_wallet/wallet_types.g.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
+import '../components/common_test_constants.dart';
+import '../components/common_test_flows.dart';
+import '../robots/auth_page_robot.dart';
+import '../robots/dashboard_page_robot.dart';
+import '../robots/security_and_backup_page_robot.dart';
+import '../robots/wallet_keys_robot.dart';
+
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+  AuthPageRobot authPageRobot;
+  CommonTestFlows commonTestFlows;
+  DashboardPageRobot dashboardPageRobot;
+  WalletKeysAndSeedPageRobot walletKeysAndSeedPageRobot;
+  SecurityAndBackupPageRobot securityAndBackupPageRobot;
+
+  testWidgets(
+    'Confirm if the seeds display properly',
+    (tester) async {
+      authPageRobot = AuthPageRobot(tester);
+      commonTestFlows = CommonTestFlows(tester);
+      dashboardPageRobot = DashboardPageRobot(tester);
+      walletKeysAndSeedPageRobot = WalletKeysAndSeedPageRobot(tester);
+      securityAndBackupPageRobot = SecurityAndBackupPageRobot(tester);
+
+      // Start the app
+      await commonTestFlows.startAppFlow(
+        ValueKey('confirm_creds_display_correctly_flow_app_key'),
+      );
+
+      await commonTestFlows.welcomePageToCreateNewWalletFlow(
+        WalletType.solana,
+        CommonTestConstants.pin,
+      );
+
+      await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(WalletType.solana);
+
+      await _confirmSeedsFlowForWalletType(
+        WalletType.solana,
+        authPageRobot,
+        dashboardPageRobot,
+        securityAndBackupPageRobot,
+        walletKeysAndSeedPageRobot,
+        tester,
+      );
+
+      // Do the same for other available wallet types
+      for (var walletType in availableWalletTypes) {
+        if (walletType == WalletType.solana) {
+          continue;
+        }
+
+        await commonTestFlows.switchToWalletMenuFromDashboardPage();
+
+        await commonTestFlows.createNewWalletFromWalletMenu(walletType);
+
+        await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(walletType);
+
+        await _confirmSeedsFlowForWalletType(
+          walletType,
+          authPageRobot,
+          dashboardPageRobot,
+          securityAndBackupPageRobot,
+          walletKeysAndSeedPageRobot,
+          tester,
+        );
+      }
+
+      await Future.delayed(Duration(seconds: 15));
+    },
+  );
+}
+
+Future<void> _confirmSeedsFlowForWalletType(
+  WalletType walletType,
+  AuthPageRobot authPageRobot,
+  DashboardPageRobot dashboardPageRobot,
+  SecurityAndBackupPageRobot securityAndBackupPageRobot,
+  WalletKeysAndSeedPageRobot walletKeysAndSeedPageRobot,
+  WidgetTester tester,
+) async {
+  await dashboardPageRobot.openDrawerMenu();
+  await dashboardPageRobot.dashboardMenuWidgetRobot.navigateToSecurityAndBackupPage();
+
+  await securityAndBackupPageRobot.navigateToShowKeysPage();
+
+  final onAuthPage = authPageRobot.onAuthPage();
+  if (onAuthPage) {
+    await authPageRobot.enterPinCode(CommonTestConstants.pin);
+  }
+
+  await tester.pumpAndSettle();
+
+  await walletKeysAndSeedPageRobot.isWalletKeysAndSeedPage();
+  walletKeysAndSeedPageRobot.hasTitle();
+  walletKeysAndSeedPageRobot.hasShareWarning();
+
+  walletKeysAndSeedPageRobot.confirmWalletCredentials(walletType);
+
+  await walletKeysAndSeedPageRobot.backToDashboard();
+}
diff --git a/integration_test/test_suites/create_wallet_flow_test.dart b/integration_test/test_suites/create_wallet_flow_test.dart
new file mode 100644
index 000000000..2a50dbbe8
--- /dev/null
+++ b/integration_test/test_suites/create_wallet_flow_test.dart
@@ -0,0 +1,57 @@
+import 'package:cake_wallet/wallet_types.g.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
+import '../components/common_test_constants.dart';
+import '../components/common_test_flows.dart';
+import '../robots/dashboard_page_robot.dart';
+
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+  CommonTestFlows commonTestFlows;
+  DashboardPageRobot dashboardPageRobot;
+
+  testWidgets(
+    'Create Wallet Flow',
+    (tester) async {
+      commonTestFlows = CommonTestFlows(tester);
+      dashboardPageRobot = DashboardPageRobot(tester);
+
+      // Start the app
+      await commonTestFlows.startAppFlow(
+        ValueKey('create_wallets_through_seeds_test_app_key'),
+      );
+
+      await commonTestFlows.welcomePageToCreateNewWalletFlow(
+        WalletType.solana,
+        CommonTestConstants.pin,
+      );
+
+      // Confirm it actually restores a solana wallet
+      await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(WalletType.solana);
+
+      // Do the same for other available wallet types
+      for (var walletType in availableWalletTypes) {
+        if (walletType == WalletType.solana) {
+          continue;
+        }
+
+        await commonTestFlows.switchToWalletMenuFromDashboardPage();
+
+        await commonTestFlows.createNewWalletFromWalletMenu(walletType);
+
+        await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(walletType);
+      }
+
+      // Goes to the wallet menu and provides a confirmation that all the wallets were correctly restored
+      await commonTestFlows.switchToWalletMenuFromDashboardPage();
+
+      commonTestFlows.confirmAllAvailableWalletTypeIconsDisplayCorrectly();
+
+      await Future.delayed(Duration(seconds: 5));
+    },
+  );
+}
diff --git a/integration_test/test_suites/exchange_flow_test.dart b/integration_test/test_suites/exchange_flow_test.dart
index 6c993634c..c36ef9396 100644
--- a/integration_test/test_suites/exchange_flow_test.dart
+++ b/integration_test/test_suites/exchange_flow_test.dart
@@ -9,6 +9,7 @@ import '../robots/dashboard_page_robot.dart';
 import '../robots/exchange_confirm_page_robot.dart';
 import '../robots/exchange_page_robot.dart';
 import '../robots/exchange_trade_page_robot.dart';
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
 
 void main() {
   IntegrationTestWidgetsFlutterBinding.ensureInitialized();
@@ -20,40 +21,42 @@ void main() {
   ExchangeTradePageRobot exchangeTradePageRobot;
   ExchangeConfirmPageRobot exchangeConfirmPageRobot;
 
-  group('Exchange Flow Tests', () {
-    testWidgets('Exchange flow', (tester) async {
-      authPageRobot = AuthPageRobot(tester);
-      commonTestFlows = CommonTestFlows(tester);
-      exchangePageRobot = ExchangePageRobot(tester);
-      dashboardPageRobot = DashboardPageRobot(tester);
-      exchangeTradePageRobot = ExchangeTradePageRobot(tester);
-      exchangeConfirmPageRobot = ExchangeConfirmPageRobot(tester);
+  testWidgets('Exchange flow', (tester) async {
+    authPageRobot = AuthPageRobot(tester);
+    commonTestFlows = CommonTestFlows(tester);
+    exchangePageRobot = ExchangePageRobot(tester);
+    dashboardPageRobot = DashboardPageRobot(tester);
+    exchangeTradePageRobot = ExchangeTradePageRobot(tester);
+    exchangeConfirmPageRobot = ExchangeConfirmPageRobot(tester);
 
-      await commonTestFlows.startAppFlow(ValueKey('exchange_app_test_key'));
-      await commonTestFlows.restoreWalletThroughSeedsFlow();
-      await dashboardPageRobot.navigateToExchangePage();
+    await commonTestFlows.startAppFlow(ValueKey('exchange_app_test_key'));
+    await commonTestFlows.welcomePageToRestoreWalletThroughSeedsFlow(
+      CommonTestConstants.testWalletType,
+      secrets.solanaTestWalletSeeds,
+      CommonTestConstants.pin,
+    );
+    await dashboardPageRobot.navigateToExchangePage();
 
-      // ----------- Exchange Page -------------
-      await exchangePageRobot.selectDepositCurrency(CommonTestConstants.testDepositCurrency);
-      await exchangePageRobot.selectReceiveCurrency(CommonTestConstants.testReceiveCurrency);
+    // ----------- Exchange Page -------------
+    await exchangePageRobot.selectDepositCurrency(CommonTestConstants.testDepositCurrency);
+    await exchangePageRobot.selectReceiveCurrency(CommonTestConstants.testReceiveCurrency);
 
-      await exchangePageRobot.enterDepositAmount(CommonTestConstants.exchangeTestAmount);
-      await exchangePageRobot.enterDepositRefundAddress(
-        depositAddress: CommonTestConstants.testWalletAddress,
-      );
-      await exchangePageRobot.enterReceiveAddress(CommonTestConstants.testWalletAddress);
-      
-      await exchangePageRobot.onExchangeButtonPressed();
+    await exchangePageRobot.enterDepositAmount(CommonTestConstants.exchangeTestAmount);
+    await exchangePageRobot.enterDepositRefundAddress(
+      depositAddress: CommonTestConstants.testWalletAddress,
+    );
+    await exchangePageRobot.enterReceiveAddress(CommonTestConstants.testWalletAddress);
 
-      await exchangePageRobot.handleErrors(CommonTestConstants.exchangeTestAmount);
+    await exchangePageRobot.onExchangeButtonPressed();
 
-      final onAuthPage = authPageRobot.onAuthPage();
-      if (onAuthPage) {
-        await authPageRobot.enterPinCode(CommonTestConstants.pin, false);
-      }
+    await exchangePageRobot.handleErrors(CommonTestConstants.exchangeTestAmount);
 
-      await exchangeConfirmPageRobot.onSavedTradeIdButtonPressed();
-      await exchangeTradePageRobot.onGotItButtonPressed();
-    });
+    final onAuthPage = authPageRobot.onAuthPage();
+    if (onAuthPage) {
+      await authPageRobot.enterPinCode(CommonTestConstants.pin);
+    }
+
+    await exchangeConfirmPageRobot.onSavedTradeIdButtonPressed();
+    await exchangeTradePageRobot.onGotItButtonPressed();
   });
 }
diff --git a/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart b/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
new file mode 100644
index 000000000..a810aa722
--- /dev/null
+++ b/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
@@ -0,0 +1,63 @@
+import 'package:cake_wallet/wallet_types.g.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
+import '../components/common_test_constants.dart';
+import '../components/common_test_flows.dart';
+import '../robots/dashboard_page_robot.dart';
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
+
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+  CommonTestFlows commonTestFlows;
+  DashboardPageRobot dashboardPageRobot;
+
+  testWidgets(
+    'Restoring Wallets Through Seeds',
+    (tester) async {
+      commonTestFlows = CommonTestFlows(tester);
+      dashboardPageRobot = DashboardPageRobot(tester);
+
+      // Start the app
+      await commonTestFlows.startAppFlow(
+        ValueKey('restore_wallets_through_seeds_test_app_key'),
+      );
+
+      // Restore the first wallet type: Solana
+      await commonTestFlows.welcomePageToRestoreWalletThroughSeedsFlow(
+        WalletType.solana,
+        secrets.solanaTestWalletSeeds,
+        CommonTestConstants.pin,
+      );
+
+      // Confirm it actually restores a solana wallet
+      await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(WalletType.solana);
+
+      // Do the same for other available wallet types
+      for (var walletType in availableWalletTypes) {
+        if (walletType == WalletType.solana) {
+          continue;
+        }
+
+        await commonTestFlows.switchToWalletMenuFromDashboardPage();
+
+        await commonTestFlows.restoreWalletFromWalletMenu(
+          walletType,
+          commonTestFlows.getWalletSeedsByWalletType(walletType),
+        );
+
+        await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(walletType);
+      }
+
+      // Goes to the wallet menu and provides a visual confirmation that all the wallets were correctly restored
+      await commonTestFlows.switchToWalletMenuFromDashboardPage();
+
+      commonTestFlows.confirmAllAvailableWalletTypeIconsDisplayCorrectly();
+
+      await Future.delayed(Duration(seconds: 5));
+    },
+  );
+}
diff --git a/integration_test/test_suites/send_flow_test.dart b/integration_test/test_suites/send_flow_test.dart
index 38ac1574f..7a46435b8 100644
--- a/integration_test/test_suites/send_flow_test.dart
+++ b/integration_test/test_suites/send_flow_test.dart
@@ -6,6 +6,7 @@ import '../components/common_test_constants.dart';
 import '../components/common_test_flows.dart';
 import '../robots/dashboard_page_robot.dart';
 import '../robots/send_page_robot.dart';
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
 
 void main() {
   IntegrationTestWidgetsFlutterBinding.ensureInitialized();
@@ -14,28 +15,30 @@ void main() {
   CommonTestFlows commonTestFlows;
   DashboardPageRobot dashboardPageRobot;
 
-  group('Send Flow Tests', () {
-    testWidgets('Send flow', (tester) async {
-      commonTestFlows = CommonTestFlows(tester);
-      sendPageRobot = SendPageRobot(tester: tester);
-      dashboardPageRobot = DashboardPageRobot(tester);
+  testWidgets('Send flow', (tester) async {
+    commonTestFlows = CommonTestFlows(tester);
+    sendPageRobot = SendPageRobot(tester: tester);
+    dashboardPageRobot = DashboardPageRobot(tester);
 
-      await commonTestFlows.startAppFlow(ValueKey('send_test_app_key'));
-      await commonTestFlows.restoreWalletThroughSeedsFlow();
-      await dashboardPageRobot.navigateToSendPage();
+    await commonTestFlows.startAppFlow(ValueKey('send_test_app_key'));
+    await commonTestFlows.welcomePageToRestoreWalletThroughSeedsFlow(
+      CommonTestConstants.testWalletType,
+      secrets.solanaTestWalletSeeds,
+      CommonTestConstants.pin,
+    );
+    await dashboardPageRobot.navigateToSendPage();
 
-      await sendPageRobot.enterReceiveAddress(CommonTestConstants.testWalletAddress);
-      await sendPageRobot.selectReceiveCurrency(CommonTestConstants.testReceiveCurrency);
-      await sendPageRobot.enterAmount(CommonTestConstants.sendTestAmount);
-      await sendPageRobot.selectTransactionPriority();
+    await sendPageRobot.enterReceiveAddress(CommonTestConstants.testWalletAddress);
+    await sendPageRobot.selectReceiveCurrency(CommonTestConstants.testReceiveCurrency);
+    await sendPageRobot.enterAmount(CommonTestConstants.sendTestAmount);
+    await sendPageRobot.selectTransactionPriority();
 
-      await sendPageRobot.onSendButtonPressed();
+    await sendPageRobot.onSendButtonPressed();
 
-      await sendPageRobot.handleSendResult();
+    await sendPageRobot.handleSendResult();
 
-      await sendPageRobot.onSendButtonOnConfirmSendingDialogPressed();
+    await sendPageRobot.onSendButtonOnConfirmSendingDialogPressed();
 
-      await sendPageRobot.onSentDialogPopUp();
-    });
+    await sendPageRobot.onSentDialogPopUp();
   });
 }
diff --git a/integration_test/test_suites/transaction_history_flow_test.dart b/integration_test/test_suites/transaction_history_flow_test.dart
new file mode 100644
index 000000000..8af6d39fd
--- /dev/null
+++ b/integration_test/test_suites/transaction_history_flow_test.dart
@@ -0,0 +1,70 @@
+import 'package:cw_core/wallet_type.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
+import '../components/common_test_constants.dart';
+import '../components/common_test_flows.dart';
+import '../robots/dashboard_page_robot.dart';
+import '../robots/transactions_page_robot.dart';
+import 'package:cake_wallet/.secrets.g.dart' as secrets;
+
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+  CommonTestFlows commonTestFlows;
+  DashboardPageRobot dashboardPageRobot;
+  TransactionsPageRobot transactionsPageRobot;
+
+  /// Two Test Scenarios
+  ///  - Fully Synchronizes and display the transaction history either immediately or few seconds after fully synchronizing
+  /// - Displays the transaction history progressively as synchronizing happens
+  testWidgets('Transaction history flow', (tester) async {
+    commonTestFlows = CommonTestFlows(tester);
+    dashboardPageRobot = DashboardPageRobot(tester);
+    transactionsPageRobot = TransactionsPageRobot(tester);
+
+    await commonTestFlows.startAppFlow(
+      ValueKey('confirm_creds_display_correctly_flow_app_key'),
+    );
+
+    /// Test Scenario 1 - Displays transaction history list after fully synchronizing.
+    ///
+    /// For Solana/Tron WalletTypes.
+    await commonTestFlows.welcomePageToRestoreWalletThroughSeedsFlow(
+      WalletType.solana,
+      secrets.solanaTestWalletSeeds,
+      CommonTestConstants.pin,
+    );
+
+    await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(WalletType.solana);
+
+    await dashboardPageRobot.swipeDashboardTab(true);
+
+    await transactionsPageRobot.isTransactionsPage();
+
+    await transactionsPageRobot.confirmTransactionsPageConstantsDisplayProperly();
+
+    await transactionsPageRobot.confirmTransactionHistoryListDisplaysCorrectly(false);
+
+    /// Test Scenario 2 - Displays transaction history list while synchronizing.
+    ///
+    /// For bitcoin/Monero/Wownero WalletTypes.
+    await commonTestFlows.switchToWalletMenuFromDashboardPage();
+
+    await commonTestFlows.restoreWalletFromWalletMenu(
+      WalletType.bitcoin,
+      secrets.bitcoinTestWalletSeeds,
+    );
+
+    await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(WalletType.bitcoin);
+
+    await dashboardPageRobot.swipeDashboardTab(true);
+
+    await transactionsPageRobot.isTransactionsPage();
+
+    await transactionsPageRobot.confirmTransactionsPageConstantsDisplayProperly();
+
+    await transactionsPageRobot.confirmTransactionHistoryListDisplaysCorrectly(true);
+  });
+}
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 322ef6f86..470bdf4e7 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -109,15 +109,15 @@ PODS:
     - FlutterMacOS
   - permission_handler_apple (9.1.1):
     - Flutter
-  - Protobuf (3.27.2)
+  - Protobuf (3.28.2)
   - ReachabilitySwift (5.2.3)
   - reactive_ble_mobile (0.0.1):
     - Flutter
     - Protobuf (~> 3.5)
     - SwiftProtobuf (~> 1.0)
-  - SDWebImage (5.19.4):
-    - SDWebImage/Core (= 5.19.4)
-  - SDWebImage/Core (5.19.4)
+  - SDWebImage (5.19.7):
+    - SDWebImage/Core (= 5.19.7)
+  - SDWebImage/Core (5.19.7)
   - sensitive_clipboard (0.0.1):
     - Flutter
   - share_plus (0.0.1):
@@ -271,10 +271,10 @@ SPEC CHECKSUMS:
   package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
   path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
   permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
-  Protobuf: fb2c13674723f76ff6eede14f78847a776455fa2
+  Protobuf: 28c89b24435762f60244e691544ed80f50d82701
   ReachabilitySwift: 7f151ff156cea1481a8411701195ac6a984f4979
   reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c
-  SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d
+  SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3
   sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
   share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
   shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
diff --git a/lib/src/screens/InfoPage.dart b/lib/src/screens/InfoPage.dart
index 5398df22c..84b9e8632 100644
--- a/lib/src/screens/InfoPage.dart
+++ b/lib/src/screens/InfoPage.dart
@@ -21,6 +21,7 @@ abstract class InfoPage extends BasePage {
   String get pageTitle;
   String get pageDescription;
   String get buttonText;
+  Key? get buttonKey;
   void Function(BuildContext) get onPressed;
 
   @override
@@ -39,15 +40,14 @@ abstract class InfoPage extends BasePage {
         alignment: Alignment.center,
         padding: EdgeInsets.all(24),
         child: ConstrainedBox(
-          constraints: BoxConstraints(
-              maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
+          constraints:
+              BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
           child: Column(
             mainAxisAlignment: MainAxisAlignment.spaceBetween,
             children: <Widget>[
               Expanded(
                 child: ConstrainedBox(
-                  constraints: BoxConstraints(
-                      maxHeight: MediaQuery.of(context).size.height * 0.3),
+                  constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3),
                   child: AspectRatio(aspectRatio: 1, child: image),
                 ),
               ),
@@ -61,14 +61,13 @@ abstract class InfoPage extends BasePage {
                       height: 1.7,
                       fontSize: 14,
                       fontWeight: FontWeight.normal,
-                      color: Theme.of(context)
-                          .extension<CakeTextTheme>()!
-                          .secondaryTextColor,
+                      color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
                     ),
                   ),
                 ),
               ),
               PrimaryButton(
+                key: buttonKey,
                 onPressed: () => onPressed(context),
                 text: buttonText,
                 color: Theme.of(context).primaryColor,
diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart
index 953463269..9c012d518 100644
--- a/lib/src/screens/dashboard/dashboard_page.dart
+++ b/lib/src/screens/dashboard/dashboard_page.dart
@@ -140,7 +140,7 @@ class _DashboardPageView extends BasePage {
   bool get resizeToAvoidBottomInset => false;
 
   @override
-  Widget get endDrawer => MenuWidget(dashboardViewModel);
+  Widget get endDrawer => MenuWidget(dashboardViewModel, ValueKey('dashboard_page_drawer_menu_widget_key'));
 
   @override
   Widget leading(BuildContext context) {
diff --git a/lib/src/screens/dashboard/pages/nft_details_page.dart b/lib/src/screens/dashboard/pages/nft_details_page.dart
index 15d2a2b5c..b8352a672 100644
--- a/lib/src/screens/dashboard/pages/nft_details_page.dart
+++ b/lib/src/screens/dashboard/pages/nft_details_page.dart
@@ -28,7 +28,10 @@ class NFTDetailsPage extends BasePage {
   bool get resizeToAvoidBottomInset => false;
 
   @override
-  Widget get endDrawer => MenuWidget(dashboardViewModel);
+  Widget get endDrawer => MenuWidget(
+        dashboardViewModel,
+        ValueKey('nft_details_page_menu_widget_key'),
+      );
 
   @override
   Widget trailing(BuildContext context) {
diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart
index b6d1c286b..0db9ac35b 100644
--- a/lib/src/screens/dashboard/pages/transactions_page.dart
+++ b/lib/src/screens/dashboard/pages/transactions_page.dart
@@ -1,11 +1,13 @@
 import 'package:cake_wallet/bitcoin/bitcoin.dart';
 import 'package:cake_wallet/src/screens/dashboard/widgets/anonpay_transaction_row.dart';
 import 'package:cake_wallet/src/screens/dashboard/widgets/order_row.dart';
+import 'package:cake_wallet/src/screens/dashboard/widgets/trade_row.dart';
 import 'package:cake_wallet/themes/extensions/placeholder_theme.dart';
 import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
 import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart';
 import 'package:cake_wallet/view_model/dashboard/order_list_item.dart';
+import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
 import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/sync_status.dart';
 import 'package:cw_core/wallet_type.dart';
@@ -14,9 +16,7 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
 import 'package:flutter_mobx/flutter_mobx.dart';
 import 'package:cake_wallet/src/screens/dashboard/widgets/header_row.dart';
 import 'package:cake_wallet/src/screens/dashboard/widgets/date_section_raw.dart';
-import 'package:cake_wallet/src/screens/dashboard/widgets/trade_row.dart';
 import 'package:cake_wallet/src/screens/dashboard/widgets/transaction_raw.dart';
-import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
 import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
 import 'package:cake_wallet/view_model/dashboard/date_section_item.dart';
 import 'package:intl/intl.dart';
@@ -49,6 +49,7 @@ class TransactionsPage extends StatelessWidget {
                 return Padding(
                   padding: const EdgeInsets.fromLTRB(24, 0, 24, 8),
                   child: DashBoardRoundedCardWidget(
+                    key: ValueKey('transactions_page_syncing_alert_card_key'),
                     onTap: () {
                       try {
                         final uri = Uri.parse(
@@ -64,82 +65,93 @@ class TransactionsPage extends StatelessWidget {
                 return Container();
               }
             }),
-            HeaderRow(dashboardViewModel: dashboardViewModel),
-            Expanded(child: Observer(builder: (_) {
-              final items = dashboardViewModel.items;
+            HeaderRow(
+              dashboardViewModel: dashboardViewModel,
+              key: ValueKey('transactions_page_header_row_key'),
+            ),
+            Expanded(
+              child: Observer(
+                builder: (_) {
+                  final items = dashboardViewModel.items;
 
-              return items.isNotEmpty
-                  ? ListView.builder(
-                      itemCount: items.length,
-                      itemBuilder: (context, index) {
-                        final item = items[index];
+                  return items.isNotEmpty
+                      ? ListView.builder(
+                          key: ValueKey('transactions_page_list_view_builder_key'),
+                          itemCount: items.length,
+                          itemBuilder: (context, index) {
+                            final item = items[index];
 
-                        if (item is DateSectionItem) {
-                          return DateSectionRaw(date: item.date);
-                        }
-
-                        if (item is TransactionListItem) {
-                          if (item.hasTokens && item.assetOfTransaction == null) {
-                            return Container();
-                          }
-
-                          final transaction = item.transaction;
-                          final transactionType = dashboardViewModel.getTransactionType(transaction);
-
-                          List<String> tags = [];
-                          if (dashboardViewModel.type == WalletType.bitcoin) {
-                            if (bitcoin!.txIsReceivedSilentPayment(transaction)) {
-                              tags.add(S.of(context).silent_payment);
+                            if (item is DateSectionItem) {
+                              return DateSectionRaw(date: item.date, key: item.key);
                             }
-                          }
-                          if (dashboardViewModel.type == WalletType.litecoin) {
-                            if (bitcoin!.txIsMweb(transaction)) {
-                              tags.add("MWEB");
+
+                            if (item is TransactionListItem) {
+                              if (item.hasTokens && item.assetOfTransaction == null) {
+                                return Container();
+                              }
+
+                              final transaction = item.transaction;
+                              final transactionType =
+                                  dashboardViewModel.getTransactionType(transaction);
+
+                              List<String> tags = [];
+                              if (dashboardViewModel.type == WalletType.bitcoin) {
+                                if (bitcoin!.txIsReceivedSilentPayment(transaction)) {
+                                  tags.add(S.of(context).silent_payment);
+                                }
+                              }
+                              if (dashboardViewModel.type == WalletType.litecoin) {
+                                if (bitcoin!.txIsMweb(transaction)) {
+                                  tags.add("MWEB");
+                                }
+                              }
+
+                              return Observer(
+                                builder: (_) => TransactionRow(
+                                  key: item.key,
+                                  onTap: () => Navigator.of(context)
+                                      .pushNamed(Routes.transactionDetails, arguments: transaction),
+                                  direction: transaction.direction,
+                                  formattedDate: DateFormat('HH:mm').format(transaction.date),
+                                  formattedAmount: item.formattedCryptoAmount,
+                                  formattedFiatAmount:
+                                      dashboardViewModel.balanceViewModel.isFiatDisabled
+                                          ? ''
+                                          : item.formattedFiatAmount,
+                                  isPending: transaction.isPending,
+                                  title:
+                                      item.formattedTitle + item.formattedStatus + transactionType,
+                                  tags: tags,
+                                ),
+                              );
                             }
-                          }
 
-                          return Observer(
-                            builder: (_) => TransactionRow(
-                              onTap: () => Navigator.of(context)
-                                  .pushNamed(Routes.transactionDetails, arguments: transaction),
-                              direction: transaction.direction,
-                              formattedDate: DateFormat('HH:mm').format(transaction.date),
-                              formattedAmount: item.formattedCryptoAmount,
-                              formattedFiatAmount:
-                                  dashboardViewModel.balanceViewModel.isFiatDisabled
-                                      ? ''
-                                      : item.formattedFiatAmount,
-                              isPending: transaction.isPending,
-                              title:
-                                  item.formattedTitle + item.formattedStatus + transactionType,
-                              tags: tags,
-                            ),
-                          );
-                        }
+                            if (item is AnonpayTransactionListItem) {
+                              final transactionInfo = item.transaction;
 
-                        if (item is AnonpayTransactionListItem) {
-                          final transactionInfo = item.transaction;
+                              return AnonpayTransactionRow(
+                                key: item.key,
+                                onTap: () => Navigator.of(context).pushNamed(
+                                    Routes.anonPayDetailsPage,
+                                    arguments: transactionInfo),
+                                currency: transactionInfo.fiatAmount != null
+                                    ? transactionInfo.fiatEquiv ?? ''
+                                    : CryptoCurrency.fromFullName(transactionInfo.coinTo)
+                                        .name
+                                        .toUpperCase(),
+                                provider: transactionInfo.provider,
+                                amount: transactionInfo.fiatAmount?.toString() ??
+                                    (transactionInfo.amountTo?.toString() ?? ''),
+                                createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt),
+                              );
+                            }
 
-                          return AnonpayTransactionRow(
-                            onTap: () => Navigator.of(context)
-                                .pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
-                            currency: transactionInfo.fiatAmount != null
-                                ? transactionInfo.fiatEquiv ?? ''
-                                : CryptoCurrency.fromFullName(transactionInfo.coinTo)
-                                    .name
-                                    .toUpperCase(),
-                            provider: transactionInfo.provider,
-                            amount: transactionInfo.fiatAmount?.toString() ??
-                                (transactionInfo.amountTo?.toString() ?? ''),
-                            createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt),
-                          );
-                        }
+                            if (item is TradeListItem) {
+                              final trade = item.trade;
 
-                        if (item is TradeListItem) {
-                          final trade = item.trade;
-
-                          return Observer(
-                              builder: (_) => TradeRow(
+                              return Observer(
+                                builder: (_) => TradeRow(
+                                  key: item.key,
                                   onTap: () => Navigator.of(context)
                                       .pushNamed(Routes.tradeDetails, arguments: trade),
                                   provider: trade.provider,
@@ -148,36 +160,44 @@ class TransactionsPage extends StatelessWidget {
                                   createdAtFormattedDate: trade.createdAt != null
                                       ? DateFormat('HH:mm').format(trade.createdAt!)
                                       : null,
-                                  formattedAmount: item.tradeFormattedAmount));
-                        }
+                                  formattedAmount: item.tradeFormattedAmount,
+                                ),
+                              );
+                            }
 
-                        if (item is OrderListItem) {
-                          final order = item.order;
+                            if (item is OrderListItem) {
+                              final order = item.order;
 
-                          return Observer(
-                              builder: (_) => OrderRow(
-                                    onTap: () => Navigator.of(context)
-                                        .pushNamed(Routes.orderDetails, arguments: order),
-                                    provider: order.provider,
-                                    from: order.from!,
-                                    to: order.to!,
-                                    createdAtFormattedDate:
-                                        DateFormat('HH:mm').format(order.createdAt),
-                                    formattedAmount: item.orderFormattedAmount,
-                                  ));
-                        }
+                              return Observer(
+                                builder: (_) => OrderRow(
+                                  key: item.key,
+                                  onTap: () => Navigator.of(context)
+                                      .pushNamed(Routes.orderDetails, arguments: order),
+                                  provider: order.provider,
+                                  from: order.from!,
+                                  to: order.to!,
+                                  createdAtFormattedDate:
+                                      DateFormat('HH:mm').format(order.createdAt),
+                                  formattedAmount: item.orderFormattedAmount,
+                                ),
+                              );
+                            }
 
-                        return Container(color: Colors.transparent, height: 1);
-                      })
-                  : Center(
-                      child: Text(
-                        S.of(context).placeholder_transactions,
-                        style: TextStyle(
-                            fontSize: 14,
-                            color: Theme.of(context).extension<PlaceholderTheme>()!.color),
-                      ),
-                    );
-            }))
+                            return Container(color: Colors.transparent, height: 1);
+                          })
+                      : Center(
+                          child: Text(
+                            key: ValueKey('transactions_page_placeholder_transactions_text_key'),
+                            S.of(context).placeholder_transactions,
+                            style: TextStyle(
+                              fontSize: 14,
+                              color: Theme.of(context).extension<PlaceholderTheme>()!.color,
+                            ),
+                          ),
+                        );
+                },
+              ),
+            )
           ],
         ),
       ),
diff --git a/lib/src/screens/dashboard/widgets/anonpay_transaction_row.dart b/lib/src/screens/dashboard/widgets/anonpay_transaction_row.dart
index cb8bef0b7..64d4bfe85 100644
--- a/lib/src/screens/dashboard/widgets/anonpay_transaction_row.dart
+++ b/lib/src/screens/dashboard/widgets/anonpay_transaction_row.dart
@@ -9,6 +9,7 @@ class AnonpayTransactionRow extends StatelessWidget {
     required this.currency,
     required this.onTap,
     required this.amount,
+    super.key,
   });
 
   final VoidCallback? onTap;
diff --git a/lib/src/screens/dashboard/widgets/date_section_raw.dart b/lib/src/screens/dashboard/widgets/date_section_raw.dart
index 73f9f03a1..02fcef7f4 100644
--- a/lib/src/screens/dashboard/widgets/date_section_raw.dart
+++ b/lib/src/screens/dashboard/widgets/date_section_raw.dart
@@ -1,42 +1,27 @@
 import 'package:flutter/material.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
-import 'package:intl/intl.dart';
-import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/utils/date_formatter.dart';
 
 class DateSectionRaw extends StatelessWidget {
-  DateSectionRaw({required this.date});
+  DateSectionRaw({required this.date, super.key});
 
   final DateTime date;
 
   @override
   Widget build(BuildContext context) {
-    final nowDate = DateTime.now();
-    final diffDays = date.difference(nowDate).inDays;
-    final isToday = nowDate.day == date.day &&
-        nowDate.month == date.month &&
-        nowDate.year == date.year;
-    final dateSectionDateFormat = DateFormatter.withCurrentLocal(hasTime: false);
-    var title = "";
-
-    if (isToday) {
-      title = S.of(context).today;
-    } else if (diffDays == 0) {
-      title = S.of(context).yesterday;
-    } else if (diffDays > -7 && diffDays < 0) {
-      final dateFormat = DateFormat.EEEE();
-      title = dateFormat.format(date);
-    } else {
-      title = dateSectionDateFormat.format(date);
-    }
+    final title = DateFormatter.convertDateTimeToReadableString(date);
 
     return Container(
-        height: 35,
-        alignment: Alignment.center,
-        color: Colors.transparent,
-        child: Text(title,
-            style: TextStyle(
-                fontSize: 12,
-                color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)));
+      height: 35,
+      alignment: Alignment.center,
+      color: Colors.transparent,
+      child: Text(
+        title,
+        style: TextStyle(
+          fontSize: 12,
+          color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor,
+        ),
+      ),
+    );
   }
 }
diff --git a/lib/src/screens/dashboard/widgets/header_row.dart b/lib/src/screens/dashboard/widgets/header_row.dart
index cb4f67fc2..f1f3f0889 100644
--- a/lib/src/screens/dashboard/widgets/header_row.dart
+++ b/lib/src/screens/dashboard/widgets/header_row.dart
@@ -7,7 +7,7 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
 import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
 
 class HeaderRow extends StatelessWidget {
-  HeaderRow({required this.dashboardViewModel});
+  HeaderRow({required this.dashboardViewModel, super.key});
 
   final DashboardViewModel dashboardViewModel;
 
@@ -34,6 +34,7 @@ class HeaderRow extends StatelessWidget {
           Semantics(
             container: true,
             child: GestureDetector(
+              key: ValueKey('transactions_page_header_row_transaction_filter_button_key'),
               onTap: () {
                 showPopUp<void>(
                   context: context,
diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart
index 6d8379b29..f0e330f04 100644
--- a/lib/src/screens/dashboard/widgets/menu_widget.dart
+++ b/lib/src/screens/dashboard/widgets/menu_widget.dart
@@ -9,7 +9,7 @@ import 'package:cw_core/wallet_type.dart';
 import 'package:flutter_mobx/flutter_mobx.dart';
 
 class MenuWidget extends StatefulWidget {
-  MenuWidget(this.dashboardViewModel);
+  MenuWidget(this.dashboardViewModel, Key? key);
 
   final DashboardViewModel dashboardViewModel;
 
@@ -193,6 +193,7 @@ class MenuWidgetState extends State<MenuWidget> {
                   final isLastTile = index == itemCount - 1;
 
                   return SettingActionButton(
+                    key: item.key,
                     isLastTile: isLastTile,
                     tileHeight: tileHeight,
                     selectionActive: false,
diff --git a/lib/src/screens/dashboard/widgets/order_row.dart b/lib/src/screens/dashboard/widgets/order_row.dart
index 8adc6e0d5..221ea5689 100644
--- a/lib/src/screens/dashboard/widgets/order_row.dart
+++ b/lib/src/screens/dashboard/widgets/order_row.dart
@@ -12,7 +12,10 @@ class OrderRow extends StatelessWidget {
     required this.to,
     required this.createdAtFormattedDate,
     this.onTap,
-    this.formattedAmount});
+    this.formattedAmount,
+    super.key,
+  });
+  
   final VoidCallback? onTap;
   final BuyProviderDescription provider;
   final String from;
@@ -22,8 +25,7 @@ class OrderRow extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final iconColor =
-        Theme.of(context).extension<OrderTheme>()!.iconColor;
+    final iconColor = Theme.of(context).extension<OrderTheme>()!.iconColor;
 
     final providerIcon = getBuyProviderIcon(provider, iconColor: iconColor);
 
@@ -36,46 +38,42 @@ class OrderRow extends StatelessWidget {
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
-              if (providerIcon != null) Padding(
-                padding: EdgeInsets.only(right: 12),
-                child: providerIcon,
-              ),
+              if (providerIcon != null)
+                Padding(
+                  padding: EdgeInsets.only(right: 12),
+                  child: providerIcon,
+                ),
               Expanded(
                   child: Column(
-                    mainAxisSize: MainAxisSize.min,
-                    children: [
-                      Row(
-                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                          children: <Widget>[
-                            Text('$from → $to',
-                                style: TextStyle(
-                                    fontSize: 16,
-                                    fontWeight: FontWeight.w500,
-                                    color: Theme.of(context).extension<DashboardPageTheme>()!.textColor
-                                )),
-                            formattedAmount != null
-                                ? Text(formattedAmount! + ' ' + to,
-                                style: TextStyle(
-                                    fontSize: 16,
-                                    fontWeight: FontWeight.w500,
-                                    color: Theme.of(context).extension<DashboardPageTheme>()!.textColor
-                                ))
-                                : Container()
-                          ]),
-                      SizedBox(height: 5),
-                      Row(
-                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                          children: <Widget>[
-                            Text(createdAtFormattedDate,
-                                style: TextStyle(
-                                    fontSize: 14,
-                                    color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
-                          ])
-                    ],
-                  )
-              )
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[
+                    Text('$from → $to',
+                        style: TextStyle(
+                            fontSize: 16,
+                            fontWeight: FontWeight.w500,
+                            color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)),
+                    formattedAmount != null
+                        ? Text(formattedAmount! + ' ' + to,
+                            style: TextStyle(
+                                fontSize: 16,
+                                fontWeight: FontWeight.w500,
+                                color:
+                                    Theme.of(context).extension<DashboardPageTheme>()!.textColor))
+                        : Container()
+                  ]),
+                  SizedBox(height: 5),
+                  Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[
+                    Text(createdAtFormattedDate,
+                        style: TextStyle(
+                            fontSize: 14,
+                            color:
+                                Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
+                  ])
+                ],
+              ))
             ],
           ),
         ));
   }
-}
\ No newline at end of file
+}
diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart
index 7c809aa9d..84a5d2beb 100644
--- a/lib/src/screens/dashboard/widgets/trade_row.dart
+++ b/lib/src/screens/dashboard/widgets/trade_row.dart
@@ -13,6 +13,7 @@ class TradeRow extends StatelessWidget {
     required this.createdAtFormattedDate,
     this.onTap,
     this.formattedAmount,
+    super.key,
   });
 
   final VoidCallback? onTap;
diff --git a/lib/src/screens/dashboard/widgets/transaction_raw.dart b/lib/src/screens/dashboard/widgets/transaction_raw.dart
index b18131f3d..2d7cbb809 100644
--- a/lib/src/screens/dashboard/widgets/transaction_raw.dart
+++ b/lib/src/screens/dashboard/widgets/transaction_raw.dart
@@ -14,6 +14,7 @@ class TransactionRow extends StatelessWidget {
     required this.tags,
     required this.title,
     required this.onTap,
+    super.key,
   });
 
   final VoidCallback onTap;
@@ -28,33 +29,36 @@ class TransactionRow extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return InkWell(
-        onTap: onTap,
-        child: Container(
-          padding: EdgeInsets.fromLTRB(24, 8, 24, 8),
-          color: Colors.transparent,
-          child: Row(
-            mainAxisSize: MainAxisSize.max,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              Container(
-                height: 36,
-                width: 36,
-                decoration: BoxDecoration(
-                    shape: BoxShape.circle,
-                    color: Theme.of(context).extension<TransactionTradeTheme>()!.rowsColor),
-                child: Image.asset(direction == TransactionDirection.incoming
-                    ? 'assets/images/down_arrow.png'
-                    : 'assets/images/up_arrow.png'),
-              ),
-              SizedBox(width: 12),
-              Expanded(
-                  child: Column(
+      onTap: onTap,
+      child: Container(
+        padding: EdgeInsets.fromLTRB(24, 8, 24, 8),
+        color: Colors.transparent,
+        child: Row(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            Container(
+              height: 36,
+              width: 36,
+              decoration: BoxDecoration(
+                  shape: BoxShape.circle,
+                  color: Theme.of(context).extension<TransactionTradeTheme>()!.rowsColor),
+              child: Image.asset(direction == TransactionDirection.incoming
+                  ? 'assets/images/down_arrow.png'
+                  : 'assets/images/up_arrow.png'),
+            ),
+            SizedBox(width: 12),
+            Expanded(
+              child: Column(
                 mainAxisSize: MainAxisSize.min,
                 children: [
-                  Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[
-                    Row(
-                      children: [
-                        Text(title,
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: <Widget>[
+                      Row(
+                        children: [
+                          Text(
+                            title,
                             style: TextStyle(
                               fontSize: 16,
                               fontWeight: FontWeight.w500,
@@ -65,28 +69,39 @@ class TransactionRow extends StatelessWidget {
                     ),
                     Text(formattedAmount,
                         style: TextStyle(
-                            fontSize: 16,
-                            fontWeight: FontWeight.w500,
-                            color: Theme.of(context).extension<DashboardPageTheme>()!.textColor))
-                  ]),
+                          fontSize: 16,
+                          fontWeight: FontWeight.w500,
+                          color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
+                        ),
+                      )
+                    ],
+                  ),
                   SizedBox(height: 5),
-                  Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[
-                    Text(formattedDate,
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: <Widget>[
+                      Text(formattedDate,
+                          style: TextStyle(
+                              fontSize: 14,
+                              color: Theme.of(context)
+                                  .extension<CakeTextTheme>()!
+                                  .dateSectionRowColor)),
+                      Text(
+                        formattedFiatAmount,
                         style: TextStyle(
-                            fontSize: 14,
-                            color:
-                                Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)),
-                    Text(formattedFiatAmount,
-                        style: TextStyle(
-                            fontSize: 14,
-                            color:
-                                Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
-                  ])
+                          fontSize: 14,
+                          color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor,
+                        ),
+                      )
+                    ],
+                  ),
                 ],
-              ))
-            ],
-          ),
-        ));
+              ),
+            )
+          ],
+        ),
+      ),
+    );
   }
 }
 
diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart
index 929e3027a..387904df0 100644
--- a/lib/src/screens/new_wallet/new_wallet_page.dart
+++ b/lib/src/screens/new_wallet/new_wallet_page.dart
@@ -112,10 +112,13 @@ class _WalletNameFormState extends State<WalletNameForm> {
                 context: context,
                 builder: (_) {
                   return AlertWithOneAction(
-                      alertTitle: S.current.new_wallet,
-                      alertContent: state.error,
-                      buttonText: S.of(context).ok,
-                      buttonAction: () => Navigator.of(context).pop());
+                    key: ValueKey('new_wallet_page_failure_dialog_key'),
+                    buttonKey: ValueKey('new_wallet_page_failure_dialog_button_key'),
+                    alertTitle: S.current.new_wallet,
+                    alertContent: state.error,
+                    buttonText: S.of(context).ok,
+                    buttonAction: () => Navigator.of(context).pop(),
+                  );
                 });
           }
         });
@@ -152,6 +155,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
                       child: Column(
                         children: [
                           TextFormField(
+                            key: ValueKey('new_wallet_page_wallet_name_textformfield_key'),
                             onChanged: (value) => _walletNewVM.name = value,
                             controller: _nameController,
                             textAlign: TextAlign.center,
@@ -182,6 +186,8 @@ class _WalletNameFormState extends State<WalletNameForm> {
                               suffixIcon: Semantics(
                                 label: S.of(context).generate_name,
                                 child: IconButton(
+                                  key: ValueKey(
+                                      'new_wallet_page_wallet_name_textformfield_generate_name_button_key'),
                                   onPressed: () async {
                                     final rName = await generateName();
                                     FocusManager.instance.primaryFocus?.unfocus();
@@ -297,6 +303,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
                         builder: (BuildContext build) => Padding(
                           padding: EdgeInsets.only(top: 24),
                           child: SelectButton(
+                            key: ValueKey('new_wallet_page_monero_seed_type_button_key'),
                             text: widget._seedSettingsViewModel.moneroSeedType.title,
                             onTap: () async {
                               await showPopUp<void>(
@@ -318,6 +325,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
                         padding: EdgeInsets.only(top: 10),
                         child: SeedLanguageSelector(
                           key: _languageSelectorKey,
+                          buttonKey: ValueKey('new_wallet_page_seed_language_selector_button_key'),
                           initialSelected: defaultSeedLanguage,
                           seedType: _walletNewVM.hasSeedType
                               ? widget._seedSettingsViewModel.moneroSeedType
@@ -336,6 +344,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
               Observer(
                 builder: (context) {
                   return LoadingPrimaryButton(
+                    key: ValueKey('new_wallet_page_confirm_button_key'),
                     onPressed: _confirmForm,
                     text: S.of(context).seed_language_next,
                     color: Colors.green,
@@ -347,6 +356,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
               ),
               const SizedBox(height: 25),
               GestureDetector(
+                key: ValueKey('new_wallet_page_advanced_settings_button_key'),
                 onTap: () {
                   Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, arguments: {
                     "type": _walletNewVM.type,
diff --git a/lib/src/screens/new_wallet/wallet_group_description_page.dart b/lib/src/screens/new_wallet/wallet_group_description_page.dart
index d0936b640..e892e0d49 100644
--- a/lib/src/screens/new_wallet/wallet_group_description_page.dart
+++ b/lib/src/screens/new_wallet/wallet_group_description_page.dart
@@ -66,6 +66,7 @@ class WalletGroupDescriptionPage extends BasePage {
             ),
           ),
           PrimaryButton(
+            key: ValueKey('wallet_group_description_page_create_new_seed_button_key'),
             onPressed: () => Navigator.of(context).pushNamed(
               Routes.newWallet,
               arguments: NewWalletArguments(type: selectedWalletType),
@@ -76,6 +77,7 @@ class WalletGroupDescriptionPage extends BasePage {
           ),
           SizedBox(height: 12),
           PrimaryButton(
+            key: ValueKey('wallet_group_description_page_choose_wallet_group_button_key'),
             onPressed: () => Navigator.of(context).pushNamed(
               Routes.walletGroupsDisplayPage,
               arguments: selectedWalletType,
diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart
index 57f5ec727..299846a72 100644
--- a/lib/src/screens/restore/restore_options_page.dart
+++ b/lib/src/screens/restore/restore_options_page.dart
@@ -56,7 +56,8 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
     }
 
     if (isMoneroOnly) {
-      return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS).isNotEmpty;
+      return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS)
+          .isNotEmpty;
     }
 
     return true;
@@ -80,13 +81,12 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
             child: Column(
               children: <Widget>[
                 OptionTile(
-                  key: ValueKey('restore_options_from_seeds_button_key'),
-                  onPressed: () =>
-                      Navigator.pushNamed(
-                        context,
-                        Routes.restoreWalletFromSeedKeys,
-                        arguments: widget.isNewInstall,
-                      ),
+                  key: ValueKey('restore_options_from_seeds_or_keys_button_key'),
+                  onPressed: () => Navigator.pushNamed(
+                    context,
+                    Routes.restoreWalletFromSeedKeys,
+                    arguments: widget.isNewInstall,
+                  ),
                   image: imageSeedKeys,
                   title: S.of(context).restore_title_from_seed_keys,
                   description: S.of(context).restore_description_from_seed_keys,
@@ -107,7 +107,8 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
                     padding: EdgeInsets.only(top: 24),
                     child: OptionTile(
                       key: ValueKey('restore_options_from_hardware_wallet_button_key'),
-                      onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromHardwareWallet,
+                      onPressed: () => Navigator.pushNamed(
+                          context, Routes.restoreWalletFromHardwareWallet,
                           arguments: widget.isNewInstall),
                       image: imageLedger,
                       title: S.of(context).restore_title_from_hardware_wallet,
@@ -120,9 +121,9 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
                       key: ValueKey('restore_options_from_qr_button_key'),
                       onPressed: () => _onScanQRCode(context),
                       icon: Icon(
-                          Icons.qr_code_rounded,
-                          color: imageColor,
-                          size: 50,
+                        Icons.qr_code_rounded,
+                        color: imageColor,
+                        size: 50,
                       ),
                       title: S.of(context).scan_qr_code,
                       description: S.of(context).cold_or_recover_wallet),
@@ -149,20 +150,20 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
                 buttonAction: () => Navigator.of(context).pop());
           });
     });
-
   }
 
   Future<void> _onScanQRCode(BuildContext context) async {
-    final isCameraPermissionGranted = await PermissionHandler.checkPermission(Permission.camera, context);
+    final isCameraPermissionGranted =
+        await PermissionHandler.checkPermission(Permission.camera, context);
 
     if (!isCameraPermissionGranted) return;
     bool isPinSet = false;
     if (widget.isNewInstall) {
       await Navigator.pushNamed(context, Routes.setupPin,
           arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
-            setupPinContext.close();
-            isPinSet = true;
-          });
+        setupPinContext.close();
+        isPinSet = true;
+      });
     }
     if (!widget.isNewInstall || isPinSet) {
       try {
@@ -174,7 +175,8 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
         });
         final restoreWallet = await WalletRestoreFromQRCode.scanQRCodeForRestoring(context);
 
-        final restoreFromQRViewModel = getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type);
+        final restoreFromQRViewModel =
+            getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type);
 
         await restoreFromQRViewModel.create(restoreWallet: restoreWallet);
         if (restoreFromQRViewModel.state is FailureState) {
diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart
index c8a75cf40..1684f6f92 100644
--- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart
+++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart
@@ -191,6 +191,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
           ),
           if (widget.type == WalletType.monero || widget.type == WalletType.wownero)
             GestureDetector(
+              key: ValueKey('wallet_restore_from_seed_seedtype_picker_button_key'),
               onTap: () async {
                 await showPopUp<void>(
                     context: context,
@@ -264,6 +265,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
             BlockchainHeightWidget(
               focusNode: widget.blockHeightFocusNode,
               key: blockchainHeightKey,
+              blockHeightTextFieldKey: ValueKey('wallet_restore_from_seed_blockheight_textfield_key'),
               onHeightOrDateEntered: widget.onHeightOrDateEntered,
               hasDatePicker: widget.type == WalletType.monero || widget.type == WalletType.wownero,
               walletType: widget.type,
diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart
index 730dfa5f8..23de4564f 100644
--- a/lib/src/screens/seed/pre_seed_page.dart
+++ b/lib/src/screens/seed/pre_seed_page.dart
@@ -15,13 +15,15 @@ class PreSeedPage extends InfoPage {
   String get pageTitle => S.current.pre_seed_title;
 
   @override
-  String get pageDescription =>
-      S.current.pre_seed_description(seedPhraseLength.toString());
+  String get pageDescription => S.current.pre_seed_description(seedPhraseLength.toString());
 
   @override
   String get buttonText => S.current.pre_seed_button_text;
 
   @override
-  void Function(BuildContext) get onPressed => (BuildContext context) =>
-      Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true);
+  Key? get buttonKey => ValueKey('pre_seed_page_button_key');
+
+  @override
+  void Function(BuildContext) get onPressed =>
+      (BuildContext context) => Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true);
 }
diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart
index 200b87b7d..10160839c 100644
--- a/lib/src/screens/seed/wallet_seed_page.dart
+++ b/lib/src/screens/seed/wallet_seed_page.dart
@@ -33,16 +33,22 @@ class WalletSeedPage extends BasePage {
   void onClose(BuildContext context) async {
     if (isNewWalletCreated) {
       final confirmed = await showPopUp<bool>(
-              context: context,
-              builder: (BuildContext context) {
-                return AlertWithTwoActions(
-                    alertTitle: S.of(context).seed_alert_title,
-                    alertContent: S.of(context).seed_alert_content,
-                    leftButtonText: S.of(context).seed_alert_back,
-                    rightButtonText: S.of(context).seed_alert_yes,
-                    actionLeftButton: () => Navigator.of(context).pop(false),
-                    actionRightButton: () => Navigator.of(context).pop(true));
-              }) ??
+            context: context,
+            builder: (BuildContext context) {
+              return AlertWithTwoActions(
+                alertDialogKey: ValueKey('wallet_seed_page_seed_alert_dialog_key'),
+                alertRightActionButtonKey:
+                    ValueKey('wallet_seed_page_seed_alert_confirm_button_key'),
+                alertLeftActionButtonKey: ValueKey('wallet_seed_page_seed_alert_back_button_key'),
+                alertTitle: S.of(context).seed_alert_title,
+                alertContent: S.of(context).seed_alert_content,
+                leftButtonText: S.of(context).seed_alert_back,
+                rightButtonText: S.of(context).seed_alert_yes,
+                actionLeftButton: () => Navigator.of(context).pop(false),
+                actionRightButton: () => Navigator.of(context).pop(true),
+              );
+            },
+          ) ??
           false;
 
       if (confirmed) {
@@ -62,6 +68,7 @@ class WalletSeedPage extends BasePage {
   Widget trailing(BuildContext context) {
     return isNewWalletCreated
         ? GestureDetector(
+            key: ValueKey('wallet_seed_page_next_button_key'),
             onTap: () => onClose(context),
             child: Container(
               width: 100,
@@ -74,9 +81,9 @@ class WalletSeedPage extends BasePage {
               child: Text(
                 S.of(context).seed_language_next,
                 style: TextStyle(
-                    fontSize: 14, fontWeight: FontWeight.w600, color: Theme.of(context)
-                        .extension<CakeTextTheme>()!
-                        .buttonTextColor),
+                    fontSize: 14,
+                    fontWeight: FontWeight.w600,
+                    color: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor),
               ),
             ),
           )
@@ -93,7 +100,8 @@ class WalletSeedPage extends BasePage {
           padding: EdgeInsets.all(24),
           alignment: Alignment.center,
           child: ConstrainedBox(
-            constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
+            constraints:
+                BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
             child: Column(
               mainAxisAlignment: MainAxisAlignment.spaceBetween,
               children: <Widget>[
@@ -106,6 +114,7 @@ class WalletSeedPage extends BasePage {
                     crossAxisAlignment: CrossAxisAlignment.center,
                     children: <Widget>[
                       Text(
+                        key: ValueKey('wallet_seed_page_wallet_name_text_key'),
                         walletSeedViewModel.name,
                         style: TextStyle(
                             fontSize: 20,
@@ -115,12 +124,14 @@ class WalletSeedPage extends BasePage {
                       Padding(
                         padding: EdgeInsets.only(top: 20, left: 16, right: 16),
                         child: Text(
+                          key: ValueKey('wallet_seed_page_wallet_seed_text_key'),
                           walletSeedViewModel.seed,
                           textAlign: TextAlign.center,
                           style: TextStyle(
                               fontSize: 14,
                               fontWeight: FontWeight.normal,
-                              color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor),
+                              color:
+                                  Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor),
                         ),
                       )
                     ],
@@ -132,12 +143,18 @@ class WalletSeedPage extends BasePage {
                         ? Padding(
                             padding: EdgeInsets.only(bottom: 43, left: 43, right: 43),
                             child: Text(
+                              key: ValueKey(
+                                'wallet_seed_page_wallet_seed_reminder_text_key',
+                              ),
                               S.of(context).seed_reminder,
                               textAlign: TextAlign.center,
                               style: TextStyle(
-                                  fontSize: 12,
-                                  fontWeight: FontWeight.normal,
-                                  color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
+                                fontSize: 12,
+                                fontWeight: FontWeight.normal,
+                                color: Theme.of(context)
+                                    .extension<TransactionTradeTheme>()!
+                                    .detailsTitlesColor,
+                              ),
                             ),
                           )
                         : Offstage(),
@@ -145,9 +162,10 @@ class WalletSeedPage extends BasePage {
                       mainAxisSize: MainAxisSize.max,
                       children: <Widget>[
                         Flexible(
-                            child: Container(
-                          padding: EdgeInsets.only(right: 8.0),
-                          child: PrimaryButton(
+                          child: Container(
+                            padding: EdgeInsets.only(right: 8.0),
+                            child: PrimaryButton(
+                              key: ValueKey('wallet_seed_page_save_seeds_button_key'),
                               onPressed: () {
                                 ShareUtil.share(
                                   text: walletSeedViewModel.seed,
@@ -156,22 +174,29 @@ class WalletSeedPage extends BasePage {
                               },
                               text: S.of(context).save,
                               color: Colors.green,
-                              textColor: Colors.white),
-                        )),
+                              textColor: Colors.white,
+                            ),
+                          ),
+                        ),
                         Flexible(
-                            child: Container(
-                          padding: EdgeInsets.only(left: 8.0),
-                          child: Builder(
+                          child: Container(
+                            padding: EdgeInsets.only(left: 8.0),
+                            child: Builder(
                               builder: (context) => PrimaryButton(
-                                  onPressed: () {
-                                    ClipboardUtil.setSensitiveDataToClipboard(
-                                        ClipboardData(text: walletSeedViewModel.seed));
-                                    showBar<void>(context, S.of(context).copied_to_clipboard);
-                                  },
-                                  text: S.of(context).copy,
-                                  color: Theme.of(context).extension<PinCodeTheme>()!.indicatorsColor,
-                                  textColor: Colors.white)),
-                        ))
+                                key: ValueKey('wallet_seed_page_copy_seeds_button_key'),
+                                onPressed: () {
+                                  ClipboardUtil.setSensitiveDataToClipboard(
+                                    ClipboardData(text: walletSeedViewModel.seed),
+                                  );
+                                  showBar<void>(context, S.of(context).copied_to_clipboard);
+                                },
+                                text: S.of(context).copy,
+                                color: Theme.of(context).extension<PinCodeTheme>()!.indicatorsColor,
+                                textColor: Colors.white,
+                              ),
+                            ),
+                          ),
+                        )
                       ],
                     )
                   ],
diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart
index 04ae53d77..bb1c00ff5 100644
--- a/lib/src/screens/settings/security_backup_page.dart
+++ b/lib/src/screens/settings/security_backup_page.dart
@@ -16,7 +16,8 @@ import 'package:flutter/material.dart';
 import 'package:flutter_mobx/flutter_mobx.dart';
 
 class SecurityBackupPage extends BasePage {
-  SecurityBackupPage(this._securitySettingsViewModel, this._authService, [this._isHardwareWallet = false]);
+  SecurityBackupPage(this._securitySettingsViewModel, this._authService,
+      [this._isHardwareWallet = false]);
 
   final AuthService _authService;
 
@@ -30,10 +31,13 @@ class SecurityBackupPage extends BasePage {
   @override
   Widget body(BuildContext context) {
     return Container(
-        padding: EdgeInsets.only(top: 10),
-        child: Column(mainAxisSize: MainAxisSize.min, children: [
+      padding: EdgeInsets.only(top: 10),
+      child: Column(
+        mainAxisSize: MainAxisSize.min,
+        children: [
           if (!_isHardwareWallet)
             SettingsCellWithArrow(
+              key: ValueKey('security_backup_page_show_keys_button_key'),
               title: S.current.show_keys,
               handler: (_) => _authService.authenticateAction(
                 context,
@@ -44,15 +48,17 @@ class SecurityBackupPage extends BasePage {
             ),
           if (!SettingsStoreBase.walletPasswordDirectInput)
             SettingsCellWithArrow(
+              key: ValueKey('security_backup_page_create_backup_button_key'),
               title: S.current.create_backup,
               handler: (_) => _authService.authenticateAction(
                 context,
                 route: Routes.backup,
-                conditionToDetermineIfToUse2FA: _securitySettingsViewModel
-                    .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
+                conditionToDetermineIfToUse2FA:
+                    _securitySettingsViewModel.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
               ),
             ),
           SettingsCellWithArrow(
+            key: ValueKey('security_backup_page_change_pin_button_key'),
             title: S.current.settings_change_pin,
             handler: (_) => _authService.authenticateAction(
               context,
@@ -60,28 +66,30 @@ class SecurityBackupPage extends BasePage {
               arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
                 setupPinContext.close();
               },
-              conditionToDetermineIfToUse2FA: _securitySettingsViewModel
-                  .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
+              conditionToDetermineIfToUse2FA:
+                  _securitySettingsViewModel.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
             ),
           ),
           if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux)
             Observer(builder: (_) {
               return SettingsSwitcherCell(
+                  key: ValueKey('security_backup_page_allow_biometrics_button_key'),
                   title: S.current.settings_allow_biometrical_authentication,
                   value: _securitySettingsViewModel.allowBiometricalAuthentication,
                   onValueChange: (BuildContext context, bool value) {
                     if (value) {
-                      _authService.authenticateAction(context,
-                          onAuthSuccess: (isAuthenticatedSuccessfully) async {
-                        if (isAuthenticatedSuccessfully) {
-                          if (await _securitySettingsViewModel.biometricAuthenticated()) {
+                      _authService.authenticateAction(
+                        context,
+                        onAuthSuccess: (isAuthenticatedSuccessfully) async {
+                          if (isAuthenticatedSuccessfully) {
+                            if (await _securitySettingsViewModel.biometricAuthenticated()) {
+                              _securitySettingsViewModel
+                                  .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully);
+                            }
+                          } else {
                             _securitySettingsViewModel
                                 .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully);
                           }
-                        } else {
-                          _securitySettingsViewModel
-                              .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully);
-                        }
                         },
                         conditionToDetermineIfToUse2FA: _securitySettingsViewModel
                             .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
@@ -93,6 +101,7 @@ class SecurityBackupPage extends BasePage {
             }),
           Observer(builder: (_) {
             return SettingsPickerCell<PinCodeRequiredDuration>(
+              key: ValueKey('security_backup_page_require_pin_after_button_key'),
               title: S.current.require_pin_after,
               items: PinCodeRequiredDuration.values,
               selectedItem: _securitySettingsViewModel.pinCodeRequiredDuration,
@@ -104,14 +113,15 @@ class SecurityBackupPage extends BasePage {
           Observer(
             builder: (context) {
               return SettingsCellWithArrow(
+                key: ValueKey('security_backup_page_totp_2fa_button_key'),
                 title: _securitySettingsViewModel.useTotp2FA
                     ? S.current.modify_2fa
                     : S.current.setup_2fa,
-            handler: (_) => _authService.authenticateAction(
-              context,
-              route: _securitySettingsViewModel.useTotp2FA
-                  ? Routes.modify2FAPage
-                  : Routes.setup2faInfoPage,
+                handler: (_) => _authService.authenticateAction(
+                  context,
+                  route: _securitySettingsViewModel.useTotp2FA
+                      ? Routes.modify2FAPage
+                      : Routes.setup2faInfoPage,
                   conditionToDetermineIfToUse2FA: _securitySettingsViewModel
                       .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
                 ),
diff --git a/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart b/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart
index f0e19a715..cb4f9dc78 100644
--- a/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart
+++ b/lib/src/screens/settings/widgets/settings_cell_with_arrow.dart
@@ -3,8 +3,11 @@ import 'package:cake_wallet/src/widgets/standard_list.dart';
 import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
 
 class SettingsCellWithArrow extends StandardListRow {
-  SettingsCellWithArrow({required String title, required Function(BuildContext context)? handler})
-      : super(title: title, isSelected: false, onTap: handler);
+  SettingsCellWithArrow({
+    required String title,
+    required Function(BuildContext context)? handler,
+    Key? key,
+  }) : super(title: title, isSelected: false, onTap: handler, key: key);
 
   @override
   Widget buildTrailing(BuildContext context) => Image.asset('assets/images/select_arrow.png',
diff --git a/lib/src/screens/settings/widgets/settings_picker_cell.dart b/lib/src/screens/settings/widgets/settings_picker_cell.dart
index 8e0492330..765ac2991 100644
--- a/lib/src/screens/settings/widgets/settings_picker_cell.dart
+++ b/lib/src/screens/settings/widgets/settings_picker_cell.dart
@@ -5,19 +5,21 @@ import 'package:cake_wallet/src/widgets/picker.dart';
 import 'package:cake_wallet/src/widgets/standard_list.dart';
 
 class SettingsPickerCell<ItemType> extends StandardListRow {
-  SettingsPickerCell(
-      {required String title,
-      required this.selectedItem,
-      required this.items,
-      this.displayItem,
-      this.images,
-      this.searchHintText,
-      this.isGridView = false,
-      this.matchingCriteria,
-      this.onItemSelected})
-      : super(
+  SettingsPickerCell({
+    required String title,
+    required this.selectedItem,
+    required this.items,
+    this.displayItem,
+    this.images,
+    this.searchHintText,
+    this.isGridView = false,
+    this.matchingCriteria,
+    this.onItemSelected,
+    Key? key,
+  }) : super(
           title: title,
           isSelected: false,
+          key: key,
           onTap: (BuildContext context) async {
             final selectedAtIndex = items.indexOf(selectedItem);
 
diff --git a/lib/src/screens/settings/widgets/settings_switcher_cell.dart b/lib/src/screens/settings/widgets/settings_switcher_cell.dart
index 0e5c04524..6a3c8b4a0 100644
--- a/lib/src/screens/settings/widgets/settings_switcher_cell.dart
+++ b/lib/src/screens/settings/widgets/settings_switcher_cell.dart
@@ -10,7 +10,8 @@ class SettingsSwitcherCell extends StandardListRow {
     Decoration? decoration,
     this.leading,
     void Function(BuildContext context)? onTap,
-  }) : super(title: title, isSelected: false, decoration: decoration, onTap: onTap);
+    Key? key,
+  }) : super(title: title, isSelected: false, decoration: decoration, onTap: onTap, key: key);
 
   final bool value;
   final void Function(BuildContext context, bool value)? onValueChange;
diff --git a/lib/src/screens/setup_2fa/setup_2fa_info_page.dart b/lib/src/screens/setup_2fa/setup_2fa_info_page.dart
index ff6187665..8aa0ac3c9 100644
--- a/lib/src/screens/setup_2fa/setup_2fa_info_page.dart
+++ b/lib/src/screens/setup_2fa/setup_2fa_info_page.dart
@@ -4,7 +4,6 @@ import 'package:cake_wallet/src/screens/InfoPage.dart';
 import 'package:flutter/cupertino.dart';
 
 class Setup2FAInfoPage extends InfoPage {
-
   @override
   String get pageTitle => S.current.pre_seed_title;
 
@@ -15,6 +14,9 @@ class Setup2FAInfoPage extends InfoPage {
   String get buttonText => S.current.understand;
 
   @override
-  void Function(BuildContext) get onPressed => (BuildContext context) =>
-      Navigator.of(context).popAndPushNamed(Routes.setup_2faPage);
+  Key? get buttonKey => ValueKey('setup_2fa_info_page_button_key');
+
+  @override
+  void Function(BuildContext) get onPressed =>
+      (BuildContext context) => Navigator.of(context).popAndPushNamed(Routes.setup_2faPage);
 }
diff --git a/lib/src/screens/transaction_details/blockexplorer_list_item.dart b/lib/src/screens/transaction_details/blockexplorer_list_item.dart
index d5a70daa7..0126a147a 100644
--- a/lib/src/screens/transaction_details/blockexplorer_list_item.dart
+++ b/lib/src/screens/transaction_details/blockexplorer_list_item.dart
@@ -1,7 +1,12 @@
 import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
+import 'package:flutter/foundation.dart';
 
 class BlockExplorerListItem extends TransactionDetailsListItem {
-  BlockExplorerListItem({required String title, required String value, required this.onTap})
-      : super(title: title, value: value);
+  BlockExplorerListItem({
+    required String title,
+    required String value,
+    required this.onTap,
+    Key? key,
+  }) : super(title: title, value: value, key: key);
   final Function() onTap;
 }
diff --git a/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart b/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart
index db3d94500..96ddc94cd 100644
--- a/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart
+++ b/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart
@@ -1,18 +1,20 @@
 import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
+import 'package:flutter/widgets.dart';
 
 class StandardPickerListItem<T> extends TransactionDetailsListItem {
-  StandardPickerListItem(
-      {required String title,
-      required String value,
-      required this.items,
-      required this.displayItem,
-      required this.onSliderChanged,
-      required this.onItemSelected,
-      required this.selectedIdx,
-      required this.customItemIndex,
-      this.maxValue,
-      required this.customValue})
-      : super(title: title, value: value);
+  StandardPickerListItem({
+    required String title,
+    required String value,
+    required this.items,
+    required this.displayItem,
+    required this.onSliderChanged,
+    required this.onItemSelected,
+    required this.selectedIdx,
+    required this.customItemIndex,
+    this.maxValue,
+    required this.customValue,
+    Key? key,
+  }) : super(title: title, value: value, key: key);
 
   final List<T> items;
   final String Function(T item, double sliderValue) displayItem;
diff --git a/lib/src/screens/transaction_details/standart_list_item.dart b/lib/src/screens/transaction_details/standart_list_item.dart
index 705daf970..673eabe42 100644
--- a/lib/src/screens/transaction_details/standart_list_item.dart
+++ b/lib/src/screens/transaction_details/standart_list_item.dart
@@ -1,6 +1,9 @@
 import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
 
 class StandartListItem extends TransactionDetailsListItem {
-  StandartListItem({required String title, required String value})
-      : super(title: title, value: value);
+  StandartListItem({
+    required String super.title,
+    required String super.value,
+    super.key,
+  });
 }
diff --git a/lib/src/screens/transaction_details/textfield_list_item.dart b/lib/src/screens/transaction_details/textfield_list_item.dart
index 49ef2705e..846f9acd5 100644
--- a/lib/src/screens/transaction_details/textfield_list_item.dart
+++ b/lib/src/screens/transaction_details/textfield_list_item.dart
@@ -1,11 +1,17 @@
 import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
+import 'package:flutter/foundation.dart';
 
 class TextFieldListItem extends TransactionDetailsListItem {
   TextFieldListItem({
     required String title,
     required String value,
-    required this.onSubmitted})
-      : super(title: title, value: value);
+    required this.onSubmitted,
+    Key? key,
+  }) : super(
+          title: title,
+          value: value,
+          key: key,
+        );
 
   final Function(String value) onSubmitted;
 }
\ No newline at end of file
diff --git a/lib/src/screens/transaction_details/transaction_details_list_item.dart b/lib/src/screens/transaction_details/transaction_details_list_item.dart
index 8a8449350..446383d72 100644
--- a/lib/src/screens/transaction_details/transaction_details_list_item.dart
+++ b/lib/src/screens/transaction_details/transaction_details_list_item.dart
@@ -1,6 +1,9 @@
+import 'package:flutter/foundation.dart';
+
 abstract class TransactionDetailsListItem {
-  TransactionDetailsListItem({required this.title, required this.value});
+  TransactionDetailsListItem({required this.title, required this.value, this.key});
 
   final String title;
   final String value;
-}
\ No newline at end of file
+  final Key? key;
+}
diff --git a/lib/src/screens/transaction_details/transaction_details_page.dart b/lib/src/screens/transaction_details/transaction_details_page.dart
index 1b088fc31..9484bf4da 100644
--- a/lib/src/screens/transaction_details/transaction_details_page.dart
+++ b/lib/src/screens/transaction_details/transaction_details_page.dart
@@ -33,38 +33,42 @@ class TransactionDetailsPage extends BasePage {
       children: [
         Expanded(
           child: SectionStandardList(
-              sectionCount: 1,
-              itemCounter: (int _) => transactionDetailsViewModel.items.length,
-              itemBuilder: (__, index) {
-                final item = transactionDetailsViewModel.items[index];
+            sectionCount: 1,
+            itemCounter: (int _) => transactionDetailsViewModel.items.length,
+            itemBuilder: (__, index) {
+              final item = transactionDetailsViewModel.items[index];
 
-                if (item is StandartListItem) {
-                  return GestureDetector(
-                    onTap: () {
-                      Clipboard.setData(ClipboardData(text: item.value));
-                      showBar<void>(context, S.of(context).transaction_details_copied(item.title));
-                    },
-                    child: ListRow(title: '${item.title}:', value: item.value),
-                  );
-                }
+              if (item is StandartListItem) {
+                return GestureDetector(
+                  key: item.key,
+                  onTap: () {
+                    Clipboard.setData(ClipboardData(text: item.value));
+                    showBar<void>(context, S.of(context).transaction_details_copied(item.title));
+                  },
+                  child: ListRow(title: '${item.title}:', value: item.value),
+                );
+              }
 
-                if (item is BlockExplorerListItem) {
-                  return GestureDetector(
-                    onTap: item.onTap,
-                    child: ListRow(title: '${item.title}:', value: item.value),
-                  );
-                }
+              if (item is BlockExplorerListItem) {
+                return GestureDetector(
+                  key: item.key,
+                  onTap: item.onTap,
+                  child: ListRow(title: '${item.title}:', value: item.value),
+                );
+              }
 
-                if (item is TextFieldListItem) {
-                  return TextFieldListRow(
-                    title: item.title,
-                    value: item.value,
-                    onSubmitted: item.onSubmitted,
-                  );
-                }
+              if (item is TextFieldListItem) {
+                return TextFieldListRow(
+                  key: item.key,
+                  title: item.title,
+                  value: item.value,
+                  onSubmitted: item.onSubmitted,
+                );
+              }
 
-                return Container();
-              }),
+              return Container();
+            },
+          ),
         ),
         Observer(
           builder: (_) {
diff --git a/lib/src/screens/transaction_details/transaction_expandable_list_item.dart b/lib/src/screens/transaction_details/transaction_expandable_list_item.dart
index e87405de3..db6cf22ae 100644
--- a/lib/src/screens/transaction_details/transaction_expandable_list_item.dart
+++ b/lib/src/screens/transaction_details/transaction_expandable_list_item.dart
@@ -1,7 +1,12 @@
 import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
+import 'package:flutter/foundation.dart';
 
 class StandardExpandableListItem<T> extends TransactionDetailsListItem {
-  StandardExpandableListItem({required String title, required this.expandableItems})
-      : super(title: title, value: '');
+  StandardExpandableListItem({
+    required String title,
+    required this.expandableItems,
+    Key? key,
+  }) : super(title: title, value: '', key: key);
+  
   final List<T> expandableItems;
 }
diff --git a/lib/src/screens/transaction_details/widgets/textfield_list_row.dart b/lib/src/screens/transaction_details/widgets/textfield_list_row.dart
index a86645ecb..24016a293 100644
--- a/lib/src/screens/transaction_details/widgets/textfield_list_row.dart
+++ b/lib/src/screens/transaction_details/widgets/textfield_list_row.dart
@@ -4,12 +4,14 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
 import 'package:flutter/material.dart';
 
 class TextFieldListRow extends StatefulWidget {
-  TextFieldListRow(
-      {required this.title,
-      required this.value,
-      this.titleFontSize = 14,
-      this.valueFontSize = 16,
-      this.onSubmitted});
+  TextFieldListRow({
+    required this.title,
+    required this.value,
+    this.titleFontSize = 14,
+    this.valueFontSize = 16,
+    this.onSubmitted,
+    super.key,
+  });
 
   final String title;
   final String value;
diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart
index 5117f152f..fac760516 100644
--- a/lib/src/screens/wallet_keys/wallet_keys_page.dart
+++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart
@@ -25,23 +25,25 @@ class WalletKeysPage extends BasePage {
 
   @override
   Widget trailing(BuildContext context) => IconButton(
-      onPressed: () async {
-        final url = await walletKeysViewModel.url;
+        key: ValueKey('wallet_keys_page_fullscreen_qr_button_key'),
+        onPressed: () async {
+          final url = await walletKeysViewModel.url;
 
-        BrightnessUtil.changeBrightnessForFunction(() async {
-          await Navigator.pushNamed(
-            context,
-            Routes.fullscreenQR,
-            arguments: QrViewData(data: url.toString(), version: QrVersions.auto),
-          );
-        });
-      },
-      splashColor: Colors.transparent,
-      highlightColor: Colors.transparent,
-      hoverColor: Colors.transparent,
-      icon: Image.asset(
-        'assets/images/qr_code_icon.png',
-      ));
+          BrightnessUtil.changeBrightnessForFunction(() async {
+            await Navigator.pushNamed(
+              context,
+              Routes.fullscreenQR,
+              arguments: QrViewData(data: url.toString(), version: QrVersions.auto),
+            );
+          });
+        },
+        splashColor: Colors.transparent,
+        highlightColor: Colors.transparent,
+        hoverColor: Colors.transparent,
+        icon: Image.asset(
+          'assets/images/qr_code_icon.png',
+        ),
+      );
 
   @override
   Widget body(BuildContext context) {
@@ -60,6 +62,7 @@ class WalletKeysPage extends BasePage {
                 child: Padding(
                   padding: const EdgeInsets.all(8.0),
                   child: AutoSizeText(
+                    key: ValueKey('wallet_keys_page_share_warning_text_key'),
                     S.of(context).do_not_share_warning_text.toUpperCase(),
                     textAlign: TextAlign.center,
                     maxLines: 4,
@@ -92,6 +95,7 @@ class WalletKeysPage extends BasePage {
                     final item = walletKeysViewModel.items[index];
 
                     return GestureDetector(
+                      key: item.key,
                       onTap: () {
                         ClipboardUtil.setSensitiveDataToClipboard(ClipboardData(text: item.value));
                         showBar<void>(context, S.of(context).copied_key_to_clipboard(item.title));
diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart
index afb86cf0a..a9a9d9413 100644
--- a/lib/src/screens/wallet_list/wallet_list_page.dart
+++ b/lib/src/screens/wallet_list/wallet_list_page.dart
@@ -318,6 +318,7 @@ class WalletListBodyState extends State<WalletListBody> {
             child: Column(
               children: <Widget>[
                 PrimaryImageButton(
+                  key: ValueKey('wallet_list_page_create_new_wallet_button_key'),
                   onPressed: () {
                     //TODO(David): Find a way to optimize this
                     if (isSingleCoin) {
@@ -359,6 +360,7 @@ class WalletListBodyState extends State<WalletListBody> {
                 ),
                 SizedBox(height: 10.0),
                 PrimaryImageButton(
+                  key: ValueKey('wallet_list_page_restore_wallet_button_key'),
                   onPressed: () {
                     if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) {
                       widget.authService.authenticateAction(
diff --git a/lib/src/widgets/blockchain_height_widget.dart b/lib/src/widgets/blockchain_height_widget.dart
index 9d66c1789..1c6b6da02 100644
--- a/lib/src/widgets/blockchain_height_widget.dart
+++ b/lib/src/widgets/blockchain_height_widget.dart
@@ -23,6 +23,7 @@ class BlockchainHeightWidget extends StatefulWidget {
     this.doSingleScan = false,
     this.bitcoinMempoolAPIEnabled,
     required this.walletType,
+    this.blockHeightTextFieldKey,
   }) : super(key: key);
 
   final Function(int)? onHeightChange;
@@ -35,6 +36,7 @@ class BlockchainHeightWidget extends StatefulWidget {
   final Future<bool>? bitcoinMempoolAPIEnabled;
   final Function()? toggleSingleScan;
   final WalletType walletType;
+  final Key? blockHeightTextFieldKey;
 
   @override
   State<StatefulWidget> createState() => BlockchainHeightState();
@@ -81,6 +83,7 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
                   child: Container(
                       padding: EdgeInsets.only(top: 20.0, bottom: 10.0),
                       child: BaseTextFormField(
+                        key: widget.blockHeightTextFieldKey,
                         focusNode: widget.focusNode,
                         controller: restoreHeightController,
                         keyboardType:
diff --git a/lib/src/widgets/dashboard_card_widget.dart b/lib/src/widgets/dashboard_card_widget.dart
index d9b545040..dc223eb02 100644
--- a/lib/src/widgets/dashboard_card_widget.dart
+++ b/lib/src/widgets/dashboard_card_widget.dart
@@ -15,6 +15,7 @@ class DashBoardRoundedCardWidget extends StatelessWidget {
     this.icon,
     this.onClose,
     this.customBorder,
+    super.key,
   });
 
   final VoidCallback onTap;
diff --git a/lib/src/widgets/option_tile.dart b/lib/src/widgets/option_tile.dart
index 31f958f54..c2d8b9506 100644
--- a/lib/src/widgets/option_tile.dart
+++ b/lib/src/widgets/option_tile.dart
@@ -2,14 +2,14 @@ import 'package:cake_wallet/themes/extensions/option_tile_theme.dart';
 import 'package:flutter/material.dart';
 
 class OptionTile extends StatelessWidget {
-  const OptionTile(
-      {required this.onPressed,
-       this.image,
-        this.icon,
-      required this.title,
-      required this.description,
-      super.key})
-  : assert(image!=null || icon!=null);
+  const OptionTile({
+    required this.onPressed,
+    this.image,
+    this.icon,
+    required this.title,
+    required this.description,
+    super.key,
+  }) : assert(image != null || icon != null);
 
   final VoidCallback onPressed;
   final Image? image;
@@ -34,7 +34,7 @@ class OptionTile extends StatelessWidget {
           mainAxisAlignment: MainAxisAlignment.center,
           crossAxisAlignment: CrossAxisAlignment.start,
           children: <Widget>[
-             icon ?? image!,
+            icon ?? image!,
             Expanded(
               child: Padding(
                 padding: EdgeInsets.only(left: 16),
diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart
index 801a79595..ed5c05be6 100644
--- a/lib/src/widgets/picker.dart
+++ b/lib/src/widgets/picker.dart
@@ -2,6 +2,7 @@
 
 import 'dart:math';
 
+import 'package:cake_wallet/entities/seed_type.dart';
 import 'package:cake_wallet/src/widgets/search_bar_widget.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
 import 'package:cw_core/transaction_priority.dart';
@@ -310,6 +311,8 @@ class _PickerState<Item> extends State<Picker<Item>> {
       itemName = item.name;
     } else if (item is TransactionPriority) {
       itemName = item.title;
+    } else if (item is MoneroSeedType) {
+      itemName = item.title;
     } else {
       itemName = '';
     }
diff --git a/lib/src/widgets/seed_language_selector.dart b/lib/src/widgets/seed_language_selector.dart
index 87f3aa573..711bff390 100644
--- a/lib/src/widgets/seed_language_selector.dart
+++ b/lib/src/widgets/seed_language_selector.dart
@@ -6,12 +6,16 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:flutter/material.dart';
 
 class SeedLanguageSelector extends StatefulWidget {
-  SeedLanguageSelector(
-      {Key? key, required this.initialSelected, this.seedType = MoneroSeedType.defaultSeedType})
-      : super(key: key);
+  SeedLanguageSelector({
+    required this.initialSelected,
+    this.seedType = MoneroSeedType.defaultSeedType,
+    this.buttonKey,
+    Key? key,
+  }) : super(key: key);
 
   final String initialSelected;
   final MoneroSeedType seedType;
+  final Key? buttonKey;
 
   @override
   SeedLanguageSelectorState createState() => SeedLanguageSelectorState(selected: initialSelected);
@@ -25,6 +29,7 @@ class SeedLanguageSelectorState extends State<SeedLanguageSelector> {
   @override
   Widget build(BuildContext context) {
     return SelectButton(
+      key: widget.buttonKey,
       image: null,
       text:
           "${seedLanguages.firstWhere((e) => e.name == selected).nameLocalized} (${S.of(context).seed_language})",
diff --git a/lib/src/widgets/setting_actions.dart b/lib/src/widgets/setting_actions.dart
index b9af97f32..048d006cc 100644
--- a/lib/src/widgets/setting_actions.dart
+++ b/lib/src/widgets/setting_actions.dart
@@ -5,9 +5,11 @@ import 'package:flutter/material.dart';
 class SettingActions {
   final String Function(BuildContext) name;
   final String image;
+  final Key key;
   final void Function(BuildContext) onTap;
 
   SettingActions._({
+    required this.key,
     required this.name,
     required this.image,
     required this.onTap,
@@ -39,6 +41,7 @@ class SettingActions {
   ];
 
   static SettingActions silentPaymentsSettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_silent_payment_settings_button_key'),
     name: (context) => S.of(context).silent_payments_settings,
     image: 'assets/images/bitcoin_menu.png',
     onTap: (BuildContext context) {
@@ -48,6 +51,7 @@ class SettingActions {
   );
 
   static SettingActions litecoinMwebSettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_litecoin_mweb_settings_button_key'),
     name: (context) => S.of(context).litecoin_mweb_settings,
     image: 'assets/images/litecoin_menu.png',
     onTap: (BuildContext context) {
@@ -57,6 +61,7 @@ class SettingActions {
   );
 
   static SettingActions connectionSettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_connection_and_sync_settings_button_key'),
     name: (context) => S.of(context).connection_sync,
     image: 'assets/images/nodes_menu.png',
     onTap: (BuildContext context) {
@@ -66,6 +71,7 @@ class SettingActions {
   );
 
   static SettingActions walletSettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_wallet_menu_button_key'),
     name: (context) => S.of(context).wallets,
     image: 'assets/images/wallet_menu.png',
     onTap: (BuildContext context) {
@@ -75,6 +81,7 @@ class SettingActions {
   );
 
   static SettingActions addressBookSettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_address_book_button_key'),
     name: (context) => S.of(context).address_book_menu,
     image: 'assets/images/open_book_menu.png',
     onTap: (BuildContext context) {
@@ -84,6 +91,7 @@ class SettingActions {
   );
 
   static SettingActions securityBackupSettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_security_and_backup_button_key'),
     name: (context) => S.of(context).security_and_backup,
     image: 'assets/images/key_menu.png',
     onTap: (BuildContext context) {
@@ -93,6 +101,7 @@ class SettingActions {
   );
 
   static SettingActions privacySettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_privacy_settings_button_key'),
     name: (context) => S.of(context).privacy,
     image: 'assets/images/privacy_menu.png',
     onTap: (BuildContext context) {
@@ -102,6 +111,7 @@ class SettingActions {
   );
 
   static SettingActions displaySettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_display_settings_button_key'),
     name: (context) => S.of(context).display_settings,
     image: 'assets/images/eye_menu.png',
     onTap: (BuildContext context) {
@@ -111,6 +121,7 @@ class SettingActions {
   );
 
   static SettingActions otherSettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_other_settings_button_key'),
     name: (context) => S.of(context).other_settings,
     image: 'assets/images/settings_menu.png',
     onTap: (BuildContext context) {
@@ -120,6 +131,7 @@ class SettingActions {
   );
 
   static SettingActions supportSettingAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_support_settings_button_key'),
     name: (context) => S.of(context).settings_support,
     image: 'assets/images/question_mark.png',
     onTap: (BuildContext context) {
diff --git a/lib/src/widgets/standard_list.dart b/lib/src/widgets/standard_list.dart
index c1fcae052..0780d64cd 100644
--- a/lib/src/widgets/standard_list.dart
+++ b/lib/src/widgets/standard_list.dart
@@ -4,7 +4,13 @@ import 'package:cake_wallet/src/widgets/standard_list_status_row.dart';
 import 'package:flutter/material.dart';
 
 class StandardListRow extends StatelessWidget {
-  StandardListRow({required this.title, required this.isSelected, this.onTap, this.decoration});
+  StandardListRow({
+    required this.title,
+    required this.isSelected,
+    this.onTap,
+    this.decoration,
+    super.key,
+  });
 
   final String title;
   final bool isSelected;
diff --git a/lib/store/anonpay/anonpay_transactions_store.dart b/lib/store/anonpay/anonpay_transactions_store.dart
index c6f05b993..d0384ca5a 100644
--- a/lib/store/anonpay/anonpay_transactions_store.dart
+++ b/lib/store/anonpay/anonpay_transactions_store.dart
@@ -1,6 +1,7 @@
 import 'dart:async';
 import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
 import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart';
+import 'package:flutter/foundation.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 
@@ -27,7 +28,10 @@ abstract class AnonpayTransactionsStoreBase with Store {
   Future<void> updateTransactionList() async {
     transactions = anonpayInvoiceInfoSource.values
         .map(
-          (transaction) => AnonpayTransactionListItem(transaction: transaction),
+          (transaction) => AnonpayTransactionListItem(
+            transaction: transaction,
+            key: ValueKey('anonpay_invoice_transaction_list_item_${transaction.invoiceId}_key'),
+          ),
         )
         .toList();
   }
diff --git a/lib/store/dashboard/orders_store.dart b/lib/store/dashboard/orders_store.dart
index b5ec658f7..d91ad3512 100644
--- a/lib/store/dashboard/orders_store.dart
+++ b/lib/store/dashboard/orders_store.dart
@@ -1,6 +1,7 @@
 import 'dart:async';
 import 'package:cake_wallet/buy/order.dart';
 import 'package:cake_wallet/view_model/dashboard/order_list_item.dart';
+import 'package:flutter/foundation.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 import 'package:cake_wallet/store/settings_store.dart';
@@ -10,12 +11,10 @@ part 'orders_store.g.dart';
 class OrdersStore = OrdersStoreBase with _$OrdersStore;
 
 abstract class OrdersStoreBase with Store {
-  OrdersStoreBase({required this.ordersSource,
-    required this.settingsStore})
-    : orders = <OrderListItem>[],
-      orderId = '' {
-    _onOrdersChanged =
-        ordersSource.watch().listen((_) async => await updateOrderList());
+  OrdersStoreBase({required this.ordersSource, required this.settingsStore})
+      : orders = <OrderListItem>[],
+        orderId = '' {
+    _onOrdersChanged = ordersSource.watch().listen((_) async => await updateOrderList());
     updateOrderList();
   }
 
@@ -38,8 +37,11 @@ abstract class OrdersStoreBase with Store {
   void setOrder(Order order) => this.order = order;
 
   @action
-  Future updateOrderList() async => orders =
-      ordersSource.values.map((order) => OrderListItem(
-          order: order,
-          settingsStore: settingsStore)).toList();
-}
\ No newline at end of file
+  Future updateOrderList() async => orders = ordersSource.values
+      .map((order) => OrderListItem(
+            order: order,
+            settingsStore: settingsStore,
+            key: ValueKey('order_list_item_${order.id}_key'),
+          ))
+      .toList();
+}
diff --git a/lib/store/dashboard/trades_store.dart b/lib/store/dashboard/trades_store.dart
index 72442b46f..d0a4592e3 100644
--- a/lib/store/dashboard/trades_store.dart
+++ b/lib/store/dashboard/trades_store.dart
@@ -1,6 +1,7 @@
 import 'dart:async';
 import 'package:cake_wallet/exchange/trade.dart';
 import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
+import 'package:flutter/foundation.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 import 'package:cake_wallet/store/settings_store.dart';
@@ -11,9 +12,8 @@ class TradesStore = TradesStoreBase with _$TradesStore;
 
 abstract class TradesStoreBase with Store {
   TradesStoreBase({required this.tradesSource, required this.settingsStore})
-    : trades = <TradeListItem>[] {
-    _onTradesChanged =
-        tradesSource.watch().listen((_) async => await updateTradeList());
+      : trades = <TradeListItem>[] {
+    _onTradesChanged = tradesSource.watch().listen((_) async => await updateTradeList());
     updateTradeList();
   }
 
@@ -31,8 +31,11 @@ abstract class TradesStoreBase with Store {
   void setTrade(Trade trade) => this.trade = trade;
 
   @action
-  Future<void> updateTradeList() async => trades =
-      tradesSource.values.map((trade) => TradeListItem(
-          trade: trade,
-          settingsStore: settingsStore)).toList();
-}
\ No newline at end of file
+  Future<void> updateTradeList() async => trades = tradesSource.values
+      .map((trade) => TradeListItem(
+            trade: trade,
+            settingsStore: settingsStore,
+            key: ValueKey('trade_list_item_${trade.id}_key'),
+          ))
+      .toList();
+}
diff --git a/lib/utils/date_formatter.dart b/lib/utils/date_formatter.dart
index 9cff68614..58e59966a 100644
--- a/lib/utils/date_formatter.dart
+++ b/lib/utils/date_formatter.dart
@@ -1,3 +1,4 @@
+import 'package:cake_wallet/generated/i18n.dart';
 import 'package:intl/intl.dart';
 import 'package:cake_wallet/di.dart';
 import 'package:cake_wallet/store/settings_store.dart';
@@ -5,8 +6,7 @@ import 'package:cake_wallet/store/settings_store.dart';
 class DateFormatter {
   static String currentLocalFormat({bool hasTime = true, bool reverse = false}) {
     final isUSA = getIt.get<SettingsStore>().languageCode.toLowerCase() == 'en';
-    final format =
-        isUSA ? usaStyleFormat(hasTime, reverse) : regularStyleFormat(hasTime, reverse);
+    final format = isUSA ? usaStyleFormat(hasTime, reverse) : regularStyleFormat(hasTime, reverse);
 
     return format;
   }
@@ -20,4 +20,26 @@ class DateFormatter {
 
   static String regularStyleFormat(bool hasTime, bool reverse) =>
       hasTime ? (reverse ? 'HH:mm  dd.MM.yyyy' : 'dd.MM.yyyy, HH:mm') : 'dd.MM.yyyy';
+
+  static String convertDateTimeToReadableString(DateTime date) {
+    final nowDate = DateTime.now();
+    final diffDays = date.difference(nowDate).inDays;
+    final isToday =
+        nowDate.day == date.day && nowDate.month == date.month && nowDate.year == date.year;
+    final dateSectionDateFormat = withCurrentLocal(hasTime: false);
+    var title = "";
+
+    if (isToday) {
+      title = S.current.today;
+    } else if (diffDays == 0) {
+      title = S.current.yesterday;
+    } else if (diffDays > -7 && diffDays < 0) {
+      final dateFormat = DateFormat.EEEE();
+      title = dateFormat.format(date);
+    } else {
+      title = dateSectionDateFormat.format(date);
+    }
+
+    return title;
+  }
 }
diff --git a/lib/utils/image_utill.dart b/lib/utils/image_utill.dart
index ef3775e4c..746fde453 100644
--- a/lib/utils/image_utill.dart
+++ b/lib/utils/image_utill.dart
@@ -11,6 +11,7 @@ class ImageUtil {
     if (isNetworkImage) {
       return isSvg
           ? SvgPicture.network(
+              key: ValueKey(imagePath),
               imagePath,
               height: _height,
               width: _width,
@@ -23,6 +24,7 @@ class ImageUtil {
               ),
             )
           : Image.network(
+              key: ValueKey(imagePath),
               imagePath,
               height: _height,
               width: _width,
@@ -58,12 +60,14 @@ class ImageUtil {
               height: _height,
               width: _width,
               placeholderBuilder: (_) => Icon(Icons.error),
+              key: ValueKey(imagePath),
             )
           : Image.asset(
               imagePath,
               height: _height,
               width: _width,
               errorBuilder: (_, __, ___) => Icon(Icons.error),
+              key: ValueKey(imagePath),
             );
     }
   }
diff --git a/lib/view_model/dashboard/action_list_item.dart b/lib/view_model/dashboard/action_list_item.dart
index b03bd1bdc..1ee4e6a3c 100644
--- a/lib/view_model/dashboard/action_list_item.dart
+++ b/lib/view_model/dashboard/action_list_item.dart
@@ -1,3 +1,8 @@
+import 'package:flutter/foundation.dart';
+
 abstract class ActionListItem {
+  ActionListItem({required this.key});
+
   DateTime get date;
+  Key key;
 }
\ No newline at end of file
diff --git a/lib/view_model/dashboard/anonpay_transaction_list_item.dart b/lib/view_model/dashboard/anonpay_transaction_list_item.dart
index 261e49070..a54a4b334 100644
--- a/lib/view_model/dashboard/anonpay_transaction_list_item.dart
+++ b/lib/view_model/dashboard/anonpay_transaction_list_item.dart
@@ -2,7 +2,7 @@ import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
 import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
 
 class AnonpayTransactionListItem extends ActionListItem {
-  AnonpayTransactionListItem({required this.transaction});
+  AnonpayTransactionListItem({required this.transaction, required super.key});
 
   final AnonpayInvoiceInfo transaction;
 
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 423babefc..6cf7c49d0 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -48,6 +48,7 @@ import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:eth_sig_util/util/utils.dart';
+import 'package:flutter/foundation.dart';
 import 'package:flutter/services.dart';
 import 'package:http/http.dart' as http;
 import 'package:mobx/mobx.dart';
@@ -182,10 +183,16 @@ abstract class DashboardViewModelBase with Store {
       final sortedTransactions = [..._accountTransactions];
       sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
 
-      transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem(
-          transaction: transaction,
-          balanceViewModel: balanceViewModel,
-          settingsStore: appStore.settingsStore)));
+      transactions = ObservableList.of(
+        sortedTransactions.map(
+          (transaction) => TransactionListItem(
+            transaction: transaction,
+            balanceViewModel: balanceViewModel,
+            settingsStore: appStore.settingsStore,
+            key: ValueKey('monero_transaction_history_item_${transaction.id}_key'),
+          ),
+        ),
+      );
     } else if (_wallet.type == WalletType.wownero) {
       subname = wow.wownero!.getCurrentAccount(_wallet).label;
 
@@ -206,18 +213,30 @@ abstract class DashboardViewModelBase with Store {
       final sortedTransactions = [..._accountTransactions];
       sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
 
-      transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem(
-          transaction: transaction,
-          balanceViewModel: balanceViewModel,
-          settingsStore: appStore.settingsStore)));
+      transactions = ObservableList.of(
+        sortedTransactions.map(
+          (transaction) => TransactionListItem(
+            transaction: transaction,
+            balanceViewModel: balanceViewModel,
+            settingsStore: appStore.settingsStore,
+            key: ValueKey('wownero_transaction_history_item_${transaction.id}_key'),
+          ),
+        ),
+      );
     } else {
       final sortedTransactions = [...wallet.transactionHistory.transactions.values];
       sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
 
-      transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem(
-          transaction: transaction,
-          balanceViewModel: balanceViewModel,
-          settingsStore: appStore.settingsStore)));
+      transactions = ObservableList.of(
+        sortedTransactions.map(
+          (transaction) => TransactionListItem(
+            transaction: transaction,
+            balanceViewModel: balanceViewModel,
+            settingsStore: appStore.settingsStore,
+            key: ValueKey('${_wallet.type.name}_transaction_history_item_${transaction.id}_key'),
+          ),
+        ),
+      );
     }
 
     // TODO: nano sub-account generation is disabled:
@@ -234,9 +253,13 @@ abstract class DashboardViewModelBase with Store {
         appStore.wallet!.transactionHistory.transactions,
         transactions,
         (TransactionInfo? transaction) => TransactionListItem(
-            transaction: transaction!,
-            balanceViewModel: balanceViewModel,
-            settingsStore: appStore.settingsStore), filter: (TransactionInfo? transaction) {
+              transaction: transaction!,
+              balanceViewModel: balanceViewModel,
+              settingsStore: appStore.settingsStore,
+              key: ValueKey(
+                '${_wallet.type.name}_transaction_history_item_${transaction.id}_key',
+              ),
+            ), filter: (TransactionInfo? transaction) {
       if (transaction == null) {
         return false;
       }
@@ -650,20 +673,29 @@ abstract class DashboardViewModelBase with Store {
 
       transactions.clear();
 
-      transactions.addAll(wallet.transactionHistory.transactions.values.map((transaction) =>
-          TransactionListItem(
-              transaction: transaction,
-              balanceViewModel: balanceViewModel,
-              settingsStore: appStore.settingsStore)));
+      transactions.addAll(
+        wallet.transactionHistory.transactions.values.map(
+          (transaction) => TransactionListItem(
+            transaction: transaction,
+            balanceViewModel: balanceViewModel,
+            settingsStore: appStore.settingsStore,
+            key: ValueKey('${wallet.type.name}_transaction_history_item_${transaction.id}_key'),
+          ),
+        ),
+      );
     }
 
     connectMapToListWithTransform(
         appStore.wallet!.transactionHistory.transactions,
         transactions,
         (TransactionInfo? transaction) => TransactionListItem(
-            transaction: transaction!,
-            balanceViewModel: balanceViewModel,
-            settingsStore: appStore.settingsStore), filter: (TransactionInfo? tx) {
+              transaction: transaction!,
+              balanceViewModel: balanceViewModel,
+              settingsStore: appStore.settingsStore,
+              key: ValueKey(
+                '${wallet.type.name}_transaction_history_item_${transaction.id}_key',
+              ),
+            ), filter: (TransactionInfo? tx) {
       if (tx == null) {
         return false;
       }
@@ -703,10 +735,16 @@ abstract class DashboardViewModelBase with Store {
               monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
           .toList();
 
-      transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem(
-          transaction: transaction,
-          balanceViewModel: balanceViewModel,
-          settingsStore: appStore.settingsStore)));
+      transactions.addAll(
+        _accountTransactions.map(
+          (transaction) => TransactionListItem(
+            transaction: transaction,
+            balanceViewModel: balanceViewModel,
+            settingsStore: appStore.settingsStore,
+            key: ValueKey('monero_transaction_history_item_${transaction.id}_key'),
+          ),
+        ),
+      );
     } else if (wallet.type == WalletType.wownero) {
       final _accountTransactions = wow.wownero!
           .getTransactionHistory(wallet)
@@ -717,10 +755,16 @@ abstract class DashboardViewModelBase with Store {
               wow.wownero!.getCurrentAccount(wallet).id)
           .toList();
 
-      transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem(
-          transaction: transaction,
-          balanceViewModel: balanceViewModel,
-          settingsStore: appStore.settingsStore)));
+      transactions.addAll(
+        _accountTransactions.map(
+          (transaction) => TransactionListItem(
+            transaction: transaction,
+            balanceViewModel: balanceViewModel,
+            settingsStore: appStore.settingsStore,
+            key: ValueKey('wownero_transaction_history_item_${transaction.id}_key'),
+          ),
+        ),
+      );
     }
   }
 
diff --git a/lib/view_model/dashboard/date_section_item.dart b/lib/view_model/dashboard/date_section_item.dart
index 0b361ecce..75250a7ea 100644
--- a/lib/view_model/dashboard/date_section_item.dart
+++ b/lib/view_model/dashboard/date_section_item.dart
@@ -1,7 +1,7 @@
 import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
 
 class DateSectionItem extends ActionListItem {
-  DateSectionItem(this.date);
+  DateSectionItem(this.date, {required super.key});
   
   @override
   final DateTime date;
diff --git a/lib/view_model/dashboard/formatted_item_list.dart b/lib/view_model/dashboard/formatted_item_list.dart
index a1cbbbf7d..04464ca89 100644
--- a/lib/view_model/dashboard/formatted_item_list.dart
+++ b/lib/view_model/dashboard/formatted_item_list.dart
@@ -1,5 +1,6 @@
 import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
 import 'package:cake_wallet/view_model/dashboard/date_section_item.dart';
+import 'package:flutter/foundation.dart';
 
 List<ActionListItem> formattedItemsList(List<ActionListItem> items) {
   final formattedList = <ActionListItem>[];
@@ -11,7 +12,12 @@ List<ActionListItem> formattedItemsList(List<ActionListItem> items) {
 
     if (lastDate == null) {
       lastDate = transaction.date;
-      formattedList.add(DateSectionItem(transaction.date));
+      formattedList.add(
+        DateSectionItem(
+          transaction.date,
+          key: ValueKey('date_section_item_${transaction.date.microsecondsSinceEpoch}_key'),
+        ),
+      );
       formattedList.add(transaction);
       continue;
     }
@@ -26,7 +32,12 @@ List<ActionListItem> formattedItemsList(List<ActionListItem> items) {
     }
 
     lastDate = transaction.date;
-    formattedList.add(DateSectionItem(transaction.date));
+    formattedList.add(
+      DateSectionItem(
+        transaction.date,
+        key: ValueKey('date_section_item_${transaction.date.microsecondsSinceEpoch}_key'),
+      ),
+    );
     formattedList.add(transaction);
   }
 
diff --git a/lib/view_model/dashboard/order_list_item.dart b/lib/view_model/dashboard/order_list_item.dart
index 9120cc1a6..52adf53a6 100644
--- a/lib/view_model/dashboard/order_list_item.dart
+++ b/lib/view_model/dashboard/order_list_item.dart
@@ -6,7 +6,9 @@ import 'package:cake_wallet/entities/balance_display_mode.dart';
 class OrderListItem extends ActionListItem {
   OrderListItem({
     required this.order,
-    required this.settingsStore});
+    required this.settingsStore,
+    required super.key,
+  });
 
   final Order order;
   final SettingsStore settingsStore;
diff --git a/lib/view_model/dashboard/trade_list_item.dart b/lib/view_model/dashboard/trade_list_item.dart
index 964ba4ffa..55ae4e99f 100644
--- a/lib/view_model/dashboard/trade_list_item.dart
+++ b/lib/view_model/dashboard/trade_list_item.dart
@@ -4,7 +4,11 @@ import 'package:cake_wallet/store/settings_store.dart';
 import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
 
 class TradeListItem extends ActionListItem {
-  TradeListItem({required this.trade, required this.settingsStore});
+  TradeListItem({
+    required this.trade,
+    required this.settingsStore,
+    required super.key,
+  });
 
   final Trade trade;
   final SettingsStore settingsStore;
diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart
index b218c8e9f..d9b361fd2 100644
--- a/lib/view_model/dashboard/transaction_list_item.dart
+++ b/lib/view_model/dashboard/transaction_list_item.dart
@@ -22,8 +22,12 @@ import 'package:cw_core/keyable.dart';
 import 'package:cw_core/wallet_type.dart';
 
 class TransactionListItem extends ActionListItem with Keyable {
-  TransactionListItem(
-      {required this.transaction, required this.balanceViewModel, required this.settingsStore});
+  TransactionListItem({
+    required this.transaction,
+    required this.balanceViewModel,
+    required this.settingsStore,
+    required super.key,
+  });
 
   final TransactionInfo transaction;
   final BalanceViewModel balanceViewModel;
diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart
index da6699ae6..a189ebe6c 100644
--- a/lib/view_model/transaction_details_view_model.dart
+++ b/lib/view_model/transaction_details_view_model.dart
@@ -20,6 +20,7 @@ import 'package:cake_wallet/view_model/send/send_view_model.dart';
 import 'package:collection/collection.dart';
 import 'package:cw_core/transaction_direction.dart';
 import 'package:cw_core/transaction_priority.dart';
+import 'package:flutter/foundation.dart';
 import 'package:hive/hive.dart';
 import 'package:intl/src/intl/date_format.dart';
 import 'package:mobx/mobx.dart';
@@ -52,7 +53,7 @@ abstract class TransactionDetailsViewModelBase with Store {
         break;
       case WalletType.bitcoin:
         _addElectrumListItems(tx, dateFormat);
-        if(!canReplaceByFee)_checkForRBF(tx);
+        if (!canReplaceByFee) _checkForRBF(tx);
         break;
       case WalletType.litecoin:
       case WalletType.bitcoinCash:
@@ -83,8 +84,7 @@ abstract class TransactionDetailsViewModelBase with Store {
         break;
     }
 
-    final descriptionKey =
-        '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
+    final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
     final description = transactionDescriptionBox.values.firstWhere(
         (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
         orElse: () => TransactionDescription(id: descriptionKey));
@@ -93,15 +93,20 @@ abstract class TransactionDetailsViewModelBase with Store {
       final recipientAddress = description.recipientAddress;
 
       if (recipientAddress?.isNotEmpty ?? false) {
-        items.add(StandartListItem(
-          title: S.current.transaction_details_recipient_address,
-          value: recipientAddress!));
+        items.add(
+          StandartListItem(
+            title: S.current.transaction_details_recipient_address,
+            value: recipientAddress!,
+            key: ValueKey('standard_list_item_${recipientAddress}_key'),
+          ),
+        );
       }
     }
 
     final type = wallet.type;
 
-    items.add(BlockExplorerListItem(
+    items.add(
+      BlockExplorerListItem(
         title: S.current.view_in_block_explorer,
         value: _explorerDescription(type),
         onTap: () async {
@@ -109,9 +114,13 @@ abstract class TransactionDetailsViewModelBase with Store {
             final uri = Uri.parse(_explorerUrl(type, tx.txHash));
             if (await canLaunchUrl(uri)) await launchUrl(uri, mode: LaunchMode.externalApplication);
           } catch (e) {}
-        }));
+        },
+        key: ValueKey('block_explorer_list_item_${type.name}_wallet_type_key'),
+      ),
+    );
 
-    items.add(TextFieldListItem(
+    items.add(
+      TextFieldListItem(
         title: S.current.note_tap_to_change,
         value: description.note,
         onSubmitted: (value) {
@@ -122,7 +131,10 @@ abstract class TransactionDetailsViewModelBase with Store {
           } else {
             transactionDescriptionBox.add(description);
           }
-        }));
+        },
+        key: ValueKey('textfield_list_item_note_entry_key'),
+      ),
+    );
   }
 
   final TransactionInfo transactionInfo;
@@ -209,14 +221,38 @@ abstract class TransactionDetailsViewModelBase with Store {
     final addressIndex = tx.additionalInfo['addressIndex'] as int;
     final feeFormatted = tx.feeFormatted();
     final _items = [
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_height,
+        value: '${tx.height}',
+        key: ValueKey('standard_list_item_transaction_details_height_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
       if (feeFormatted != null)
-        StandartListItem(title: S.current.transaction_details_fee, value: feeFormatted),
-      if (key?.isNotEmpty ?? false) StandartListItem(title: S.current.transaction_key, value: key!),
+        StandartListItem(
+          title: S.current.transaction_details_fee,
+          value: feeFormatted,
+          key: ValueKey('standard_list_item_transaction_details_fee_key'),
+        ),
+      if (key?.isNotEmpty ?? false)
+        StandartListItem(
+          title: S.current.transaction_key,
+          value: key!,
+          key: ValueKey('standard_list_item_transaction_key'),
+        ),
     ];
 
     if (tx.direction == TransactionDirection.incoming) {
@@ -226,14 +262,21 @@ abstract class TransactionDetailsViewModelBase with Store {
 
         if (address.isNotEmpty) {
           isRecipientAddressShown = true;
-          _items.add(StandartListItem(
-            title: S.current.transaction_details_recipient_address,
-            value: address,
-          ));
+          _items.add(
+            StandartListItem(
+              title: S.current.transaction_details_recipient_address,
+              value: address,
+              key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
+            ),
+          );
         }
 
         if (label.isNotEmpty) {
-          _items.add(StandartListItem(title: S.current.address_label, value: label));
+          _items.add(StandartListItem(
+            title: S.current.address_label,
+            value: label,
+            key: ValueKey('standard_list_item_address_label_key'),
+          ));
         }
       } catch (e) {
         print(e.toString());
@@ -245,14 +288,37 @@ abstract class TransactionDetailsViewModelBase with Store {
 
   void _addElectrumListItems(TransactionInfo tx, DateFormat dateFormat) {
     final _items = [
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.confirmations, value: tx.confirmations.toString()),
-      StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.confirmations,
+        value: tx.confirmations.toString(),
+        key: ValueKey('standard_list_item_transaction_confirmations_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_height,
+        value: '${tx.height}',
+        key: ValueKey('standard_list_item_transaction_details_height_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
       if (tx.feeFormatted()?.isNotEmpty ?? false)
-        StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
+        StandartListItem(
+          title: S.current.transaction_details_fee,
+          value: tx.feeFormatted()!,
+          key: ValueKey('standard_list_item_transaction_details_fee_key'),
+        ),
     ];
 
     items.addAll(_items);
@@ -260,30 +326,80 @@ abstract class TransactionDetailsViewModelBase with Store {
 
   void _addHavenListItems(TransactionInfo tx, DateFormat dateFormat) {
     items.addAll([
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_height,
+        value: '${tx.height}',
+        key: ValueKey('standard_list_item_transaction_details_height_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
       if (tx.feeFormatted()?.isNotEmpty ?? false)
-        StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
+        StandartListItem(
+          title: S.current.transaction_details_fee,
+          value: tx.feeFormatted()!,
+          key: ValueKey('standard_list_item_transaction_details_fee_key'),
+        ),
     ]);
   }
 
   void _addEthereumListItems(TransactionInfo tx, DateFormat dateFormat) {
     final _items = [
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.confirmations, value: tx.confirmations.toString()),
-      StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.confirmations,
+        value: tx.confirmations.toString(),
+        key: ValueKey('standard_list_item_transaction_confirmations_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_height,
+        value: '${tx.height}',
+        key: ValueKey('standard_list_item_transaction_details_height_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
       if (tx.feeFormatted()?.isNotEmpty ?? false)
-        StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
+        StandartListItem(
+          title: S.current.transaction_details_fee,
+          value: tx.feeFormatted()!,
+          key: ValueKey('standard_list_item_transaction_details_fee_key'),
+        ),
       if (showRecipientAddress && tx.to != null)
-        StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!),
+        StandartListItem(
+          title: S.current.transaction_details_recipient_address,
+          value: tx.to!,
+          key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
+        ),
       if (tx.direction == TransactionDirection.incoming && tx.from != null)
-        StandartListItem(title: S.current.transaction_details_source_address, value: tx.from!),
+        StandartListItem(
+          title: S.current.transaction_details_source_address,
+          value: tx.from!,
+          key: ValueKey('standard_list_item_transaction_details_source_address_key'),
+        ),
     ];
 
     items.addAll(_items);
@@ -291,16 +407,43 @@ abstract class TransactionDetailsViewModelBase with Store {
 
   void _addNanoListItems(TransactionInfo tx, DateFormat dateFormat) {
     final _items = [
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
-      if (showRecipientAddress && tx.to != null)
-        StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!),
-      if (showRecipientAddress && tx.from != null)
-        StandartListItem(title: S.current.transaction_details_source_address, value: tx.from!),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.confirmed_tx, value: (tx.confirmations > 0).toString()),
-      StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      if (showRecipientAddress && tx.to != null)
+        StandartListItem(
+          title: S.current.transaction_details_recipient_address,
+          value: tx.to!,
+          key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
+        ),
+      if (showRecipientAddress && tx.from != null)
+        StandartListItem(
+          title: S.current.transaction_details_source_address,
+          value: tx.from!,
+          key: ValueKey('standard_list_item_transaction_details_source_address_key'),
+        ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.confirmed_tx,
+        value: (tx.confirmations > 0).toString(),
+        key: ValueKey('standard_list_item_transaction_confirmed_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_height,
+        value: '${tx.height}',
+        key: ValueKey('standard_list_item_transaction_details_height_key'),
+      ),
     ];
 
     items.addAll(_items);
@@ -308,18 +451,49 @@ abstract class TransactionDetailsViewModelBase with Store {
 
   void _addPolygonListItems(TransactionInfo tx, DateFormat dateFormat) {
     final _items = [
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.confirmations, value: tx.confirmations.toString()),
-      StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.confirmations,
+        value: tx.confirmations.toString(),
+        key: ValueKey('standard_list_item_transaction_confirmations_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_height,
+        value: '${tx.height}',
+        key: ValueKey('standard_list_item_transaction_details_height_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
       if (tx.feeFormatted()?.isNotEmpty ?? false)
-        StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
+        StandartListItem(
+          title: S.current.transaction_details_fee,
+          value: tx.feeFormatted()!,
+          key: ValueKey('standard_list_item_transaction_details_fee_key'),
+        ),
       if (showRecipientAddress && tx.to != null && tx.direction == TransactionDirection.outgoing)
-        StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!),
+        StandartListItem(
+          title: S.current.transaction_details_recipient_address,
+          value: tx.to!,
+          key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
+        ),
       if (tx.direction == TransactionDirection.incoming && tx.from != null)
-        StandartListItem(title: S.current.transaction_details_source_address, value: tx.from!),
+        StandartListItem(
+          title: S.current.transaction_details_source_address,
+          value: tx.from!,
+          key: ValueKey('standard_list_item_transaction_details_source_address_key'),
+        ),
     ];
 
     items.addAll(_items);
@@ -327,16 +501,39 @@ abstract class TransactionDetailsViewModelBase with Store {
 
   void _addSolanaListItems(TransactionInfo tx, DateFormat dateFormat) {
     final _items = [
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
       if (tx.feeFormatted()?.isNotEmpty ?? false)
-        StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
+        StandartListItem(
+          title: S.current.transaction_details_fee,
+          value: tx.feeFormatted()!,
+          key: ValueKey('standard_list_item_transaction_details_fee_key'),
+        ),
       if (showRecipientAddress && tx.to != null)
-        StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!),
+        StandartListItem(
+          title: S.current.transaction_details_recipient_address,
+          value: tx.to!,
+          key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
+        ),
       if (tx.from != null)
-        StandartListItem(title: S.current.transaction_details_source_address, value: tx.from!),
+        StandartListItem(
+          title: S.current.transaction_details_source_address,
+          value: tx.from!,
+          key: ValueKey('standard_list_item_transaction_details_source_address_key'),
+        ),
     ];
 
     items.addAll(_items);
@@ -354,7 +551,13 @@ abstract class TransactionDetailsViewModelBase with Store {
     newFee = bitcoin!.getFeeAmountForPriority(
         wallet, bitcoin!.getBitcoinTransactionPriorityMedium(), inputsCount, outputsCount);
 
-    RBFListItems.add(StandartListItem(title: S.current.old_fee, value: tx.feeFormatted() ?? '0.0'));
+    RBFListItems.add(
+      StandartListItem(
+        title: S.current.old_fee,
+        value: tx.feeFormatted() ?? '0.0',
+        key: ValueKey('standard_list_item_rbf_old_fee_key'),
+      ),
+    );
 
     if (transactionInfo.fee != null && rawTransaction.isNotEmpty) {
       final size = bitcoin!.getTransactionVSize(wallet, rawTransaction);
@@ -371,7 +574,9 @@ abstract class TransactionDetailsViewModelBase with Store {
     final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null;
     final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
 
-    RBFListItems.add(StandardPickerListItem(
+    RBFListItems.add(
+      StandardPickerListItem(
+        key: ValueKey('standard_picker_list_item_transaction_priorities_key'),
         title: S.current.estimated_new_fee,
         value: bitcoin!.formatterBitcoinAmountToString(amount: newFee) +
             ' ${walletTypeToCryptoCurrency(wallet.type)}',
@@ -387,42 +592,73 @@ abstract class TransactionDetailsViewModelBase with Store {
         onItemSelected: (dynamic item, double sliderValue) {
           transactionPriority = item as TransactionPriority;
           return setNewFee(value: sliderValue, priority: transactionPriority!);
-        }));
+        },
+      ),
+    );
 
     if (transactionInfo.inputAddresses != null && transactionInfo.inputAddresses!.isNotEmpty) {
-      RBFListItems.add(StandardExpandableListItem(
-          title: S.current.inputs, expandableItems: transactionInfo.inputAddresses!));
+      RBFListItems.add(
+        StandardExpandableListItem(
+          key: ValueKey('standard_expandable_list_item_transaction_input_addresses_key'),
+          title: S.current.inputs,
+          expandableItems: transactionInfo.inputAddresses!,
+        ),
+      );
     }
 
     if (transactionInfo.outputAddresses != null && transactionInfo.outputAddresses!.isNotEmpty) {
       final outputAddresses = transactionInfo.outputAddresses!.map((element) {
         if (element.contains('OP_RETURN:') && element.length > 40) {
-            return element.substring(0, 40) + '...';
+          return element.substring(0, 40) + '...';
         }
         return element;
       }).toList();
 
       RBFListItems.add(
-          StandardExpandableListItem(title: S.current.outputs, expandableItems: outputAddresses));
+        StandardExpandableListItem(
+          title: S.current.outputs,
+          expandableItems: outputAddresses,
+          key: ValueKey('standard_expandable_list_item_transaction_output_addresses_key'),
+        ),
+      );
     }
   }
 
   void _addTronListItems(TransactionInfo tx, DateFormat dateFormat) {
     final _items = [
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
       if (tx.feeFormatted()?.isNotEmpty ?? false)
-        StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
+        StandartListItem(
+          title: S.current.transaction_details_fee,
+          value: tx.feeFormatted()!,
+          key: ValueKey('standard_list_item_transaction_details_fee_key'),
+        ),
       if (showRecipientAddress && tx.to != null)
         StandartListItem(
-            title: S.current.transaction_details_recipient_address,
-            value: tron!.getTronBase58Address(tx.to!, wallet)),
+          title: S.current.transaction_details_recipient_address,
+          value: tron!.getTronBase58Address(tx.to!, wallet),
+          key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
+        ),
       if (tx.from != null)
         StandartListItem(
-            title: S.current.transaction_details_source_address,
-            value: tron!.getTronBase58Address(tx.from!, wallet)),
+          title: S.current.transaction_details_source_address,
+          value: tron!.getTronBase58Address(tx.from!, wallet),
+          key: ValueKey('standard_list_item_transaction_details_source_address_key'),
+        ),
     ];
 
     items.addAll(_items);
@@ -455,7 +691,7 @@ abstract class TransactionDetailsViewModelBase with Store {
     return bitcoin!.formatterBitcoinAmountToString(amount: newFee);
   }
 
-  void replaceByFee(String newFee) => sendViewModel.replaceByFee(transactionInfo, newFee,);
+  void replaceByFee(String newFee) => sendViewModel.replaceByFee(transactionInfo, newFee);
 
   @computed
   String get pendingTransactionFiatAmountValueFormatted => sendViewModel.isFiatDisabled
@@ -473,14 +709,38 @@ abstract class TransactionDetailsViewModelBase with Store {
     final addressIndex = tx.additionalInfo['addressIndex'] as int;
     final feeFormatted = tx.feeFormatted();
     final _items = [
-      StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.txHash),
       StandartListItem(
-          title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
-      StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
-      StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
+        title: S.current.transaction_details_transaction_id,
+        value: tx.txHash,
+        key: ValueKey('standard_list_item_transaction_details_id_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_date,
+        value: dateFormat.format(tx.date),
+        key: ValueKey('standard_list_item_transaction_details_date_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_height,
+        value: '${tx.height}',
+        key: ValueKey('standard_list_item_transaction_details_height_key'),
+      ),
+      StandartListItem(
+        title: S.current.transaction_details_amount,
+        value: tx.amountFormatted(),
+        key: ValueKey('standard_list_item_transaction_details_amount_key'),
+      ),
       if (feeFormatted != null)
-        StandartListItem(title: S.current.transaction_details_fee, value: feeFormatted),
-      if (key?.isNotEmpty ?? false) StandartListItem(title: S.current.transaction_key, value: key!),
+        StandartListItem(
+          title: S.current.transaction_details_fee,
+          value: feeFormatted,
+          key: ValueKey('standard_list_item_transaction_details_fee_key'),
+        ),
+      if (key?.isNotEmpty ?? false)
+        StandartListItem(
+          title: S.current.transaction_key,
+          value: key!,
+          key: ValueKey('standard_list_item_transaction_key'),
+        ),
     ];
 
     if (tx.direction == TransactionDirection.incoming) {
@@ -490,14 +750,23 @@ abstract class TransactionDetailsViewModelBase with Store {
 
         if (address.isNotEmpty) {
           isRecipientAddressShown = true;
-          _items.add(StandartListItem(
-            title: S.current.transaction_details_recipient_address,
-            value: address,
-          ));
+          _items.add(
+            StandartListItem(
+              title: S.current.transaction_details_recipient_address,
+              value: address,
+              key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
+            ),
+          );
         }
 
         if (label.isNotEmpty) {
-          _items.add(StandartListItem(title: S.current.address_label, value: label));
+          _items.add(
+            StandartListItem(
+              title: S.current.address_label,
+              value: label,
+              key: ValueKey('standard_list_item_address_label_key'),
+            ),
+          );
         }
       } catch (e) {
         print(e.toString());
diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart
index 9921ae30a..6455fc0e3 100644
--- a/lib/view_model/wallet_keys_view_model.dart
+++ b/lib/view_model/wallet_keys_view_model.dart
@@ -10,6 +10,7 @@ import 'package:cw_core/transaction_info.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:cw_monero/monero_wallet.dart';
+import 'package:flutter/foundation.dart';
 import 'package:mobx/mobx.dart';
 import 'package:polyseed/polyseed.dart';
 
@@ -24,6 +25,7 @@ abstract class WalletKeysViewModelBase with Store {
                 _appStore.wallet!.type == WalletType.bitcoinCash
             ? S.current.wallet_seed
             : S.current.wallet_keys,
+        _walletName = _appStore.wallet!.type.name,
         _restoreHeight = _appStore.wallet!.walletInfo.restoreHeight,
         _restoreHeightByTransactions = 0,
         items = ObservableList<StandartListItem>() {
@@ -38,12 +40,10 @@ abstract class WalletKeysViewModelBase with Store {
         _appStore.wallet!.type == WalletType.wownero) {
       final accountTransactions = _getWalletTransactions(_appStore.wallet!);
       if (accountTransactions.isNotEmpty) {
-        final incomingAccountTransactions = accountTransactions
-            .where((tx) => tx.direction == TransactionDirection.incoming);
+        final incomingAccountTransactions =
+            accountTransactions.where((tx) => tx.direction == TransactionDirection.incoming);
         if (incomingAccountTransactions.isNotEmpty) {
-          incomingAccountTransactions
-              .toList()
-              .sort((a, b) => a.date.compareTo(b.date));
+          incomingAccountTransactions.toList().sort((a, b) => a.date.compareTo(b.date));
           _restoreHeightByTransactions = _getRestoreHeightByTransactions(
               _appStore.wallet!.type, incomingAccountTransactions.first.date);
         }
@@ -55,6 +55,10 @@ abstract class WalletKeysViewModelBase with Store {
 
   final String title;
 
+  final String _walletName;
+
+  AppStore get appStore => _appStore;
+
   final AppStore _appStore;
 
   final int _restoreHeight;
@@ -70,37 +74,56 @@ abstract class WalletKeysViewModelBase with Store {
       items.addAll([
         if (keys['publicSpendKey'] != null)
           StandartListItem(
-              title: S.current.spend_key_public,
-              value: keys['publicSpendKey']!),
+            key: ValueKey('${_walletName}_wallet_public_spend_key_item_key'),
+            title: S.current.spend_key_public,
+            value: keys['publicSpendKey']!,
+          ),
         if (keys['privateSpendKey'] != null)
           StandartListItem(
-              title: S.current.spend_key_private,
-              value: keys['privateSpendKey']!),
+            key: ValueKey('${_walletName}_wallet_private_spend_key_item_key'),
+            title: S.current.spend_key_private,
+            value: keys['privateSpendKey']!,
+          ),
         if (keys['publicViewKey'] != null)
           StandartListItem(
-              title: S.current.view_key_public, value: keys['publicViewKey']!),
+            key: ValueKey('${_walletName}_wallet_public_view_key_item_key'),
+            title: S.current.view_key_public,
+            value: keys['publicViewKey']!,
+          ),
         if (keys['privateViewKey'] != null)
           StandartListItem(
-              title: S.current.view_key_private,
-              value: keys['privateViewKey']!),
+            key: ValueKey('${_walletName}_wallet_private_view_key_item_key'),
+            title: S.current.view_key_private,
+            value: keys['privateViewKey']!,
+          ),
         if (_appStore.wallet!.seed!.isNotEmpty)
-          StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
+          StandartListItem(
+            key: ValueKey('${_walletName}_wallet_seed_item_key'),
+            title: S.current.wallet_seed,
+            value: _appStore.wallet!.seed!,
+          ),
       ]);
 
-      if (_appStore.wallet?.seed != null &&
-          Polyseed.isValidSeed(_appStore.wallet!.seed!)) {
+      if (_appStore.wallet?.seed != null && Polyseed.isValidSeed(_appStore.wallet!.seed!)) {
         final lang = PolyseedLang.getByPhrase(_appStore.wallet!.seed!);
-        items.add(StandartListItem(
+        items.add(
+          StandartListItem(
+            key: ValueKey('${_walletName}_wallet_seed_legacy_item_key'),
             title: S.current.wallet_seed_legacy,
-            value: (_appStore.wallet as MoneroWalletBase)
-                .seedLegacy(lang.nameEnglish)));
+            value: (_appStore.wallet as MoneroWalletBase).seedLegacy(lang.nameEnglish),
+          ),
+        );
       }
 
       final restoreHeight = monero!.getRestoreHeight(_appStore.wallet!);
       if (restoreHeight != null) {
-        items.add(StandartListItem(
+        items.add(
+          StandartListItem(
+            key: ValueKey('${_walletName}_wallet_restore_height_item_key'),
             title: S.current.wallet_recovery_height,
-            value: restoreHeight.toString()));
+            value: restoreHeight.toString(),
+          ),
+        );
       }
     }
 
@@ -110,21 +133,34 @@ abstract class WalletKeysViewModelBase with Store {
       items.addAll([
         if (keys['publicSpendKey'] != null)
           StandartListItem(
-              title: S.current.spend_key_public,
-              value: keys['publicSpendKey']!),
+            key: ValueKey('${_walletName}_wallet_public_spend_key_item_key'),
+            title: S.current.spend_key_public,
+            value: keys['publicSpendKey']!,
+          ),
         if (keys['privateSpendKey'] != null)
           StandartListItem(
-              title: S.current.spend_key_private,
-              value: keys['privateSpendKey']!),
+            key: ValueKey('${_walletName}_wallet_private_spend_key_item_key'),
+            title: S.current.spend_key_private,
+            value: keys['privateSpendKey']!,
+          ),
         if (keys['publicViewKey'] != null)
           StandartListItem(
-              title: S.current.view_key_public, value: keys['publicViewKey']!),
+            key: ValueKey('${_walletName}_wallet_public_view_key_item_key'),
+            title: S.current.view_key_public,
+            value: keys['publicViewKey']!,
+          ),
         if (keys['privateViewKey'] != null)
           StandartListItem(
-              title: S.current.view_key_private,
-              value: keys['privateViewKey']!),
+            key: ValueKey('${_walletName}_wallet_private_view_key_item_key'),
+            title: S.current.view_key_private,
+            value: keys['privateViewKey']!,
+          ),
         if (_appStore.wallet!.seed!.isNotEmpty)
-          StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
+          StandartListItem(
+            key: ValueKey('${_walletName}_wallet_seed_item_key'),
+            title: S.current.wallet_seed,
+            value: _appStore.wallet!.seed!,
+          ),
       ]);
     }
 
@@ -134,29 +170,45 @@ abstract class WalletKeysViewModelBase with Store {
       items.addAll([
         if (keys['publicSpendKey'] != null)
           StandartListItem(
-              title: S.current.spend_key_public,
-              value: keys['publicSpendKey']!),
+            key: ValueKey('${_walletName}_wallet_public_spend_key_item_key'),
+            title: S.current.spend_key_public,
+            value: keys['publicSpendKey']!,
+          ),
         if (keys['privateSpendKey'] != null)
           StandartListItem(
-              title: S.current.spend_key_private,
-              value: keys['privateSpendKey']!),
+            key: ValueKey('${_walletName}_wallet_private_spend_key_item_key'),
+            title: S.current.spend_key_private,
+            value: keys['privateSpendKey']!,
+          ),
         if (keys['publicViewKey'] != null)
           StandartListItem(
-              title: S.current.view_key_public, value: keys['publicViewKey']!),
+            key: ValueKey('${_walletName}_wallet_public_view_key_item_key'),
+            title: S.current.view_key_public,
+            value: keys['publicViewKey']!,
+          ),
         if (keys['privateViewKey'] != null)
           StandartListItem(
-              title: S.current.view_key_private,
-              value: keys['privateViewKey']!),
+            key: ValueKey('${_walletName}_wallet_private_view_key_item_key'),
+            title: S.current.view_key_private,
+            value: keys['privateViewKey']!,
+          ),
         if (_appStore.wallet!.seed!.isNotEmpty)
-          StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
+          StandartListItem(
+            key: ValueKey('${_walletName}_wallet_seed_item_key'),
+            title: S.current.wallet_seed,
+            value: _appStore.wallet!.seed!,
+          ),
       ]);
 
-      if (_appStore.wallet?.seed != null &&
-          Polyseed.isValidSeed(_appStore.wallet!.seed!)) {
+      if (_appStore.wallet?.seed != null && Polyseed.isValidSeed(_appStore.wallet!.seed!)) {
         final lang = PolyseedLang.getByPhrase(_appStore.wallet!.seed!);
-        items.add(StandartListItem(
+        items.add(
+          StandartListItem(
+            key: ValueKey('${_walletName}_wallet_seed_legacy_item_key'),
             title: S.current.wallet_seed_legacy,
-            value: wownero!.getLegacySeed(_appStore.wallet!, lang.nameEnglish)));
+            value: wownero!.getLegacySeed(_appStore.wallet!, lang.nameEnglish),
+          ),
+        );
       }
     }
 
@@ -173,7 +225,10 @@ abstract class WalletKeysViewModelBase with Store {
         // if (keys['publicKey'] != null)
         //   StandartListItem(title: S.current.public_key, value: keys['publicKey']!),
         StandartListItem(
-            title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
+          key: ValueKey('${_walletName}_wallet_seed_item_key'),
+          title: S.current.wallet_seed,
+          value: _appStore.wallet!.seed!,
+        ),
       ]);
     }
 
@@ -183,31 +238,43 @@ abstract class WalletKeysViewModelBase with Store {
       items.addAll([
         if (_appStore.wallet!.privateKey != null)
           StandartListItem(
-              title: S.current.private_key,
-              value: _appStore.wallet!.privateKey!),
+            key: ValueKey('${_walletName}_wallet_private_key_item_key'),
+            title: S.current.private_key,
+            value: _appStore.wallet!.privateKey!,
+          ),
         if (_appStore.wallet!.seed != null)
           StandartListItem(
-              title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
+            key: ValueKey('${_walletName}_wallet_seed_item_key'),
+            title: S.current.wallet_seed,
+            value: _appStore.wallet!.seed!,
+          ),
       ]);
     }
 
-    bool nanoBased = _appStore.wallet!.type == WalletType.nano ||
-        _appStore.wallet!.type == WalletType.banano;
+    bool nanoBased =
+        _appStore.wallet!.type == WalletType.nano || _appStore.wallet!.type == WalletType.banano;
 
     if (nanoBased) {
       // we always have the hex version of the seed and private key:
       items.addAll([
         if (_appStore.wallet!.seed != null)
           StandartListItem(
-              title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
+            key: ValueKey('${_walletName}_wallet_seed_item_key'),
+            title: S.current.wallet_seed,
+            value: _appStore.wallet!.seed!,
+          ),
         if (_appStore.wallet!.hexSeed != null)
           StandartListItem(
-              title: S.current.seed_hex_form,
-              value: _appStore.wallet!.hexSeed!),
+            key: ValueKey('${_walletName}_wallet_hex_seed_key'),
+            title: S.current.seed_hex_form,
+            value: _appStore.wallet!.hexSeed!,
+          ),
         if (_appStore.wallet!.privateKey != null)
           StandartListItem(
-              title: S.current.private_key,
-              value: _appStore.wallet!.privateKey!),
+            key: ValueKey('${_walletName}_wallet_private_key_item_key'),
+            title: S.current.private_key,
+            value: _appStore.wallet!.privateKey!,
+          ),
       ]);
     }
   }
@@ -273,8 +340,7 @@ abstract class WalletKeysViewModelBase with Store {
       if (_appStore.wallet!.seed != null) 'seed': _appStore.wallet!.seed!,
       if (_appStore.wallet!.seed == null && _appStore.wallet!.hexSeed != null)
         'hexSeed': _appStore.wallet!.hexSeed!,
-      if (_appStore.wallet!.seed == null &&
-          _appStore.wallet!.privateKey != null)
+      if (_appStore.wallet!.seed == null && _appStore.wallet!.privateKey != null)
         'private_key': _appStore.wallet!.privateKey!,
       if (restoreHeightResult != null) ...{'height': restoreHeightResult},
       if (_appStore.wallet!.passphrase != null) 'passphrase': _appStore.wallet!.passphrase!
@@ -292,11 +358,7 @@ abstract class WalletKeysViewModelBase with Store {
     } else if (wallet.type == WalletType.haven) {
       return haven!.getTransactionHistory(wallet).transactions.values.toList();
     } else if (wallet.type == WalletType.wownero) {
-      return wownero!
-          .getTransactionHistory(wallet)
-          .transactions
-          .values
-          .toList();
+      return wownero!.getTransactionHistory(wallet).transactions.values.toList();
     }
     return [];
   }
@@ -312,6 +374,5 @@ abstract class WalletKeysViewModelBase with Store {
     return 0;
   }
 
-  String getRoundedRestoreHeight(int height) =>
-      ((height / 1000).floor() * 1000).toString();
+  String getRoundedRestoreHeight(int height) => ((height / 1000).floor() * 1000).toString();
 }
diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart
index d3b652935..88cbbfce3 100644
--- a/tool/utils/secret_key.dart
+++ b/tool/utils/secret_key.dart
@@ -44,12 +44,35 @@ class SecretKey {
     SecretKey('cakePayApiKey', () => ''),
     SecretKey('CSRFToken', () => ''),
     SecretKey('authorization', () => ''),
+    SecretKey('moneroTestWalletSeeds', () => ''),
+    SecretKey('moneroLegacyTestWalletSeeds ', () => ''),
+    SecretKey('bitcoinTestWalletSeeds', () => ''),
+    SecretKey('ethereumTestWalletSeeds', () => ''),
+    SecretKey('litecoinTestWalletSeeds', () => ''),
+    SecretKey('bitcoinCashTestWalletSeeds', () => ''),
+    SecretKey('polygonTestWalletSeeds', () => ''),
+    SecretKey('solanaTestWalletSeeds', () => ''),
+    SecretKey('polygonTestWalletSeeds', () => ''),
+    SecretKey('tronTestWalletSeeds', () => ''),
+    SecretKey('nanoTestWalletSeeds', () => ''),
+    SecretKey('wowneroTestWalletSeeds', () => ''),
+    SecretKey('moneroTestWalletReceiveAddress', () => ''),
+    SecretKey('bitcoinTestWalletReceiveAddress', () => ''),
+    SecretKey('ethereumTestWalletReceiveAddress', () => ''),
+    SecretKey('litecoinTestWalletReceiveAddress', () => ''),
+    SecretKey('bitco inCashTestWalletReceiveAddress', () => ''),
+    SecretKey('polygonTestWalletReceiveAddress', () => ''),
+    SecretKey('solanaTestWalletReceiveAddress', () => ''),
+    SecretKey('tronTestWalletReceiveAddress', () => ''),
+    SecretKey('nanoTestWalletReceiveAddress', () => ''),
+    SecretKey('wowneroTestWalletReceiveAddress', () => ''),
     SecretKey('etherScanApiKey', () => ''),
     SecretKey('polygonScanApiKey', () => ''),
     SecretKey('letsExchangeBearerToken', () => ''),
     SecretKey('letsExchangeAffiliateId', () => ''),
     SecretKey('stealthExBearerToken', () => ''),
     SecretKey('stealthExAdditionalFeePercent', () => ''),
+    SecretKey('moneroTestWalletBlockHeight', () => ''),
   ];
 
   static final evmChainsSecrets = [

From 389c334f1076779a134cd037b2af5b1b1c11df2b Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Fri, 8 Nov 2024 12:50:21 +0200
Subject: [PATCH 34/50] Electrum enhancements (#1794)

* Enhance the code for sending/sending-ALL for Electrum

* remove prints [skip ci]
---
 cw_bitcoin/lib/electrum_wallet.dart | 159 +++++++++++-----------------
 cw_bitcoin/pubspec.lock             |   4 +-
 2 files changed, 63 insertions(+), 100 deletions(-)

diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 7988a4479..6245aa787 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -11,7 +11,6 @@ import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:collection/collection.dart';
 import 'package:cw_bitcoin/address_from_output.dart';
 import 'package:cw_bitcoin/bitcoin_address_record.dart';
-import 'package:cw_bitcoin/bitcoin_amount_format.dart';
 import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
 import 'package:cw_bitcoin/bitcoin_unspent.dart';
@@ -597,8 +596,8 @@ abstract class ElectrumWalletBase
 
   UtxoDetails _createUTXOS({
     required bool sendAll,
-    required int credentialsAmount,
     required bool paysToSilentPayment,
+    int credentialsAmount = 0,
     int? inputsCount,
     UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any,
   }) {
@@ -732,13 +731,11 @@ abstract class ElectrumWalletBase
     List<BitcoinOutput> outputs,
     int feeRate, {
     String? memo,
-    int credentialsAmount = 0,
     bool hasSilentPayment = false,
     UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any,
   }) async {
     final utxoDetails = _createUTXOS(
       sendAll: true,
-      credentialsAmount: credentialsAmount,
       paysToSilentPayment: hasSilentPayment,
       coinTypeToSpendFrom: coinTypeToSpendFrom,
     );
@@ -764,23 +761,11 @@ abstract class ElectrumWalletBase
       throw BitcoinTransactionWrongBalanceException(amount: utxoDetails.allInputsAmount + fee);
     }
 
-    if (amount <= 0) {
-      throw BitcoinTransactionWrongBalanceException();
-    }
-
     // Attempting to send less than the dust limit
     if (_isBelowDust(amount)) {
       throw BitcoinTransactionNoDustException();
     }
 
-    if (credentialsAmount > 0) {
-      final amountLeftForFee = amount - credentialsAmount;
-      if (amountLeftForFee > 0 && _isBelowDust(amountLeftForFee)) {
-        amount -= amountLeftForFee;
-        fee += amountLeftForFee;
-      }
-    }
-
     if (outputs.length == 1) {
       outputs[0] = BitcoinOutput(address: outputs.last.address, value: BigInt.from(amount));
     }
@@ -810,6 +795,11 @@ abstract class ElectrumWalletBase
     bool hasSilentPayment = false,
     UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any,
   }) async {
+    // Attempting to send less than the dust limit
+    if (_isBelowDust(credentialsAmount)) {
+      throw BitcoinTransactionNoDustException();
+    }
+
     final utxoDetails = _createUTXOS(
       sendAll: false,
       credentialsAmount: credentialsAmount,
@@ -894,7 +884,43 @@ abstract class ElectrumWalletBase
     final lastOutput = updatedOutputs.last;
     final amountLeftForChange = amountLeftForChangeAndFee - fee;
 
-    if (!_isBelowDust(amountLeftForChange)) {
+    if (_isBelowDust(amountLeftForChange)) {
+      // If has change that is lower than dust, will end up with tx rejected by network rules
+      // so remove the change amount
+      updatedOutputs.removeLast();
+      outputs.removeLast();
+
+      if (amountLeftForChange < 0) {
+        if (!spendingAllCoins) {
+          return estimateTxForAmount(
+            credentialsAmount,
+            outputs,
+            updatedOutputs,
+            feeRate,
+            inputsCount: utxoDetails.utxos.length + 1,
+            memo: memo,
+            useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins,
+            hasSilentPayment: hasSilentPayment,
+            coinTypeToSpendFrom: coinTypeToSpendFrom,
+          );
+        } else {
+          throw BitcoinTransactionWrongBalanceException();
+        }
+      }
+
+      return EstimatedTxResult(
+        utxos: utxoDetails.utxos,
+        inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos,
+        publicKeys: utxoDetails.publicKeys,
+        fee: fee,
+        amount: amount,
+        hasChange: false,
+        isSendAll: spendingAllCoins,
+        memo: memo,
+        spendsUnconfirmedTX: utxoDetails.spendsUnconfirmedTX,
+        spendsSilentPayment: utxoDetails.spendsSilentPayment,
+      );
+    } else {
       // Here, lastOutput already is change, return the amount left without the fee to the user's address.
       updatedOutputs[updatedOutputs.length - 1] = BitcoinOutput(
         address: lastOutput.address,
@@ -908,88 +934,20 @@ abstract class ElectrumWalletBase
         isSilentPayment: lastOutput.isSilentPayment,
         isChange: true,
       );
-    } else {
-      // If has change that is lower than dust, will end up with tx rejected by network rules, so estimate again without the added change
-      updatedOutputs.removeLast();
-      outputs.removeLast();
 
-      // Still has inputs to spend before failing
-      if (!spendingAllCoins) {
-        return estimateTxForAmount(
-          credentialsAmount,
-          outputs,
-          updatedOutputs,
-          feeRate,
-          inputsCount: utxoDetails.utxos.length + 1,
-          memo: memo,
-          hasSilentPayment: hasSilentPayment,
-          useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins,
-          coinTypeToSpendFrom: coinTypeToSpendFrom,
-        );
-      }
-
-      final estimatedSendAll = await estimateSendAllTx(
-        updatedOutputs,
-        feeRate,
+      return EstimatedTxResult(
+        utxos: utxoDetails.utxos,
+        inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos,
+        publicKeys: utxoDetails.publicKeys,
+        fee: fee,
+        amount: amount,
+        hasChange: true,
+        isSendAll: spendingAllCoins,
         memo: memo,
-        coinTypeToSpendFrom: coinTypeToSpendFrom,
-      );
-
-      if (estimatedSendAll.amount == credentialsAmount) {
-        return estimatedSendAll;
-      }
-
-      // Estimate to user how much is needed to send to cover the fee
-      final maxAmountWithReturningChange = utxoDetails.allInputsAmount - _dustAmount - fee - 1;
-      throw BitcoinTransactionNoDustOnChangeException(
-        bitcoinAmountToString(amount: maxAmountWithReturningChange),
-        bitcoinAmountToString(amount: estimatedSendAll.amount),
+        spendsUnconfirmedTX: utxoDetails.spendsUnconfirmedTX,
+        spendsSilentPayment: utxoDetails.spendsSilentPayment,
       );
     }
-
-    // Attempting to send less than the dust limit
-    if (_isBelowDust(amount)) {
-      throw BitcoinTransactionNoDustException();
-    }
-
-    final totalAmount = amount + fee;
-
-    if (totalAmount > (balance[currency]!.confirmed + balance[currency]!.secondConfirmed)) {
-      throw BitcoinTransactionWrongBalanceException();
-    }
-
-    if (totalAmount > utxoDetails.allInputsAmount) {
-      if (spendingAllCoins) {
-        throw BitcoinTransactionWrongBalanceException();
-      } else {
-        updatedOutputs.removeLast();
-        outputs.removeLast();
-        return estimateTxForAmount(
-          credentialsAmount,
-          outputs,
-          updatedOutputs,
-          feeRate,
-          inputsCount: utxoDetails.utxos.length + 1,
-          memo: memo,
-          useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins,
-          hasSilentPayment: hasSilentPayment,
-          coinTypeToSpendFrom: coinTypeToSpendFrom,
-        );
-      }
-    }
-
-    return EstimatedTxResult(
-      utxos: utxoDetails.utxos,
-      inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos,
-      publicKeys: utxoDetails.publicKeys,
-      fee: fee,
-      amount: amount,
-      hasChange: true,
-      isSendAll: false,
-      memo: memo,
-      spendsUnconfirmedTX: utxoDetails.spendsUnconfirmedTX,
-      spendsSilentPayment: utxoDetails.spendsSilentPayment,
-    );
   }
 
   Future<int> calcFee({
@@ -1080,15 +1038,20 @@ abstract class ElectrumWalletBase
           : feeRate(transactionCredentials.priority!);
 
       EstimatedTxResult estimatedTx;
-      final updatedOutputs =
-          outputs.map((e) => BitcoinOutput(address: e.address, value: e.value)).toList();
+      final updatedOutputs = outputs
+          .map((e) => BitcoinOutput(
+                address: e.address,
+                value: e.value,
+                isSilentPayment: e.isSilentPayment,
+                isChange: e.isChange,
+              ))
+          .toList();
 
       if (sendAll) {
         estimatedTx = await estimateSendAllTx(
           updatedOutputs,
           feeRateInt,
           memo: memo,
-          credentialsAmount: credentialsAmount,
           hasSilentPayment: hasSilentPayment,
           coinTypeToSpendFrom: coinTypeToSpendFrom,
         );
diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock
index 5cba9b734..0e4921a3a 100644
--- a/cw_bitcoin/pubspec.lock
+++ b/cw_bitcoin/pubspec.lock
@@ -568,10 +568,10 @@ packages:
     dependency: "direct main"
     description:
       name: ledger_flutter_plus
-      sha256: ea3ed586e1697776dacf42ac979095f1ca3bd143bf007cbe5c78e09cb6943f42
+      sha256: c7b04008553193dbca7e17b430768eecc372a72b0ff3625b5e7fc5e5c8d3231b
       url: "https://pub.dev"
     source: hosted
-    version: "1.2.5"
+    version: "1.4.1"
   ledger_litecoin:
     dependency: "direct main"
     description:

From 8e12fb1ad9c4475abb846937946fc7c9ede6daf8 Mon Sep 17 00:00:00 2001
From: Rafael <github@rafael.saes.dev>
Date: Sat, 9 Nov 2024 02:20:06 -0300
Subject: [PATCH 35/50] fix: paymentUrls is null (#1786)

* fix: paymentUrls is null

* feat: potential secure storage error
---
 lib/cake_pay/cake_pay_order.dart                            | 1 -
 lib/cake_pay/cake_pay_service.dart                          | 6 ++++--
 .../cake_pay/cards/cake_pay_confirm_purchase_card_page.dart | 6 +++++-
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/lib/cake_pay/cake_pay_order.dart b/lib/cake_pay/cake_pay_order.dart
index 8cb6e784a..acdf86ea0 100644
--- a/lib/cake_pay/cake_pay_order.dart
+++ b/lib/cake_pay/cake_pay_order.dart
@@ -1,4 +1,3 @@
-
 class CakePayOrder {
   final String orderId;
   final List<OrderCard> cards;
diff --git a/lib/cake_pay/cake_pay_service.dart b/lib/cake_pay/cake_pay_service.dart
index 39f2ca77a..cf2ec254c 100644
--- a/lib/cake_pay/cake_pay_service.dart
+++ b/lib/cake_pay/cake_pay_service.dart
@@ -82,10 +82,12 @@ class CakePayService {
   }
 
   /// Logout
-  Future<void> logout(String email) async {
+  Future<void> logout([String? email]) async {
     await secureStorage.delete(key: cakePayUsernameStorageKey);
     await secureStorage.delete(key: cakePayUserTokenKey);
-    await cakePayApi.logoutUser(email: email, apiKey: cakePayApiKey);
+    if (email != null) {
+      await cakePayApi.logoutUser(email: email, apiKey: cakePayApiKey);
+    }
   }
 
   /// Purchase Gift Card
diff --git a/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart b/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
index 81f6a354f..309c435a2 100644
--- a/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
+++ b/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
@@ -258,7 +258,11 @@ class CakePayBuyCardDetailPage extends BasePage {
     if (!isLogged) {
       Navigator.of(context).pushNamed(Routes.cakePayWelcomePage);
     } else {
-      await cakePayPurchaseViewModel.createOrder();
+      try {
+        await cakePayPurchaseViewModel.createOrder();
+      } catch (_) {
+        await cakePayPurchaseViewModel.cakePayService.logout();
+      }
     }
   }
 

From cea3084bb320dde27fbdbb78fba579311b58b704 Mon Sep 17 00:00:00 2001
From: cyan <cyjan@mrcyjanek.net>
Date: Sat, 9 Nov 2024 19:59:47 +0100
Subject: [PATCH 36/50] WIP: CW-665 Implement AirGapped Monero Transactions
 (#1535)

* replace qr scanner with fast_scanner

* bump java version

* fix qr code scanning

* add flashlight and camera switch

* airgap work

* commitTransactionUR

* bump fast_scanner, fix configure script

* add option to restore wallet from NERO qr format

* fixes to the flow and logic
use gsed or otherwise it fails?

* remove Expanded() to fix URQR on release builds

* cache key to allow app updates

* rename cache key

* [skip ci] cache key.jks in cache_dependencies

* update fast_scanner to work on ios, with light mlkit dependency

* ui fixes

* error handling fix

* update fast_scanner to drop iOS dependency

* changes from review

* Update lib/entities/qr_scanner.dart

* changes from review

* remove useless commit

* don't set state multiple times
remove return Container() for non monero wallets

* return on fail
don't handle empty qr codes

* set node as trusted
display primary address in seed screen

* fix wow and haven

* migrate node to trusted

* - update trusted node for existing users
- update locales
- fix conflicts
- move menu item

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 .github/workflows/cache_dependencies.yml      |   3 +-
 .github/workflows/pr_test_build_android.yml   |   4 +-
 android/app/build.gradle                      |   5 +
 android/gradle.properties                     |   2 +-
 assets/node_list.yml                          |   1 +
 .../lib/pending_bitcoin_transaction.dart      |   5 +
 .../src/pending_bitcoin_cash_transaction.dart |   4 +
 cw_core/lib/monero_wallet_keys.dart           |   4 +-
 cw_core/lib/pending_transaction.dart          |   3 +
 cw_evm/lib/pending_evm_chain_transaction.dart |   5 +
 .../wallet_restore_from_keys_exception.dart   |   5 +
 cw_haven/lib/haven_wallet.dart                |   1 +
 cw_haven/lib/pending_haven_transaction.dart   |   5 +
 cw_monero/lib/api/account_list.dart           |   1 +
 cw_monero/lib/api/transaction_history.dart    |  24 +-
 cw_monero/lib/api/wallet_manager.dart         |   2 +
 cw_monero/lib/monero_wallet.dart              |  32 ++
 cw_monero/lib/pending_monero_transaction.dart |  24 +-
 cw_nano/lib/pending_nano_transaction.dart     |   5 +
 cw_shared_external/pubspec.lock               | 189 +++++++++
 cw_solana/lib/pending_solana_transaction.dart |   5 +
 cw_tron/lib/pending_tron_transaction.dart     |   5 +
 .../wallet_restore_from_keys_exception.dart   |   1 +
 .../lib/pending_wownero_transaction.dart      |   5 +
 cw_wownero/lib/wownero_wallet.dart            |   1 +
 lib/di.dart                                   |   7 +
 lib/entities/default_settings_migration.dart  |  15 +-
 lib/entities/qr_scanner.dart                  | 369 +++++++++++++++++-
 lib/main.dart                                 |   2 +-
 lib/monero/cw_monero.dart                     |  24 ++
 lib/router.dart                               |   4 +
 lib/routes.dart                               |   1 +
 .../cake_pay_confirm_purchase_card_page.dart  |   4 +-
 .../dashboard/widgets/menu_widget.dart        |   4 +-
 .../exchange_trade/exchange_trade_page.dart   |   2 +-
 lib/src/screens/send/send_page.dart           |   2 +-
 .../desktop_settings_page.dart                |   7 +-
 .../transaction_details/rbf_details_page.dart |   2 +-
 lib/src/screens/ur/animated_ur_page.dart      | 184 +++++++++
 .../wc_connections_listing_view.dart          |   2 +-
 lib/src/widgets/address_text_field.dart       |   2 +-
 lib/src/widgets/setting_actions.dart          |  11 +
 lib/view_model/animated_ur_model.dart         |  10 +
 .../dashboard/dashboard_view_model.dart       |   6 +
 .../node_create_or_edit_view_model.dart       |   2 +-
 lib/view_model/restore/restore_wallet.dart    |  14 +-
 .../restore/wallet_restore_from_qr_code.dart  |  28 +-
 lib/view_model/send/send_view_model.dart      |  18 +-
 lib/view_model/wallet_keys_view_model.dart    |  12 +
 linux/flutter/generated_plugins.cmake         |   1 -
 macos/Flutter/GeneratedPluginRegistrant.swift |   4 +-
 macos/Podfile.lock                            |   6 +
 pubspec_base.yaml                             |   6 +-
 res/values/strings_ar.arb                     |  13 +-
 res/values/strings_bg.arb                     |  13 +-
 res/values/strings_cs.arb                     |  13 +-
 res/values/strings_de.arb                     |   8 +-
 res/values/strings_en.arb                     |  10 +-
 res/values/strings_es.arb                     |  13 +-
 res/values/strings_fr.arb                     |  13 +-
 res/values/strings_ha.arb                     |  13 +-
 res/values/strings_hi.arb                     |  13 +-
 res/values/strings_hr.arb                     |  13 +-
 res/values/strings_hy.arb                     |  16 +-
 res/values/strings_id.arb                     |  13 +-
 res/values/strings_it.arb                     |  13 +-
 res/values/strings_ja.arb                     |  13 +-
 res/values/strings_ko.arb                     |  13 +-
 res/values/strings_my.arb                     |  13 +-
 res/values/strings_nl.arb                     |  13 +-
 res/values/strings_pl.arb                     |  13 +-
 res/values/strings_pt.arb                     |  10 +-
 res/values/strings_ru.arb                     |  13 +-
 res/values/strings_th.arb                     |  13 +-
 res/values/strings_tl.arb                     |  10 +-
 res/values/strings_tr.arb                     |  13 +-
 res/values/strings_uk.arb                     |  13 +-
 res/values/strings_ur.arb                     |  13 +-
 res/values/strings_vi.arb                     |  16 +-
 res/values/strings_yo.arb                     |  13 +-
 res/values/strings_zh.arb                     |  13 +-
 scripts/macos/gen_common.sh                   |   4 +-
 tool/configure.dart                           |   8 +
 windows/flutter/generated_plugins.cmake       |   1 -
 84 files changed, 1318 insertions(+), 141 deletions(-)
 create mode 100644 cw_shared_external/pubspec.lock
 create mode 100644 lib/src/screens/ur/animated_ur_page.dart
 create mode 100644 lib/view_model/animated_ur_model.dart

diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml
index c0042bf5c..0fcd5c45b 100644
--- a/.github/workflows/cache_dependencies.yml
+++ b/.github/workflows/cache_dependencies.yml
@@ -62,10 +62,9 @@ jobs:
             /opt/android/cake_wallet/cw_haven/android/.cxx
             /opt/android/cake_wallet/scripts/monero_c/release
           key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
-
       - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
         name: Generate Externals
         run: |
           cd /opt/android/cake_wallet/scripts/android/
           source ./app_env.sh cakewallet
-          ./build_monero_all.sh
+          ./build_monero_all.sh
\ No newline at end of file
diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index c9021fac0..6d0e541ce 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -82,7 +82,8 @@ jobs:
           path: |
             /opt/android/cake_wallet/cw_haven/android/.cxx
             /opt/android/cake_wallet/scripts/monero_c/release
-          key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
+            /opt/android/cake_wallet/android/app/key.jks
+          key: android_${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
 
       - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
         name: Generate Externals
@@ -116,6 +117,7 @@ jobs:
           ./build_mwebd.sh --dont-install
 
       - name: Generate KeyStore
+        if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
         run: |
           cd /opt/android/cake_wallet/android/app
           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 $STORE_PASS -keypass $KEY_PASS
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 2f5427531..5005a8bab 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -92,3 +92,8 @@ dependencies {
     androidTestImplementation 'androidx.test:runner:1.3.0'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
 }
+configurations {
+    implementation.exclude module:'proto-google-common-protos'
+    implementation.exclude module:'protolite-well-known-types'
+    implementation.exclude module:'protobuf-javalite'
+}
\ No newline at end of file
diff --git a/android/gradle.properties b/android/gradle.properties
index 38c8d4544..66dd09454 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,4 +1,4 @@
-org.gradle.jvmargs=-Xmx1536M
+org.gradle.jvmargs=-Xmx3072M
 android.enableR8=true
 android.useAndroidX=true
 android.enableJetifier=true
diff --git a/assets/node_list.yml b/assets/node_list.yml
index d04a9a2e8..6191129b3 100644
--- a/assets/node_list.yml
+++ b/assets/node_list.yml
@@ -1,6 +1,7 @@
 -
   uri: xmr-node.cakewallet.com:18081
   is_default: true
+  trusted: true
 -
   uri: cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081
   is_default: false
diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
index 140965655..411c7de16 100644
--- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart
+++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
@@ -153,4 +153,9 @@ class PendingBitcoinTransaction with PendingTransaction {
       inputAddresses: _tx.inputs.map((input) => input.txId).toList(),
       outputAddresses: outputAddresses,
       fee: fee);
+      
+  @override
+  Future<String?> commitUR() {
+    throw UnimplementedError();
+  }
 }
diff --git a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart
index e1fa9d6e0..05483ce54 100644
--- a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart
+++ b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart
@@ -85,4 +85,8 @@ class PendingBitcoinCashTransaction with PendingTransaction {
       fee: fee, 
       isReplaced: false,
       );
+  @override
+  Future<String?> commitUR() {
+    throw UnimplementedError();
+  }
 }
diff --git a/cw_core/lib/monero_wallet_keys.dart b/cw_core/lib/monero_wallet_keys.dart
index 1435002a8..fe3784986 100644
--- a/cw_core/lib/monero_wallet_keys.dart
+++ b/cw_core/lib/monero_wallet_keys.dart
@@ -1,10 +1,12 @@
 class MoneroWalletKeys {
   const MoneroWalletKeys(
-      {required this.privateSpendKey,
+      {required this.primaryAddress,
+        required this.privateSpendKey,
         required this.privateViewKey,
         required this.publicSpendKey,
         required this.publicViewKey});
 
+  final String primaryAddress;
   final String publicViewKey;
   final String privateViewKey;
   final String publicSpendKey;
diff --git a/cw_core/lib/pending_transaction.dart b/cw_core/lib/pending_transaction.dart
index 0a6103a5f..78eba68a3 100644
--- a/cw_core/lib/pending_transaction.dart
+++ b/cw_core/lib/pending_transaction.dart
@@ -14,5 +14,8 @@ mixin PendingTransaction {
   int? get outputCount => null;
   PendingChange? change;
 
+  bool shouldCommitUR() => false;
+
   Future<void> commit();
+  Future<String?> commitUR();
 }
diff --git a/cw_evm/lib/pending_evm_chain_transaction.dart b/cw_evm/lib/pending_evm_chain_transaction.dart
index 0b367da68..6861b41f8 100644
--- a/cw_evm/lib/pending_evm_chain_transaction.dart
+++ b/cw_evm/lib/pending_evm_chain_transaction.dart
@@ -47,4 +47,9 @@ class PendingEVMChainTransaction with PendingTransaction {
 
     return '0x${Hex.HEX.encode(txid)}';
   }
+  
+  @override
+  Future<String?> commitUR() {
+    throw UnimplementedError();
+  }
 }
diff --git a/cw_haven/lib/api/exceptions/wallet_restore_from_keys_exception.dart b/cw_haven/lib/api/exceptions/wallet_restore_from_keys_exception.dart
index c6b6c6ef7..3ff5f2438 100644
--- a/cw_haven/lib/api/exceptions/wallet_restore_from_keys_exception.dart
+++ b/cw_haven/lib/api/exceptions/wallet_restore_from_keys_exception.dart
@@ -2,4 +2,9 @@ class WalletRestoreFromKeysException implements Exception {
   WalletRestoreFromKeysException({required this.message});
   
   final String message;
+
+  @override
+  String toString() {
+    return message;
+  }
 }
\ No newline at end of file
diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart
index 06a838100..e2e598bbe 100644
--- a/cw_haven/lib/haven_wallet.dart
+++ b/cw_haven/lib/haven_wallet.dart
@@ -73,6 +73,7 @@ abstract class HavenWalletBase
 
   @override
   MoneroWalletKeys get keys => MoneroWalletKeys(
+      primaryAddress: haven_wallet.getAddress(accountIndex: 0, addressIndex: 0),
       privateSpendKey: haven_wallet.getSecretSpendKey(),
       privateViewKey: haven_wallet.getSecretViewKey(),
       publicSpendKey: haven_wallet.getPublicSpendKey(),
diff --git a/cw_haven/lib/pending_haven_transaction.dart b/cw_haven/lib/pending_haven_transaction.dart
index 1d95de08c..dbf075044 100644
--- a/cw_haven/lib/pending_haven_transaction.dart
+++ b/cw_haven/lib/pending_haven_transaction.dart
@@ -48,4 +48,9 @@ class PendingHavenTransaction with PendingTransaction {
       rethrow;
     }
   }
+  
+  @override
+  Future<String?> commitUR() {
+    throw UnimplementedError();
+  }
 }
diff --git a/cw_monero/lib/api/account_list.dart b/cw_monero/lib/api/account_list.dart
index 7cb95a507..e3bb25c97 100644
--- a/cw_monero/lib/api/account_list.dart
+++ b/cw_monero/lib/api/account_list.dart
@@ -2,6 +2,7 @@ import 'package:cw_monero/api/wallet.dart';
 import 'package:monero/monero.dart' as monero;
 
 monero.wallet? wptr = null;
+bool get isViewOnly => int.tryParse(monero.Wallet_secretSpendKey(wptr!)) == 0;
 
 int _wlptrForW = 0;
 monero.WalletListener? _wlptr = null;
diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart
index a308b682e..7748a16af 100644
--- a/cw_monero/lib/api/transaction_history.dart
+++ b/cw_monero/lib/api/transaction_history.dart
@@ -13,7 +13,13 @@ import 'package:mutex/mutex.dart';
 
 
 String getTxKey(String txId) {
-  return monero.Wallet_getTxKey(wptr!, txid: txId);
+  final txKey = monero.Wallet_getTxKey(wptr!, txid: txId);
+  final status = monero.Wallet_status(wptr!);
+  if (status != 0) {
+    final error = monero.Wallet_errorString(wptr!);
+    return txId+"_"+error;
+  }
+  return txKey;
 }
 final txHistoryMutex = Mutex();
 monero.TransactionHistory? txhistory;
@@ -178,12 +184,13 @@ PendingTransactionDescription createTransactionMultDestSync(
   );
 }
 
-void commitTransactionFromPointerAddress({required int address}) =>
-    commitTransaction(transactionPointer: monero.PendingTransaction.fromAddress(address));
+String? commitTransactionFromPointerAddress({required int address, required bool useUR}) =>
+    commitTransaction(transactionPointer: monero.PendingTransaction.fromAddress(address), useUR: useUR);
 
-void commitTransaction({required monero.PendingTransaction transactionPointer}) {
-  
-  final txCommit = monero.PendingTransaction_commit(transactionPointer, filename: '', overwrite: false);
+String? commitTransaction({required monero.PendingTransaction transactionPointer, required bool useUR}) {
+  final txCommit = useUR
+    ? monero.PendingTransaction_commitUR(transactionPointer, 120)
+    : monero.PendingTransaction_commit(transactionPointer, filename: '', overwrite: false);
 
   final String? error = (() {
     final status = monero.PendingTransaction_status(transactionPointer.cast());
@@ -196,6 +203,11 @@ void commitTransaction({required monero.PendingTransaction transactionPointer})
   if (error != null) {
     throw CreationTransactionException(message: error);
   }
+  if (useUR) {
+    return txCommit as String?;
+  } else {
+    return null;
+  }
 }
 
 Future<PendingTransactionDescription> _createTransactionSync(Map args) async {
diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart
index dca7586fb..61fd6edf0 100644
--- a/cw_monero/lib/api/wallet_manager.dart
+++ b/cw_monero/lib/api/wallet_manager.dart
@@ -425,3 +425,5 @@ Future<void> restoreFromSpendKey(
     });
 
 bool isWalletExist({required String path}) => _isWalletExist(path);
+
+bool isViewOnlyBySpendKey() => int.tryParse(monero.Wallet_secretSpendKey(wptr!)) == 0;
\ No newline at end of file
diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart
index 0ae2202ba..bc8c3c94d 100644
--- a/cw_monero/lib/monero_wallet.dart
+++ b/cw_monero/lib/monero_wallet.dart
@@ -19,6 +19,7 @@ import 'package:cw_core/transaction_direction.dart';
 import 'package:cw_core/unspent_coins_info.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_info.dart';
+import 'package:cw_monero/api/account_list.dart';
 import 'package:cw_monero/api/coins_info.dart';
 import 'package:cw_monero/api/monero_output.dart';
 import 'package:cw_monero/api/structs/pending_transaction.dart';
@@ -121,6 +122,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
 
   @override
   MoneroWalletKeys get keys => MoneroWalletKeys(
+      primaryAddress: monero_wallet.getAddress(accountIndex: 0, addressIndex: 0),
       privateSpendKey: monero_wallet.getSecretSpendKey(),
       privateViewKey: monero_wallet.getSecretViewKey(),
       publicSpendKey: monero_wallet.getPublicSpendKey(),
@@ -230,6 +232,36 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
     }
   }
 
+  Future<bool> submitTransactionUR(String ur) async {
+    final retStatus = monero.Wallet_submitTransactionUR(wptr!, ur);
+    final status = monero.Wallet_status(wptr!);
+    if (status != 0) {
+      final err = monero.Wallet_errorString(wptr!);
+      throw MoneroTransactionCreationException("unable to broadcast signed transaction: $err");
+    }
+    return retStatus;
+  }
+
+  bool importKeyImagesUR(String ur) {
+    final retStatus = monero.Wallet_importKeyImagesUR(wptr!, ur);
+    final status = monero.Wallet_status(wptr!);
+    if (status != 0) {
+      final err = monero.Wallet_errorString(wptr!);
+      throw Exception("unable to import key images: $err");
+    }
+    return retStatus;
+  }
+
+  String exportOutputsUR(bool all) {
+    final str = monero.Wallet_exportOutputsUR(wptr!, all: all);
+    final status = monero.Wallet_status(wptr!);
+    if (status != 0) {
+      final err = monero.Wallet_errorString(wptr!);
+      throw MoneroTransactionCreationException("unable to export UR: $err");
+    }
+    return str;
+  }
+
   @override
   Future<PendingTransaction> createTransaction(Object credentials) async {
     final _credentials = credentials as MoneroTransactionCreationCredentials;
diff --git a/cw_monero/lib/pending_monero_transaction.dart b/cw_monero/lib/pending_monero_transaction.dart
index 2a75fc26b..eb714eeb3 100644
--- a/cw_monero/lib/pending_monero_transaction.dart
+++ b/cw_monero/lib/pending_monero_transaction.dart
@@ -1,3 +1,4 @@
+import 'package:cw_monero/api/account_list.dart';
 import 'package:cw_monero/api/structs/pending_transaction.dart';
 import 'package:cw_monero/api/transaction_history.dart'
     as monero_transaction_history;
@@ -35,11 +36,32 @@ class PendingMoneroTransaction with PendingTransaction {
   String get feeFormatted => AmountConverter.amountIntToString(
       CryptoCurrency.xmr, pendingTransactionDescription.fee);
 
+  bool shouldCommitUR() => isViewOnly;
+
   @override
   Future<void> commit() async {
     try {
       monero_transaction_history.commitTransactionFromPointerAddress(
-          address: pendingTransactionDescription.pointerAddress);
+          address: pendingTransactionDescription.pointerAddress,
+          useUR: false);
+    } catch (e) {
+      final message = e.toString();
+
+      if (message.contains('Reason: double spend')) {
+        throw DoubleSpendException();
+      }
+
+      rethrow;
+    }
+  }
+
+  @override
+  Future<String?> commitUR() async {
+    try {
+      final ret = monero_transaction_history.commitTransactionFromPointerAddress(
+          address: pendingTransactionDescription.pointerAddress,
+          useUR: true);
+      return ret;
     } catch (e) {
       final message = e.toString();
 
diff --git a/cw_nano/lib/pending_nano_transaction.dart b/cw_nano/lib/pending_nano_transaction.dart
index a027100fd..51a4ef6c1 100644
--- a/cw_nano/lib/pending_nano_transaction.dart
+++ b/cw_nano/lib/pending_nano_transaction.dart
@@ -37,4 +37,9 @@ class PendingNanoTransaction with PendingTransaction {
       await nanoClient.processBlock(block, "send");
     }
   }
+  
+  @override
+  Future<String?> commitUR() {
+    throw UnimplementedError();
+  }
 }
diff --git a/cw_shared_external/pubspec.lock b/cw_shared_external/pubspec.lock
new file mode 100644
index 000000000..203ecd5c3
--- /dev/null
+++ b/cw_shared_external/pubspec.lock
@@ -0,0 +1,189 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+  async:
+    dependency: transitive
+    description:
+      name: async
+      sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.11.0"
+  boolean_selector:
+    dependency: transitive
+    description:
+      name: boolean_selector
+      sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
+  characters:
+    dependency: transitive
+    description:
+      name: characters
+      sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.3.0"
+  clock:
+    dependency: transitive
+    description:
+      name: clock
+      sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.1"
+  collection:
+    dependency: transitive
+    description:
+      name: collection
+      sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.18.0"
+  fake_async:
+    dependency: transitive
+    description:
+      name: fake_async
+      sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.3.1"
+  flutter:
+    dependency: "direct main"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  flutter_test:
+    dependency: "direct dev"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  leak_tracker:
+    dependency: transitive
+    description:
+      name: leak_tracker
+      sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
+      url: "https://pub.dev"
+    source: hosted
+    version: "10.0.4"
+  leak_tracker_flutter_testing:
+    dependency: transitive
+    description:
+      name: leak_tracker_flutter_testing
+      sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.3"
+  leak_tracker_testing:
+    dependency: transitive
+    description:
+      name: leak_tracker_testing
+      sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.1"
+  matcher:
+    dependency: transitive
+    description:
+      name: matcher
+      sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.12.16+1"
+  material_color_utilities:
+    dependency: transitive
+    description:
+      name: material_color_utilities
+      sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.8.0"
+  meta:
+    dependency: transitive
+    description:
+      name: meta
+      sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.12.0"
+  path:
+    dependency: transitive
+    description:
+      name: path
+      sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.9.0"
+  sky_engine:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.99"
+  source_span:
+    dependency: transitive
+    description:
+      name: source_span
+      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.10.0"
+  stack_trace:
+    dependency: transitive
+    description:
+      name: stack_trace
+      sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.11.1"
+  stream_channel:
+    dependency: transitive
+    description:
+      name: stream_channel
+      sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.2"
+  string_scanner:
+    dependency: transitive
+    description:
+      name: string_scanner
+      sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.0"
+  term_glyph:
+    dependency: transitive
+    description:
+      name: term_glyph
+      sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.1"
+  test_api:
+    dependency: transitive
+    description:
+      name: test_api
+      sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.7.0"
+  vector_math:
+    dependency: transitive
+    description:
+      name: vector_math
+      sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.4"
+  vm_service:
+    dependency: transitive
+    description:
+      name: vm_service
+      sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
+      url: "https://pub.dev"
+    source: hosted
+    version: "14.2.1"
+sdks:
+  dart: ">=3.3.0 <4.0.0"
+  flutter: ">=3.18.0-18.0.pre.54"
diff --git a/cw_solana/lib/pending_solana_transaction.dart b/cw_solana/lib/pending_solana_transaction.dart
index 38347ed13..e01446000 100644
--- a/cw_solana/lib/pending_solana_transaction.dart
+++ b/cw_solana/lib/pending_solana_transaction.dart
@@ -40,4 +40,9 @@ class PendingSolanaTransaction with PendingTransaction {
 
   @override
   String get id => '';
+  
+  @override
+  Future<String?> commitUR() {
+    throw UnimplementedError();
+  }
 }
diff --git a/cw_tron/lib/pending_tron_transaction.dart b/cw_tron/lib/pending_tron_transaction.dart
index b6d064b31..2420f083b 100644
--- a/cw_tron/lib/pending_tron_transaction.dart
+++ b/cw_tron/lib/pending_tron_transaction.dart
@@ -30,4 +30,9 @@ class PendingTronTransaction with PendingTransaction {
 
   @override
   String get id => '';
+  
+  @override
+  Future<String?> commitUR() {
+    throw UnimplementedError();
+  }
 }
diff --git a/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart b/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart
index ad576faa2..6c461ee4c 100644
--- a/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart
+++ b/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart
@@ -3,5 +3,6 @@ class WalletRestoreFromKeysException implements Exception {
   
   final String message;
 
+  @override
   String toString() => message;
 }
\ No newline at end of file
diff --git a/cw_wownero/lib/pending_wownero_transaction.dart b/cw_wownero/lib/pending_wownero_transaction.dart
index 1fc1805eb..967f63756 100644
--- a/cw_wownero/lib/pending_wownero_transaction.dart
+++ b/cw_wownero/lib/pending_wownero_transaction.dart
@@ -50,4 +50,9 @@ class PendingWowneroTransaction with PendingTransaction {
       rethrow;
     }
   }
+  
+  @override
+  Future<String?> commitUR() {
+    throw UnimplementedError();
+  }
 }
diff --git a/cw_wownero/lib/wownero_wallet.dart b/cw_wownero/lib/wownero_wallet.dart
index 331957d67..5927d6434 100644
--- a/cw_wownero/lib/wownero_wallet.dart
+++ b/cw_wownero/lib/wownero_wallet.dart
@@ -120,6 +120,7 @@ abstract class WowneroWalletBase
 
   @override
   MoneroWalletKeys get keys => MoneroWalletKeys(
+      primaryAddress: wownero_wallet.getAddress(accountIndex: 0, addressIndex: 0),
       privateSpendKey: wownero_wallet.getSecretSpendKey(),
       privateViewKey: wownero_wallet.getSecretViewKey(),
       publicSpendKey: wownero_wallet.getPublicSpendKey(),
diff --git a/lib/di.dart b/lib/di.dart
index 540a546fd..9cff29798 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -125,6 +125,7 @@ import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.d
 import 'package:cake_wallet/src/screens/support/support_page.dart';
 import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart';
 import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart';
+import 'package:cake_wallet/src/screens/ur/animated_ur_page.dart';
 import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart';
 import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart';
 import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart';
@@ -134,6 +135,7 @@ import 'package:cake_wallet/utils/device_info.dart';
 import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart';
 import 'package:cake_wallet/utils/payment_request.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
+import 'package:cake_wallet/view_model/animated_ur_model.dart';
 import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart';
 import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
 import 'package:cake_wallet/view_model/anonpay_details_view_model.dart';
@@ -903,6 +905,11 @@ Future<void> setup({
   getIt.registerFactory(() => WalletKeysViewModel(getIt.get<AppStore>()));
 
   getIt.registerFactory(() => WalletKeysPage(getIt.get<WalletKeysViewModel>()));
+  
+  getIt.registerFactory(() => AnimatedURModel(getIt.get<AppStore>()));
+
+  getIt.registerFactoryParam<AnimatedURPage, String, void>((String urQr, _) =>
+    AnimatedURPage(getIt.get<AnimatedURModel>(), urQr: urQr));
 
   getIt.registerFactoryParam<ContactViewModel, ContactRecord?, void>(
       (ContactRecord? contact, _) => ContactViewModel(_contactSource, contact: contact));
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index af6f1ce78..d863b136e 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -259,6 +259,10 @@ Future<void> defaultSettingsMigration(
         case 42:
           updateBtcElectrumNodeToUseSSL(nodes, sharedPreferences);
           break;
+        case 43:
+          _updateCakeXmrNode(nodes);
+          break;
+
         default:
           break;
       }
@@ -273,6 +277,15 @@ Future<void> defaultSettingsMigration(
   await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
 }
 
+void _updateCakeXmrNode(Box<Node> nodes) {
+  final node = nodes.values.firstWhereOrNull((element) => element.uriRaw == newCakeWalletMoneroUri);
+
+  if (node != null && !node.trusted) {
+    node.trusted = true;
+    node.save();
+  }
+}
+
 void updateBtcElectrumNodeToUseSSL(Box<Node> nodes, SharedPreferences sharedPreferences) {
   final btcElectrumNode = nodes.values.firstWhereOrNull((element) => element.uriRaw == newCakeWalletBitcoinUri);
 
@@ -843,7 +856,7 @@ Future<void> changeDefaultMoneroNode(
     }
   });
 
-  final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
+  final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero, trusted: true);
 
   await nodeSource.add(newCakeWalletNode);
 
diff --git a/lib/entities/qr_scanner.dart b/lib/entities/qr_scanner.dart
index c6873a5bc..2e2637566 100644
--- a/lib/entities/qr_scanner.dart
+++ b/lib/entities/qr_scanner.dart
@@ -1,15 +1,376 @@
-import 'package:barcode_scan2/barcode_scan2.dart';
+import 'dart:math';
+
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/main.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/utils/show_pop_up.dart';
+import 'package:fast_scanner/fast_scanner.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/scheduler.dart';
 
 var isQrScannerShown = false;
 
-Future<String> presentQRScanner() async {
+Future<String> presentQRScanner(BuildContext context) async {
   isQrScannerShown = true;
   try {
-    final result = await BarcodeScanner.scan();
+    final result = await Navigator.of(context).push<String>(
+      MaterialPageRoute(
+        builder:(context) {
+          return BarcodeScannerSimple();
+        },
+      ),
+    );
     isQrScannerShown = false;
-    return result.rawContent.trim();
+    return result??'';
   } catch (e) {
     isQrScannerShown = false;
     rethrow;
   }
 }
+
+// https://github.com/MrCyjaneK/fast_scanner/blob/master/example/lib/barcode_scanner_simple.dart
+class BarcodeScannerSimple extends StatefulWidget {
+  const BarcodeScannerSimple({super.key});
+
+  @override
+  State<BarcodeScannerSimple> createState() => _BarcodeScannerSimpleState();
+}
+
+class _BarcodeScannerSimpleState extends State<BarcodeScannerSimple> {
+  Barcode? _barcode;
+  bool popped = false;
+
+  List<String> urCodes = [];
+  late var ur = URQRToURQRData(urCodes);
+
+  void _handleBarcode(BarcodeCapture barcodes) {
+    try {
+      _handleBarcodeInternal(barcodes);
+    } catch (e) {
+      showPopUp<void>(
+        context: context,
+        builder: (context) {
+          return AlertWithOneAction(
+            alertTitle: S.of(context).error,
+            alertContent: S.of(context).error_dialog_content,
+            buttonText: 'ok',
+            buttonAction: () {
+              Navigator.of(context).pop();
+            },
+          );
+        },
+      );
+      print(e);
+    }
+  }
+
+  void _handleBarcodeInternal(BarcodeCapture barcodes) {
+    for (final barcode in barcodes.barcodes) {
+      // don't handle unknown QR codes
+      if (barcode.rawValue?.trim().isEmpty??false == false) continue;
+      if (barcode.rawValue!.startsWith("ur:")) {
+        if (urCodes.contains(barcode.rawValue)) continue;
+        setState(() {
+          urCodes.add(barcode.rawValue!);
+          ur = URQRToURQRData(urCodes);
+        });
+        if (ur.progress == 1) {
+          setState(() {
+            popped = true;
+          });
+          SchedulerBinding.instance.addPostFrameCallback((_) {
+            Navigator.of(context).pop(ur.inputs.join("\n"));
+          });
+        };
+      }
+    }
+    if (urCodes.isNotEmpty) return;
+    if (mounted) {
+      setState(() {
+        _barcode = barcodes.barcodes.firstOrNull;
+      });
+      if (_barcode != null && popped != true) {
+        setState(() {
+          popped = true;
+        });
+        SchedulerBinding.instance.addPostFrameCallback((_) {
+          Navigator.of(context).pop(_barcode?.rawValue ?? "");
+        });
+      }
+    }
+  }
+
+  final MobileScannerController ctrl = MobileScannerController();
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: const Text('Scan'),
+        actions: [
+          SwitchCameraButton(controller: ctrl),
+          ToggleFlashlightButton(controller: ctrl),
+        ],
+      ),
+      backgroundColor: Colors.black,
+      body: Stack(
+        children: [
+          MobileScanner(
+            onDetect: _handleBarcode,
+            controller: ctrl,
+          ),
+          if (ur.inputs.length != 0) 
+            Center(child:
+              Text(
+                "${ur.inputs.length}/${ur.count}",
+                style: Theme.of(context).textTheme.displayLarge?.copyWith(color: Colors.white)
+              ),
+            ),
+          SizedBox(
+            child: Center(
+              child: SizedBox(
+                width: 250,
+                height: 250,
+                child: CustomPaint(
+                  painter: ProgressPainter(
+                    urQrProgress: URQrProgress(
+                      expectedPartCount: ur.count - 1,
+                      processedPartsCount: ur.inputs.length,
+                      receivedPartIndexes: _urParts(),
+                      percentage: ur.progress,
+                    ),
+                  ),
+                ),
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+
+  List<int> _urParts() {
+    List<int> l = [];
+    for (var inp in ur.inputs) {
+      try {
+        l.add(int.parse(inp.split("/")[1].split("-")[0]));
+      } catch (e) {}
+    }
+    return l;
+  }
+}
+
+
+class ToggleFlashlightButton extends StatelessWidget {
+  const ToggleFlashlightButton({required this.controller, super.key});
+
+  final MobileScannerController controller;
+
+  @override
+  Widget build(BuildContext context) {
+    return ValueListenableBuilder(
+      valueListenable: controller,
+      builder: (context, state, child) {
+        if (!state.isInitialized || !state.isRunning) {
+          return const SizedBox.shrink();
+        }
+
+        switch (state.torchState) {
+          case TorchState.auto:
+            return IconButton(
+              iconSize: 32.0,
+              icon: const Icon(Icons.flash_auto),
+              onPressed: () async {
+                await controller.toggleTorch();
+              },
+            );
+          case TorchState.off:
+            return IconButton(
+              iconSize: 32.0,
+              icon: const Icon(Icons.flash_off),
+              onPressed: () async {
+                await controller.toggleTorch();
+              },
+            );
+          case TorchState.on:
+            return IconButton(
+              iconSize: 32.0,
+              icon: const Icon(Icons.flash_on),
+              onPressed: () async {
+                await controller.toggleTorch();
+              },
+            );
+          case TorchState.unavailable:
+            return const Icon(
+              Icons.no_flash,
+              color: Colors.grey,
+            );
+        }
+      },
+    );
+  }
+}
+
+class SwitchCameraButton extends StatelessWidget {
+  const SwitchCameraButton({required this.controller, super.key});
+
+  final MobileScannerController controller;
+
+  @override
+  Widget build(BuildContext context) {
+    return ValueListenableBuilder(
+      valueListenable: controller,
+      builder: (context, state, child) {
+        if (!state.isInitialized || !state.isRunning) {
+          return const SizedBox.shrink();
+        }
+
+        final int? availableCameras = state.availableCameras;
+
+        if (availableCameras != null && availableCameras < 2) {
+          return const SizedBox.shrink();
+        }
+
+        final Widget icon;
+
+        switch (state.cameraDirection) {
+          case CameraFacing.front:
+            icon = const Icon(Icons.camera_front);
+          case CameraFacing.back:
+            icon = const Icon(Icons.camera_rear);
+        }
+
+        return IconButton(
+          iconSize: 32.0,
+          icon: icon,
+          onPressed: () async {
+            await controller.switchCamera();
+          },
+        );
+      },
+    );
+  }
+}
+
+class URQRData {
+  URQRData(
+      {required this.tag,
+      required this.str,
+      required this.progress,
+      required this.count,
+      required this.error,
+      required this.inputs});
+  final String tag;
+  final String str;
+  final double progress;
+  final int count;
+  final String error;
+  final List<String> inputs;
+  Map<String, dynamic> toJson() {
+    return {
+      "tag": tag,
+      "str": str,
+      "progress": progress,
+      "count": count,
+      "error": error,
+      "inputs": inputs,
+    };
+  }
+}
+
+URQRData URQRToURQRData(List<String> urqr_) {
+  final urqr = urqr_.toSet().toList();
+  urqr.sort((s1, s2) {
+    final s1s = s1.split("/");
+    final s1frameStr = s1s[1].split("-");
+    final s1curFrame = int.parse(s1frameStr[0]);
+    final s2s = s2.split("/");
+    final s2frameStr = s2s[1].split("-");
+    final s2curFrame = int.parse(s2frameStr[0]);
+    return s1curFrame - s2curFrame;
+  });
+
+  String tag = '';
+  int count = 0;
+  String bw = '';
+  for (var elm in urqr) {
+    final s = elm.substring(elm.indexOf(":") + 1); // strip down ur: prefix
+    final s2 = s.split("/");
+    tag = s2[0];
+    final frameStr = s2[1].split("-");
+    // final curFrame = int.parse(frameStr[0]);
+    count = int.parse(frameStr[1]);
+    final byteWords = s2[2];
+    bw += byteWords;
+  }
+  String? error;
+
+  return URQRData(
+    tag: tag,
+    str: bw,
+    progress: count == 0 ? 0 : (urqr.length / count),
+    count: count,
+    error: error ?? "",
+    inputs: urqr,
+  );
+}
+
+class ProgressPainter extends CustomPainter {
+  final URQrProgress urQrProgress;
+
+  ProgressPainter({required this.urQrProgress});
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    final c = Offset(size.width / 2.0, size.height / 2.0);
+    final radius = size.width * 0.9;
+    final rect = Rect.fromCenter(center: c, width: radius, height: radius);
+    const fullAngle = 360.0;
+    var startAngle = 0.0;
+    for (int i = 0; i < urQrProgress.expectedPartCount.toInt(); i++) {
+      var sweepAngle =
+          (1 / urQrProgress.expectedPartCount) * fullAngle * pi / 180.0;
+      drawSector(canvas, urQrProgress.receivedPartIndexes.contains(i), rect,
+          startAngle, sweepAngle);
+      startAngle += sweepAngle;
+    }
+  }
+
+  void drawSector(Canvas canvas, bool isActive, Rect rect, double startAngle,
+      double sweepAngle) {
+    final paint = Paint()
+      ..style = PaintingStyle.stroke
+      ..strokeWidth = 8
+      ..strokeCap = StrokeCap.round
+      ..strokeJoin = StrokeJoin.round
+      ..color = isActive ? const Color(0xffff6600) : Colors.white70;
+    canvas.drawArc(rect, startAngle, sweepAngle, false, paint);
+  }
+
+  @override
+  bool shouldRepaint(covariant ProgressPainter oldDelegate) {
+    return urQrProgress != oldDelegate.urQrProgress;
+  }
+}
+
+class URQrProgress {
+  int expectedPartCount;
+  int processedPartsCount;
+  List<int> receivedPartIndexes;
+  double percentage;
+
+  URQrProgress({
+    required this.expectedPartCount,
+    required this.processedPartsCount,
+    required this.receivedPartIndexes,
+    required this.percentage,
+  });
+
+  bool equals(URQrProgress? progress) {
+    if (progress == null) {
+      return false;
+    }
+    return processedPartsCount == progress.processedPartsCount;
+  }
+}
diff --git a/lib/main.dart b/lib/main.dart
index 29b216b22..51fab4dd1 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -204,7 +204,7 @@ Future<void> initializeAppConfigs() async {
     transactionDescriptions: transactionDescriptions,
     secureStorage: secureStorage,
     anonpayInvoiceInfo: anonpayInvoiceInfo,
-    initialMigrationVersion: 42,
+    initialMigrationVersion: 43,
   );
 }
 
diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart
index b1cf49482..dfda4d600 100644
--- a/lib/monero/cw_monero.dart
+++ b/lib/monero/cw_monero.dart
@@ -248,6 +248,7 @@ class CWMonero extends Monero {
     final moneroWallet = wallet as MoneroWallet;
     final keys = moneroWallet.keys;
     return <String, String>{
+      'primaryAddress': keys.primaryAddress,
       'privateSpendKey': keys.privateSpendKey,
       'privateViewKey': keys.privateViewKey,
       'publicSpendKey': keys.publicSpendKey,
@@ -357,9 +358,32 @@ class CWMonero extends Monero {
   Future<int> getCurrentHeight() async {
     return monero_wallet_api.getCurrentHeight();
   }
+  
+  @override
+  bool importKeyImagesUR(Object wallet, String ur) {
+    final moneroWallet = wallet as MoneroWallet;
+    return moneroWallet.importKeyImagesUR(ur);
+  }
+
+
+  @override
+  Future<bool> commitTransactionUR(Object wallet, String ur) {
+    final moneroWallet = wallet as MoneroWallet;
+    return moneroWallet.submitTransactionUR(ur);
+  }
+
+  @override
+  String exportOutputsUR(Object wallet, bool all) {
+    final moneroWallet = wallet as MoneroWallet;
+    return moneroWallet.exportOutputsUR(all);
+  }
 
   @override
   void monerocCheck() {
     checkIfMoneroCIsFine();
   }
+
+  bool isViewOnly() {
+    return isViewOnlyBySpendKey();
+  }
 }
diff --git a/lib/router.dart b/lib/router.dart
index 6c234ff80..4b99aabc0 100644
--- a/lib/router.dart
+++ b/lib/router.dart
@@ -96,6 +96,7 @@ import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dar
 import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart';
 import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart';
 import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart';
+import 'package:cake_wallet/src/screens/ur/animated_ur_page.dart';
 import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart';
 import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart';
 import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
@@ -732,6 +733,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
     case Routes.setup2faInfoPage:
       return MaterialPageRoute<void>(builder: (_) => getIt.get<Setup2FAInfoPage>());
 
+    case Routes.urqrAnimatedPage:
+      return MaterialPageRoute<void>(builder: (_) => getIt.get<AnimatedURPage>(param1: settings.arguments));
+
     case Routes.homeSettings:
       return CupertinoPageRoute<void>(
         builder: (_) => getIt.get<HomeSettingsPage>(param1: settings.arguments),
diff --git a/lib/routes.dart b/lib/routes.dart
index 5f11b11a3..63c41bde5 100644
--- a/lib/routes.dart
+++ b/lib/routes.dart
@@ -108,6 +108,7 @@ class Routes {
 
   static const signPage = '/sign_page';
   static const connectDevices = '/device/connect';
+  static const urqrAnimatedPage = '/urqr/animated_page';
   static const walletGroupsDisplayPage = '/wallet_groups_display_page';
   static const walletGroupDescription = '/wallet_group_description';
 }
diff --git a/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart b/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
index 309c435a2..9357df2c3 100644
--- a/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
+++ b/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
@@ -347,8 +347,8 @@ class CakePayBuyCardDetailPage extends BasePage {
                 rightButtonText: S.of(popupContext).send,
                 leftButtonText: S.of(popupContext).cancel,
                 actionRightButton: () async {
-                  Navigator.of(popupContext).pop();
-                  await cakePayPurchaseViewModel.sendViewModel.commitTransaction();
+                  Navigator.of(context).pop();
+                  await cakePayPurchaseViewModel.sendViewModel.commitTransaction(context);
                 },
                 actionLeftButton: () => Navigator.of(popupContext).pop()));
       },
diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart
index f0e330f04..b49a08584 100644
--- a/lib/src/screens/dashboard/widgets/menu_widget.dart
+++ b/lib/src/screens/dashboard/widgets/menu_widget.dart
@@ -101,6 +101,9 @@ class MenuWidgetState extends State<MenuWidget> {
     if (!widget.dashboardViewModel.hasSilentPayments) {
       items.removeWhere((element) => element.name(context) == S.of(context).silent_payments_settings);
     }
+    if (!widget.dashboardViewModel.isMoneroViewOnly) {
+      items.removeWhere((element) => element.name(context) == S.of(context).export_outputs);
+    }
     if (!widget.dashboardViewModel.hasMweb) {
       items.removeWhere((element) => element.name(context) == S.of(context).litecoin_mweb_settings);
     }
@@ -189,7 +192,6 @@ class MenuWidgetState extends State<MenuWidget> {
                   index--;
 
                   final item = items[index];
-
                   final isLastTile = index == itemCount - 1;
 
                   return SettingActionButton(
diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart
index 0f3cc7bd9..130ffa6b0 100644
--- a/lib/src/screens/exchange_trade/exchange_trade_page.dart
+++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart
@@ -277,7 +277,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
                     actionRightButton: () async {
                       Navigator.of(popupContext).pop();
                       await widget.exchangeTradeViewModel.sendViewModel
-                          .commitTransaction();
+                          .commitTransaction(context);
                       transactionStatePopup();
                     },
                     actionLeftButton: () => Navigator.of(popupContext).pop(),
diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart
index bce82312d..7003ceafb 100644
--- a/lib/src/screens/send/send_page.dart
+++ b/lib/src/screens/send/send_page.dart
@@ -498,7 +498,7 @@ class SendPage extends BasePage {
                           ValueKey('send_page_confirm_sending_dialog_cancel_button_key'),
                       actionRightButton: () async {
                         Navigator.of(_dialogContext).pop();
-                        sendViewModel.commitTransaction();
+                        sendViewModel.commitTransaction(context);
                         await showPopUp<void>(
                             context: context,
                             builder: (BuildContext _dialogContext) {
diff --git a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart
index 79f74065a..6f7afe2ff 100644
--- a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart
+++ b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart
@@ -4,6 +4,7 @@ import 'package:cake_wallet/src/widgets/setting_action_button.dart';
 import 'package:cake_wallet/src/widgets/setting_actions.dart';
 import 'package:cake_wallet/typography.dart';
 import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
+import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/material.dart';
 import 'package:cake_wallet/router.dart' as Router;
 import 'package:cake_wallet/themes/extensions/menu_theme.dart';
@@ -60,8 +61,10 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
                           return Container();
                         }
 
-                        if (!widget.dashboardViewModel.hasMweb &&
-                            item.name(context) == S.of(context).litecoin_mweb_settings) {
+                        if ((!widget.dashboardViewModel.isMoneroViewOnly &&
+                            item.name(context) == S.of(context).export_outputs) ||
+                           (!widget.dashboardViewModel.hasMweb &&
+                            item.name(context) == S.of(context).litecoin_mweb_settings)) {
                           return Container();
                         }
 
diff --git a/lib/src/screens/transaction_details/rbf_details_page.dart b/lib/src/screens/transaction_details/rbf_details_page.dart
index b117a0b68..2c5edd8b4 100644
--- a/lib/src/screens/transaction_details/rbf_details_page.dart
+++ b/lib/src/screens/transaction_details/rbf_details_page.dart
@@ -168,7 +168,7 @@ class RBFDetailsPage extends BasePage {
                     leftButtonText: S.of(popupContext).cancel,
                     actionRightButton: () async {
                       Navigator.of(popupContext).pop();
-                      await transactionDetailsViewModel.sendViewModel.commitTransaction();
+                      await transactionDetailsViewModel.sendViewModel.commitTransaction(context);
                       try {
                         Navigator.of(popupContext).pop();
                       } catch (_) {}
diff --git a/lib/src/screens/ur/animated_ur_page.dart b/lib/src/screens/ur/animated_ur_page.dart
new file mode 100644
index 000000000..dc40e6a12
--- /dev/null
+++ b/lib/src/screens/ur/animated_ur_page.dart
@@ -0,0 +1,184 @@
+import 'dart:async';
+
+import 'package:cake_wallet/di.dart';
+import 'package:cake_wallet/entities/qr_scanner.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/monero/monero.dart';
+import 'package:cake_wallet/src/screens/base_page.dart';
+import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
+import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
+import 'package:cake_wallet/src/widgets/primary_button.dart';
+import 'package:cake_wallet/utils/show_pop_up.dart';
+import 'package:cake_wallet/view_model/animated_ur_model.dart';
+import 'package:cake_wallet/view_model/dashboard/wallet_balance.dart';
+import 'package:cw_core/balance.dart';
+import 'package:cw_core/transaction_history.dart';
+import 'package:cw_core/transaction_info.dart';
+import 'package:cw_core/wallet_base.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+
+// ur:xmr-txunsigned - unsigned transaction
+//     should show a scanner afterwards.
+
+class AnimatedURPage extends BasePage {
+  final bool isAll;
+  AnimatedURPage(this.animatedURmodel, {required String urQr, this.isAll = false}) {
+    if (urQr == "export-outputs") {
+      this.urQr = monero!.exportOutputsUR(animatedURmodel.wallet, false);
+    } else if (urQr == "export-outputs-all") {
+      this.urQr = monero!.exportOutputsUR(animatedURmodel.wallet, true);
+    } else {
+      this.urQr = urQr;
+    }
+  }
+
+  late String urQr;
+
+  final AnimatedURModel animatedURmodel;
+
+  String get urQrType {
+    final first = urQr.trim().split("\n")[0];
+    return first.split('/')[0];
+  }
+
+  @override
+  Widget body(BuildContext context) {
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        Padding(
+          padding: const EdgeInsets.only(top: 64.0),
+          child: URQR(
+            frames: urQr.trim().split("\n"),
+          ),
+        ),
+        SizedBox(height: 32),
+        if (urQrType == "ur:xmr-txunsigned" || urQrType == "ur:xmr-output")
+          Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 16.0),
+            child: SizedBox(
+              width: double.maxFinite,
+              child: PrimaryButton(
+                onPressed: () => _continue(context),
+                text: "Continue",
+                color: Theme.of(context).primaryColor,
+                textColor: Colors.white,
+              ),
+            ),
+          ),
+        SizedBox(height: 32),
+        if (urQrType == "ur:xmr-output" && !isAll) Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 16.0),
+            child: SizedBox(
+              width: double.maxFinite,
+              child: PrimaryButton(
+                onPressed: () => _exportAll(context),
+                text: "Export all",
+                color: Theme.of(context).colorScheme.secondary,
+                textColor: Colors.white,
+              ),
+            ),
+          ),
+      ],
+    );
+  }
+
+  void _exportAll(BuildContext context) {
+    Navigator.of(context).pushReplacement(
+      MaterialPageRoute(
+        builder: (context) {
+          return AnimatedURPage(animatedURmodel, urQr: "export-outputs-all", isAll: true);
+        },
+      ),
+    );
+  }
+
+  Future<void> _continue(BuildContext context) async {
+    try {
+    switch (urQrType) {
+      case "ur:xmr-txunsigned": // ur:xmr-txsigned
+        final ur = await presentQRScanner(context);
+        final result = await monero!.commitTransactionUR(animatedURmodel.wallet, ur);
+        if (result) {
+          Navigator.of(context).pop(true);
+        }        
+        break;
+      case "ur:xmr-output": // xmr-keyimage
+        final ur = await presentQRScanner(context);
+        final result = await monero!.importKeyImagesUR(animatedURmodel.wallet, ur);
+        if (result) {
+          Navigator.of(context).pop(true);
+        }        
+        break;
+      default:
+        throw UnimplementedError("unable to handle UR: ${urQrType}");
+    }
+  } catch (e) {
+    await showPopUp<void>(
+      context: context,
+      builder: (BuildContext context) {
+        return AlertWithOneAction(
+            alertTitle: S.of(context).error,
+            alertContent: e.toString(),
+            buttonText: S.of(context).ok,
+            buttonAction: () => Navigator.pop(context, true));
+      });
+    }
+  }
+}
+
+class URQR extends StatefulWidget {
+  URQR({super.key, required this.frames});
+
+  List<String> frames;
+
+  @override
+  // ignore: library_private_types_in_public_api
+  _URQRState createState() => _URQRState();
+}
+
+const urFrameTime = 1000 ~/ 5;
+
+class _URQRState extends State<URQR> {
+  Timer? t;
+  int frame = 0;
+  @override
+  void initState() {
+    super.initState();
+    setState(() {
+      t = Timer.periodic(const Duration(milliseconds: urFrameTime), (timer) {
+        _nextFrame();
+      });
+    });
+  }
+
+  void _nextFrame() {
+    setState(() {
+      frame++;
+    });
+  }
+
+  @override
+  void dispose() {
+    t?.cancel();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Center(
+          child: QrImage(
+            data: widget.frames[frame % widget.frames.length], version: -1,
+            size: 400,
+          ),
+        ),
+      ],
+    );
+  }
+}
\ No newline at end of file
diff --git a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart
index eda2a748f..3a78f6af6 100644
--- a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart
+++ b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart
@@ -65,7 +65,7 @@ class WCPairingsWidget extends BasePage {
       bool isCameraPermissionGranted =
       await PermissionHandler.checkPermission(Permission.camera, context);
       if (!isCameraPermissionGranted) return;
-      uri = await presentQRScanner();
+      uri = await presentQRScanner(context);
     } else {
       uri = await _showEnterWalletConnectURIPopUp(context);
     }
diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart
index 0b1ef4796..d904768f0 100644
--- a/lib/src/widgets/address_text_field.dart
+++ b/lib/src/widgets/address_text_field.dart
@@ -231,7 +231,7 @@ class AddressTextField extends StatelessWidget {
     bool isCameraPermissionGranted =
         await PermissionHandler.checkPermission(Permission.camera, context);
     if (!isCameraPermissionGranted) return;
-    final code = await presentQRScanner();
+    final code = await presentQRScanner(context);
     if (code.isEmpty) {
       return;
     }
diff --git a/lib/src/widgets/setting_actions.dart b/lib/src/widgets/setting_actions.dart
index 048d006cc..da9f26bc6 100644
--- a/lib/src/widgets/setting_actions.dart
+++ b/lib/src/widgets/setting_actions.dart
@@ -21,6 +21,7 @@ class SettingActions {
     addressBookSettingAction,
     silentPaymentsSettingAction,
     litecoinMwebSettingAction,
+    exportOutputsAction,
     securityBackupSettingAction,
     privacySettingAction,
     displaySettingAction,
@@ -50,6 +51,16 @@ class SettingActions {
     },
   );
 
+  static SettingActions exportOutputsAction = SettingActions._(
+    key: ValueKey('dashboard_page_menu_widget_export_outputs_settings_button_key'),
+    name: (context) => S.of(context).export_outputs,
+    image: 'assets/images/monero_menu.png',
+    onTap: (BuildContext context) {
+      Navigator.pop(context);
+      Navigator.of(context).pushNamed(Routes.urqrAnimatedPage, arguments: 'export-outputs');
+    },
+  );
+  
   static SettingActions litecoinMwebSettingAction = SettingActions._(
     key: ValueKey('dashboard_page_menu_widget_litecoin_mweb_settings_button_key'),
     name: (context) => S.of(context).litecoin_mweb_settings,
diff --git a/lib/view_model/animated_ur_model.dart b/lib/view_model/animated_ur_model.dart
new file mode 100644
index 000000000..f613d26be
--- /dev/null
+++ b/lib/view_model/animated_ur_model.dart
@@ -0,0 +1,10 @@
+import 'package:cake_wallet/store/app_store.dart';
+import 'package:cw_core/wallet_base.dart';
+import 'package:mobx/mobx.dart';
+
+class AnimatedURModel with Store {
+ AnimatedURModel(this.appStore)
+      : wallet = appStore.wallet!;
+  final AppStore appStore;
+  final WalletBase wallet;
+}
\ No newline at end of file
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 6cf7c49d0..934cbdee7 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -393,6 +393,12 @@ abstract class DashboardViewModelBase with Store {
       wallet.type == WalletType.wownero ||
       wallet.type == WalletType.haven;
 
+  @computed
+  bool get isMoneroViewOnly {
+    if (wallet.type != WalletType.monero) return false;
+    return monero!.isViewOnly();
+  }
+
   @computed
   String? get getMoneroError {
     if (wallet.type != WalletType.monero) return null;
diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart
index 86ceb654c..8b3c70c5e 100644
--- a/lib/view_model/node_list/node_create_or_edit_view_model.dart
+++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart
@@ -213,7 +213,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
       bool isCameraPermissionGranted =
           await PermissionHandler.checkPermission(Permission.camera, context);
       if (!isCameraPermissionGranted) return;
-      String code = await presentQRScanner();
+      String code = await presentQRScanner(context);
 
       if (code.isEmpty) {
         throw Exception('Unexpected scan QR code value: value is empty');
diff --git a/lib/view_model/restore/restore_wallet.dart b/lib/view_model/restore/restore_wallet.dart
index 2c2a25005..cc3ad4123 100644
--- a/lib/view_model/restore/restore_wallet.dart
+++ b/lib/view_model/restore/restore_wallet.dart
@@ -1,3 +1,5 @@
+import 'dart:convert';
+
 import 'package:cake_wallet/view_model/restore/restore_mode.dart';
 import 'package:cw_core/wallet_type.dart';
 
@@ -32,6 +34,16 @@ class RestoredWallet {
   final String? privateKey;
 
   factory RestoredWallet.fromKey(Map<String, dynamic> json) {
+    try {
+    final codeParsed = jsonDecode(json['raw_qr'].toString());
+      if (codeParsed["version"] == 0) {
+        json['address'] = codeParsed["primaryAddress"];
+        json['view_key'] = codeParsed["privateViewKey"];
+        json['height'] = codeParsed["restoreHeight"].toString();
+      }
+    } catch (e) {
+      // fine, we don't care, it is only for monero anyway
+    }
     final height = json['height'] as String?;
     return RestoredWallet(
       restoreMode: json['mode'] as WalletRestoreMode,
@@ -39,7 +51,7 @@ class RestoredWallet {
       address: json['address'] as String?,
       spendKey: json['spend_key'] as String?,
       viewKey: json['view_key'] as String?,
-      height: height != null ? int.parse(height) : 0,
+      height: height != null ? int.tryParse(height)??0 : 0,
       privateKey: json['private_key'] as String?,
     );
   }
diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart
index 23850befa..c1a19ea57 100644
--- a/lib/view_model/restore/wallet_restore_from_qr_code.dart
+++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart
@@ -1,3 +1,5 @@
+import 'dart:convert';
+
 import 'package:cake_wallet/core/seed_validator.dart';
 import 'package:cake_wallet/entities/parse_address_from_domain.dart';
 import 'package:cake_wallet/entities/qr_scanner.dart';
@@ -48,6 +50,17 @@ class WalletRestoreFromQRCode {
 
     final extracted = sortedKeys.firstWhereOrNull((key) => code.toLowerCase().contains(key));
 
+    if (extracted == null) {
+      // Special case for view-only monero wallet
+      final codeParsed = json.decode(code);
+      if (codeParsed["version"] == 0 &&
+          codeParsed["primaryAddress"] != null &&
+          codeParsed["privateViewKey"] != null &&
+          codeParsed["restoreHeight"] != null) {
+        return WalletType.monero;
+      }
+    }
+
     return _walletTypeMap[extracted];
   }
 
@@ -75,7 +88,7 @@ class WalletRestoreFromQRCode {
   }
 
   static Future<RestoredWallet> scanQRCodeForRestoring(BuildContext context) async {
-    String code = await presentQRScanner();
+    String code = await presentQRScanner(context);
     if (code.isEmpty) throw Exception('Unexpected scan QR code value: value is empty');
 
     WalletType? walletType;
@@ -109,7 +122,7 @@ class WalletRestoreFromQRCode {
       queryParameters['address'] = _extractAddressFromUrl(code, walletType!);
     }
 
-    Map<String, dynamic> credentials = {'type': walletType, ...queryParameters};
+    Map<String, dynamic> credentials = {'type': walletType, ...queryParameters, 'raw_qr': code};
 
     credentials['mode'] = _determineWalletRestoreMode(credentials);
 
@@ -205,6 +218,17 @@ class WalletRestoreFromQRCode {
       return WalletRestoreMode.keys;
     }
 
+    if (type == WalletType.monero) {
+      final codeParsed = json.decode(credentials['raw_qr'].toString());
+      if (codeParsed["version"] != 0) throw UnimplementedError("Found view-only restore with unsupported version");
+      if (codeParsed["primaryAddress"] == null ||
+          codeParsed["privateViewKey"] == null ||
+          codeParsed["restoreHeight"] == null) {
+        throw UnimplementedError("Missing one or more attributes in the JSON");
+      }
+      return WalletRestoreMode.keys;
+    }
+
     throw Exception('Unexpected restore mode: restore params are invalid');
   }
 }
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 1403eb109..4621e8d16 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -1,3 +1,4 @@
+import 'package:cake_wallet/di.dart';
 import 'package:cake_wallet/entities/contact.dart';
 import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
 import 'package:cake_wallet/entities/transaction_description.dart';
@@ -10,7 +11,9 @@ import 'package:cake_wallet/entities/contact_record.dart';
 import 'package:cake_wallet/entities/wallet_contact.dart';
 import 'package:cake_wallet/polygon/polygon.dart';
 import 'package:cake_wallet/reactions/wallet_connect.dart';
+import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/solana/solana.dart';
+import 'package:cake_wallet/src/screens/ur/animated_ur_page.dart';
 import 'package:cake_wallet/store/app_store.dart';
 import 'package:cake_wallet/tron/tron.dart';
 import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
@@ -23,6 +26,7 @@ import 'package:cw_core/transaction_priority.dart';
 import 'package:cw_core/unspent_coin_type.dart';
 import 'package:cake_wallet/view_model/send/output.dart';
 import 'package:cake_wallet/view_model/send/send_template_view_model.dart';
+import 'package:flutter/material.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 import 'package:cake_wallet/entities/template.dart';
@@ -457,7 +461,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
   }
 
   @action
-  Future<void> commitTransaction() async {
+  Future<void> commitTransaction(BuildContext context) async {
     if (pendingTransaction == null) {
       throw Exception("Pending transaction doesn't exist. It should not be happened.");
     }
@@ -476,7 +480,17 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
 
     try {
       state = TransactionCommitting();
-      await pendingTransaction!.commit();
+      
+      if (pendingTransaction!.shouldCommitUR()) {
+        final urstr = await pendingTransaction!.commitUR();
+        final result = await Navigator.of(context).pushNamed(Routes.urqrAnimatedPage, arguments: urstr);
+        if (result == null) {
+          state = FailureState("Canceled by user");
+          return;
+        }
+      } else {
+        await pendingTransaction!.commit();
+      }
 
       if (walletType == WalletType.nano) {
         nano!.updateTransactions(wallet);
diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart
index 6455fc0e3..81eda7cc8 100644
--- a/lib/view_model/wallet_keys_view_model.dart
+++ b/lib/view_model/wallet_keys_view_model.dart
@@ -72,6 +72,10 @@ abstract class WalletKeysViewModelBase with Store {
       final keys = monero!.getKeys(_appStore.wallet!);
 
       items.addAll([
+        if (keys['primaryAddress'] != null)
+          StandartListItem(
+              title: S.current.primary_address,
+              value: keys['primaryAddress']!),
         if (keys['publicSpendKey'] != null)
           StandartListItem(
             key: ValueKey('${_walletName}_wallet_public_spend_key_item_key'),
@@ -131,6 +135,10 @@ abstract class WalletKeysViewModelBase with Store {
       final keys = haven!.getKeys(_appStore.wallet!);
 
       items.addAll([
+        if (keys['primaryAddress'] != null)
+          StandartListItem(
+              title: S.current.primary_address,
+              value: keys['primaryAddress']!),
         if (keys['publicSpendKey'] != null)
           StandartListItem(
             key: ValueKey('${_walletName}_wallet_public_spend_key_item_key'),
@@ -168,6 +176,10 @@ abstract class WalletKeysViewModelBase with Store {
       final keys = wownero!.getKeys(_appStore.wallet!);
 
       items.addAll([
+        if (keys['primaryAddress'] != null)
+          StandartListItem(
+              title: S.current.primary_address,
+              value: keys['primaryAddress']!),
         if (keys['publicSpendKey'] != null)
           StandartListItem(
             key: ValueKey('${_walletName}_wallet_public_spend_key_item_key'),
diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake
index f52be7481..4b9eb3b2d 100644
--- a/linux/flutter/generated_plugins.cmake
+++ b/linux/flutter/generated_plugins.cmake
@@ -10,7 +10,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
 )
 
 list(APPEND FLUTTER_FFI_PLUGIN_LIST
-  sp_scanner
 )
 
 set(PLUGIN_BUNDLED_LIBRARIES)
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 9895e6305..52b44e53e 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -6,9 +6,9 @@ import FlutterMacOS
 import Foundation
 
 import connectivity_plus
-import cw_mweb
 import device_info_plus
 import devicelocale
+import fast_scanner
 import flutter_inappwebview_macos
 import flutter_local_authentication
 import flutter_secure_storage_macos
@@ -23,9 +23,9 @@ import wakelock_plus
 
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
   ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
-  CwMwebPlugin.register(with: registry.registrar(forPlugin: "CwMwebPlugin"))
   DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
   DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
+  MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
   InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
   FlutterLocalAuthenticationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalAuthenticationPlugin"))
   FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
diff --git a/macos/Podfile.lock b/macos/Podfile.lock
index d6199d028..001d75696 100644
--- a/macos/Podfile.lock
+++ b/macos/Podfile.lock
@@ -8,6 +8,8 @@ PODS:
     - FlutterMacOS
   - devicelocale (0.0.1):
     - FlutterMacOS
+  - fast_scanner (5.1.1):
+    - FlutterMacOS
   - flutter_inappwebview_macos (0.0.1):
     - FlutterMacOS
     - OrderedSet (~> 5.0)
@@ -42,6 +44,7 @@ DEPENDENCIES:
   - cw_mweb (from `Flutter/ephemeral/.symlinks/plugins/cw_mweb/macos`)
   - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
   - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
+  - fast_scanner (from `Flutter/ephemeral/.symlinks/plugins/fast_scanner/macos`)
   - flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`)
   - flutter_local_authentication (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos`)
   - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
@@ -69,6 +72,8 @@ EXTERNAL SOURCES:
     :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
   devicelocale:
     :path: Flutter/ephemeral/.symlinks/plugins/devicelocale/macos
+  fast_scanner:
+    :path: Flutter/ephemeral/.symlinks/plugins/fast_scanner/macos
   flutter_inappwebview_macos:
     :path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos
   flutter_local_authentication:
@@ -99,6 +104,7 @@ SPEC CHECKSUMS:
   cw_mweb: 7440b12ead811dda972a9918442ea2a458e8742c
   device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
   devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
+  fast_scanner: d31bae07e2653403a69dac99fb710c1722b16a97
   flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d
   flutter_local_authentication: 85674893931e1c9cfa7c9e4f5973cb8c56b018b0
   flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
diff --git a/pubspec_base.yaml b/pubspec_base.yaml
index 2abd8401a..fa70b5837 100644
--- a/pubspec_base.yaml
+++ b/pubspec_base.yaml
@@ -14,8 +14,10 @@ dependencies:
   # provider: ^6.0.3
   rxdart: ^0.28.0
   yaml: ^3.1.1
-  #barcode_scan: any
-  barcode_scan2: ^4.2.1
+  fast_scanner:
+    git:
+      url: https://github.com/MrCyjaneK/fast_scanner
+      ref: c8311b46cc67dd02250970a54d2a4526168187f3
   http: ^1.1.0
   path_provider: ^2.0.11
   mobx: ^2.1.4
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index b8c933a2e..fc0ea8ea9 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "رابط Clearnet",
   "close": "يغلق",
   "coin_control": "التحكم في العملة (اختياري)",
-  "cold_or_recover_wallet": "أضف محفظة باردة أو استعد محفظة ورقية",
+  "cold_or_recover_wallet": "أضف محفظة للقراءة فقط من Cupcake أو محفظة باردة أو استعاد محفظة ورقية",
   "color_theme": "سمة اللون",
   "commit_transaction_amount_fee": "تنفيذ الصفقة\nالمبلغ: ${amount}\nالرسوم: ${fee}",
   "confirm": "تأكيد",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "جهات الاتصال",
   "contact_list_wallets": "محافظ",
   "contact_name": "اسم جهة الاتصال",
+  "contact_name_exists": "                   .ﻒﻠﺘﺨﻣ ﻢﺳﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ .ﻞﻌﻔﻟﺎﺑ ﺓﺩﻮﺟﻮﻣ ﻢﺳﻻﺍ ﺍﺬﻬﺑ ﻝﺎﺼﺗﺍ ﺔﻬﺟ",
   "contact_support": "اتصل بالدعم",
   "continue_text": "التالي",
   "contract_warning": "تم وضع علامة على عنوان العقد هذا على أنه احتيالي محتمل. يرجى المعالجة بحذر.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "انتهاء الصلاحية والصلاحية",
   "export_backup": "تصدير نسخة احتياطية",
   "export_logs": "سجلات التصدير",
+  "export_outputs": "مخرجات التصدير",
   "extra_id": "معرف إضافي:",
   "extracted_address_content": "سوف ترسل الأموال إلى\n${recipient_name}",
   "failed_authentication": "${state_error} فشل المصادقة.",
@@ -336,7 +338,9 @@
   "haven_app": "Haven بواسطة Cake Wallet",
   "haven_app_wallet_text": "محفظة رائعة ل Haven",
   "help": "مساعده",
+  "hidden_addresses": "العناوين المخفية",
   "hidden_balance": "الميزان الخفي",
+  "hide": "يخفي",
   "hide_details": "أخف التفاصيل",
   "high_contrast_theme": "موضوع عالي التباين",
   "home_screen_settings": "إعدادات الشاشة الرئيسية",
@@ -500,6 +504,7 @@
   "pre_seed_title": "مهم",
   "prepaid_cards": "البطاقات المدفوعة مسبقا",
   "prevent_screenshots": "منع لقطات الشاشة وتسجيل الشاشة",
+  "primary_address": "العنوان الأساسي",
   "privacy": "خصوصية",
   "privacy_policy": "سياسة الخصوصية",
   "privacy_settings": "إعدادات الخصوصية",
@@ -696,6 +701,7 @@
   "share": "يشارك",
   "share_address": "شارك العنوان",
   "shared_seed_wallet_groups": "مجموعات محفظة البذور المشتركة",
+  "show": "يعرض",
   "show_details": "اظهر التفاصيل",
   "show_keys": "اظهار السييد / المفاتيح",
   "show_market_place": "إظهار السوق",
@@ -942,6 +948,5 @@
   "you_pay": "انت تدفع",
   "you_will_get": "حول الى",
   "you_will_send": "تحويل من",
-  "yy": "YY",
-  "contact_name_exists": "                   .ﻒﻠﺘﺨﻣ ﻢﺳﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ .ﻞﻌﻔﻟﺎﺑ ﺓﺩﻮﺟﻮﻣ ﻢﺳﻻﺍ ﺍﺬﻬﺑ ﻝﺎﺼﺗﺍ ﺔﻬﺟ"
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index 2fd644d01..e66a40b36 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Clearnet връзка",
   "close": "затвори",
   "coin_control": "Управление на монетите (не е задължително)",
-  "cold_or_recover_wallet": "Добавете студен портфейл или възстановете хартиен портфейл",
+  "cold_or_recover_wallet": "Добавете портфейл само за четене от Cupcake или студен портфейл или възстановете хартиен портфейл",
   "color_theme": "Цвят",
   "commit_transaction_amount_fee": "Изпълняване на транзакция\nСума: ${amount}\nТакса: ${fee}",
   "confirm": "Потвърждаване",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Контакти",
   "contact_list_wallets": "Моите портфейли",
   "contact_name": "Име на контакт",
+  "contact_name_exists": "Вече съществува контакт с това име. Моля, изберете друго име.",
   "contact_support": "Свържи се с отдел поддръжка",
   "continue_text": "Напред",
   "contract_warning": "Този адрес на договора е маркиран като потенциално измамник. Моля, обработете с повишено внимание.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Изтичане и валидност",
   "export_backup": "Експортиране на резервно копие",
   "export_logs": "Експортни дневници",
+  "export_outputs": "Експортни резултати",
   "extra_id": "Допълнително ID:",
   "extracted_address_content": "Ще изпратите средства на \n${recipient_name}",
   "failed_authentication": "Неуспешно удостоверяване. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven от Cake Wallet",
   "haven_app_wallet_text": "Невероятен портфейл за Haven",
   "help": "Помощ",
+  "hidden_addresses": "Скрити адреси",
   "hidden_balance": "Скрит баланс",
+  "hide": "Скрий",
   "hide_details": "Скриване на подробностите",
   "high_contrast_theme": "Тема с висок контраст",
   "home_screen_settings": "Настройки на началния екран",
@@ -500,6 +504,7 @@
   "pre_seed_title": "ВАЖНО",
   "prepaid_cards": "Предплатени карти",
   "prevent_screenshots": "Предотвратете екранни снимки и запис на екрана",
+  "primary_address": "Първичен адрес",
   "privacy": "Поверителност",
   "privacy_policy": "Политика за поверителността",
   "privacy_settings": "Настройки за поверителност",
@@ -696,6 +701,7 @@
   "share": "Дял",
   "share_address": "Сподели адрес",
   "shared_seed_wallet_groups": "Споделени групи за портфейли за семена",
+  "show": "Показване",
   "show_details": "Показване на подробностите",
   "show_keys": "Покажи seed/keys",
   "show_market_place": "Покажи пазар",
@@ -942,6 +948,5 @@
   "you_pay": "Вие плащате",
   "you_will_get": "Обръщане в",
   "you_will_send": "Обръщане от",
-  "yy": "гг",
-  "contact_name_exists": "Вече съществува контакт с това име. Моля, изберете друго име."
-}
+  "yy": "гг"
+}
\ No newline at end of file
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index 8f3b5bf28..4911030b2 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Odkaz na Clearnet",
   "close": "zavřít",
   "coin_control": "Volba mincí (nepovinné)",
-  "cold_or_recover_wallet": "Přidejte studenou peněženku nebo obnovte papírovou peněženku",
+  "cold_or_recover_wallet": "Přidejte peněženku pouze pro čtení z Cupcake nebo studené peněženky nebo obnovte papírovou peněženku",
   "color_theme": "Barevný motiv",
   "commit_transaction_amount_fee": "Odeslat transakci\nČástka: ${amount}\nPoplatek: ${fee}",
   "confirm": "Potvrdit",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Kontakty",
   "contact_list_wallets": "Moje peněženky",
   "contact_name": "Jméno kontaktu",
+  "contact_name_exists": "Kontakt s tímto jménem již existuje. Vyberte prosím jiný název.",
   "contact_support": "Kontaktovat podporu",
   "continue_text": "Pokračovat",
   "contract_warning": "Tato adresa smlouvy byla označena jako potenciálně podvodná. Zpracovejte prosím opatrně.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Vypršení a platnost",
   "export_backup": "Exportovat zálohu",
   "export_logs": "Vývozní protokoly",
+  "export_outputs": "Vývozní výstupy",
   "extra_id": "Extra ID:",
   "extracted_address_content": "Prostředky budete posílat na\n${recipient_name}",
   "failed_authentication": "Ověřování selhalo. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven od Cake Wallet",
   "haven_app_wallet_text": "Úžasná peněženka pro Haven",
   "help": "pomoc",
+  "hidden_addresses": "Skryté adresy",
   "hidden_balance": "Skrytý zůstatek",
+  "hide": "Skrýt",
   "hide_details": "Skrýt detaily",
   "high_contrast_theme": "Téma s vysokým kontrastem",
   "home_screen_settings": "Nastavení domovské obrazovky",
@@ -500,6 +504,7 @@
   "pre_seed_title": "DŮLEŽITÉ",
   "prepaid_cards": "Předplacené karty",
   "prevent_screenshots": "Zabránit vytváření snímků obrazovky a nahrávání obrazovky",
+  "primary_address": "Primární adresa",
   "privacy": "Soukromí",
   "privacy_policy": "Zásady ochrany soukromí",
   "privacy_settings": "Nastavení soukromí",
@@ -696,6 +701,7 @@
   "share": "Podíl",
   "share_address": "Sdílet adresu",
   "shared_seed_wallet_groups": "Skupiny sdílených semen",
+  "show": "Show",
   "show_details": "Zobrazit detaily",
   "show_keys": "Zobrazit seed/klíče",
   "show_market_place": "Zobrazit trh",
@@ -942,6 +948,5 @@
   "you_pay": "Zaplatíte",
   "you_will_get": "Směnit na",
   "you_will_send": "Směnit z",
-  "yy": "YY",
-  "contact_name_exists": "Kontakt s tímto jménem již existuje. Vyberte prosím jiný název."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index 77a531d1b..a69174dd6 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Clearnet-Link",
   "close": "Schließen",
   "coin_control": "Coin Control (optional)",
-  "cold_or_recover_wallet": "Fügen Sie eine Cold Wallet hinzu oder stellen Sie eine Paper Wallet wieder her",
+  "cold_or_recover_wallet": "Fügen Sie eine schreibgeschützte Brieftasche von Cupcake oder eine kalte Brieftasche hinzu oder erholen Sie sich eine Brieftasche",
   "color_theme": "Farbthema",
   "commit_transaction_amount_fee": "Transaktion absenden\nBetrag: ${amount}\nGebühr: ${fee}",
   "confirm": "Bestätigen",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Kontakte",
   "contact_list_wallets": "Meine Wallets",
   "contact_name": "Name des Kontakts",
+  "contact_name_exists": "Ein Kontakt mit diesem Namen besteht bereits. Bitte wählen Sie einen anderen Namen.",
   "contact_support": "Support kontaktieren",
   "continue_text": "Weiter",
   "contract_warning": "Diese Vertragsadresse wurde als potenziell betrügerisch gekennzeichnet. Bitte verarbeiten Sie mit Vorsicht.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Ablauf und Gültigkeit",
   "export_backup": "Sicherung exportieren",
   "export_logs": "Exportprotokolle",
+  "export_outputs": "Exportausgaben",
   "extra_id": "Extra ID:",
   "extracted_address_content": "Sie senden Geld an\n${recipient_name}",
   "failed_authentication": "Authentifizierung fehlgeschlagen. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven von Cake Wallet",
   "haven_app_wallet_text": "Eine großartige Wallet für Haven",
   "help": "hilfe",
+  "hidden_addresses": "Versteckte Adressen",
   "hidden_balance": "Verstecktes Guthaben",
+  "hide": "Verstecken",
   "hide_details": "Details ausblenden",
   "high_contrast_theme": "Kontrastreiches Thema",
   "home_screen_settings": "Einstellungen für den Startbildschirm",
@@ -501,6 +505,7 @@
   "pre_seed_title": "WICHTIG",
   "prepaid_cards": "Karten mit Guthaben",
   "prevent_screenshots": "Verhindern Sie Screenshots und Bildschirmaufzeichnungen",
+  "primary_address": "Primäradresse",
   "privacy": "Datenschutz",
   "privacy_policy": "Datenschutzrichtlinie",
   "privacy_settings": "Datenschutzeinstellungen",
@@ -697,6 +702,7 @@
   "share": "Teilen",
   "share_address": "Adresse teilen ",
   "shared_seed_wallet_groups": "Gemeinsame Walletsseed Gruppen",
+  "show": "Zeigen",
   "show_details": "Details anzeigen",
   "show_keys": "Seed/Schlüssel anzeigen",
   "show_market_place": "Marktplatz anzeigen",
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index 4fe375ff9..322e38b85 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Clearnet link",
   "close": "Close",
   "coin_control": "Coin control (optional)",
-  "cold_or_recover_wallet": "Add a cold wallet or recover a paper wallet",
+  "cold_or_recover_wallet": "Add a read-only wallet from Cupcake or a cold wallet or recover a paper wallet",
   "color_theme": "Color theme",
   "commit_transaction_amount_fee": "Commit transaction\nAmount: ${amount}\nFee: ${fee}",
   "confirm": "Confirm",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Contacts",
   "contact_list_wallets": "My Wallets",
   "contact_name": "Contact Name",
+  "contact_name_exists": "A contact with that name already exists. Please choose a different name.",
   "contact_support": "Contact Support",
   "continue_text": "Continue",
   "contract_warning": "This contract address has been flagged as potentially fraudulent. Please process with caution.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Expiry and Validity",
   "export_backup": "Export backup",
   "export_logs": "Export logs",
+  "export_outputs": "Export outputs",
   "extra_id": "Extra ID:",
   "extracted_address_content": "You will be sending funds to\n${recipient_name}",
   "failed_authentication": "Failed authentication. ${state_error}",
@@ -502,6 +504,7 @@
   "pre_seed_title": "IMPORTANT",
   "prepaid_cards": "Prepaid Cards",
   "prevent_screenshots": "Prevent screenshots and screen recording",
+  "primary_address": "Primary Address",
   "privacy": "Privacy",
   "privacy_policy": "Privacy Policy",
   "privacy_settings": "Privacy settings",
@@ -945,6 +948,5 @@
   "you_pay": "You Pay",
   "you_will_get": "Convert to",
   "you_will_send": "Convert from",
-  "yy": "YY",
-  "contact_name_exists": "A contact with that name already exists. Please choose a different name."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 31498df2d..5a8ff0582 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "enlace Clearnet",
   "close": "Cerca",
   "coin_control": "Control de monedas (opcional)",
-  "cold_or_recover_wallet": "Agrega una billetera fría o recupera una billetera de papel",
+  "cold_or_recover_wallet": "Agregue una billetera de solo lectura de Cupcake o una billetera en frío o recupere una billetera de papel",
   "color_theme": "Tema de color",
   "commit_transaction_amount_fee": "Confirmar transacción\nCantidad: ${amount}\nCuota: ${fee}",
   "confirm": "Confirmar",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Contactos",
   "contact_list_wallets": "Mis billeteras",
   "contact_name": "Nombre de contacto",
+  "contact_name_exists": "Ya existe un contacto con ese nombre. Elija un nombre diferente.",
   "contact_support": "Contactar con Soporte",
   "continue_text": "Continuar",
   "contract_warning": "Esta dirección de contrato ha sido marcada como potencialmente fraudulenta. Por favor, procese con precaución.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Vencimiento y validez",
   "export_backup": "Exportar copia de seguridad",
   "export_logs": "Registros de exportación",
+  "export_outputs": "Exportaciones de exportación",
   "extra_id": "ID adicional:",
   "extracted_address_content": "Enviará fondos a\n${recipient_name}",
   "failed_authentication": "Autenticación fallida. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Increíble billetera para Haven",
   "help": "ayuda",
+  "hidden_addresses": "Direcciones ocultas",
   "hidden_balance": "Balance oculto",
+  "hide": "Esconder",
   "hide_details": "Ocultar detalles",
   "high_contrast_theme": "Tema de alto contraste",
   "home_screen_settings": "Configuración de la pantalla de inicio",
@@ -501,6 +505,7 @@
   "pre_seed_title": "IMPORTANTE",
   "prepaid_cards": "Tajetas prepagadas",
   "prevent_screenshots": "Evitar capturas de pantalla y grabación de pantalla",
+  "primary_address": "Dirección principal",
   "privacy": "Privacidad",
   "privacy_policy": "Política de privacidad",
   "privacy_settings": "Configuración de privacidad",
@@ -697,6 +702,7 @@
   "share": "Compartir",
   "share_address": "Compartir dirección",
   "shared_seed_wallet_groups": "Grupos de billetera de semillas compartidas",
+  "show": "Espectáculo",
   "show_details": "Mostrar detalles",
   "show_keys": "Mostrar semilla/claves",
   "show_market_place": "Mostrar mercado",
@@ -943,6 +949,5 @@
   "you_pay": "Tú pagas",
   "you_will_get": "Convertir a",
   "you_will_send": "Convertir de",
-  "yy": "YY",
-  "contact_name_exists": "Ya existe un contacto con ese nombre. Elija un nombre diferente."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index f96e9e304..6abe72681 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Lien Clearnet",
   "close": "Fermer",
   "coin_control": "Contrôle optionnel des pièces (coins)",
-  "cold_or_recover_wallet": "Ajoutez un portefeuille froid (cold wallet) ou récupérez un portefeuille papier (paper wallet)",
+  "cold_or_recover_wallet": "Ajoutez un portefeuille en lecture seule de Cupcake ou d'un portefeuille froid ou récupérez un portefeuille en papier",
   "color_theme": "Thème",
   "commit_transaction_amount_fee": "Valider la transaction\nMontant : ${amount}\nFrais : ${fee}",
   "confirm": "Confirmer",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Contacts",
   "contact_list_wallets": "Mes portefeuilles (wallets)",
   "contact_name": "Nom de Contact",
+  "contact_name_exists": "Un contact portant ce nom existe déjà. Veuillez choisir un autre nom.",
   "contact_support": "Contacter l'assistance",
   "continue_text": "Continuer",
   "contract_warning": "Cette adresse contractuelle a été signalée comme potentiellement frauduleuse. Veuillez traiter avec prudence.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Expiration et validité",
   "export_backup": "Exporter la sauvegarde",
   "export_logs": "Journaux d'exportation",
+  "export_outputs": "Exportation des sorties",
   "extra_id": "ID supplémentaire :",
   "extracted_address_content": "Vous allez envoyer des fonds à\n${recipient_name}",
   "failed_authentication": "Échec d'authentification. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven par Cake Wallet",
   "haven_app_wallet_text": "Super portefeuille (wallet) pour Haven",
   "help": "aide",
+  "hidden_addresses": "Adresses cachées",
   "hidden_balance": "Solde Caché",
+  "hide": "Cacher",
   "hide_details": "Masquer les détails",
   "high_contrast_theme": "Thème à contraste élevé",
   "home_screen_settings": "Paramètres de l'écran d'accueil",
@@ -500,6 +504,7 @@
   "pre_seed_title": "IMPORTANT",
   "prepaid_cards": "Cartes prépayées",
   "prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran",
+  "primary_address": "Adresse primaire",
   "privacy": "Confidentialité",
   "privacy_policy": "Politique de confidentialité",
   "privacy_settings": "Paramètres de confidentialité",
@@ -696,6 +701,7 @@
   "share": "Partager",
   "share_address": "Partager l'adresse",
   "shared_seed_wallet_groups": "Groupes de portefeuilles partagés",
+  "show": "Montrer",
   "show_details": "Afficher les détails",
   "show_keys": "Visualiser la phrase secrète (seed) et les clefs",
   "show_market_place": "Afficher la place de marché",
@@ -942,6 +948,5 @@
   "you_pay": "Vous payez",
   "you_will_get": "Convertir vers",
   "you_will_send": "Convertir depuis",
-  "yy": "AA",
-  "contact_name_exists": "Un contact portant ce nom existe déjà. Veuillez choisir un autre nom."
-}
+  "yy": "AA"
+}
\ No newline at end of file
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index 5fc64e0b3..5a53d6795 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Lambar makomar kwayoyi",
   "close": "Rufa",
   "coin_control": "Sarrafa tsabar kuɗi (na zaɓi)",
-  "cold_or_recover_wallet": "Samun kashi na baya ko samun kashi na kasa",
+  "cold_or_recover_wallet": "Aara wani walat mai karanta-kawai Cupcake ko walat ɗin mai sanyi ko murmurewa takarda takarda",
   "color_theme": "Jigon launi",
   "commit_transaction_amount_fee": "Aikata ciniki\nAdadi: ${amount}\nKuda: ${fee}",
   "confirm": "Tabbatar",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Lambobin sadarwa",
   "contact_list_wallets": "Wallets dina",
   "contact_name": "Sunan Tuntuɓi",
+  "contact_name_exists": "An riga an sami lamba tare da wannan sunan. Da fatan za a zaɓi suna daban.",
   "contact_support": "Tuntuɓi Support",
   "continue_text": "Ci gaba",
   "contract_warning": "An kafa wannan adireshin kwantaragin kwangilar yayin da yuwuwar zamba. Da fatan za a aiwatar da taka tsantsan.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Karewa da inganci",
   "export_backup": "Ajiyayyen fitarwa",
   "export_logs": "Injin fitarwa",
+  "export_outputs": "Fitarwar fitarwa",
   "extra_id": "Karin ID:",
   "extracted_address_content": "Za ku aika da kudade zuwa\n${recipient_name}",
   "failed_authentication": "Binne wajen shiga. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven da Cake Wallet",
   "haven_app_wallet_text": "Aikace-aikacen e-wallet ga Haven",
   "help": "taimako",
+  "hidden_addresses": "Adireshin ɓoye",
   "hidden_balance": "BOYE KUDI",
+  "hide": "Ɓoye",
   "hide_details": "Ɓoye cikakkun bayanai",
   "high_contrast_theme": "Babban Jigon Kwatance",
   "home_screen_settings": "Saitunan allo na gida",
@@ -502,6 +506,7 @@
   "pre_seed_title": "MUHIMMANCI",
   "prepaid_cards": "Katunan shirye-shirye",
   "prevent_screenshots": "Fada lambobi da jarrabobi na kayan lambobi",
+  "primary_address": "Adireshin farko",
   "privacy": "Keɓantawa",
   "privacy_policy": "takardar kebantawa",
   "privacy_settings": "Saitunan sirri",
@@ -698,6 +703,7 @@
   "share": "Raba",
   "share_address": "Raba adireshin",
   "shared_seed_wallet_groups": "Raba ƙungiya walat",
+  "show": "Nuna",
   "show_details": "Nuna Cikakkun bayanai",
   "show_keys": "Nuna iri/maɓallai",
   "show_market_place": "Nuna dan kasuwa",
@@ -944,6 +950,5 @@
   "you_pay": "Ka Bayar",
   "you_will_get": "Maida zuwa",
   "you_will_send": "Maida daga",
-  "yy": "YY",
-  "contact_name_exists": "An riga an sami lamba tare da wannan sunan. Da fatan za a zaɓi suna daban."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index fb3b78900..d130c2b5f 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "क्लियरनेट लिंक",
   "close": "बंद करना",
   "coin_control": "सिक्का नियंत्रण (वैकल्पिक)",
-  "cold_or_recover_wallet": "कोल्ड वॉलेट जोड़ें या पेपर वॉलेट पुनर्प्राप्त करें",
+  "cold_or_recover_wallet": "Cupcake या एक कोल्ड वॉलेट से एक रीड-ओनली वॉलेट जोड़ें या एक पेपर वॉलेट को पुनर्प्राप्त करें",
   "color_theme": "रंग विषय",
   "commit_transaction_amount_fee": "लेन-देन करें\nरकम: ${amount}\nशुल्क: ${fee}",
   "confirm": "की पुष्टि करें",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "संपर्क",
   "contact_list_wallets": "मेरा बटुआ",
   "contact_name": "संपर्क नाम",
+  "contact_name_exists": "उस नाम का एक संपर्क पहले से मौजूद है. कृपया कोई भिन्न नाम चुनें.",
   "contact_support": "सहायता से संपर्क करें",
   "continue_text": "जारी रहना",
   "contract_warning": "इस अनुबंध के पते को संभावित रूप से धोखाधड़ी के रूप में चिह्नित किया गया है। कृपया सावधानी के साथ प्रक्रिया करें।",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "समाप्ति और वैधता",
   "export_backup": "निर्यात बैकअप",
   "export_logs": "निर्यात लॉग",
+  "export_outputs": "निर्यात आउटपुट",
   "extra_id": "अतिरिक्त आईडी:",
   "extracted_address_content": "आपको धनराशि भेजी जाएगी\n${recipient_name}",
   "failed_authentication": "प्रमाणीकरण विफल. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "मदद करना",
+  "hidden_addresses": "छिपे हुए पते",
   "hidden_balance": "छिपा हुआ संतुलन",
+  "hide": "छिपाना",
   "hide_details": "विवरण छुपाएं",
   "high_contrast_theme": "उच्च कंट्रास्ट थीम",
   "home_screen_settings": "होम स्क्रीन सेटिंग्स",
@@ -501,6 +505,7 @@
   "pre_seed_title": "महत्वपूर्ण",
   "prepaid_cards": "पूर्वदत्त कार्ड",
   "prevent_screenshots": "स्क्रीनशॉट और स्क्रीन रिकॉर्डिंग रोकें",
+  "primary_address": "प्राथमिक पता",
   "privacy": "गोपनीयता",
   "privacy_policy": "गोपनीयता नीति",
   "privacy_settings": "गोपनीयता सेटिंग्स",
@@ -698,6 +703,7 @@
   "share": "शेयर करना",
   "share_address": "पता साझा करें",
   "shared_seed_wallet_groups": "साझा बीज बटुए समूह",
+  "show": "दिखाओ",
   "show_details": "विवरण दिखाएं",
   "show_keys": "बीज / कुंजियाँ दिखाएँ",
   "show_market_place": "बाज़ार दिखाएँ",
@@ -944,6 +950,5 @@
   "you_pay": "आप भुगतान करते हैं",
   "you_will_get": "में बदलें",
   "you_will_send": "से रूपांतरित करें",
-  "yy": "वाईवाई",
-  "contact_name_exists": "उस नाम का एक संपर्क पहले से मौजूद है. कृपया कोई भिन्न नाम चुनें."
-}
+  "yy": "वाईवाई"
+}
\ No newline at end of file
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 230aa955b..037e6e9f2 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Clearnet veza",
   "close": "Zatvoriti",
   "coin_control": "Kontrola novca (nije obavezno)",
-  "cold_or_recover_wallet": "Dodajte hladni novčanik ili povratite papirnati novčanik",
+  "cold_or_recover_wallet": "Dodajte novčanik samo za čitanje od Cupcake ili hladnog novčanika ili oporavite papirni novčanik",
   "color_theme": "Shema boja",
   "commit_transaction_amount_fee": "Izvrši transakciju \nAmount: ${amount}\nFee: ${fee}",
   "confirm": "Potvrdi",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Kontakti",
   "contact_list_wallets": "Moji novčanici",
   "contact_name": "Ime kontakta",
+  "contact_name_exists": "Kontakt s tim imenom već postoji. Odaberite drugo ime.",
   "contact_support": "Kontaktirajte podršku",
   "continue_text": "Nastavak",
   "contract_warning": "Ova adresa ugovora označena je kao potencijalno lažna. Molimo obradite s oprezom.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Istek i valjanost",
   "export_backup": "Izvezi sigurnosnu kopiju",
   "export_logs": "Izvozni trupci",
+  "export_outputs": "Izvoz izlaza",
   "extra_id": "Dodatni ID:",
   "extracted_address_content": "Poslat ćete sredstva primatelju\n${recipient_name}",
   "failed_authentication": "Autentifikacija neuspješna. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "pomozite",
+  "hidden_addresses": "Skrivene adrese",
   "hidden_balance": "Skriven iznos",
+  "hide": "Sakriti",
   "hide_details": "Sakrij pojedinosti",
   "high_contrast_theme": "Tema visokog kontrasta",
   "home_screen_settings": "Postavke početnog zaslona",
@@ -500,6 +504,7 @@
   "pre_seed_title": "VAŽNO",
   "prepaid_cards": "Unaprijed plaćene kartice",
   "prevent_screenshots": "Spriječite snimke zaslona i snimanje zaslona",
+  "primary_address": "Primarna adresa",
   "privacy": "Privatnost",
   "privacy_policy": "Pravila privatnosti",
   "privacy_settings": "Postavke privatnosti",
@@ -696,6 +701,7 @@
   "share": "Udio",
   "share_address": "Podijeli adresu",
   "shared_seed_wallet_groups": "Zajedničke grupe za sjeme novčanika",
+  "show": "Pokazati",
   "show_details": "Prikaži pojedinosti",
   "show_keys": "Prikaži pristupni izraz/ključ",
   "show_market_place": "Prikaži tržište",
@@ -942,6 +948,5 @@
   "you_pay": "Vi plaćate",
   "you_will_get": "Razmijeni u",
   "you_will_send": "Razmijeni iz",
-  "yy": "GG",
-  "contact_name_exists": "Kontakt s tim imenom već postoji. Odaberite drugo ime."
-}
+  "yy": "GG"
+}
\ No newline at end of file
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index 63a986103..04a7cddf5 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Բաց ցանցի հղում",
   "close": "Փակել",
   "coin_control": "Մետաղադրամի վերահսկում (ըստ ցանկության)",
-  "cold_or_recover_wallet": "Ավելացնել սառը դրամապանակ կամ վերականգնել թղթային դրամապանակ",
+  "cold_or_recover_wallet": "Cupcake կամ ցուրտ դրամապանակից ավելացնել միայն ընթերցված դրամապանակ կամ վերականգնել թղթի դրամապանակը",
   "color_theme": "Գույների տեսք",
   "commit_transaction_amount_fee": "Հաստատել գործարքը\nՍկզբնական գումար. ${amount}\nՄիջնորդավճար. ${fee}",
   "confirm": "Հաստատել",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Կոնտակտներ",
   "contact_list_wallets": "Իմ դրամապանակներ",
   "contact_name": "Կոնտակտի անուն",
+  "contact_name_exists": "Այդ անվանման հետ կապ կա արդեն: Խնդրում ենք ընտրել այլ անուն:",
   "contact_support": "Հետադարձ կապ",
   "continue_text": "Շարունակել",
   "contract_warning": "Պայմանագրի այս հասցեն դրոշմել է որպես հնարավոր կեղծ: Խնդրում ենք զգուշությամբ մշակել:",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Վավերականություն և լրացում",
   "export_backup": "Արտահանել կրկնօրինակը",
   "export_logs": "Արտահանման տեղեկամատյաններ",
+  "export_outputs": "Արտահանման արդյունքներ",
   "extra_id": "Լրացուցիչ ID",
   "extracted_address_content": "Դուք կուղարկեք գումար ${recipient_name}",
   "failed_authentication": "Վավերացումը ձախողվեց. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven ծրագիր",
   "haven_app_wallet_text": "Հիանալի հաշվեհամար Haven համար",
   "help": "Օգնություն",
+  "hidden_addresses": "Թաքնված հասցեներ",
   "hidden_balance": "Թաքնված մնացորդ",
+  "hide": "Թաքցնել",
   "hide_details": "Թաքցնել մանրամասները",
   "high_contrast_theme": "Բարձր հակադրության տեսք",
   "home_screen_settings": "Գլխավոր էկրանի կարգավորումներ",
@@ -366,14 +370,22 @@
   "ledger_error_wrong_app": "Խնդրում ենք համոզվել, որ դուք բացել եք ճիշտ ծրագիրը ձեր Ledger-ում",
   "ledger_please_enable_bluetooth": "Խնդրում ենք միացնել Bluetooth-ը ձեր Ledger-ը հայտնաբերելու համար",
   "light_theme": "Լուսավոր",
+  "litecoin_enable_mweb_sync": "Միացնել MWEB սկան",
+  "litecoin_mweb": "Մուեբ",
+  "litecoin_mweb_always_scan": "Սահմանեք Mweb Միշտ սկանավորում",
   "litecoin_mweb_description": "Mweb- ը նոր արձանագրություն է, որը բերում է ավելի արագ, ավելի էժան եւ ավելի մասնավոր գործարքներ դեպի LITECOIN",
   "litecoin_mweb_dismiss": "Հեռացնել",
+  "litecoin_mweb_display_card": "Show ույց տալ Mweb քարտը",
   "litecoin_mweb_enable": "Միացնել Mweb- ը",
   "litecoin_mweb_enable_later": "Կարող եք ընտրել Mweb- ը կրկին միացնել ցուցադրման պարամետրերը:",
   "litecoin_mweb_logs": "Mweb տեղեկամատյաններ",
   "litecoin_mweb_node": "Mweb հանգույց",
   "litecoin_mweb_pegin": "Peg in",
   "litecoin_mweb_pegout": "Հափշտակել",
+  "litecoin_mweb_scanning": "Mweb սկանավորում",
+  "litecoin_mweb_settings": "Mweb- ի պարամետրերը",
+  "litecoin_mweb_warning": "Mweb- ի օգտագործումը սկզբում ներբեռնվի 600 ՄԲ տվյալներ եւ կարող է տեւել 30 րոպե, կախված ցանցի արագությունից: Այս նախնական տվյալները միայն մեկ անգամ ներբեռնելու են եւ հասանելի կլինեն բոլոր Litecoin դրամապանակների համար",
+  "litecoin_what_is_mweb": "Ինչ է Mweb- ը:",
   "live_fee_rates": "Ապակի վարձավճարներ API- ի միջոցով",
   "load_more": "Բեռնել ավելին",
   "loading_your_wallet": "Ձեր հաշվեհամարը բեռնում է",
@@ -492,6 +504,7 @@
   "pre_seed_title": "ԿԱՐԵՎՈՐ",
   "prepaid_cards": "Նախավճարային քարտեր",
   "prevent_screenshots": "Կանխել էկրանի պատկերները և տեսագրությունը",
+  "primary_address": "Առաջնային հասցե",
   "privacy": "Գաղտնիություն",
   "privacy_policy": "Գաղտնիության քաղաքականություն",
   "privacy_settings": "Գաղտնիության կարգավորումներ",
@@ -688,6 +701,7 @@
   "share": "Կիսվել",
   "share_address": "Կիսվել հասցեով",
   "shared_seed_wallet_groups": "Համօգտագործված սերմերի դրամապանակների խմբեր",
+  "show": "Ցուցահանդես",
   "show_details": "Ցուցադրել մանրամասներ",
   "show_keys": "Ցուցադրել բանալիներ",
   "show_market_place": "Ցուցադրել շուկան",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index 3fa3a958f..231ac037d 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Tautan clearnet",
   "close": "Menutup",
   "coin_control": "Kontrol koin (opsional)",
-  "cold_or_recover_wallet": "Tambahkan dompet dingin atau pulihkan dompet kertas",
+  "cold_or_recover_wallet": "Tambahkan dompet hanya baca dari Cupcake atau dompet dingin atau memulihkan dompet kertas",
   "color_theme": "Tema warna",
   "commit_transaction_amount_fee": "Lakukan transaksi\nJumlah: ${amount}\nBiaya: ${fee}",
   "confirm": "Konfirmasi",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Kontak",
   "contact_list_wallets": "Dompet Saya",
   "contact_name": "Nama Kontak",
+  "contact_name_exists": "Kontak dengan nama tersebut sudah ada. Silakan pilih nama lain.",
   "contact_support": "Hubungi Dukungan",
   "continue_text": "Lanjutkan",
   "contract_warning": "Alamat kontrak ini telah ditandai sebagai berpotensi curang. Silakan memproses dengan hati -hati.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Kedaluwarsa dan validitas",
   "export_backup": "Ekspor cadangan",
   "export_logs": "Log ekspor",
+  "export_outputs": "Ekspor output",
   "extra_id": "ID tambahan:",
   "extracted_address_content": "Anda akan mengirim dana ke\n${recipient_name}",
   "failed_authentication": "Otentikasi gagal. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven Oleh Cake Wallet",
   "haven_app_wallet_text": "Dompet luar biasa untuk Haven",
   "help": "bantuan",
+  "hidden_addresses": "Alamat tersembunyi",
   "hidden_balance": "Saldo Tersembunyi",
+  "hide": "Bersembunyi",
   "hide_details": "Sembunyikan Rincian",
   "high_contrast_theme": "Tema Kontras Tinggi",
   "home_screen_settings": "Pengaturan layar awal",
@@ -502,6 +506,7 @@
   "pre_seed_title": "PENTING",
   "prepaid_cards": "Kartu prabayar",
   "prevent_screenshots": "Cegah tangkapan layar dan perekaman layar",
+  "primary_address": "Alamat utama",
   "privacy": "Privasi",
   "privacy_policy": "Kebijakan Privasi",
   "privacy_settings": "Pengaturan privasi",
@@ -699,6 +704,7 @@
   "share": "Membagikan",
   "share_address": "Bagikan alamat",
   "shared_seed_wallet_groups": "Kelompok dompet benih bersama",
+  "show": "Menunjukkan",
   "show_details": "Tampilkan Rincian",
   "show_keys": "Tampilkan seed/kunci",
   "show_market_place": "Tampilkan Pasar",
@@ -945,6 +951,5 @@
   "you_pay": "Anda Membayar",
   "you_will_get": "Konversi ke",
   "you_will_send": "Konversi dari",
-  "yy": "YY",
-  "contact_name_exists": "Kontak dengan nama tersebut sudah ada. Silakan pilih nama lain."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index aab18d434..b06a35537 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Collegamento Clearnet",
   "close": "Chiudere",
   "coin_control": "Controllo monete (opzionale)",
-  "cold_or_recover_wallet": "Aggiungi un cold wallet o recupera un paper wallet",
+  "cold_or_recover_wallet": "Aggiungi un portafoglio di sola lettura da Cupcake o un portafoglio freddo o recupera un portafoglio di carta",
   "color_theme": "Colore tema",
   "commit_transaction_amount_fee": "Invia transazione\nAmmontare: ${amount}\nCommissione: ${fee}",
   "confirm": "Conferma",
@@ -162,6 +162,7 @@
   "contact_list_contacts": "Contatti",
   "contact_list_wallets": "I miei portafogli",
   "contact_name": "Nome Contatto",
+  "contact_name_exists": "Esiste già un contatto con quel nome. Scegli un nome diverso.",
   "contact_support": "Contatta l'assistenza",
   "continue_text": "Continua",
   "contract_warning": "Questo indirizzo del contratto è stato contrassegnato come potenzialmente fraudolento. Si prega di elaborare con cautela.",
@@ -297,6 +298,7 @@
   "expiry_and_validity": "Scadenza e validità",
   "export_backup": "Esporta backup",
   "export_logs": "Registri di esportazione",
+  "export_outputs": "Output di esportazione",
   "extra_id": "Extra ID:",
   "extracted_address_content": "Invierai i tuoi fondi a\n${recipient_name}",
   "failed_authentication": "Autenticazione fallita. ${state_error}",
@@ -337,7 +339,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Portafoglio fantastico per Haven",
   "help": "aiuto",
+  "hidden_addresses": "Indirizzi nascosti",
   "hidden_balance": "Saldo Nascosto",
+  "hide": "Nascondere",
   "hide_details": "Nascondi dettagli",
   "high_contrast_theme": "Tema ad alto contrasto",
   "home_screen_settings": "Impostazioni della schermata iniziale",
@@ -502,6 +506,7 @@
   "pre_seed_title": "IMPORTANTE",
   "prepaid_cards": "Carte prepagata",
   "prevent_screenshots": "Impedisci screenshot e registrazione dello schermo",
+  "primary_address": "Indirizzo primario",
   "privacy": "Privacy",
   "privacy_policy": "Informativa sulla privacy",
   "privacy_settings": "Impostazioni privacy",
@@ -698,6 +703,7 @@
   "share": "Condividere",
   "share_address": "Condividi indirizzo",
   "shared_seed_wallet_groups": "Gruppi di portafoglio di semi condivisi",
+  "show": "Spettacolo",
   "show_details": "Mostra dettagli",
   "show_keys": "Mostra seme/chiavi",
   "show_market_place": "Mostra mercato",
@@ -945,6 +951,5 @@
   "you_pay": "Tu paghi",
   "you_will_get": "Converti a",
   "you_will_send": "Conveti da",
-  "yy": "YY",
-  "contact_name_exists": "Esiste già un contatto con quel nome. Scegli un nome diverso."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index f1fd0acd3..d55c4d5a1 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "クリアネット リンク",
   "close": "近い",
   "coin_control": "コインコントロール(オプション)",
-  "cold_or_recover_wallet": "コールド ウォレットを追加するか、ペーパー ウォレットを復元する",
+  "cold_or_recover_wallet": "Cupcakeまたはコールドウォレットから読み取り専用ウォレットを追加するか、紙の財布を回収する",
   "color_theme": "カラーテーマ",
   "commit_transaction_amount_fee": "トランザクションをコミット\n量: ${amount}\n費用: ${fee}",
   "confirm": "確認する",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "連絡先",
   "contact_list_wallets": "マイウォレット",
   "contact_name": "連絡先",
+  "contact_name_exists": "その名前の連絡先はすでに存在します。別の名前を選択してください。",
   "contact_support": "サポートに連絡する",
   "continue_text": "持続する",
   "contract_warning": "この契約住所は、潜在的に不正としてフラグが立てられています。注意して処理してください。",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "有効期限と有効性",
   "export_backup": "バックアップのエクスポート",
   "export_logs": "ログをエクスポートします",
+  "export_outputs": "エクスポート出力",
   "extra_id": "追加ID:",
   "extracted_address_content": "に送金します\n${recipient_name}",
   "failed_authentication": "認証失敗. ${state_error}",
@@ -337,7 +339,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "ヘルプ",
+  "hidden_addresses": "隠されたアドレス",
   "hidden_balance": "隠れたバランス",
+  "hide": "隠れる",
   "hide_details": "詳細を非表示",
   "high_contrast_theme": "ハイコントラストテーマ",
   "home_screen_settings": "ホーム画面の設定",
@@ -501,6 +505,7 @@
   "pre_seed_title": "重要",
   "prepaid_cards": "プリペイドカード",
   "prevent_screenshots": "スクリーンショットと画面録画を防止する",
+  "primary_address": "主なアドレス",
   "privacy": "プライバシー",
   "privacy_policy": "プライバシーポリシー",
   "privacy_settings": "プライバシー設定",
@@ -697,6 +702,7 @@
   "share": "共有",
   "share_address": "住所を共有する",
   "shared_seed_wallet_groups": "共有シードウォレットグループ",
+  "show": "見せる",
   "show_details": "詳細を表示",
   "show_keys": "シード/キーを表示する",
   "show_market_place": "マーケットプレイスを表示",
@@ -943,6 +949,5 @@
   "you_pay": "あなたが支払う",
   "you_will_get": "に変換",
   "you_will_send": "から変換",
-  "yy": "YY",
-  "contact_name_exists": "その名前の連絡先はすでに存在します。別の名前を選択してください。"
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 7e3467cf2..303527fea 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "클리어넷 링크",
   "close": "닫다",
   "coin_control": "코인 제어 (옵션)",
-  "cold_or_recover_wallet": "콜드 지갑 추가 또는 종이 지갑 복구",
+  "cold_or_recover_wallet": "Cupcake 또는 차가운 지갑에서 읽기 전용 지갑을 추가하거나 종이 지갑을 복구하십시오.",
   "color_theme": "색상 테마",
   "commit_transaction_amount_fee": "커밋 거래\n양: ${amount}\n보수: ${fee}",
   "confirm": "확인",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "콘택트 렌즈",
   "contact_list_wallets": "내 지갑",
   "contact_name": "담당자 이름",
+  "contact_name_exists": "해당 이름을 가진 연락처가 이미 존재합니다. 다른 이름을 선택하세요.",
   "contact_support": "지원팀에 문의",
   "continue_text": "잇다",
   "contract_warning": "이 계약 주소는 잠재적으로 사기성으로 표시되었습니다. 주의해서 처리하십시오.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "만료와 타당성",
   "export_backup": "백업 내보내기",
   "export_logs": "내보내기 로그",
+  "export_outputs": "내보내기 출력",
   "extra_id": "추가 ID:",
   "extracted_address_content": "당신은에 자금을 보낼 것입니다\n${recipient_name}",
   "failed_authentication": "인증 실패. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "돕다",
+  "hidden_addresses": "숨겨진 주소",
   "hidden_balance": "숨겨진 균형",
+  "hide": "숨다",
   "hide_details": "세부 정보 숨기기",
   "high_contrast_theme": "고대비 테마",
   "home_screen_settings": "홈 화면 설정",
@@ -501,6 +505,7 @@
   "pre_seed_title": "중대한",
   "prepaid_cards": "선불 카드",
   "prevent_screenshots": "스크린샷 및 화면 녹화 방지",
+  "primary_address": "기본 주소",
   "privacy": "프라이버시",
   "privacy_policy": "개인 정보 보호 정책",
   "privacy_settings": "개인정보 설정",
@@ -697,6 +702,7 @@
   "share": "공유하다",
   "share_address": "주소 공유",
   "shared_seed_wallet_groups": "공유 종자 지갑 그룹",
+  "show": "보여주다",
   "show_details": "세부정보 표시",
   "show_keys": "시드 / 키 표시",
   "show_market_place": "마켓플레이스 표시",
@@ -944,6 +950,5 @@
   "you_will_get": "로 변환하다",
   "you_will_send": "다음에서 변환",
   "YY": "YY",
-  "yy": "YY",
-  "contact_name_exists": "해당 이름을 가진 연락처가 이미 존재합니다. 다른 이름을 선택하세요."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index 10c13cfef..9b9b44657 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Clearnet လင့်ခ်",
   "close": "အနီးကပ်",
   "coin_control": "အကြွေစေ့ထိန်းချုပ်မှု (ချန်လှပ်ထားနိုင်သည်)",
-  "cold_or_recover_wallet": "အေးသောပိုက်ဆံအိတ်ထည့်ပါ သို့မဟုတ် စက္ကူပိုက်ဆံအိတ်ကို ပြန်ယူပါ။",
+  "cold_or_recover_wallet": "Cupcake သို့မဟုတ်အအေးပိုက်ဆံအိတ်မှဖတ်ရန်သာပိုက်ဆံအိတ်တစ်ခုထည့်ပါသို့မဟုတ်စက္ကူပိုက်ဆံအိတ်ကိုပြန်လည်ရယူပါ",
   "color_theme": "အရောင်အပြင်အဆင်",
   "commit_transaction_amount_fee": "ငွေလွှဲခြင်း\nပမာဏ- ${amount}\nအခကြေးငွေ- ${fee}",
   "confirm": "အတည်ပြုပါ။",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "အဆက်အသွယ်များ",
   "contact_list_wallets": "ကျွန်ုပ်၏ ပိုက်ဆံအိတ်များ",
   "contact_name": "ဆက်သွယ်ရန်အမည်",
+  "contact_name_exists": "ထိုအမည်နှင့် အဆက်အသွယ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ။",
   "contact_support": "ပံ့ပိုးကူညီမှုထံ ဆက်သွယ်ပါ။",
   "continue_text": "ဆက်လက်",
   "contract_warning": "ဒီစာချုပ်လိပ်စာအလားအလာအလားအလာအလားအလာအလံများကိုအလံလွှင့်တင်ခဲ့သည်။ ကျေးဇူးပြုပြီးသတိဖြင့်လုပ်ငန်းစဉ်။",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "သက်တမ်းကုန်ဆုံးခြင်းနှင့်တရားဝင်မှု",
   "export_backup": "အရန်ကူးထုတ်ရန်",
   "export_logs": "ပို့ကုန်မှတ်တမ်းများ",
+  "export_outputs": "ပို့ကုန်ထုတ်ကုန်များ",
   "extra_id": "အပို ID-",
   "extracted_address_content": "သင်သည် \n${recipient_name} သို့ ရန်ပုံငွေများ ပေးပို့ပါမည်",
   "failed_authentication": "အထောက်အထားစိစစ်ခြင်း မအောင်မြင်ပါ။. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "ဟေးဗင် ကိတ် ဝေါလက်",
   "haven_app_wallet_text": "ဟေဗင်အတွက် အံ့ဩစရာကောင်းတဲ့ ပိုက်ဆံအုံး",
   "help": "ကူညီပါ",
+  "hidden_addresses": "လျှို့ဝှက်လိပ်စာများ",
   "hidden_balance": "Hidden Balance",
+  "hide": "သားရေ",
   "hide_details": "အသေးစိတ်ကို ဝှက်ပါ။",
   "high_contrast_theme": "အလင်းအမှောင် မြင့်မားသော အပြင်အဆင်",
   "home_screen_settings": "ပင်မစခရင် ဆက်တင်များ",
@@ -500,6 +504,7 @@
   "pre_seed_title": "အရေးကြီးသည်။",
   "prepaid_cards": "ကြိုတင်ငွေဖြည့်ကဒ်များ",
   "prevent_screenshots": "ဖန်သားပြင်ဓာတ်ပုံများနှင့် မျက်နှာပြင်ရိုက်ကူးခြင်းကို တားဆီးပါ။",
+  "primary_address": "အဓိကလိပ်စာ",
   "privacy": "ကိုယ်ရေးကိုယ်တာ",
   "privacy_policy": "ကိုယ်ရေးအချက်အလက်မူဝါဒ",
   "privacy_settings": "Privacy settings တွေကို",
@@ -696,6 +701,7 @@
   "share": "မျှဝေပါ။",
   "share_address": "လိပ်စာမျှဝေပါ။",
   "shared_seed_wallet_groups": "shared မျိုးစေ့ပိုက်ဆံအိတ်အုပ်စုများ",
+  "show": "ပြသ",
   "show_details": "အသေးစိတ်ပြ",
   "show_keys": "မျိုးစေ့ /သော့များကို ပြပါ။",
   "show_market_place": "စျေးကွက်ကိုပြသပါ။",
@@ -942,6 +948,5 @@
   "you_pay": "သင်ပေးချေပါ။",
   "you_will_get": "သို့ပြောင်းပါ။",
   "you_will_send": "မှပြောင်းပါ။",
-  "yy": "YY",
-  "contact_name_exists": "ထိုအမည်နှင့် အဆက်အသွယ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ။"
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 9552f2439..657450f61 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Clearnet-link",
   "close": "Dichtbij",
   "coin_control": "Muntcontrole (optioneel)",
-  "cold_or_recover_wallet": "Voeg een cold wallet toe of herstel een paper wallet",
+  "cold_or_recover_wallet": "Voeg een alleen-lezen portemonnee toe van Cupcake of een koude portemonnee of herstel een papieren portemonnee",
   "color_theme": "Kleur thema",
   "commit_transaction_amount_fee": "Verricht transactie\nBedrag: ${amount}\nhonorarium: ${fee}",
   "confirm": "Bevestigen",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Contacten",
   "contact_list_wallets": "Mijn portefeuilles",
   "contact_name": "Contactnaam",
+  "contact_name_exists": "Er bestaat al een contact met die naam. Kies een andere naam.",
   "contact_support": "Contact opnemen met ondersteuning",
   "continue_text": "Doorgaan met",
   "contract_warning": "Dit contractadres is gemarkeerd als mogelijk frauduleus. Verwerk met voorzichtigheid.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Vervallen en geldigheid",
   "export_backup": "Back-up exporteren",
   "export_logs": "Exporteer logboeken",
+  "export_outputs": "Exportuitgangen exporteren",
   "extra_id": "Extra ID:",
   "extracted_address_content": "U stuurt geld naar\n${recipient_name}",
   "failed_authentication": "Mislukte authenticatie. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "helpen",
+  "hidden_addresses": "Verborgen adressen",
   "hidden_balance": "Verborgen balans",
+  "hide": "Verbergen",
   "hide_details": "Details verbergen",
   "high_contrast_theme": "Thema met hoog contrast",
   "home_screen_settings": "Instellingen voor het startscherm",
@@ -500,6 +504,7 @@
   "pre_seed_title": "BELANGRIJK",
   "prepaid_cards": "Prepaid-kaarten",
   "prevent_screenshots": "Voorkom screenshots en schermopname",
+  "primary_address": "Primair adres",
   "privacy": "Privacy",
   "privacy_policy": "Privacybeleid",
   "privacy_settings": "Privacy-instellingen",
@@ -696,6 +701,7 @@
   "share": "Deel",
   "share_address": "Deel adres",
   "shared_seed_wallet_groups": "Gedeelde zaadportelgroepen",
+  "show": "Show",
   "show_details": "Toon details",
   "show_keys": "Toon zaad/sleutels",
   "show_market_place": "Toon Marktplaats",
@@ -943,6 +949,5 @@
   "you_pay": "U betaalt",
   "you_will_get": "Converteren naar",
   "you_will_send": "Converteren van",
-  "yy": "JJ",
-  "contact_name_exists": "Er bestaat al een contact met die naam. Kies een andere naam."
-}
+  "yy": "JJ"
+}
\ No newline at end of file
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index f3c3e4810..e47c93dcf 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "łącze Clearnet",
   "close": "Zamknąć",
   "coin_control": "Kontrola monet (opcjonalnie)",
-  "cold_or_recover_wallet": "Dodaj zimny portfel lub odzyskaj portfel papierowy",
+  "cold_or_recover_wallet": "Dodaj portfel tylko do odczytu od Cupcake lub zimnego portfela lub odzyskaj papierowy portfel",
   "color_theme": "Motyw kolorystyczny",
   "commit_transaction_amount_fee": "Zatwierdź transakcję\nIlość: ${amount}\nOpłata: ${fee}",
   "confirm": "Potwierdzać",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Łączność",
   "contact_list_wallets": "Moje portfele",
   "contact_name": "Nazwa Kontaktu",
+  "contact_name_exists": "Kontakt o tej nazwie już istnieje. Proszę wybrać inną nazwę.",
   "contact_support": "Skontaktuj się z pomocą techniczną",
   "continue_text": "Dalej",
   "contract_warning": "Ten adres umowy został oznaczony jako potencjalnie nieuczciwy. Prosimy o ostrożność.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Wygaśnięcie i ważność",
   "export_backup": "Eksportuj kopię zapasową",
   "export_logs": "Dzienniki eksportu",
+  "export_outputs": "Wyjścia eksportowe",
   "extra_id": "Dodatkowy ID:",
   "extracted_address_content": "Wysyłasz środki na\n${recipient_name}",
   "failed_authentication": "Nieudane uwierzytelnienie. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "pomoc",
+  "hidden_addresses": "Ukryte adresy",
   "hidden_balance": "Ukryte saldo",
+  "hide": "Ukrywać",
   "hide_details": "Ukryj szczegóły",
   "high_contrast_theme": "Motyw o wysokim kontraście",
   "home_screen_settings": "Ustawienia ekranu głównego",
@@ -500,6 +504,7 @@
   "pre_seed_title": "WAŻNY",
   "prepaid_cards": "Karty przedpłacone",
   "prevent_screenshots": "Zapobiegaj zrzutom ekranu i nagrywaniu ekranu",
+  "primary_address": "Adres podstawowy",
   "privacy": "Prywatność",
   "privacy_policy": "Polityka prywatności",
   "privacy_settings": "Ustawienia prywatności",
@@ -696,6 +701,7 @@
   "share": "Udział",
   "share_address": "Udostępnij adres",
   "shared_seed_wallet_groups": "Wspólne grupy portfeli nasion",
+  "show": "Pokazywać",
   "show_details": "Pokaż szczegóły",
   "show_keys": "Pokaż seed/klucze",
   "show_market_place": "Pokaż rynek",
@@ -942,6 +948,5 @@
   "you_pay": "Płacisz",
   "you_will_get": "Konwertuj na",
   "you_will_send": "Konwertuj z",
-  "yy": "RR",
-  "contact_name_exists": "Kontakt o tej nazwie już istnieje. Proszę wybrać inną nazwę."
-}
+  "yy": "RR"
+}
\ No newline at end of file
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index 410e8cb1c..d5aa95c16 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "link clear net",
   "close": "Fechar",
   "coin_control": "Controle de moedas (opcional)",
-  "cold_or_recover_wallet": "Adicione uma cold wallet ou recupere uma paper wallet",
+  "cold_or_recover_wallet": "Adicione uma carteira somente leitura de Cupcake ou uma carteira fria ou recupere uma carteira de papel",
   "color_theme": "Tema de cor",
   "commit_transaction_amount_fee": "Confirmar transação\nQuantia: ${amount}\nTaxa: ${fee}",
   "confirm": "Confirmar",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Contatos",
   "contact_list_wallets": "minhas carteiras",
   "contact_name": "Nome do contato",
+  "contact_name_exists": "Um contato com esse nome já existe. Escolha um nome diferente.",
   "contact_support": "Contatar Suporte",
   "continue_text": "Continuar",
   "contract_warning": "Este endereço do contrato foi sinalizado como potencialmente fraudulento. Por favor, processe com cautela.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Expiração e validade",
   "export_backup": "Backup de exportação",
   "export_logs": "Exportar logs",
+  "export_outputs": "Saídas de exportação",
   "extra_id": "ID extra:",
   "extracted_address_content": "Você enviará fundos para\n${recipient_name}",
   "failed_authentication": "Falha na autenticação. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "ajuda",
+  "hidden_addresses": "Endereços ocultos",
   "hidden_balance": "Saldo escondido",
+  "hide": "Esconder",
   "hide_details": "Ocultar detalhes",
   "high_contrast_theme": "Tema de alto contraste",
   "home_screen_settings": "Configurações da tela inicial",
@@ -502,6 +506,7 @@
   "pre_seed_title": "IMPORTANTE",
   "prepaid_cards": "Cartões pré-pagos",
   "prevent_screenshots": "Evite capturas de tela e gravação de tela",
+  "primary_address": "Endereço primário",
   "privacy": "Privacidade",
   "privacy_policy": "Política de privacidade",
   "privacy_settings": "Configurações de privacidade",
@@ -698,6 +703,7 @@
   "share": "Compartilhar",
   "share_address": "Compartilhar endereço",
   "shared_seed_wallet_groups": "Grupos de carteira de sementes compartilhados",
+  "show": "Mostrar",
   "show_details": "Mostrar detalhes",
   "show_keys": "Mostrar semente/chaves",
   "show_market_place": "Mostrar mercado",
@@ -946,4 +952,4 @@
   "you_will_get": "Converter para",
   "you_will_send": "Converter de",
   "yy": "aa"
-}
+}
\ No newline at end of file
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index a8ee5a309..f999b4aaa 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Клирнет ссылка",
   "close": "Закрывать",
   "coin_control": "Контроль монет (необязательно)",
-  "cold_or_recover_wallet": "Добавьте холодный кошелек или восстановите бумажный кошелек",
+  "cold_or_recover_wallet": "Добавить кошелек только для чтения из Cupcake или холодный кошелек или восстановить бумажный кошелек",
   "color_theme": "Цветовая тема",
   "commit_transaction_amount_fee": "Подтвердить транзакцию \nСумма: ${amount}\nКомиссия: ${fee}",
   "confirm": "Подтвердить",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Контакты",
   "contact_list_wallets": "Мои кошельки",
   "contact_name": "Имя контакта",
+  "contact_name_exists": "Контакт с таким именем уже существует. Пожалуйста, выберите другое имя.",
   "contact_support": "Связаться со службой поддержки",
   "continue_text": "Продолжить",
   "contract_warning": "Этот адрес контракта был отмечен как потенциально мошеннический. Пожалуйста, обработайтесь с осторожностью.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Истечение и достоверность",
   "export_backup": "Экспорт резервной копии",
   "export_logs": "Экспортные журналы",
+  "export_outputs": "Экспортные выходы",
   "extra_id": "Дополнительный ID:",
   "extracted_address_content": "Вы будете отправлять средства\n${recipient_name}",
   "failed_authentication": "Ошибка аутентификации. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "помощь",
+  "hidden_addresses": "Скрытые адреса",
   "hidden_balance": "Скрытый баланс",
+  "hide": "Скрывать",
   "hide_details": "Скрыть детали",
   "high_contrast_theme": "Высококонтрастная тема",
   "home_screen_settings": "Настройки главного экрана",
@@ -501,6 +505,7 @@
   "pre_seed_title": "ВАЖНО",
   "prepaid_cards": "Предоплаченные карты",
   "prevent_screenshots": "Предотвратить скриншоты и запись экрана",
+  "primary_address": "Первичный адрес",
   "privacy": "Конфиденциальность",
   "privacy_policy": "Политика конфиденциальности",
   "privacy_settings": "Настройки конфиденциальности",
@@ -697,6 +702,7 @@
   "share": "Делиться",
   "share_address": "Поделиться адресом",
   "shared_seed_wallet_groups": "Общие группы кошелька семян",
+  "show": "Показывать",
   "show_details": "Показать детали",
   "show_keys": "Показать мнемоническую фразу/ключи",
   "show_market_place": "Показать торговую площадку",
@@ -943,6 +949,5 @@
   "you_pay": "Вы платите",
   "you_will_get": "Конвертировать в",
   "you_will_send": "Конвертировать из",
-  "yy": "ГГ",
-  "contact_name_exists": "Контакт с таким именем уже существует. Пожалуйста, выберите другое имя."
-}
+  "yy": "ГГ"
+}
\ No newline at end of file
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index 5102e150c..a35e16a97 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "ลิงค์เคลียร์เน็ต",
   "close": "ปิด",
   "coin_control": "การควบคุมเหรียญ (ตัวเลือก)",
-  "cold_or_recover_wallet": "เพิ่มกระเป๋าเงินเย็นหรือกู้คืนกระเป๋าเงินกระดาษ",
+  "cold_or_recover_wallet": "เพิ่มกระเป๋าเงินแบบอ่านอย่างเดียวจาก Cupcake หรือกระเป๋าเงินเย็นหรือกู้คืนกระเป๋ากระดาษ",
   "color_theme": "ธีมสี",
   "commit_transaction_amount_fee": "ยืนยันธุรกรรม\nจำนวน: ${amount}\nค่าธรรมเนียม: ${fee}",
   "confirm": "ยืนยัน",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "ติดต่อ",
   "contact_list_wallets": "กระเป๋าเงินของฉัน",
   "contact_name": "ชื่อผู้ติดต่อ",
+  "contact_name_exists": "มีผู้ติดต่อชื่อนั้นอยู่แล้ว โปรดเลือกชื่ออื่น",
   "contact_support": "ติดต่อฝ่ายสนับสนุน",
   "continue_text": "ดำเนินการต่อ",
   "contract_warning": "ที่อยู่สัญญานี้ได้รับการตั้งค่าสถานะว่าเป็นการฉ้อโกง กรุณาดำเนินการด้วยความระมัดระวัง",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "หมดอายุและถูกต้อง",
   "export_backup": "ส่งออกข้อมูลสำรอง",
   "export_logs": "บันทึกการส่งออก",
+  "export_outputs": "เอาต์พุตส่งออก",
   "extra_id": "ไอดีเพิ่มเติม:",
   "extracted_address_content": "คุณกำลังจะส่งเงินไปยัง\n${recipient_name}",
   "failed_authentication": "การยืนยันสิทธิ์ล้มเหลว ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven ของ Cake Wallet",
   "haven_app_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Haven",
   "help": "ช่วยเหลือ",
+  "hidden_addresses": "ที่อยู่ที่ซ่อนอยู่",
   "hidden_balance": "ยอดคงเหลือซ่อนอยู่",
+  "hide": "ซ่อน",
   "hide_details": "ซ่อนรายละเอียด",
   "high_contrast_theme": "ธีมความคมชัดสูง",
   "home_screen_settings": "การตั้งค่าหน้าจอหลัก",
@@ -500,6 +504,7 @@
   "pre_seed_title": "สำคัญ",
   "prepaid_cards": "บัตรเติมเงิน",
   "prevent_screenshots": "ป้องกันภาพหน้าจอและการบันทึกหน้าจอ",
+  "primary_address": "ที่อยู่ปฐมภูมิ",
   "privacy": "ความเป็นส่วนตัว",
   "privacy_policy": "นโยบายความเป็นส่วนตัว",
   "privacy_settings": "การตั้งค่าความเป็นส่วนตัว",
@@ -696,6 +701,7 @@
   "share": "แบ่งปัน",
   "share_address": "แชร์ที่อยู่",
   "shared_seed_wallet_groups": "กลุ่มกระเป๋าเงินที่ใช้ร่วมกัน",
+  "show": "แสดง",
   "show_details": "แสดงรายละเอียด",
   "show_keys": "แสดงซีด/คีย์",
   "show_market_place": "แสดงตลาดกลาง",
@@ -942,6 +948,5 @@
   "you_pay": "คุณจ่าย",
   "you_will_get": "แปลงเป็น",
   "you_will_send": "แปลงจาก",
-  "yy": "ปี",
-  "contact_name_exists": "มีผู้ติดต่อชื่อนั้นอยู่แล้ว โปรดเลือกชื่ออื่น"
-}
+  "yy": "ปี"
+}
\ No newline at end of file
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index eb78c8d3c..090bdb8a7 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Link ng Clearnet",
   "close": "Isara",
   "coin_control": "Coin control (opsyonal)",
-  "cold_or_recover_wallet": "Magdagdag ng isang cold wallet o mabawi ang isang paper wallet",
+  "cold_or_recover_wallet": "Magdagdag ng isang basahin lamang na pitaka mula sa Cupcake o isang malamig na pitaka o mabawi ang isang wallet ng papel",
   "color_theme": "Color theme",
   "commit_transaction_amount_fee": "Gumawa ng transaksyon\nHalaga: ${amount}\nFee: ${fee}",
   "confirm": "Kumpirmahin",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Mga Contact",
   "contact_list_wallets": "Mga Wallet Ko",
   "contact_name": "Pangalan ng Contact",
+  "contact_name_exists": "Ang isang pakikipag -ugnay sa pangalang iyon ay mayroon na. Mangyaring pumili ng ibang pangalan.",
   "contact_support": "Makipag-ugnay sa Suporta",
   "continue_text": "Magpatuloy",
   "contract_warning": "Ang address ng kontrata na ito ay na -flag bilang potensyal na mapanlinlang. Mangyaring iproseso nang may pag -iingat.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Pag-expire at Bisa",
   "export_backup": "I-export ang backup",
   "export_logs": "Mga log ng pag -export",
+  "export_outputs": "Mga output ng pag -export",
   "extra_id": "Dagdag na ID:",
   "extracted_address_content": "Magpapadala ka ng pondo sa\n${recipient_name}",
   "failed_authentication": "Nabigo ang pagpapatunay. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Kahanga-hangang wallet para sa Haven",
   "help": "Tulong",
+  "hidden_addresses": "Nakatagong mga address",
   "hidden_balance": "Nakatagong Balanse",
+  "hide": "Itago",
   "hide_details": "Itago ang mga detalye",
   "high_contrast_theme": "High Contrast Theme",
   "home_screen_settings": "Mga setting ng home screen",
@@ -500,6 +504,7 @@
   "pre_seed_title": "Mahalaga",
   "prepaid_cards": "Mga Prepaid Card",
   "prevent_screenshots": "Maiwasan ang mga screenshot at pag -record ng screen",
+  "primary_address": "Pangunahing address",
   "privacy": "Privacy",
   "privacy_policy": "Patakaran sa Pagkapribado",
   "privacy_settings": "Settings para sa pagsasa-pribado",
@@ -696,6 +701,7 @@
   "share": "Ibahagi",
   "share_address": "Ibahagi ang address",
   "shared_seed_wallet_groups": "Ibinahaging mga pangkat ng pitaka ng binhi",
+  "show": "Ipakita",
   "show_details": "Ipakita ang mga detalye",
   "show_keys": "Ipakita ang mga seed/key",
   "show_market_place": "Ipakita ang Marketplace",
@@ -943,4 +949,4 @@
   "you_will_get": "I-convert sa",
   "you_will_send": "I-convert mula sa",
   "yy": "YY"
-}
+}
\ No newline at end of file
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index 0b4700397..3a426de9e 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Net bağlantı",
   "close": "Kapalı",
   "coin_control": "Koin kontrolü (isteğe bağlı)",
-  "cold_or_recover_wallet": "Soğuk bir cüzdan ekleyin veya bir kağıt cüzdanı kurtarın",
+  "cold_or_recover_wallet": "Cupcake veya soğuk bir cüzdandan salt okunur bir cüzdan ekleyin veya bir kağıt cüzdanı kurtar",
   "color_theme": "Renk teması",
   "commit_transaction_amount_fee": "Transferi gerçekleştir\nMiktar: ${amount}\nKomisyon: ${fee}",
   "confirm": "Onayla",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Rehberim",
   "contact_list_wallets": "Cüzdanlarım",
   "contact_name": "Kişi ismi",
+  "contact_name_exists": "Bu isimde bir kişi zaten mevcut. Lütfen farklı bir ad seçin.",
   "contact_support": "Destek ile İletişime Geç",
   "continue_text": "Devam et",
   "contract_warning": "Bu sözleşme adresi potansiyel olarak hileli olarak işaretlenmiştir. Lütfen dikkatle işleyin.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Sona erme ve geçerlilik",
   "export_backup": "Yedeği dışa aktar",
   "export_logs": "Dışa aktarma günlükleri",
+  "export_outputs": "İhracat çıktıları",
   "extra_id": "Ekstra ID:",
   "extracted_address_content": "Parayı buraya gönderceksin:\n${recipient_name}",
   "failed_authentication": "Doğrulama başarısız oldu. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Cake Wallet tarafından Haven",
   "haven_app_wallet_text": "Haven için harika cüzdan ",
   "help": "yardım",
+  "hidden_addresses": "Gizli adresler",
   "hidden_balance": "Gizli Bakiye",
+  "hide": "Saklamak",
   "hide_details": "Detayları Gizle",
   "high_contrast_theme": "Yüksek Kontrastlı Tema",
   "home_screen_settings": "Ana ekran ayarları",
@@ -500,6 +504,7 @@
   "pre_seed_title": "UYARI",
   "prepaid_cards": "Ön ödemeli kartlar",
   "prevent_screenshots": "Ekran görüntülerini ve ekran kaydını önleyin",
+  "primary_address": "Birincil adres",
   "privacy": "Gizlilik",
   "privacy_policy": "Gizlilik Politikası",
   "privacy_settings": "Gizlilik ayarları",
@@ -696,6 +701,7 @@
   "share": "Paylaşmak",
   "share_address": "Adresi paylaş",
   "shared_seed_wallet_groups": "Paylaşılan tohum cüzdan grupları",
+  "show": "Göstermek",
   "show_details": "Detayları Göster",
   "show_keys": "Tohumları/anahtarları göster",
   "show_market_place": "Pazar Yerini Göster",
@@ -942,6 +948,5 @@
   "you_pay": "Şu kadar ödeyeceksin: ",
   "you_will_get": "Biçimine dönüştür:",
   "you_will_send": "Biçiminden dönüştür:",
-  "yy": "YY",
-  "contact_name_exists": "Bu isimde bir kişi zaten mevcut. Lütfen farklı bir ad seçin."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index c9afde7be..63665875f 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Посилання Clearnet",
   "close": "Закрити",
   "coin_control": "Контроль монет (необов’язково)",
-  "cold_or_recover_wallet": "Додайте холодний гаманець або відновіть паперовий гаманець",
+  "cold_or_recover_wallet": "Додайте гаманець лише для читання від Cupcake або холодного гаманця або відновіть паперовий гаманець",
   "color_theme": "Кольорова тема",
   "commit_transaction_amount_fee": "Підтвердити транзакцію \nСума: ${amount}\nКомісія: ${fee}",
   "confirm": "Підтвердити",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Контакти",
   "contact_list_wallets": "Мої гаманці",
   "contact_name": "Ім'я контакту",
+  "contact_name_exists": "Контакт із такою назвою вже існує. Виберіть інше ім'я.",
   "contact_support": "Звернутися до служби підтримки",
   "continue_text": "Продовжити",
   "contract_warning": "Ця адреса контракту була позначена як потенційно шахрайська. Будь ласка, обробляйте обережно.",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "Закінчення та обгрунтованість",
   "export_backup": "Експортувати резервну копію",
   "export_logs": "Експортні журнали",
+  "export_outputs": "Експортні результати",
   "extra_id": "Додатковий ID:",
   "extracted_address_content": "Ви будете відправляти кошти\n${recipient_name}",
   "failed_authentication": "Помилка аутентифікації. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "допомога",
+  "hidden_addresses": "Приховані адреси",
   "hidden_balance": "Прихований баланс",
+  "hide": "Сховати",
   "hide_details": "Приховати деталі",
   "high_contrast_theme": "Тема високої контрастності",
   "home_screen_settings": "Налаштування головного екрана",
@@ -500,6 +504,7 @@
   "pre_seed_title": "ВАЖЛИВО",
   "prepaid_cards": "Передплачені картки",
   "prevent_screenshots": "Запобігати знімкам екрана та запису екрана",
+  "primary_address": "Первинна адреса",
   "privacy": "Конфіденційність",
   "privacy_policy": "Політика конфіденційності",
   "privacy_settings": "Налаштування конфіденційності",
@@ -697,6 +702,7 @@
   "share": "Поділіться",
   "share_address": "Поділитися адресою",
   "shared_seed_wallet_groups": "Спільні групи насіннєвих гаманців",
+  "show": "Показувати",
   "show_details": "Показати деталі",
   "show_keys": "Показати мнемонічну фразу/ключі",
   "show_market_place": "Відображати маркетплейс",
@@ -943,6 +949,5 @@
   "you_pay": "Ви платите",
   "you_will_get": "Конвертувати в",
   "you_will_send": "Конвертувати з",
-  "yy": "YY",
-  "contact_name_exists": "Контакт із такою назвою вже існує. Виберіть інше ім'я."
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index 50c6f1889..2a40fbe13 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "کلیرنیٹ لنک",
   "close": "بند کریں",
   "coin_control": "سکے کنٹرول (اختیاری)",
-  "cold_or_recover_wallet": "ٹھنڈا پرس ڈالیں یا کاغذ کا پرس بازیافت کریں",
+  "cold_or_recover_wallet": "Cupcake یا سرد بٹوے سے صرف ایک پڑھنے والا پرس شامل کریں یا کاغذ کا پرس بازیافت کریں",
   "color_theme": "رنگین تھیم",
   "commit_transaction_amount_fee": "لین دین کا ارتکاب کریں\\nرقم: ${amount}\\nفیس: ${fee}",
   "confirm": "تصدیق کریں۔",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "رابطے",
   "contact_list_wallets": "میرے بٹوے",
   "contact_name": "رابطے کا نام",
+  "contact_name_exists": " ۔ﮟﯾﺮﮐ ﺐﺨﺘﻨﻣ ﻡﺎﻧ ﻒﻠﺘﺨﻣ ﮏﯾﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮯﮨ ﺩﻮﺟﻮﻣ ﮯﺳ ﮯﻠﮩﭘ ﮧﻄﺑﺍﺭ ﮏﯾﺍ ﮫﺗﺎﺳ ﮯﮐ ﻡﺎﻧ ﺱﺍ",
   "contact_support": "سپورٹ سے رابطہ کریں۔",
   "continue_text": "جاری رہے",
   "contract_warning": "اس معاہدے کے پتے کو ممکنہ طور پر جعلی قرار دیا گیا ہے۔ براہ کرم احتیاط کے ساتھ کارروائی کریں۔",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "میعاد ختم اور صداقت",
   "export_backup": "بیک اپ برآمد کریں۔",
   "export_logs": "نوشتہ جات برآمد کریں",
+  "export_outputs": "برآمد کے نتائج",
   "extra_id": "اضافی ID:",
   "extracted_address_content": "آپ فنڈز بھیج رہے ہوں گے\n${recipient_name}",
   "failed_authentication": "ناکام تصدیق۔ ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven از Cake والیٹ",
   "haven_app_wallet_text": "Havek کے لیے زبردست پرس",
   "help": "مدد",
+  "hidden_addresses": "پوشیدہ پتے",
   "hidden_balance": "پوشیدہ بیلنس",
+  "hide": "چھپائیں",
   "hide_details": "تفصیلات چھپائیں۔",
   "high_contrast_theme": "ہائی کنٹراسٹ تھیم",
   "home_screen_settings": "ہوم اسکرین کی ترتیبات",
@@ -502,6 +506,7 @@
   "pre_seed_title": "اہم",
   "prepaid_cards": "پری پیڈ کارڈز",
   "prevent_screenshots": "اسکرین شاٹس اور اسکرین ریکارڈنگ کو روکیں۔",
+  "primary_address": "بنیادی پتہ",
   "privacy": "رازداری",
   "privacy_policy": "رازداری کی پالیسی",
   "privacy_settings": "رازداری کی ترتیبات",
@@ -698,6 +703,7 @@
   "share": "بانٹیں",
   "share_address": "پتہ شیئر کریں۔",
   "shared_seed_wallet_groups": "مشترکہ بیج پرس گروپ",
+  "show": "دکھائیں",
   "show_details": "تفصیلات دکھائیں",
   "show_keys": "بیج / چابیاں دکھائیں۔",
   "show_market_place": "بازار دکھائیں۔",
@@ -944,6 +950,5 @@
   "you_pay": "تم ادا کرو",
   "you_will_get": "میں تبدیل کریں۔",
   "you_will_send": "سے تبدیل کریں۔",
-  "yy": "YY",
-  "contact_name_exists": " ۔ﮟﯾﺮﮐ ﺐﺨﺘﻨﻣ ﻡﺎﻧ ﻒﻠﺘﺨﻣ ﮏﯾﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮯﮨ ﺩﻮﺟﻮﻣ ﮯﺳ ﮯﻠﮩﭘ ﮧﻄﺑﺍﺭ ﮏﯾﺍ ﮫﺗﺎﺳ ﮯﮐ ﻡﺎﻧ ﺱﺍ"
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index e3ffbef3e..9fee9f4fc 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Liên kết Clearnet",
   "close": "Đóng",
   "coin_control": "Kiểm soát đồng xu (tùy chọn)",
-  "cold_or_recover_wallet": "Thêm ví lạnh hoặc khôi phục ví giấy",
+  "cold_or_recover_wallet": "Thêm ví chỉ đọc từ Cupcake hoặc ví lạnh hoặc thu hồi ví giấy",
   "color_theme": "Chủ đề màu sắc",
   "commit_transaction_amount_fee": "Cam kết giao dịch\nSố tiền: ${amount}\nPhí: ${fee}",
   "confirm": "Xác nhận",
@@ -162,6 +162,7 @@
   "contact_list_contacts": "Danh bạ",
   "contact_list_wallets": "Ví của tôi",
   "contact_name": "Tên liên hệ",
+  "contact_name_exists": "Một liên hệ với cái tên đó đã tồn tại. Vui lòng chọn một tên khác.",
   "contact_support": "Liên hệ Hỗ trợ",
   "continue_text": "Tiếp tục",
   "contract_warning": "Địa chỉ hợp đồng này đã được gắn cờ là có khả năng lừa đảo. Vui lòng xử lý một cách thận trọng.",
@@ -297,6 +298,7 @@
   "expiry_and_validity": "Hạn và hiệu lực",
   "export_backup": "Xuất sao lưu",
   "export_logs": "Nhật ký xuất khẩu",
+  "export_outputs": "Đầu ra xuất khẩu",
   "extra_id": "ID bổ sung:",
   "extracted_address_content": "Bạn sẽ gửi tiền cho\n${recipient_name}",
   "failed_authentication": "Xác thực không thành công. ${state_error}",
@@ -337,7 +339,9 @@
   "haven_app": "Haven bởi Cake Wallet",
   "haven_app_wallet_text": "Ví tuyệt vời cho Haven",
   "help": "Trợ giúp",
+  "hidden_addresses": "Địa chỉ ẩn",
   "hidden_balance": "Số dư ẩn",
+  "hide": "Trốn",
   "hide_details": "Ẩn chi tiết",
   "high_contrast_theme": "Chủ đề độ tương phản cao",
   "home_screen_settings": "Cài đặt màn hình chính",
@@ -367,14 +371,22 @@
   "ledger_error_wrong_app": "Vui lòng đảm bảo bạn đã mở đúng ứng dụng trên Ledger của mình",
   "ledger_please_enable_bluetooth": "Vui lòng bật Bluetooth để phát hiện Ledger của bạn",
   "light_theme": "Chủ đề sáng",
+  "litecoin_enable_mweb_sync": "Bật quét MWEB",
+  "litecoin_mweb": "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",
+  "litecoin_mweb_display_card": "Hiển thị thẻ MWEB",
   "litecoin_mweb_enable": "Bật MWEB",
   "litecoin_mweb_enable_later": "Bạn có thể chọn bật lại MWEB trong cài đặt hiển thị.",
   "litecoin_mweb_logs": "Nhật ký MWEB",
   "litecoin_mweb_node": "Nút MWEB",
   "litecoin_mweb_pegin": "Chốt vào",
   "litecoin_mweb_pegout": "Chốt ra",
+  "litecoin_mweb_scanning": "Quét MWEB",
+  "litecoin_mweb_settings": "Cài đặt MWEB",
+  "litecoin_mweb_warning": "Sử dụng MWEB ban đầu sẽ tải xuống ~ 600MB dữ liệu và có thể mất tới 30 phút tùy thuộc vào tốc độ mạng. Dữ liệu ban đầu này sẽ chỉ tải xuống một lần và có sẵn cho tất cả các ví Litecoin",
+  "litecoin_what_is_mweb": "MWEB là gì?",
   "live_fee_rates": "Tỷ lệ phí hiện tại qua API",
   "load_more": "Tải thêm",
   "loading_your_wallet": "Đang tải ví của bạn",
@@ -493,6 +505,7 @@
   "pre_seed_title": "QUAN TRỌNG",
   "prepaid_cards": "Thẻ trả trước",
   "prevent_screenshots": "Ngăn chặn ảnh chụp màn hình và ghi hình màn hình",
+  "primary_address": "Địa chỉ chính",
   "privacy": "Quyền riêng tư",
   "privacy_policy": "Chính sách quyền riêng tư",
   "privacy_settings": "Cài đặt quyền riêng tư",
@@ -689,6 +702,7 @@
   "share": "Chia sẻ",
   "share_address": "Chia sẻ địa chỉ",
   "shared_seed_wallet_groups": "Nhóm ví hạt được chia sẻ",
+  "show": "Trình diễn",
   "show_details": "Hiển thị chi tiết",
   "show_keys": "Hiển thị hạt giống/khóa",
   "show_market_place": "Hiển thị Thị trường",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 19dc9f110..1dd6eafda 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "Kọja ilọ oke",
   "close": "sunmo",
   "coin_control": "Ìdarí owó ẹyọ (ìyàn nìyí)",
-  "cold_or_recover_wallet": "Fi owo aisan tabi yiyewo owo iwe iwe",
+  "cold_or_recover_wallet": "Ṣafikun apamọwọ kika-nikan lati Cupcake tabi apamọwọ tutu tabi gba owo apamọwọ iwe kan",
   "color_theme": "Àwọn ààtò àwọ̀",
   "commit_transaction_amount_fee": "Jẹ́rìí sí àránṣẹ́\nOwó: ${amount}\nIye àfikún: ${fee}",
   "confirm": "Jẹ́rìísí",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "Àwọn olùbásọ̀rọ̀",
   "contact_list_wallets": "Àwọn àpamọ́wọ́ mi",
   "contact_name": "Orúkọ olùbásọ̀rọ̀",
+  "contact_name_exists": "Olubasọrọ pẹlu orukọ yẹn ti wa tẹlẹ. Jọwọ yan orukọ ti o yatọ.",
   "contact_support": "Bá ìranlọ́wọ́ sọ̀rọ̀",
   "continue_text": "Tẹ̀síwájú",
   "contract_warning": "Adirẹsi adehun adehun yii ti samisi bi arekereke. Jọwọ ṣe ilana pẹlu iṣọra.",
@@ -297,6 +298,7 @@
   "expiry_and_validity": "Ipari ati idaniloju",
   "export_backup": "Sún ẹ̀dà nípamọ́ síta",
   "export_logs": "Wọle si okeere",
+  "export_outputs": "Agbohunlu okeere",
   "extra_id": "Àmì ìdánimọ̀ tó fikún:",
   "extracted_address_content": "Ẹ máa máa fi owó ránṣẹ́ sí\n${recipient_name}",
   "failed_authentication": "Ìfẹ̀rílàdí pipòfo. ${state_error}",
@@ -337,7 +339,9 @@
   "haven_app": "Haven latí ọwọ́ Cake Wallet",
   "haven_app_wallet_text": "Àpamọ́wọ́ Haven wà pa",
   "help": "ìranlọ́wọ́",
+  "hidden_addresses": "Awọn adirẹsi ti o farapamọ",
   "hidden_balance": "Ìyókù owó dídé",
+  "hide": "Pamọ",
   "hide_details": "Dé ìsọfúnni kékeré",
   "high_contrast_theme": "Akori Iyatọ giga",
   "home_screen_settings": "Awọn eto iboju ile",
@@ -501,6 +505,7 @@
   "pre_seed_title": "Ó TI ṢE PÀTÀKÌ",
   "prepaid_cards": "Awọn kaadi ti a ti sanwo",
   "prevent_screenshots": "Pese asapọ ti awọn ẹrọ eto aṣa",
+  "primary_address": "Adirẹsi akọkọ",
   "privacy": "Ìdáwà",
   "privacy_policy": "Òfin Aládàáni",
   "privacy_settings": "Ààtò àdáni",
@@ -697,6 +702,7 @@
   "share": "Pinpin",
   "share_address": "Pín àdírẹ́sì",
   "shared_seed_wallet_groups": "Awọn ẹgbẹ ti a pin irugbin",
+  "show": "Fihan",
   "show_details": "Fi ìsọfúnni kékeré hàn",
   "show_keys": "Wo hóró / àwọn kọ́kọ́rọ́",
   "show_market_place": "Wa Sopọ Pataki",
@@ -943,6 +949,5 @@
   "you_pay": "Ẹ sàn",
   "you_will_get": "Ṣe pàṣípààrọ̀ sí",
   "you_will_send": "Ṣe pàṣípààrọ̀ láti",
-  "yy": "Ọd",
-  "contact_name_exists": "Olubasọrọ pẹlu orukọ yẹn ti wa tẹlẹ. Jọwọ yan orukọ ti o yatọ."
-}
+  "yy": "Ọd"
+}
\ No newline at end of file
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index 009a31d86..92a540d19 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -136,7 +136,7 @@
   "clearnet_link": "明网链接",
   "close": "关闭",
   "coin_control": "硬幣控制(可選)",
-  "cold_or_recover_wallet": "添加冷钱包或恢复纸钱包",
+  "cold_or_recover_wallet": "从Cupcake或冷钱包中添加只读的钱包或恢复纸钱包",
   "color_theme": "主题",
   "commit_transaction_amount_fee": "提交交易\n金额: ${amount}\n手续费: ${fee}",
   "confirm": "确认",
@@ -161,6 +161,7 @@
   "contact_list_contacts": "联系人",
   "contact_list_wallets": "我的钱包",
   "contact_name": "联系人姓名",
+  "contact_name_exists": "已存在具有该名称的联系人。请选择不同的名称。",
   "contact_support": "联系支持",
   "continue_text": "继续",
   "contract_warning": "该合同地址已被标记为潜在的欺诈性。请谨慎处理。",
@@ -296,6 +297,7 @@
   "expiry_and_validity": "到期和有效性",
   "export_backup": "导出备份",
   "export_logs": "导出日志",
+  "export_outputs": "导出输出",
   "extra_id": "额外ID:",
   "extracted_address_content": "您将汇款至\n${recipient_name}",
   "failed_authentication": "身份验证失败. ${state_error}",
@@ -336,7 +338,9 @@
   "haven_app": "Haven by Cake Wallet",
   "haven_app_wallet_text": "Awesome wallet for Haven",
   "help": "帮助",
+  "hidden_addresses": "隐藏的地址",
   "hidden_balance": "隐藏余额",
+  "hide": "隐藏",
   "hide_details": "隐藏细节",
   "high_contrast_theme": "高对比度主题",
   "home_screen_settings": "主屏幕设置",
@@ -500,6 +504,7 @@
   "pre_seed_title": "重要",
   "prepaid_cards": "预付费卡",
   "prevent_screenshots": "防止截屏和录屏",
+  "primary_address": "主要地址",
   "privacy": "隐私",
   "privacy_policy": "隐私政策",
   "privacy_settings": "隐私设置",
@@ -696,6 +701,7 @@
   "share": "分享",
   "share_address": "分享地址",
   "shared_seed_wallet_groups": "共享种子钱包组",
+  "show": "展示",
   "show_details": "显示详细信息",
   "show_keys": "显示种子/密钥",
   "show_market_place": "显示市场",
@@ -942,6 +948,5 @@
   "you_pay": "你付钱",
   "you_will_get": "转换到",
   "you_will_send": "转换自",
-  "yy": "YY",
-  "contact_name_exists": "已存在具有该名称的联系人。请选择不同的名称。"
-}
+  "yy": "YY"
+}
\ No newline at end of file
diff --git a/scripts/macos/gen_common.sh b/scripts/macos/gen_common.sh
index 87fd54b43..d75ac919e 100755
--- a/scripts/macos/gen_common.sh
+++ b/scripts/macos/gen_common.sh
@@ -9,7 +9,7 @@ gen_podspec() {
 	DEFAULT_FILE_PATH="${CW_PLUGIN_DIR}/${DEFAULT_FILENAME}"
 	rm -f $DEFAULT_FILE_PATH
 	cp $BASE_FILE_PATH $DEFAULT_FILE_PATH
-	sed -i '' "s/#___VALID_ARCHS___#/${ARCH}/g" $DEFAULT_FILE_PATH
+	gsed -i "s/#___VALID_ARCHS___#/${ARCH}/g" $DEFAULT_FILE_PATH
 }
 
 gen_project() {
@@ -17,7 +17,7 @@ gen_project() {
 	CW_DIR="`pwd`/../../macos/Runner.xcodeproj"
 	DEFAULT_FILENAME="project.pbxproj"
 	DEFAULT_FILE_PATH="${CW_DIR}/${DEFAULT_FILENAME}"
-	sed -i '' "s/ARCHS =.*/ARCHS = \"${ARCH}\";/g" $DEFAULT_FILE_PATH
+	gsed -i "s/ARCHS =.*/ARCHS = \"${ARCH}\";/g" $DEFAULT_FILE_PATH
 }
 
 gen() {
diff --git a/tool/configure.dart b/tool/configure.dart
index 97541c2fa..c5d4a6863 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -276,6 +276,7 @@ import 'package:cw_core/get_height_by_date.dart';
 import 'package:cw_core/monero_amount_format.dart';
 import 'package:cw_core/monero_transaction_priority.dart';
 import 'package:cw_monero/monero_unspent.dart';
+import 'package:cw_monero/api/account_list.dart';
 import 'package:cw_monero/monero_wallet_service.dart';
 import 'package:cw_monero/api/wallet_manager.dart';
 import 'package:cw_monero/monero_wallet.dart';
@@ -379,6 +380,12 @@ abstract class Monero {
 
   Future<int> getCurrentHeight();
 
+  Future<bool> commitTransactionUR(Object wallet, String ur);
+
+  String exportOutputsUR(Object wallet, bool all);
+
+  bool importKeyImagesUR(Object wallet, String ur);
+
   WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
     required String name,
     required String spendKey,
@@ -398,6 +405,7 @@ abstract class Monero {
   int formatterMoneroParseAmount({required String amount});
   Account getCurrentAccount(Object wallet);
   void monerocCheck();
+  bool isViewOnly();
   void setCurrentAccount(Object wallet, int id, String label, String? balance);
   void onStartup();
   int getTransactionInfoAccountId(TransactionInfo tx);
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index 92431a6fb..26d481f85 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -13,7 +13,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
 )
 
 list(APPEND FLUTTER_FFI_PLUGIN_LIST
-  sp_scanner
 )
 
 set(PLUGIN_BUNDLED_LIBRARIES)

From 02f53055b1a72b5e7d33cc5bda2565412857b187 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Sat, 9 Nov 2024 21:00:56 +0200
Subject: [PATCH 37/50] Cw 657 new buy sell flow (#1553)

* init commit

* onramper

* moonPay

* dfx provider

* meld

* dfx payment methods

* fiat buy credentials

* moonpay payment method

* payment loading state

* dfx sell quote

* onramper launch trade

* meld launch trade

* country picker

* update option tile

* buy/sell action

* meld refactor

* update pr_test_build.yml

* ui fixes

* revert country picker commit

* update the ui

* recommended providers

* payment method [skip ci]

* provider option tile

* remove buy action

* minor fixes

* update the best rate when the amount is changed

* fixes for currency title

* fix icons

* code refactoring

* null issue

* code review fixes

* Update pr_test_build_linux.yml

* Update meld_buy_provider.dart

* Update meld_buy_provider.dart

* add show wallets action

* remove default sell / buy provider setting

* localisation

* providerTypes

* icons

* remove duplicate file [skip ci]

* minor changes [skip ci]

* fixes from review

* disable dfx for non eur/chf currencies
fix providers to be fetched with the selected currency

* fix breaking from loop if one element failed

* fix minor naming issue from merging conflicts

* add fiat check for moonpay

* fix address validation

* merge conflict

* fix destination and source currency

* minor fix

* minor fix

* update the flow

* fix bch address format

* fix wallet addresses

* fix initial fetching amount.

* Update address_validator.dart

* review comments

* revert switch case to return null

* minor fix

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
---
 .github/workflows/pr_test_build_android.yml   |   2 +
 .github/workflows/pr_test_build_linux.yml     |   2 +
 assets/images/apple_pay_logo.png              | Bin 0 -> 56018 bytes
 assets/images/apple_pay_round_dark.svg        |   9 +
 assets/images/apple_pay_round_light.svg       |   9 +
 assets/images/bank.png                        | Bin 0 -> 1323 bytes
 assets/images/bank_dark.svg                   |   8 +
 assets/images/bank_light.svg                  |   8 +
 assets/images/buy_sell.png                    | Bin 0 -> 9931 bytes
 assets/images/card.svg                        |   1 +
 assets/images/card_dark.svg                   |   7 +
 assets/images/dollar_coin.svg                 |  12 +
 assets/images/google_pay_icon.png             | Bin 0 -> 12336 bytes
 assets/images/meld_logo.svg                   |  30 +
 assets/images/revolut.png                     | Bin 0 -> 11588 bytes
 assets/images/skrill.svg                      |  15 +
 assets/images/usd_round_dark.svg              |   4 +
 assets/images/usd_round_light.svg             |   2 +
 assets/images/wallet_new.png                  | Bin 0 -> 5619 bytes
 cw_core/lib/currency_for_wallet_type.dart     |  31 ++
 lib/buy/buy_provider.dart                     |  32 +-
 lib/buy/buy_quote.dart                        | 302 ++++++++++
 lib/buy/dfx/dfx_buy_provider.dart             | 273 +++++++--
 lib/buy/meld/meld_buy_provider.dart           | 266 +++++++++
 lib/buy/moonpay/moonpay_provider.dart         | 451 +++++++++------
 lib/buy/onramper/onramper_buy_provider.dart   | 359 ++++++++++--
 lib/buy/payment_method.dart                   | 287 ++++++++++
 lib/buy/robinhood/robinhood_buy_provider.dart | 102 +++-
 lib/buy/sell_buy_states.dart                  |  20 +
 lib/buy/wyre/wyre_buy_provider.dart           |   9 +-
 lib/core/backup_service.dart                  |  19 +-
 lib/core/selectable_option.dart               |  47 ++
 lib/di.dart                                   |  32 +-
 lib/entities/main_actions.dart                |  65 +--
 lib/entities/preferences_key.dart             |   4 +-
 lib/entities/provider_types.dart              |  42 +-
 lib/router.dart                               |  16 +-
 lib/routes.dart                               |   2 +
 .../screens/{InfoPage.dart => Info_page.dart} |   0
 lib/src/screens/buy/buy_options_page.dart     |  74 ---
 .../screens/buy/buy_sell_options_page.dart    |  48 ++
 lib/src/screens/buy/buy_sell_page.dart        | 469 ++++++++++++++++
 .../buy/payment_method_options_page.dart      |  47 ++
 .../desktop_dashboard_actions.dart            |  27 +-
 .../exchange/widgets/exchange_card.dart       |  58 +-
 .../mobile_exchange_cards_section.dart        |  91 ++-
 lib/src/screens/seed/pre_seed_page.dart       |   2 +-
 lib/src/screens/select_options_page.dart      | 199 +++++++
 .../screens/settings/other_settings_page.dart |  16 -
 lib/src/screens/settings/privacy_page.dart    |  12 +-
 .../setup_2fa/setup_2fa_info_page.dart        |   2 +-
 lib/src/widgets/address_text_field.dart       |   7 +-
 lib/src/widgets/provider_optoin_tile.dart     | 527 ++++++++++++++++++
 lib/store/settings_store.dart                 |  79 +--
 lib/typography.dart                           |   2 +
 lib/view_model/buy/buy_sell_view_model.dart   | 446 +++++++++++++++
 .../dashboard/dashboard_view_model.dart       |  45 +-
 .../settings/other_settings_view_model.dart   |  45 --
 .../settings/privacy_settings_view_model.dart |  10 +-
 res/values/strings_ar.arb                     |   3 +
 res/values/strings_bg.arb                     |   3 +
 res/values/strings_cs.arb                     |   3 +
 res/values/strings_de.arb                     |   3 +
 res/values/strings_en.arb                     |   3 +
 res/values/strings_es.arb                     |   3 +
 res/values/strings_fr.arb                     |   3 +
 res/values/strings_ha.arb                     |   3 +
 res/values/strings_hi.arb                     |   3 +
 res/values/strings_hr.arb                     |   3 +
 res/values/strings_hy.arb                     |   3 +
 res/values/strings_id.arb                     |   3 +
 res/values/strings_it.arb                     |   3 +
 res/values/strings_ja.arb                     |   3 +
 res/values/strings_ko.arb                     |   3 +
 res/values/strings_my.arb                     |   3 +
 res/values/strings_nl.arb                     |   3 +
 res/values/strings_pl.arb                     |   3 +
 res/values/strings_pt.arb                     |   3 +
 res/values/strings_ru.arb                     |   3 +
 res/values/strings_th.arb                     |   3 +
 res/values/strings_tl.arb                     |   3 +
 res/values/strings_tr.arb                     |   3 +
 res/values/strings_uk.arb                     |  13 +-
 res/values/strings_ur.arb                     |   3 +
 res/values/strings_vi.arb                     |   1 +
 res/values/strings_yo.arb                     |   3 +
 res/values/strings_zh.arb                     |   3 +
 tool/utils/secret_key.dart                    |   2 +
 88 files changed, 4082 insertions(+), 686 deletions(-)
 create mode 100644 assets/images/apple_pay_logo.png
 create mode 100644 assets/images/apple_pay_round_dark.svg
 create mode 100644 assets/images/apple_pay_round_light.svg
 create mode 100644 assets/images/bank.png
 create mode 100644 assets/images/bank_dark.svg
 create mode 100644 assets/images/bank_light.svg
 create mode 100644 assets/images/buy_sell.png
 create mode 100644 assets/images/card.svg
 create mode 100644 assets/images/card_dark.svg
 create mode 100644 assets/images/dollar_coin.svg
 create mode 100644 assets/images/google_pay_icon.png
 create mode 100644 assets/images/meld_logo.svg
 create mode 100644 assets/images/revolut.png
 create mode 100644 assets/images/skrill.svg
 create mode 100644 assets/images/usd_round_dark.svg
 create mode 100644 assets/images/usd_round_light.svg
 create mode 100644 assets/images/wallet_new.png
 create mode 100644 lib/buy/buy_quote.dart
 create mode 100644 lib/buy/meld/meld_buy_provider.dart
 create mode 100644 lib/buy/payment_method.dart
 create mode 100644 lib/buy/sell_buy_states.dart
 create mode 100644 lib/core/selectable_option.dart
 rename lib/src/screens/{InfoPage.dart => Info_page.dart} (100%)
 delete mode 100644 lib/src/screens/buy/buy_options_page.dart
 create mode 100644 lib/src/screens/buy/buy_sell_options_page.dart
 create mode 100644 lib/src/screens/buy/buy_sell_page.dart
 create mode 100644 lib/src/screens/buy/payment_method_options_page.dart
 create mode 100644 lib/src/screens/select_options_page.dart
 create mode 100644 lib/src/widgets/provider_optoin_tile.dart
 create mode 100644 lib/view_model/buy/buy_sell_view_model.dart

diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 6d0e541ce..a12fd422f 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -194,6 +194,8 @@ jobs:
           echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
           echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
           echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
+          echo "const meldTestApiKey = '${{ secrets.MELD_TEST_API_KEY }}';" >> lib/.secrets.g.dart
+          echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dar
           echo "const letsExchangeBearerToken = '${{ secrets.LETS_EXCHANGE_TOKEN }}';" >> lib/.secrets.g.dart
           echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
           echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml
index 5ea0cb377..f3ce1045d 100644
--- a/.github/workflows/pr_test_build_linux.yml
+++ b/.github/workflows/pr_test_build_linux.yml
@@ -175,6 +175,8 @@ jobs:
           echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
           echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
           echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
+          echo "const meldTestApiKey = '${{ secrets.MELD_TEST_API_KEY }}';" >> lib/.secrets.g.dart
+          echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dar
           echo "const letsExchangeBearerToken = '${{ secrets.LETS_EXCHANGE_TOKEN }}';" >> lib/.secrets.g.dart
           echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
           echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
diff --git a/assets/images/apple_pay_logo.png b/assets/images/apple_pay_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..346007e3b164651dab29b53c8368c6d48fe3310e
GIT binary patch
literal 56018
zcmeFacTiMK*Du-x5fzXTBxjJIB*{q_C8~&k837SN$$}t3(ujy835t@l4;T<oB&SiL
zA|j$7Ns=TH21IhYz4sn`-tRl-RNbmu_trh9>^}td?q0ptZ-rjHx@QbAG|;8r&aoW;
zKz~?I%NYLP0bpA@Ee(7UcSj`;{$O|0KI?Yk>SZ^Ni`T5dL945l)_jK@FJ7@Ww!UcP
z<?_~A4S+7U!&(PVdUpMMO+f*N5Te%erf3nWf7@RK{vz-ffxig+Mc^+2e-ZeLz+VLZ
zBJdZ1zX<$A;4cFIM<YP!yhVi+1Hi%cc20dm^w<BR1^z4CUj+Ul@E3u<2>eChF9LrN
z_=~__1pXrM7lFSB{6*k@YXp+0El3Ra+v;C}aCQCpfgG(H`S-+yoOZ<dx>*bIeQkVn
z=1p2uiovzs5N@h=Z<XvL4?e$NjhbqT6nou}%nmpH(w4nD){7^{-{~Ot3IHJL{m!=E
zc(dVq)dBtyM;i&R44i*EJ}y1hYJ(xwpS{d1n5Dk$0erKMi3ie%{p>sI!5K_`U39u{
zwet8IAprUx1nNQ}q_L`{^1IsDYiTFn<tvwrQ>hQbH?rFh@)yRd)@^U$u=k&bN%V((
zcL_qW#~Bgg8b9FM`{cL!M^ir}MlTC#Q37ypnic@1tNS@5)5&kApQ|TpKKdXEfJFi_
zv-Gjval1BUCD<8hix1R0gQx+xFQ`Td2;*b-zCr>>D+xcfi=P7E=a4~$#Xe;`_y4?#
zP)}CmzpeurnZrSL@V?iUMK%eRJWyXN*tQLT#{`6zAJO+GbufxVB{~Y@D|C>W!T@A0
zChuqwCnSNiq2CKMkG?@3)70Jw0w8)OmKx5AG(7wA@8f}xLFPlA@ZaI_d;MevMNgzs
z>p^04D6!0=0dOGF(inVq@lgQc7=ok4YMIa`XFooRQ0xLA{2{_u{j)y<EI5{h@KE^H
zc!ZsB19h{FwPg{E7?HU`!;JUS($+8DLr^O&`7_8^!R*<fOb2Fims*K?0LuHVCmBjb
z6m`qCkJTb`4{n+LV&4luMQJJWF7aLVL`&P;Yf)?@sG3zz);OBHryFwGe+)6J{z<oS
zF78T2@?8{y|AT6C|K!}3ddOKZs-o_uw-3pZ5@J159W)^4iHV5S_MG%6<GD*lw7+;R
z+x{X1+u0XEv?SR~<*F)K=lyd*i;oqdX_us+Y<(GSo9k<vL-0qN<cOxq2JpTL1$5?C
zfC?sFzn(qO%0_;jn{|A25(-GXjUe2A!+pGB5~6}M!UX4F<~P`}|JqbI{995|q?K%k
z#OF&%Ebz(udW4;vqz_UBWL7;neO0bPF@X7DM8&c9?~jqmS<o#DsYChBl*_``CBc#*
z5$H5f1p*?e1C)UHtobf{V(#d9Zte9Ze>%gyDqHn7QIk?c#(F;BS9w=Y9xQDa*7k*y
z3aTX>F$KTW&H2)}1|f5v{D?)Z@@#UB_o{``PE#T{dMf{UT8ci^N1w9)dAfu?r9+>p
z|9N@<eYyjE`Y&By^eK}E;vdyQDrD_EZp%b$rMdtyH9yI0SI^qU=N+7y81oh<i@F_u
zc=IZ<q#Yk^MzpXq5aEt=Z5Ma%<&R#`51XtPTe^!5A8TV{#D<(w<zld{)=*pOTbpUP
zMbWF1ip<N1nwzb1NQ9)~d)_x0ckV<6kvXUyXwW+x=Vs))ix=wN1Ev2e6Ianwd^5U)
ztQsf#f~A&?4N1LaM@`Sq2$)HTHSlpLa9dwmES$SBJA6Evtorb_zWw(Y$F)&$A0Uud
ziKr}xR4a09L$n85n*O0jS7z6aKtcS&DL}t!@AwV5AX3QYYlAyA{F4h?ai7|j-M;xC
z;Yt_@R|QEQx+C-~p<a*{$ASBFA2k?@L4;>#ce#L=_K9P5-NN$6E|IN6+9<Kv|C4+9
zF<(+KXPdIx59lz2C%X_M_i8gr`2~Xd8{NqS`_I>~JZfk#ARtC)@dlx(Z)Pw$ZF6I1
z3af3Y>2|U;5>j{Z`G!QWtnY#0RU1)qmU#9y9bHZ5S0>k=*m7);aV1<y^d!7eF-!K}
z0x8{vKoG<@zXgqo9hkmR`C@>KtmlJmTlH$%Grv_snX<H?OAt>&_jB31bKhnplXRqw
z>MBb9B)Blng{a7?2l0QVm^Q79%p_LZ>b|f|&cf^ygt;Rdq*9L>Xc>(1mQn-4TVw^1
z*1jJc5hS5o-aFsa<cGos2=?siv0Q$PE&>#vroCL<e?TVd-b1e9;v`S;@X$-mo_S{A
z48ccQPmkpbec$S5Yx`FQjFJ@qIKc-sVqq5{uhEk~JT@?pc>)F)q<woo;H>A^-M$|8
z%x!((C|np4P|4Z-PVehjc3xTgwi(YX<b?Cr8a<>bz~gU7ES1J7pW@&iu3+RQM~cjX
zZpUh$lyfgWh*1GU)xraCTBG5j%z-^?(=XvgK%`mZFx=6!>n>_<;C%P=8`5tdCp65s
zfFv!bKeS!VuuXW?N3!>=&=sKr_+|%$^X(CZ2R=?4`*|ww#CjQqhAQ%Q-k=8fLZm~Q
zyP4z8KTdi?&gX-d8qbLjVO>1U?NH-St%o4Th0pA|qc@|;<JTBOKceqFhf|+yL?WME
z`<LI+8Ds-XV=3<~Dr(kM&E5|1cM<#goRe^U{?BWL-SxW3C$@kz1z9*E&DiXzklL<I
zFys@PpDypsBw14e!`+C8j~{H#oCaz}Gj_i<U<QN)#LXWYovG3M{x6PSIMrF7i>lvn
z%YZZ19yt!#auZ*p2pY2~?pA?02+}NMFdTz)&n4x43xSi|LKX|dc%L$L<~6X%qeZ|J
ziPYw^E;;F5{)u;ZZG8E=7S!L(yNEECJ*kq9`VrRrQWLUV?qPI^LJ}-ZpBL&Hbc>)J
z8g4;it^C_@E}q>--N?2T^~vG%Y6s_;>}RfUP|VZ^XoHXSB$r2K5B=%#L8I$ziEcJ6
zz|)Vw_=(pJ?RA&ag7)0LjqGhnJ$-%IORHvGlkR&o>hp`9cqBk#`p}>75@jc+>obq1
zs{4AmFp$|g*R249<fE2Ujo4MT)FdGQ_MofI-qwdVh9>4<2pOU#o1tI6$@M*beg<1M
z2*Lo+q1Hj8oUF*R+qS${<se3oAoB10|ERyYkp0X95ytK^6!K)6s#)ZoZ;O7_#hWW<
zKkMa!jOwYea>yj}1S&B;y4C2zj?FcMC`+gD<81y<$b={oLkXXTjj#F?{zxL*J^Eg0
zwd7LzOD1ZNb`l9gM`DjwjL+S;)D1C48gU2n>QF?a!A?LhZieeK;SG0K#rRO`Te4sk
zA5n|l_pAN*84@zlT||vB;<27>HAQ5b1?Eo0-4Aa}bdE#qWuPXJzw-$(wxD~meUr{=
z7K(dl_l=n29q*8i3Gs;S<X^H?RC7?h;kh{W9pea?UsTxlYa$XZ$g0qrk6gO~;c-^o
zv@SwNlb6wVM^$C`3dw%bPMV<<$SUriJN+!Tw%aM03xI!+Ow{n{pm}4F<Ira^b;&f_
zgk8lv)*@R0-WKt%n7ypm3%q8A>lDd7VvWYyGe1Da4R;}yxaZwJz0T=U6=Xnknj&Fh
zLYzaEHc=zV$)L(<a#Sm+n7eVJOF~0M9<nBYu%_jBSn+&+m=i{rAn@ur?@btP?UA*`
zFvIjy^Nm(|?42|Bv9?D^tpD`7k3twkZzC&Wu7l_1YvOhB*rS?IJNr<P5^^6Un&l}P
zz+4V#{h>TO>JQzUo}ZusY0QY0OEQWIH_eDZvVu>r=SNO_meP<%mKkhdSNp_WerN={
zk&qyIOmbMK^6REFcZ(#Zboo`YX#jp3f)lynTNASOLyeSBqTq}lDeHuJ!XH+2u9>qz
zRhY(Y&H;yse!EsGKJLz&3>Vxz$WlYxo%1Jq0VU~0j&u-QNz@MyuMRSiXF6`jflOiA
zg)BItjW6Oj5AY<zd=Y8HyJ*NLH+J&4UZw(hB*t|jnIgHJyjW_=fv^#UxP|d|OD8!g
zB-JE0Lp6l(KaKzNJihReY&f2rj@``H%b_5I7wB${-1n4CLdKiSpS1w6siN$hy;z+F
z7i)5xeuUb4u$h?R@@T5RiUjtYpeU1CeYD(cKkxp$Bq;W!%g9<lZp7|J7@vr7hzV`B
zZ#oK)k$MCJ!1~JkDuM{o`soWDFG2a8`BCqUBBwuqFlvLL6N*T<3sLcAE0I9>BsXHW
zryN4q0SPk9X-98YI2_=KG}wW??!Vi7S=;x(Cl6%`z$SsL801EHifM?j1KnJ1J_g_>
zI^8SC|7LSO|6e(S&-;rIgK_4cn5!ozoWS#m17si^P4&nlA0O#f*wgFeZuvhvZ<7mx
zeOQt7;XfK`aR2^|W~=}HNx=Vy{^4V4gsb}8eZxB4MJ^_P`r+j<){Y^uW3&C>|BpZ5
z!~dMgFd4dKkKM#8XaM{E16af4;cMsKJ-?j21rX2vrzWA7{?Az1oC_wz{}V|6eG6#+
z!`a|t{Qq+l{w4lDom$eO@*Co_<Yu@Vk@8Xp2iXGQW8x$tAX_=2!p&AJ^1sFm_W8e~
zolR2z|AXXT&i+5w#^0&`U27l~|L>dsU%>wY{@2V<FZj=O4?g%C!yyR&n=R)58%MK6
zUhjo~B!wag3pQhR)<YbzTNHkk5G^fBD|_yA*ACt#RQ^MHcI5g8Uw0Onyq_1yDJ)R=
zZ~4-l|JZpzG{*j0w#AL)h5xoR&HtJ<x*<EEe;a|}KT<yU_~U=e6#q_6#tQ!zb}|xw
z4Q|tY{ui#M>rmW%xXp)Sb2A}*q#E7T5?+MnKXxqctG<xeaX&Awxpkwn%uiODOwHmX
z=I7yWBxO`s*)}&P(^8m&-V#E#xo9hiL?Zy<wM{|`$zPJC@FMvI=s{1D0KQ#7;pG={
z4Fsh5V-ewHL9dgDV|iic=8OKD*o;<!MVy<*4gjQJ0R#WZvb^=$lKRqe7aO@^0*Fl5
zK2Yz^fh6cJ#ApcpW2-I_rtP@79R^a!X$9Q)Yzx>7M}${c=<$3q>8>gk`i5_l>s_-=
zC`+EVX(Qgf{8Q`&Lhq33G301(K<4l--(Pcu`^g0%KnTP*@l42CN)l%&Jh(~A3fr0z
zYw8|mW{A>lLdGXpjhxK^f^JCvWAS~P1xA1mLMoYXL(iWu;`;LJXPQmeqr|Xc!Ppn4
zrq-y8%#1iM3-UWc>kH(V3J|_&xt(OL>t8o5i2oCk*?7t0v>lW=EH_KHK>9RtrU*+0
zvFT3An@q8(Vtq?G*)lShDt_asU=O5a3SmqMTc5jY*=BU=6psV;0$9XgaGOeGWaj1F
z{UbKr*Q+R0{l?vs?#$=OM<D>9XSaZ`<F35Q(+S0$>SQv~M=+E4@N#_97%Y4+%1Lq~
zV>aqiX5^lLXoDfG^i=$r(N&eFPv4Ob@HbDD0pXT_$}+T)O>-yeVI#&Ex!0cM_L*+#
zY?IRB(KesZKOADK*K{hhiF4w1w-y`hzWmv%OWTnhhq2Yjh?$1M%339vgYsNrOVi;~
zr*t<~wD%{zzbtzT!?S-6CO~im!{Z4>P0&A3Ri)5Zojc>YFSSD)6Ng6|T@0nKWe9@C
zCQBpUwU!mm7>A=|3g##(gy{2<ee?r&QWJ#$A8Uhx=%jgftsX|e6mt$~OY3voYDsGD
zE~1<u==<oyNBLpVKbD&bST7|#Y#QT?%pr#WU_s};|I<|JAtCIo-?B9d)e!VYZC%};
z3}#fsuUZ7=>a4bLkF*}S)IJhB){{*NGY}nN21Zuxi;TL=w;go><IP`wkGL*6Rp@kW
z$FwIcNoE|!ojih<2X1x3kGOI0+#fcgC+2lJkHq(BD)BQIQ-SP|D2#snP%K(V3)gJ(
zF@R{%xE$h2q5+buIAezsNe0<{Bv|Q18XF55gov~-vQ-x`ImbED1LtzjJRF6w!`bi!
zaykC{aZGH=rr~n_q!%Xgu*h{Fm_DqC5Az(lTd12@^bZoRa)FUoF!)h}v3LnGwq96O
zlI|?m^j)gzB!$#iIDY4=?f~Sb0@518u<^u)O&*#h#D+V{6hv8CvMj%lf;8mxF|5O@
z_cYnQn6yzyWTysd(a1#w*!Xs0AW?);RUm<i_3_hpjG$i|xln;LTk`ZDuPr&zvO;gs
z1O!$lGV719z$z{6a#oRnbnP2zq(W92WX}508zTTvUFvQfc2K1x$Y~Sgk_|+T&DxUB
zV5KmZW{XlvvhQxSM*94gV43qEFmsX*w>;G`j0v>^rjp3<#rI6n(8K3WlS9(96~_L}
zU`JikdU!I?c--N7_@wT)S&V%(Y*Db_b5Jcyf>si>;GOc-?^Ul8Jr-5^Ut{h;)&F55
zwgA@7f3bE)hGtCjU?%kEwFOy%i<MhLC&?RUwICFDKG&(={-s5Z^b~+bxQO>ycH3L`
za(T?X2`QM<%Uprdjm%z?No<C}m*%PH_HJ^%c>`Mz8si*wV^<bE6{!JR$yYz-ndr?~
z*04}u^}Z;x>8m?67{bjMIcOl~@kr~zj4Mj4J3_L!GY9gZBRnWbip8X#!m6E(F_8GV
z=NwRVxatdgo8IwZubnXT8$UvR19!Y19e$MC2iep4IblD`&Fi&+g)Zj<s0Q#s|JoPW
zsMpmt3MPw?OD3bw6?eC$AgRbi{(h&!Wkx{UU?OvAs*AcnRD99(v-3$y6-l4x5@C?$
z9z>%vAT*ItDmeQ&$hp3up`0H8U2UI}4<Eo@NK3-<@5bQr+0^1c^bcRSz&V4}yov0X
z9fZGnK0OxmX9iXrnS&%U%#D^toNu-zHg_=s!m~{QA}|}b%CJ?Z9|%M>SrW2Hwg71?
z(daz?JmIZ_f-EiQzr4w|BnFHyOIQ~pLmUjhX4TNOoE0~D>ceb{{i{=PkTYIO7f#Cu
z*T>Ci*U8$!cW;kmSVDE5=CMiJpA1Ppgk)N?yNC>_rk2lVxm2?8ha<=5aK-%@903Sd
zf)~BZ3%#)L#)hRw_`x3AjjI`gpg%q|gOLnH<{m5s;Y6PAuEmUbvzEQ97|th+gU**%
zXj;XIMHp$7H>jfSiNKpF=93flvSOPyL@+{5rT`Giu~paApn@4h)OND?(hB5Jd*CQz
zrkPe~Wf-Ow%os32hhZl02s*>&i0$YILLdwQq8mMsKfdco&_pZ%fLmDQnU8(eOAJzc
zIXzbxA7gEerB=i=3@^Py2+Sssu9e_m=A^ql`LzZ1de;}Z)Xb%VDM*^o!>r8@Z*w4x
zW}+B1qv<1#-CftHKNircJbNk=oFc(e$nOjzpJWD>>(OBGj(D^-eK9i9qZLP_g2_(D
zRhrfUSJ}JI6&+U=MmS%5Qu6V2tSUaWT#Ch*ARW~DiEY|$R{H?ZWZFO3lIE_V)w%P2
z`^20_&KqYftJBP~M%bz%EsBAlMSorMP<Ii-cS`9aD;GccMKLE{3t$uThk%rDpj@-X
zT+l&&A<EW1%+&B-hgQ&kCpc>G4E4Sl6ZYsSyDvV~?)PG88{GM^m6J%W?0A+asZCC8
z0O$B%x1G23zVjEIb}Bx93ndC@4r1Ka{4C<C8?Xia3gwJq<|l??9rebM3;@wKTu`Vn
zx7dm6W_M7gB&<&s@plHs<ihOhIoYE4uoZUf6c-`Fk?ut@1@KH-JEn)@?+l1}2$N8Z
zP-6;a!{)UYN0k=2wx&@KMnh@Eiumg6Ur6YU+aw&<#Q1uNd2qiZj;rqBZKa=dpyHd;
zj(cEy4sk!U4<QHBa>-jiXXf)P0H)Sap9~*9ARAC8a{daF&E2ozDxyvJZF1p4A`+@G
zqvSh^;tnKt-FdJDE)-G}pC-g(NpP`6niW~|MlX6r8AKZRhm~@~l_&|Tla!A<lSh>u
z4q%3KZLS-owkT!^b7Od?$%1GZcCl7k+lZ~6skS{c4jx~_hBqMR*XL_>pv5^+1HoN+
z3q`yK?vTO5M_?V;o+w$Eo_f%%0|=A4$1NwYU>C)SB|y7&a|SOnr?;-3&Q$tsSAYZg
zmsVPbkc%ov`(BUk69_jucRqB0H{Wu1yIg|_4Ma<thlpHMfsIduY;1K38H-!Mbm#&<
zP8#M^YzMj>5A3>w*{|{<mYKnuaLgC=VJKRvkPA<#Ba<L-VS0v_O+^PYn=ebK|LAlg
zGm8I#IXVpBLh3(KH-%&H!)|+CV(F&oDk^tLgUilVFs}sz{+ER!o~bKX8jNSaM$^4Z
zkFt63IB&h$^@snJLc8_l7A(cB*=jLetGi~GaQuZVDo&IfYL(N5E^)t@U(*zK?F@$=
zc48+!bw~VsjnJJC3O0@zqiT{^#Tm3eFvg53cV1Sw%sTPC^2$JvQpnoGRA+Rn#Js=o
zynl6hF1IudpT}UPU*C}DRczFwBdCjT74otj5Rg<E{<={OSDcfl=GMHo$~CyG9a!n|
zuD@QnGCFmGrGp|$aK=bO;OTr7b`Y(HorNwIq1(=5eu?_4<&*1c?lVCWGBss1cbGZM
zTo2qa3;u3G!^aAz{kF4qg%2l#$tQry7k*MQy>*YDQ*;R9Tbg*a+S8f*rnh`MZ|mh+
zgKNKLX4YFK9(4Tju3fp7w}6hrhoVSI3*fv0)33&KZp?P_-5<Fws!+CW!op7x_0-eR
zu6sVU<H;N8DbMBwzuo94y=c@mX`FsWH>}gJ<L*sJUl9<3n5mata1fg7VnBO68bPyV
z;&g3#-OC)|w(;Mpry0Fh?OFNiOfA*R=?&F%-gjJIWZU1O^mS5&hHnq9S!=A>vCG{a
z^E>=Cj5kIcr#68xT9<m8KxCVrj^2Ka<x++^oxIYBq0zqUbi`+l3ig^Mt?TYsJRqDz
z&5qBt{J9K{Q#r>oF<8;kZ}4t+@V8I-)mz@m(-HR-I@;5ER1|N;qzOT#kty79z~RAo
zhhN1&|LBsv;qQkjW_qI>H2tS87j#+`+R+WtOcdTV!eBE&S&NEa>kn=S@f5twRZw(r
zL}R7<uGZBh(;7-4kn$Xw?m&G9W*CGRj3+9bx7MnF(v7>lH1Yela+QB=bk9_qq!gmy
z1}&e9p7ZxCR$*04zTK$%>6udN;=D^%yg2G#Z8<!xpf+P_d5aaaz-&=?*2@+PZh#%l
zQt%n>oR_I}Z8?6iJX)L7$*mqRFGm=;Sa6Q>%>(K_jPWBF<8fxc2Z$Hd=ZpD<IruxB
z<kZW7t<3-z7)O%9l7UKWS-@|{dIu|+iY_;v59BJR6|;=^yfeJMI(1U#XYRSJNfe$j
za9a|%ukd+?H97+yJ<7S~i{7kwS`D^{VCBL6z1n(WA^xeo@*-}RL~`$xNWwjYTEKJN
zj_Oz}BIzNw2;d!EQA)<d%RyI*jf68I&S>kEf3+z-)g<4*?_yT#YHas{3oI4Pk%RJa
zY?_<B4+TABcw>WApk+k%ND3+po_49MEu;dzFXzUV7p|d9fxLM%{Pvd)g7p62V8Xm+
zTJOQ0jJRV^x6K`=oqbz7<T+YRx{DMq+z0tmMLb@qSlo_cMIB4+utU)~$v(&Afi%rK
z&QhJ*^Ud?jPN<zUVump<$w9%s2J}14tn2u=Ev?i97h;oQca_0$izZyLb8}Q^aQC~H
z2|hj*-G0<Wv(1H}u}KPvxP*q#nq`JFl%-*dqD8!Q^9rD(Vb6K)r87N5j2QNr05Hwx
zqU5iV?8n=_l`S+lk}H6wzp7(bH+fTY4b6rLTZ1*1T$Fe%f-S?&JGfF2&cDB0@Ycti
zqxN=QDMl?1&CCfYbr*fMQr}Dub95RM1Wu<;nPWZ#uA!F<2q|#?O43|(VdI5+@);ww
z4GN+>+_p33E+%1%^z>d-4PytnXv9O|&AV^|HB#Mds%9%NwO5y-AE0!ckjJ8%CpQXY
zk1Z=VMR@!oEy4cODQirZAOtmFB6q^b2{-C#4aiEaQODIF=bLpI3YdZPTceifocS_`
zi;{Zrpbs@seq{C&*#UN;!J5FS<@Ouayl4qjwYtFc>C?TMC4`PssKEWFu<?6fX66Oy
zOJekk<`S@5^cC2SEtgM)vLuO|-~;fBY&9|&f`kcepWmY`ythFA<1bI+krG-Gv;oIE
z8H%_d-mZ+fpQ$yAof@@;XzYu^_W!1MH)`iT*Rjh53bddkx<$Zr=*rm`yRRNU`zAj6
z`)U~P4ehj2Nc2iW!AwE!@d9uKW@}SSE$NWUh>%HP1)kS)^HiDX8+6Ibvy-}qi}s+M
ze`DJ_5!iVdNmfgGC1p(VI@B}Q^Lh77`e~%b-hcYE%3n$cHRF;N%*blAbirEa=w~Il
z9YAC9s`x;D){<Oc^nq_P_Ryv__J$6sKAmBo`?Zj~KX0)x@uE+CWc&>cm88_@-b)i5
zGZ)NN^`cXo+mKtweA;M*j!5AmU2{{CuwIwmS>z~E(D_~(fO+*>L2Hu-e(zHsBKd#l
zbJX4&8o!Xm9(wGwpE;k#U`t!=BBVfGEH!E`5L7EDr<HKLYfG~YeBi6Mqw`qmjPH~~
z_oP*&dHHx<7}t(y0UQ3EGjU5x$`Vz5*N)x4=Q&y9Z3(IT!iu5&8ZL|b7;34e&sv{j
zrvw`<MY#H3Ua|_DaMw+0NybqJ3xC2zYO4v)EY{|E<~WS#oe#7$o$sM~;#?p?3W1n5
z-bZ85x-K+9HJ5x@23JZD>td+b*AlOBN$}TFd{~2iV2os<kL0BqI<ZROYdz%3+gmhy
zByONN;k1@ZT-$3w;Eq@)8}*A;>AvF7s88S1)~!3F9^t7yOpK7dI>48q200!1GN-Ee
zDwsA^Xr{<Naq0noR3WYLV8K6MZN9qWjMdr|JhP^~-W*&z8a%A``bMQfAk$^pmMaK)
zM-giwj@2FHhc-P?n|=%sxauyhdrC1SIt%E{bY4>%d=b&0#<NmF6Ud!602y#d;D0cB
zjG>?s-Z3P6Ml)izLM68E2A@IR?mLlOpQ(xM+poQ>?rl71H^`B{W&AqVSB;h|c4N=p
z?<HvQ34VA8bv296gBFY+Pd+tv>Ldf9BVdQptHk<C7Uj5xpH~n5nq5|V^Q9^GnCG6E
zZkL&4#K|8SpxoNjB?nV@K8J>qc$Z2K;JfB;36|7K;zLP14hufw13!jaE=}(pEFOCL
z&I7rh`3SXgqG;X49sUFK(<&~yeQ-OYBt#2@_E|;;>rm_V2v&IqJ2p{1YA}H-mr_kV
zySesncN4hZMhyQg8d#)NTs}6W?<aJ;7^Ve!YqFQL1aM&`7q|H0_zpb0wGwM~3vV)*
zg_Jy_sL&vlS%B<ti92d<CIm;oO-w%<=RVKEukZMj2BYVxgqAldUN4O*c`7IpRC1qI
zAn`3~D>iV~R&OpoD$gn<YPRzc(An^zgVO76D%X_~vO`G1g9%IlzZ)q0^djl6W_Py3
zts`C%HG^=SRqf(2+WsZWCL=fsi1`^XbIlxanXHo^b6#KL>aYHJ<JPDjZ-40|TcSE*
ztZ2?cXcY~8!w6DDi@4wpvI%an6N1$&1#??M9tq^ul?ZRqTkxkDSe@ln3;R0xdA5oK
zKRf{%(StdH5xRl$%ut$UMLGSLI@d+>x=Ni_=lexL$tNN9GP%e4F7`|f4fQg9$iEqM
z1y`CpvVs&5uA!Afi|IkB(q1#BelK^pxBn=W{(dc$KD+Hn%N-%9+}4uQ++Ecvw^n1#
zE=<!26c3$#hF<(@L@p-+!fSN9*nhaIXg91UycKKu;eDU(yHIXtiF;`T)!JxCmnTgk
z$MFNzVM2(kXc?1m&_3a~$Cj<0_ktsOE^-0Aw@yvbEw{h#&Fu}23>1iUP20HF;*=|r
zGP_!Lu}T$=<5NV}CK|^VkLfA;w;|fFb5OPv9h~+vZE|tl{b9EByINoDj7>^jM8N~Z
zC%7=55chvgKh2dP2$qfEDn#tHl-1YLRgjRD!-drrHhVG5*VsSru-BaSV})ZV&@zX#
zp3BGgz2_--;HoF$zrKppNe=t6gg3)`{6TwjC&%5EeV@A~-C7$hy|^>dFE?Xfl`dp)
zbH+!*zj_$~k0?WvgTj;r9e5<D@LJ1_`VwPDne+G6D=ZNO(LuU1J#MC_I!$2GicdkU
zhR&d8uER{8f(M2y@MxYL&Xr2Vp7`}QSBLr?<$nK!QGFim&+bW%4p3{~(X9!wA4Z>P
zB`6zAx4G*^ShtR`KP#E9(?$BHG|Q>|@CuPU{}nM4^o)jZ@Wmu;zYD}pZD>u+)U^`f
zinZ^Se)fr$bY1lt=cHyiPpJj9qI@V#lq~85w+2756Nli!<oOC#^&T|U2C=4Y^k1Ek
z9r(D>$MsvIx!HT#e9Ft=BHTpsUBPse2@7l#{Rg{><f-8i7>-+6eCM5z$n}x54X<3*
z<yT1ck4O%;=P;jUTesxw-!Gt&(0mydy(*H%Xg@IVt~KA>a7|q>-S@j@_QR7=>%J#Y
zk|;%tEsJg(@e*W<k9*cj`G-dJ7_Fp;dROZ07TN5Q=$*c}7u=)X$o}RUT28WH<hlpO
zkdJ+RGCuXiX5(juU`fj2*ah{rq*0ahomHs^-nYxc-a+UA8h)ND0*qa7IO&Yv3G@bL
zQ^shWMAVmKZ*63Eo}`NO;hFD65{)I4_ozx#-8Yz9ThYvbFQmmAQjc70e7)i7@N~c&
zmceOtOP(NG0ZlX!<Fj{huIHB{Ae9`#$**qIYwX@W%v(2x3K$wX!|M*T+xH1_S#~4U
zA5Am`<g+j0ruaQER5QC5<PCk?3vbJh^?e=6eEQUsS_D=?gS)+&)pOt$1u?>dXdyXD
zq8sKCUy3Fdl8F@krz)ypZqe^j??c5(L9`vb-~<a~LCypTdpHLj7JVE_nfBrR2l3$$
zBv1KPoZ9JCpSqULIE@A8)h@#M;C6-rYs9ViQ5T7Nj%0HLp4x%(=K6#D@FY}Acbe-`
zL}Vby?li4=-XiAK`4WaiVidYpYP@%g5v*aw&qiX@&U{#i+8R3$GB_&XH>DQ&vSoxL
zcUZNn#^DS!BMTeUA*|jWq$T*ha#W2+jDpytT%ux*(_n@tLDN<<u8Q@GHidR-i@LP<
zbl#$8P;zNG)cRfy8GHq6!K%~nl#OtPiTh@1_2_!MFO7;e?R$B&gqv@M$dQi8kzCZv
zL5bg~z}Y<n2pxNma#9dm23$**D1ToH=WLV2DS9EGk~?#Ie4;M7&|MS+@W$=-2Y-Im
z`e~6UQDMHy6(PZQ_BqGSRa}+Fkg*fP^{-fU8%Qf*Obr?&fQ7JfQdyHCc!EnyQh25L
zYo_zVC5Ca)P|K5jrOdZmG)Gf12e_iUE>>NIQ(6RLAXu0BC{hztOIIYpv>i?v*s`~I
zNWLMoIlLU;a_PEQ^aPO{{p<&LIT-O3EQDxEGjvi!!J}chKpZUKGV&dqNp6ZuiQGcj
z&}mhpJou`{0e+GISUkoisJW;`Sow1(;5k03q8LMP({`45cuZKGGx>5ReRd9vk4nV5
z=FnK!_M-0BInCMy7BGEQbhLbCWN2*QcRw%3=i4;wsjgVt%&zoahtmLu^XNoss>CQX
z7B>b}f21if<9h5mY6dDgMjzBO%i^b6-d^f-hsn~`RoZmXhObBb&l)X$fLHJd1Ivy`
z3jLjU!G@}*0Ur7o%Rj7{<QaWV6lcQaEU;e+X8m=Nd86T5<?yQrEhBLIbmYFOnG)LX
zE)CYwOqtj5PI`lQu3wKEOpK4Nd5L8^Fn!4F?WwG++`ZwdlbF;Zs-OAf+G^)`K8*a}
zh%l1V;8|7=a`wB?SOC3qeLHx#XT@900@?H?WaR_HGSUa`kwS4l7xx~rxv)_AQMYW6
zF|K#w%nv`t@SGJ{qTGCw`lKx+6=Q&|i{gv76o}&~skap=^kOw>{2s1IKcngHUgnTF
z!jEU<&(1rTJ<#`CK1wJ&Ca8o#KF}b8yU5mu<Tl1G;Td>kx#cJFNr@vOC|kcQ;U23E
zUfK@>_)lCihU+BPLqf$~TPxh|x0d?S3(-^c)DX&BK2CoA=$XmgF3aJU8F(4V4;J5Q
zJcK_8pXo(-sHBrmcu?rYYtp>)PtiCaVMg2+oIXm+2@$E>U`>tR^@e%Iwbp+|cFuQW
zU6y0ID%a%D1qKHt{Th1tZ%kQ@mGMZz5W$aega9QMGz#>RAw8DYGLG!A{(WKi53{ak
zwD%ob4WB7s;1|lx4C+5D7q~xnLM4p2(Q<uWc^c6y2Q6Bn#i!F%gD90dbTP-^xtZ3`
zaq6o_>=Y90X!+@n>6t|JJZqVWw@d<JR5xd4t{|nc&v+EsM_-(uN)q?5`B4yLzIXk|
zm>iQKd1#hLN7ZJZ4NKqhR&{##^YmIc%X1QGoKL#yYN3e<Vn|Q<P|iP<<rdHa5$RP*
z{0|7Ff}`%JptD;NKY>|7k5X^+jAnnD?aw?-xn4dW_r*@=DL|ePIZENPHE5)XlcbTL
z$C&04X*lQ!2YY8TDXHA0dDJ9&K$>Ia{gul}S)73_^R|cK&@|xym;eHyro#y!+qS!1
z07R{pS6RGsxki^{qq=<HX6EeAWPU=e*JnocnexvIElxlE)&Iwl=fru$DZ#h79Z{EN
zgA6-KTHbHEyAz46>~$vf33gdZeLM^0F;^6wN6*2?hCfA(p4g@F(d?yYym?|a@;)5(
z`gfaFqj-W>AdjR-`{|Wd(wC1m4=;_i6(k<*a#%MB<gW6Dkt9ul%rBmb=yq(V)(m_)
zedByk-_R<L;;BHclvLH`ZD*uk@osyVlpCZ|z@?e$eAukx+<zSn41?Ly<np)Uf7sbH
zDaH15U6m8iXQfxesSK7`Hs6l?IcGdonR_7iv}V8a_P$DpkD(ykWWnu-RTPDViij&!
zRGE#cOofT0qi#c3`Y<gwyJ=N2EpMGX(VVxy{Ho~~F5&8rA=NHljAtE`XJAN+j8uVR
znjFUt9J1yTIi!obfm11~ETMU$JHHy2^+Kb8c4vp~SBF#*63ZS(_alY&!@qPL3AUDm
z-N5*Y#gb<!edR)Bf9ng915QPN8yT41vSmoF-_zsSnle%kkl%$`!{PPE^wP(=i&!WK
zkJwM92p6X>G&I}}o2N?8e6^4`9etpBU-3w(y~|m{1FzVpW_ywKzYrY?2$bS1JCSkQ
zvbdy*+kVpv^LiY+9q~!n$BIOH_uOmBgp1|mPRF1Xp9N@l_~)oT^&;+nq{w>fsKgFP
zi$2(}jn!OXx0pM$ytbt;7OMStR&$3-&1KVP)<%&7h|fn5Zvj9iw%b_-To2KqyY;N?
zd;80QWga*x)uuq&)QPlWwu5x_P+j@yXa8u!zG)_y0c20mSySjoqXWHen3x2HWLOKb
z(%j$4r1I{Jsp5d(A?ntzBF-l2jzM14snBwWrP~mnj!KG+y%GkbZw{~m<K5}Zqy-qY
z5_8ro;n245{^c(g1xx2wTSNoh7uk=O1~&cj(|~S5aAiU;1%z<+04hG~u86Fr=Wjn+
z{3@v;-L8>k?Py6`YO%9<?$q6Wo2Rm68_$CykHt3@ki!5aMbvUYV;sK{oKS)dj%7Oi
z_Cnw((*_xca=^OA;{kQvRI2%HDG!f6e!qg$LVsc!6x*LfOPon6+X44=k9?@!whg!E
z4lWe?;*4>|qD^*%uV`u0d}k}N)#T;kAFTSpbqvI!Aq4)HBd$Lrf!GZM7$#cg(c^mm
zykBrkzfbzYc<5DegKfRo{rV#$WMiLyl&k}5u#3Q42g+`KY5UG1+HO}U!GQ~W)AV~a
zXRT(f^BYeld-nSUCH1-m$$1Sp4h@h|Y*afygFPBHVmdm`T#RATwz*v)0gdN1&vRpm
z1>e-0z5(^aGrd0*`pV%b;#SO$EG?iae$D-U^@>)+E}_DpEi#Hdb-AjT_BNBaVDZZD
zLYqdhFw*7T71+%p9Q6WV^$yShvG|trHBUvBXRr7vCJxJg{I(FFt9(JjAaiCUpW{vN
z{E`yA@-U-7w|^B97kRNjgM6n5+sWN3DrV3d_%A*C@=4(2p`qrBg@L%+E%RRMLu<$_
ziFepaCS#|>4cFTvK9T-Dre}jMG`^_&D8G?5`B>8Bxx7Wmg@WTJ4A|AWCq3X0B`q}E
zTYbK!B1u$MvgIT&YmGg&<=8P0Z!Y1eJJ(8p3rm@u-|2yZvONE{B)6}laFlZ}CJ+E3
zI2Dx!4!fqe@kN=-Hbl0CU%yP7TlV^#UYL`5K$ZT}74}|?*zA43d6Y)Rf1g2H%l?v#
z-2=CZo|Y|0&h1j4br5YG8hRsu5s&)QU29CQ{55I#Mncu;z@0(&Ce42A@fqnf+?D>q
zF`y1o&OeTE?`C!d2O_LK?k1easr*vY9V31#^l13ZY<~9nL&-&kyUI(uIJ(>AWW(SX
zpo;l=&;WEsy~K~LOG?Kyu5w&uRPR1>!t<g6lRjIfvdD3UTQ94j>iR{n$OnMWKAMo*
z5g(3T3Z2mX7TChb*P9KyeIxxu68y!GO`f-EBk*ZHxe~KtI59Mo@na%;oQC#T=I**#
ze*eVg3t<))pk9fQn|fuF4~$Tf(tPgK=BD}aMxDcmxxqTJdd?$zrByw$X%EHtf?R$B
zBCAT-d)FRA`)||@7N&P8f_gZAO3tn0)#XgOT3~-?I<l*VpO~j8d9_qg>5W*x4hRDa
zziYrHIxgD$=k?$g-=I3Z$`a$Q?yR>+xMjdX1C+LRVq&6qZLPA6B&F4D#NNS3!$8e9
zH9obYyF&B3rr!HmZrD9yE^iO~!MDZWEBq{OclCXH<+2>(t_b+G5QQCv<=gW2QQEvw
zSRpZYUHUZYT3#6maU|4i3cQy^LihObqcz#Ar;WR#FJ4>Z3$AxQ&fL?>a!e&<_jvWj
zKra#oBIY8INnm??LT;DbF+n%CE&sgYrbs=qjp>&+PICDELg??g%KqpzB<eS8O7K`e
z>6%7rF$YJkRpmEYQNWzzcs@+}SMI^G3aT!o3@d$`tSS7SAY$~x%n1`@;U}#4oRa(T
zXiYsBC3gZ#p5TYdVJzL}>_*k<PEA<xb%b4xioUPf0_AzKDbIG6o0%&s-c&@zL1tfq
zid^%1fuA39?hBIw=Oy5L`WRU7H_@YX%k{SNG)J#KBYB4b!;nsW!o>~cMLV;6WH*uq
zIMAE|fbF=O@U~{9eS*%|SpE8HJm=-x+mXDK&{9M3P5TqmvAC~!h$Ig-B^j{{{=L4w
ze!%(nuU`%acjcQ%NKoRf6Lk9B&ID#0*6p~?^4bsK`RyjpGIFmtwfprlVHuCw*HIVD
zg?RhReVchg+7f9jkXBWB0nykHIfJ}R7fbbd-y5B-yPsI7M#JiE-3E_O!Z0+jgI;w!
z*h5cUOAmfj94Mu1vh&7L&&@_5G(Q^Hb)jqC<GAT@1^#h2+MAu(u&47=e+f7NY<QKR
zwy`bYznHQ|TQ1A)pfD`8sb(ta^ee{wE;*3;wq*^uS*I_E<dm>E3+CnJdH8NDuWtnC
zc!lww*8BqC9i!W7Rl!-@EsfnA0h2yIkHd}@9GDxxd#NiN(%TQ|44;DzKtb@py`0I}
z5DL_`TR{^4I33KpK!0q#LA0W?Y2@4uSH;9;acZy;CaiWdanfVY&B*Q<^W{=01d#D{
zCPJmRnH|@;c3|iJ-j)BOYavCqT5P!I{tq8UJc|<t2E!yzy(<(@v0SHrB=O|P_cLM`
z>$^X_+TxQvp`y+9ID#W+>9Ab>4PmNjBmFn_922x7toIeYI*OhPK$eJG$SSh9C?GB<
zP1P1$e+?`)3RP6s)p8%~_4*Cdrkf-_*wb`G1KE5aZFFMA{E{-b(B<S2>RkIh*-L9|
zM+cJZnQD>+1RvZyJfz&HiNy)^u7h!JRoj^6uOSyLh>Ylbq5&GKlt~RCbwE0mmKzo{
z4uNS2ic>3JOSgHKA~}ZzEgA-yU-SCGuXZtUP&gh6h=+^1lLff;-@IaCCL%hi0+mFV
zKr<9LH8Etl%EOrwh@8*!7khJ|#prdWSY^e}-2>GL^<6N7hS3az=0VqF%5DlE%$z;E
zgPX!Rx4hh2d(nUAPJ8XRU=JGqvq%soUf(p_{;jQYPIg;BtWEc6T%2jg_0aqqJ0p;V
zvIB>uH%Dv*C<(S&V>Z<bJzM%^0-pKHhFsy0lJeGeUPDOnVWiTG6M}(-&mmnvH>Wm`
ztSMJ7(lcBJ2@&}Jh`_3lD54FBvsQS9R*Suk-FuPzi4NNzSt{M!)$e1lpN25=+qb%`
zvhoxy$Q|*rlv4fY&YePm)s7o$N0H3e0${+^Y>R>BE*2O8*t*=yPXumsTu&AV|2{W&
z3U`{J6cXN?7hfl5PeGhUI%>9g7I9TT&@R5Z9^P-{+=vw0=yWli?#(*40|f1XIz6j)
zVg0g9ixLk{d+79qi8(24*o|<L?7hPXIcbDkH#+YDk4fu0BWuKR1Zboq1tu>Z?a0`2
zB3%&FcgUs4Zxx;me~~id$A>B#_M|E^f_!dYI9;=oJ^N&CN41ZMbgj-@{psEP8QN{#
zi2@dr@DuClg8d@<wZ9hxt>;dhhOlpWDW%-B<~!j%#O~n#-JDwAs@OYM?B@?127r%V
zM<~Jwe?jh$T{|UV*48tKD`VidDy5eG6UQx)>uPr<t=Ug=F>i&P=*Vdv3%-B_nEqO2
zRtYd!W#)Q1#_WCeIb`NaWNz={twVhx1vVV^s&D{X0v3?O@kt+ZAy@_?Zq#id<4L%f
z4JQfv<sF?py}c{nWEZ_DPPZeekTfM4H9|ASDf?xnl7X{Ix}Z{|t)_HEk>li0#MFL<
zPt)cWwB3^*SfL>S9c-&>BxeRp4IoQCQVc3z9Z~`#^oFx-H4i$|X0duJc6?K1^10*1
z3v01*?ViXaH0UJYEN!z1m@dSe&9E{rK#P*jFg5POV3+)pD~}f_+HWkp8Akf=BKHrr
zX%E#oc~=2UE2azD{c^FpZAd8|J1*|ux5D+vrFVt!v#V$hRcJJ-c|&G;R?rdB217dN
zkBk#ekB<MubzCA;Y&S<ezle9ShW>QrRQ#KF3kbG4LWncsjpR&$sfa;shXWNL!Cbb%
z;xwfW@wfn={mb}}10Byjs3R@Q_8?sGkhzMpasFaOkH6gNQ`V{G#Ur!C@$=)VgceA8
z_nV~QUVde(ttn9!UNq`%$1p?Z0bs}M;^M0=lIm^1_YW<%7lX`go2Z?_>=YfrQ4VV5
zJ-Q`Yf#&D7<skmrxSokb|Cr0=y<(Ka-5D2;&Ef$2oUfEyt&M;U^M;d?lix<zHl~^5
zXF<tBTM3f>RH@bEB@*vz_|+%C!W4BskdIG@1dT!*27+$PCj>1-ao;1-TGxD6&U~b`
zu*oW1^(76vr5t_s<?`%zG)EL9Z<e-v@}b7F?B6e+#kGxlf8bD>QJb7F2gUvUg~Kpr
z7>GQY`@n&msn=tfw@X4jZx}@o<J|&~fAWr)ZkCpGZNj+c)95su^qnHd-4}-$@4C|3
zR&M<WMI+3ho@dCFeUg$+vxWs6wSI@|*rh;uL{M+#&SCZJ@iIwYdM=ACkbWCl9sz_c
zvU9YAJ^P1)?K`yJ=-|g&l=XipKNyXp%0YzPi^ZD5nOlg``Ufa2#PpR1ckP!Kq|}9d
z>5*u5HvYTo_B-JfdC28Mf-Pn#k056h7JMA{z~gu^UDLAlkbEd+z*qQ95B7cALe}+_
z?C1KfR7@a@WC>tldq;LB3&BLYzcEJ8V9uoshrg@u;x!8HlB{=L(U$IAMnK6z7jArX
z(%Eg&;>XT|&q4{gec!&x#az2b%hlUgoW)5I)}Q=UmC5%fsk*J`xfBu%^wE@;AYdy^
z&30ODK<9)ci22E=WCE8F8VwZ&F6-1)Ab!WglGM|&6j3OEj35Vwd!9Z%#?&AbE_KyE
zR?L~iL~u%!4<!Ri;(pFP_}R8**^6w|vEBqr+m`^+A4#}DjX%tAGjpv<cHk!OHZF>D
zw1ZU>Wd=BPFP6)2QO0=E$71fT5FIlRmq^5oGAdENRNq(N+Oknx#j3XJJ+g3&W9rPw
zY9-K02lY;!!-2TlSYH|0FT*Vb1PvIX$2;ypE{MOeb@!o;7Qsa;^WKOA$a>W~b^7Yn
ztCYG);sKv1b@7+8$|__BMt80(ez7a?`i1&7J2|Q!ii|{7;4y}qg3WD7dlQ~sb#nT2
z+zrrXmB&rH>eDtIJOyWwW<}jJl;v(Hpp(klS_@AH*-YdPFZfD1*LF^ky8BMRLnkEl
z$kAU`9xIcaBasg5hXdb}7nysZ_cP_4DWqd++#o`(90#r_>nn#^$N_)a=_=XrQM36`
ztG2Tjpx%h4m_P{{qEz7%Gc$*ApyX`eU46wtjw~*U)zzG4NrvXe54D32ERfjzevB81
zBWYIaX>`)LO8b>L{4S|%0ZD^XQ+{8Ho~Pl?gox=<>H-Z{(VgiN*GQdPreSvrb73SI
zF|4q0ptexMsfUhS0E<q?c<592cZ$AwdPvt)FiU}!n<A+`UClp*yK`YOep^2hL@F@m
z%#*Shh$R_IXJDoG5>9THf~C!V+nIrj&l$lL_4@@)YBM6<V|yv5DbYxs=MR@`*k~cv
z)tpTfjbaHZg1>o1-q}xC+2EWNhH3j{vMRr)EZ$dk+s$<Z@s3$p<bzv;LFIGY796dO
zyHC)9M*aYu{Rh)YE7e&XFoejZ!<#X+1<EPioz}^#$jAy#xZNQvk+Y5sCi-LN5=+5D
z$wN8;I{FgryASDt4%xXqqu*0$NtcD4k#KFjsEZ`Vj}OY}sjKDernI1Rsdh{_e|HQ#
z$V=Usw5!F`@}A|q7(LJo8TFd?xWt|+=9{YODTEEiLJ3&kBg|B*MK>Twc)5+uXfNbz
zpze3<&xQ6l5M!H~aKPcRFS4_;M!TnNH@LnfE@c`=tjH)`91<fXNIkjv5l2+AG>ckW
z=U^hd{Ana;^}tsGDMQ2@#N1`kI56_tw{OgpduPvC+%_f^6jP>%hr&^wT<>SqDMXJl
zsvbHW--&Eo@ye)%9@o2<!w6?V(~7U?^Vm+YJ4E=veHVgqI~_z}=$GG5-(7}5{qFNE
zooK1(-3)3)@T(7*=xbZ`=)m-DD28qAtJ<G0k5j(mqjdid(m^LADMke0_Z<3YkI`DF
zunVuP3e^au^-d|zT@klHVMSBOw7ni43!y-oX#ig87lic2<7o;^Dyt;De;9RKf1+`L
z0x@9GFf_S1WqY2U1YCE)3q=eW<L4pa8(FV&PWx8>>^B-2eP)4dmt#<8B0ROp0dc9*
zIKY^mnPtmNX+e|qTHIUUqtimta>3j>azOHKHWDfS8#3M94Xl*{BVoi|xD51k#)9`O
zJH647d+lF1a+g4?sWG95A689VDlh&Xf<MY|D*25nvSk*HM0xsBT3&v^&6NT#F=*Z+
zw{og)f#Vk7i*9HT(N0sE$xU;tPI*^qzF{oHvZt!8Q}Zfr_55IA@>1of2frbtVxb<O
z3xAvx;Rt~`d52@#85jxp?!<Z8Xw;vTOje;jXRVPWB1|PA;mLgQ>H9z}=wNC3*qDZp
zTriANrz8w}`}*!y89blG@cPwD-Va0ZuPUw}(brHIjYz<P5qhsq`dZZqI&gNZAjNt`
zOv&m8V@%zE8i^_3A+z24RWHAVRY)3)>_Kyr2XM3TL>FucWy&Uz&O_atjq|KJk=^n}
zi&85;$G+!#s&(+&fcW@OM3cj4^)c;8tI!sFe8%|X$jId{3zb2q!C8V$VEbqDDy6g`
z{H((F7oBR)6NE_zR2YO!-W|vz&C)~);1L2b=$b;<YiqSt^g^558(okebwy=ZDaAs_
zg8J*#%B@zhhIih#^=cT5Ae)bOzp!w2x*=Pc$}r33WL0$so*ESX;!3?heb;h>^X61>
zaq$<wzBLAzM^J3-?2DGTXlxjmEi<c+EFCZ7Q5g#p>LGygo?e}KFs;$opd`H0VscY!
zh&K<UwQRAUq)rl8QGFT5eA3(5dfUJg`xGxYH@;IJ+4-cIaO8s@yV@dQ)^!^Yj;N`t
zi@gbq$mY<dsyra&ymujNS%l`gS?r?OO_CHMA$EfHw70i+A0=LUQ0T|XO3`wbG&rl$
z7Lmp8KuzbR@iu2Z<Y0ViX^Jl#V5p9&?rA%+Q#~on@f6|jWxTswiV|M)D=nKz&vBVB
zO-Z{4URRS2NFyK?VxhyXGjT7lyS$78F>haGx^PkIuK0>LP=~vxrmLHE{Ik}ZSU-!T
z3wBsSJtubxe4dbA6QzXro!IqNIZo@l29N7d>Jq=cJWi8${hHxOe%>gu@P9_*4B?0M
z)u-TWfX%D2($XhIMs(oen^*9ZSC}jQ^A7zzD{EQxZx6;V5OMF32>oMo5*G^bhMJn?
zh2NPrH)ufCm9Ew~xR^3U5K5;Gp4;}Jy-w8(c7J>ab*ZqZ(kGM_wi)MgY&j@|;CFZ0
z>UM;U(?gz;5S|<Z47sYJqdkzjqK4R-%fjz{VheHCHa-gCD}B{6Q#r%x%F6g};JxIE
z?_;E(+WvmUlynX89ZA%8!~;eo3B$Yal!Wn=(j=1fFm2kSm3vptEiJ2)*4xWX5oWNM
z6NVGfr^+{l@JOd1S%&1tg~}1zG^Jy%iOUOl*42yC`36f%o_CPwJ%@%gi~Z<MR<EBC
zPYHtV7cMOsx5{y+XLfg=uLGg?*S?*s5lVl5$M%)uga8DI@D9x~^4U15z%S=RGJvi@
z==E#||BCOGo!glm%X^{D>}lKD86!Bt4&Ov%=0#0|WsmELEqGxAJsQG*m6M-(2frJ&
zVOiE&?g;S%CljxKO7kd2I*X7yLxAusSZ7B+_1KR%!~1dX9(oz)7&^vRlp}nopo?O@
zXzNJ|;!A6%6e>dc19e=+qq#e<bK?8^mPZ-BOu4t%YOs==5F`ySBtO87E;V6GQ;*tK
zpec(RluK;BF95#m7c0^?i<NEsk&M*kK4TtU2Wj`K?*vK0_Or9f%T<c$6djCT-l^>`
z`uz5gl+;R0s&1R-L+D@RBcij9-XGfyrbvMJ<fVc}>fS6_TJ8akjLY#N^$*$T#O3Ma
zx3rvq<R8akh7$t~hq%TKl(a`iMo(z<cRtcibB`xo+CxKCU~o8$4{=39DGZUru55%A
zRX~(SwFL{dW0|j_9NWcg=YJu+uwxh&<eal<*NLt0@Lmlr{sW0?-zO)Z9|B<?<-AB&
z_8eoo;p<x%i}>GDbhkycw0462A%Ki{689d6A0FYeKFk!ftbS$svEzAGe%SLQ77Xe_
zv$l)aQHoDgF#tNjiO;uB#HEBy&@L2NcTT2+Eh@h>;9wp>6tj#e#>U_?^;sHvB9P9>
zIl*d>evqRBchpK|vEn7oZtm@fyEUQiM$E8fqdH4->>4042PWVA=bhTYqQJwN=Wc~E
z+=kE+upGl;MlOQlvxI@(haRD=;F4(iwsNgEABgv?{d5%;YSVLC%<de5S|-Y1*6GR7
z0Dg=FTETCbee)sdC?T@Tis9yaWfz;Nk8MdUNcwBRjwTgnD{Q!C?>G@|D8mnL#RcTc
zMjdSTuyUo@GD>%#*|xyz+G~XBA(U!VfQB2@XZVeyVwCVZNQ=Es2Og(Yb&bej(tmtm
zBx=~S!?EMK*o0#!A0#i1#RjoOO+|ciLj4*iApEjQwm7sVb4Pr%%;|#p{J7mDBT@u9
z%YrKS)AZJ>gfdul*bzYq=EIo9Ca9Sn7Ia+eH4vPLId~@+_9VW<*w7haGNZ7ApKyS2
z&hSw<lm6L==8?D8RiktGwf{@U&=WZnKlr7$gCS4Pv-<+BZ$0Db>wAj&=|g2^nK|l=
zaDHtPQp~mRLZQ(6$2O^Gn<3R*SUQY(3QGg|qffuYFa>8ZC_i|!at2`)+u0k3Fqx62
zrgl@NIcLEW0>iy0YR(4a3`B*)zRV;u+2fxPz5Rn7@+CKqz;u7RFyD4?)*FQHb5*i>
zdRU8HGt{xWtOU}uxQR{P@EOT9gDJs@PeRSgS=+^l%thU1@A}Fo%33#gVQp8;-u?!%
z{Sd#8I**vG-B!^P)S9xX74&eKlQEFKSo$(Z%iMfEb3<cU{lawPL8RK7kL~dvJ$k|o
z^N@5X*<J)#3H!5FKPQwg>9tZHL<Ez>bbu5|fg#&#nCcvP;1aN{DOO%wW@Ii&{!!fZ
z02bKM3R@ve*4Y>gS#BcT9-`gm*1pDdxYkEmw!b|GyG3E=2v2OUZ56$P7X{%`6U;Ov
z?M@3hwBo1RKQ^9ism-1E^yM0~FZhlBfEa+fOjLrf2SJ85fRZRDV{nncALm|suh4NK
zUMVd$*0;<AX3J$!khsNb46)+{s>D_5gUGkj+UkCdlxSnS`6hf}2kA7T(xrd<RLF_J
z??aVoi^!K6Itka*mE^?wSAvMtDyY<FZF51~eIN=vrw%>QR}~1$8Hi5Ln?dH}`1Wl(
zvZ*3|LK!3;ndOFiISmRzsdbXU>v3{t{!|L~TcPv65y5Yv%30O$7u_0{(k}v}i^JQ*
zl<wN<THT-N{TkIm2tU}KbN?mm%EyV$zUZION0GH>dK<t$F~4x(n5sZ>4*$LMLqVMZ
zIWX6@6|si%<FRWI&RR@rL^o=63WBj#BXz_9n8i?zYXu9v5$dGd|3q}i^$`qNNc~s{
zs~_viy{6LF{Ky1E55vnuGrH8YFONyyycK@&9)IpacngkX1Znf_#Q4C=su36EL@B@?
zcFV3UO|5cw1uXI&zAt17gB$ZFKOVTqpay_mQv$p;L0j2k2_nFdqs>vNr26Xao4;j(
zj^xIlb#t_NqQfq73E}!Oy5vlURFPl_MTjy5NK2jAt{(fsCCT6a|7!2b<EebY{VPNz
z*`j0#SxYF&mZVU&Xrn@>M3%BswmM0KEJX-$N~BGypR(qZgk%><aZp)OC|kDfGw*vW
zzx%oO{&nv^_hbGjXO?GXzVpoTEHf`lK=tYq>0jc5wHpIsdcQ+<x>pWW($UFDse|D%
z6$U9TS(-Vy{DX3(FsG`0yp9Oz+U9+(cGysS^`5Z&jcB#?#Rr<U1mDKk-rX$)9G@tK
z|9)Pg+lSH2-Z%$iJ$C=jnkK}+Ru04|?y*LB6vvT~A3a~KA8|OZvC95(73%?+Bg1H*
zk_T`s)y9Rj7i~<t$!&4qX&+r#pWrL1xZ0iRZ;X<;t0R{6J$K)b3k4nDzYzMnR(X)o
zR`|89T>xK@STX9rsi`m|6*2li?z;1WgU8vf4^Dbjkx#xXPE)|2(A|J96J+7uksG3z
zxyXXVgS*QYVm($pChSC)X{%Olm*_N*4+*ww`p^sqVohQvclN(5nZJO|`l%P_btwF4
zLbA!#oQV=vrC$;k>2wA}$56*jP!|XVkWnTGHB96ss1w$;>JwY`M#SiMv8v0Rb?sS`
z;-;miAL+6H4RAlc+hIoaBL$*ZVi|%-2WUqDZMlx4>URt_s46A?!@~|{3Ao!#fWKp)
zWN1`O4W71$daNYDpn2UuRykE?fsDSWJ5y}=u*SOPH7R@lIdvbQ6d8xlki?f?*vWO)
z>MK`a_96nl@#8*W4f+6UW7!JTKX$ijii$o?p@%JY5>}c@jtVb@myG1TA-_kg@QILP
zJ;l2#I-?D{STiKufAx*)Nk~wUtbsF}vqS|i)*70&W-kv$@nzqyY-o^G+Hm{@kHTZU
zF4n;2PV2mpbE$o9TevqE<-<~qO%Y7ZCtt=$bHEu13*~BC-j<TPqf1KS0K>3X>{!o>
zzZOz<!2++4!WG|#sLaQ%>OPCIWH924;x<rQKvuO~qY+W2;&F*WuI6Nu>(J<XTBg&a
zmELj=RYJ)9>;GwmCAR<kLK}=!CR(kP<C)jl%AjylY=y3X;+3)!QDGWO#AFXPd;bJ{
z>D{?@613H=-Q$*=7&XbJMzor%E#)M)oIOW!`3VsQlCoixQ%_CFxL@N})k~#quqk4i
zxNt#U`&zga->7!V{k#Y=)?x;1on=78v3ueDCM(<BvU742zOqV0x>Sw0yfR7i2?H-3
zFeKtjJZAdwWD*a9vz)se6Itf^ac7mblt0DMDWd}9?&C{R1a`wyH%U=jItA9FzUAW@
zVe;ByyGKSC^M+6#ik&W;-1eHw@!gC)8P+9!DL%oK$?fyVub-2-8Tv!xA3M=#vEaic
zPgWK;e<~Dd@@d>a4<qMh0i&2+vRk3xRWg_|pdALzaq8!p;tm9uJSkvQV=~xyQBd#+
z8U+EO*7LXxCVPYdd(SEQ!cs9M;jCg3tAKX)T6?y4a)(JuufjRK->vzLF2!TCR-9!?
zt6kdf*J++NXiwrB(ZDEYC9>Iz22+j-vV?Ci<Ue1#=)wBr0u9LTOlUV3@`Um650ly2
zE$=je3{}Ka)FzN7tW63mXBF5c=%W==_7WK!sk%gu<d^!8eFQP%RZ&X=`OaTYNJw}O
zd*2GlkVA_g`^N*>u6G4CAmDt7HG?rUaEs)H1^T=r$`xf;=DQQ>MLuWDmaO&@OIxLV
z>Xwel+Vf)R7o6X2xPBZR9DNDftPV#7-<0vPbta#h72_DF8<fIG199vOx8u6Fk0$hn
z-+`j!G1dp`BX%7?Z975qd=1XvKTlzrO2=;9WaN3n$L%M2(k;$ES~|d;b=7r8rt;O9
zx$5lvhygVS^RifQS^+HL3(PJnSExc!s_UYayVt(jtj{h|+{ayLI&oH?eU&z;>I>h7
zCtJ;13Xr0UwvoU>R5FlJpL1k`q%fmq_!hR`%1~w>h5y3NAWF^AdnOYa13t1AOv4YZ
zmFaaks(gI59}O*S?_b!7;E^MT!oIVc%^B+74KiY-V)3OL1GM#c_nr@zWYlJzsOD%<
ze6G#(T9o7-`DdIfIgBcFy?9HoH3tRJctL36xx2=vMs`(USuI71dlzU5)tp&(W?xLi
zw%ZpvG;0SsHwSc(OuBM^)+LLmG59@EGZ^<gm!43Dj>uFn>A-)a1@ZFaLn<!?G1m=4
z>FmkOSA8ApEF~M>W{wGx2P^M8N|>Uiw*JBOQ{aX>Zp4X=tj8#ew;NV4G%m{Kl}hFi
zhaCNa_)Z&V+zKkR>=O*w{!4c2$ypl`Mbo~vdo6<;^s}9Tl+m)G5?{)~8pUs~t*}yA
z2{YR@EDqMn+Re{GjPItoAfGk(qzP_q;I7MOsV5co@i1U!r;zD6W67vVe%~!4f25(M
z?k4)MFg}`m6<<85PBoW%X-uPHX)7FRgQ~nN>%Dd(a&#}9cdO&06^9wcYj-Zfe813`
z&hXt_yw`&I``E5eb&!ipcz;k05(U_!b;QK6{`W1#JDAKKqF&R2I+;BR5HU=dI03$s
zijSGNA}n>W?k)rQ(GKONmW%HUWCQD1?=_^HI;@Ry8WF>^v94=b^lE<T8%9g94|&u=
z?XJp0D~;+DGp-$qJA?Qsk?<z8;jPd&GFtfU_7yHn*`x2+RpynAZxtS{P@X)vO>krr
zWF+s!4{MqXx1@`NC(f(b-e$roIqNukElOYCmQzlSwEr{BWyf(AHNIp!(MV-6Fof=q
zCb8tu?$>G0seeRohg6{*%Zwc#HmOSsHAs5=(hOw%*JC0LoTP_rzQt{-UpHJ?44IS(
zk(Or%qp<un+XZ!ip83<$HT%M|HuPTu6Vgp%!;UGWhfE}_2a8kAFI#c=lNG=w0#C%e
z_I}mE>|jmXh%D4n(Imt!&cvZyDiZ27Aa<pO<^7;oW;<tS67$0oK1BiJ+k}rV#W?;3
zSz*wx&)o_m$v@7xG{jtQ1bdxi;-RFp0kn`|%E|b~%VPj7ysg}12G=ZB#P@S%ajW_d
zBrO{?fGl*;Rr94{Kg0H5o3}$_v0CsR+7AoSFKkK~Q5VBW>PbsAkm`hTmOw7smKLfb
zMb@`VW5UunL{9kd**|SkmtJr=-Ok{HbhipRj5;sE@k`faS_pJwYYi5m0d8&g85<rR
z9?x7xQqOqo`V(pEuvp?Sq-RTGTwgO%pd*J-TbRS+SQpnJ$wdAsvc*BRY~l>D?{z&F
zO+ZT*>?;8gQrD_E4IbI`>UTavCmqN|J4Uqe3M<EsNbpswF_wm#P49M%UgByj)zXzO
z_>kZ&^v<Ub@oRP<4$eNEQP$DmKt1$516?yQ#+$&S#y*fv*+bA0X%nNZ<(FX~*S`LE
z90Xyer@@m?l{UO{D40rRwMSEUAHk+F%iF{%e5kOo!zUza27CLNzHzkXeb~xq-Fwi)
z4N)XC$;OXuTk1410Wi#9;u~|WNf%ol>|%Xe3&O3zN&ILB9kC}W&tc_f6=sM(!$9U2
z0KZ`Q%iZ#e_CaPYmM-~8H>4w{5#F<z*el)0gs4vp<oMUQ#X^A!jc+8*Yvmx1lyoJ?
zX1o#~5i`~>pGY{^VaC6OboMH451!1-Qiy(JXP#n@#;u;%Wq5atvbxroEyC&@3#NvA
z3>h0QVTXHz9){iY&DfiTSh|PUB$j~vKn3+fpVJ}!`SZ==D=IzXTzMEaQH0Vy-$kOU
zaV%jqijjP!OFwn5SmL&;qZE|(ZM-_bk!C#_--d=f-YbS3bFOXKNn`D)R~&w7kLG_p
z?u?1?>W!vrl-#^!%dt|%?AO7KEsi4-g@1qMR*u}}a=A5b^Lq^p^16njV^<2;8eV7i
z`uLfb|NPzYS@N?OunygkgzB%NkZ&FoSz|8gF8udg#NTm_om@IHyA|1sm6l>8x$WQl
zqNQ~+*-ot`soI=EEEhP4E3wJeq1;B}FHA38*S=ux%kJXsGZAW&!?o%g`&Ls$?>AK|
zx4KRAa(W-t(1QDc4Fv`dc11{DxO#f4#|K@8a+>#n!$686gb!yVxxZ#mRLa#hTurgG
zxYM}fbf@yAH35oMr*{DmrRy3}9w$F$ugKvIud?LcvTlT5*AR8!7qPf;1@&K97%(6Z
z6ecS5<n_1gh`LDM<TuNec;U&SGp$vxb4&RZt6F+8c{2tu7MddX=lI8?1IKdWWVnO9
z!kd36FiPa)VBJXBn%gcfOlxfKmT_UU-%9CN?UTlr3v?qd*xA^lwT)0EV_YE;8LT1B
zIS-DeJQ9!)(T<|@HF(@=+LI!VQAd~}W1cVMRrb$s+-i@^Z_$Rh<a9NJvQyF1C3pKq
zbEfcsFbzIKf0I>vBiFmxK4ZdYgF|<)J(E7`&Wn{gAYRWx({?ejtp#ganKJEA?DFe7
zlY7M`yY9Nbdv5l^4z+LN%$W0^79H$v#+Dc=r*rnXlo%+bNvwn9ze-&LLESn<f0UVn
z3$ME}Ve-8nH#Qt-NU~NH=;0V=T>6VTP{0890>LhU+fJ|vo3R=-NvDYK9Gb3N1=6}0
z){x}YP{8hiy{J<hF1AOjY&3BS94$XOX7cQfx}?+Y@6KF)zKu_Ay!EloSA>heq>ovh
zM;Bk^s8w`mDH1Bb$xf9Xv8zX#dnsaP=$8w6lb_0>m6&hw=JXF|uF2X2%?L(aet$6H
za60T3xjoR3S8`O$XB|zTiCx?TnbGK%H>k1Uj3WB&Uw*h2I_W3+uYnI@84r)`W$n(*
z%E;uDuitXLTruo4nz7Vud@~>m%fe-nt$E!#9?D7nJjn+iE~NzZB~m#tO+lZe?X2A#
z0em~gyqv_rj#1_}@+2O76ChmvfwMSfw0x=cfYWmyOAm|Z-d;_7lfQMgn<tLlV@R<a
zXwu$jb*aw+)M<R<zjcasH$RJ)JKFBE<?pw8H}dxeN|3xSsMsuqCLNahP!y808nPS2
z<)3}neImcg^6*BegbWWG0UKZRx!)FaIc-4&pQcXG!u&n{tAnb8GEI{DEEiQIztVxb
zjRIN&`b)$F{WlKpqnbN9{_{9dEUk*6|M$m&FGUYDG#2|EgPl1YK9z$sJu(Wq9A7v_
zS$`J2I5#l4#Og2S!Hp8|(aMLr?wG~0KTgZaVAk7n&}y`|z2L)9Jw+_k>qS>5NX<Km
zQ>J`??Y_`+L0EP5w#be*$|7Pf#-{ux&ibC5QXiFBeOkaq?VB14MpbdBt!ju2lHMh}
z^fQxJ{%KW?^$YAdd_0Usn#R$lNLJWc3Sa+H<&MC3zujM5sxYz-#iG_{CU*SzVaSOY
zk=i-I^|0!-7^IN)2=8V<y6Dx<AEmt-$cg)a);alWM5EwO40G!SZ;Q%Iw56gXV%^45
zY<~ZGVj8e9P6GKT8|)&C%J3)oV6SIYh;!id`QSFr5_l2H0z<2hP(3Cui?9E9q|HEo
z=7E5Xp9n=4R)_DvcnZlCw2pHqeVL^cXAb(L8!2`m^+MJ(V#cCE)Gx@<&iPhe-uU|;
z5Ai)!e#>lS5<_G5A8V!$`6OO^A;c>)KnmB&$MmiHUnxD{gTN}8o0n&bW-W<Oh2e#a
z)9D9-xG=mbJTeN@@ypxT=&pX4&9s9oH12qA#@+yK+^7dx<=4(>7>*`4etw3ecl4Vp
z@F#f}fhU-Q@Z+itv1*{IsB3U~r=F`3DRW?01A171fv)3;BaU9E43+|NGc@n{bG+}M
zz(gVj9#&X@$ENcw`oL*&&Pn-PUT(>0^bZ{!3gK^x7rJbZ^zbu%GN${uqcoi%G_u@C
zoQ7YT3UlaHeE)u5H1Q}pwEX8JLo~AXxQ-t-Y@S(&bbjOHlqzsvTuhsADMb~Lc=A3!
z6;12{_Y@DGwYX3cO(@P#D%m8?(><3yP*O9u9pIroFoW+8*!ZBa5JVSPC;ycM-bw-7
z)5wO<J>wu3m2&K34WJ=nRIm6v1kvZ2!~5H=LsfHlZ`z`c@-4LbSmT8okKjkhoKYkh
zsHsMPz5+0s@c{=1$pAau&L*S}hrmPZX6R4yHbuh}))Qvna)o%`SaBAijAzYT*1iI(
zEJ`2@wx|R~-4BXgQ}EiosJy-I6YeN$tUjmMuhG%ltS7R;G2t_P7JkJw8+c*bvAoZ}
zasA{8aG=DIO81}Tc0MmyZnuD`tKA?Cj$YGtWumAka)feDo8~B`Sq@Ncp7hIu#eMDT
z>kZ$J;C<XT;}1>y`ysFS)3Ymzi&NYqJ!-BtE-!o1<#A=*sdsgY-_%|I^kINS{AsBh
zS%;B<pVT^*peu*<xvJjSp({+omlxwz_#Ium4Njin;h@i5I>3-YG!MV^j3@O=+)9aX
z!<C@v#1mjBnq0^w=ojvQ4+s8%LOd^)ujf9fLMK7IuZQCMMQdt0bI=PYaM=uJJQPb6
z4i49-%0f#l#Rk9rjAAkWE?a(rf)ajl9*^ul_pDj1riRI!7_`~14$<!XzLw(Vt{8qn
zL4w|`ygt}dh(P%+lrVYr#HHYDyz+JDLs5hAuy)w@>rQt?*~W1ANfvj;U#mtbq>Gg=
zYbGaet}J=Ef}7~K+2R?bs3EN3>xo8_r16{41hv)5x#4?4(5g)?CZ1?T@$2eUHpzUg
z?;TOIGJk3F^c4Qo0a$xh%ygH`+?`vJ{Fir?MQc&fOI%dEHT{Afd?K^WSKD^I>8T_+
z{u_(JUc}&dgGGL3F=}ZW9^N$7D{uoWas|Iy{}B$^b9QNH(vV;4<qn#Njm-*g1TPj!
zye*3U9KG$vx@O^_M;(vR=WnshovlcuB!aNp3(u_PNqIC-nLB6Nh>cQ$f-Vq!n;ldt
zOX4Fz^rjkQCOw{oqMxCt8h_BwjCg(zC!N1nx)|?V`)u23f}0Xffy<-_<RBN%jx|+{
zZMze`hb*5%RVS4P@5+7R?N>yVy!pe)XK=ML5dAo?eTK0xCwaC4yt(^l*_e7Hde3E)
z@j>{^CX89SsC&*3(48e92ZSpeM~cwFkSa5$$;{JzoAY(GiEZ@0-J6qfbBR^sKXh>3
z&*?^Jg-vs>=T`It1NMM;>=HE!oBA#wxOBS{!icOh+mOFvASl3~#m=^Q%0y2A#Zl#E
z$v$XNQ3d~G)Lg7^mi;pAZz0UcTW7(|JVZpr&bHMI-p4}pzR#f-4zdk~(fZ~@g%DAv
z=0pV&Q9tHH`4drovr+5dSqwyLa!yn{5oI+esure4Qc}_me1ZxSZwNy%jO0>TQzJi!
zkMSt|nNbuU>Z<NZbY+q6W`rgl^iA~a=#z}fWUh{ILV@C)Q1Q&m+nabc-+*{|93^PJ
z4=>4B8Q6j&$2|*^aVjh;d-R^dWLOB<sLXTf$Wl3?!X<#JG{?Ufj_6=y`@}~A(*wA6
z)MmP7?AuQPfopq+Zkc{T$4VkR^;GwqW--i^cz6<}kYbo{2#(-SJ>hw&4_MJ6g?-yL
z!x+?c^r){1NQ}e7s0?&cI#qG^?%f11*Ii~7HS&G6Bb##zP9;1$6^2?azxNeBn^3`w
zcHhr%D5$i?c|~t_^~qlG7&TY3V0M@cdd~EoojQzv0?wFtVg-@Fl7IQW?;3uF7C3yG
zYt2$Q6WbZ8qlMG9o&~sH^a{>&-m`qz(x&pdd;G=9lA|VncUO7l2@By5+s-b%KI*zE
zg(WKR-jMXy!S-{{Tl+G`Za|;GS1@$z=^T9SJfB^l3}^zs^LYoeMbTQKdFsV=yrt9s
zjNX`?QYemf77+B4{#-5k69w{r`u?8(eBpV(=9y%EVxYxgeleI|J?D3f`CSsN1@nu+
z|G`lzF0Tfi;pm|eN&lpudP{|KTKn>m{}&N5rT*U?;mE~JeW$a0doDCWk27YE;i$u!
zvvMBZe<U1GKZRxa+BR<SmL(v8e@P0c*t^fRGZG2haGyPg&lH_003XesIdbEX9REYT
zp|u_nI&cbDG<)6$kB7>aFkJ8Om+d8<wD#d*H$i_LdUBb}uO2sB9gTPtcP8Rr{R*ue
zL6SUa!JMHbnY?k4hu#=yB5{bjCs%h`l<7Z^0@6?%@ggNbklH9E0p%-EAL?nOxgg9+
z3Ls6^5d8>7{UB+LPgWvnf=)v8U!8k{ko<;!re0Quo1UkCvtMiDU``4j<8)oO>VMs|
z80pHQXLwPn%#MJ<E1<{0fB%vzc-!1n-_wcw#2eghTpsjuMC}nXQKFw&@2-rxj3paJ
z&iSu~kk485#x&T@)<h@dMbKy}t#tTPy=P`1^Lr2y-_ZNKnua0M669!9UD>i7V5_M|
z8J!vCpkTT$1W7z;NKU0lAe8Yi8ug;jVeAu&+(JxqDc<7a54x@Le%6H2C35pJdbg37
zN7IrSSE6$!*?#|MQDh3d<49SE#@2psMUGct8oi^`B?wt#{9#`6>TY-32@7hZUi>kl
z2Dz!sXh_m4%<4*Fh)-HUV)pID=Qw`7gf||Im!Ljpt#lYOE4)W1>3r}k2N#B|?|cJH
zv#;xJT7+yW*jv4kp&bHwNp{ZNpO3U06W*S6=f=oGt{^*;`S*Kx!lNX#Vj>f^p5}h<
z*T<T!uTc3#1jzc60xZ+qXRdj1E0YQ$Xph=N(Fyvfk^Nn$0GDE+&97x9L`vJ=Ls9%C
z%?wgu>q<IIB&};x*cY5^Sr~wuUf-5{?x({TZI2!($YL3Z>f@*thS$z9*S0o;O-yDz
zcsx_DeQFh+9&vdFq|2nK;^WX`+{_ZuQJrWcDaS&T?%xG0I@(lR&Okl)A+PnpCdc*c
z)JElT@^O)*m2ztaKkH%_4zivad0A>1oX2IkBv!(3*QgciPVXc)_p1@L1-`YTca}uI
zDK!Fb@=cDWM`{Dd&t7uLZ%`q~lTW-|rr~K}+TJi}1NgPaA>Jwr@mcz|o(>RsGVzA2
z-Y3smD4~Z;1)62N;*Po1`p$F;n`4E&-!0SNwM_+Ij%aj;np~UOzUgES(iA|TKINIH
zwyK3Y@kH_N5Z~pq)bB{2`Dha34qtNOG6a_@^5Rd?+1>B$mp^SX7$M4ILPs}94@*XL
zHfL3D10u(fHb!ZuxZ}r}CYBsrFQ?yfwiYET?T0xc)9;cuR=cU7>EtohNe+t>Gi`}@
z(D+?hW6Hc|cyBMd(W`kyLJt;YaYwz+qxM-LO$O5s%F{H8<RhZr?0KHNU3ZBEjNCpJ
zJma3btG22g?n2(P5U5*X%FC~A*KN{*M+T&t_8}&CeWZElaPX?ulbaN7oV}C*mr9Ae
zv`X)S@Q#iuabb~DjeV-%l3s?_t?j7SGV!mvSFZ~6>aGh9{BRMb3&jktSi4fcWumD`
zi-pd6&!FPk?YakRcR`;|AV{*Ly?abrmnnod=F)3abSSWdCwNkY#kMBqR2xFZ%{Vww
zMMHjf6Ho(_t2+AojU@@1WC=k*!S~LWx54l9m*-*H8DHNw#_+4$;t#VN(Fbw^TTy<X
zRpR$GP+uIfH81B+q21Lz4VMPpp#TcDI_!d}iVe;@g%toBKSJ3!MaDAX-WTy{DlD?G
zu~`A(R~;9?jnli{F!lBq*QdM?J|^(UgT6MWHvn20-|bZ@IbOlCw(m7E>f+fZZpD^C
z3<{bLWtIr0a)7dxvcVtX>SeUW`EpTyJT(kbtvhoUgBl4LXVMQU#m*)g%CHHh%7cM~
zycjus7(eA%Zqd6~m=3Q}y1aYzbud3@Uc-x8?2pZxp<5=ilwMR1=h=mqo8LFOQ;7B>
zH*W}1I;l5P-Z?1%lrh23pnoX2SB6hVMf@sOCo)idVhf!P@T;me!fii$3F~E;=GuD+
z-tH%|4i%r=RCkofMYDK&Gi4(CSn32jOwW7hvZm(Rz(dPojxcZhLm%cdPQOmSd%Iot
z!g{cetL=hWc<9N8jHic|HI8h*+>r&bcyL-D6#h#rWVt@NzM#p7u5MDqLqAwd9gr^M
ziaD}m<K#3w{XcouUvH-Ln%`l-Y+oX#wta_~`e9J>$xSXE9?R>xgSv9BJJJak8k}7-
z(ACv745eJVy7Wq*)Oln?d)Rcc@p#@?{4$krs|N?Zj}CTQ2?z=Gs1ohzzXvP~bMez#
z7ZyPljIx|t9Jt+N^Fx8b_G2q0C6BnHx1AuIaq)T!_n&12Rf58=Rx)DMA&hv=ihNBE
zP!30xeHnfwOk|~rf9Z=Tl6R7IkJbWZHTezlC9l566K28Mx#X|!fE*dN5fpl@a`N*h
zr{Zcqe5_&l47DpE{`qI!k;Qjn*c0WZm?MdN<j&IbDP_mG?%a`-6*_`QN+52j&i&21
zOm>=>`hkw~DeKOe8co3zu&u!X`(%?R(foe1*Jy=AMn=Z5tV1Ptb_>H~t3E<+f%7=I
zP59izO25`(<#5?p(Nm3oC$!-s)%Svd2=$@w-j=o7Ul$i|Ffw`}MK7W##S&gw$$O<X
zeTCX~bk{%=f7*<8f0g*?y}qEhs!pw)M6-=^1U4Od*x=&reQU*E3Gms{{EgU{c3;CY
zDq{47{7k;(M^jjCI5ldmgofWhV>WSE_?7Nfx$0Jt+ZhSKh<kAzJMi;sS1+&eN0~Jj
z_VglKD4k%TYk#_FU<v0A;)q5b>2$nhB4InY2E8|g(S#AI&Rg43wwRl*`}^l_Ss5QQ
zeX%ih-&`iez2W0wc0qA#Som@G-BE?M6h6<*g58JxVO>L^->ub1?k#+hOf1#psAUrP
z(_y~2ljqq75f-DDj#!NPEYNH1$vp^POGP*OAW)=QSuXvwI#!dw2`dBH2k`*4YDmPl
zK0h=xRTR&I?Rz`8`dQ_3hns9r#}U-b{!EPkzz7fa(Z@C;+i5m_(N5h6FrlX??SiYN
z;QWG{xFZ^a;8r~zG?(r{-g(puIL>xs9B?lm4^jsg--M;>3~uZ{lRI079?qhe5N`cW
zy0feea-l%JdK;~1WJ%-$K<@m$eR@lxFcF~Qc68EKKX6whO5~p)5)PueN$2Jy=n@G{
z?8sYrIOdf${oF+LaT9v+70!&7X|Stda>t%p-2b6Eh8~GUq2JS$)};qLLE4HYC7Ext
zqv<063J*@AFby{Vk51uT^_XeK#35-<)K%I=9P#hnR(zUt5NICwDoy4)O#$%w?f3Mq
ze-^cePB1@S1ZS506GyP&pFc|NR<lxU8G|*~u-)Vc{%WxL>Zud$#w)J<V{O^8p;s^d
zO6A?2tG!iIh4y@?yMi5GQ;s43EEJsHmaJyLNZW)Tz>fn1ThjUq&6x2NjC$Yt#%_-c
zbbqZJ*%ztaPbyO@OT36wZ1i-;wUnm-5A_#1iDhOuWS^x^yZ)_DDjWa6D);~wU7Aas
zr&mgvNyo($1=ZX`P{#w@5ZRm)_<fpH<jUgwQ=CwR-+fL%j_QCtojmZFCp?f(967ca
z+D{HcXJU$MYGo9CY%rD>1#O@~ebaIn$|{OmjcHPwWaz~%08uey`BQvV3|QNm-gS#l
zruV^T(;FQ-fTEfgAw#iP`TUVrss}w$%{{zZtjBISBn#om!s6!B!!vx8EqtK^H0BvP
z@Kd&mPk%U8GnolmQq74D=7aYG=%1U#Y>zbL1khl9<RS|-dFooWHhtm29+t+f7f9U?
zdvh|5qullzRc(u5Nkbv?M&}2qhrknKNFpKo$;_rCJ#Y)|whD%B8{xv--#}+(fE)$0
zH)lTEW`aTQgCuH)Kskpf9YmVPn-5Z*0FoyX?64B0cU4hPH6G+jRbx58qD^f>^vEXH
zOO)uPNbX6=7a$we1@)F(C@nI*dWmtOdl~0&5j{f6Wl5w_1N=t8qFgohk6$J`aJLX@
zL_dGg?mmAyL0kPdvhr^cCkf#e!5HIqPZ7H{dIa;6trO3UZvhuytp5OlgnA%Q?QbZW
zkPwt}f8Y4K(Oed?9>A@q-uv1cL(!asP<?@|jlTR65%d4fBQTG^JOc9w%p)+5z&rx;
z2+SiekH9<v^9al%@V|z@1Zf#N2-6@LPaIjbZU20jM_?X-c?9MWm`7k9fq4Yx5tv6{
z9)WoT<`I}jU><@0R|qiKE@Q`S?o5;Cez2iOSLVZiivU%ma4YxeBg{L`p)9+!jdo;c
Hk^KJyr@mf2

literal 0
HcmV?d00001

diff --git a/assets/images/apple_pay_round_dark.svg b/assets/images/apple_pay_round_dark.svg
new file mode 100644
index 000000000..82443bfb4
--- /dev/null
+++ b/assets/images/apple_pay_round_dark.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
+
+<defs>
+</defs>
+    <g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
+	<path d="M 24.144 34.985 c -0.77 0.912 -2.003 1.631 -3.236 1.528 c -0.154 -1.233 0.449 -2.542 1.156 -3.351 c 0.77 -0.937 2.119 -1.605 3.21 -1.656 C 25.402 32.789 24.902 34.047 24.144 34.985 M 25.261 36.757 c -1.785 -0.103 -3.313 1.014 -4.16 1.014 c -0.86 0 -2.157 -0.963 -3.57 -0.937 c -1.836 0.026 -3.544 1.066 -4.481 2.722 c -1.926 3.313 -0.501 8.218 1.361 10.914 c 0.912 1.335 2.003 2.799 3.441 2.748 c 1.361 -0.051 1.9 -0.886 3.544 -0.886 c 1.656 0 2.131 0.886 3.57 0.86 c 1.489 -0.026 2.427 -1.335 3.338 -2.671 c 1.04 -1.515 1.464 -2.992 1.489 -3.069 c -0.026 -0.026 -2.876 -1.117 -2.902 -4.404 c -0.026 -2.748 2.247 -4.057 2.35 -4.134 C 27.958 37.014 25.954 36.808 25.261 36.757 M 35.572 33.033 v 20.018 h 3.107 v -6.844 h 4.301 c 3.929 0 6.69 -2.696 6.69 -6.6 s -2.709 -6.574 -6.587 -6.574 H 35.572 L 35.572 33.033 z M 38.679 35.652 h 3.582 c 2.696 0 4.237 1.438 4.237 3.968 c 0 2.529 -1.541 3.98 -4.25 3.98 h -3.57 V 35.652 z M 55.345 53.205 c 1.952 0 3.762 -0.989 4.584 -2.555 h 0.064 v 2.401 h 2.876 v -9.964 c 0 -2.889 -2.311 -4.751 -5.868 -4.751 c -3.3 0 -5.739 1.887 -5.829 4.481 h 2.799 c 0.231 -1.233 1.374 -2.042 2.94 -2.042 c 1.9 0 2.966 0.886 2.966 2.517 v 1.104 L 56 44.628 c -3.608 0.218 -5.56 1.695 -5.56 4.263 C 50.44 51.484 52.456 53.205 55.345 53.205 z M 56.18 50.829 c -1.656 0 -2.709 -0.796 -2.709 -2.016 c 0 -1.258 1.014 -1.99 2.953 -2.106 l 3.454 -0.218 v 1.13 C 59.878 49.494 58.286 50.829 56.18 50.829 z M 66.709 58.495 c 3.03 0 4.455 -1.156 5.701 -4.661 l 5.457 -15.305 h -3.159 l -3.659 11.826 h -0.064 l -3.659 -11.826 h -3.249 l 5.264 14.573 l -0.282 0.886 c -0.475 1.502 -1.245 2.08 -2.619 2.08 c -0.244 0 -0.719 -0.026 -0.912 -0.051 v 2.401 C 65.707 58.469 66.478 58.495 66.709 58.495 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: white; fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+        <path d="M 45 90 C 20.187 90 0 69.813 0 45 C 0 20.187 20.187 0 45 0 c 24.813 0 45 20.187 45 45 C 90 69.813 69.813 90 45 90 z M 45 3 C 21.841 3 3 21.841 3 45 c 0 23.159 18.841 42 42 42 c 23.159 0 42 -18.841 42 -42 C 87 21.841 68.159 3 45 3 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: white; fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+</g>
+</svg>
\ No newline at end of file
diff --git a/assets/images/apple_pay_round_light.svg b/assets/images/apple_pay_round_light.svg
new file mode 100644
index 000000000..2beb1248f
--- /dev/null
+++ b/assets/images/apple_pay_round_light.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
+
+<defs>
+</defs>
+<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
+	<path d="M 24.144 34.985 c -0.77 0.912 -2.003 1.631 -3.236 1.528 c -0.154 -1.233 0.449 -2.542 1.156 -3.351 c 0.77 -0.937 2.119 -1.605 3.21 -1.656 C 25.402 32.789 24.902 34.047 24.144 34.985 M 25.261 36.757 c -1.785 -0.103 -3.313 1.014 -4.16 1.014 c -0.86 0 -2.157 -0.963 -3.57 -0.937 c -1.836 0.026 -3.544 1.066 -4.481 2.722 c -1.926 3.313 -0.501 8.218 1.361 10.914 c 0.912 1.335 2.003 2.799 3.441 2.748 c 1.361 -0.051 1.9 -0.886 3.544 -0.886 c 1.656 0 2.131 0.886 3.57 0.86 c 1.489 -0.026 2.427 -1.335 3.338 -2.671 c 1.04 -1.515 1.464 -2.992 1.489 -3.069 c -0.026 -0.026 -2.876 -1.117 -2.902 -4.404 c -0.026 -2.748 2.247 -4.057 2.35 -4.134 C 27.958 37.014 25.954 36.808 25.261 36.757 M 35.572 33.033 v 20.018 h 3.107 v -6.844 h 4.301 c 3.929 0 6.69 -2.696 6.69 -6.6 s -2.709 -6.574 -6.587 -6.574 H 35.572 L 35.572 33.033 z M 38.679 35.652 h 3.582 c 2.696 0 4.237 1.438 4.237 3.968 c 0 2.529 -1.541 3.98 -4.25 3.98 h -3.57 V 35.652 z M 55.345 53.205 c 1.952 0 3.762 -0.989 4.584 -2.555 h 0.064 v 2.401 h 2.876 v -9.964 c 0 -2.889 -2.311 -4.751 -5.868 -4.751 c -3.3 0 -5.739 1.887 -5.829 4.481 h 2.799 c 0.231 -1.233 1.374 -2.042 2.94 -2.042 c 1.9 0 2.966 0.886 2.966 2.517 v 1.104 L 56 44.628 c -3.608 0.218 -5.56 1.695 -5.56 4.263 C 50.44 51.484 52.456 53.205 55.345 53.205 z M 56.18 50.829 c -1.656 0 -2.709 -0.796 -2.709 -2.016 c 0 -1.258 1.014 -1.99 2.953 -2.106 l 3.454 -0.218 v 1.13 C 59.878 49.494 58.286 50.829 56.18 50.829 z M 66.709 58.495 c 3.03 0 4.455 -1.156 5.701 -4.661 l 5.457 -15.305 h -3.159 l -3.659 11.826 h -0.064 l -3.659 -11.826 h -3.249 l 5.264 14.573 l -0.282 0.886 c -0.475 1.502 -1.245 2.08 -2.619 2.08 c -0.244 0 -0.719 -0.026 -0.912 -0.051 v 2.401 C 65.707 58.469 66.478 58.495 66.709 58.495 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+	<path d="M 45 90 C 20.187 90 0 69.813 0 45 C 0 20.187 20.187 0 45 0 c 24.813 0 45 20.187 45 45 C 90 69.813 69.813 90 45 90 z M 45 3 C 21.841 3 3 21.841 3 45 c 0 23.159 18.841 42 42 42 c 23.159 0 42 -18.841 42 -42 C 87 21.841 68.159 3 45 3 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+</g>
+</svg>
\ No newline at end of file
diff --git a/assets/images/bank.png b/assets/images/bank.png
new file mode 100644
index 0000000000000000000000000000000000000000..9dc68147aad18488da6007bca88b92ba13697559
GIT binary patch
literal 1323
zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrVEN?f;uumf=j~kE^`fC7ZTBNI
zG^94Nh;~MO6uz<|Tsk>DadpBM^%V=m!fHy&yw<#7RXXCQ+be(3>q^iAr-jdw^jeip
z8d~3+kT}P-*e-4EOw-quljh!;V4J@7_rCWtZ>FEyuwG=cwTi9I%T61)Q~%k7p9^{(
zSBafsvbvXhQlHl?^ODII>|fsf*SKWAbkF>&$4WitdsOi#CrR2Xb6idoeVop6P`_3R
z$k``WuKxLJb)0j)$1kgXX>OVC{Y&~Ibbi$yzaR6&Hm-7Rt@a+iZr9_-t}Ajl_O5pp
zXp)L=S70&S$LGkARU_LZaOH;;i{grpr5sKHk6#P4EI?MMUL&wbYW)kx13wnv#T5me
z%X2Q@=~sRG{{Q#(Gym3n{Hi)H>E3F~O6N<aJ@aD(wyEyD_Vv*F<UdcEKg7K}8pl<$
z-tLyv!>7Nv-%Kgte0-SY;ie_KSF`Us_ek%~(udo=9(dmBx!=>u;LdwS?IMNh8&BTu
ze04;-)l+}XEk>Sm-K_cMt0(`{_3_GP{&4o(w4;A?y{>c4V4M3-s3Fstp~?6$kHBn6
z#*VXVv>9%<a#pv!maIz3KX`lps>yYlK2^Kd>m?ZQiSMzEpIfr&>Fy^YOy^ka?*DAx
z-0pj?E@JMVKTPrJMkbuRX0JMbCb9S$ZV}_%r&Zhh#ab=nmExbxZ!Hfl|J1T@cFGBt
zW_uOen_DY9Uj7ggHrXn$%=^#c&+8SJKL2!i$@A!U!UiT$ypz)HpI-g<U#te0w!mQZ
zhlVB2lg>SP&b{vG#5z0OmkXBMW%l;zcRN3K|K#}wFLzm&hF+S;_-{X>t<*$0k)LIq
zx2M=YyX$@p$hRxJ^u>L~b6Iimn_HXYOqcZaF2C}=`o|%qxwd5&79U%ato;7lkF`^;
zHZT8@v18J{TS*zeL_Ta;QvIpI?NYk#=j}XpvKJOBwnv?*S^ac}vhMM{Uj0&w`+DbO
zRz5E;+*a^Lv+9aOY0i`DP9IBdy?=D`(8iZ(g0@*DR%Ss}HaXX2j^B&6Fx#sJ5!v-`
z&FhM)nE8FZ0u2^cvqYZpJaBiPe2C>hf1g?_XM?<~FPAWbJy1f8p{~S4(}&^Di;SQd
z3_mVjTw=iZVew+mM5aNY;l^(^!S823m*>1JG_lg#;_7pYcTIP1<Mxh)$K@<y1<Z3<
zuOHocXyg2E7bR?0<;zN2-YEL(89hUHbKzs{FDndR?YN@Wlm1yRZ1<-d8I{lP-_iI~
z2MWWOtj&j9kIx3Gczwg;){Gy!<!1dmRxmlaO6F(TNAXW_|Guoa_&OrRzfN5L)))Tl
zf6anlGEVgEdHVaB%(48Z*;iwy@m_pv@aEj^(B-_{_2<fYwtqgq{FD2Xt!sl`3PKao
zf|(`h?^>3ewyisT{DOw5hn)QMl5|rBb+-!=&e>NVM3^#!8#r8Knqjk_b$MN@^z>DX
z7IsZ-5>cz!++TMe5NY!5xp1X<$ISKrx9c(~YW!!c{2hJkt)%`Xknx_belF{r5}E)9
CLv&mK

literal 0
HcmV?d00001

diff --git a/assets/images/bank_dark.svg b/assets/images/bank_dark.svg
new file mode 100644
index 000000000..670120796
--- /dev/null
+++ b/assets/images/bank_dark.svg
@@ -0,0 +1,8 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
+
+<defs>
+</defs>
+    <g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: white; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
+	<path d="M 84.668 38.004 v -6.27 H 90 V 20 L 45 3.034 L 0 20 v 11.734 h 5.332 v 6.27 h 4.818 v 30.892 H 5.332 v 6.271 H 0 v 11.8 h 90 v -11.8 h -5.332 v -6.271 H 79.85 V 38.004 H 84.668 z M 81.668 35.004 H 66.332 v -3.27 h 15.336 V 35.004 z M 63.332 68.896 v 6.271 h -7.664 v -6.271 H 50.85 V 38.004 h 4.818 v -6.27 h 7.664 v 6.27 h 4.818 v 30.892 H 63.332 z M 26.668 38.004 v -6.27 h 7.664 v 6.27 h 4.818 v 30.892 h -4.818 v 6.271 h -7.664 v -6.271 H 21.85 V 38.004 H 26.668 z M 42.15 68.896 V 38.004 h 5.7 v 30.892 H 42.15 z M 37.332 35.004 v -3.27 h 15.336 v 3.27 H 37.332 z M 37.332 71.896 h 15.336 v 3.271 H 37.332 V 71.896 z M 3 22.075 L 45 6.24 l 42 15.835 v 6.659 H 3 V 22.075 z M 8.332 31.734 h 15.336 v 3.27 H 8.332 V 31.734 z M 13.15 38.004 h 5.7 v 30.892 h -5.7 V 38.004 z M 8.332 71.896 h 15.336 v 3.271 H 8.332 V 71.896 z M 87 83.966 H 3 v -5.8 h 84 V 83.966 z M 81.668 75.166 H 66.332 v -3.271 h 15.336 V 75.166 z M 76.85 68.896 H 71.15 V 38.004 h 5.699 V 68.896 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: white; fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+</g>
+</svg>
\ No newline at end of file
diff --git a/assets/images/bank_light.svg b/assets/images/bank_light.svg
new file mode 100644
index 000000000..804716289
--- /dev/null
+++ b/assets/images/bank_light.svg
@@ -0,0 +1,8 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
+
+<defs>
+</defs>
+	<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: black; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
+	<path d="M 84.668 38.004 v -6.27 H 90 V 20 L 45 3.034 L 0 20 v 11.734 h 5.332 v 6.27 h 4.818 v 30.892 H 5.332 v 6.271 H 0 v 11.8 h 90 v -11.8 h -5.332 v -6.271 H 79.85 V 38.004 H 84.668 z M 81.668 35.004 H 66.332 v -3.27 h 15.336 V 35.004 z M 63.332 68.896 v 6.271 h -7.664 v -6.271 H 50.85 V 38.004 h 4.818 v -6.27 h 7.664 v 6.27 h 4.818 v 30.892 H 63.332 z M 26.668 38.004 v -6.27 h 7.664 v 6.27 h 4.818 v 30.892 h -4.818 v 6.271 h -7.664 v -6.271 H 21.85 V 38.004 H 26.668 z M 42.15 68.896 V 38.004 h 5.7 v 30.892 H 42.15 z M 37.332 35.004 v -3.27 h 15.336 v 3.27 H 37.332 z M 37.332 71.896 h 15.336 v 3.271 H 37.332 V 71.896 z M 3 22.075 L 45 6.24 l 42 15.835 v 6.659 H 3 V 22.075 z M 8.332 31.734 h 15.336 v 3.27 H 8.332 V 31.734 z M 13.15 38.004 h 5.7 v 30.892 h -5.7 V 38.004 z M 8.332 71.896 h 15.336 v 3.271 H 8.332 V 71.896 z M 87 83.966 H 3 v -5.8 h 84 V 83.966 z M 81.668 75.166 H 66.332 v -3.271 h 15.336 V 75.166 z M 76.85 68.896 H 71.15 V 38.004 h 5.699 V 68.896 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: black; fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+</g>
+</svg>
\ No newline at end of file
diff --git a/assets/images/buy_sell.png b/assets/images/buy_sell.png
new file mode 100644
index 0000000000000000000000000000000000000000..0fbffe56fb0e74a762e0b48e79c5930d5c116498
GIT binary patch
literal 9931
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

literal 0
HcmV?d00001

diff --git a/assets/images/card.svg b/assets/images/card.svg
new file mode 100644
index 000000000..95530cdc9
--- /dev/null
+++ b/assets/images/card.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="iso-8859-1"?><!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" width="100px" height="100px"><path style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:10;" d="M43,40H7c-2.209,0-4-1.791-4-4V14c0-2.209,1.791-4,4-4h36c2.209,0,4,1.791,4,4v22C47,38.209,45.209,40,43,40z"/><rect x="3" y="16" width="44" height="5"/><line style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:10;" x1="9" y1="25" x2="25" y2="25"/></svg>
\ No newline at end of file
diff --git a/assets/images/card_dark.svg b/assets/images/card_dark.svg
new file mode 100644
index 000000000..2e5bcf986
--- /dev/null
+++ b/assets/images/card_dark.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" width="100px" height="100px">
+    <path style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-miterlimit:10;" d="M43,40H7c-2.209,0-4-1.791-4-4V14c0-2.209,1.791-4,4-4h36c2.209,0,4,1.791,4,4v22C47,38.209,45.209,40,43,40z"/>
+    <rect x="3" y="16" width="44" height="5" style="fill:white;stroke:#ffffff;stroke-width:2;"/>
+    <line style="fill:none;stroke:#ffffff;stroke-width:2;stroke-miterlimit:10;" x1="9" y1="25" x2="25" y2="25"/>
+</svg>
\ No newline at end of file
diff --git a/assets/images/dollar_coin.svg b/assets/images/dollar_coin.svg
new file mode 100644
index 000000000..22218f332
--- /dev/null
+++ b/assets/images/dollar_coin.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg fill="#000000" width="800px" height="800px" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+
<g id="Outline">
+
<g data-name="Outline" id="Outline-2">
+
<path d="M39,36.852a6.8,6.8,0,0,0-6.793-6.793h-.319A3.716,3.716,0,1,1,35.6,26.344a1,1,0,0,0,2,0,5.725,5.725,0,0,0-4.561-5.6V18.09a1,1,0,0,0-2,0V20.7a5.712,5.712,0,0,0,.846,11.361h.319a4.793,4.793,0,1,1-4.793,4.793,1,1,0,0,0-2,0A6.8,6.8,0,0,0,31.451,43.6v2.947a1,1,0,0,0,2,0v-3c0-.008,0-.014,0-.021A6.8,6.8,0,0,0,39,36.852Z"/>
+
<path d="M32,2A30,30,0,1,0,62,32,30.034,30.034,0,0,0,32,2Zm0,58A28,28,0,1,1,60,32,28.032,28.032,0,0,1,32,60Z"/>
+
<path d="M49.655,16.793a3.172,3.172,0,1,0-3.172,3.172,3.137,3.137,0,0,0,1.263-.266A19.994,19.994,0,0,1,22.692,49.707a1,1,0,0,0-.933,1.769,21.986,21.986,0,0,0,27.47-33.124A3.141,3.141,0,0,0,49.655,16.793Zm-4.344,0a1.172,1.172,0,1,1,1.172,1.172A1.172,1.172,0,0,1,45.311,16.793Z"/>
+
<path d="M16.793,44.035a3.164,3.164,0,0,0-.692.081A19.779,19.779,0,0,1,12,32,20.023,20.023,0,0,1,32,12a19.811,19.811,0,0,1,8.463,1.874,1,1,0,0,0,.848-1.812A21.989,21.989,0,0,0,14.39,45.16a3.141,3.141,0,0,0-.769,2.047,3.172,3.172,0,1,0,3.172-3.172Zm0,4.344a1.172,1.172,0,1,1,1.172-1.172A1.172,1.172,0,0,1,16.793,48.379Z"/>
+
</g>
+
</g>
+
</svg>
\ No newline at end of file
diff --git a/assets/images/google_pay_icon.png b/assets/images/google_pay_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..a3ca38311cf31e5304b3fa2eb541d7e59dfe2863
GIT binary patch
literal 12336
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
O_efn=ty;x4^8W!pu>c<c

literal 0
HcmV?d00001

diff --git a/assets/images/meld_logo.svg b/assets/images/meld_logo.svg
new file mode 100644
index 000000000..1d9211d64
--- /dev/null
+++ b/assets/images/meld_logo.svg
@@ -0,0 +1,30 @@
+<svg width="40" height="42" viewBox="0 0 40 42" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path opacity="0.7" d="M19.9526 41.9076L7.3877 34.655V26.1226L19.9526 33.3751V41.9076Z" fill="url(#paint0_linear_2113_32117)"/>
+<path opacity="0.7" d="M19.9521 41.9076L32.5171 34.655V26.1226L19.9521 33.3751V41.9076Z" fill="url(#paint1_linear_2113_32117)"/>
+<path opacity="0.7" d="M39.9095 7.34521V21.8562L32.5166 26.1225V11.6114L39.9095 7.34521Z" fill="url(#paint2_linear_2113_32117)"/>
+<path d="M39.9099 7.34536L27.345 0.0927734L19.9521 4.359L32.5171 11.6116L39.9099 7.34536Z" fill="url(#paint3_linear_2113_32117)"/>
+<path d="M0 7.34536L12.5649 0.0927734L19.9519 4.359L7.387 11.6116L0 7.34536Z" fill="#F969D3"/>
+<path opacity="0.7" d="M0 7.34521V21.8562L7.387 26.1225V11.6114L0 7.34521Z" fill="url(#paint4_linear_2113_32117)"/>
+<defs>
+<linearGradient id="paint0_linear_2113_32117" x1="18.6099" y1="41.8335" x2="7.73529" y2="8.31842" gradientUnits="userSpaceOnUse">
+<stop stop-color="#E98ADA"/>
+<stop offset="1" stop-color="#7E4DBD"/>
+</linearGradient>
+<linearGradient id="paint1_linear_2113_32117" x1="26.2346" y1="26.1226" x2="26.2346" y2="41.9076" gradientUnits="userSpaceOnUse">
+<stop stop-color="#719DED"/>
+<stop offset="1" stop-color="#2545BE"/>
+</linearGradient>
+<linearGradient id="paint2_linear_2113_32117" x1="36.213" y1="7.34521" x2="36.213" y2="26.1225" gradientUnits="userSpaceOnUse">
+<stop stop-color="#93EBFF"/>
+<stop offset="1" stop-color="#197DDB"/>
+</linearGradient>
+<linearGradient id="paint3_linear_2113_32117" x1="29.931" y1="0.0927734" x2="38.2156" y2="14.8448" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F969D3"/>
+<stop offset="1" stop-color="#4F51C0"/>
+</linearGradient>
+<linearGradient id="paint4_linear_2113_32117" x1="18.1251" y1="44.2539" x2="-7.06792" y2="15.2763" gradientUnits="userSpaceOnUse">
+<stop stop-color="#E98ADA"/>
+<stop offset="1" stop-color="#7E4DBD"/>
+</linearGradient>
+</defs>
+</svg>
diff --git a/assets/images/revolut.png b/assets/images/revolut.png
new file mode 100644
index 0000000000000000000000000000000000000000..bbe342592660209396ef45a6a119154437f93259
GIT binary patch
literal 11588
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
Hk754@^tnqa

literal 0
HcmV?d00001

diff --git a/assets/images/skrill.svg b/assets/images/skrill.svg
new file mode 100644
index 000000000..b264b57eb
--- /dev/null
+++ b/assets/images/skrill.svg
@@ -0,0 +1,15 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
+
+<defs>
+</defs>
+<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
+	<circle cx="45" cy="45" r="45" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(127,33,99); fill-rule: nonzero; opacity: 1;" transform="  matrix(1 0 0 1 0 0) "/>
+	<polygon points="69.59,36.9 69.59,54.86 74.5,54.86 74.5,36.02 " style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(249,249,249); fill-rule: nonzero; opacity: 1;" transform="  matrix(1 0 0 1 0 0) "/>
+	<polygon points="62.42,36.9 67.33,36.02 67.33,54.87 62.42,54.87 " style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(249,249,249); fill-rule: nonzero; opacity: 1;" transform="  matrix(1 0 0 1 0 0) "/>
+	<rect x="55.43" y="41.08" rx="0" ry="0" width="4.91" height="13.78" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(249,249,249); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) "/>
+	<path d="M 57.879 39.76 c 1.332 0 2.425 -1.082 2.425 -2.415 s -1.082 -2.425 -2.425 -2.425 c -1.332 0 -2.415 1.082 -2.415 2.425 C 55.465 38.677 56.547 39.76 57.879 39.76 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(249,249,249); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+	<path d="M 52.665 40.884 c -4.538 0.146 -6.838 2.186 -6.838 6.234 v 7.754 h 4.954 v -6.328 c 0 -2.425 0.312 -3.466 3.195 -3.559 v -4.038 C 53.477 40.853 52.665 40.884 52.665 40.884 L 52.665 40.884 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(249,249,249); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+	<path d="M 39.344 41.071 c -0.104 0.271 -0.895 2.498 -2.8 4.798 v -9.845 l -5.068 0.999 v 17.838 h 5.068 v -5.516 c 1.467 2.206 2.196 5.516 2.196 5.516 h 6.068 c -0.604 -2.498 -3.226 -7.098 -3.226 -7.098 c 2.352 -2.987 3.393 -6.172 3.559 -6.702 h -5.797 L 39.344 41.071 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(249,249,249); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+	<path d="M 22.973 43.028 c -0.624 -0.042 -2.061 -0.135 -2.061 -1.426 c 0 -1.561 2.071 -1.561 2.841 -1.561 c 1.363 0 3.133 0.406 4.392 0.781 c 0 0 0.708 0.25 1.301 0.5 l 0.052 0.01 v -4.267 l -0.073 -0.021 c -1.488 -0.52 -3.216 -1.02 -6.432 -1.02 c -5.537 0 -7.493 3.226 -7.493 5.984 c 0 1.592 0.687 5.339 7.025 5.776 c 0.541 0.031 1.967 0.114 1.967 1.457 c 0 1.103 -1.166 1.759 -3.133 1.759 c -2.154 0 -4.236 -0.552 -5.506 -1.072 v 4.402 c 1.894 0.5 4.038 0.749 6.546 0.749 c 5.412 0 7.837 -3.049 7.837 -6.078 C 30.237 45.567 27.531 43.34 22.973 43.028 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(249,249,249); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
+</g>
+</svg>
\ No newline at end of file
diff --git a/assets/images/usd_round_dark.svg b/assets/images/usd_round_dark.svg
new file mode 100644
index 000000000..f329dd617
--- /dev/null
+++ b/assets/images/usd_round_dark.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512">
+    <path d="M12,0C5.383,0,0,5.383,0,12s5.383,12,12,12,12-5.383,12-12S18.617,0,12,0Zm0,23c-6.065,0-11-4.935-11-11S5.935,1,12,1s11,4.935,11,11-4.935,11-11,11Zm4-8.626c0,1.448-1.178,2.626-2.626,2.626h-.874v1.5c0,.276-.224,.5-.5,.5s-.5-.224-.5-.5v-1.5h-.926c-.979,0-1.893-.526-2.382-1.375-.139-.239-.057-.545,.183-.683,.238-.14,.544-.057,.683,.183,.312,.54,.894,.875,1.517,.875h2.8c.896,0,1.626-.729,1.626-1.626,0-.803-.575-1.478-1.368-1.605l-3.422-.55c-1.28-.206-2.21-1.296-2.21-2.593,0-1.448,1.178-2.626,2.626-2.626h.874v-1.5c0-.276,.224-.5,.5-.5s.5,.224,.5,.5v1.5h.926c.979,0,1.892,.527,2.382,1.375,.139,.239,.057,.545-.183,.683-.236,.136-.545,.057-.683-.183-.312-.54-.894-.875-1.517-.875h-2.8c-.896,0-1.626,.729-1.626,1.626,0,.803,.575,1.478,1.368,1.605l3.422,.55c1.28,.206,2.21,1.297,2.21,2.593Z" fill="white"/>
+</svg>
\ No newline at end of file
diff --git a/assets/images/usd_round_light.svg b/assets/images/usd_round_light.svg
new file mode 100644
index 000000000..f5965c597
--- /dev/null
+++ b/assets/images/usd_round_light.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M12,0C5.383,0,0,5.383,0,12s5.383,12,12,12,12-5.383,12-12S18.617,0,12,0Zm0,23c-6.065,0-11-4.935-11-11S5.935,1,12,1s11,4.935,11,11-4.935,11-11,11Zm4-8.626c0,1.448-1.178,2.626-2.626,2.626h-.874v1.5c0,.276-.224,.5-.5,.5s-.5-.224-.5-.5v-1.5h-.926c-.979,0-1.893-.526-2.382-1.375-.139-.239-.057-.545,.183-.683,.238-.14,.544-.057,.683,.183,.312,.54,.894,.875,1.517,.875h2.8c.896,0,1.626-.729,1.626-1.626,0-.803-.575-1.478-1.368-1.605l-3.422-.55c-1.28-.206-2.21-1.296-2.21-2.593,0-1.448,1.178-2.626,2.626-2.626h.874v-1.5c0-.276,.224-.5,.5-.5s.5,.224,.5,.5v1.5h.926c.979,0,1.892,.527,2.382,1.375,.139,.239,.057,.545-.183,.683-.236,.136-.545,.057-.683-.183-.312-.54-.894-.875-1.517-.875h-2.8c-.896,0-1.626,.729-1.626,1.626,0,.803,.575,1.478,1.368,1.605l3.422,.55c1.28,.206,2.21,1.297,2.21,2.593Z"/></svg>
diff --git a/assets/images/wallet_new.png b/assets/images/wallet_new.png
new file mode 100644
index 0000000000000000000000000000000000000000..47c43bfca99bc5cf9958e150081d4f885ed27802
GIT binary patch
literal 5619
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

literal 0
HcmV?d00001

diff --git a/cw_core/lib/currency_for_wallet_type.dart b/cw_core/lib/currency_for_wallet_type.dart
index 630078949..af6037a3b 100644
--- a/cw_core/lib/currency_for_wallet_type.dart
+++ b/cw_core/lib/currency_for_wallet_type.dart
@@ -35,3 +35,34 @@ CryptoCurrency currencyForWalletType(WalletType type, {bool? isTestnet}) {
           'Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType');
   }
 }
+
+WalletType? walletTypeForCurrency(CryptoCurrency currency) {
+  switch (currency) {
+    case CryptoCurrency.btc:
+      return WalletType.bitcoin;
+    case CryptoCurrency.xmr:
+      return WalletType.monero;
+    case CryptoCurrency.ltc:
+      return WalletType.litecoin;
+    case CryptoCurrency.xhv:
+      return WalletType.haven;
+    case CryptoCurrency.eth:
+      return WalletType.ethereum;
+    case CryptoCurrency.bch:
+      return WalletType.bitcoinCash;
+    case CryptoCurrency.nano:
+      return WalletType.nano;
+    case CryptoCurrency.banano:
+      return WalletType.banano;
+    case CryptoCurrency.maticpoly:
+      return WalletType.polygon;
+    case CryptoCurrency.sol:
+      return WalletType.solana;
+    case CryptoCurrency.trx:
+      return WalletType.tron;
+    case CryptoCurrency.wow:
+      return WalletType.wownero;
+    default:
+      return null;
+  }
+}
diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart
index 1a37e09b3..8e79e16b8 100644
--- a/lib/buy/buy_provider.dart
+++ b/lib/buy/buy_provider.dart
@@ -1,6 +1,10 @@
 import 'package:cake_wallet/buy/buy_amount.dart';
+import 'package:cake_wallet/buy/buy_quote.dart';
 import 'package:cake_wallet/buy/order.dart';
+import 'package:cake_wallet/buy/payment_method.dart';
+import 'package:cake_wallet/entities/fiat_currency.dart';
 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
+import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:flutter/material.dart';
 
@@ -23,14 +27,38 @@ abstract class BuyProvider {
 
   String get darkIcon;
 
+  bool get isAggregator;
+
   @override
   String toString() => title;
 
-  Future<void> launchProvider(BuildContext context, bool? isBuyAction);
+  Future<void>? launchProvider(
+          {required BuildContext context,
+          required Quote quote,
+          required double amount,
+          required bool isBuyAction,
+          required String cryptoCurrencyAddress,
+          String? countryCode}) =>
+      null;
 
   Future<String> requestUrl(String amount, String sourceCurrency) => throw UnimplementedError();
 
   Future<Order> findOrderById(String id) => throw UnimplementedError();
 
-  Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) => throw UnimplementedError();
+  Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) =>
+      throw UnimplementedError();
+
+  Future<List<PaymentMethod>> getAvailablePaymentTypes(
+          String fiatCurrency, String cryptoCurrency, bool isBuyAction) async =>
+      [];
+
+  Future<List<Quote>?> fetchQuote(
+          {required CryptoCurrency cryptoCurrency,
+          required FiatCurrency fiatCurrency,
+          required double amount,
+          required bool isBuyAction,
+          required String walletAddress,
+          PaymentType? paymentType,
+          String? countryCode}) async =>
+      null;
 }
diff --git a/lib/buy/buy_quote.dart b/lib/buy/buy_quote.dart
new file mode 100644
index 000000000..72ab7bd7d
--- /dev/null
+++ b/lib/buy/buy_quote.dart
@@ -0,0 +1,302 @@
+import 'package:cake_wallet/buy/buy_provider.dart';
+import 'package:cake_wallet/buy/payment_method.dart';
+import 'package:cake_wallet/core/selectable_option.dart';
+import 'package:cake_wallet/entities/fiat_currency.dart';
+import 'package:cake_wallet/entities/provider_types.dart';
+import 'package:cake_wallet/exchange/limits.dart';
+import 'package:cw_core/crypto_currency.dart';
+
+enum ProviderRecommendation { bestRate, lowKyc, successRate }
+
+extension RecommendationTitle on ProviderRecommendation {
+  String get title {
+    switch (this) {
+      case ProviderRecommendation.bestRate:
+        return 'BEST RATE';
+      case ProviderRecommendation.lowKyc:
+        return 'LOW KYC';
+      case ProviderRecommendation.successRate:
+        return 'SUCCESS RATE';
+    }
+  }
+}
+
+ProviderRecommendation? getRecommendationFromString(String title) {
+  switch (title) {
+    case 'BEST RATE':
+      return ProviderRecommendation.bestRate;
+    case 'LowKyc':
+      return ProviderRecommendation.lowKyc;
+    case 'SuccessRate':
+      return ProviderRecommendation.successRate;
+    default:
+      return null;
+  }
+}
+
+class Quote extends SelectableOption {
+  Quote({
+    required this.rate,
+    required this.feeAmount,
+    required this.networkFee,
+    required this.transactionFee,
+    required this.payout,
+    required this.provider,
+    required this.paymentType,
+    required this.recommendations,
+    this.isBuyAction = true,
+    this.quoteId,
+    this.rampId,
+    this.rampName,
+    this.rampIconPath,
+    this.limits,
+  }) : super(title: provider.isAggregator ? rampName ?? '' : provider.title);
+
+  final double rate;
+  final double feeAmount;
+  final double networkFee;
+  final double transactionFee;
+  final double payout;
+  final PaymentType paymentType;
+  final BuyProvider provider;
+  final String? quoteId;
+  final List<ProviderRecommendation> recommendations;
+  String? rampId;
+  String? rampName;
+  String? rampIconPath;
+  bool _isSelected = false;
+  bool _isBestRate = false;
+  bool isBuyAction;
+  Limits? limits;
+
+  late FiatCurrency _fiatCurrency;
+  late CryptoCurrency _cryptoCurrency;
+
+
+  bool get isSelected => _isSelected;
+  bool get isBestRate => _isBestRate;
+  FiatCurrency get fiatCurrency => _fiatCurrency;
+  CryptoCurrency get cryptoCurrency => _cryptoCurrency;
+
+  @override
+  bool get isOptionSelected => this._isSelected;
+
+  @override
+  String get lightIconPath =>
+      provider.isAggregator ? rampIconPath ?? provider.lightIcon : provider.lightIcon;
+
+  @override
+  String get darkIconPath =>
+      provider.isAggregator ? rampIconPath ?? provider.darkIcon : provider.darkIcon;
+
+  @override
+  List<String> get badges => recommendations.map((e) => e.title).toList();
+
+  @override
+  String get topLeftSubTitle =>
+      this.rate > 0 ? '1 $cryptoName = ${rate.toStringAsFixed(2)} $fiatName' : '';
+
+  @override
+  String get bottomLeftSubTitle {
+    if (limits != null) {
+      final min = limits!.min;
+      final max = limits!.max;
+      return 'min: ${min} ${fiatCurrency.toString()} | max: ${max == double.infinity ? '' : '${max} ${fiatCurrency.toString()}'}';
+    }
+    return '';
+  }
+
+  String get fiatName => isBuyAction ? fiatCurrency.toString() : cryptoCurrency.toString();
+
+  String get cryptoName => isBuyAction ? cryptoCurrency.toString() : fiatCurrency.toString();
+
+  @override
+  String? get topRightSubTitle => '';
+
+  @override
+  String get topRightSubTitleLightIconPath => provider.isAggregator ? provider.lightIcon : '';
+
+  @override
+  String get topRightSubTitleDarkIconPath => provider.isAggregator ? provider.darkIcon : '';
+
+  String get quoteTitle => '${provider.title} - ${paymentType.name}';
+
+  String get formatedFee => '$feeAmount ${isBuyAction ? fiatCurrency : cryptoCurrency}';
+
+  set setIsSelected(bool isSelected) => _isSelected = isSelected;
+  set setIsBestRate(bool isBestRate) => _isBestRate = isBestRate;
+  set setFiatCurrency(FiatCurrency fiatCurrency) => _fiatCurrency = fiatCurrency;
+  set setCryptoCurrency(CryptoCurrency cryptoCurrency) => _cryptoCurrency = cryptoCurrency;
+  set setLimits(Limits limits) => this.limits = limits;
+
+  factory Quote.fromOnramperJson(Map<String, dynamic> json, bool isBuyAction,
+      Map<String, dynamic> metaData, PaymentType paymentType) {
+    final rate = _toDouble(json['rate']) ?? 0.0;
+    final networkFee = _toDouble(json['networkFee']) ?? 0.0;
+    final transactionFee = _toDouble(json['transactionFee']) ?? 0.0;
+    final feeAmount = double.parse((networkFee + transactionFee).toStringAsFixed(2));
+
+    final rampId = json['ramp'] as String? ?? '';
+    final rampData = metaData[rampId] ?? {};
+    final rampName = rampData['displayName'] as String? ?? '';
+    final rampIconPath = rampData['svg'] as String? ?? '';
+
+    final recommendations = json['recommendations'] != null
+        ? List<String>.from(json['recommendations'] as List<dynamic>)
+        : <String>[];
+
+    final enumRecommendations = recommendations
+        .map((e) => getRecommendationFromString(e))
+        .whereType<ProviderRecommendation>()
+        .toList();
+
+    final availablePaymentMethods = json['availablePaymentMethods'] as List<dynamic>? ?? [];
+    double minLimit = 0.0;
+    double maxLimit = double.infinity;
+
+    for (var paymentMethod in availablePaymentMethods) {
+      if (paymentMethod is Map<String, dynamic>) {
+        final details = paymentMethod['details'] as Map<String, dynamic>?;
+
+        if (details != null) {
+          final limits = details['limits'] as Map<String, dynamic>?;
+
+          if (limits != null && limits.isNotEmpty) {
+            final firstLimitEntry = limits.values.first as Map<String, dynamic>?;
+            if (firstLimitEntry != null) {
+              minLimit = _toDouble(firstLimitEntry['min'])?.roundToDouble() ?? 0.0;
+              maxLimit = _toDouble(firstLimitEntry['max'])?.roundToDouble() ?? double.infinity;
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    return Quote(
+      rate: rate,
+      feeAmount: feeAmount,
+      networkFee: networkFee,
+      transactionFee: transactionFee,
+      payout: json['payout'] as double? ?? 0.0,
+      rampId: rampId,
+      rampName: rampName,
+      rampIconPath: rampIconPath,
+      paymentType: paymentType,
+      quoteId: json['quoteId'] as String? ?? '',
+      recommendations: enumRecommendations,
+      provider: ProvidersHelper.getProviderByType(ProviderType.onramper)!,
+      isBuyAction: isBuyAction,
+      limits: Limits(min: minLimit, max: maxLimit),
+    );
+  }
+
+  factory Quote.fromMoonPayJson(
+      Map<String, dynamic> json, bool isBuyAction, PaymentType paymentType) {
+    final rate = isBuyAction
+        ? json['quoteCurrencyPrice'] as double? ?? 0.0
+        : json['baseCurrencyPrice'] as double? ?? 0.0;
+    final fee = _toDouble(json['feeAmount']) ?? 0.0;
+    final networkFee = _toDouble(json['networkFeeAmount']) ?? 0.0;
+    final transactionFee = _toDouble(json['extraFeeAmount']) ?? 0.0;
+    final feeAmount = double.parse((fee + networkFee + transactionFee).toStringAsFixed(2));
+
+    final baseCurrency = json['baseCurrency'] as Map<String, dynamic>?;
+
+    double minLimit = 0.0;
+    double maxLimit = double.infinity;
+
+    if (baseCurrency != null) {
+      minLimit = _toDouble(baseCurrency['minAmount']) ?? minLimit;
+      maxLimit = _toDouble(baseCurrency['maxAmount']) ?? maxLimit;
+    }
+
+    return Quote(
+      rate: rate,
+      feeAmount: feeAmount,
+      networkFee: networkFee,
+      transactionFee: transactionFee,
+      payout: _toDouble(json['quoteCurrencyAmount']) ?? 0.0,
+      paymentType: paymentType,
+      recommendations: [],
+      quoteId: json['signature'] as String? ?? '',
+      provider: ProvidersHelper.getProviderByType(ProviderType.moonpay)!,
+      isBuyAction: isBuyAction,
+      limits: Limits(min: minLimit, max: maxLimit),
+    );
+  }
+
+  factory Quote.fromDFXJson(
+    Map<String, dynamic> json,
+    bool isBuyAction,
+    PaymentType paymentType,
+  ) {
+    final rate = _toDouble(json['exchangeRate']) ?? 0.0;
+    final fees = json['fees'] as Map<String, dynamic>;
+
+    final minVolume = _toDouble(json['minVolume']) ?? 0.0;
+    final maxVolume = _toDouble(json['maxVolume']) ?? double.infinity;
+
+    return Quote(
+      rate: isBuyAction ? rate : 1 / rate,
+      feeAmount: _toDouble(json['feeAmount']) ?? 0.0,
+      networkFee: _toDouble(fees['network']) ?? 0.0,
+      transactionFee: _toDouble(fees['rate']) ?? 0.0,
+      payout: _toDouble(json['payout']) ?? 0.0,
+      paymentType: paymentType,
+      recommendations: [ProviderRecommendation.lowKyc],
+      provider: ProvidersHelper.getProviderByType(ProviderType.dfx)!,
+      isBuyAction: isBuyAction,
+      limits: Limits(min: minVolume, max: maxVolume),
+    );
+  }
+
+  factory Quote.fromRobinhoodJson(
+      Map<String, dynamic> json, bool isBuyAction, PaymentType paymentType) {
+    final networkFee = json['networkFee'] as Map<String, dynamic>;
+    final processingFee = json['processingFee'] as Map<String, dynamic>;
+    final networkFeeAmount = _toDouble(networkFee['fiatAmount']) ?? 0.0;
+    final transactionFeeAmount = _toDouble(processingFee['fiatAmount']) ?? 0.0;
+    final feeAmount = double.parse((networkFeeAmount + transactionFeeAmount).toStringAsFixed(2));
+
+    return Quote(
+      rate: _toDouble(json['price']) ?? 0.0,
+      feeAmount: feeAmount,
+      networkFee: _toDouble(networkFee['fiatAmount']) ?? 0.0,
+      transactionFee: _toDouble(processingFee['fiatAmount']) ?? 0.0,
+      payout: _toDouble(json['cryptoAmount']) ?? 0.0,
+      paymentType: paymentType,
+      recommendations: [],
+      provider: ProvidersHelper.getProviderByType(ProviderType.robinhood)!,
+      isBuyAction: isBuyAction,
+      limits: Limits(min: 0.0, max: double.infinity),
+    );
+  }
+
+  factory Quote.fromMeldJson(Map<String, dynamic> json, bool isBuyAction, PaymentType paymentType) {
+    final quotes = json['quotes'][0] as Map<String, dynamic>;
+    return Quote(
+      rate: quotes['exchangeRate'] as double? ?? 0.0,
+      feeAmount: quotes['totalFee'] as double? ?? 0.0,
+      networkFee: quotes['networkFee'] as double? ?? 0.0,
+      transactionFee: quotes['transactionFee'] as double? ?? 0.0,
+      payout: quotes['payout'] as double? ?? 0.0,
+      paymentType: paymentType,
+      recommendations: [],
+      provider: ProvidersHelper.getProviderByType(ProviderType.meld)!,
+      isBuyAction: isBuyAction,
+      limits: Limits(min: 0.0, max: double.infinity),
+    );
+  }
+
+  static double? _toDouble(dynamic value) {
+    if (value is int) {
+      return value.toDouble();
+    } else if (value is double) {
+      return value;
+    } else if (value is String) {
+      return double.tryParse(value);
+    }
+    return null;
+  }
+}
diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart
index b3ed72498..c1ed762b1 100644
--- a/lib/buy/dfx/dfx_buy_provider.dart
+++ b/lib/buy/dfx/dfx_buy_provider.dart
@@ -1,13 +1,17 @@
 import 'dart:convert';
+import 'dart:developer';
 
 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/generated/i18n.dart';
 import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
-import 'package:cake_wallet/utils/device_info.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
+import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/material.dart';
@@ -15,10 +19,12 @@ import 'package:http/http.dart' as http;
 import 'package:url_launcher/url_launcher.dart';
 
 class DFXBuyProvider extends BuyProvider {
-  DFXBuyProvider({required WalletBase wallet, bool isTestEnvironment = false, LedgerViewModel? ledgerVM})
+  DFXBuyProvider(
+      {required WalletBase wallet, bool isTestEnvironment = false, LedgerViewModel? ledgerVM})
       : super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: ledgerVM);
 
   static const _baseUrl = 'api.dfx.swiss';
+
   // static const _signMessagePath = '/v1/auth/signMessage';
   static const _authPath = '/v1/auth';
   static const walletName = 'CakeWallet';
@@ -35,24 +41,8 @@ class DFXBuyProvider extends BuyProvider {
   @override
   String get darkIcon => 'assets/images/dfx_dark.png';
 
-  String get assetOut {
-    switch (wallet.type) {
-      case WalletType.bitcoin:
-        return 'BTC';
-      case WalletType.bitcoinCash:
-        return 'BCH';
-      case WalletType.litecoin:
-        return 'LTC';
-      case WalletType.monero:
-        return 'XMR';
-      case WalletType.ethereum:
-        return 'ETH';
-      case WalletType.polygon:
-        return 'MATIC';
-      default:
-        throw Exception("WalletType is not available for DFX ${wallet.type}");
-    }
-  }
+  @override
+  bool get isAggregator => false;
 
   String get blockchain {
     switch (wallet.type) {
@@ -60,21 +50,13 @@ class DFXBuyProvider extends BuyProvider {
       case WalletType.bitcoinCash:
       case WalletType.litecoin:
         return 'Bitcoin';
-      case WalletType.monero:
-        return 'Monero';
-      case WalletType.ethereum:
-        return 'Ethereum';
-      case WalletType.polygon:
-        return 'Polygon';
       default:
-        throw Exception("WalletType is not available for DFX ${wallet.type}");
+        return walletTypeToString(wallet.type);
     }
   }
 
-  String get walletAddress =>
-      wallet.walletAddresses.primaryAddress ?? wallet.walletAddresses.address;
 
-  Future<String> getSignMessage() async =>
+  Future<String> getSignMessage(String walletAddress) async =>
       "By_signing_this_message,_you_confirm_that_you_are_the_sole_owner_of_the_provided_Blockchain_address._Your_ID:_$walletAddress";
 
   // // Lets keep this just in case, but we can avoid this API Call
@@ -92,8 +74,9 @@ class DFXBuyProvider extends BuyProvider {
   //  }
   // }
 
-  Future<String> auth() async {
-    final signMessage = await getSignature(await getSignMessage());
+  Future<String> auth(String walletAddress) async {
+    final signMessage = await getSignature(
+        await getSignMessage(walletAddress), walletAddress);
 
     final requestBody = jsonEncode({
       'wallet': walletName,
@@ -120,7 +103,7 @@ class DFXBuyProvider extends BuyProvider {
     }
   }
 
-  Future<String> getSignature(String message) async {
+  Future<String> getSignature(String message, String walletAddress) async {
     switch (wallet.type) {
       case WalletType.ethereum:
       case WalletType.polygon:
@@ -135,8 +118,178 @@ class DFXBuyProvider extends BuyProvider {
     }
   }
 
+  Future<Map<String, dynamic>> fetchFiatCredentials(String fiatCurrency) async {
+    final url = Uri.https(_baseUrl, '/v1/fiat');
+
+    try {
+      final response = await http.get(url, headers: {'accept': 'application/json'});
+
+      if (response.statusCode == 200) {
+        final data = jsonDecode(response.body) as List<dynamic>;
+        for (final item in data) {
+          if (item['name'] == fiatCurrency) return item as Map<String, dynamic>;
+        }
+        log('DFX does not support fiat: $fiatCurrency');
+        return {};
+      } else {
+        log('DFX Failed to fetch fiat currencies: ${response.statusCode}');
+        return {};
+      }
+    } catch (e) {
+      print('DFX Error fetching fiat currencies: $e');
+      return {};
+    }
+  }
+
+  Future<Map<String, dynamic>> fetchAssetCredential(String assetsName) async {
+    final url = Uri.https(_baseUrl, '/v1/asset', {'blockchains': blockchain});
+
+    try {
+      final response = await http.get(url, headers: {'accept': 'application/json'});
+
+      if (response.statusCode == 200) {
+        final responseData = jsonDecode(response.body);
+
+        if (responseData is List && responseData.isNotEmpty) {
+          return responseData.first as Map<String, dynamic>;
+        } else if (responseData is Map<String, dynamic>) {
+          return responseData;
+        } else {
+          log('DFX: Does not support this asset name : ${blockchain}');
+        }
+      } else {
+        log('DFX: Failed to fetch assets: ${response.statusCode}');
+      }
+    } catch (e) {
+      log('DFX: Error fetching assets: $e');
+    }
+    return {};
+  }
+
+  Future<List<PaymentMethod>> getAvailablePaymentTypes(
+      String fiatCurrency, String cryptoCurrency, bool isBuyAction) async {
+    final List<PaymentMethod> paymentMethods = [];
+
+    if (isBuyAction) {
+      final fiatBuyCredentials = await fetchFiatCredentials(fiatCurrency);
+      if (fiatBuyCredentials.isNotEmpty) {
+        fiatBuyCredentials.forEach((key, value) {
+          if (key == 'limits') {
+            final limits = value as Map<String, dynamic>;
+            limits.forEach((paymentMethodKey, paymentMethodValue) {
+              final min = _toDouble(paymentMethodValue['minVolume']);
+              final max = _toDouble(paymentMethodValue['maxVolume']);
+              if (min != null && max != null && min > 0 && max > 0) {
+                final paymentMethod = PaymentMethod.fromDFX(
+                    paymentMethodKey, _getPaymentTypeByString(paymentMethodKey));
+                paymentMethods.add(paymentMethod);
+              }
+            });
+          }
+        });
+      }
+    } else {
+      final assetCredentials = await fetchAssetCredential(cryptoCurrency);
+      if (assetCredentials.isNotEmpty) {
+        if (assetCredentials['sellable'] == true) {
+          final availablePaymentTypes = [
+            PaymentType.bankTransfer,
+            PaymentType.creditCard,
+            PaymentType.sepa
+          ];
+          availablePaymentTypes.forEach((element) {
+            final paymentMethod = PaymentMethod.fromDFX(normalizePaymentMethod(element)!, element);
+            paymentMethods.add(paymentMethod);
+          });
+        }
+      }
+    }
+
+    return paymentMethods;
+  }
+
   @override
-  Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
+  Future<List<Quote>?> fetchQuote(
+      {required CryptoCurrency cryptoCurrency,
+      required FiatCurrency fiatCurrency,
+      required double amount,
+      required bool isBuyAction,
+      required String walletAddress,
+      PaymentType? paymentType,
+      String? countryCode}) async {
+    /// if buying with any currency other than eur or chf then DFX is not supported
+
+    if (isBuyAction && (fiatCurrency != FiatCurrency.eur && fiatCurrency != FiatCurrency.chf)) {
+      return null;
+    }
+
+    String? paymentMethod;
+    if (paymentType != null && paymentType != PaymentType.all) {
+      paymentMethod = normalizePaymentMethod(paymentType);
+      if (paymentMethod == null) paymentMethod = paymentType.name;
+    } else {
+      paymentMethod = 'Bank';
+    }
+
+    final action = isBuyAction ? 'buy' : 'sell';
+
+    if (isBuyAction && cryptoCurrency != wallet.currency) return null;
+
+    final fiatCredentials = await fetchFiatCredentials(fiatCurrency.name.toString());
+    if (fiatCredentials['id'] == null) return null;
+
+    final assetCredentials = await fetchAssetCredential(cryptoCurrency.title.toString());
+    if (assetCredentials['id'] == null) return null;
+
+    log('DFX: Fetching $action quote: ${isBuyAction ? cryptoCurrency : fiatCurrency} -> ${isBuyAction ? fiatCurrency : cryptoCurrency}, amount: $amount, paymentMethod: $paymentMethod');
+
+    final url = Uri.https(_baseUrl, '/v1/$action/quote');
+    final headers = {'accept': 'application/json', 'Content-Type': 'application/json'};
+    final body = jsonEncode({
+      'currency': {'id': fiatCredentials['id'] as int},
+      'asset': {'id': assetCredentials['id']},
+      'amount': amount,
+      'targetAmount': 0,
+      'paymentMethod': paymentMethod,
+      'discountCode': ''
+    });
+
+    try {
+      final response = await http.put(url, headers: headers, body: body);
+      final responseData = jsonDecode(response.body);
+
+      if (response.statusCode == 200) {
+        if (responseData is Map<String, dynamic>) {
+          final paymentType = _getPaymentTypeByString(responseData['paymentMethod'] as String?);
+          final quote = Quote.fromDFXJson(responseData, isBuyAction, paymentType);
+          quote.setFiatCurrency = fiatCurrency;
+          quote.setCryptoCurrency = cryptoCurrency;
+          return [quote];
+        } else {
+          print('DFX: Unexpected data type: ${responseData.runtimeType}');
+          return null;
+        }
+      } else {
+        if (responseData is Map<String, dynamic> && responseData.containsKey('message')) {
+          print('DFX Error: ${responseData['message']}');
+        } else {
+          print('DFX Failed to fetch buy quote: ${response.statusCode}');
+        }
+        return null;
+      }
+    } catch (e) {
+      print('DFX Error fetching buy quote: $e');
+      return null;
+    }
+  }
+
+  Future<void>? launchProvider(
+      {required BuildContext context,
+      required Quote quote,
+      required double amount,
+      required bool isBuyAction,
+      required String cryptoCurrencyAddress,
+      String? countryCode}) async {
     if (wallet.isHardwareWallet) {
       if (!ledgerVM!.isConnected) {
         await Navigator.of(context).pushNamed(Routes.connectDevices,
@@ -152,26 +305,21 @@ class DFXBuyProvider extends BuyProvider {
     }
 
     try {
-      final assetOut = this.assetOut;
-      final blockchain = this.blockchain;
-      final actionType = isBuyAction == true ? '/buy' : '/sell';
+      final actionType = isBuyAction ? '/buy' : '/sell';
 
-      final accessToken = await auth();
+      final accessToken = await auth(cryptoCurrencyAddress);
 
       final uri = Uri.https('services.dfx.swiss', actionType, {
         'session': accessToken,
         'lang': 'en',
-        'asset-out': assetOut,
+        'asset-out': isBuyAction ? quote.cryptoCurrency.toString() : quote.fiatCurrency.toString(),
         'blockchain': blockchain,
-        'asset-in': 'EUR',
+        'asset-in': isBuyAction ? quote.fiatCurrency.toString() : quote.cryptoCurrency.toString(),
+        'amount': amount.toString() //TODO: Amount does not work
       });
 
       if (await canLaunchUrl(uri)) {
-        if (DeviceInfo.instance.isMobile) {
-          Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [title, uri]);
-        } else {
-          await launchUrl(uri, mode: LaunchMode.externalApplication);
-        }
+        await launchUrl(uri, mode: LaunchMode.externalApplication);
       } else {
         throw Exception('Could not launch URL');
       }
@@ -187,4 +335,39 @@ class DFXBuyProvider extends BuyProvider {
           });
     }
   }
+
+  String? normalizePaymentMethod(PaymentType paymentMethod) {
+    switch (paymentMethod) {
+      case PaymentType.bankTransfer:
+        return 'Bank';
+      case PaymentType.creditCard:
+        return 'Card';
+      case PaymentType.sepa:
+        return 'Instant';
+      default:
+        return null;
+    }
+  }
+
+  PaymentType _getPaymentTypeByString(String? paymentMethod) {
+    switch (paymentMethod) {
+      case 'Bank':
+        return PaymentType.bankTransfer;
+      case 'Card':
+        return PaymentType.creditCard;
+      case 'Instant':
+        return PaymentType.sepa;
+      default:
+        return PaymentType.all;
+    }
+  }
+
+  double? _toDouble(dynamic value) {
+    if (value is int) {
+      return value.toDouble();
+    } else if (value is double) {
+      return value;
+    }
+    return null;
+  }
 }
diff --git a/lib/buy/meld/meld_buy_provider.dart b/lib/buy/meld/meld_buy_provider.dart
new file mode 100644
index 000000000..696301f2e
--- /dev/null
+++ b/lib/buy/meld/meld_buy_provider.dart
@@ -0,0 +1,266 @@
+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/entities/provider_types.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/routes.dart';
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
+import 'package:cake_wallet/utils/device_info.dart';
+import 'package:cake_wallet/utils/show_pop_up.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/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 MeldBuyProvider extends BuyProvider {
+  MeldBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
+      : super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: null);
+
+  static const _isProduction = false;
+
+  static const _baseUrl = _isProduction ? 'api.meld.io' : 'api-sb.meld.io';
+  static const _providersProperties = '/service-providers/properties';
+  static const _paymentMethodsPath = '/payment-methods';
+  static const _quotePath = '/payments/crypto/quote';
+
+  static const String sandboxUrl = 'sb.fluidmoney.xyz';
+  static const String productionUrl = 'fluidmoney.xyz';
+
+  static const String _baseWidgetUrl = _isProduction ? productionUrl : sandboxUrl;
+
+  static String get _testApiKey => secrets.meldTestApiKey;
+
+  static String get _testPublicKey => '' ; //secrets.meldTestPublicKey;
+
+  @override
+  String get title => 'Meld';
+
+  @override
+  String get providerDescription => 'Meld Buy Provider';
+
+  @override
+  String get lightIcon => 'assets/images/meld_logo.svg';
+
+  @override
+  String get darkIcon => 'assets/images/meld_logo.svg';
+
+  @override
+  bool get isAggregator => true;
+
+  @override
+  Future<List<PaymentMethod>> getAvailablePaymentTypes(
+      String fiatCurrency, String cryptoCurrency, bool isBuyAction) async {
+    final params = {'fiatCurrencies': fiatCurrency, 'statuses': 'LIVE,RECENTLY_ADDED,BUILDING'};
+
+    final path = '$_providersProperties$_paymentMethodsPath';
+    final url = Uri.https(_baseUrl, path, params);
+
+    try {
+      final response = await http.get(
+        url,
+        headers: {
+          'Authorization': _isProduction ? '' : _testApiKey,
+          'Meld-Version': '2023-12-19',
+          'accept': 'application/json',
+          'content-type': 'application/json',
+        },
+      );
+
+      if (response.statusCode == 200) {
+        final data = jsonDecode(response.body) as List<dynamic>;
+        final paymentMethods =
+            data.map((e) => PaymentMethod.fromMeldJson(e as Map<String, dynamic>)).toList();
+        return paymentMethods;
+      } else {
+        print('Meld: Failed to fetch payment types');
+        return List<PaymentMethod>.empty();
+      }
+    } catch (e) {
+      print('Meld: Failed to fetch payment types: $e');
+      return List<PaymentMethod>.empty();
+    }
+  }
+
+  @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 {
+    String? paymentMethod;
+    if (paymentType != null && paymentType != PaymentType.all) {
+      paymentMethod = normalizePaymentMethod(paymentType);
+      if (paymentMethod == null) paymentMethod = paymentType.name;
+    }
+
+    log('Meld: Fetching buy quote: ${isBuyAction ? cryptoCurrency : fiatCurrency} -> ${isBuyAction ? fiatCurrency : cryptoCurrency}, amount: $amount');
+
+    final url = Uri.https(_baseUrl, _quotePath);
+    final headers = {
+      'Authorization': _testApiKey,
+      'Meld-Version': '2023-12-19',
+      'accept': 'application/json',
+      'content-type': 'application/json',
+    };
+    final body = jsonEncode({
+      'countryCode': countryCode,
+      'destinationCurrencyCode': isBuyAction ? fiatCurrency.name : cryptoCurrency.title,
+      'sourceAmount': amount,
+      'sourceCurrencyCode': isBuyAction ? cryptoCurrency.title : fiatCurrency.name,
+      if (paymentMethod != null) 'paymentMethod': paymentMethod,
+    });
+
+    try {
+      final response = await http.post(url, headers: headers, body: body);
+
+      if (response.statusCode == 200) {
+        final data = jsonDecode(response.body) as Map<String, dynamic>;
+        final paymentType = _getPaymentTypeByString(data['paymentMethodType'] as String?);
+        final quote = Quote.fromMeldJson(data, isBuyAction, paymentType);
+
+        quote.setFiatCurrency = fiatCurrency;
+        quote.setCryptoCurrency = cryptoCurrency;
+
+        return [quote];
+      } else {
+        return null;
+      }
+    } catch (e) {
+      print('Error fetching buy quote: $e');
+      return null;
+    }
+  }
+
+  Future<void>? launchProvider(
+      {required BuildContext context,
+      required Quote quote,
+      required double amount,
+      required bool isBuyAction,
+      required String cryptoCurrencyAddress,
+      String? countryCode}) async {
+    final actionType = isBuyAction ? 'BUY' : 'SELL';
+
+    final params = {
+      'publicKey': _isProduction ? '' : _testPublicKey,
+      'countryCode': countryCode,
+      //'paymentMethodType': normalizePaymentMethod(paymentMethod.paymentMethodType),
+      'sourceAmount': amount.toString(),
+      'sourceCurrencyCode': quote.fiatCurrency,
+      'destinationCurrencyCode': quote.cryptoCurrency,
+      'walletAddress': cryptoCurrencyAddress,
+      'transactionType': actionType
+    };
+
+    final uri = Uri.https(_baseWidgetUrl, '', 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: "Meld",
+                alertContent: S.of(context).buy_provider_unavailable + ': $e',
+                buttonText: S.of(context).ok,
+                buttonAction: () => Navigator.of(context).pop());
+          });
+    }
+  }
+
+  String? normalizePaymentMethod(PaymentType paymentType) {
+    switch (paymentType) {
+      case PaymentType.creditCard:
+        return 'CREDIT_DEBIT_CARD';
+      case PaymentType.applePay:
+        return 'APPLE_PAY';
+      case PaymentType.googlePay:
+        return 'GOOGLE_PAY';
+      case PaymentType.neteller:
+        return 'NETELLER';
+      case PaymentType.skrill:
+        return 'SKRILL';
+      case PaymentType.sepa:
+        return 'SEPA';
+      case PaymentType.sepaInstant:
+        return 'SEPA_INSTANT';
+      case PaymentType.ach:
+        return 'ACH';
+      case PaymentType.achInstant:
+        return 'INSTANT_ACH';
+      case PaymentType.Khipu:
+        return 'KHIPU';
+      case PaymentType.ovo:
+        return 'OVO';
+      case PaymentType.zaloPay:
+        return 'ZALOPAY';
+      case PaymentType.zaloBankTransfer:
+        return 'ZA_BANK_TRANSFER';
+      case PaymentType.gcash:
+        return 'GCASH';
+      case PaymentType.imps:
+        return 'IMPS';
+      case PaymentType.dana:
+        return 'DANA';
+      case PaymentType.ideal:
+        return 'IDEAL';
+      default:
+        return null;
+    }
+  }
+
+  PaymentType _getPaymentTypeByString(String? paymentMethod) {
+    switch (paymentMethod?.toUpperCase()) {
+      case 'CREDIT_DEBIT_CARD':
+        return PaymentType.creditCard;
+      case 'APPLE_PAY':
+        return PaymentType.applePay;
+      case 'GOOGLE_PAY':
+        return PaymentType.googlePay;
+      case 'NETELLER':
+        return PaymentType.neteller;
+      case 'SKRILL':
+        return PaymentType.skrill;
+      case 'SEPA':
+        return PaymentType.sepa;
+      case 'SEPA_INSTANT':
+        return PaymentType.sepaInstant;
+      case 'ACH':
+        return PaymentType.ach;
+      case 'INSTANT_ACH':
+        return PaymentType.achInstant;
+      case 'KHIPU':
+        return PaymentType.Khipu;
+      case 'OVO':
+        return PaymentType.ovo;
+      case 'ZALOPAY':
+        return PaymentType.zaloPay;
+      case 'ZA_BANK_TRANSFER':
+        return PaymentType.zaloBankTransfer;
+      case 'GCASH':
+        return PaymentType.gcash;
+      case 'IMPS':
+        return PaymentType.imps;
+      case 'DANA':
+        return PaymentType.dana;
+      case 'IDEAL':
+        return PaymentType.ideal;
+      default:
+        return PaymentType.all;
+    }
+  }
+}
diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart
index 67ee75d7c..b93c0f02d 100644
--- a/lib/buy/moonpay/moonpay_provider.dart
+++ b/lib/buy/moonpay/moonpay_provider.dart
@@ -1,19 +1,20 @@
 import 'dart:convert';
+import 'dart:developer';
 
 import 'package:cake_wallet/.secrets.g.dart' as secrets;
-import 'package:cake_wallet/buy/buy_amount.dart';
 import 'package:cake_wallet/buy/buy_exception.dart';
 import 'package:cake_wallet/buy/buy_provider.dart';
 import 'package:cake_wallet/buy/buy_provider_description.dart';
+import 'package:cake_wallet/buy/buy_quote.dart';
 import 'package:cake_wallet/buy/order.dart';
+import 'package:cake_wallet/buy/payment_method.dart';
+import 'package:cake_wallet/entities/fiat_currency.dart';
 import 'package:cake_wallet/exchange/trade_state.dart';
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/palette.dart';
-import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
 import 'package:cake_wallet/store/settings_store.dart';
 import 'package:cake_wallet/themes/theme_base.dart';
-import 'package:cake_wallet/utils/device_info.dart';
 import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_type.dart';
@@ -39,6 +40,15 @@ class MoonPayProvider extends BuyProvider {
   static const _baseBuyProductUrl = 'buy.moonpay.com';
   static const _cIdBaseUrl = 'exchange-helper.cakewallet.com';
   static const _apiUrl = 'https://api.moonpay.com';
+  static const _baseUrl = 'api.moonpay.com';
+  static const _currenciesPath = '/v3/currencies';
+  static const _buyQuote = '/buy_quote';
+  static const _sellQuote = '/sell_quote';
+
+  static const _transactionsSuffix = '/v1/transactions';
+
+  final String baseBuyUrl;
+  final String baseSellUrl;
 
   @override
   String get providerDescription =>
@@ -53,6 +63,17 @@ class MoonPayProvider extends BuyProvider {
   @override
   String get darkIcon => 'assets/images/moonpay_dark.png';
 
+  @override
+  bool get isAggregator => false;
+
+  static String get _apiKey => secrets.moonPayApiKey;
+
+  String get currencyCode => walletTypeToCryptoCurrency(wallet.type).title.toLowerCase();
+
+  String get trackUrl => baseBuyUrl + '/transaction_receipt?transactionId=';
+
+  static String get _exchangeHelperApiKey => secrets.exchangeHelperApiKey;
+
   static String themeToMoonPayTheme(ThemeBase theme) {
     switch (theme.type) {
       case ThemeType.bright:
@@ -63,28 +84,12 @@ class MoonPayProvider extends BuyProvider {
     }
   }
 
-  static String get _apiKey => secrets.moonPayApiKey;
-
-  final String baseBuyUrl;
-  final String baseSellUrl;
-
-  String get currencyCode => walletTypeToCryptoCurrency(wallet.type).title.toLowerCase();
-
-  String get trackUrl => baseBuyUrl + '/transaction_receipt?transactionId=';
-
-  static String get _exchangeHelperApiKey => secrets.exchangeHelperApiKey;
-
   Future<String> getMoonpaySignature(String query) async {
     final uri = Uri.https(_cIdBaseUrl, "/api/moonpay");
 
-    final response = await post(
-      uri,
-      headers: {
-        'Content-Type': 'application/json',
-        'x-api-key': _exchangeHelperApiKey,
-      },
-      body: json.encode({'query': query}),
-    );
+    final response = await post(uri,
+        headers: {'Content-Type': 'application/json', 'x-api-key': _exchangeHelperApiKey},
+        body: json.encode({'query': query}));
 
     if (response.statusCode == 200) {
       return (jsonDecode(response.body) as Map<String, dynamic>)['signature'] as String;
@@ -94,85 +99,195 @@ class MoonPayProvider extends BuyProvider {
     }
   }
 
-  Future<Uri> requestSellMoonPayUrl({
-    required CryptoCurrency currency,
-    required String refundWalletAddress,
-    required SettingsStore settingsStore,
-  }) async {
-    final params = {
-      'theme': themeToMoonPayTheme(settingsStore.currentTheme),
-      'language': settingsStore.languageCode,
-      'colorCode': settingsStore.currentTheme.type == ThemeType.dark
-          ? '#${Palette.blueCraiola.value.toRadixString(16).substring(2, 8)}'
-          : '#${Palette.moderateSlateBlue.value.toRadixString(16).substring(2, 8)}',
-      'defaultCurrencyCode': _normalizeCurrency(currency),
-      'refundWalletAddress': refundWalletAddress,
-    };
+  Future<Map<String, dynamic>> fetchFiatCredentials(
+      String fiatCurrency, String cryptocurrency, String? paymentMethod) async {
+    final params = {'baseCurrencyCode': fiatCurrency.toLowerCase(), 'apiKey': _apiKey};
 
-    if (_apiKey.isNotEmpty) {
-      params['apiKey'] = _apiKey;
+    if (paymentMethod != null) params['paymentMethod'] = paymentMethod;
+
+    final path = '$_currenciesPath/${cryptocurrency.toLowerCase()}/limits';
+    final url = Uri.https(_baseUrl, path, params);
+
+    try {
+      final response = await get(url, headers: {'accept': 'application/json'});
+      if (response.statusCode == 200) {
+        return jsonDecode(response.body) as Map<String, dynamic>;
+      } else {
+        print('MoonPay does not support fiat: $fiatCurrency');
+        return {};
+      }
+    } catch (e) {
+      print('MoonPay Error fetching fiat currencies: $e');
+      return {};
     }
-
-    final originalUri = Uri.https(
-      baseSellUrl,
-      '',
-      params,
-    );
-
-    if (isTestEnvironment) {
-      return originalUri;
-    }
-
-    final signature = await getMoonpaySignature('?${originalUri.query}');
-
-    final query = Map<String, dynamic>.from(originalUri.queryParameters);
-    query['signature'] = signature;
-    final signedUri = originalUri.replace(queryParameters: query);
-    return signedUri;
   }
 
-  // BUY:
-  static const _currenciesSuffix = '/v3/currencies';
-  static const _quoteSuffix = '/buy_quote';
-  static const _transactionsSuffix = '/v1/transactions';
-  static const _ipAddressSuffix = '/v4/ip_address';
+  Future<List<PaymentMethod>> getAvailablePaymentTypes(
+      String fiatCurrency, String cryptoCurrency, bool isBuyAction) async {
+    final List<PaymentMethod> paymentMethods = [];
+
+    if (isBuyAction) {
+      final fiatBuyCredentials = await fetchFiatCredentials(fiatCurrency, cryptoCurrency, null);
+      if (fiatBuyCredentials.isNotEmpty) {
+        final paymentMethod = fiatBuyCredentials['paymentMethod'] as String?;
+        paymentMethods.add(PaymentMethod.fromMoonPayJson(
+            fiatBuyCredentials, _getPaymentTypeByString(paymentMethod)));
+        return paymentMethods;
+      }
+    }
+
+    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 {
+    String? paymentMethod;
+
+    if (paymentType != null && paymentType != PaymentType.all) {
+      paymentMethod = normalizePaymentMethod(paymentType);
+      if (paymentMethod == null) paymentMethod = paymentType.name;
+    } else {
+      paymentMethod = 'credit_debit_card';
+    }
+
+    final action = isBuyAction ? 'buy' : 'sell';
+
+    final formattedCryptoCurrency = _normalizeCurrency(cryptoCurrency);
+    final baseCurrencyCode =
+        isBuyAction ? fiatCurrency.name.toLowerCase() : cryptoCurrency.title.toLowerCase();
 
-  Future<Uri> requestBuyMoonPayUrl({
-    required CryptoCurrency currency,
-    required SettingsStore settingsStore,
-    required String walletAddress,
-    String? amount,
-  }) async {
     final params = {
-      'theme': themeToMoonPayTheme(settingsStore.currentTheme),
-      'language': settingsStore.languageCode,
-      'colorCode': settingsStore.currentTheme.type == ThemeType.dark
+      'baseCurrencyCode': baseCurrencyCode,
+      'baseCurrencyAmount': amount.toString(),
+      'amount': amount.toString(),
+      'paymentMethod': paymentMethod,
+      'areFeesIncluded': 'false',
+      'apiKey': _apiKey
+    };
+
+    log('MoonPay: Fetching $action quote: ${isBuyAction ? formattedCryptoCurrency : fiatCurrency.name.toLowerCase()} -> ${isBuyAction ? baseCurrencyCode : formattedCryptoCurrency}, amount: $amount, paymentMethod: $paymentMethod');
+
+    final quotePath = isBuyAction ? _buyQuote : _sellQuote;
+
+    final path = '$_currenciesPath/$formattedCryptoCurrency$quotePath';
+    final url = Uri.https(_baseUrl, path, params);
+    try {
+      final response = await get(url);
+
+      if (response.statusCode == 200) {
+        final data = jsonDecode(response.body) as Map<String, dynamic>;
+
+        // Check if the response is for the correct fiat currency
+        if (isBuyAction) {
+          final fiatCurrencyCode = data['baseCurrencyCode'] as String?;
+          if (fiatCurrencyCode == null || fiatCurrencyCode != fiatCurrency.name.toLowerCase())
+            return null;
+        } else {
+          final quoteCurrency = data['quoteCurrency'] as Map<String, dynamic>?;
+          if (quoteCurrency == null || quoteCurrency['code'] != fiatCurrency.name.toLowerCase())
+            return null;
+        }
+
+        final paymentMethods = data['paymentMethod'] as String?;
+        final quote =
+            Quote.fromMoonPayJson(data, isBuyAction, _getPaymentTypeByString(paymentMethods));
+
+        quote.setFiatCurrency = fiatCurrency;
+        quote.setCryptoCurrency = cryptoCurrency;
+
+        return [quote];
+      } else {
+        print('Moon Pay: Error fetching buy quote: ');
+        return null;
+      }
+    } catch (e) {
+      print('Moon Pay: Error fetching buy quote: $e');
+      return null;
+    }
+  }
+
+  @override
+  Future<void>? launchProvider(
+      {required BuildContext context,
+      required Quote quote,
+      required double amount,
+      required bool isBuyAction,
+      required String cryptoCurrencyAddress,
+      String? countryCode}) async {
+
+    final Map<String, String> params = {
+      'theme': themeToMoonPayTheme(_settingsStore.currentTheme),
+      'language': _settingsStore.languageCode,
+      'colorCode': _settingsStore.currentTheme.type == ThemeType.dark
           ? '#${Palette.blueCraiola.value.toRadixString(16).substring(2, 8)}'
           : '#${Palette.moderateSlateBlue.value.toRadixString(16).substring(2, 8)}',
-      'baseCurrencyCode': settingsStore.fiatCurrency.title,
-      'baseCurrencyAmount': amount ?? '0',
-      'currencyCode': _normalizeCurrency(currency),
-      'walletAddress': walletAddress,
+      'baseCurrencyCode': isBuyAction ? quote.fiatCurrency.name : quote.cryptoCurrency.name,
+      'baseCurrencyAmount': amount.toString(),
+      'walletAddress': cryptoCurrencyAddress,
       'lockAmount': 'false',
       'showAllCurrencies': 'false',
       'showWalletAddressForm': 'false',
-      'enabledPaymentMethods':
-          'credit_debit_card,apple_pay,google_pay,samsung_pay,sepa_bank_transfer,gbp_bank_transfer,gbp_open_banking_payment',
+      if (isBuyAction)
+        'enabledPaymentMethods': normalizePaymentMethod(quote.paymentType) ??
+            'credit_debit_card,apple_pay,google_pay,samsung_pay,sepa_bank_transfer,gbp_bank_transfer,gbp_open_banking_payment',
+      if (!isBuyAction) 'refundWalletAddress': cryptoCurrencyAddress
     };
 
-    if (_apiKey.isNotEmpty) {
-      params['apiKey'] = _apiKey;
-    }
+    if (isBuyAction) params['currencyCode'] = quote.cryptoCurrency.name;
+    if (!isBuyAction) params['quoteCurrencyCode'] = quote.cryptoCurrency.name;
 
-    final originalUri = Uri.https(
-      baseBuyUrl,
-      '',
-      params,
-    );
+    try {
+      {
+        final uri = await requestMoonPayUrl(
+            walletAddress: cryptoCurrencyAddress,
+            settingsStore: _settingsStore,
+            isBuyAction: isBuyAction,
+            amount: amount.toString(),
+            params: params);
 
-    if (isTestEnvironment) {
-      return originalUri;
+        if (await canLaunchUrl(uri)) {
+          await launchUrl(uri, mode: LaunchMode.externalApplication);
+        } else {
+          throw Exception('Could not launch URL');
+        }
+      }
+    } catch (e) {
+      if (context.mounted) {
+        await showDialog<void>(
+          context: context,
+          builder: (BuildContext context) {
+            return AlertWithOneAction(
+              alertTitle: 'MoonPay',
+              alertContent: 'The MoonPay service is currently unavailable: $e',
+              buttonText: S.of(context).ok,
+              buttonAction: () => Navigator.of(context).pop(),
+            );
+          },
+        );
+      }
     }
+  }
+
+  Future<Uri> requestMoonPayUrl({
+    required String walletAddress,
+    required SettingsStore settingsStore,
+    required bool isBuyAction,
+    required Map<String, String> params,
+    String? amount,
+  }) async {
+    if (_apiKey.isNotEmpty) params['apiKey'] = _apiKey;
+
+    final baseUrl = isBuyAction ? baseBuyUrl : baseSellUrl;
+    final originalUri = Uri.https(baseUrl, '', params);
+
+    if (isTestEnvironment) return originalUri;
 
     final signature = await getMoonpaySignature('?${originalUri.query}');
     final query = Map<String, dynamic>.from(originalUri.queryParameters);
@@ -181,33 +296,6 @@ class MoonPayProvider extends BuyProvider {
     return signedUri;
   }
 
-  Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
-    final url = _apiUrl +
-        _currenciesSuffix +
-        '/$currencyCode' +
-        _quoteSuffix +
-        '/?apiKey=' +
-        _apiKey +
-        '&baseCurrencyAmount=' +
-        amount +
-        '&baseCurrencyCode=' +
-        sourceCurrency.toLowerCase();
-    final uri = Uri.parse(url);
-    final response = await get(uri);
-
-    if (response.statusCode != 200) {
-      throw BuyException(title: providerDescription, content: 'Quote is not found!');
-    }
-
-    final responseJSON = json.decode(response.body) as Map<String, dynamic>;
-    final sourceAmount = responseJSON['totalAmount'] as double;
-    final destAmount = responseJSON['quoteCurrencyAmount'] as double;
-    final minSourceAmount = responseJSON['baseCurrency']['minAmount'] as int;
-
-    return BuyAmount(
-        sourceAmount: sourceAmount, destAmount: destAmount, minAmount: minSourceAmount);
-  }
-
   Future<Order> findOrderById(String id) async {
     final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey;
     final uri = Uri.parse(url);
@@ -235,74 +323,83 @@ class MoonPayProvider extends BuyProvider {
         walletId: wallet.id);
   }
 
-  static Future<bool> onEnabled() async {
-    final url = _apiUrl + _ipAddressSuffix + '?apiKey=' + _apiKey;
-    var isBuyEnable = false;
-    final uri = Uri.parse(url);
-    final response = await get(uri);
-
-    try {
-      final responseJSON = json.decode(response.body) as Map<String, dynamic>;
-      isBuyEnable = responseJSON['isBuyAllowed'] as bool;
-    } catch (e) {
-      isBuyEnable = false;
-      print(e.toString());
-    }
-
-    return isBuyEnable;
-  }
-
-  @override
-  Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
-    try {
-      late final Uri uri;
-      if (isBuyAction ?? true) {
-        uri = await requestBuyMoonPayUrl(
-          currency: wallet.currency,
-          walletAddress: wallet.walletAddresses.address,
-          settingsStore: _settingsStore,
-        );
-      } else {
-        uri = await requestSellMoonPayUrl(
-          currency: wallet.currency,
-          refundWalletAddress: wallet.walletAddresses.address,
-          settingsStore: _settingsStore,
-        );
-      }
-
-      if (await canLaunchUrl(uri)) {
-        if (DeviceInfo.instance.isMobile) {
-          Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]);
-        } else {
-          await launchUrl(uri, mode: LaunchMode.externalApplication);
-        }
-      } else {
-        throw Exception('Could not launch URL');
-      }
-    } catch (e) {
-      if (context.mounted) {
-        await showDialog<void>(
-          context: context,
-          builder: (BuildContext context) {
-            return AlertWithOneAction(
-              alertTitle: 'MoonPay',
-              alertContent: 'The MoonPay service is currently unavailable: $e',
-              buttonText: S.of(context).ok,
-              buttonAction: () => Navigator.of(context).pop(),
-            );
-          },
-        );
-      }
-    }
-  }
-
   String _normalizeCurrency(CryptoCurrency currency) {
-    if (currency == CryptoCurrency.maticpoly) {
-      return "POL_POLYGON";
-    } else if (currency == CryptoCurrency.matic) {
-      return "POL";
+    if (currency.tag == 'POLY') {
+      return '${currency.title.toLowerCase()}_polygon';
+    }
+
+    if (currency.tag == 'TRX') {
+      return '${currency.title.toLowerCase()}_trx';
     }
 
     return currency.toString().toLowerCase();
   }
+
+  String? normalizePaymentMethod(PaymentType paymentMethod) {
+    switch (paymentMethod) {
+      case PaymentType.creditCard:
+        return 'credit_debit_card';
+      case PaymentType.debitCard:
+        return 'credit_debit_card';
+      case PaymentType.ach:
+        return 'ach_bank_transfer';
+      case PaymentType.applePay:
+        return 'apple_pay';
+      case PaymentType.googlePay:
+        return 'google_pay';
+      case PaymentType.sepa:
+        return 'sepa_bank_transfer';
+      case PaymentType.paypal:
+        return 'paypal';
+      case PaymentType.sepaOpenBankingPayment:
+        return 'sepa_open_banking_payment';
+      case PaymentType.gbpOpenBankingPayment:
+        return 'gbp_open_banking_payment';
+      case PaymentType.lowCostAch:
+        return 'low_cost_ach';
+      case PaymentType.mobileWallet:
+        return 'mobile_wallet';
+      case PaymentType.pixInstantPayment:
+        return 'pix_instant_payment';
+      case PaymentType.yellowCardBankTransfer:
+        return 'yellow_card_bank_transfer';
+      case PaymentType.fiatBalance:
+        return 'fiat_balance';
+      default:
+        return null;
+    }
+  }
+
+  PaymentType _getPaymentTypeByString(String? paymentMethod) {
+    switch (paymentMethod) {
+      case 'ach_bank_transfer':
+        return PaymentType.ach;
+      case 'apple_pay':
+        return PaymentType.applePay;
+      case 'credit_debit_card':
+        return PaymentType.creditCard;
+      case 'fiat_balance':
+        return PaymentType.fiatBalance;
+      case 'gbp_open_banking_payment':
+        return PaymentType.gbpOpenBankingPayment;
+      case 'google_pay':
+        return PaymentType.googlePay;
+      case 'low_cost_ach':
+        return PaymentType.lowCostAch;
+      case 'mobile_wallet':
+        return PaymentType.mobileWallet;
+      case 'paypal':
+        return PaymentType.paypal;
+      case 'pix_instant_payment':
+        return PaymentType.pixInstantPayment;
+      case 'sepa_bank_transfer':
+        return PaymentType.sepa;
+      case 'sepa_open_banking_payment':
+        return PaymentType.sepaOpenBankingPayment;
+      case 'yellow_card_bank_transfer':
+        return PaymentType.yellowCardBankTransfer;
+      default:
+        return PaymentType.all;
+    }
+  }
 }
diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart
index 1f1c86962..ee9c9bb74 100644
--- a/lib/buy/onramper/onramper_buy_provider.dart
+++ b/lib/buy/onramper/onramper_buy_provider.dart
@@ -1,13 +1,19 @@
+import 'dart:convert';
+import 'dart:developer';
+
 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/generated/i18n.dart';
-import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/store/settings_store.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
-import 'package:cake_wallet/utils/device_info.dart';
 import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/currency.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:flutter/material.dart';
+import 'package:http/http.dart' as http;
 import 'package:url_launcher/url_launcher.dart';
 
 class OnRamperBuyProvider extends BuyProvider {
@@ -16,9 +22,15 @@ class OnRamperBuyProvider extends BuyProvider {
       : super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: null);
 
   static const _baseUrl = 'buy.onramper.com';
+  static const _baseApiUrl = 'api.onramper.com';
+  static const quotes = '/quotes';
+  static const paymentTypes = '/payment-types';
+  static const supported = '/supported';
 
   final SettingsStore _settingsStore;
 
+  String get _apiKey => secrets.onramperApiKey;
+
   @override
   String get title => 'Onramper';
 
@@ -31,74 +43,327 @@ class OnRamperBuyProvider extends BuyProvider {
   @override
   String get darkIcon => 'assets/images/onramper_dark.png';
 
-  String get _apiKey => secrets.onramperApiKey;
+  @override
+  bool get isAggregator => true;
 
-  String get _normalizeCryptoCurrency {
-    switch (wallet.currency) {
-      case CryptoCurrency.ltc:
-        return "LTC_LITECOIN";
-      case CryptoCurrency.xmr:
-        return "XMR_MONERO";
-      case CryptoCurrency.bch:
-        return "BCH_BITCOINCASH";
-      case CryptoCurrency.nano:
-        return "XNO_NANO";
-      default:
-        return wallet.currency.title;
+  Future<List<PaymentMethod>> getAvailablePaymentTypes(
+      String fiatCurrency, String cryptoCurrency, bool isBuyAction) async {
+    final params = {
+      'fiatCurrency': fiatCurrency,
+      'type': isBuyAction ? 'buy' : 'sell',
+      'isRecurringPayment': 'false'
+    };
+
+    final url = Uri.https(_baseApiUrl, '$supported$paymentTypes/$fiatCurrency', params);
+
+    try {
+      final response =
+          await http.get(url, headers: {'Authorization': _apiKey, 'accept': 'application/json'});
+
+      if (response.statusCode == 200) {
+        final Map<String, dynamic> data = jsonDecode(response.body) as Map<String, dynamic>;
+        final List<dynamic> message = data['message'] as List<dynamic>;
+        return message
+            .map((item) => PaymentMethod.fromOnramperJson(item as Map<String, dynamic>))
+            .toList();
+      } else {
+        print('Failed to fetch available payment types');
+        return [];
+      }
+    } catch (e) {
+      print('Failed to fetch available payment types: $e');
+      return [];
     }
   }
 
-  String getColorStr(Color color) {
-    return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), "");
+  Future<Map<String, dynamic>> getOnrampMetadata() async {
+    final url = Uri.https(_baseApiUrl, '$supported/onramps/all');
+
+    try {
+      final response =
+          await http.get(url, headers: {'Authorization': _apiKey, 'accept': 'application/json'});
+
+      if (response.statusCode == 200) {
+        final Map<String, dynamic> data = jsonDecode(response.body) as Map<String, dynamic>;
+
+        final List<dynamic> onramps = data['message'] as List<dynamic>;
+
+        final Map<String, dynamic> result = {
+          for (var onramp in onramps)
+            (onramp['id'] as String): {
+              'displayName': onramp['displayName'] as String,
+              'svg': onramp['icons']['svg'] as String
+            }
+        };
+
+        return result;
+      } else {
+        print('Failed to fetch onramp metadata');
+        return {};
+      }
+    } catch (e) {
+      print('Error occurred: $e');
+      return {};
+    }
   }
 
-  Uri requestOnramperUrl(BuildContext context, bool? isBuyAction) {
-    String primaryColor,
-        secondaryColor,
-        primaryTextColor,
-        secondaryTextColor,
-        containerColor,
-        cardColor;
+  @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 {
+    String? paymentMethod;
 
-    primaryColor = getColorStr(Theme.of(context).primaryColor);
-    secondaryColor = getColorStr(Theme.of(context).colorScheme.background);
-    primaryTextColor =
-        getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
-    secondaryTextColor = getColorStr(
-        Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
-    containerColor = getColorStr(Theme.of(context).colorScheme.background);
-    cardColor = getColorStr(Theme.of(context).cardColor);
+    if (paymentType != null && paymentType != PaymentType.all) {
+      paymentMethod = normalizePaymentMethod(paymentType);
+      if (paymentMethod == null) paymentMethod = paymentType.name;
+    }
+
+    final actionType = isBuyAction ? 'buy' : 'sell';
+
+    final normalizedCryptoCurrency = _getNormalizeCryptoCurrency(cryptoCurrency);
+
+    final params = {
+      'amount': amount.toString(),
+      if (paymentMethod != null) 'paymentMethod': paymentMethod,
+      'clientName': 'CakeWallet',
+      'type': actionType,
+      'walletAddress': walletAddress,
+      'isRecurringPayment': 'false',
+      'input': 'source',
+    };
+
+    log('Onramper: Fetching $actionType quote: ${isBuyAction ? normalizedCryptoCurrency : fiatCurrency.name} -> ${isBuyAction ? fiatCurrency.name : normalizedCryptoCurrency}, amount: $amount, paymentMethod: $paymentMethod');
+
+    final sourceCurrency = isBuyAction ? fiatCurrency.name : normalizedCryptoCurrency;
+    final destinationCurrency = isBuyAction ? normalizedCryptoCurrency : fiatCurrency.name;
+
+    final url = Uri.https(_baseApiUrl, '$quotes/${sourceCurrency}/${destinationCurrency}', params);
+    final headers = {'Authorization': _apiKey, 'accept': 'application/json'};
+
+    try {
+      final response = await http.get(url, headers: headers);
+
+      if (response.statusCode == 200) {
+        final data = jsonDecode(response.body) as List<dynamic>;
+        if (data.isEmpty) return null;
+
+        List<Quote> validQuotes = [];
+
+        final onrampMetadata = await getOnrampMetadata();
+
+        for (var item in data) {
+
+          if (item['errors'] != null) continue;
+
+          final paymentMethod = (item as Map<String, dynamic>)['paymentMethod'] as String;
+
+          final rampId = item['ramp'] as String?;
+          final rampMetaData = onrampMetadata[rampId] as Map<String, dynamic>?;
+
+          if (rampMetaData == null) continue;
+
+          final quote = Quote.fromOnramperJson(
+              item, isBuyAction, onrampMetadata, _getPaymentTypeByString(paymentMethod));
+          quote.setFiatCurrency = fiatCurrency;
+          quote.setCryptoCurrency = cryptoCurrency;
+          validQuotes.add(quote);
+        }
+
+        if (validQuotes.isEmpty) return null;
+
+        return validQuotes;
+      } else {
+        print('Onramper: Failed to fetch rate');
+        return null;
+      }
+    } catch (e) {
+      print('Onramper: Failed to fetch rate $e');
+      return null;
+    }
+  }
+
+  Future<void>? launchProvider(
+      {required BuildContext context,
+      required Quote quote,
+      required double amount,
+      required bool isBuyAction,
+      required String cryptoCurrencyAddress,
+      String? countryCode}) async {
+    final actionType = isBuyAction ? 'buy' : 'sell';
+    final prefix = actionType == 'sell' ? actionType + '_' : '';
+
+    final primaryColor = getColorStr(Theme.of(context).primaryColor);
+    final secondaryColor = getColorStr(Theme.of(context).colorScheme.background);
+    final primaryTextColor = getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
+    final secondaryTextColor =
+        getColorStr(Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
+    final containerColor = getColorStr(Theme.of(context).colorScheme.background);
+    var cardColor = getColorStr(Theme.of(context).cardColor);
 
     if (_settingsStore.currentTheme.title == S.current.high_contrast_theme) {
       cardColor = getColorStr(Colors.white);
     }
 
-    final networkName =
-        wallet.currency.fullName?.toUpperCase().replaceAll(" ", "");
+    final defaultCrypto = _getNormalizeCryptoCurrency(quote.cryptoCurrency);
 
-    return Uri.https(_baseUrl, '', <String, dynamic>{
+    final paymentMethod = normalizePaymentMethod(quote.paymentType);
+
+    final uri = Uri.https(_baseUrl, '', {
       'apiKey': _apiKey,
-      'defaultCrypto': _normalizeCryptoCurrency,
-      'sell_defaultCrypto': _normalizeCryptoCurrency,
-      'networkWallets': '${networkName}:${wallet.walletAddresses.address}',
+      'mode': actionType,
+      '${prefix}defaultFiat': quote.fiatCurrency.name,
+      '${prefix}defaultCrypto': quote.cryptoCurrency.name,
+      '${prefix}defaultAmount': amount.toString(),
+      if (paymentMethod != null) '${prefix}defaultPaymentMethod': paymentMethod,
+      'onlyOnramps': quote.rampId,
+      'networkWallets': '$defaultCrypto:$cryptoCurrencyAddress',
+      'walletAddress': cryptoCurrencyAddress,
       'supportSwap': "false",
       'primaryColor': primaryColor,
       'secondaryColor': secondaryColor,
+      'containerColor': containerColor,
       'primaryTextColor': primaryTextColor,
       'secondaryTextColor': secondaryTextColor,
-      'containerColor': containerColor,
       'cardColor': cardColor,
-      'mode': isBuyAction == true ? 'buy' : 'sell',
     });
-  }
 
-  Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
-    final uri = requestOnramperUrl(context, isBuyAction);
-    if (DeviceInfo.instance.isMobile) {
-      Navigator.of(context)
-          .pushNamed(Routes.webViewPage, arguments: [title, uri]);
+    if (await canLaunchUrl(uri)) {
+      await launchUrl(uri, mode: LaunchMode.externalApplication);
     } else {
-      await launchUrl(uri);
+      throw Exception('Could not launch URL');
     }
   }
+
+  List<CryptoCurrency> mainCurrency = [
+    CryptoCurrency.btc,
+    CryptoCurrency.eth,
+    CryptoCurrency.sol,
+  ];
+
+  String _tagToNetwork(String tag) {
+    switch (tag) {
+      case 'OMNI':
+        return tag;
+      case 'POL':
+        return 'POLYGON';
+      default:
+        return CryptoCurrency.fromString(tag).fullName ?? tag;
+    }
+  }
+
+  String _getNormalizeCryptoCurrency(Currency currency) {
+    if (currency is CryptoCurrency) {
+      if (!mainCurrency.contains(currency)) {
+        final network = currency.tag == null ? currency.fullName : _tagToNetwork(currency.tag!);
+        return '${currency.title}_${network?.replaceAll(' ', '')}'.toUpperCase();
+      }
+      return currency.title.toUpperCase();
+    }
+    return currency.name.toUpperCase();
+  }
+
+  String? normalizePaymentMethod(PaymentType paymentType) {
+    switch (paymentType) {
+      case PaymentType.bankTransfer:
+        return 'banktransfer';
+      case PaymentType.creditCard:
+        return 'creditcard';
+      case PaymentType.debitCard:
+        return 'debitcard';
+      case PaymentType.applePay:
+        return 'applepay';
+      case PaymentType.googlePay:
+        return 'googlepay';
+      case PaymentType.revolutPay:
+        return 'revolutpay';
+      case PaymentType.neteller:
+        return 'neteller';
+      case PaymentType.skrill:
+        return 'skrill';
+      case PaymentType.sepa:
+        return 'sepabanktransfer';
+      case PaymentType.sepaInstant:
+        return 'sepainstant';
+      case PaymentType.ach:
+        return 'ach';
+      case PaymentType.achInstant:
+        return 'iach';
+      case PaymentType.Khipu:
+        return 'khipu';
+      case PaymentType.palomaBanktTansfer:
+        return 'palomabanktransfer';
+      case PaymentType.ovo:
+        return 'ovo';
+      case PaymentType.zaloPay:
+        return 'zalopay';
+      case PaymentType.zaloBankTransfer:
+        return 'zalobanktransfer';
+      case PaymentType.gcash:
+        return 'gcash';
+      case PaymentType.imps:
+        return 'imps';
+      case PaymentType.dana:
+        return 'dana';
+      case PaymentType.ideal:
+        return 'ideal';
+      default:
+        return null;
+    }
+  }
+
+  PaymentType _getPaymentTypeByString(String paymentMethod) {
+    switch (paymentMethod.toLowerCase()) {
+      case 'banktransfer':
+        return PaymentType.bankTransfer;
+      case 'creditcard':
+        return PaymentType.creditCard;
+      case 'debitcard':
+        return PaymentType.debitCard;
+      case 'applepay':
+        return PaymentType.applePay;
+      case 'googlepay':
+        return PaymentType.googlePay;
+      case 'revolutpay':
+        return PaymentType.revolutPay;
+      case 'neteller':
+        return PaymentType.neteller;
+      case 'skrill':
+        return PaymentType.skrill;
+      case 'sepabanktransfer':
+        return PaymentType.sepa;
+      case 'sepainstant':
+        return PaymentType.sepaInstant;
+      case 'ach':
+        return PaymentType.ach;
+      case 'iach':
+        return PaymentType.achInstant;
+      case 'khipu':
+        return PaymentType.Khipu;
+      case 'palomabanktransfer':
+        return PaymentType.palomaBanktTansfer;
+      case 'ovo':
+        return PaymentType.ovo;
+      case 'zalopay':
+        return PaymentType.zaloPay;
+      case 'zalobanktransfer':
+        return PaymentType.zaloBankTransfer;
+      case 'gcash':
+        return PaymentType.gcash;
+      case 'imps':
+        return PaymentType.imps;
+      case 'dana':
+        return PaymentType.dana;
+      case 'ideal':
+        return PaymentType.ideal;
+      default:
+        return PaymentType.all;
+    }
+  }
+
+  String getColorStr(Color color) => color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), "");
 }
diff --git a/lib/buy/payment_method.dart b/lib/buy/payment_method.dart
new file mode 100644
index 000000000..cf85c441b
--- /dev/null
+++ b/lib/buy/payment_method.dart
@@ -0,0 +1,287 @@
+import 'dart:ui';
+
+import 'package:cake_wallet/core/selectable_option.dart';
+
+enum PaymentType {
+  all,
+  bankTransfer,
+  creditCard,
+  debitCard,
+  applePay,
+  googlePay,
+  revolutPay,
+  neteller,
+  skrill,
+  sepa,
+  sepaInstant,
+  ach,
+  achInstant,
+  Khipu,
+  palomaBanktTansfer,
+  ovo,
+  zaloPay,
+  zaloBankTransfer,
+  gcash,
+  imps,
+  dana,
+  ideal,
+  paypal,
+  sepaOpenBankingPayment,
+  gbpOpenBankingPayment,
+  lowCostAch,
+  mobileWallet,
+  pixInstantPayment,
+  yellowCardBankTransfer,
+  fiatBalance,
+  bancontact,
+}
+
+extension PaymentTypeTitle on PaymentType {
+  String? get title {
+    switch (this) {
+      case PaymentType.all:
+        return 'All Payment Methods';
+      case PaymentType.bankTransfer:
+        return 'Bank Transfer';
+      case PaymentType.creditCard:
+        return 'Credit Card';
+      case PaymentType.debitCard:
+        return 'Debit Card';
+      case PaymentType.applePay:
+        return 'Apple Pay';
+      case PaymentType.googlePay:
+        return 'Google Pay';
+      case PaymentType.revolutPay:
+        return 'Revolut Pay';
+      case PaymentType.neteller:
+        return 'Neteller';
+      case PaymentType.skrill:
+        return 'Skrill';
+      case PaymentType.sepa:
+        return 'SEPA';
+      case PaymentType.sepaInstant:
+        return 'SEPA Instant';
+      case PaymentType.ach:
+        return 'ACH';
+      case PaymentType.achInstant:
+        return 'ACH Instant';
+      case PaymentType.Khipu:
+        return 'Khipu';
+      case PaymentType.palomaBanktTansfer:
+        return 'Paloma Bank Transfer';
+      case PaymentType.ovo:
+        return 'OVO';
+      case PaymentType.zaloPay:
+        return 'Zalo Pay';
+      case PaymentType.zaloBankTransfer:
+        return 'Zalo Bank Transfer';
+      case PaymentType.gcash:
+        return 'GCash';
+      case PaymentType.imps:
+        return 'IMPS';
+      case PaymentType.dana:
+        return 'DANA';
+      case PaymentType.ideal:
+        return 'iDEAL';
+      case PaymentType.paypal:
+        return 'PayPal';
+      case PaymentType.sepaOpenBankingPayment:
+        return 'SEPA Open Banking Payment';
+      case PaymentType.gbpOpenBankingPayment:
+        return 'GBP Open Banking Payment';
+      case PaymentType.lowCostAch:
+        return 'Low Cost ACH';
+      case PaymentType.mobileWallet:
+        return 'Mobile Wallet';
+      case PaymentType.pixInstantPayment:
+        return 'PIX Instant Payment';
+      case PaymentType.yellowCardBankTransfer:
+        return 'Yellow Card Bank Transfer';
+      case PaymentType.fiatBalance:
+        return 'Fiat Balance';
+      case PaymentType.bancontact:
+        return 'Bancontact';
+      default:
+        return null;
+    }
+  }
+
+  String? get lightIconPath {
+    switch (this) {
+      case PaymentType.all:
+        return 'assets/images/usd_round_light.svg';
+      case PaymentType.creditCard:
+      case PaymentType.debitCard:
+      case PaymentType.yellowCardBankTransfer:
+        return 'assets/images/card.svg';
+      case PaymentType.bankTransfer:
+        return 'assets/images/bank_light.svg';
+      case PaymentType.skrill:
+        return 'assets/images/skrill.svg';
+      case PaymentType.applePay:
+        return 'assets/images/apple_pay_round_light.svg';
+      default:
+        return null;
+    }
+  }
+
+  String? get darkIconPath {
+    switch (this) {
+      case PaymentType.all:
+        return 'assets/images/usd_round_dark.svg';
+      case PaymentType.creditCard:
+      case PaymentType.debitCard:
+      case PaymentType.yellowCardBankTransfer:
+        return 'assets/images/card_dark.svg';
+      case PaymentType.bankTransfer:
+        return 'assets/images/bank_dark.svg';
+      case PaymentType.skrill:
+        return 'assets/images/skrill.svg';
+      case PaymentType.applePay:
+        return 'assets/images/apple_pay_round_dark.svg';
+      default:
+        return null;
+    }
+  }
+
+  String? get description {
+    switch (this) {
+      default:
+        return null;
+    }
+  }
+}
+
+class PaymentMethod extends SelectableOption {
+  PaymentMethod({
+    required this.paymentMethodType,
+    required this.customTitle,
+    required this.customIconPath,
+    this.customDescription,
+  }) : super(title: paymentMethodType.title ?? customTitle);
+
+  final PaymentType paymentMethodType;
+  final String customTitle;
+  final String customIconPath;
+  final String? customDescription;
+  bool isSelected = false;
+
+  @override
+  String? get description => paymentMethodType.description ?? customDescription;
+
+  @override
+  String get lightIconPath => paymentMethodType.lightIconPath ?? customIconPath;
+
+  @override
+  String get darkIconPath => paymentMethodType.darkIconPath ?? customIconPath;
+
+  @override
+  bool get isOptionSelected => isSelected;
+
+  factory PaymentMethod.all() {
+    return PaymentMethod(
+        paymentMethodType: PaymentType.all,
+        customTitle: 'All Payment Methods',
+        customIconPath: 'assets/images/dollar_coin.svg');
+  }
+
+  factory PaymentMethod.fromOnramperJson(Map<String, dynamic> json) {
+    final type = PaymentMethod.getPaymentTypeId(json['paymentTypeId'] as String?);
+    return PaymentMethod(
+        paymentMethodType: type,
+        customTitle: json['name'] as String? ?? 'Unknown',
+        customIconPath: json['icon'] as String? ?? 'assets/images/card.png',
+        customDescription: json['description'] as String?);
+  }
+
+  factory PaymentMethod.fromDFX(String paymentMethod, PaymentType paymentType) {
+    return PaymentMethod(
+        paymentMethodType: paymentType,
+        customTitle: paymentMethod,
+        customIconPath: 'assets/images/card.png');
+  }
+
+  factory PaymentMethod.fromMoonPayJson(Map<String, dynamic> json, PaymentType paymentType) {
+    return PaymentMethod(
+        paymentMethodType: paymentType,
+        customTitle: json['paymentMethod'] as String,
+        customIconPath: 'assets/images/card.png');
+  }
+
+  factory PaymentMethod.fromMeldJson(Map<String, dynamic> json) {
+    final type = PaymentMethod.getPaymentTypeId(json['paymentMethod'] as String?);
+    final logos = json['logos'] as Map<String, dynamic>;
+    return PaymentMethod(
+        paymentMethodType: type,
+        customTitle: json['name'] as String? ?? 'Unknown',
+        customIconPath: logos['dark'] as String? ?? 'assets/images/card.png',
+        customDescription: json['description'] as String?);
+  }
+
+  static PaymentType getPaymentTypeId(String? type) {
+    switch (type?.toLowerCase()) {
+      case 'banktransfer':
+      case 'bank':
+      case 'yellow_card_bank_transfer':
+        return PaymentType.bankTransfer;
+      case 'creditcard':
+      case 'card':
+      case 'credit_debit_card':
+        return PaymentType.creditCard;
+      case 'debitcard':
+        return PaymentType.debitCard;
+      case 'applepay':
+      case 'apple_pay':
+        return PaymentType.applePay;
+      case 'googlepay':
+      case 'google_pay':
+        return PaymentType.googlePay;
+      case 'revolutpay':
+        return PaymentType.revolutPay;
+      case 'neteller':
+        return PaymentType.neteller;
+      case 'skrill':
+        return PaymentType.skrill;
+      case 'sepabanktransfer':
+      case 'sepa':
+      case 'sepa_bank_transfer':
+        return PaymentType.sepa;
+      case 'sepainstant':
+      case 'sepa_instant':
+        return PaymentType.sepaInstant;
+      case 'ach':
+      case 'ach_bank_transfer':
+        return PaymentType.ach;
+      case 'iach':
+      case 'instant_ach':
+        return PaymentType.achInstant;
+      case 'khipu':
+        return PaymentType.Khipu;
+      case 'palomabanktransfer':
+        return PaymentType.palomaBanktTansfer;
+      case 'ovo':
+        return PaymentType.ovo;
+      case 'zalopay':
+        return PaymentType.zaloPay;
+      case 'zalobanktransfer':
+      case 'za_bank_transfer':
+        return PaymentType.zaloBankTransfer;
+      case 'gcash':
+        return PaymentType.gcash;
+      case 'imps':
+        return PaymentType.imps;
+      case 'dana':
+        return PaymentType.dana;
+      case 'ideal':
+        return PaymentType.ideal;
+      case 'paypal':
+        return PaymentType.paypal;
+      case 'sepa_open_banking_payment':
+        return PaymentType.sepaOpenBankingPayment;
+      case 'bancontact':
+        return PaymentType.bancontact;
+      default:
+        return PaymentType.all;
+    }
+  }
+}
diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart
index 2d809772e..e8de5a59c 100644
--- a/lib/buy/robinhood/robinhood_buy_provider.dart
+++ b/lib/buy/robinhood/robinhood_buy_provider.dart
@@ -1,13 +1,18 @@
 import 'dart:convert';
+import 'dart:developer';
 
 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/generated/i18n.dart';
 import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
+import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/material.dart';
@@ -15,7 +20,8 @@ import 'package:http/http.dart' as http;
 import 'package:url_launcher/url_launcher.dart';
 
 class RobinhoodBuyProvider extends BuyProvider {
-  RobinhoodBuyProvider({required WalletBase wallet, bool isTestEnvironment = false, LedgerViewModel? ledgerVM})
+  RobinhoodBuyProvider(
+      {required WalletBase wallet, bool isTestEnvironment = false, LedgerViewModel? ledgerVM})
       : super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: ledgerVM);
 
   static const _baseUrl = 'applink.robinhood.com';
@@ -33,6 +39,9 @@ class RobinhoodBuyProvider extends BuyProvider {
   @override
   String get darkIcon => 'assets/images/robinhood_dark.png';
 
+  @override
+  bool get isAggregator => false;
+
   String get _applicationId => secrets.robinhoodApplicationId;
 
   String get _apiSecret => secrets.exchangeHelperApiKey;
@@ -86,7 +95,13 @@ class RobinhoodBuyProvider extends BuyProvider {
     });
   }
 
-  Future<void> launchProvider(BuildContext context, bool? isBuyAction) async {
+  Future<void>? launchProvider(
+      {required BuildContext context,
+      required Quote quote,
+      required double amount,
+      required bool isBuyAction,
+      required String cryptoCurrencyAddress,
+      String? countryCode}) async {
     if (wallet.isHardwareWallet) {
       if (!ledgerVM!.isConnected) {
         await Navigator.of(context).pushNamed(Routes.connectDevices,
@@ -116,4 +131,87 @@ class RobinhoodBuyProvider extends BuyProvider {
           });
     }
   }
+
+  @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 {
+    String? paymentMethod;
+
+    if (paymentType != null && paymentType != PaymentType.all) {
+      paymentMethod = normalizePaymentMethod(paymentType);
+      if (paymentMethod == null) paymentMethod = paymentType.name;
+    }
+
+    final action = isBuyAction ? 'buy' : 'sell';
+    log('Robinhood: Fetching $action quote: ${isBuyAction ? cryptoCurrency.title : fiatCurrency.name.toUpperCase()} -> ${isBuyAction ? fiatCurrency.name.toUpperCase() : cryptoCurrency.title}, amount: $amount paymentMethod: $paymentMethod');
+
+    final queryParams = {
+      'applicationId': _applicationId,
+      'fiatCode': fiatCurrency.name,
+      'assetCode': cryptoCurrency.title,
+      'fiatAmount': amount.toString(),
+      if (paymentMethod != null) 'paymentMethod': paymentMethod,
+    };
+
+    final uri =
+        Uri.https('api.robinhood.com', '/catpay/v1/${cryptoCurrency.title}/quote/', queryParams);
+
+    try {
+      final response = await http.get(uri, headers: {'accept': 'application/json'});
+      final responseData = jsonDecode(response.body) as Map<String, dynamic>;
+
+      if (response.statusCode == 200) {
+        final paymentType = _getPaymentTypeByString(responseData['paymentMethod'] as String?);
+        final quote = Quote.fromRobinhoodJson(responseData, isBuyAction, paymentType);
+        quote.setFiatCurrency = fiatCurrency;
+        quote.setCryptoCurrency = cryptoCurrency;
+        return [quote];
+      } else {
+        if (responseData.containsKey('message')) {
+          log('Robinhood Error: ${responseData['message']}');
+        } else {
+          print('Robinhood Failed to fetch $action quote: ${response.statusCode}');
+        }
+        return null;
+      }
+    } catch (e) {
+      log('Robinhood: Failed to fetch $action quote: $e');
+      return null;
+    }
+
+    // ● buying_power
+    // ● crypto_balance
+    // ● debit_card
+    // ● bank_transfer
+  }
+
+  String? normalizePaymentMethod(PaymentType paymentMethod) {
+    switch (paymentMethod) {
+      case PaymentType.creditCard:
+        return 'debit_card';
+      case PaymentType.debitCard:
+        return 'debit_card';
+      case PaymentType.bankTransfer:
+        return 'bank_transfer';
+      default:
+        return null;
+    }
+  }
+
+  PaymentType _getPaymentTypeByString(String? paymentMethod) {
+    switch (paymentMethod) {
+      case 'debit_card':
+        return PaymentType.debitCard;
+      case 'bank_transfer':
+        return PaymentType.bankTransfer;
+      default:
+        return PaymentType.all;
+    }
+  }
 }
diff --git a/lib/buy/sell_buy_states.dart b/lib/buy/sell_buy_states.dart
new file mode 100644
index 000000000..26ea20205
--- /dev/null
+++ b/lib/buy/sell_buy_states.dart
@@ -0,0 +1,20 @@
+abstract class PaymentMethodLoadingState {}
+
+class InitialPaymentMethod extends PaymentMethodLoadingState {}
+
+class PaymentMethodLoading extends PaymentMethodLoadingState {}
+
+class PaymentMethodLoaded extends PaymentMethodLoadingState {}
+
+class PaymentMethodFailed extends PaymentMethodLoadingState {}
+
+
+abstract class BuySellQuotLoadingState {}
+
+class InitialBuySellQuotState extends BuySellQuotLoadingState {}
+
+class BuySellQuotLoading extends BuySellQuotLoadingState {}
+
+class BuySellQuotLoaded extends BuySellQuotLoadingState {}
+
+class BuySellQuotFailed extends BuySellQuotLoadingState {}
\ No newline at end of file
diff --git a/lib/buy/wyre/wyre_buy_provider.dart b/lib/buy/wyre/wyre_buy_provider.dart
index e09186ad5..78b109ac0 100644
--- a/lib/buy/wyre/wyre_buy_provider.dart
+++ b/lib/buy/wyre/wyre_buy_provider.dart
@@ -42,6 +42,9 @@ class WyreBuyProvider extends BuyProvider {
   @override
   String get darkIcon => 'assets/images/robinhood_dark.png';
 
+  @override
+  bool get isAggregator => false;
+
   String get trackUrl => isTestEnvironment ? _trackTestUrl : _trackProductUrl;
 
   String baseApiUrl;
@@ -148,10 +151,4 @@ class WyreBuyProvider extends BuyProvider {
         receiveAddress: wallet.walletAddresses.address,
         walletId: wallet.id);
   }
-
-  @override
-  Future<void> launchProvider(BuildContext context, bool? isBuyAction) {
-    // TODO: implement launchProvider
-    throw UnimplementedError();
-  }
 }
diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart
index d65530eb5..992ed6288 100644
--- a/lib/core/backup_service.dart
+++ b/lib/core/backup_service.dart
@@ -268,9 +268,7 @@ class BackupService {
     final currentFiatCurrency = data[PreferencesKey.currentFiatCurrencyKey] as String?;
     final shouldSaveRecipientAddress = data[PreferencesKey.shouldSaveRecipientAddressKey] as bool?;
     final isAppSecure = data[PreferencesKey.isAppSecureKey] as bool?;
-    final disableBuy = data[PreferencesKey.disableBuyKey] as bool?;
-    final disableSell = data[PreferencesKey.disableSellKey] as bool?;
-    final defaultBuyProvider = data[PreferencesKey.defaultBuyProvider] as int?;
+    final disableTradeOption = data[PreferencesKey.disableTradeOption] as bool?;
     final currentTransactionPriorityKeyLegacy =
         data[PreferencesKey.currentTransactionPriorityKeyLegacy] as int?;
     final currentBitcoinElectrumSererId =
@@ -323,14 +321,8 @@ class BackupService {
     if (isAppSecure != null)
       await _sharedPreferences.setBool(PreferencesKey.isAppSecureKey, isAppSecure);
 
-    if (disableBuy != null)
-      await _sharedPreferences.setBool(PreferencesKey.disableBuyKey, disableBuy);
-
-    if (disableSell != null)
-      await _sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell);
-
-    if (defaultBuyProvider != null)
-      await _sharedPreferences.setInt(PreferencesKey.defaultBuyProvider, defaultBuyProvider);
+    if (disableTradeOption != null)
+      await _sharedPreferences.setBool(PreferencesKey.disableTradeOption, disableTradeOption);
 
     if (currentTransactionPriorityKeyLegacy != null)
       await _sharedPreferences.setInt(
@@ -516,10 +508,7 @@ class BackupService {
           _sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey),
       PreferencesKey.shouldSaveRecipientAddressKey:
           _sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey),
-      PreferencesKey.disableBuyKey: _sharedPreferences.getBool(PreferencesKey.disableBuyKey),
-      PreferencesKey.disableSellKey: _sharedPreferences.getBool(PreferencesKey.disableSellKey),
-      PreferencesKey.defaultBuyProvider:
-          _sharedPreferences.getInt(PreferencesKey.defaultBuyProvider),
+      PreferencesKey.disableTradeOption: _sharedPreferences.getBool(PreferencesKey.disableTradeOption),
       PreferencesKey.currentPinLength: _sharedPreferences.getInt(PreferencesKey.currentPinLength),
       PreferencesKey.currentTransactionPriorityKeyLegacy:
           _sharedPreferences.getInt(PreferencesKey.currentTransactionPriorityKeyLegacy),
diff --git a/lib/core/selectable_option.dart b/lib/core/selectable_option.dart
new file mode 100644
index 000000000..0d7511c95
--- /dev/null
+++ b/lib/core/selectable_option.dart
@@ -0,0 +1,47 @@
+abstract class SelectableItem {
+  SelectableItem({required this.title});
+  final String title;
+}
+
+class OptionTitle extends SelectableItem {
+  OptionTitle({required String title}) : super(title: title);
+
+}
+
+abstract class SelectableOption extends SelectableItem {
+  SelectableOption({required String title}) : super(title: title);
+
+  String get lightIconPath;
+
+  String get darkIconPath;
+
+  String? get description => null;
+
+  String? get topLeftSubTitle => null;
+
+  String? get topLeftSubTitleIconPath => null;
+
+  String? get topRightSubTitle => null;
+
+  String? get topRightSubTitleLightIconPath => null;
+
+  String? get topRightSubTitleDarkIconPath => null;
+
+  String? get bottomLeftSubTitle => null;
+
+  String? get bottomLeftSubTitleIconPath => null;
+
+  String? get bottomRightSubTitle => null;
+
+  String? get bottomRightSubTitleLightIconPath => null;
+
+  String? get bottomRightSubTitleDarkIconPath => null;
+
+  List<String> get badges => [];
+
+  bool get isOptionSelected => false;
+
+  set isOptionSelected(bool isSelected) => false;
+}
+
+
diff --git a/lib/di.dart b/lib/di.dart
index 9cff29798..8dd1029a9 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -19,6 +19,7 @@ import 'package:cake_wallet/core/backup_service.dart';
 import 'package:cake_wallet/core/key_service.dart';
 import 'package:cake_wallet/core/new_wallet_type_arguments.dart';
 import 'package:cake_wallet/core/secure_storage.dart';
+import 'package:cake_wallet/core/selectable_option.dart';
 import 'package:cake_wallet/core/totp_request_details.dart';
 import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart';
 import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
@@ -34,6 +35,8 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
 import 'package:cake_wallet/entities/parse_address_from_domain.dart';
 import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
 import 'package:cake_wallet/entities/wallet_manager.dart';
+import 'package:cake_wallet/src/screens/buy/buy_sell_options_page.dart';
+import 'package:cake_wallet/src/screens/buy/payment_method_options_page.dart';
 import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
 import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart';
 import 'package:cake_wallet/src/screens/settings/mweb_node_page.dart';
@@ -61,7 +64,6 @@ import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dar
 import 'package:cake_wallet/src/screens/auth/auth_page.dart';
 import 'package:cake_wallet/src/screens/backup/backup_page.dart';
 import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
-import 'package:cake_wallet/src/screens/buy/buy_options_page.dart';
 import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart';
 import 'package:cake_wallet/src/screens/buy/webview_page.dart';
 import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
@@ -135,6 +137,7 @@ import 'package:cake_wallet/utils/device_info.dart';
 import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart';
 import 'package:cake_wallet/utils/payment_request.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
+import 'package:cake_wallet/view_model/buy/buy_sell_view_model.dart';
 import 'package:cake_wallet/view_model/animated_ur_model.dart';
 import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart';
 import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
@@ -248,6 +251,8 @@ 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/meld/meld_buy_provider.dart';
+import 'src/screens/buy/buy_sell_page.dart';
 import 'cake_pay/cake_pay_payment_credantials.dart';
 
 final getIt = GetIt.instance;
@@ -1004,6 +1009,10 @@ Future<void> setup({
         wallet: getIt.get<AppStore>().wallet!,
       ));
 
+  getIt.registerFactory<MeldBuyProvider>(() => MeldBuyProvider(
+    wallet: getIt.get<AppStore>().wallet!,
+  ));
+
   getIt.registerFactoryParam<WebViewPage, String, Uri>((title, uri) => WebViewPage(title, uri));
 
   getIt.registerFactory<PayfuraBuyProvider>(() => PayfuraBuyProvider(
@@ -1193,8 +1202,25 @@ Future<void> setup({
 
   getIt.registerFactory(() => BuyAmountViewModel());
 
-  getIt.registerFactoryParam<BuySellOptionsPage, bool, void>(
-      (isBuyOption, _) => BuySellOptionsPage(getIt.get<DashboardViewModel>(), isBuyOption));
+  getIt.registerFactory(() => BuySellViewModel(getIt.get<AppStore>()));
+
+  getIt.registerFactory(() => BuySellPage(getIt.get<BuySellViewModel>()));
+
+  getIt.registerFactoryParam<BuyOptionsPage, List<dynamic>, void>((List<dynamic> args, _) {
+    final items = args.first as List<SelectableItem>;
+    final pickAnOption = args[1] as void Function(SelectableOption option)?;
+    final confirmOption = args[2] as void Function(BuildContext contex)?;
+    return BuyOptionsPage(
+        items: items, pickAnOption: pickAnOption, confirmOption: confirmOption);
+  });
+
+  getIt.registerFactoryParam<PaymentMethodOptionsPage, List<dynamic>, void>((List<dynamic> args, _) {
+    final items = args.first as List<SelectableOption>;
+    final pickAnOption = args[1] as void Function(SelectableOption option)?;
+
+    return PaymentMethodOptionsPage(
+        items: items, pickAnOption: pickAnOption);
+  });
 
   getIt.registerFactory(() {
     final wallet = getIt.get<AppStore>().wallet;
diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart
index c1dd71cc9..94be0d2b7 100644
--- a/lib/entities/main_actions.dart
+++ b/lib/entities/main_actions.dart
@@ -23,31 +23,18 @@ class MainActions {
   });
 
   static List<MainActions> all = [
-    buyAction,
+    showWalletsAction,
     receiveAction,
     exchangeAction,
     sendAction,
-    sellAction,
+    tradeAction,
   ];
 
-  static MainActions buyAction = MainActions._(
-    name: (context) => S.of(context).buy,
-    image: 'assets/images/buy.png',
-    isEnabled: (viewModel) => viewModel.isEnabledBuyAction,
-    canShow: (viewModel) => viewModel.hasBuyAction,
+  static MainActions showWalletsAction = MainActions._(
+    name: (context) => S.of(context).wallets,
+    image: 'assets/images/wallet_new.png',
     onTap: (BuildContext context, DashboardViewModel viewModel) async {
-      if (!viewModel.isEnabledBuyAction) {
-        return;
-      }
-
-      final defaultBuyProvider = viewModel.defaultBuyProvider;
-      try {
-        defaultBuyProvider != null
-            ? await defaultBuyProvider.launchProvider(context, true)
-            : await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: true);
-      } catch (e) {
-        await _showErrorDialog(context, defaultBuyProvider.toString(), e.toString());
-      }
+      Navigator.pushNamed(context, Routes.walletList);
     },
   );
 
@@ -79,39 +66,15 @@ class MainActions {
     },
   );
 
-  static MainActions sellAction = MainActions._(
-    name: (context) => S.of(context).sell,
-    image: 'assets/images/sell.png',
-    isEnabled: (viewModel) => viewModel.isEnabledSellAction,
-    canShow: (viewModel) => viewModel.hasSellAction,
-    onTap: (BuildContext context, DashboardViewModel viewModel) async {
-      if (!viewModel.isEnabledSellAction) {
-        return;
-      }
 
-      final defaultSellProvider = viewModel.defaultSellProvider;
-      try {
-        defaultSellProvider != null
-            ? await defaultSellProvider.launchProvider(context, false)
-            : await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: false);
-      } catch (e) {
-        await _showErrorDialog(context, defaultSellProvider.toString(), e.toString());
-      }
+  static MainActions tradeAction = MainActions._(
+    name: (context) => '${S.of(context).buy} / ${S.of(context).sell}',
+    image: 'assets/images/buy_sell.png',
+    isEnabled: (viewModel) => viewModel.isEnabledTradeAction,
+    canShow: (viewModel) => viewModel.hasTradeAction,
+    onTap: (BuildContext context, DashboardViewModel viewModel) async {
+      if (!viewModel.isEnabledTradeAction) return;
+      await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: false);
     },
   );
-
-  static Future<void> _showErrorDialog(
-      BuildContext context, String title, String errorMessage) async {
-    await showPopUp<void>(
-      context: context,
-      builder: (BuildContext context) {
-        return AlertWithOneAction(
-          alertTitle: title,
-          alertContent: errorMessage,
-          buttonText: S.of(context).ok,
-          buttonAction: () => Navigator.of(context).pop(),
-        );
-      },
-    );
-  }
 }
\ No newline at end of file
diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart
index 0bb526e5d..5ed7a7ed6 100644
--- a/lib/entities/preferences_key.dart
+++ b/lib/entities/preferences_key.dart
@@ -21,10 +21,8 @@ class PreferencesKey {
   static const currentBalanceDisplayModeKey = 'current_balance_display_mode';
   static const shouldSaveRecipientAddressKey = 'save_recipient_address';
   static const isAppSecureKey = 'is_app_secure';
-  static const disableBuyKey = 'disable_buy';
-  static const disableSellKey = 'disable_sell';
+  static const disableTradeOption = 'disable_buy';
   static const disableBulletinKey = 'disable_bulletin';
-  static const defaultBuyProvider = 'default_buy_provider';
   static const walletListOrder = 'wallet_list_order';
   static const contactListOrder = 'contact_list_order';
   static const walletListAscending = 'wallet_list_ascending';
diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart
index b9dd4ef2a..42ec74c12 100644
--- a/lib/entities/provider_types.dart
+++ b/lib/entities/provider_types.dart
@@ -1,24 +1,18 @@
 import 'package:cake_wallet/buy/buy_provider.dart';
 import 'package:cake_wallet/buy/dfx/dfx_buy_provider.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';
 import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
 import 'package:cake_wallet/di.dart';
 import 'package:cw_core/wallet_type.dart';
+import 'package:http/http.dart';
 
-enum ProviderType {
-  askEachTime,
-  robinhood,
-  dfx,
-  onramper,
-  moonpay,
-}
+enum ProviderType { robinhood, dfx, onramper, moonpay, meld }
 
 extension ProviderTypeName on ProviderType {
   String get title {
     switch (this) {
-      case ProviderType.askEachTime:
-        return 'Ask each time';
       case ProviderType.robinhood:
         return 'Robinhood Connect';
       case ProviderType.dfx:
@@ -27,13 +21,13 @@ extension ProviderTypeName on ProviderType {
         return 'Onramper';
       case ProviderType.moonpay:
         return 'MoonPay';
+      case ProviderType.meld:
+        return 'Meld';
     }
   }
 
   String get id {
     switch (this) {
-      case ProviderType.askEachTime:
-        return 'ask_each_time_provider';
       case ProviderType.robinhood:
         return 'robinhood_connect_provider';
       case ProviderType.dfx:
@@ -42,6 +36,8 @@ extension ProviderTypeName on ProviderType {
         return 'onramper_provider';
       case ProviderType.moonpay:
         return 'moonpay_provider';
+      case ProviderType.meld:
+        return 'meld_provider';
     }
   }
 }
@@ -52,14 +48,13 @@ class ProvidersHelper {
       case WalletType.nano:
       case WalletType.banano:
       case WalletType.wownero:
-        return [ProviderType.askEachTime, ProviderType.onramper];
+        return [ProviderType.onramper];
       case WalletType.monero:
-        return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx];
+        return [ProviderType.onramper, ProviderType.dfx];
       case WalletType.bitcoin:
       case WalletType.polygon:
       case WalletType.ethereum:
         return [
-          ProviderType.askEachTime,
           ProviderType.onramper,
           ProviderType.dfx,
           ProviderType.robinhood,
@@ -68,10 +63,13 @@ class ProvidersHelper {
       case WalletType.litecoin:
       case WalletType.bitcoinCash:
       case WalletType.solana:
-        return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood, ProviderType.moonpay];
+        return [
+          ProviderType.onramper,
+          ProviderType.robinhood,
+          ProviderType.moonpay
+        ];
       case WalletType.tron:
         return [
-          ProviderType.askEachTime,
           ProviderType.onramper,
           ProviderType.robinhood,
           ProviderType.moonpay,
@@ -88,28 +86,24 @@ class ProvidersHelper {
       case WalletType.ethereum:
       case WalletType.polygon:
         return [
-          ProviderType.askEachTime,
           ProviderType.onramper,
           ProviderType.moonpay,
           ProviderType.dfx,
         ];
       case WalletType.litecoin:
       case WalletType.bitcoinCash:
-        return [ProviderType.askEachTime, ProviderType.moonpay];
+        return [ProviderType.moonpay];
       case WalletType.solana:
         return [
-          ProviderType.askEachTime,
           ProviderType.onramper,
-          ProviderType.robinhood,
           ProviderType.moonpay,
         ];
       case WalletType.tron:
         return [
-          ProviderType.askEachTime,
-          ProviderType.robinhood,
           ProviderType.moonpay,
         ];
       case WalletType.monero:
+        return [ProviderType.dfx];
       case WalletType.nano:
       case WalletType.banano:
       case WalletType.none:
@@ -129,7 +123,9 @@ class ProvidersHelper {
         return getIt.get<OnRamperBuyProvider>();
       case ProviderType.moonpay:
         return getIt.get<MoonPayProvider>();
-      case ProviderType.askEachTime:
+      case ProviderType.meld:
+        return getIt.get<MeldBuyProvider>();
+      default:
         return null;
     }
   }
diff --git a/lib/router.dart b/lib/router.dart
index 4b99aabc0..781a6e057 100644
--- a/lib/router.dart
+++ b/lib/router.dart
@@ -17,8 +17,9 @@ import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dar
 import 'package:cake_wallet/src/screens/auth/auth_page.dart';
 import 'package:cake_wallet/src/screens/backup/backup_page.dart';
 import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
-import 'package:cake_wallet/src/screens/buy/buy_options_page.dart';
+import 'package:cake_wallet/src/screens/buy/buy_sell_options_page.dart';
 import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart';
+import 'package:cake_wallet/src/screens/buy/payment_method_options_page.dart';
 import 'package:cake_wallet/src/screens/buy/webview_page.dart';
 import 'package:cake_wallet/src/screens/cake_pay/auth/cake_pay_account_page.dart';
 import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
@@ -129,7 +130,8 @@ import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
-
+import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
+import 'src/screens/buy/buy_sell_page.dart';
 import 'src/screens/dashboard/pages/nft_import_page.dart';
 
 late RouteSettings currentRouteSettings;
@@ -571,7 +573,15 @@ Route<dynamic> createRoute(RouteSettings settings) {
 
     case Routes.buySellPage:
       final args = settings.arguments as bool;
-      return MaterialPageRoute<void>(builder: (_) => getIt.get<BuySellOptionsPage>(param1: args));
+      return MaterialPageRoute<void>(builder: (_) => getIt.get<BuySellPage>(param1: args));
+
+    case Routes.buyOptionsPage:
+      final args = settings.arguments as List;
+      return MaterialPageRoute<void>(builder: (_) => getIt.get<BuyOptionsPage>(param1: args));
+
+    case Routes.paymentMethodOptionsPage:
+      final args = settings.arguments as List;
+      return MaterialPageRoute<void>(builder: (_) => getIt.get<PaymentMethodOptionsPage>(param1: args));
 
     case Routes.buyWebView:
       final args = settings.arguments as List;
diff --git a/lib/routes.dart b/lib/routes.dart
index 63c41bde5..0b8beb0ea 100644
--- a/lib/routes.dart
+++ b/lib/routes.dart
@@ -59,6 +59,8 @@ class Routes {
   static const supportOtherLinks = '/support/other';
   static const orderDetails = '/order_details';
   static const buySellPage = '/buy_sell_page';
+  static const buyOptionsPage = '/buy_sell_options';
+  static const paymentMethodOptionsPage = '/payment_method_options';
   static const buyWebView = '/buy_web_view';
   static const unspentCoinsList = '/unspent_coins_list';
   static const unspentCoinsDetails = '/unspent_coins_details';
diff --git a/lib/src/screens/InfoPage.dart b/lib/src/screens/Info_page.dart
similarity index 100%
rename from lib/src/screens/InfoPage.dart
rename to lib/src/screens/Info_page.dart
diff --git a/lib/src/screens/buy/buy_options_page.dart b/lib/src/screens/buy/buy_options_page.dart
deleted file mode 100644
index 38f3ed968..000000000
--- a/lib/src/screens/buy/buy_options_page.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cake_wallet/src/screens/base_page.dart';
-import 'package:cake_wallet/src/widgets/option_tile.dart';
-import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
-import 'package:cake_wallet/themes/extensions/option_tile_theme.dart';
-import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
-import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
-import 'package:flutter/material.dart';
-
-class BuySellOptionsPage extends BasePage {
-  BuySellOptionsPage(this.dashboardViewModel, this.isBuyAction);
-
-  final DashboardViewModel dashboardViewModel;
-  final bool isBuyAction;
-
-  @override
-  String get title => isBuyAction ? S.current.buy : S.current.sell;
-
-  @override
-  AppBarStyle get appBarStyle => AppBarStyle.regular;
-
-  @override
-  Widget body(BuildContext context) {
-    final isLightMode = Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
-    final availableProviders = isBuyAction
-        ? dashboardViewModel.availableBuyProviders
-        : dashboardViewModel.availableSellProviders;
-
-    return ScrollableWithBottomSection(
-      content: Container(
-        child: Center(
-          child: ConstrainedBox(
-            constraints: BoxConstraints(maxWidth: 330),
-            child: Column(
-              children: [
-                ...availableProviders.map((provider) {
-                  final icon = Image.asset(
-                    isLightMode ? provider.lightIcon : provider.darkIcon,
-                    height: 40,
-                    width: 40,
-                  );
-
-                  return Padding(
-                    padding: EdgeInsets.only(top: 24),
-                    child: OptionTile(
-                      image: icon,
-                      title: provider.toString(),
-                      description: provider.providerDescription,
-                      onPressed: () => provider.launchProvider(context, isBuyAction),
-                    ),
-                  );
-                }).toList(),
-              ],
-            ),
-          ),
-        ),
-      ),
-      bottomSection: Padding(
-        padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
-        child: Text(
-          isBuyAction
-              ? S.of(context).select_buy_provider_notice
-              : S.of(context).select_sell_provider_notice,
-          textAlign: TextAlign.center,
-          style: TextStyle(
-            fontSize: 14,
-            fontWeight: FontWeight.normal,
-            color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
-          ),
-        ),
-      ),
-    );
-  }
-}
diff --git a/lib/src/screens/buy/buy_sell_options_page.dart b/lib/src/screens/buy/buy_sell_options_page.dart
new file mode 100644
index 000000000..900810f68
--- /dev/null
+++ b/lib/src/screens/buy/buy_sell_options_page.dart
@@ -0,0 +1,48 @@
+import 'package:cake_wallet/core/selectable_option.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/select_options_page.dart';
+import 'package:flutter/cupertino.dart';
+
+class BuyOptionsPage extends SelectOptionsPage {
+  BuyOptionsPage({required this.items, this.pickAnOption, this.confirmOption});
+
+  final List<SelectableItem> items;
+  final Function(SelectableOption option)? pickAnOption;
+  final Function(BuildContext context)? confirmOption;
+
+  @override
+  String get pageTitle => S.current.choose_a_provider;
+
+  @override
+  EdgeInsets? get contentPadding => null;
+
+  @override
+  EdgeInsets? get tilePadding => EdgeInsets.only(top: 8);
+
+  @override
+  EdgeInsets? get innerPadding => EdgeInsets.symmetric(horizontal: 24, vertical: 8);
+
+  @override
+  double? get imageHeight => 40;
+
+  @override
+  double? get imageWidth => 40;
+
+  @override
+  Color? get selectedBackgroundColor => null;
+
+  @override
+  double? get tileBorderRadius => 30;
+
+  @override
+  String get bottomSectionText => '';
+
+  @override
+  void Function(SelectableOption option)? get onOptionTap => pickAnOption;
+
+  @override
+  String get primaryButtonText => S.current.confirm;
+
+  @override
+  void Function(BuildContext context)? get primaryButtonAction => confirmOption;
+}
diff --git a/lib/src/screens/buy/buy_sell_page.dart b/lib/src/screens/buy/buy_sell_page.dart
new file mode 100644
index 000000000..d2f16fe3c
--- /dev/null
+++ b/lib/src/screens/buy/buy_sell_page.dart
@@ -0,0 +1,469 @@
+import 'package:cake_wallet/buy/sell_buy_states.dart';
+import 'package:cake_wallet/core/address_validator.dart';
+import 'package:cake_wallet/di.dart';
+import 'package:cake_wallet/entities/fiat_currency.dart';
+import 'package:cake_wallet/entities/parse_address_from_domain.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/routes.dart';
+import 'package:cake_wallet/src/screens/base_page.dart';
+import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart';
+import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart';
+import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
+import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
+import 'package:cake_wallet/src/widgets/primary_button.dart';
+import 'package:cake_wallet/src/widgets/provider_optoin_tile.dart';
+import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
+import 'package:cake_wallet/src/widgets/trail_button.dart';
+import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
+import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
+import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
+import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
+import 'package:cake_wallet/themes/theme_base.dart';
+import 'package:cake_wallet/typography.dart';
+import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart';
+import 'package:cake_wallet/utils/responsive_layout_util.dart';
+import 'package:cake_wallet/view_model/buy/buy_sell_view_model.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/currency.dart';
+import 'package:cw_core/wallet_type.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';
+
+class BuySellPage extends BasePage {
+  BuySellPage(this.buySellViewModel);
+
+  final BuySellViewModel buySellViewModel;
+  final cryptoCurrencyKey = GlobalKey<ExchangeCardState>();
+  final fiatCurrencyKey = GlobalKey<ExchangeCardState>();
+  final _formKey = GlobalKey<FormState>();
+  final _fiatAmountFocus = FocusNode();
+  final _cryptoAmountFocus = FocusNode();
+  final _cryptoAddressFocus = FocusNode();
+  var _isReactionsSet = false;
+
+  final arrowBottomPurple = Image.asset(
+    'assets/images/arrow_bottom_purple_icon.png',
+    color: Colors.white,
+    height: 8,
+  );
+  final arrowBottomCakeGreen = Image.asset(
+    'assets/images/arrow_bottom_cake_green.png',
+    color: Colors.white,
+    height: 8,
+  );
+
+  late final String? depositWalletName;
+  late final String? receiveWalletName;
+
+  @override
+  String get title => S.current.buy + '/' + S.current.sell;
+
+  @override
+  bool get gradientBackground => true;
+
+  @override
+  bool get gradientAll => true;
+
+  @override
+  bool get resizeToAvoidBottomInset => false;
+
+  @override
+  bool get extendBodyBehindAppBar => true;
+
+  @override
+  AppBarStyle get appBarStyle => AppBarStyle.transparent;
+
+  @override
+  Function(BuildContext)? get pushToNextWidget => (context) {
+        FocusScopeNode currentFocus = FocusScope.of(context);
+        if (!currentFocus.hasPrimaryFocus) {
+          currentFocus.focusedChild?.unfocus();
+        }
+      };
+
+  @override
+  Widget trailing(BuildContext context) => TrailButton(
+      caption: S.of(context).clear,
+      onPressed: () {
+        _formKey.currentState?.reset();
+        buySellViewModel.reset();
+      });
+
+  @override
+  Widget? leading(BuildContext context) {
+    final _backButton = Icon(
+      Icons.arrow_back_ios,
+      color: titleColor(context),
+      size: 16,
+    );
+    final _closeButton =
+        currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage;
+
+    bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI;
+
+    return MergeSemantics(
+      child: SizedBox(
+        height: isMobileView ? 37 : 45,
+        width: isMobileView ? 37 : 45,
+        child: ButtonTheme(
+          minWidth: double.minPositive,
+          child: Semantics(
+            label: !isMobileView ? S.of(context).close : S.of(context).seed_alert_back,
+            child: TextButton(
+              style: ButtonStyle(
+                overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent),
+              ),
+              onPressed: () => onClose(context),
+              child: !isMobileView ? _closeButton : _backButton,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
+  @override
+  Widget body(BuildContext context) {
+    WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context, buySellViewModel));
+
+    return KeyboardActions(
+        disableScroll: true,
+        config: KeyboardActionsConfig(
+            keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
+            keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
+            nextFocus: false,
+            actions: [
+              KeyboardActionsItem(
+                  focusNode: _fiatAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]),
+              KeyboardActionsItem(
+                  focusNode: _cryptoAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()])
+            ]),
+        child: Container(
+          color: Theme.of(context).colorScheme.background,
+          child: Form(
+              key: _formKey,
+              child: ScrollableWithBottomSection(
+                contentPadding: EdgeInsets.only(bottom: 24),
+                content: Observer(
+                    builder: (_) => Column(children: [
+                          _exchangeCardsSection(context),
+                          Padding(
+                            padding: EdgeInsets.symmetric(horizontal: 24),
+                            child: Column(
+                              children: [
+                                SizedBox(height: 12),
+                                _buildPaymentMethodTile(context),
+                              ],
+                            ),
+                          ),
+                        ])),
+                bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
+                bottomSection: Column(children: [
+                  Observer(
+                      builder: (_) => LoadingPrimaryButton(
+                          text: S.current.choose_a_provider,
+                          onPressed: () async {
+                            if(!_formKey.currentState!.validate()) return;
+                            buySellViewModel.onTapChoseProvider(context);
+                          },
+                          color: Theme.of(context).primaryColor,
+                          textColor: Colors.white,
+                          isDisabled: false,
+                          isLoading: !buySellViewModel.isReadyToTrade)),
+                ]),
+              )),
+        ));
+  }
+
+  Widget _buildPaymentMethodTile(BuildContext context) {
+    if (buySellViewModel.paymentMethodState is PaymentMethodLoading ||
+        buySellViewModel.paymentMethodState is InitialPaymentMethod) {
+      return OptionTilePlaceholder(
+          withBadge: false,
+          withSubtitle: false,
+          borderRadius: 30,
+          padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8),
+          leadingIcon: Icons.arrow_forward_ios,
+          isDarkTheme: buySellViewModel.isDarkTheme);
+    }
+    if (buySellViewModel.paymentMethodState is PaymentMethodFailed) {
+      return OptionTilePlaceholder(errorText: 'No payment methods available', borderRadius: 30);
+    }
+    if (buySellViewModel.paymentMethodState is PaymentMethodLoaded &&
+        buySellViewModel.selectedPaymentMethod != null) {
+      return Observer(builder: (_) {
+        final selectedPaymentMethod = buySellViewModel.selectedPaymentMethod!;
+        return ProviderOptionTile(
+          lightImagePath: selectedPaymentMethod.lightIconPath,
+          darkImagePath: selectedPaymentMethod.darkIconPath,
+          title: selectedPaymentMethod.title,
+          onPressed: () => _pickPaymentMethod(context),
+          leadingIcon: Icons.arrow_forward_ios,
+          isLightMode: !buySellViewModel.isDarkTheme,
+          borderRadius: 30,
+          padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8),
+          titleTextStyle:
+          textLargeBold(color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
+        );
+      });
+    }
+    return OptionTilePlaceholder(errorText: 'No payment methods available', borderRadius: 30);
+  }
+
+  void _pickPaymentMethod(BuildContext context) async {
+    final currentOption = buySellViewModel.selectedPaymentMethod;
+    await Navigator.of(context).pushNamed(
+      Routes.paymentMethodOptionsPage,
+      arguments: [
+        buySellViewModel.paymentMethods,
+        buySellViewModel.changeOption,
+      ],
+    );
+
+    buySellViewModel.selectedPaymentMethod;
+    if (currentOption != null &&
+        currentOption.paymentMethodType !=
+            buySellViewModel.selectedPaymentMethod?.paymentMethodType) {
+      await buySellViewModel.calculateBestRate();
+    }
+  }
+
+  void _setReactions(BuildContext context, BuySellViewModel buySellViewModel) {
+    if (_isReactionsSet) {
+      return;
+    }
+
+    final fiatAmountController = fiatCurrencyKey.currentState!.amountController;
+    final cryptoAmountController = cryptoCurrencyKey.currentState!.amountController;
+    final cryptoAddressController = cryptoCurrencyKey.currentState!.addressController;
+
+    _onCurrencyChange(buySellViewModel.cryptoCurrency, buySellViewModel, cryptoCurrencyKey);
+    _onCurrencyChange(buySellViewModel.fiatCurrency, buySellViewModel, fiatCurrencyKey);
+
+    reaction(
+            (_) => buySellViewModel.wallet.name,
+            (String _) =>
+            _onWalletNameChange(buySellViewModel, buySellViewModel.cryptoCurrency, cryptoCurrencyKey));
+
+    reaction(
+        (_) => buySellViewModel.cryptoCurrency,
+        (CryptoCurrency currency) =>
+            _onCurrencyChange(currency, buySellViewModel, cryptoCurrencyKey));
+
+    reaction(
+        (_) => buySellViewModel.fiatCurrency,
+        (FiatCurrency currency) =>
+            _onCurrencyChange(currency, buySellViewModel, fiatCurrencyKey));
+
+    reaction((_) => buySellViewModel.fiatAmount, (String amount) {
+      if (fiatCurrencyKey.currentState!.amountController.text != amount) {
+        fiatCurrencyKey.currentState!.amountController.text = amount;
+      }
+    });
+
+    reaction((_) => buySellViewModel.isCryptoCurrencyAddressEnabled, (bool isEnabled) {
+      cryptoCurrencyKey.currentState!.isAddressEditable(isEditable: isEnabled);
+    });
+
+    reaction((_) => buySellViewModel.cryptoAmount, (String amount) {
+      if (cryptoCurrencyKey.currentState!.amountController.text != amount) {
+        cryptoCurrencyKey.currentState!.amountController.text = amount;
+      }
+    });
+
+    reaction((_) => buySellViewModel.cryptoCurrencyAddress, (String address) {
+      if (cryptoAddressController != address) {
+        cryptoCurrencyKey.currentState!.addressController.text = address;
+      }
+    });
+
+    fiatAmountController.addListener(() {
+      if (fiatAmountController.text != buySellViewModel.fiatAmount) {
+          buySellViewModel.changeFiatAmount(amount: fiatAmountController.text);
+      }
+    });
+
+    cryptoAmountController.addListener(() {
+      if (cryptoAmountController.text != buySellViewModel.cryptoAmount) {
+          buySellViewModel.changeCryptoAmount(amount: cryptoAmountController.text);
+      }
+    });
+
+    cryptoAddressController.addListener(() {
+      buySellViewModel.changeCryptoCurrencyAddress(cryptoAddressController.text);
+    });
+
+    _cryptoAddressFocus.addListener(() async {
+      if (!_cryptoAddressFocus.hasFocus && cryptoAddressController.text.isNotEmpty) {
+        final domain = cryptoAddressController.text;
+        buySellViewModel.cryptoCurrencyAddress =
+        await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
+      }
+    });
+
+    reaction((_) => buySellViewModel.wallet.walletAddresses.addressForExchange, (String address) {
+      if (buySellViewModel.cryptoCurrency == CryptoCurrency.xmr) {
+        cryptoCurrencyKey.currentState!.changeAddress(address: address);
+      }
+    });
+
+    reaction((_) => buySellViewModel.isReadyToTrade, (bool isReady) {
+      if (isReady) {
+        if (cryptoAmountController.text.isNotEmpty &&
+            cryptoAmountController.text != S.current.fetching) {
+          buySellViewModel.changeCryptoAmount(amount: cryptoAmountController.text);
+        } else if (fiatAmountController.text.isNotEmpty &&
+            fiatAmountController.text != S.current.fetching) {
+          buySellViewModel.changeFiatAmount(amount: fiatAmountController.text);
+        }
+      }
+    });
+
+    _isReactionsSet = true;
+  }
+
+  void _onCurrencyChange(Currency currency, BuySellViewModel buySellViewModel,
+      GlobalKey<ExchangeCardState> key) {
+    final isCurrentTypeWallet = currency == buySellViewModel.wallet.currency;
+
+    key.currentState!.changeSelectedCurrency(currency);
+    key.currentState!.changeWalletName(isCurrentTypeWallet ? buySellViewModel.wallet.name : '');
+
+    key.currentState!.changeAddress(
+        address: isCurrentTypeWallet ? buySellViewModel.wallet.walletAddresses.addressForExchange : '');
+
+    key.currentState!.changeAmount(amount: '');
+  }
+
+  void _onWalletNameChange(BuySellViewModel buySellViewModel, CryptoCurrency currency,
+      GlobalKey<ExchangeCardState> key) {
+    final isCurrentTypeWallet = currency == buySellViewModel.wallet.currency;
+
+    if (isCurrentTypeWallet) {
+      key.currentState!.changeWalletName(buySellViewModel.wallet.name);
+      key.currentState!.addressController.text = buySellViewModel.wallet.walletAddresses.addressForExchange;
+    } else if (key.currentState!.addressController.text ==
+        buySellViewModel.wallet.walletAddresses.addressForExchange) {
+      key.currentState!.changeWalletName('');
+      key.currentState!.addressController.text = '';
+    }
+  }
+
+  void disposeBestRateSync() => {};
+
+  Widget _exchangeCardsSection(BuildContext context) {
+    final fiatExchangeCard = Observer(
+        builder: (_) => ExchangeCard(
+              cardInstanceName: 'fiat_currency_trade_card',
+              onDispose: disposeBestRateSync,
+              amountFocusNode: _fiatAmountFocus,
+              key: fiatCurrencyKey,
+              title: 'FIAT ${S.of(context).amount}',
+              initialCurrency: buySellViewModel.fiatCurrency,
+              initialWalletName: '',
+              initialAddress: '',
+              initialIsAmountEditable: true,
+              isAmountEstimated: false,
+              currencyRowPadding: EdgeInsets.zero,
+              addressRowPadding: EdgeInsets.zero,
+              isMoneroWallet: buySellViewModel.wallet == WalletType.monero,
+              showAddressField: false,
+              showLimitsField: false,
+              currencies: buySellViewModel.fiatCurrencies,
+              onCurrencySelected: (currency) =>
+                  buySellViewModel.changeFiatCurrency(currency: currency),
+              imageArrow: arrowBottomPurple,
+              currencyButtonColor: Colors.transparent,
+              addressButtonsColor:
+                  Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
+              borderColor:
+                  Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor,
+              onPushPasteButton: (context) async {},
+              onPushAddressBookButton: (context) async {},
+            ));
+
+    final cryptoExchangeCard = Observer(
+        builder: (_) => ExchangeCard(
+              cardInstanceName: 'crypto_currency_trade_card',
+              onDispose: disposeBestRateSync,
+              amountFocusNode: _cryptoAmountFocus,
+              addressFocusNode: _cryptoAddressFocus,
+              key: cryptoCurrencyKey,
+              title: 'Crypto ${S.of(context).amount}',
+              initialCurrency: buySellViewModel.cryptoCurrency,
+              initialWalletName: '',
+              initialAddress: buySellViewModel.cryptoCurrency == buySellViewModel.wallet.currency
+                  ? buySellViewModel.wallet.walletAddresses.addressForExchange
+                  : buySellViewModel.cryptoCurrencyAddress,
+              initialIsAmountEditable: true,
+              isAmountEstimated: true,
+              showLimitsField: false,
+              currencyRowPadding: EdgeInsets.zero,
+              addressRowPadding: EdgeInsets.zero,
+              isMoneroWallet: buySellViewModel.wallet == WalletType.monero,
+              currencies: buySellViewModel.cryptoCurrencies,
+              onCurrencySelected: (currency) =>
+                  buySellViewModel.changeCryptoCurrency(currency: currency),
+              imageArrow: arrowBottomCakeGreen,
+              currencyButtonColor: Colors.transparent,
+              addressButtonsColor:
+                  Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
+              borderColor:
+                  Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
+              addressTextFieldValidator: AddressValidator(type: buySellViewModel.cryptoCurrency),
+              onPushPasteButton: (context) async {},
+              onPushAddressBookButton: (context) async {},
+            ));
+
+    if (responsiveLayoutUtil.shouldRenderMobileUI) {
+      return Observer(
+        builder: (_) {
+          if (buySellViewModel.isBuyAction) {
+            return MobileExchangeCardsSection(
+              firstExchangeCard: fiatExchangeCard,
+              secondExchangeCard: cryptoExchangeCard,
+              onBuyTap: () => null,
+              onSellTap: () =>
+                  buySellViewModel.isBuyAction ? buySellViewModel.changeBuySellAction() : null,
+              isBuySellOption: true,
+            );
+          } else {
+            return MobileExchangeCardsSection(
+              firstExchangeCard: cryptoExchangeCard,
+              secondExchangeCard: fiatExchangeCard,
+              onBuyTap: () =>
+                  !buySellViewModel.isBuyAction ? buySellViewModel.changeBuySellAction() : null,
+              onSellTap: () => null,
+              isBuySellOption: true,
+            );
+          }
+        },
+      );
+    }
+
+    return Observer(
+      builder: (_) {
+        if (buySellViewModel.isBuyAction) {
+          return DesktopExchangeCardsSection(
+            firstExchangeCard: fiatExchangeCard,
+            secondExchangeCard: cryptoExchangeCard,
+          );
+        } else {
+          return DesktopExchangeCardsSection(
+            firstExchangeCard: cryptoExchangeCard,
+            secondExchangeCard: fiatExchangeCard,
+          );
+        }
+      },
+    );
+  }
+
+  Future<String> fetchParsedAddress(
+      BuildContext context, String domain, CryptoCurrency currency) async {
+    final parsedAddress = await getIt.get<AddressResolver>().resolve(context, domain, currency);
+    final address = await extractAddressFromParsed(context, parsedAddress);
+    return address;
+  }
+}
diff --git a/lib/src/screens/buy/payment_method_options_page.dart b/lib/src/screens/buy/payment_method_options_page.dart
new file mode 100644
index 000000000..541f91ab4
--- /dev/null
+++ b/lib/src/screens/buy/payment_method_options_page.dart
@@ -0,0 +1,47 @@
+import 'package:cake_wallet/core/selectable_option.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/select_options_page.dart';
+import 'package:flutter/cupertino.dart';
+
+class PaymentMethodOptionsPage extends SelectOptionsPage {
+  PaymentMethodOptionsPage({required this.items, this.pickAnOption});
+
+  final List<SelectableItem> items;
+  final Function(SelectableOption option)? pickAnOption;
+
+  @override
+  String get pageTitle => S.current.choose_a_payment_method;
+
+  @override
+  EdgeInsets? get contentPadding => null;
+
+  @override
+  EdgeInsets? get tilePadding => EdgeInsets.only(top: 12);
+
+  @override
+  EdgeInsets? get innerPadding => EdgeInsets.symmetric(horizontal: 24, vertical: 12);
+
+  @override
+  double? get imageHeight => null;
+
+  @override
+  double? get imageWidth => null;
+
+  @override
+  Color? get selectedBackgroundColor => null;
+
+  @override
+  double? get tileBorderRadius => 30;
+
+  @override
+  String get bottomSectionText => '';
+
+  @override
+  void Function(SelectableOption option)? get onOptionTap => pickAnOption;
+
+  @override
+  String get primaryButtonText => S.current.confirm;
+
+  @override
+  void Function(BuildContext context)? get primaryButtonAction => null;
+}
diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart
index d36c06013..7bb5f77f8 100644
--- a/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart
+++ b/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart
@@ -21,6 +21,14 @@ class DesktopDashboardActions extends StatelessWidget {
           return Column(
             children: [
               const SizedBox(height: 16),
+              DesktopActionButton(
+                title: MainActions.showWalletsAction.name(context),
+                image: MainActions.showWalletsAction.image,
+                canShow: MainActions.showWalletsAction.canShow?.call(dashboardViewModel),
+                isEnabled: MainActions.showWalletsAction.isEnabled?.call(dashboardViewModel),
+                onTap: () async =>
+                    await MainActions.showWalletsAction.onTap(context, dashboardViewModel),
+              ),
               DesktopActionButton(
                 title: MainActions.exchangeAction.name(context),
                 image: MainActions.exchangeAction.image,
@@ -55,20 +63,11 @@ class DesktopDashboardActions extends StatelessWidget {
                 children: [
                   Expanded(
                     child: DesktopActionButton(
-                      title: MainActions.buyAction.name(context),
-                      image: MainActions.buyAction.image,
-                      canShow: MainActions.buyAction.canShow?.call(dashboardViewModel),
-                      isEnabled: MainActions.buyAction.isEnabled?.call(dashboardViewModel),
-                      onTap: () async => await MainActions.buyAction.onTap(context, dashboardViewModel),
-                    ),
-                  ),
-                  Expanded(
-                    child: DesktopActionButton(
-                      title: MainActions.sellAction.name(context),
-                      image: MainActions.sellAction.image,
-                      canShow: MainActions.sellAction.canShow?.call(dashboardViewModel),
-                      isEnabled: MainActions.sellAction.isEnabled?.call(dashboardViewModel),
-                      onTap: () async => await MainActions.sellAction.onTap(context, dashboardViewModel),
+                      title: MainActions.tradeAction.name(context),
+                      image: MainActions.tradeAction.image,
+                      canShow: MainActions.tradeAction.canShow?.call(dashboardViewModel),
+                      isEnabled: MainActions.tradeAction.isEnabled?.call(dashboardViewModel),
+                      onTap: () async => await MainActions.tradeAction.onTap(context, dashboardViewModel),
                     ),
                   ),
                 ],
diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart
index 75a2eadd7..7c4cc948d 100644
--- a/lib/src/screens/exchange/widgets/exchange_card.dart
+++ b/lib/src/screens/exchange/widgets/exchange_card.dart
@@ -18,7 +18,7 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
 import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
 import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
 
-class ExchangeCard extends StatefulWidget {
+class ExchangeCard<T extends Currency> extends StatefulWidget {
   ExchangeCard({
     Key? key,
     required this.initialCurrency,
@@ -40,19 +40,23 @@ class ExchangeCard extends StatefulWidget {
     this.borderColor = Colors.transparent,
     this.hasAllAmount = false,
     this.isAllAmountEnabled = false,
+    this.showAddressField = true,
+    this.showLimitsField = true,
     this.amountFocusNode,
     this.addressFocusNode,
     this.allAmount,
+    this.currencyRowPadding,
+    this.addressRowPadding,
     this.onPushPasteButton,
     this.onPushAddressBookButton,
     this.onDispose,
     required this.cardInstanceName,
   }) : super(key: key);
 
-  final List<CryptoCurrency> currencies;
-  final Function(CryptoCurrency) onCurrencySelected;
+  final List<T> currencies;
+  final Function(T) onCurrencySelected;
   final String title;
-  final CryptoCurrency initialCurrency;
+  final T initialCurrency;
   final String initialWalletName;
   final String initialAddress;
   final bool initialIsAmountEditable;
@@ -70,18 +74,22 @@ class ExchangeCard extends StatefulWidget {
   final FocusNode? amountFocusNode;
   final FocusNode? addressFocusNode;
   final bool hasAllAmount;
+  final bool showAddressField;
+  final bool showLimitsField;
   final bool isAllAmountEnabled;
   final VoidCallback? allAmount;
+  final EdgeInsets? currencyRowPadding;
+  final EdgeInsets? addressRowPadding;
   final void Function(BuildContext context)? onPushPasteButton;
   final void Function(BuildContext context)? onPushAddressBookButton;
   final Function()? onDispose;
   final String cardInstanceName;
 
   @override
-  ExchangeCardState createState() => ExchangeCardState();
+  ExchangeCardState<T> createState() => ExchangeCardState<T>();
 }
 
-class ExchangeCardState extends State<ExchangeCard> {
+class ExchangeCardState<T extends Currency> extends State<ExchangeCard<T>> {
   ExchangeCardState()
       : _title = '',
         _min = '',
@@ -89,7 +97,6 @@ class ExchangeCardState extends State<ExchangeCard> {
         _isAmountEditable = false,
         _isAddressEditable = false,
         _walletName = '',
-        _selectedCurrency = CryptoCurrency.btc,
         _isAmountEstimated = false,
         _isMoneroWallet = false,
         _cardInstanceName = '';
@@ -101,7 +108,7 @@ class ExchangeCardState extends State<ExchangeCard> {
   String _title;
   String? _min;
   String? _max;
-  CryptoCurrency _selectedCurrency;
+  late T _selectedCurrency;
   String _walletName;
   bool _isAmountEditable;
   bool _isAddressEditable;
@@ -118,7 +125,8 @@ class ExchangeCardState extends State<ExchangeCard> {
     _selectedCurrency = widget.initialCurrency;
     _isAmountEstimated = widget.isAmountEstimated;
     _isMoneroWallet = widget.isMoneroWallet;
-    addressController.text = widget.initialAddress;
+    addressController.text = _normalizeAddressFormat(widget.initialAddress);
+
     super.initState();
   }
 
@@ -136,7 +144,7 @@ class ExchangeCardState extends State<ExchangeCard> {
     });
   }
 
-  void changeSelectedCurrency(CryptoCurrency currency) {
+  void changeSelectedCurrency(T currency) {
     setState(() => _selectedCurrency = currency);
   }
 
@@ -157,7 +165,7 @@ class ExchangeCardState extends State<ExchangeCard> {
   }
 
   void changeAddress({required String address}) {
-    setState(() => addressController.text = address);
+    setState(() => addressController.text = _normalizeAddressFormat(address));
   }
 
   void changeAmount({required String amount}) {
@@ -222,7 +230,7 @@ class ExchangeCardState extends State<ExchangeCard> {
         Divider(height: 1, color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
         Padding(
           padding: EdgeInsets.only(top: 5),
-          child: Container(
+          child: widget.showLimitsField ? Container(
               height: 15,
               child: Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
                 _min != null
@@ -247,7 +255,7 @@ class ExchangeCardState extends State<ExchangeCard> {
                         ),
                       )
                     : Offstage(),
-              ])),
+              ])) : Offstage(),
         ),
         !_isAddressEditable && widget.hasRefundAddress
             ? Padding(
@@ -261,10 +269,11 @@ class ExchangeCardState extends State<ExchangeCard> {
                 ))
             : Offstage(),
         _isAddressEditable
+            ? widget.showAddressField
             ? FocusTraversalOrder(
                 order: NumericFocusOrder(2),
                 child: Padding(
-                  padding: EdgeInsets.only(top: 20),
+                  padding: widget.addressRowPadding ?? EdgeInsets.only(top: 20),
                   child: AddressTextField(
                       addressKey: ValueKey('${_cardInstanceName}_editable_address_textfield_key'),
                       focusNode: widget.addressFocusNode,
@@ -280,26 +289,29 @@ class ExchangeCardState extends State<ExchangeCard> {
                         widget.amountFocusNode?.requestFocus();
                         amountController.text = paymentRequest.amount;
                       },
-                      placeholder: widget.hasRefundAddress ? S.of(context).refund_address : null,
+                      placeholder:
+                      widget.hasRefundAddress ? S.of(context).refund_address : null,
                       options: [
                         AddressTextFieldOption.paste,
                         AddressTextFieldOption.qrCode,
                         AddressTextFieldOption.addressBook,
                       ],
                       isBorderExist: false,
-                      textStyle:
-                          TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
+                      textStyle: TextStyle(
+                          fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
                       hintStyle: TextStyle(
                           fontSize: 16,
                           fontWeight: FontWeight.w600,
-                          color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
+                          color:
+                          Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
                       buttonColor: widget.addressButtonsColor,
                       validator: widget.addressTextFieldValidator,
                       onPushPasteButton: widget.onPushPasteButton,
                       onPushAddressBookButton: widget.onPushAddressBookButton,
                       selectedCurrency: _selectedCurrency),
                 ),
-              )
+        )
+            : Offstage()
             : Padding(
                 padding: EdgeInsets.only(top: 10),
                 child: Builder(
@@ -402,7 +414,7 @@ class ExchangeCardState extends State<ExchangeCard> {
         hintText: S.of(context).search_currency,
         isMoneroWallet: _isMoneroWallet,
         isConvertFrom: widget.hasRefundAddress,
-        onItemSelected: (Currency item) => widget.onCurrencySelected(item as CryptoCurrency),
+        onItemSelected: (Currency item) => widget.onCurrencySelected(item as T),
       ),
     );
   }
@@ -424,4 +436,10 @@ class ExchangeCardState extends State<ExchangeCard> {
               actionLeftButton: () => Navigator.of(dialogContext).pop());
         });
   }
+
+  String _normalizeAddressFormat(String address) {
+    if (address.startsWith('bitcoincash:')) address = address.substring(12);
+    return address;
+  }
 }
+
diff --git a/lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart b/lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart
index 126bca835..d53f16339 100644
--- a/lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart
+++ b/lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart
@@ -1,20 +1,29 @@
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
 import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
+import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
 import 'package:flutter/material.dart';
 
 class MobileExchangeCardsSection extends StatelessWidget {
   final Widget firstExchangeCard;
   final Widget secondExchangeCard;
+  final bool isBuySellOption;
+  final VoidCallback? onBuyTap;
+  final VoidCallback? onSellTap;
 
   const MobileExchangeCardsSection({
     Key? key,
     required this.firstExchangeCard,
     required this.secondExchangeCard,
+    this.isBuySellOption = false,
+    this.onBuyTap,
+    this.onSellTap,
   }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
     return Container(
-      padding: EdgeInsets.only(bottom: 32),
+      padding: EdgeInsets.only(bottom: isBuySellOption ? 8 : 32),
       decoration: BoxDecoration(
         borderRadius: BorderRadius.only(
           bottomLeft: Radius.circular(24),
@@ -45,8 +54,18 @@ class MobileExchangeCardsSection extends StatelessWidget {
                 end: Alignment.bottomRight,
               ),
             ),
-            padding: EdgeInsets.fromLTRB(24, 100, 24, 32),
-            child: firstExchangeCard,
+            padding: EdgeInsets.fromLTRB(24, 90, 24, isBuySellOption ? 8 : 32),
+            child: Column(
+              children: [
+                if (isBuySellOption) Column(
+                  children: [
+                    const SizedBox(height: 16),
+                    BuySellOptionButtons(onBuyTap: onBuyTap, onSellTap: onSellTap),
+                  ],
+                ),
+                firstExchangeCard,
+              ],
+            ),
           ),
           Padding(
             padding: EdgeInsets.only(top: 29, left: 24, right: 24),
@@ -57,3 +76,69 @@ class MobileExchangeCardsSection extends StatelessWidget {
     );
   }
 }
+
+class BuySellOptionButtons extends StatefulWidget {
+  final VoidCallback? onBuyTap;
+  final VoidCallback? onSellTap;
+
+  const BuySellOptionButtons({this.onBuyTap, this.onSellTap});
+
+  @override
+  _BuySellOptionButtonsState createState() => _BuySellOptionButtonsState();
+}
+
+class _BuySellOptionButtonsState extends State<BuySellOptionButtons> {
+  bool isBuySelected = true;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 24),
+      child: Row(
+        children: [
+          Expanded(flex: 2, child: SizedBox()),
+          Expanded(
+            flex: 5,
+            child: SelectButton(
+              height: 44,
+              text: S.of(context).buy,
+              isSelected: isBuySelected,
+              showTrailingIcon: false,
+              textColor: Colors.white,
+              image: Image.asset('assets/images/buy.png', height: 25, width: 25),
+              padding: EdgeInsets.only(left: 10, right: 30),
+              color: isBuySelected
+                  ? null
+                  : Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
+              onTap: () {
+                setState(() => isBuySelected = true);
+                if (widget.onBuyTap != null) widget.onBuyTap!();
+              },
+            ),
+          ),
+          Expanded(child: const SizedBox()),
+          Expanded(
+            flex: 5,
+            child: SelectButton(
+              height: 44,
+              text: S.of(context).sell,
+              isSelected: !isBuySelected,
+              showTrailingIcon: false,
+              textColor: Colors.white,
+              image: Image.asset('assets/images/sell.png', height: 25, width: 25),
+              padding: EdgeInsets.only(left: 10, right: 30),
+              color: !isBuySelected
+                  ? null
+                  : Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
+              onTap: () {
+                setState(() => isBuySelected = false);
+                if (widget.onSellTap != null) widget.onSellTap!();
+              },
+            ),
+          ),
+          Expanded(flex: 2, child: SizedBox()),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart
index 23de4564f..475f45fca 100644
--- a/lib/src/screens/seed/pre_seed_page.dart
+++ b/lib/src/screens/seed/pre_seed_page.dart
@@ -1,6 +1,6 @@
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/routes.dart';
-import 'package:cake_wallet/src/screens/InfoPage.dart';
+import 'package:cake_wallet/src/screens/Info_page.dart';
 import 'package:flutter/cupertino.dart';
 
 class PreSeedPage extends InfoPage {
diff --git a/lib/src/screens/select_options_page.dart b/lib/src/screens/select_options_page.dart
new file mode 100644
index 000000000..70cb2abc1
--- /dev/null
+++ b/lib/src/screens/select_options_page.dart
@@ -0,0 +1,199 @@
+import 'package:cake_wallet/core/selectable_option.dart';
+import 'package:cake_wallet/src/screens/base_page.dart';
+import 'package:cake_wallet/src/widgets/primary_button.dart';
+import 'package:cake_wallet/src/widgets/provider_optoin_tile.dart';
+import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
+import 'package:cake_wallet/themes/extensions/option_tile_theme.dart';
+import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
+import 'package:flutter/material.dart';
+
+abstract class SelectOptionsPage extends BasePage {
+  SelectOptionsPage();
+
+  String get pageTitle;
+
+  EdgeInsets? get contentPadding;
+
+  EdgeInsets? get tilePadding;
+
+  EdgeInsets? get innerPadding;
+
+  double? get imageHeight;
+
+  double? get imageWidth;
+
+  Color? get selectedBackgroundColor;
+
+  double? get tileBorderRadius;
+
+  String get bottomSectionText;
+
+  bool get primaryButtonEnabled => true;
+
+  String get primaryButtonText => '';
+
+  List<SelectableItem> get items;
+
+  void Function(SelectableOption option)? get onOptionTap;
+
+  void Function(BuildContext context)? get primaryButtonAction;
+
+  @override
+  String get title => pageTitle;
+
+  @override
+  Widget body(BuildContext context) {
+    return ScrollableWithBottomSection(
+      content: BodySelectOptionsPage(
+          items: items,
+          onOptionTap: onOptionTap,
+          tilePadding: tilePadding,
+          tileBorderRadius: tileBorderRadius,
+          imageHeight: imageHeight,
+          imageWidth: imageWidth,
+          innerPadding: innerPadding),
+      bottomSection: Padding(
+        padding: contentPadding ?? EdgeInsets.zero,
+        child: Column(
+          children: [
+            Text(
+              bottomSectionText,
+              textAlign: TextAlign.center,
+              style: TextStyle(
+                fontSize: 14,
+                fontWeight: FontWeight.normal,
+                color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
+              ),
+            ),
+            if (primaryButtonEnabled)
+              LoadingPrimaryButton(
+                  text: primaryButtonText,
+                  onPressed: () {
+                    primaryButtonAction != null
+                        ? primaryButtonAction!(context)
+                        : Navigator.pop(context);
+                  },
+                  color: Theme.of(context).primaryColor,
+                  textColor: Colors.white,
+                  isDisabled: false,
+                  isLoading: false)
+          ],
+        ),
+      ),
+    );
+  }
+}
+
+class BodySelectOptionsPage extends StatefulWidget {
+  const BodySelectOptionsPage({
+    required this.items,
+    this.onOptionTap,
+    this.tilePadding,
+    this.tileBorderRadius,
+    this.imageHeight,
+    this.imageWidth,
+    this.innerPadding,
+  });
+
+  final List<SelectableItem> items;
+  final void Function(SelectableOption option)? onOptionTap;
+  final EdgeInsets? tilePadding;
+  final double? tileBorderRadius;
+  final double? imageHeight;
+  final double? imageWidth;
+  final EdgeInsets? innerPadding;
+
+  @override
+  _BodySelectOptionsPageState createState() => _BodySelectOptionsPageState();
+}
+
+class _BodySelectOptionsPageState extends State<BodySelectOptionsPage> {
+  late List<SelectableItem> _items;
+
+  @override
+  void initState() {
+    super.initState();
+    _items = widget.items;
+  }
+
+  void _handleOptionTap(SelectableOption option) {
+    setState(() {
+      for (var item in _items) {
+        if (item is SelectableOption) {
+          item.isOptionSelected = false;
+        }
+      }
+      option.isOptionSelected = true;
+    });
+    widget.onOptionTap?.call(option);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final isLightMode = Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
+
+    Color titleColor =
+        isLightMode ? Theme.of(context).appBarTheme.titleTextStyle!.color! : Colors.white;
+
+    return Center(
+      child: ConstrainedBox(
+        constraints: const BoxConstraints(maxWidth: 350),
+        child: Column(
+          children: _items.map((item) {
+            if (item is OptionTitle) {
+              return Padding(
+                padding: const EdgeInsets.only(top: 18, bottom: 8),
+                child: Container(
+                  width: double.infinity,
+                  decoration: BoxDecoration(
+                    border: Border(
+                      bottom: BorderSide(
+                        color: titleColor,
+                        width: 1,
+                      ),
+                    ),
+                  ),
+                  child: Padding(
+                    padding: const EdgeInsets.only(bottom: 8.0),
+                    child: Text(
+                      item.title,
+                      style: TextStyle(
+                        fontSize: 18,
+                        fontWeight: FontWeight.w700,
+                        color: titleColor,
+                      ),
+                    ),
+                  ),
+                ),
+              );
+            } else if (item is SelectableOption) {
+              return Padding(
+                padding: widget.tilePadding ?? const EdgeInsets.only(top: 24),
+                child: ProviderOptionTile(
+                  title: item.title,
+                  lightImagePath: item.lightIconPath,
+                  darkImagePath: item.darkIconPath,
+                  imageHeight: widget.imageHeight,
+                  imageWidth: widget.imageWidth,
+                  padding: widget.innerPadding,
+                  description: item.description,
+                  topLeftSubTitle: item.topLeftSubTitle,
+                  topRightSubTitle: item.topRightSubTitle,
+                  rightSubTitleLightIconPath: item.topRightSubTitleLightIconPath,
+                  rightSubTitleDarkIconPath: item.topRightSubTitleDarkIconPath,
+                  bottomLeftSubTitle: item.bottomLeftSubTitle,
+                  badges: item.badges,
+                  isSelected: item.isOptionSelected,
+                  borderRadius: widget.tileBorderRadius,
+                  isLightMode: isLightMode,
+                  onPressed: () => _handleOptionTap(item),
+                ),
+              );
+            }
+            return const SizedBox.shrink();
+          }).toList(),
+        ),
+      ),
+    );
+  }
+}
diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart
index 137f699f5..f6a6288f5 100644
--- a/lib/src/screens/settings/other_settings_page.dart
+++ b/lib/src/screens/settings/other_settings_page.dart
@@ -57,22 +57,6 @@ class OtherSettingsPage extends BasePage {
                   handler: (BuildContext context) =>
                       Navigator.of(context).pushNamed(Routes.changeRep),
                 ),
-              if(_otherSettingsViewModel.isEnabledBuyAction)
-              SettingsPickerCell(
-                title: S.current.default_buy_provider,
-                items: _otherSettingsViewModel.availableBuyProvidersTypes,
-                displayItem: _otherSettingsViewModel.getBuyProviderType,
-                selectedItem: _otherSettingsViewModel.buyProviderType,
-                onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected
-              ),
-              if(_otherSettingsViewModel.isEnabledSellAction)
-              SettingsPickerCell(
-                title: S.current.default_sell_provider,
-                items: _otherSettingsViewModel.availableSellProvidersTypes,
-                displayItem: _otherSettingsViewModel.getSellProviderType,
-                selectedItem: _otherSettingsViewModel.sellProviderType,
-                onItemSelected: _otherSettingsViewModel.onSellProviderTypeSelected,
-              ),
               SettingsCellWithArrow(
                 title: S.current.settings_terms_and_conditions,
                 handler: (BuildContext context) =>
diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart
index 53e7686e8..8652c4af6 100644
--- a/lib/src/screens/settings/privacy_page.dart
+++ b/lib/src/screens/settings/privacy_page.dart
@@ -73,16 +73,10 @@ class PrivacyPage extends BasePage {
                       _privacySettingsViewModel.setIsAppSecure(value);
                     }),
               SettingsSwitcherCell(
-                  title: S.current.disable_buy,
-                  value: _privacySettingsViewModel.disableBuy,
+                  title: S.current.disable_trade_option,
+                  value: _privacySettingsViewModel.disableTradeOption,
                   onValueChange: (BuildContext _, bool value) {
-                    _privacySettingsViewModel.setDisableBuy(value);
-                  }),
-              SettingsSwitcherCell(
-                  title: S.current.disable_sell,
-                  value: _privacySettingsViewModel.disableSell,
-                  onValueChange: (BuildContext _, bool value) {
-                    _privacySettingsViewModel.setDisableSell(value);
+                    _privacySettingsViewModel.setDisableTradeOption(value);
                   }),
               SettingsSwitcherCell(
                   title: S.current.disable_bulletin,
diff --git a/lib/src/screens/setup_2fa/setup_2fa_info_page.dart b/lib/src/screens/setup_2fa/setup_2fa_info_page.dart
index 8aa0ac3c9..834d01c26 100644
--- a/lib/src/screens/setup_2fa/setup_2fa_info_page.dart
+++ b/lib/src/screens/setup_2fa/setup_2fa_info_page.dart
@@ -1,6 +1,6 @@
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/routes.dart';
-import 'package:cake_wallet/src/screens/InfoPage.dart';
+import 'package:cake_wallet/src/screens/Info_page.dart';
 import 'package:flutter/cupertino.dart';
 
 class Setup2FAInfoPage extends InfoPage {
diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart
index d904768f0..9b407dedb 100644
--- a/lib/src/widgets/address_text_field.dart
+++ b/lib/src/widgets/address_text_field.dart
@@ -1,20 +1,21 @@
 import 'package:cake_wallet/utils/device_info.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
+import 'package:cw_core/currency.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter/material.dart';
 import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/generated/i18n.dart';
 import 'package:cake_wallet/entities/qr_scanner.dart';
 import 'package:cake_wallet/entities/contact_base.dart';
-import 'package:cw_core/crypto_currency.dart';
 import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
 import 'package:cake_wallet/utils/permission_handler.dart';
 import 'package:permission_handler/permission_handler.dart';
 
 enum AddressTextFieldOption { paste, qrCode, addressBook, walletAddresses }
 
-class AddressTextField extends StatelessWidget {
+
+class AddressTextField<T extends Currency> extends StatelessWidget{
   AddressTextField({
     required this.controller,
     this.isActive = true,
@@ -58,7 +59,7 @@ class AddressTextField extends StatelessWidget {
   final Function(BuildContext context)? onPushAddressBookButton;
   final Function(BuildContext context)? onPushAddressPickerButton;
   final Function(ContactBase contact)? onSelectedContact;
-  final CryptoCurrency? selectedCurrency;
+  final T? selectedCurrency;
   final Key? addressKey;
 
   @override
diff --git a/lib/src/widgets/provider_optoin_tile.dart b/lib/src/widgets/provider_optoin_tile.dart
new file mode 100644
index 000000000..85396a97d
--- /dev/null
+++ b/lib/src/widgets/provider_optoin_tile.dart
@@ -0,0 +1,527 @@
+import 'package:cake_wallet/themes/extensions/option_tile_theme.dart';
+import 'package:cake_wallet/themes/extensions/receive_page_theme.dart';
+import 'package:cake_wallet/typography.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+
+class ProviderOptionTile extends StatelessWidget {
+  const ProviderOptionTile({
+    required this.onPressed,
+    required this.lightImagePath,
+    required this.darkImagePath,
+    required this.title,
+    this.topLeftSubTitle,
+    this.topRightSubTitle,
+    this.bottomLeftSubTitle,
+    this.bottomRightSubTitle,
+    this.leftSubTitleIconPath,
+    this.rightSubTitleLightIconPath,
+    this.rightSubTitleDarkIconPath,
+    this.description,
+    this.badges,
+    this.borderRadius,
+    this.imageHeight,
+    this.imageWidth,
+    this.padding,
+    this.titleTextStyle,
+    this.firstSubTitleTextStyle,
+    this.secondSubTitleTextStyle,
+    this.leadingIcon,
+    this.selectedBackgroundColor,
+    this.isSelected = false,
+    required this.isLightMode,
+  });
+
+  final VoidCallback onPressed;
+  final String lightImagePath;
+  final String darkImagePath;
+  final String title;
+  final String? topLeftSubTitle;
+  final String? topRightSubTitle;
+  final String? bottomLeftSubTitle;
+  final String? bottomRightSubTitle;
+  final String? leftSubTitleIconPath;
+  final String? rightSubTitleLightIconPath;
+  final String? rightSubTitleDarkIconPath;
+  final String? description;
+  final List<String>? badges;
+  final double? borderRadius;
+  final double? imageHeight;
+  final double? imageWidth;
+  final EdgeInsets? padding;
+  final TextStyle? titleTextStyle;
+  final TextStyle? firstSubTitleTextStyle;
+  final TextStyle? secondSubTitleTextStyle;
+  final IconData? leadingIcon;
+  final Color? selectedBackgroundColor;
+  final bool isSelected;
+  final bool isLightMode;
+
+  @override
+  Widget build(BuildContext context) {
+    final backgroundColor = isSelected
+        ? isLightMode
+            ? Theme.of(context).extension<ReceivePageTheme>()!.currentTileBackgroundColor
+            : Theme.of(context).extension<OptionTileTheme>()!.titleColor
+        : Theme.of(context).cardColor;
+
+    final textColor = isSelected
+        ? isLightMode
+            ? Colors.white
+            : Theme.of(context).cardColor
+        : Theme.of(context).extension<OptionTileTheme>()!.titleColor;
+
+    final badgeColor = isSelected
+        ? Theme.of(context).cardColor
+        : Theme.of(context).extension<OptionTileTheme>()!.titleColor;
+
+    final badgeTextColor = isSelected
+        ? Theme.of(context).extension<OptionTileTheme>()!.titleColor
+        : Theme.of(context).cardColor;
+
+    final imagePath = isSelected
+        ? isLightMode
+            ? darkImagePath
+            : lightImagePath
+        : isLightMode
+            ? lightImagePath
+            : darkImagePath;
+
+    final rightSubTitleIconPath = isSelected
+        ? isLightMode
+            ? rightSubTitleDarkIconPath
+            : rightSubTitleLightIconPath
+        : isLightMode
+            ? rightSubTitleLightIconPath
+            : rightSubTitleDarkIconPath;
+
+    return GestureDetector(
+      onTap: onPressed,
+      child: Container(
+        width: double.infinity,
+        alignment: Alignment.center,
+        decoration: BoxDecoration(
+          borderRadius: BorderRadius.all(Radius.circular(borderRadius ?? 12)),
+          border: isSelected && !isLightMode ? Border.all(color: textColor) : null,
+          color: backgroundColor,
+        ),
+        child: Padding(
+          padding: padding ?? const EdgeInsets.all(16),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              Row(
+                children: [
+                  getImage(imagePath, height: imageHeight, width: imageWidth),
+                  SizedBox(width: 8),
+                  Expanded(
+                    child: Container(
+                      child: Row(
+                        children: [
+                          Expanded(
+                              child: Text(title,
+                                  style: titleTextStyle ?? textLargeBold(color: textColor))),
+                          Row(
+                            children: [
+                              if (leadingIcon != null)
+                                Icon(leadingIcon, size: 16, color: textColor),
+                            ],
+                          )
+                        ],
+                      ),
+                    ),
+                  ),
+                ],
+              ),
+              if (topLeftSubTitle != null || topRightSubTitle != null)
+                subTitleWidget(
+                    leftSubTitle: topLeftSubTitle,
+                    subTitleIconPath: leftSubTitleIconPath,
+                    textColor: textColor,
+                    rightSubTitle: topRightSubTitle,
+                    rightSubTitleIconPath: rightSubTitleIconPath),
+              if (bottomLeftSubTitle != null || bottomRightSubTitle != null)
+                subTitleWidget(
+                    leftSubTitle: bottomLeftSubTitle,
+                    textColor: textColor,
+                    subTitleFontSize: 12),
+              if (badges != null && badges!.isNotEmpty)
+                Padding(
+                  padding: const EdgeInsets.only(top: 12),
+                  child: Row(children: [
+                    ...badges!
+                        .map((badge) => Badge(
+                            title: badge, textColor: badgeTextColor, backgroundColor: badgeColor))
+                        .toList()
+                  ]),
+                )
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+class subTitleWidget extends StatelessWidget {
+  const subTitleWidget({
+    super.key,
+    this.leftSubTitle,
+    this.subTitleIconPath,
+    required this.textColor,
+    this.rightSubTitle,
+    this.rightSubTitleIconPath,
+    this.subTitleFontSize = 16,
+  });
+
+  final String? leftSubTitle;
+  final String? subTitleIconPath;
+  final Color textColor;
+  final String? rightSubTitle;
+  final String? rightSubTitleIconPath;
+  final double subTitleFontSize;
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+      children: [
+        leftSubTitle != null || subTitleIconPath != null
+            ? Row(
+              children: [
+                if (subTitleIconPath != null && subTitleIconPath!.isNotEmpty)
+                  Padding(
+                    padding: const EdgeInsets.only(right: 6),
+                    child: getImage(subTitleIconPath!),
+                  ),
+                Text(
+                  leftSubTitle ?? '',
+                  style: TextStyle(
+                      fontSize: subTitleFontSize,
+                      fontWeight: FontWeight.w700,
+                      color: textColor),
+                ),
+              ],
+            )
+            : Offstage(),
+        rightSubTitle != null || rightSubTitleIconPath != null
+            ? Row(
+                children: [
+                  if (rightSubTitleIconPath != null && rightSubTitleIconPath!.isNotEmpty)
+                    Padding(
+                      padding: const EdgeInsets.only(right: 4),
+                      child: getImage(rightSubTitleIconPath!, imageColor: textColor),
+                    ),
+                  Text(
+                    rightSubTitle ?? '',
+                    style: TextStyle(
+                        fontSize: subTitleFontSize, fontWeight: FontWeight.w700, color: textColor),
+                  ),
+                ],
+              )
+            : Offstage(),
+      ],
+    );
+  }
+}
+
+class Badge extends StatelessWidget {
+  Badge({required this.textColor, required this.backgroundColor, required this.title});
+
+  final String title;
+  final Color textColor;
+  final Color backgroundColor;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(right: 8),
+      child: FittedBox(
+        fit: BoxFit.fitHeight,
+        child: Container(
+          padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4),
+          decoration: BoxDecoration(
+              borderRadius: BorderRadius.all(Radius.circular(24)), color: backgroundColor),
+          alignment: Alignment.center,
+          child: Text(
+            title,
+            style: TextStyle(
+              color: textColor,
+              fontSize: 12,
+              fontWeight: FontWeight.w600,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+Widget getImage(String imagePath, {double? height, double? width, Color? imageColor}) {
+  final bool isNetworkImage = imagePath.startsWith('http') || imagePath.startsWith('https');
+  final bool isSvg = imagePath.endsWith('.svg');
+  final double imageHeight = height ?? 35;
+  final double imageWidth = width ?? 35;
+
+  if (isNetworkImage) {
+    return isSvg
+        ? SvgPicture.network(
+            imagePath,
+            height: imageHeight,
+            width: imageWidth,
+            colorFilter: imageColor != null ? ColorFilter.mode(imageColor, BlendMode.srcIn) : null,
+            placeholderBuilder: (BuildContext context) => Container(
+              height: imageHeight,
+              width: imageWidth,
+              child: Center(
+                child: CircularProgressIndicator(),
+              ),
+            ),
+          )
+        : Image.network(
+            imagePath,
+            height: imageHeight,
+            width: imageWidth,
+            loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
+              if (loadingProgress == null) {
+                return child;
+              }
+              return Container(
+                height: imageHeight,
+                width: imageWidth,
+                child: Center(
+                  child: CircularProgressIndicator(
+                    value: loadingProgress.expectedTotalBytes != null
+                        ? loadingProgress.cumulativeBytesLoaded /
+                            loadingProgress.expectedTotalBytes!
+                        : null,
+                  ),
+                ),
+              );
+            },
+            errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
+              return Container(
+                height: imageHeight,
+                width: imageWidth,
+              );
+            },
+          );
+  } else {
+    return isSvg
+        ? SvgPicture.asset(
+            imagePath,
+            height: imageHeight,
+            width: imageWidth,
+            colorFilter: imageColor != null ? ColorFilter.mode(imageColor, BlendMode.srcIn) : null,
+          )
+        : Image.asset(imagePath, height: imageHeight, width: imageWidth);
+  }
+}
+
+class OptionTilePlaceholder extends StatefulWidget {
+  OptionTilePlaceholder({
+    this.borderRadius,
+    this.imageHeight,
+    this.imageWidth,
+    this.padding,
+    this.leadingIcon,
+    this.withBadge = true,
+    this.withSubtitle = true,
+    this.isDarkTheme = false,
+    this.errorText,
+  });
+
+  final double? borderRadius;
+  final double? imageHeight;
+  final double? imageWidth;
+  final EdgeInsets? padding;
+  final IconData? leadingIcon;
+  final bool withBadge;
+  final bool withSubtitle;
+  final bool isDarkTheme;
+  final String? errorText;
+
+  @override
+  _OptionTilePlaceholderState createState() => _OptionTilePlaceholderState();
+}
+
+class _OptionTilePlaceholderState extends State<OptionTilePlaceholder>
+    with SingleTickerProviderStateMixin {
+  late AnimationController _controller;
+  late Animation<double> _animation;
+
+  @override
+  void initState() {
+    super.initState();
+
+    _controller = AnimationController(
+      duration: const Duration(seconds: 2),
+      vsync: this,
+    )..repeat();
+
+    _animation = CurvedAnimation(
+      parent: _controller,
+      curve: Curves.linear,
+    );
+  }
+
+  @override
+  void dispose() {
+    _controller.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final backgroundColor = Theme.of(context).cardColor;
+    final titleColor = Theme.of(context).extension<OptionTileTheme>()!.titleColor.withOpacity(0.4);
+
+    return widget.errorText != null
+        ? Container(
+            width: double.infinity,
+            padding: widget.padding ?? EdgeInsets.all(16),
+            alignment: Alignment.center,
+            decoration: BoxDecoration(
+              borderRadius: BorderRadius.all(Radius.circular(widget.borderRadius ?? 12)),
+              color: backgroundColor,
+            ),
+            child: Column(
+              children: [
+                Text(
+                  widget.errorText!,
+                  style: TextStyle(
+                    color: titleColor,
+                    fontSize: 16,
+                  ),
+                ),
+                if (widget.withSubtitle) SizedBox(height: 8),
+                Text(
+                  '',
+                  style: TextStyle(
+                    color: titleColor,
+                    fontSize: 16,
+                  ),
+                ),
+              ],
+            ),
+          )
+        : AnimatedBuilder(
+            animation: _animation,
+            builder: (context, child) {
+              return Stack(
+                children: [
+                  Container(
+                    width: double.infinity,
+                    padding: widget.padding ?? EdgeInsets.all(16),
+                    alignment: Alignment.center,
+                    decoration: BoxDecoration(
+                      borderRadius: BorderRadius.all(Radius.circular(widget.borderRadius ?? 12)),
+                      color: backgroundColor,
+                    ),
+                    child: Column(
+                      crossAxisAlignment: CrossAxisAlignment.center,
+                      children: [
+                        Row(
+                          children: [
+                            Container(
+                              height: widget.imageHeight ?? 35,
+                              width: widget.imageWidth ?? 35,
+                              decoration: BoxDecoration(
+                                color: titleColor,
+                                shape: BoxShape.circle,
+                              ),
+                            ),
+                            SizedBox(width: 8),
+                            Expanded(
+                              child: Container(
+                                child: Row(
+                                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                                  children: [
+                                    Container(
+                                      height: 20,
+                                      width: 70,
+                                      decoration: BoxDecoration(
+                                        color: titleColor,
+                                        borderRadius: BorderRadius.all(Radius.circular(8)),
+                                      ),
+                                    ),
+                                    if (widget.leadingIcon != null)
+                                      Icon(widget.leadingIcon, size: 16, color: titleColor),
+                                  ],
+                                ),
+                              ),
+                            ),
+                          ],
+                        ),
+                        if (widget.withSubtitle)
+                          Padding(
+                            padding: EdgeInsets.symmetric(vertical: 8),
+                            child: Row(
+                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                              children: [
+                                Container(
+                                  height: 20,
+                                  width: 170,
+                                  decoration: BoxDecoration(
+                                    color: titleColor,
+                                    borderRadius: BorderRadius.all(Radius.circular(8)),
+                                  ),
+                                ),
+                              ],
+                            ),
+                          ),
+                        if (widget.withBadge)
+                          Padding(
+                            padding: const EdgeInsets.only(top: 16.0),
+                            child: Row(
+                              children: [
+                                Container(
+                                  height: 30,
+                                  width: 70,
+                                  decoration: BoxDecoration(
+                                    color: titleColor,
+                                    borderRadius: BorderRadius.all(Radius.circular(20)),
+                                  ),
+                                ),
+                                SizedBox(width: 8),
+                                Container(
+                                  height: 30,
+                                  width: 70,
+                                  decoration: BoxDecoration(
+                                    color: titleColor,
+                                    borderRadius: BorderRadius.all(Radius.circular(20)),
+                                  ),
+                                ),
+                              ],
+                            ),
+                          ),
+                      ],
+                    ),
+                  ),
+                  Positioned.fill(
+                    child: Container(
+                      decoration: BoxDecoration(
+                        borderRadius: BorderRadius.all(Radius.circular(widget.borderRadius ?? 12)),
+                        gradient: LinearGradient(
+                          begin: Alignment(-2, -4),
+                          end: Alignment(2, 4),
+                          stops: [
+                            _animation.value - 0.2,
+                            _animation.value,
+                            _animation.value + 0.2,
+                          ],
+                          colors: [
+                            backgroundColor.withOpacity(widget.isDarkTheme ? 0.4 : 0.7),
+                            backgroundColor.withOpacity(widget.isDarkTheme ? 0.7 : 0.4),
+                            backgroundColor.withOpacity(widget.isDarkTheme ? 0.4 : 0.7),
+                          ],
+                        ),
+                      ),
+                    ),
+                  ),
+                ],
+              );
+            },
+          );
+  }
+}
diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart
index 50d51d2ed..1ecaf50cc 100644
--- a/lib/store/settings_store.dart
+++ b/lib/store/settings_store.dart
@@ -61,8 +61,7 @@ abstract class SettingsStoreBase with Store {
       required BitcoinSeedType initialBitcoinSeedType,
       required NanoSeedType initialNanoSeedType,
       required bool initialAppSecure,
-      required bool initialDisableBuy,
-      required bool initialDisableSell,
+      required bool initialDisableTrade,
       required FilterListOrderType initialWalletListOrder,
       required FilterListOrderType initialContactListOrder,
       required bool initialDisableBulletin,
@@ -150,8 +149,7 @@ abstract class SettingsStoreBase with Store {
         useTOTP2FA = initialUseTOTP2FA,
         numberOfFailedTokenTrials = initialFailedTokenTrial,
         isAppSecure = initialAppSecure,
-        disableBuy = initialDisableBuy,
-        disableSell = initialDisableSell,
+        disableTradeOption = initialDisableTrade,
         disableBulletin = initialDisableBulletin,
         walletListOrder = initialWalletListOrder,
         contactListOrder = initialContactListOrder,
@@ -178,9 +176,7 @@ abstract class SettingsStoreBase with Store {
             initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings,
         currentSyncMode = initialSyncMode,
         currentSyncAll = initialSyncAll,
-        priority = ObservableMap<WalletType, TransactionPriority>(),
-        defaultBuyProviders = ObservableMap<WalletType, ProviderType>(),
-        defaultSellProviders = ObservableMap<WalletType, ProviderType>() {
+        priority = ObservableMap<WalletType, TransactionPriority>() {
     //this.nodes = ObservableMap<WalletType, Node>.of(nodes);
 
     if (initialMoneroTransactionPriority != null) {
@@ -221,30 +217,6 @@ abstract class SettingsStoreBase with Store {
 
     initializeTrocadorProviderStates();
 
-    WalletType.values.forEach((walletType) {
-      final key = 'buyProvider_${walletType.toString()}';
-      final providerId = sharedPreferences.getString(key);
-      if (providerId != null) {
-        defaultBuyProviders[walletType] = ProviderType.values.firstWhere(
-            (provider) => provider.id == providerId,
-            orElse: () => ProviderType.askEachTime);
-      } else {
-        defaultBuyProviders[walletType] = ProviderType.askEachTime;
-      }
-    });
-
-    WalletType.values.forEach((walletType) {
-      final key = 'sellProvider_${walletType.toString()}';
-      final providerId = sharedPreferences.getString(key);
-      if (providerId != null) {
-        defaultSellProviders[walletType] = ProviderType.values.firstWhere(
-            (provider) => provider.id == providerId,
-            orElse: () => ProviderType.askEachTime);
-      } else {
-        defaultSellProviders[walletType] = ProviderType.askEachTime;
-      }
-    });
-
     reaction(
         (_) => fiatCurrency,
         (FiatCurrency fiatCurrency) => sharedPreferences.setString(
@@ -267,20 +239,6 @@ abstract class SettingsStoreBase with Store {
     reaction((_) => shouldShowRepWarning,
         (bool val) => sharedPreferences.setBool(PreferencesKey.shouldShowRepWarning, val));
 
-    defaultBuyProviders.observe((change) {
-      final String key = 'buyProvider_${change.key.toString()}';
-      if (change.newValue != null) {
-        sharedPreferences.setString(key, change.newValue!.id);
-      }
-    });
-
-    defaultSellProviders.observe((change) {
-      final String key = 'sellProvider_${change.key.toString()}';
-      if (change.newValue != null) {
-        sharedPreferences.setString(key, change.newValue!.id);
-      }
-    });
-
     priority.observe((change) {
       final String? key;
       switch (change.key) {
@@ -329,14 +287,9 @@ abstract class SettingsStoreBase with Store {
       });
     }
 
-    reaction((_) => disableBuy,
-        (bool disableBuy) => sharedPreferences.setBool(PreferencesKey.disableBuyKey, disableBuy));
-
-    reaction(
-        (_) => disableSell,
-        (bool disableSell) =>
-            sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell));
-
+    reaction((_) => disableTradeOption,
+        (bool disableTradeOption) => sharedPreferences.setBool(PreferencesKey.disableTradeOption, disableTradeOption));
+    
     reaction(
         (_) => disableBulletin,
         (bool disableBulletin) =>
@@ -680,10 +633,7 @@ abstract class SettingsStoreBase with Store {
   bool isAppSecure;
 
   @observable
-  bool disableBuy;
-
-  @observable
-  bool disableSell;
+  bool disableTradeOption;
 
   @observable
   FilterListOrderType contactListOrder;
@@ -769,12 +719,6 @@ abstract class SettingsStoreBase with Store {
   @observable
   ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
 
-  @observable
-  ObservableMap<WalletType, ProviderType> defaultBuyProviders;
-
-  @observable
-  ObservableMap<WalletType, ProviderType> defaultSellProviders;
-
   @observable
   SortBalanceBy sortBalanceBy;
 
@@ -956,8 +900,7 @@ abstract class SettingsStoreBase with Store {
     final shouldSaveRecipientAddress =
         sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? false;
     final isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false;
-    final disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false;
-    final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false;
+    final disableTradeOption = sharedPreferences.getBool(PreferencesKey.disableTradeOption) ?? false;
     final disableBulletin = sharedPreferences.getBool(PreferencesKey.disableBulletinKey) ?? false;
     final walletListOrder =
         FilterListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0];
@@ -1255,8 +1198,7 @@ abstract class SettingsStoreBase with Store {
       initialBitcoinSeedType: bitcoinSeedType,
       initialNanoSeedType: nanoSeedType,
       initialAppSecure: isAppSecure,
-      initialDisableBuy: disableBuy,
-      initialDisableSell: disableSell,
+      initialDisableTrade: disableTradeOption,
       initialDisableBulletin: disableBulletin,
       initialWalletListOrder: walletListOrder,
       initialWalletListAscending: walletListAscending,
@@ -1406,8 +1348,7 @@ abstract class SettingsStoreBase with Store {
     numberOfFailedTokenTrials =
         sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? numberOfFailedTokenTrials;
     isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure;
-    disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy;
-    disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell;
+    disableTradeOption = sharedPreferences.getBool(PreferencesKey.disableTradeOption) ?? disableTradeOption;
     disableBulletin =
         sharedPreferences.getBool(PreferencesKey.disableBulletinKey) ?? disableBulletin;
     walletListOrder =
diff --git a/lib/typography.dart b/lib/typography.dart
index 8ae2cb4e5..816f116b4 100644
--- a/lib/typography.dart
+++ b/lib/typography.dart
@@ -22,6 +22,8 @@ TextStyle textMediumSemiBold({Color? color}) => _cakeSemiBold(22, color);
 
 TextStyle textLarge({Color? color}) => _cakeRegular(18, color);
 
+TextStyle textLargeBold({Color? color}) => _cakeBold(18, color);
+
 TextStyle textLargeSemiBold({Color? color}) => _cakeSemiBold(24, color);
 
 TextStyle textXLarge({Color? color}) => _cakeRegular(32, color);
diff --git a/lib/view_model/buy/buy_sell_view_model.dart b/lib/view_model/buy/buy_sell_view_model.dart
new file mode 100644
index 000000000..e1c53ee56
--- /dev/null
+++ b/lib/view_model/buy/buy_sell_view_model.dart
@@ -0,0 +1,446 @@
+import 'dart:async';
+
+import 'package:cake_wallet/buy/buy_provider.dart';
+import 'package:cake_wallet/buy/buy_quote.dart';
+import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
+import 'package:cake_wallet/buy/payment_method.dart';
+import 'package:cake_wallet/buy/sell_buy_states.dart';
+import 'package:cake_wallet/core/selectable_option.dart';
+import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
+import 'package:cake_wallet/entities/fiat_currency.dart';
+import 'package:cake_wallet/entities/provider_types.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/routes.dart';
+import 'package:cake_wallet/store/app_store.dart';
+import 'package:cake_wallet/store/settings_store.dart';
+import 'package:cake_wallet/themes/theme_base.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/currency_for_wallet_type.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:intl/intl.dart';
+import 'package:mobx/mobx.dart';
+
+part 'buy_sell_view_model.g.dart';
+
+class BuySellViewModel = BuySellViewModelBase with _$BuySellViewModel;
+
+abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with Store {
+  BuySellViewModelBase(
+    AppStore appStore,
+  )   : _cryptoNumberFormat = NumberFormat(),
+        cryptoAmount = '',
+        fiatAmount = '',
+        cryptoCurrencyAddress = '',
+        isCryptoCurrencyAddressEnabled = false,
+        cryptoCurrencies = <CryptoCurrency>[],
+        fiatCurrencies = <FiatCurrency>[],
+        paymentMethodState = InitialPaymentMethod(),
+        buySellQuotState = InitialBuySellQuotState(),
+        cryptoCurrency = appStore.wallet!.currency,
+        fiatCurrency = appStore.settingsStore.fiatCurrency,
+        providerList = [],
+        sortedRecommendedQuotes = ObservableList<Quote>(),
+        sortedQuotes = ObservableList<Quote>(),
+        paymentMethods = ObservableList<PaymentMethod>(),
+        settingsStore = appStore.settingsStore,
+        super(appStore: appStore) {
+    const excludeFiatCurrencies = [];
+    const excludeCryptoCurrencies = [];
+
+    fiatCurrencies =
+        FiatCurrency.all.where((currency) => !excludeFiatCurrencies.contains(currency)).toList();
+    cryptoCurrencies = CryptoCurrency.all
+        .where((currency) => !excludeCryptoCurrencies.contains(currency))
+        .toList();
+    _initialize();
+
+    isCryptoCurrencyAddressEnabled = !(cryptoCurrency == wallet.currency);
+  }
+
+  final NumberFormat _cryptoNumberFormat;
+  late Timer bestRateSync;
+
+  List<BuyProvider> get availableBuyProviders {
+    final providerTypes = ProvidersHelper.getAvailableBuyProviderTypes(
+        walletTypeForCurrency(cryptoCurrency) ?? wallet.type);
+    return providerTypes
+        .map((type) => ProvidersHelper.getProviderByType(type))
+        .where((provider) => provider != null)
+        .cast<BuyProvider>()
+        .toList();
+  }
+
+  List<BuyProvider> get availableSellProviders {
+    final providerTypes = ProvidersHelper.getAvailableSellProviderTypes(
+        walletTypeForCurrency(cryptoCurrency) ?? wallet.type);
+    return providerTypes
+        .map((type) => ProvidersHelper.getProviderByType(type))
+        .where((provider) => provider != null)
+        .cast<BuyProvider>()
+        .toList();
+  }
+
+  @override
+  void onWalletChange(wallet) {
+    cryptoCurrency = wallet.currency;
+  }
+
+  bool get isDarkTheme => settingsStore.currentTheme.type == ThemeType.dark;
+
+  double get amount {
+    final formattedFiatAmount = double.tryParse(fiatAmount) ?? 200.0;
+    final formattedCryptoAmount =
+        double.tryParse(cryptoAmount) ?? (cryptoCurrency == CryptoCurrency.btc ? 0.001 : 1);
+
+    return isBuyAction ? formattedFiatAmount : formattedCryptoAmount;
+  }
+
+  SettingsStore settingsStore;
+
+  Quote? bestRateQuote;
+
+  Quote? selectedQuote;
+
+  @observable
+  List<CryptoCurrency> cryptoCurrencies;
+
+  @observable
+  List<FiatCurrency> fiatCurrencies;
+
+  @observable
+  bool isBuyAction = true;
+
+  @observable
+  List<BuyProvider> providerList;
+
+  @observable
+  ObservableList<Quote> sortedRecommendedQuotes;
+
+  @observable
+  ObservableList<Quote> sortedQuotes;
+
+  @observable
+  ObservableList<PaymentMethod> paymentMethods;
+
+  @observable
+  FiatCurrency fiatCurrency;
+
+  @observable
+  CryptoCurrency cryptoCurrency;
+
+  @observable
+  String cryptoAmount;
+
+  @observable
+  String fiatAmount;
+
+  @observable
+  String cryptoCurrencyAddress;
+
+  @observable
+  bool isCryptoCurrencyAddressEnabled;
+
+  @observable
+  PaymentMethod? selectedPaymentMethod;
+
+  @observable
+  PaymentMethodLoadingState paymentMethodState;
+
+  @observable
+  BuySellQuotLoadingState buySellQuotState;
+
+  @computed
+  bool get isReadyToTrade {
+    final hasSelectedQuote = selectedQuote != null;
+    final hasSelectedPaymentMethod = selectedPaymentMethod != null;
+    final isPaymentMethodLoaded = paymentMethodState is PaymentMethodLoaded;
+    final isBuySellQuotLoaded = buySellQuotState is BuySellQuotLoaded;
+
+    return hasSelectedQuote &&
+        hasSelectedPaymentMethod &&
+        isPaymentMethodLoaded &&
+        isBuySellQuotLoaded;
+  }
+
+  @action
+  void reset() {
+    cryptoCurrency = wallet.currency;
+    fiatCurrency = settingsStore.fiatCurrency;
+    isCryptoCurrencyAddressEnabled = !(cryptoCurrency == wallet.currency);
+    _initialize();
+  }
+
+  @action
+  void changeBuySellAction() {
+    isBuyAction = !isBuyAction;
+    _initialize();
+  }
+
+  @action
+  void changeFiatCurrency({required FiatCurrency currency}) {
+    fiatCurrency = currency;
+    _onPairChange();
+  }
+
+  @action
+  void changeCryptoCurrency({required CryptoCurrency currency}) {
+    cryptoCurrency = currency;
+    _onPairChange();
+    isCryptoCurrencyAddressEnabled = !(cryptoCurrency == wallet.currency);
+  }
+
+  @action
+  void changeCryptoCurrencyAddress(String address) => cryptoCurrencyAddress = address;
+
+  @action
+  Future<void> changeFiatAmount({required String amount}) async {
+    fiatAmount = amount;
+
+    if (amount.isEmpty) {
+      fiatAmount = '';
+      cryptoAmount = '';
+      return;
+    }
+
+    final enteredAmount = double.tryParse(amount.replaceAll(',', '.')) ?? 0;
+
+    if (!isReadyToTrade) {
+      cryptoAmount = S.current.fetching;
+      return;
+    }
+
+    if (bestRateQuote != null) {
+      _cryptoNumberFormat.maximumFractionDigits = cryptoCurrency.decimals;
+      cryptoAmount = _cryptoNumberFormat
+          .format(enteredAmount / bestRateQuote!.rate)
+          .toString()
+          .replaceAll(RegExp('\\,'), '');
+    } else {
+      await calculateBestRate();
+    }
+  }
+
+  @action
+  Future<void> changeCryptoAmount({required String amount}) async {
+    cryptoAmount = amount;
+
+    if (amount.isEmpty) {
+      fiatAmount = '';
+      cryptoAmount = '';
+      return;
+    }
+
+    final enteredAmount = double.tryParse(amount.replaceAll(',', '.')) ?? 0;
+
+    if (!isReadyToTrade) {
+      fiatAmount = S.current.fetching;
+    }
+
+    if (bestRateQuote != null) {
+      fiatAmount = _cryptoNumberFormat
+          .format(enteredAmount * bestRateQuote!.rate)
+          .toString()
+          .replaceAll(RegExp('\\,'), '');
+    } else {
+      await calculateBestRate();
+    }
+  }
+
+  @action
+  void changeOption(SelectableOption option) {
+    if (option is Quote) {
+      sortedRecommendedQuotes.forEach((element) => element.setIsSelected = false);
+      sortedQuotes.forEach((element) => element.setIsSelected = false);
+      option.setIsSelected = true;
+      selectedQuote = option;
+    } else if (option is PaymentMethod) {
+      paymentMethods.forEach((element) => element.isSelected = false);
+      option.isSelected = true;
+      selectedPaymentMethod = option;
+    } else {
+      throw ArgumentError('Unknown option type');
+    }
+  }
+
+  void onTapChoseProvider(BuildContext context) async {
+    final initialQuotes = List<Quote>.from(sortedRecommendedQuotes + sortedQuotes);
+    await calculateBestRate();
+    final newQuotes = (sortedRecommendedQuotes + sortedQuotes);
+
+    for (var quote in newQuotes) quote.limits = null;
+
+    final newQuoteProviders = newQuotes
+        .map((quote) => quote.provider.isAggregator ? quote.rampName : quote.provider.title)
+        .toSet();
+
+    final outOfLimitQuotes = initialQuotes.where((initialQuote) {
+      return !newQuoteProviders.contains(
+          initialQuote.provider.isAggregator ? initialQuote.rampName : initialQuote.provider.title);
+    }).map((missingQuote) {
+      final quote = Quote(
+        rate: missingQuote.rate,
+        feeAmount: missingQuote.feeAmount,
+        networkFee: missingQuote.networkFee,
+        transactionFee: missingQuote.transactionFee,
+        payout: missingQuote.payout,
+        rampId: missingQuote.rampId,
+        rampName: missingQuote.rampName,
+        rampIconPath: missingQuote.rampIconPath,
+        paymentType: missingQuote.paymentType,
+        quoteId: missingQuote.quoteId,
+        recommendations: missingQuote.recommendations,
+        provider: missingQuote.provider,
+        isBuyAction: missingQuote.isBuyAction,
+        limits: missingQuote.limits,
+      );
+      quote.setFiatCurrency = missingQuote.fiatCurrency;
+      quote.setCryptoCurrency = missingQuote.cryptoCurrency;
+      return quote;
+    }).toList();
+
+    final updatedQuoteOptions = List<SelectableItem>.from([
+      OptionTitle(title: 'Recommended'),
+      ...sortedRecommendedQuotes,
+      if (sortedQuotes.isNotEmpty) OptionTitle(title: 'All Providers'),
+      ...sortedQuotes,
+      if (outOfLimitQuotes.isNotEmpty) OptionTitle(title: 'Out of Limits'),
+      ...outOfLimitQuotes,
+    ]);
+
+    await Navigator.of(context).pushNamed(
+      Routes.buyOptionsPage,
+      arguments: [
+        updatedQuoteOptions,
+        changeOption,
+        launchTrade,
+      ],
+    ).then((value) => calculateBestRate());
+  }
+
+  void _onPairChange() {
+    _initialize();
+  }
+
+  void _setProviders() =>
+      providerList = isBuyAction ? availableBuyProviders : availableSellProviders;
+
+  Future<void> _initialize() async {
+    _setProviders();
+    cryptoAmount = '';
+    fiatAmount = '';
+    cryptoCurrencyAddress = _getInitialCryptoCurrencyAddress();
+    paymentMethodState = InitialPaymentMethod();
+    buySellQuotState = InitialBuySellQuotState();
+    await _getAvailablePaymentTypes();
+    await calculateBestRate();
+  }
+
+  String _getInitialCryptoCurrencyAddress() {
+    return cryptoCurrency == wallet.currency ? wallet.walletAddresses.address : '';
+  }
+
+  @action
+  Future<void> _getAvailablePaymentTypes() async {
+    paymentMethodState = PaymentMethodLoading();
+    selectedPaymentMethod = null;
+    final result = await Future.wait(providerList.map((element) => element
+        .getAvailablePaymentTypes(fiatCurrency.title, cryptoCurrency.title, isBuyAction)
+        .timeout(
+          Duration(seconds: 10),
+          onTimeout: () => [],
+        )));
+
+    final Map<PaymentType, PaymentMethod> uniquePaymentMethods = {};
+    for (var methods in result) {
+      for (var method in methods) {
+        uniquePaymentMethods[method.paymentMethodType] = method;
+      }
+    }
+
+    paymentMethods = ObservableList<PaymentMethod>.of(uniquePaymentMethods.values);
+    if (paymentMethods.isNotEmpty) {
+      paymentMethods.insert(0, PaymentMethod.all());
+      selectedPaymentMethod = paymentMethods.first;
+      selectedPaymentMethod!.isSelected = true;
+      paymentMethodState = PaymentMethodLoaded();
+    } else {
+      paymentMethodState = PaymentMethodFailed();
+    }
+  }
+
+  @action
+  Future<void> calculateBestRate() async {
+    buySellQuotState = BuySellQuotLoading();
+
+    final result = await Future.wait<List<Quote>?>(providerList.map((element) => element
+        .fetchQuote(
+          cryptoCurrency: cryptoCurrency,
+          fiatCurrency: fiatCurrency,
+          amount: amount,
+          paymentType: selectedPaymentMethod?.paymentMethodType,
+          isBuyAction: isBuyAction,
+          walletAddress: wallet.walletAddresses.address,
+        )
+        .timeout(
+          Duration(seconds: 10),
+          onTimeout: () => null,
+        )));
+
+    sortedRecommendedQuotes.clear();
+    sortedQuotes.clear();
+
+    final validQuotes = result
+        .where((element) => element != null && element.isNotEmpty)
+        .expand((element) => element!)
+        .toList();
+
+    if (validQuotes.isEmpty) {
+      buySellQuotState = BuySellQuotFailed();
+      return;
+    }
+
+    validQuotes.sort((a, b) => a.rate.compareTo(b.rate));
+
+    final Set<String> addedProviders = {};
+    final List<Quote> uniqueProviderQuotes = validQuotes.where((element) {
+      if (addedProviders.contains(element.provider.title)) return false;
+      addedProviders.add(element.provider.title);
+      return true;
+    }).toList();
+
+    sortedRecommendedQuotes.addAll(uniqueProviderQuotes);
+
+    sortedQuotes = ObservableList.of(
+        validQuotes.where((element) => !uniqueProviderQuotes.contains(element)).toList());
+
+    if (sortedRecommendedQuotes.isNotEmpty) {
+      sortedRecommendedQuotes.first
+        ..setIsBestRate = true
+        ..recommendations.insert(0, ProviderRecommendation.bestRate);
+      bestRateQuote = sortedRecommendedQuotes.first;
+
+      sortedRecommendedQuotes.sort((a, b) {
+        if (a.provider is OnRamperBuyProvider) return -1;
+        if (b.provider is OnRamperBuyProvider) return 1;
+        return 0;
+      });
+
+      selectedQuote = sortedRecommendedQuotes.first;
+      sortedRecommendedQuotes.first.setIsSelected = true;
+    }
+
+    buySellQuotState = BuySellQuotLoaded();
+  }
+
+  @action
+  Future<void> launchTrade(BuildContext context) async {
+    final provider = selectedQuote!.provider;
+    await provider.launchProvider(
+      context: context,
+      quote: selectedQuote!,
+      amount: amount,
+      isBuyAction: isBuyAction,
+      cryptoCurrencyAddress: cryptoCurrencyAddress,
+    );
+  }
+}
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 934cbdee7..a78012ae9 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -71,8 +71,7 @@ abstract class DashboardViewModelBase with Store {
       required this.anonpayTransactionsStore,
       required this.sharedPreferences,
       required this.keyService})
-      : hasSellAction = false,
-        hasBuyAction = false,
+      : hasTradeAction = false,
         hasExchangeAction = false,
         isShowFirstYatIntroduction = false,
         isShowSecondYatIntroduction = false,
@@ -521,37 +520,8 @@ abstract class DashboardViewModelBase with Store {
 
   Map<String, List<FilterItem>> filterItems;
 
-  BuyProvider? get defaultBuyProvider => ProvidersHelper.getProviderByType(
-      settingsStore.defaultBuyProviders[wallet.type] ?? ProviderType.askEachTime);
-
-  BuyProvider? get defaultSellProvider => ProvidersHelper.getProviderByType(
-      settingsStore.defaultSellProviders[wallet.type] ?? ProviderType.askEachTime);
-
   bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
 
-  List<BuyProvider> get availableBuyProviders {
-    final providerTypes = ProvidersHelper.getAvailableBuyProviderTypes(wallet.type);
-    return providerTypes
-        .map((type) => ProvidersHelper.getProviderByType(type))
-        .where((provider) => provider != null)
-        .cast<BuyProvider>()
-        .toList();
-  }
-
-  bool get hasBuyProviders => ProvidersHelper.getAvailableBuyProviderTypes(wallet.type).isNotEmpty;
-
-  List<BuyProvider> get availableSellProviders {
-    final providerTypes = ProvidersHelper.getAvailableSellProviderTypes(wallet.type);
-    return providerTypes
-        .map((type) => ProvidersHelper.getProviderByType(type))
-        .where((provider) => provider != null)
-        .cast<BuyProvider>()
-        .toList();
-  }
-
-  bool get hasSellProviders =>
-      ProvidersHelper.getAvailableSellProviderTypes(wallet.type).isNotEmpty;
-
   bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
 
   @action
@@ -564,16 +534,10 @@ abstract class DashboardViewModelBase with Store {
   bool hasExchangeAction;
 
   @computed
-  bool get isEnabledBuyAction => !settingsStore.disableBuy && hasBuyProviders;
+  bool get isEnabledTradeAction => !settingsStore.disableTradeOption;
 
   @observable
-  bool hasBuyAction;
-
-  @computed
-  bool get isEnabledSellAction => !settingsStore.disableSell && hasSellProviders;
-
-  @observable
-  bool hasSellAction;
+  bool hasTradeAction;
 
   @computed
   bool get isEnabledBulletinAction => !settingsStore.disableBulletin;
@@ -776,8 +740,7 @@ abstract class DashboardViewModelBase with Store {
 
   void updateActions() {
     hasExchangeAction = !isHaven;
-    hasBuyAction = !isHaven;
-    hasSellAction = !isHaven;
+    hasTradeAction = !isHaven;
   }
 
   @computed
diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart
index 9af8c67cf..3036e8ae9 100644
--- a/lib/view_model/settings/other_settings_view_model.dart
+++ b/lib/view_model/settings/other_settings_view_model.dart
@@ -65,29 +65,6 @@ abstract class OtherSettingsViewModelBase with Store {
       _wallet.type == WalletType.solana ||
       _wallet.type == WalletType.tron);
 
-  @computed
-  bool get isEnabledBuyAction =>
-      !_settingsStore.disableBuy && _wallet.type != WalletType.haven;
-
-  @computed
-  bool get isEnabledSellAction =>
-      !_settingsStore.disableSell && _wallet.type != WalletType.haven;
-
-  List<ProviderType> get availableBuyProvidersTypes {
-    return ProvidersHelper.getAvailableBuyProviderTypes(walletType);
-  }
-
-  List<ProviderType> get availableSellProvidersTypes =>
-      ProvidersHelper.getAvailableSellProviderTypes(walletType);
-
-  ProviderType get buyProviderType =>
-      _settingsStore.defaultBuyProviders[walletType] ??
-      ProviderType.askEachTime;
-
-  ProviderType get sellProviderType =>
-      _settingsStore.defaultSellProviders[walletType] ??
-      ProviderType.askEachTime;
-
   String getDisplayPriority(dynamic priority) {
     final _priority = priority as TransactionPriority;
 
@@ -115,20 +92,6 @@ abstract class OtherSettingsViewModelBase with Store {
     return priority.toString();
   }
 
-  String getBuyProviderType(dynamic buyProviderType) {
-    final _buyProviderType = buyProviderType as ProviderType;
-    return _buyProviderType == ProviderType.askEachTime
-        ? S.current.ask_each_time
-        : _buyProviderType.title;
-  }
-
-  String getSellProviderType(dynamic sellProviderType) {
-    final _sellProviderType = sellProviderType as ProviderType;
-    return _sellProviderType == ProviderType.askEachTime
-        ? S.current.ask_each_time
-        : _sellProviderType.title;
-  }
-
   void onDisplayPrioritySelected(TransactionPriority priority) =>
       _settingsStore.priority[walletType] = priority;
 
@@ -157,12 +120,4 @@ abstract class OtherSettingsViewModelBase with Store {
     }
     return null;
   }
-
-  @action
-  ProviderType onBuyProviderTypeSelected(ProviderType buyProviderType) =>
-      _settingsStore.defaultBuyProviders[walletType] = buyProviderType;
-
-  @action
-  ProviderType onSellProviderTypeSelected(ProviderType sellProviderType) =>
-      _settingsStore.defaultSellProviders[walletType] = sellProviderType;
 }
diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart
index c1e0fb1ce..eaa9f9e84 100644
--- a/lib/view_model/settings/privacy_settings_view_model.dart
+++ b/lib/view_model/settings/privacy_settings_view_model.dart
@@ -59,10 +59,7 @@ abstract class PrivacySettingsViewModelBase with Store {
   bool get isAppSecure => _settingsStore.isAppSecure;
 
   @computed
-  bool get disableBuy => _settingsStore.disableBuy;
-
-  @computed
-  bool get disableSell => _settingsStore.disableSell;
+  bool get disableTradeOption => _settingsStore.disableTradeOption;
 
   @computed
   bool get disableBulletin => _settingsStore.disableBulletin;
@@ -119,10 +116,7 @@ abstract class PrivacySettingsViewModelBase with Store {
   void setIsAppSecure(bool value) => _settingsStore.isAppSecure = value;
 
   @action
-  void setDisableBuy(bool value) => _settingsStore.disableBuy = value;
-
-  @action
-  void setDisableSell(bool value) => _settingsStore.disableSell = value;
+  void setDisableTradeOption(bool value) => _settingsStore.disableTradeOption = value;
 
   @action
   void setDisableBulletin(bool value) => _settingsStore.disableBulletin = value;
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index fc0ea8ea9..9ebab6b6f 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "تم تغيير ممثل بنجاح",
   "change_wallet_alert_content": "هل تريد تغيير المحفظة الحالية إلى ${wallet_name}؟",
   "change_wallet_alert_title": "تغيير المحفظة الحالية",
+  "choose_a_payment_method": "اختر طريقة الدفع",
+  "choose_a_provider": "اختر مزودًا",
   "choose_account": "اختر حساب",
   "choose_address": "\n\nالرجاء اختيار عنوان:",
   "choose_card_value": "اختر قيمة بطاقة",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "من خلال إيقاف تشغيل هذا ، قد تكون معدلات الرسوم غير دقيقة في بعض الحالات ، لذلك قد ينتهي بك الأمر إلى دفع مبالغ زائدة أو دفع رسوم المعاملات الخاصة بك",
   "disable_fiat": "تعطيل fiat",
   "disable_sell": "قم بتعطيل إجراء البيع",
+  "disable_trade_option": "تعطيل خيار التجارة",
   "disableBatteryOptimization": "تعطيل تحسين البطارية",
   "disableBatteryOptimizationDescription": "هل تريد تعطيل تحسين البطارية من أجل جعل الخلفية مزامنة تعمل بحرية وسلاسة؟",
   "disabled": "معطلة",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index e66a40b36..91256938d 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Успешно промени представител",
   "change_wallet_alert_content": "Искате ли да смените сегашния портфейл на ${wallet_name}?",
   "change_wallet_alert_title": "Смяна на сегашния портфейл",
+  "choose_a_payment_method": "Изберете начин на плащане",
+  "choose_a_provider": "Изберете доставчик",
   "choose_account": "Избиране на профил",
   "choose_address": "\n\nМоля, изберете адреса:",
   "choose_card_value": "Изберете стойност на картата",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "Като изключите това, таксите могат да бъдат неточни в някои случаи, така че може да се препланите или да не плащате таксите за вашите транзакции",
   "disable_fiat": "Деактивиране на fiat",
   "disable_sell": "Деактивирайте действието за продажба",
+  "disable_trade_option": "Деактивирайте опцията за търговия",
   "disableBatteryOptimization": "Деактивирайте оптимизацията на батерията",
   "disableBatteryOptimizationDescription": "Искате ли да деактивирате оптимизацията на батерията, за да направите синхронизирането на фона да работи по -свободно и гладко?",
   "disabled": "Деактивирано",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index 4911030b2..0fe38166c 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Úspěšně změnil zástupce",
   "change_wallet_alert_content": "Opravdu chcete změnit aktivní peněženku na ${wallet_name}?",
   "change_wallet_alert_title": "Přepnout peněženku",
+  "choose_a_payment_method": "Vyberte metodu platby",
+  "choose_a_provider": "Vyberte poskytovatele",
   "choose_account": "Zvolte částku",
   "choose_address": "\n\nProsím vyberte adresu:",
   "choose_card_value": "Vyberte hodnotu karty",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Zakázat možnost TRADE",
   "disableBatteryOptimization": "Zakázat optimalizaci baterie",
   "disableBatteryOptimizationDescription": "Chcete deaktivovat optimalizaci baterie, aby se synchronizovala pozadí volně a hladce?",
   "disabled": "Zakázáno",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index a69174dd6..212ce05f7 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Vertreter erfolgreich gerändert",
   "change_wallet_alert_content": "Möchten Sie die aktuelle Wallet zu ${wallet_name} ändern?",
   "change_wallet_alert_title": "Aktuelle Wallet ändern",
+  "choose_a_payment_method": "Wählen Sie eine Zahlungsmethode",
+  "choose_a_provider": "Wählen Sie einen Anbieter",
   "choose_account": "Konto auswählen",
   "choose_address": "\n\nBitte wählen Sie die Adresse:",
   "choose_card_value": "Wählen Sie einen Kartenwert",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Handelsoption deaktivieren",
   "disableBatteryOptimization": "Batterieoptimierung deaktivieren",
   "disableBatteryOptimizationDescription": "Möchten Sie die Batterieoptimierung deaktivieren, um die Hintergrundsynchronisierung reibungsloser zu gestalten?",
   "disabled": "Deaktiviert",
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index 322e38b85..15e0c04b3 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Successfully changed representative",
   "change_wallet_alert_content": "Do you want to change current wallet to ${wallet_name}?",
   "change_wallet_alert_title": "Change current wallet",
+  "choose_a_payment_method": "Choose a payment method",
+  "choose_a_provider": "Choose a provider",
   "choose_account": "Choose account",
   "choose_address": "\n\nPlease choose the address:",
   "choose_card_value": "Choose a card value",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Disable trade option",
   "disableBatteryOptimization": "Disable Battery Optimization",
   "disableBatteryOptimizationDescription": "Do you want to disable battery optimization in order to make background sync run more freely and smoothly?",
   "disabled": "Disabled",
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 5a8ff0582..83c0a09f0 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Representante cambiado con éxito",
   "change_wallet_alert_content": "¿Quieres cambiar la billetera actual a ${wallet_name}?",
   "change_wallet_alert_title": "Cambiar billetera actual",
+  "choose_a_payment_method": "Elija un método de pago",
+  "choose_a_provider": "Elija un proveedor",
   "choose_account": "Elegir cuenta",
   "choose_address": "\n\nPor favor elija la dirección:",
   "choose_card_value": "Elige un valor de tarjeta",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Deshabilitar la opción de comercio",
   "disableBatteryOptimization": "Deshabilitar la optimización de la batería",
   "disableBatteryOptimizationDescription": "¿Desea deshabilitar la optimización de la batería para que la sincronización de fondo se ejecute más libremente y sin problemas?",
   "disabled": "Desactivado",
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index 6abe72681..549ec5275 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Représentant changé avec succès",
   "change_wallet_alert_content": "Souhaitez-vous changer le portefeuille (wallet) actuel vers ${wallet_name} ?",
   "change_wallet_alert_title": "Changer le portefeuille (wallet) actuel",
+  "choose_a_payment_method": "Choisissez un mode de paiement",
+  "choose_a_provider": "Choisissez un fournisseur",
   "choose_account": "Choisir le compte",
   "choose_address": "\n\nMerci de choisir l'adresse :",
   "choose_card_value": "Choisissez une valeur de carte",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Désactiver l'option de commerce",
   "disableBatteryOptimization": "Désactiver l'optimisation de la batterie",
   "disableBatteryOptimizationDescription": "Voulez-vous désactiver l'optimisation de la batterie afin de faire fonctionner la synchronisation d'arrière-plan plus librement et en douceur?",
   "disabled": "Désactivé",
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index 5a53d6795..222a9cf2f 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "An samu nasarar canzawa wakilin",
   "change_wallet_alert_content": "Kana so ka canja walat yanzu zuwa ${wallet_name}?",
   "change_wallet_alert_title": "Canja walat yanzu",
+  "choose_a_payment_method": "Zabi hanyar biyan kuɗi",
+  "choose_a_provider": "Zabi mai bada",
   "choose_account": "Zaɓi asusu",
   "choose_address": "\n\n Da fatan za a zaɓi adireshin:",
   "choose_card_value": "Zabi darajar katin",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Musaki zaɓi na kasuwanci",
   "disableBatteryOptimization": "Kashe ingantawa baturi",
   "disableBatteryOptimizationDescription": "Shin kana son kashe ingantawa baturi don yin setnc bankwali gudu da yar kyauta da kyau?",
   "disabled": "tsaya",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index d130c2b5f..1b2f3a1b3 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "सफलतापूर्वक बदलकर प्रतिनिधि",
   "change_wallet_alert_content": "क्या आप करंट वॉलेट को बदलना चाहते हैं ${wallet_name}?",
   "change_wallet_alert_title": "वर्तमान बटुआ बदलें",
+  "choose_a_payment_method": "एक भुगतान विधि का चयन करें",
+  "choose_a_provider": "एक प्रदाता चुनें",
   "choose_account": "खाता चुनें",
   "choose_address": "\n\nकृपया पता चुनें:",
   "choose_card_value": "एक कार्ड मूल्य चुनें",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "इसे बंद करने से, कुछ मामलों में शुल्क दरें गलत हो सकती हैं, इसलिए आप अपने लेनदेन के लिए फीस को कम कर सकते हैं या कम कर सकते हैं",
   "disable_fiat": "िएट को अक्षम करें",
   "disable_sell": "बेचने की कार्रवाई अक्षम करें",
+  "disable_trade_option": "व्यापार विकल्प अक्षम करें",
   "disableBatteryOptimization": "बैटरी अनुकूलन अक्षम करें",
   "disableBatteryOptimizationDescription": "क्या आप बैकग्राउंड सिंक को अधिक स्वतंत्र और सुचारू रूप से चलाने के लिए बैटरी ऑप्टिमाइज़ेशन को अक्षम करना चाहते हैं?",
   "disabled": "अक्षम",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 037e6e9f2..4e106fdf6 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Uspješno promijenjena reprezentativna",
   "change_wallet_alert_content": "Želite li promijeniti trenutni novčanik u ${wallet_name}?",
   "change_wallet_alert_title": "Izmijeni trenutni novčanik",
+  "choose_a_payment_method": "Odaberite način plaćanja",
+  "choose_a_provider": "Odaberite davatelja usluga",
   "choose_account": "Odaberi račun",
   "choose_address": "\n\nOdaberite adresu:",
   "choose_card_value": "Odaberite vrijednost kartice",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Onemogući trgovinsku opciju",
   "disableBatteryOptimization": "Onemogući optimizaciju baterije",
   "disableBatteryOptimizationDescription": "Želite li onemogućiti optimizaciju baterije kako bi se pozadinska sinkronizacija radila slobodnije i glatko?",
   "disabled": "Onemogućeno",
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index 04a7cddf5..40142ca5b 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Ներկայացուցչի փոփոխությունը հաջողությամբ կատարվեց",
   "change_wallet_alert_content": "Ցանկանում եք փոխել ընթացիկ դրամապանակը ${wallet_name}?",
   "change_wallet_alert_title": "Փոխել ընթացիկ դրամապանակը",
+  "choose_a_payment_method": "Ընտրեք վճարման եղանակ",
+  "choose_a_provider": "Ընտրեք մատակարար",
   "choose_account": "Ընտրեք հաշիվը",
   "choose_address": "\n\nԽնդրում ենք ընտրեք հասցեն",
   "choose_card_value": "Ընտրեք քարտի արժեք",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "Դրանից անջատելով, վճարների տեմպերը որոշ դեպքերում կարող են անճիշտ լինել, այնպես որ դուք կարող եք վերջ տալ ձեր գործարքների համար վճարների գերավճարների կամ գերավճարների վրա",
   "disable_fiat": "Անջատել ֆիատ",
   "disable_sell": "Անջատել վաճառք գործողությունը",
+  "disable_trade_option": "Անջատեք առեւտրի տարբերակը",
   "disableBatteryOptimization": "Անջատել մարտկոցի օպտիմիզացիան",
   "disableBatteryOptimizationDescription": "Դուք ցանկանում եք անջատել մարտկոցի օպտիմիզացիան ֆոնային համաժամացման ավելի ազատ և հարթ ընթացքի համար?",
   "disabled": "Անջատված",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index 231ac037d..04336b76e 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Berhasil mengubah perwakilan",
   "change_wallet_alert_content": "Apakah Anda ingin mengganti dompet saat ini ke ${wallet_name}?",
   "change_wallet_alert_title": "Ganti dompet saat ini",
+  "choose_a_payment_method": "Pilih metode pembayaran",
+  "choose_a_provider": "Pilih penyedia",
   "choose_account": "Pilih akun",
   "choose_address": "\n\nSilakan pilih alamat:",
   "choose_card_value": "Pilih nilai kartu",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Nonaktifkan opsi perdagangan",
   "disableBatteryOptimization": "Nonaktifkan optimasi baterai",
   "disableBatteryOptimizationDescription": "Apakah Anda ingin menonaktifkan optimasi baterai untuk membuat sinkronisasi latar belakang berjalan lebih bebas dan lancar?",
   "disabled": "Dinonaktifkan",
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index b06a35537..ad15ab3a9 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Rappresentante modificato con successo",
   "change_wallet_alert_content": "Sei sicuro di voler cambiare il portafoglio attuale con ${wallet_name}?",
   "change_wallet_alert_title": "Cambia portafoglio attuale",
+  "choose_a_payment_method": "Scegli un metodo di pagamento",
+  "choose_a_provider": "Scegli un fornitore",
   "choose_account": "Scegli account",
   "choose_address": "\n\nSi prega di scegliere l'indirizzo:",
   "choose_card_value": "Scegli un valore della carta",
@@ -218,6 +220,7 @@
   "disable_fee_api_warning": "Disattivando questo, i tassi delle commissioni potrebbero essere inaccurati in alcuni casi, quindi potresti finire in eccesso o sostenere le commissioni per le transazioni",
   "disable_fiat": "Disabilita fiat",
   "disable_sell": "Disabilita l'azione di vendita",
+  "disable_trade_option": "Disabilita l'opzione commerciale",
   "disableBatteryOptimization": "Disabilita l'ottimizzazione della batteria",
   "disableBatteryOptimizationDescription": "Vuoi disabilitare l'ottimizzazione della batteria per far funzionare la sincronizzazione in background più libera e senza intoppi?",
   "disabled": "Disabilitato",
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index d55c4d5a1..520a73ade 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "代表者の変更に成功しました",
   "change_wallet_alert_content": "現在のウォレットをに変更しますか ${wallet_name}?",
   "change_wallet_alert_title": "現在のウォレットを変更する",
+  "choose_a_payment_method": "支払い方法を選択します",
+  "choose_a_provider": "プロバイダーを選択します",
   "choose_account": "アカウントを選択",
   "choose_address": "\n\n住所を選択してください:",
   "choose_card_value": "カード値を選択します",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "これをオフにすることで、料金金利は場合によっては不正確になる可能性があるため、取引の費用が過払いまたは不足している可能性があります",
   "disable_fiat": "フィアットを無効にする",
   "disable_sell": "販売アクションを無効にする",
+  "disable_trade_option": "取引オプションを無効にします",
   "disableBatteryOptimization": "バッテリーの最適化を無効にします",
   "disableBatteryOptimizationDescription": "バックグラウンドシンクをより自由かつスムーズに実行するために、バッテリーの最適化を無効にしたいですか?",
   "disabled": "無効",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 303527fea..1d9748866 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "대리인이 성공적으로 변경되었습니다",
   "change_wallet_alert_content": "현재 지갑을 다음으로 변경 하시겠습니까 ${wallet_name}?",
   "change_wallet_alert_title": "현재 지갑 변경",
+  "choose_a_payment_method": "결제 방법을 선택하십시오",
+  "choose_a_provider": "제공자를 선택하십시오",
   "choose_account": "계정을 선택하십시오",
   "choose_address": "\n\n주소를 선택하십시오:",
   "choose_card_value": "카드 값을 선택하십시오",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "이것을 끄면 경우에 따라 수수료가 부정확 할 수 있으므로 거래 수수료를 초과 지불하거나 지불 할 수 있습니다.",
   "disable_fiat": "법정화폐 비활성화",
   "disable_sell": "판매 조치 비활성화",
+  "disable_trade_option": "거래 옵션 비활성화",
   "disableBatteryOptimization": "배터리 최적화를 비활성화합니다",
   "disableBatteryOptimizationDescription": "백그라운드 동기화를보다 자유롭고 매끄럽게 실행하기 위해 배터리 최적화를 비활성화하고 싶습니까?",
   "disabled": "장애가 있는",
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index 9b9b44657..e6be67060 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "အောင်မြင်စွာကိုယ်စားလှယ်ပြောင်းလဲသွားတယ်",
   "change_wallet_alert_content": "လက်ရှိပိုက်ဆံအိတ်ကို ${wallet_name} သို့ ပြောင်းလိုပါသလား။",
   "change_wallet_alert_title": "လက်ရှိပိုက်ဆံအိတ်ကို ပြောင်းပါ။",
+  "choose_a_payment_method": "ငွေပေးချေမှုနည်းလမ်းကိုရွေးချယ်ပါ",
+  "choose_a_provider": "ပံ့ပိုးပေးရွေးချယ်ပါ",
   "choose_account": "အကောင့်ကို ရွေးပါ။",
   "choose_address": "\n\nလိပ်စာကို ရွေးပါ-",
   "choose_card_value": "ကဒ်တန်ဖိုးတစ်ခုရွေးပါ",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "ဤအရာကိုဖွင့်ခြင်းအားဖြင့်အချို့သောကိစ္စရပ်များတွင်အခကြေးငွေနှုန်းထားများသည်တိကျမှုရှိနိုင်သည်,",
   "disable_fiat": "Fiat ကိုပိတ်ပါ။",
   "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။",
+  "disable_trade_option": "ကုန်သွယ်ရေး option ကိုပိတ်ပါ",
   "disableBatteryOptimization": "ဘက်ထရီ optimization ကိုပိတ်ပါ",
   "disableBatteryOptimizationDescription": "နောက်ခံထပ်တူပြုခြင်းနှင့်ချောချောမွေ့မွေ့ပြုလုပ်နိုင်ရန်ဘက်ထရီ optimization ကိုသင်ပိတ်ထားလိုပါသလား။",
   "disabled": "မသန်စွမ်း",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 657450f61..82c3899d4 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Met succes veranderde vertegenwoordiger",
   "change_wallet_alert_content": "Wilt u de huidige portemonnee wijzigen in ${wallet_name}?",
   "change_wallet_alert_title": "Wijzig huidige portemonnee",
+  "choose_a_payment_method": "Kies een betaalmethode",
+  "choose_a_provider": "Kies een provider",
   "choose_account": "Kies account",
   "choose_address": "\n\nKies het adres:",
   "choose_card_value": "Kies een kaartwaarde",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Schakel handelsoptie uit",
   "disableBatteryOptimization": "Schakel de batterijoptimalisatie uit",
   "disableBatteryOptimizationDescription": "Wilt u de optimalisatie van de batterij uitschakelen om achtergrondsynchronisatie te laten werken, vrijer en soepeler?",
   "disabled": "Gehandicapt",
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index e47c93dcf..ed54624bf 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Pomyślnie zmienił przedstawiciela",
   "change_wallet_alert_content": "Czy chcesz zmienić obecny portfel na ${wallet_name}?",
   "change_wallet_alert_title": "Zmień obecny portfel",
+  "choose_a_payment_method": "Wybierz metodę płatności",
+  "choose_a_provider": "Wybierz dostawcę",
   "choose_account": "Wybierz konto",
   "choose_address": "\n\nWybierz adres:",
   "choose_card_value": "Wybierz wartość karty",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Wyłącz opcję handlu",
   "disableBatteryOptimization": "Wyłącz optymalizację baterii",
   "disableBatteryOptimizationDescription": "Czy chcesz wyłączyć optymalizację baterii, aby synchronizacja tła działała swobodniej i płynnie?",
   "disabled": "Wyłączone",
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index d5aa95c16..7b43b5b12 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Mudou com sucesso o representante",
   "change_wallet_alert_content": "Quer mudar a carteira atual para ${wallet_name}?",
   "change_wallet_alert_title": "Alterar carteira atual",
+  "choose_a_payment_method": "Escolha um método de pagamento",
+  "choose_a_provider": "Escolha um provedor",
   "choose_account": "Escolha uma conta",
   "choose_address": "\n\nEscolha o endereço:",
   "choose_card_value": "Escolha um valor de cartão",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Desativar a opção comercial",
   "disableBatteryOptimization": "Desative a otimização da bateria",
   "disableBatteryOptimizationDescription": "Deseja desativar a otimização da bateria para fazer a sincronização de fundo funcionar de forma mais livre e suave?",
   "disabled": "Desabilitado",
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index f999b4aaa..2795e1ffc 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Успешно изменил представитель",
   "change_wallet_alert_content": "Вы хотите изменить текущий кошелек на ${wallet_name}?",
   "change_wallet_alert_title": "Изменить текущий кошелек",
+  "choose_a_payment_method": "Выберите способ оплаты",
+  "choose_a_provider": "Выберите поставщика",
   "choose_account": "Выберите аккаунт",
   "choose_address": "\n\nПожалуйста, выберите адрес:",
   "choose_card_value": "Выберите значение карты",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "Выключив это, в некоторых случаях ставки платы могут быть неточными, так что вы можете в конечном итоге переплачивать или недоплачивать сборы за ваши транзакции",
   "disable_fiat": "Отключить фиат",
   "disable_sell": "Отключить действие продажи",
+  "disable_trade_option": "Отключить возможность торговли",
   "disableBatteryOptimization": "Отключить оптимизацию батареи",
   "disableBatteryOptimizationDescription": "Вы хотите отключить оптимизацию батареи, чтобы сделать фона синхронизации более свободно и плавно?",
   "disabled": "Отключено",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index a35e16a97..596861646 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "เปลี่ยนตัวแทนสำเร็จ",
   "change_wallet_alert_content": "คุณต้องการเปลี่ยนกระเป๋าปัจจุบันเป็น ${wallet_name} หรือไม่?",
   "change_wallet_alert_title": "เปลี่ยนกระเป๋าปัจจุบัน",
+  "choose_a_payment_method": "เลือกวิธีการชำระเงิน",
+  "choose_a_provider": "เลือกผู้ให้บริการ",
   "choose_account": "เลือกบัญชี",
   "choose_address": "\n\nโปรดเลือกที่อยู่:",
   "choose_card_value": "เลือกค่าบัตร",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "โดยการปิดสิ่งนี้อัตราค่าธรรมเนียมอาจไม่ถูกต้องในบางกรณีดังนั้นคุณอาจจบลงด้วยการจ่ายเงินมากเกินไปหรือจ่ายค่าธรรมเนียมสำหรับการทำธุรกรรมของคุณมากเกินไป",
   "disable_fiat": "ปิดใช้งานสกุลเงินตรา",
   "disable_sell": "ปิดการใช้งานการขาย",
+  "disable_trade_option": "ปิดใช้งานตัวเลือกการค้า",
   "disableBatteryOptimization": "ปิดใช้งานการเพิ่มประสิทธิภาพแบตเตอรี่",
   "disableBatteryOptimizationDescription": "คุณต้องการปิดใช้งานการเพิ่มประสิทธิภาพแบตเตอรี่เพื่อให้การซิงค์พื้นหลังทำงานได้อย่างอิสระและราบรื่นมากขึ้นหรือไม่?",
   "disabled": "ปิดใช้งาน",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index 090bdb8a7..f4678e00d 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Matagumpay na nagbago ng representative",
   "change_wallet_alert_content": "Gusto mo bang palitan ang kasalukuyang wallet sa ${wallet_name}?",
   "change_wallet_alert_title": "Baguhin ang kasalukuyang wallet",
+  "choose_a_payment_method": "Pumili ng isang paraan ng pagbabayad",
+  "choose_a_provider": "Pumili ng isang provider",
   "choose_account": "Pumili ng account",
   "choose_address": "Mangyaring piliin ang address:",
   "choose_card_value": "Pumili ng isang halaga ng card",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Huwag paganahin ang pagpipilian sa kalakalan",
   "disableBatteryOptimization": "Huwag Paganahin ang Pag-optimize ng Baterya",
   "disableBatteryOptimizationDescription": "Nais mo bang huwag paganahin ang pag-optimize ng baterya upang gawing mas malaya at maayos ang background sync?",
   "disabled": "Hindi pinagana",
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index 3a426de9e..d8b3ae3cf 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Temsilciyi başarıyla değiştirdi",
   "change_wallet_alert_content": "Şimdiki cüzdanı ${wallet_name} cüzdanı ile değiştirmek istediğinden emin misin?",
   "change_wallet_alert_title": "Şimdiki cüzdanı değiştir",
+  "choose_a_payment_method": "Bir Ödeme Yöntemi Seçin",
+  "choose_a_provider": "Bir Sağlayıcı Seçin",
   "choose_account": "Hesabı seç",
   "choose_address": "\n\nLütfen adresi seçin:",
   "choose_card_value": "Bir kart değeri seçin",
@@ -217,6 +219,7 @@
   "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",
+  "disable_trade_option": "Ticaret seçeneğini devre dışı bırakın",
   "disableBatteryOptimization": "Pil optimizasyonunu devre dışı bırakın",
   "disableBatteryOptimizationDescription": "Arka plan senkronizasyonunu daha özgür ve sorunsuz bir şekilde çalıştırmak için pil optimizasyonunu devre dışı bırakmak istiyor musunuz?",
   "disabled": "Devre dışı",
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index 63665875f..f27300c18 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Успішно змінив представник",
   "change_wallet_alert_content": "Ви хочете змінити поточний гаманець на ${wallet_name}?",
   "change_wallet_alert_title": "Змінити поточний гаманець",
+  "choose_a_payment_method": "Виберіть метод оплати",
+  "choose_a_provider": "Виберіть постачальника",
   "choose_account": "Оберіть акаунт",
   "choose_address": "\n\nБудь ласка, оберіть адресу:",
   "choose_card_value": "Виберіть значення картки",
@@ -185,7 +187,7 @@
   "creating_new_wallet_error": "Помилка: ${description}",
   "creation_date": "Дата створення",
   "custom": "на замовлення",
-  "custom_drag": "На замовлення (утримуйте та перетягується)",
+  "custom_drag": "На замовлення (утримуйте та перетягуйте)",
   "custom_redeem_amount": "Власна сума викупу",
   "custom_value": "Спеціальне значення",
   "dark_theme": "Темна",
@@ -206,17 +208,18 @@
   "description": "опис",
   "destination_tag": "Тег призначення:",
   "dfx_option_description": "Купуйте криптовалюту з EUR & CHF. Для роздрібних та корпоративних клієнтів у Європі",
-  "didnt_get_code": "Не отримуєте код?",
+  "didnt_get_code": "Не отримали код?",
   "digit_pin": "-значний PIN",
   "digital_and_physical_card": " цифрова та фізична передплачена дебетова картка",
   "disable": "Вимкнути",
   "disable_bulletin": "Вимкнути статус послуги",
   "disable_buy": "Вимкнути дію покупки",
   "disable_cake_2fa": "Вимкнути Cake 2FA",
-  "disable_exchange": "Вимкнути exchange",
+  "disable_exchange": "Вимкнути можливість обміну",
   "disable_fee_api_warning": "Вимкнувши це, ставки плати в деяких випадках можуть бути неточними, тому ви можете переплатити або недооплатити плату за свої транзакції",
   "disable_fiat": "Вимкнути фиат",
   "disable_sell": "Вимкнути дію продажу",
+  "disable_trade_option": "Вимкнути можливість торгівлі",
   "disableBatteryOptimization": "Вимкнути оптимізацію акумулятора",
   "disableBatteryOptimizationDescription": "Ви хочете відключити оптимізацію акумулятора, щоб зробити фонову синхронізацію більш вільно та плавно?",
   "disabled": "Вимкнено",
@@ -226,14 +229,14 @@
   "do_not_have_enough_gas_asset": "У вас недостатньо ${currency}, щоб здійснити трансакцію з поточними умовами мережі блокчейн. Вам потрібно більше ${currency}, щоб сплатити комісію мережі блокчейн, навіть якщо ви надсилаєте інший актив.",
   "do_not_send": "Не надсилайте",
   "do_not_share_warning_text": "Не діліться цим нікому, включно зі службою підтримки.\n\nВаші кошти можуть і будуть вкрадені!",
-  "do_not_show_me": "Не показуй мені це знову",
+  "do_not_show_me": "Не показувати це знову",
   "domain_looks_up": "Пошук доменів",
   "donation_link_details": "Деталі посилання для пожертв",
   "e_sign_consent": "Згода електронного підпису",
   "edit": "Редагувати",
   "edit_backup_password": "Змінити пароль резервної копії",
   "edit_node": "Редагувати вузол",
-  "edit_token": "Редагувати маркер",
+  "edit_token": "Редагувати токен",
   "electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати",
   "email_address": "Адреса електронної пошти",
   "enable": "Ввімкнути",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index 2a40fbe13..00f336d72 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "نمائندہ کو کامیابی کے ساتھ تبدیل کیا",
   "change_wallet_alert_content": "کیا آپ موجودہ والیٹ کو ${wallet_name} میں تبدیل کرنا چاہتے ہیں؟",
   "change_wallet_alert_title": "موجودہ پرس تبدیل کریں۔",
+  "choose_a_payment_method": "ادائیگی کا طریقہ منتخب کریں",
+  "choose_a_provider": "فراہم کنندہ کا انتخاب کریں",
   "choose_account": "اکاؤنٹ کا انتخاب کریں۔",
   "choose_address": "\\n\\nبراہ کرم پتہ منتخب کریں:",
   "choose_card_value": "کارڈ کی قیمت کا انتخاب کریں",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "اس کو بند کرنے سے ، کچھ معاملات میں فیس کی شرح غلط ہوسکتی ہے ، لہذا آپ اپنے لین دین کے لئے فیسوں کو زیادہ ادائیگی یا ادائیگی ختم کرسکتے ہیں۔",
   "disable_fiat": "فیاٹ کو غیر فعال کریں۔",
   "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔",
+  "disable_trade_option": "تجارت کے آپشن کو غیر فعال کریں",
   "disableBatteryOptimization": "بیٹری کی اصلاح کو غیر فعال کریں",
   "disableBatteryOptimizationDescription": "کیا آپ پس منظر کی مطابقت پذیری کو زیادہ آزادانہ اور آسانی سے چلانے کے لئے بیٹری کی اصلاح کو غیر فعال کرنا چاہتے ہیں؟",
   "disabled": "معذور",
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index 9fee9f4fc..1291b505e 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -218,6 +218,7 @@
   "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",
+  "disable_trade_option": "Tắt tùy chọn thương mại",
   "disableBatteryOptimization": "Vô hiệu hóa Tối ưu hóa Pin",
   "disableBatteryOptimizationDescription": "Bạn có muốn vô hiệu hóa tối ưu hóa pin để đồng bộ hóa nền hoạt động mượt mà hơn không?",
   "disabled": "Đã vô hiệu hóa",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 1dd6eafda..c9275b018 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "Ni ifijišẹ yipada aṣoju",
   "change_wallet_alert_content": "Ṣe ẹ fẹ́ pààrọ̀ àpamọ́wọ́ yìí sí ${wallet_name}?",
   "change_wallet_alert_title": "Ẹ pààrọ̀ àpamọ́wọ́ yìí",
+  "choose_a_payment_method": "Yan ọna isanwo kan",
+  "choose_a_provider": "Yan olupese",
   "choose_account": "Yan àkáǹtì",
   "choose_address": "\n\nẸ jọ̀wọ́ yan àdírẹ́sì:",
   "choose_card_value": "Yan iye kaadi",
@@ -217,6 +219,7 @@
   "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ọ",
+  "disable_trade_option": "Mu aṣayan iṣowo ṣiṣẹ",
   "disableBatteryOptimization": "Mu Ifasi batiri",
   "disableBatteryOptimizationDescription": "Ṣe o fẹ lati mu iṣapelo batiri si lati le ṣiṣe ayẹwo ẹhin ati laisiyonu?",
   "disabled": "Wọ́n tí a ti pa",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index 92a540d19..e508d3c2c 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -123,6 +123,8 @@
   "change_rep_successful": "成功改变了代表",
   "change_wallet_alert_content": "您是否想将当前钱包改为 ${wallet_name}?",
   "change_wallet_alert_title": "更换当前钱包",
+  "choose_a_payment_method": "选择付款方式",
+  "choose_a_provider": "选择一个提供商",
   "choose_account": "选择账户",
   "choose_address": "\n\n請選擇地址:",
   "choose_card_value": "选择卡值",
@@ -217,6 +219,7 @@
   "disable_fee_api_warning": "通过将其关闭,在某些情况下,收费率可能不准确,因此您最终可能会超额付款或支付交易费用",
   "disable_fiat": "禁用法令",
   "disable_sell": "禁用卖出操作",
+  "disable_trade_option": "禁用贸易选项",
   "disableBatteryOptimization": "禁用电池优化",
   "disableBatteryOptimizationDescription": "您是否要禁用电池优化以使背景同步更加自由,平稳地运行?",
   "disabled": "禁用",
diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart
index 88cbbfce3..affe4017c 100644
--- a/tool/utils/secret_key.dart
+++ b/tool/utils/secret_key.dart
@@ -44,6 +44,8 @@ class SecretKey {
     SecretKey('cakePayApiKey', () => ''),
     SecretKey('CSRFToken', () => ''),
     SecretKey('authorization', () => ''),
+    SecretKey('meldTestApiKey', () => ''),
+    SecretKey('meldTestPublicKey', () => ''),
     SecretKey('moneroTestWalletSeeds', () => ''),
     SecretKey('moneroLegacyTestWalletSeeds ', () => ''),
     SecretKey('bitcoinTestWalletSeeds', () => ''),

From 288164603723279711dd6a894d48d7645821fb36 Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Sat, 9 Nov 2024 21:07:17 +0200
Subject: [PATCH 38/50] Updatable builds (#1791)

* save and increment build number for each PR

* cd into repo path

* trial

* try generating the release build without a keystore

* cache keystore to maintain same signature for PR builds

* weird fix

* potential fix

* fix key path

* meh

* Update cache_dependencies.yml
---
 .github/workflows/cache_dependencies.yml    | 15 ++++++-
 .github/workflows/pr_test_build_android.yml | 49 ++++++++++++++++++++-
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml
index 0fcd5c45b..ce098b7f1 100644
--- a/.github/workflows/cache_dependencies.yml
+++ b/.github/workflows/cache_dependencies.yml
@@ -67,4 +67,17 @@ jobs:
         run: |
           cd /opt/android/cake_wallet/scripts/android/
           source ./app_env.sh cakewallet
-          ./build_monero_all.sh
\ No newline at end of file
+          ./build_monero_all.sh
+
+      - name: Cache Keystore
+        id: cache-keystore
+        uses: actions/cache@v3
+        with:
+          path: /opt/android/cake_wallet/android/app/key.jks
+          key: $STORE_PASS
+
+      - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }}
+        name: Generate KeyStore
+        run: |
+          cd /opt/android/cake_wallet/android/app
+          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 $STORE_PASS -keypass $KEY_PASS
diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index a12fd422f..1a67ed0ec 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -116,8 +116,15 @@ jobs:
           cd /opt/android/cake_wallet/scripts/android/
           ./build_mwebd.sh --dont-install
 
-      - name: Generate KeyStore
-        if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
+      - name: Cache Keystore
+        id: cache-keystore
+        uses: actions/cache@v3
+        with:
+          path: /opt/android/cake_wallet/android/app/key.jks
+          key: $STORE_PASS
+
+      - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }}
+        name: Generate KeyStore
         run: |
           cd /opt/android/cake_wallet/android/app
           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 $STORE_PASS -keypass $KEY_PASS
@@ -205,6 +212,36 @@ jobs:
         run: |
           echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties
 
+      # Step 3: Download previous build number
+      - name: Download previous build number
+        id: download-build-number
+        run: |
+          # Download the artifact if it exists
+          if [[ ! -f build_number.txt ]]; then
+            echo "1" > build_number.txt
+          fi
+
+      # Step 4: Read and Increment Build Number
+      - name: Increment Build Number
+        id: increment-build-number
+        run: |
+          # Read current build number from file
+          BUILD_NUMBER=$(cat build_number.txt)
+          BUILD_NUMBER=$((BUILD_NUMBER + 1))
+          echo "New build number: $BUILD_NUMBER"
+
+          # Save the incremented build number
+          echo "$BUILD_NUMBER" > build_number.txt
+
+          # Export the build number to use in later steps
+          echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV
+
+      # Step 5: Update pubspec.yaml with new build number
+      - name: Update build number
+        run: |
+          cd /opt/android/cake_wallet
+          sed -i "s/^version: .*/version: 1.0.$BUILD_NUMBER/" pubspec.yaml
+
       - name: Build
         run: |
           cd /opt/android/cake_wallet
@@ -235,6 +272,13 @@ jobs:
         with:
           path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/
 
+      # Re-upload updated build number for the next run
+      - name: Upload updated build number
+        uses: actions/upload-artifact@v3
+        with:
+          name: build_number
+          path: build_number.txt
+
       - name: Send Test APK
         continue-on-error: true
         uses: adrey/slack-file-upload-action@1.0.5
@@ -245,3 +289,4 @@ jobs:
           title: "${{ env.BRANCH_NAME }}.apk"
           filename: ${{ env.BRANCH_NAME }}.apk
           initial_comment: ${{ github.event.head_commit.message }}
+

From 5301ee4584429e57667a4f5a582b3b1538eec659 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Sat, 9 Nov 2024 23:44:08 +0200
Subject: [PATCH 39/50] Update onramper_buy_provider.dart (#1796)

---
 lib/buy/onramper/onramper_buy_provider.dart | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart
index ee9c9bb74..dade41d43 100644
--- a/lib/buy/onramper/onramper_buy_provider.dart
+++ b/lib/buy/onramper/onramper_buy_provider.dart
@@ -217,7 +217,7 @@ class OnRamperBuyProvider extends BuyProvider {
       'apiKey': _apiKey,
       'mode': actionType,
       '${prefix}defaultFiat': quote.fiatCurrency.name,
-      '${prefix}defaultCrypto': quote.cryptoCurrency.name,
+      '${prefix}defaultCrypto': defaultCrypto,
       '${prefix}defaultAmount': amount.toString(),
       if (paymentMethod != null) '${prefix}defaultPaymentMethod': paymentMethod,
       'onlyOnramps': quote.rampId,

From ed69dc803b70d13b83b6d5445171fe99b18e9dee Mon Sep 17 00:00:00 2001
From: OmarHatem <omarh.ismail1@gmail.com>
Date: Sun, 10 Nov 2024 00:14:38 +0200
Subject: [PATCH 40/50] fix cache key

---
 .github/workflows/pr_test_build_android.yml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 1a67ed0ec..1f2a9636e 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -82,8 +82,7 @@ jobs:
           path: |
             /opt/android/cake_wallet/cw_haven/android/.cxx
             /opt/android/cake_wallet/scripts/monero_c/release
-            /opt/android/cake_wallet/android/app/key.jks
-          key: android_${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
+          key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }}
 
       - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
         name: Generate Externals

From 89525b189732973b7e8b32f5be5157a96d0cdab1 Mon Sep 17 00:00:00 2001
From: OmarHatem <omarh.ismail1@gmail.com>
Date: Sun, 10 Nov 2024 01:16:21 +0200
Subject: [PATCH 41/50] temporarily disable key caching

---
 .github/workflows/pr_test_build_android.yml | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 1f2a9636e..774404e3b 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -115,15 +115,15 @@ jobs:
           cd /opt/android/cake_wallet/scripts/android/
           ./build_mwebd.sh --dont-install
 
-      - name: Cache Keystore
-        id: cache-keystore
-        uses: actions/cache@v3
-        with:
-          path: /opt/android/cake_wallet/android/app/key.jks
-          key: $STORE_PASS
-
-      - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }}
-        name: Generate KeyStore
+#      - name: Cache Keystore
+#        id: cache-keystore
+#        uses: actions/cache@v3
+#        with:
+#          path: /opt/android/cake_wallet/android/app/key.jks
+#          key: $STORE_PASS
+#
+#      - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }}
+      - name: Generate KeyStore
         run: |
           cd /opt/android/cake_wallet/android/app
           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 $STORE_PASS -keypass $KEY_PASS

From e148f645086e0c6797aab2121d8e707fa8cc18c7 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Mon, 11 Nov 2024 19:39:45 +0200
Subject: [PATCH 42/50] fix the UI issue with sending outputs (#1798)

---
 lib/view_model/send/send_view_model.dart | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 4621e8d16..69011aa74 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -404,8 +404,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
         final updatedOutputs = bitcoin!.updateOutputs(pendingTransaction!, outputs);
 
         if (outputs.length == updatedOutputs.length) {
-          outputs.clear();
-          outputs.addAll(updatedOutputs);
+          outputs.replaceRange(0, outputs.length, updatedOutputs);
         }
       }
 

From 2c37e427e9eb7e2c882fdd7577f7ab8cfa28c558 Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Tue, 12 Nov 2024 04:26:09 +0100
Subject: [PATCH 43/50] Cw 660 add ledger monero (#1747)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Fix conflicts with main

* fix for multiple wallets

* Add tron to windows application configuration.

* Add macOS option for description message in configure_cake_wallet.sh

* Include missed monero dll for windows.

* fix conflicts with main

* Disable haven configuration for iOS as default. Add ability to configure cakewallet for iOS with  for configuration script. Remove cw_shared configuration for cw_monero.

* fix: scan fixes, add date, allow sending while scanning

* add missing nano secrets file [skip ci]

* ios library

* don't pull prebuilds android

* Add auto generation of manifest file for android project even for iOS, macOS, Windows.

* feat: sync fixes, sp settings

* feat: fix resyncing

* store crash fix

* make init async so it won't lag
disable print starts

* fix monero_c build issues

* libstdc++

* Fix MacOS saving wallet file issue
Fix Secure Storage issue (somehow)

* update pubspec.lock

* fix build script

* Use dylib as iOS framework. Use custom path for loading of iOS framework for monero.dart. Add script for generate iOS framework for monero wallet.

* fix: date from height logic, status disconnected & chain tip get

* fix: params

* feat: electrum migration if using cake electrum

* fix nodes
update versions

* re-enable tron

* update sp_scanner to work on iOS [skip ci]

* bump monero_c hash

* bump monero_c commit

* bump moneroc version

* bump monero_c commit

* Add ability to build monero wallet lib as universal lib. Update macOS build guide. Change default arch for macOS project to .

* fix: wrong socket for old electrum nodes

* Fix unchecked wallet type call

* get App Dir correctly in default_settings_migration.dart

* handle previous issue with fetching linux documents directory [skip ci]

* backup fix

* fix NTFS issues

* Close the wallet when the wallet gets changed

* fix: double balance

* feat: node domain

* fix: menu name

* bump monero_c commit

* fix: update tip on set scanning

* fix: connection switching back and forth

* feat: check if node is electrs, and supports sp

* chore: fix build

* minor enhancements

* fixes and enhancements

* solve conflicts with main

* Only stop wallet on rename and delete

* fix: status toggle

* minor enhancement

* Monero.com fixes

* bump monero_c commit

* update sp_scanner to include windows and linux

* Update macOS build guide. Change brew dependencies for build unbound locally.

* fix conflicts and update macos build guide

* remove build cache when on gh actions

* update secure storage

* free up even more storage

* free up more storage

* Add initial wownero

* fix conflicts

* fix workflow issue

* build wownero

* ios and windows changes

* macos

* complete wownero flow (app side)

* add keychain group entitlement and update script for RunnerBase on macos

* update secure_storage version to 8.1.0 in configure.dart

* add wownero framework

* update ios builds

* proper path for wownero and monero

* finalizing wownero

* finalizing wownero

* free up even more storage

* revert commenting of build gradle configs

* revert commenting of secrets [skip ci]

* free more storage

* minor fixes

* link android wownero libraries

* bump monero_c commit

* wownero fixes

* rename target

* build_single.sh using clean env

* bump monero_c commit

* minor fix

* Add wownero polyseed

* fix conflicts with main

* fix: wallet seed display
fix: wownero not refreshing

* fix: wallet seed display
fix: wownero not refreshing

* bump monero_c commit

* minor fixes

* fix: incorrectly displaying XMR instead of WOW

* fix: incorrect restore height in wownero

* bump monero_c commit

* Add Inno Setup Script for windows exe installer

* drop libc++_shared.so

* fixes from comments

* Fix CMake for windows

* Merge latest monero dart changes [skip ci]

* bump monero_c commit

* add wownero to build scripts for macos [skip ci]

* add 14 word seed support to wownero

* UI fixes for wownero seed restore

* minor fixes

* reformat code to pass lints

* Add debug ledger code

* Add Litecoin Hardware Wallet Creation

* Add Litecoin Hardware Wallet Creation

* Fix Bitcoin not sending on Ledger

* Fixes to sending LTC using Ledger

* CW-679 Fix merge conflicts

* CW-679 Fix merge conflicts

* CW-679 Minor fixes

* CW-679 Add derivation Path of change address

* Add create Monero Wallet from Ledger

* bug fix to create Monero Wallet from Ledger

* ledger flutter plus refactoring

* ledger flutter plus refactoring

* ledger flutter plus refactoring

* Ups :|

* Ups :| I forgot USB

* Handle BT Off

* Fix Issue with A14 and USB

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Small Ledger Quality of life improvements

* Pls work

* Pls work

* Pls work

* Pls work

* Fix overpopulation

* Fix ble device detection and support for Stax and Flex

* clean up pubspec

* clean up

* MWeb merge fix

* MWeb merge fix

* Migrate to Ledger Flutter Plus

* Add connect device page before loading the wallet (Only monero)

* Add connect device page before loading the wallet (Only monero)

* Fix merge error

* Fix merge error

* Fix merge error && Allow for wallet switching

* Please compile now

* Move monero/ledger.dart from monero_c to cw_monero

* Upgrade ledger_flutter_plus

* Add more popups if action on the device is needed.

* Update monero_c dependency hash

* Yay ledger monero is even more efficient and avoids memory leaks 🥳

* [skip-ci] more code

* Fix Minor Bug

* Fix Minor Bug

* Apply requested changes

* [skip ci] Apply requested changes

* Minor Cleanup

* Welp I'm dumb :/

* Implement requested changes

* Increase ledger refresh speed

* Add Monero Ledger keep connection alive

* Add Monero Ledger keep connection alive

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>
Co-authored-by: m <m@cakewallet.com>
Co-authored-by: Rafael Saes <git@rafael.saes.dev>
Co-authored-by: Matthew Fosse <matt@fosse.co>
---
 build-guide-win.md                            |   38 +
 cw_bitcoin/pubspec.lock                       |    8 +-
 .../lib/hardware/device_connection_type.dart  |    1 +
 cw_core/lib/wallet_service.dart               |    4 +
 cw_monero/lib/api/wallet.dart                 |    4 +-
 cw_monero/lib/api/wallet_manager.dart         |  147 +-
 cw_monero/lib/ledger.dart                     |   88 +
 cw_monero/lib/monero_wallet.dart              |    7 +
 cw_monero/lib/monero_wallet_service.dart      |  108 +-
 cw_monero/pubspec.lock                        |  130 +-
 cw_monero/pubspec.yaml                        |    4 +-
 .../connection_to_node_exception.dart         |    5 +
 cw_wownero/lib/api/structs/account_row.dart   |   12 +
 .../lib/api/structs/coins_info_row.dart       |   73 +
 .../lib/api/structs/subaddress_row.dart       |   15 +
 .../lib/api/structs/transaction_info_row.dart |   41 +
 cw_wownero/lib/api/structs/ut8_box.dart       |    8 +
 cw_wownero/lib/cw_wownero.dart                |    8 +
 cw_wownero/lib/cw_wownero_method_channel.dart |   17 +
 .../lib/cw_wownero_platform_interface.dart    |   29 +
 cw_wownero/lib/mywownero.dart                 | 1689 +++++++++++++++++
 cw_wownero/pubspec.lock                       |   92 +-
 cw_wownero/pubspec.yaml                       |    3 +-
 lib/core/wallet_loading_service.dart          |   14 +-
 lib/di.dart                                   |   15 +-
 .../require_hardware_wallet_connection.dart   |   25 +
 lib/monero/cw_monero.dart                     |   25 +
 .../on_authentication_state_change.dart       |   57 +-
 lib/router.dart                               |    9 +-
 .../connect_device/connect_device_page.dart   |   66 +-
 .../monero_hardware_wallet_options_page.dart  |  230 +++
 .../screens/wallet_list/wallet_list_page.dart |  135 +-
 .../dashboard/dashboard_view_model.dart       |    2 +-
 .../hardware_wallet/ledger_view_model.dart    |    3 +
 .../wallet_hardware_restore_view_model.dart   |   15 +-
 .../wallet_list/wallet_list_view_model.dart   |   19 +-
 scripts/prepare_moneroc.sh                    |    4 +-
 tool/configure.dart                           |   11 +-
 38 files changed, 2912 insertions(+), 249 deletions(-)
 create mode 100644 build-guide-win.md
 create mode 100644 cw_monero/lib/ledger.dart
 create mode 100644 cw_wownero/lib/api/exceptions/connection_to_node_exception.dart
 create mode 100644 cw_wownero/lib/api/structs/account_row.dart
 create mode 100644 cw_wownero/lib/api/structs/coins_info_row.dart
 create mode 100644 cw_wownero/lib/api/structs/subaddress_row.dart
 create mode 100644 cw_wownero/lib/api/structs/transaction_info_row.dart
 create mode 100644 cw_wownero/lib/api/structs/ut8_box.dart
 create mode 100644 cw_wownero/lib/cw_wownero.dart
 create mode 100644 cw_wownero/lib/cw_wownero_method_channel.dart
 create mode 100644 cw_wownero/lib/cw_wownero_platform_interface.dart
 create mode 100644 cw_wownero/lib/mywownero.dart
 create mode 100644 lib/entities/hardware_wallet/require_hardware_wallet_connection.dart
 create mode 100644 lib/src/screens/connect_device/monero_hardware_wallet_options_page.dart

diff --git a/build-guide-win.md b/build-guide-win.md
new file mode 100644
index 000000000..6ace961af
--- /dev/null
+++ b/build-guide-win.md
@@ -0,0 +1,38 @@
+# 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 Windwos`, `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 downlaod 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/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock
index 0e4921a3a..8eafb2a44 100644
--- a/cw_bitcoin/pubspec.lock
+++ b/cw_bitcoin/pubspec.lock
@@ -386,10 +386,10 @@ packages:
     dependency: transitive
     description:
       name: flutter_web_bluetooth
-      sha256: "52ce64f65d7321c4bf6abfe9dac02fb888731339a5e0ad6de59fb916c20c9f02"
+      sha256: fcd03e2e5f82edcedcbc940f1b6a0635a50757374183254f447640886c53208e
       url: "https://pub.dev"
     source: hosted
-    version: "0.2.3"
+    version: "0.2.4"
   flutter_web_plugins:
     dependency: transitive
     description: flutter
@@ -560,7 +560,7 @@ packages:
     description:
       path: "packages/ledger-bitcoin"
       ref: HEAD
-      resolved-ref: dbb5c4956949dc734af3fc8febdbabed89da72aa
+      resolved-ref: "07cd61ef76a2a017b6d5ef233396740163265457"
       url: "https://github.com/cake-tech/ledger-flutter-plus-plugins"
     source: git
     version: "0.0.3"
@@ -577,7 +577,7 @@ packages:
     description:
       path: "packages/ledger-litecoin"
       ref: HEAD
-      resolved-ref: dbb5c4956949dc734af3fc8febdbabed89da72aa
+      resolved-ref: "07cd61ef76a2a017b6d5ef233396740163265457"
       url: "https://github.com/cake-tech/ledger-flutter-plus-plugins"
     source: git
     version: "0.0.2"
diff --git a/cw_core/lib/hardware/device_connection_type.dart b/cw_core/lib/hardware/device_connection_type.dart
index 9a3069552..76a501af1 100644
--- a/cw_core/lib/hardware/device_connection_type.dart
+++ b/cw_core/lib/hardware/device_connection_type.dart
@@ -7,6 +7,7 @@ enum DeviceConnectionType {
   static List<DeviceConnectionType> supportedConnectionTypes(WalletType walletType,
       [bool isIOS = false]) {
     switch (walletType) {
+      case WalletType.monero:
       case WalletType.bitcoin:
       case WalletType.litecoin:
       case WalletType.ethereum:
diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart
index d90ae30bc..85126853e 100644
--- a/cw_core/lib/wallet_service.dart
+++ b/cw_core/lib/wallet_service.dart
@@ -61,4 +61,8 @@ abstract class WalletService<N extends WalletCredentials, RFS extends WalletCred
       return '';
     }
   }
+
+  /// Check if the Wallet requires a hardware wallet to be connected during
+  /// the opening flow. (Currently only the case for Monero)
+  bool requireHardwareWalletConnection(String name) => false;
 }
diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart
index 8e03cff3e..928fd7ef1 100644
--- a/cw_monero/lib/api/wallet.dart
+++ b/cw_monero/lib/api/wallet.dart
@@ -119,7 +119,7 @@ Future<bool> setupNodeSync(
         daemonUsername: login ?? '',
         daemonPassword: password ?? '');
   });
-  // monero.Wallet_init3(wptr!, argv0: '', defaultLogBaseName: 'moneroc', console: true);
+  // monero.Wallet_init3(wptr!, argv0: '', defaultLogBaseName: 'moneroc', console: true, logPath: '');
 
   final status = monero.Wallet_status(wptr!);
 
@@ -330,4 +330,4 @@ String signMessage(String message, {String address = ""}) {
 
 bool verifyMessage(String message, String address, String signature) {
   return monero.Wallet_verifySignedMessage(wptr!, message: message, address: address, signature: signature);
-}
\ No newline at end of file
+}
diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart
index 61fd6edf0..7f9dbd8fa 100644
--- a/cw_monero/lib/api/wallet_manager.dart
+++ b/cw_monero/lib/api/wallet_manager.dart
@@ -7,19 +7,18 @@ import 'package:cw_monero/api/exceptions/wallet_creation_exception.dart';
 import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
 import 'package:cw_monero/api/exceptions/wallet_restore_from_keys_exception.dart';
 import 'package:cw_monero/api/exceptions/wallet_restore_from_seed_exception.dart';
-import 'package:cw_monero/api/wallet.dart';
 import 'package:cw_monero/api/transaction_history.dart';
+import 'package:cw_monero/api/wallet.dart';
+import 'package:cw_monero/ledger.dart';
 import 'package:monero/monero.dart' as monero;
 
 class MoneroCException implements Exception {
   final String message;
 
   MoneroCException(this.message);
-  
+
   @override
-  String toString() {
-    return message;
-  }
+  String toString() => message;
 }
 
 void checkIfMoneroCIsFine() {
@@ -43,7 +42,6 @@ void checkIfMoneroCIsFine() {
     throw MoneroCException("monero_c and monero.dart wrapper export list mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsExp'\ndart: '$dartCsExp'");
   }
 }
-
 monero.WalletManager? _wmPtr;
 final monero.WalletManager wmPtr = Pointer.fromAddress((() {
   try {
@@ -60,6 +58,13 @@ final monero.WalletManager wmPtr = Pointer.fromAddress((() {
   return _wmPtr!.address;
 })());
 
+void createWalletPointer() {
+  final newWptr = monero.WalletManager_createWallet(wmPtr,
+      path: "", password: "", language: "", networkType: 0);
+
+  wptr = newWptr;
+}
+
 void createWalletSync(
     {required String path,
     required String password,
@@ -124,24 +129,24 @@ void restoreWalletFromKeysSync(
     int restoreHeight = 0}) {
   txhistory = null;
   var newWptr = (spendKey != "")
-   ? monero.WalletManager_createDeterministicWalletFromSpendKey(
-    wmPtr,
-    path: path,
-    password: password,
-    language: language,
-    spendKeyString: spendKey, 
-    newWallet: true, // TODO(mrcyjanek): safe to remove
-    restoreHeight: restoreHeight)
-   : monero.WalletManager_createWalletFromKeys(
-    wmPtr,
-    path: path,
-    password: password,
-    restoreHeight: restoreHeight,
-    addressString: address,
-    viewKeyString: viewKey,
-    spendKeyString: spendKey,
-    nettype: 0,
-  );
+      ? monero.WalletManager_createDeterministicWalletFromSpendKey(wmPtr,
+          path: path,
+          password: password,
+          language: language,
+          spendKeyString: spendKey,
+          newWallet: true,
+          // TODO(mrcyjanek): safe to remove
+          restoreHeight: restoreHeight)
+      : monero.WalletManager_createWalletFromKeys(
+          wmPtr,
+          path: path,
+          password: password,
+          restoreHeight: restoreHeight,
+          addressString: address,
+          viewKeyString: viewKey,
+          spendKeyString: spendKey,
+          nettype: 0,
+        );
 
   final status = monero.Wallet_status(newWptr);
   if (status != 0) {
@@ -156,7 +161,7 @@ void restoreWalletFromKeysSync(
     if (viewKey != viewKeyRestored && viewKey != "") {
       monero.WalletManager_closeWallet(wmPtr, newWptr, false);
       File(path).deleteSync();
-      File(path+".keys").deleteSync();
+      File(path + ".keys").deleteSync();
       newWptr = monero.WalletManager_createWalletFromKeys(
         wmPtr,
         path: path,
@@ -199,7 +204,7 @@ void restoreWalletFromSpendKeySync(
   //   viewKeyString: '',
   //   nettype: 0,
   // );
-  
+
   txhistory = null;
   final newWptr = monero.WalletManager_createDeterministicWalletFromSpendKey(
     wmPtr,
@@ -230,41 +235,39 @@ void restoreWalletFromSpendKeySync(
 
 String _lastOpenedWallet = "";
 
-// void restoreMoneroWalletFromDevice(
-//     {required String path,
-//       required String password,
-//       required String deviceName,
-//       int nettype = 0,
-//       int restoreHeight = 0}) {
-//
-//   final pathPointer = path.toNativeUtf8();
-//   final passwordPointer = password.toNativeUtf8();
-//   final deviceNamePointer = deviceName.toNativeUtf8();
-//   final errorMessagePointer = ''.toNativeUtf8();
-//
-//   final isWalletRestored = restoreWalletFromDeviceNative(
-//       pathPointer,
-//       passwordPointer,
-//       deviceNamePointer,
-//       nettype,
-//       restoreHeight,
-//       errorMessagePointer) != 0;
-//
-//   calloc.free(pathPointer);
-//   calloc.free(passwordPointer);
-//
-//   storeSync();
-//
-//   if (!isWalletRestored) {
-//     throw WalletRestoreFromKeysException(
-//         message: convertUTF8ToString(pointer: errorMessagePointer));
-//   }
-// }
+Future<void> restoreWalletFromHardwareWallet(
+    {required String path,
+    required String password,
+    required String deviceName,
+    int nettype = 0,
+    int restoreHeight = 0}) async {
+  txhistory = null;
+
+  final newWptrAddr = await Isolate.run(() {
+    return monero.WalletManager_createWalletFromDevice(wmPtr,
+            path: path,
+            password: password,
+            restoreHeight: restoreHeight,
+            deviceName: deviceName)
+        .address;
+  });
+  final newWptr = Pointer<Void>.fromAddress(newWptrAddr);
+
+  final status = monero.Wallet_status(newWptr);
+
+  if (status != 0) {
+    final error = monero.Wallet_errorString(newWptr);
+    throw WalletRestoreFromSeedException(message: error);
+  }
+  wptr = newWptr;
+
+  openedWalletsByPath[path] = wptr!;
+}
 
 Map<String, monero.wallet> openedWalletsByPath = {};
 
-void loadWallet(
-    {required String path, required String password, int nettype = 0}) {
+Future<void> loadWallet(
+    {required String path, required String password, int nettype = 0}) async {
   if (openedWalletsByPath[path] != null) {
     txhistory = null;
     wptr = openedWalletsByPath[path]!;
@@ -278,8 +281,29 @@ void loadWallet(
       });
     }
     txhistory = null;
-    final newWptr = monero.WalletManager_openWallet(wmPtr,
-        path: path, password: password);
+
+    /// Get the device type
+    /// 0: Software Wallet
+    /// 1: Ledger
+    /// 2: Trezor
+    final deviceType = monero.WalletManager_queryWalletDevice(wmPtr,
+        keysFileName: "$path.keys", password: password, kdfRounds: 1);
+
+    if (deviceType == 1) {
+      final dummyWPtr = wptr ??
+          monero.WalletManager_openWallet(wmPtr, path: '', password: '');
+      enableLedgerExchange(dummyWPtr, gLedger!);
+    }
+
+    final addr = wmPtr.address;
+    final newWptrAddr = await Isolate.run(() {
+      return monero.WalletManager_openWallet(Pointer.fromAddress(addr),
+              path: path, password: password)
+          .address;
+    });
+
+    final newWptr = Pointer<Void>.fromAddress(newWptrAddr);
+
     _lastOpenedWallet = path;
     final status = monero.Wallet_status(newWptr);
     if (status != 0) {
@@ -287,6 +311,7 @@ void loadWallet(
       print(err);
       throw WalletOpeningException(message: err);
     }
+
     wptr = newWptr;
     openedWalletsByPath[path] = wptr!;
   }
@@ -351,7 +376,7 @@ Future<void> _openWallet(Map<String, String> args) async => loadWallet(
 
 bool _isWalletExist(String path) => isWalletExistSync(path: path);
 
-void openWallet(
+Future<void> openWallet(
         {required String path,
         required String password,
         int nettype = 0}) async =>
diff --git a/cw_monero/lib/ledger.dart b/cw_monero/lib/ledger.dart
new file mode 100644
index 000000000..074975df3
--- /dev/null
+++ b/cw_monero/lib/ledger.dart
@@ -0,0 +1,88 @@
+import 'dart:async';
+import 'dart:ffi';
+import 'dart:typed_data';
+
+import 'package:ffi/ffi.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus_dart.dart';
+import 'package:monero/monero.dart' as monero;
+// import 'package:polyseed/polyseed.dart';
+
+LedgerConnection? gLedger;
+
+Timer? _ledgerExchangeTimer;
+Timer? _ledgerKeepAlive;
+
+void enableLedgerExchange(monero.wallet ptr, LedgerConnection connection) {
+  _ledgerExchangeTimer?.cancel();
+  _ledgerExchangeTimer = Timer.periodic(Duration(milliseconds: 1), (_) async {
+    final ledgerRequestLength = monero.Wallet_getSendToDeviceLength(ptr);
+    final ledgerRequest = monero.Wallet_getSendToDevice(ptr)
+        .cast<Uint8>()
+        .asTypedList(ledgerRequestLength);
+    if (ledgerRequestLength > 0) {
+      _ledgerKeepAlive?.cancel();
+
+      final Pointer<Uint8> emptyPointer = malloc<Uint8>(0);
+      monero.Wallet_setDeviceSendData(
+          ptr, emptyPointer.cast<UnsignedChar>(), 0);
+      malloc.free(emptyPointer);
+
+      // print("> ${ledgerRequest.toHexString()}");
+      final response = await exchange(connection, ledgerRequest);
+      // print("< ${response.toHexString()}");
+
+      final Pointer<Uint8> result = malloc<Uint8>(response.length);
+      for (var i = 0; i < response.length; i++) {
+        result.asTypedList(response.length)[i] = response[i];
+      }
+
+      monero.Wallet_setDeviceReceivedData(
+          ptr, result.cast<UnsignedChar>(), response.length);
+      malloc.free(result);
+      keepAlive(connection);
+    }
+  });
+}
+
+void keepAlive(LedgerConnection connection) {
+  if (connection.connectionType == ConnectionType.ble) {
+    UniversalBle.onConnectionChange = (String deviceId, bool isConnected) {
+      print("[Monero] Ledger Disconnected");
+      _ledgerKeepAlive?.cancel();
+    };
+    _ledgerKeepAlive = Timer.periodic(Duration(seconds: 10), (_) async {
+      try {
+        UniversalBle.setNotifiable(
+          connection.device.id,
+          connection.device.deviceInfo.serviceId,
+          connection.device.deviceInfo.notifyCharacteristicKey,
+          BleInputProperty.notification,
+        );
+      } catch (_){}
+    });
+  }
+}
+
+void disableLedgerExchange() {
+  _ledgerExchangeTimer?.cancel();
+  _ledgerKeepAlive?.cancel();
+  gLedger?.disconnect();
+  gLedger = null;
+}
+
+Future<Uint8List> exchange(LedgerConnection connection, Uint8List data) async =>
+    connection.sendOperation<Uint8List>(ExchangeOperation(data));
+
+class ExchangeOperation extends LedgerRawOperation<Uint8List> {
+  final Uint8List inputData;
+
+  ExchangeOperation(this.inputData);
+
+  @override
+  Future<Uint8List> read(ByteDataReader reader) async =>
+      reader.read(reader.remainingLength);
+
+  @override
+  Future<List<Uint8List>> write(ByteDataWriter writer) async => [inputData];
+}
diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart
index bc8c3c94d..5f53b30ba 100644
--- a/cw_monero/lib/monero_wallet.dart
+++ b/cw_monero/lib/monero_wallet.dart
@@ -28,6 +28,7 @@ import 'package:cw_monero/api/wallet.dart' as monero_wallet;
 import 'package:cw_monero/api/wallet_manager.dart';
 import 'package:cw_monero/exceptions/monero_transaction_creation_exception.dart';
 import 'package:cw_monero/exceptions/monero_transaction_no_inputs_exception.dart';
+import 'package:cw_monero/ledger.dart';
 import 'package:cw_monero/monero_transaction_creation_credentials.dart';
 import 'package:cw_monero/monero_transaction_history.dart';
 import 'package:cw_monero/monero_transaction_info.dart';
@@ -36,6 +37,7 @@ import 'package:cw_monero/monero_wallet_addresses.dart';
 import 'package:cw_monero/pending_monero_transaction.dart';
 import 'package:flutter/foundation.dart';
 import 'package:hive/hive.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
 import 'package:mobx/mobx.dart';
 import 'package:monero/monero.dart' as monero;
 
@@ -828,4 +830,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
     return monero_wallet.verifyMessage(message, address, signature);
   }
 
+  void setLedgerConnection(LedgerConnection connection) {
+    final dummyWPtr = wptr ??
+        monero.WalletManager_openWallet(wmPtr, path: '', password: '');
+    enableLedgerExchange(dummyWPtr, connection);
+  }
 }
diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart
index 63ad17583..b2089dfc7 100644
--- a/cw_monero/lib/monero_wallet_service.dart
+++ b/cw_monero/lib/monero_wallet_service.dart
@@ -9,10 +9,13 @@ import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_service.dart';
 import 'package:cw_core/wallet_type.dart';
 import 'package:cw_core/get_height_by_date.dart';
+import 'package:cw_monero/api/account_list.dart';
 import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager;
 import 'package:cw_monero/api/wallet_manager.dart';
+import 'package:cw_monero/ledger.dart';
 import 'package:cw_monero/monero_wallet.dart';
 import 'package:hive/hive.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
 import 'package:polyseed/polyseed.dart';
 import 'package:monero/monero.dart' as monero;
 
@@ -25,6 +28,15 @@ class MoneroNewWalletCredentials extends WalletCredentials {
   final bool isPolyseed;
 }
 
+class MoneroRestoreWalletFromHardwareCredentials extends WalletCredentials {
+  MoneroRestoreWalletFromHardwareCredentials({required String name,
+    required this.ledgerConnection,
+    int height = 0,
+    String? password})
+      : super(name: name, password: password, height: height);
+  LedgerConnection ledgerConnection;
+}
+
 class MoneroRestoreWalletFromSeedCredentials extends WalletCredentials {
   MoneroRestoreWalletFromSeedCredentials(
       {required String name, required this.mnemonic, int height = 0, String? password})
@@ -39,14 +51,13 @@ class MoneroWalletLoadingException implements Exception {
 }
 
 class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials {
-  MoneroRestoreWalletFromKeysCredentials(
-      {required String name,
-      required String password,
-      required this.language,
-      required this.address,
-      required this.viewKey,
-      required this.spendKey,
-      int height = 0})
+  MoneroRestoreWalletFromKeysCredentials({required String name,
+    required String password,
+    required this.language,
+    required this.address,
+    required this.viewKey,
+    required this.spendKey,
+    int height = 0})
       : super(name: name, password: password, height: height);
 
   final String language;
@@ -59,7 +70,7 @@ class MoneroWalletService extends WalletService<
     MoneroNewWalletCredentials,
     MoneroRestoreWalletFromSeedCredentials,
     MoneroRestoreWalletFromKeysCredentials,
-    MoneroNewWalletCredentials> {
+    MoneroRestoreWalletFromHardwareCredentials> {
   MoneroWalletService(this.walletInfoSource, this.unspentCoinsInfoSource);
 
   final Box<WalletInfo> walletInfoSource;
@@ -81,7 +92,7 @@ class MoneroWalletService extends WalletService<
         final lang = PolyseedLang.getByEnglishName(credentials.language);
 
         final heightOverride =
-            getMoneroHeigthByDate(date: DateTime.now().subtract(Duration(days: 2)));
+        getMoneroHeigthByDate(date: DateTime.now().subtract(Duration(days: 2)));
 
         return _restoreFromPolyseed(
             path, credentials.password!, polyseed, credentials.walletInfo!, lang,
@@ -91,9 +102,9 @@ class MoneroWalletService extends WalletService<
       await monero_wallet_manager.createWallet(
           path: path, password: credentials.password!, language: credentials.language);
       final wallet = MoneroWallet(
-        walletInfo: credentials.walletInfo!,
-        unspentCoinsInfo: unspentCoinsInfoSource,
-        password: credentials.password!);
+          walletInfo: credentials.walletInfo!,
+          unspentCoinsInfo: unspentCoinsInfoSource,
+          password: credentials.password!);
       await wallet.init();
 
       return wallet;
@@ -128,11 +139,11 @@ class MoneroWalletService extends WalletService<
       await monero_wallet_manager
           .openWalletAsync({'path': path, 'password': password});
       final walletInfo = walletInfoSource.values.firstWhere(
-          (info) => info.id == WalletBase.idFor(name, getType()));
+              (info) => info.id == WalletBase.idFor(name, getType()));
       final wallet = MoneroWallet(
-        walletInfo: walletInfo,
-        unspentCoinsInfo: unspentCoinsInfoSource,
-        password: password);
+          walletInfo: walletInfo,
+          unspentCoinsInfo: unspentCoinsInfoSource,
+          password: password);
       final isValid = wallet.walletAddresses.validate();
 
       if (!isValid) {
@@ -185,10 +196,9 @@ class MoneroWalletService extends WalletService<
   }
 
   @override
-  Future<void> rename(
-      String currentName, String password, String newName) async {
+  Future<void> rename(String currentName, String password, String newName) async {
     final currentWalletInfo = walletInfoSource.values.firstWhere(
-        (info) => info.id == WalletBase.idFor(currentName, getType()));
+            (info) => info.id == WalletBase.idFor(currentName, getType()));
     final currentWallet = MoneroWallet(
       walletInfo: currentWalletInfo,
       unspentCoinsInfo: unspentCoinsInfoSource,
@@ -218,9 +228,9 @@ class MoneroWalletService extends WalletService<
           viewKey: credentials.viewKey,
           spendKey: credentials.spendKey);
       final wallet = MoneroWallet(
-        walletInfo: credentials.walletInfo!,
-        unspentCoinsInfo: unspentCoinsInfoSource,
-        password: credentials.password!);
+          walletInfo: credentials.walletInfo!,
+          unspentCoinsInfo: unspentCoinsInfoSource,
+          password: credentials.password!);
       await wallet.init();
 
       return wallet;
@@ -232,9 +242,34 @@ class MoneroWalletService extends WalletService<
   }
 
   @override
-  Future<MoneroWallet> restoreFromHardwareWallet(MoneroNewWalletCredentials credentials) {
-    throw UnimplementedError(
-        "Restoring a Monero wallet from a hardware wallet is not yet supported!");
+  Future<MoneroWallet> restoreFromHardwareWallet(
+      MoneroRestoreWalletFromHardwareCredentials credentials) async {
+    try {
+      final path = await pathForWallet(name: credentials.name, type: getType());
+      final password = credentials.password;
+      final height = credentials.height;
+
+      if (wptr == null ) monero_wallet_manager.createWalletPointer();
+
+      enableLedgerExchange(wptr!, credentials.ledgerConnection);
+      await monero_wallet_manager.restoreWalletFromHardwareWallet(
+            path: path,
+            password: password!,
+            restoreHeight: height!,
+            deviceName: 'Ledger');
+
+      final wallet = MoneroWallet(
+          walletInfo: credentials.walletInfo!,
+          unspentCoinsInfo: unspentCoinsInfoSource,
+          password: credentials.password!);
+      await wallet.init();
+
+      return wallet;
+    } catch (e) {
+      // TODO: Implement Exception for wallet list service.
+      print('MoneroWalletsManager Error: $e');
+      rethrow;
+    }
   }
 
   @override
@@ -253,9 +288,9 @@ class MoneroWalletService extends WalletService<
           seed: credentials.mnemonic,
           restoreHeight: credentials.height!);
       final wallet = MoneroWallet(
-        walletInfo: credentials.walletInfo!,
-        unspentCoinsInfo: unspentCoinsInfoSource,
-        password: credentials.password!);
+          walletInfo: credentials.walletInfo!,
+          unspentCoinsInfo: unspentCoinsInfoSource,
+          password: credentials.password!);
       await wallet.init();
 
       return wallet;
@@ -283,8 +318,8 @@ class MoneroWalletService extends WalletService<
     }
   }
 
-  Future<MoneroWallet> _restoreFromPolyseed(
-      String path, String password, Polyseed polyseed, WalletInfo walletInfo, PolyseedLang lang,
+  Future<MoneroWallet> _restoreFromPolyseed(String path, String password, Polyseed polyseed,
+      WalletInfo walletInfo, PolyseedLang lang,
       {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO, int? overrideHeight}) async {
     final height = overrideHeight ??
         getMoneroHeigthByDate(date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000));
@@ -329,7 +364,9 @@ class MoneroWalletService extends WalletService<
 
       dir.listSync().forEach((f) {
         final file = File(f.path);
-        final name = f.path.split('/').last;
+        final name = f.path
+            .split('/')
+            .last;
         final newPath = newWalletDirPath + '/$name';
         final newFile = File(newPath);
 
@@ -366,4 +403,11 @@ class MoneroWalletService extends WalletService<
       return '';
     }
   }
+
+  @override
+  bool requireHardwareWalletConnection(String name) {
+    final walletInfo = walletInfoSource.values
+        .firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
+    return walletInfo.isHardwareWallet;
+  }
 }
diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock
index ee1d48df1..a6a03dce5 100644
--- a/cw_monero/pubspec.lock
+++ b/cw_monero/pubspec.lock
@@ -29,10 +29,10 @@ packages:
     dependency: transitive
     description:
       name: asn1lib
-      sha256: "58082b3f0dca697204dbab0ef9ff208bfaea7767ea771076af9a343488428dda"
+      sha256: "6b151826fcc95ff246cd219a0bf4c753ea14f4081ad71c61939becf3aba27f70"
       url: "https://pub.dev"
     source: hosted
-    version: "1.5.3"
+    version: "1.5.5"
   async:
     dependency: transitive
     description:
@@ -41,6 +41,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.11.0"
+  bluez:
+    dependency: transitive
+    description:
+      name: bluez
+      sha256: "203a1924e818a9dd74af2b2c7a8f375ab8e5edf0e486bba8f90a0d8a17ed9fce"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.8.2"
   boolean_selector:
     dependency: transitive
     description:
@@ -209,6 +217,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.2.4"
+  dbus:
+    dependency: transitive
+    description:
+      name: dbus
+      sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.7.10"
   encrypt:
     dependency: "direct main"
     description:
@@ -229,10 +245,10 @@ packages:
     dependency: "direct main"
     description:
       name: ffi
-      sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
+      sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.3"
   file:
     dependency: transitive
     description:
@@ -267,6 +283,14 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_web_bluetooth:
+    dependency: transitive
+    description:
+      name: flutter_web_bluetooth
+      sha256: "52ce64f65d7321c4bf6abfe9dac02fb888731339a5e0ad6de59fb916c20c9f02"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.2.3"
   frontend_server_client:
     dependency: transitive
     description:
@@ -295,18 +319,18 @@ packages:
     dependency: transitive
     description:
       name: hashlib
-      sha256: d41795742c10947930630118c6836608deeb9047cd05aee32d2baeb697afd66a
+      sha256: f572f2abce09fc7aee53f15927052b9732ea1053e540af8cae211111ee0b99b1
       url: "https://pub.dev"
     source: hosted
-    version: "1.19.2"
+    version: "1.21.0"
   hashlib_codecs:
     dependency: transitive
     description:
       name: hashlib_codecs
-      sha256: "2b570061f5a4b378425be28a576c1e11783450355ad4345a19f606ff3d96db0f"
+      sha256: "8cea9ccafcfeaa7324d2ae52c61c69f7ff71f4237507a018caab31b9e416e3b1"
       url: "https://pub.dev"
     source: hosted
-    version: "2.5.0"
+    version: "2.6.0"
   hive:
     dependency: transitive
     description:
@@ -327,10 +351,10 @@ packages:
     dependency: "direct main"
     description:
       name: http
-      sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
+      sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
       url: "https://pub.dev"
     source: hosted
-    version: "1.2.1"
+    version: "1.2.2"
   http_multi_server:
     dependency: transitive
     description:
@@ -403,6 +427,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.0.1"
+  ledger_flutter_plus:
+    dependency: "direct main"
+    description:
+      name: ledger_flutter_plus
+      sha256: c7b04008553193dbca7e17b430768eecc372a72b0ff3625b5e7fc5e5c8d3231b
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.4.1"
+  ledger_usb_plus:
+    dependency: transitive
+    description:
+      name: ledger_usb_plus
+      sha256: "21cc5d976cf7edb3518bd2a0c4164139cbb0817d2e4f2054707fc4edfdf9ce87"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.4"
   logging:
     dependency: transitive
     description:
@@ -439,10 +479,10 @@ packages:
     dependency: transitive
     description:
       name: mime
-      sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
+      sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
       url: "https://pub.dev"
     source: hosted
-    version: "1.0.5"
+    version: "1.0.6"
   mobx:
     dependency: "direct main"
     description:
@@ -463,8 +503,8 @@ packages:
     dependency: "direct main"
     description:
       path: "impls/monero.dart"
-      ref: "6eb571ea498ed7b854934785f00fabfd0dadf75b"
-      resolved-ref: "6eb571ea498ed7b854934785f00fabfd0dadf75b"
+      ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
+      resolved-ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
       url: "https://github.com/mrcyjanek/monero_c"
     source: git
     version: "0.0.0"
@@ -504,10 +544,10 @@ packages:
     dependency: "direct main"
     description:
       name: path_provider
-      sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
+      sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.3"
+    version: "2.1.4"
   path_provider_android:
     dependency: transitive
     description:
@@ -544,10 +584,18 @@ packages:
     dependency: transitive
     description:
       name: path_provider_windows
-      sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
+      sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.1"
+    version: "2.3.0"
+  petitparser:
+    dependency: transitive
+    description:
+      name: petitparser
+      sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
+      url: "https://pub.dev"
+    source: hosted
+    version: "6.0.2"
   platform:
     dependency: transitive
     description:
@@ -612,6 +660,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.0"
+  rxdart:
+    dependency: transitive
+    description:
+      name: rxdart
+      sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.28.0"
   shelf:
     dependency: transitive
     description:
@@ -737,6 +793,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.2"
+  universal_ble:
+    dependency: transitive
+    description:
+      name: universal_ble
+      sha256: "0dfbd6b64bff3ad61ed7a895c232530d9614e9b01ab261a74433a43267edb7f3"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.12.0"
+  universal_platform:
+    dependency: transitive
+    description:
+      name: universal_platform
+      sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.0"
   unorm_dart:
     dependency: transitive
     description:
@@ -785,22 +857,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.4.5"
-  win32:
-    dependency: transitive
-    description:
-      name: win32
-      sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
-      url: "https://pub.dev"
-    source: hosted
-    version: "5.5.0"
   xdg_directories:
     dependency: transitive
     description:
       name: xdg_directories
-      sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
+      sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
       url: "https://pub.dev"
     source: hosted
-    version: "1.0.4"
+    version: "1.1.0"
+  xml:
+    dependency: transitive
+    description:
+      name: xml
+      sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
+      url: "https://pub.dev"
+    source: hosted
+    version: "6.5.0"
   yaml:
     dependency: transitive
     description:
@@ -811,4 +883,4 @@ packages:
     version: "3.1.2"
 sdks:
   dart: ">=3.3.0 <4.0.0"
-  flutter: ">=3.16.6"
+  flutter: ">=3.19.0"
diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml
index cb1f5519f..6fa235ee4 100644
--- a/cw_monero/pubspec.yaml
+++ b/cw_monero/pubspec.yaml
@@ -25,9 +25,11 @@ dependencies:
   monero:
     git:
       url: https://github.com/mrcyjanek/monero_c
-      ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash
+      ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
+#      ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash
       path: impls/monero.dart
   mutex: ^3.1.0
+  ledger_flutter_plus: ^1.4.1
 
 dev_dependencies:
   flutter_test:
diff --git a/cw_wownero/lib/api/exceptions/connection_to_node_exception.dart b/cw_wownero/lib/api/exceptions/connection_to_node_exception.dart
new file mode 100644
index 000000000..483b0a174
--- /dev/null
+++ b/cw_wownero/lib/api/exceptions/connection_to_node_exception.dart
@@ -0,0 +1,5 @@
+class ConnectionToNodeException implements Exception {
+  ConnectionToNodeException({required this.message});
+
+  final String message;
+}
\ No newline at end of file
diff --git a/cw_wownero/lib/api/structs/account_row.dart b/cw_wownero/lib/api/structs/account_row.dart
new file mode 100644
index 000000000..aa492ee0f
--- /dev/null
+++ b/cw_wownero/lib/api/structs/account_row.dart
@@ -0,0 +1,12 @@
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+class AccountRow extends Struct {
+  @Int64()
+  external int id;
+  
+  external Pointer<Utf8> label;
+
+  String getLabel() => label.toDartString();
+  int getId() => id;
+}
diff --git a/cw_wownero/lib/api/structs/coins_info_row.dart b/cw_wownero/lib/api/structs/coins_info_row.dart
new file mode 100644
index 000000000..ff6f6ce73
--- /dev/null
+++ b/cw_wownero/lib/api/structs/coins_info_row.dart
@@ -0,0 +1,73 @@
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+class CoinsInfoRow extends Struct {
+  @Int64()
+  external int blockHeight;
+
+  external Pointer<Utf8> hash;
+
+  @Uint64()
+  external int internalOutputIndex;
+
+  @Uint64()
+  external int globalOutputIndex;
+
+  @Int8()
+  external int spent;
+
+  @Int8()
+  external int frozen;
+
+  @Uint64()
+  external int spentHeight;
+
+  @Uint64()
+  external int amount;
+
+  @Int8()
+  external int rct;
+
+  @Int8()
+  external int keyImageKnown;
+
+  @Uint64()
+  external int pkIndex;
+
+  @Uint32()
+  external int subaddrIndex;
+
+  @Uint32()
+  external int subaddrAccount;
+
+  external Pointer<Utf8> address;
+
+  external Pointer<Utf8> addressLabel;
+
+  external Pointer<Utf8> keyImage;
+
+  @Uint64()
+  external int unlockTime;
+
+  @Int8()
+  external int unlocked;
+
+  external Pointer<Utf8> pubKey;
+
+  @Int8()
+  external int coinbase;
+
+  external Pointer<Utf8> description;
+
+  String getHash() => hash.toDartString();
+
+  String getAddress() => address.toDartString();
+
+  String getAddressLabel() => addressLabel.toDartString();
+
+  String getKeyImage() => keyImage.toDartString();
+
+  String getPubKey() => pubKey.toDartString();
+
+  String getDescription() => description.toDartString();
+}
diff --git a/cw_wownero/lib/api/structs/subaddress_row.dart b/cw_wownero/lib/api/structs/subaddress_row.dart
new file mode 100644
index 000000000..d593a793d
--- /dev/null
+++ b/cw_wownero/lib/api/structs/subaddress_row.dart
@@ -0,0 +1,15 @@
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+class SubaddressRow extends Struct {
+  @Int64()
+  external int id;
+  
+  external Pointer<Utf8> address;
+  
+  external Pointer<Utf8> label;
+
+  String getLabel() => label.toDartString();
+  String getAddress() => address.toDartString();
+  int getId() => id;
+}
\ No newline at end of file
diff --git a/cw_wownero/lib/api/structs/transaction_info_row.dart b/cw_wownero/lib/api/structs/transaction_info_row.dart
new file mode 100644
index 000000000..bdcc64d3f
--- /dev/null
+++ b/cw_wownero/lib/api/structs/transaction_info_row.dart
@@ -0,0 +1,41 @@
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+class TransactionInfoRow extends Struct {
+  @Uint64()
+  external int amount;
+
+  @Uint64()
+  external int fee;
+
+  @Uint64()
+  external int blockHeight;
+
+  @Uint64()
+  external int confirmations;
+
+  @Uint32()
+  external int subaddrAccount;
+
+  @Int8()
+  external int direction;
+
+  @Int8()
+  external int isPending;
+
+  @Uint32()
+  external int subaddrIndex;
+
+  external Pointer<Utf8> hash;
+
+  external Pointer<Utf8> paymentId;
+
+  @Int64()
+  external int datetime;
+
+  int getDatetime() => datetime;
+  int getAmount() => amount >= 0 ? amount : amount * -1;
+  bool getIsPending() => isPending != 0;
+  String getHash() => hash.toDartString();
+  String getPaymentId() => paymentId.toDartString();
+}
diff --git a/cw_wownero/lib/api/structs/ut8_box.dart b/cw_wownero/lib/api/structs/ut8_box.dart
new file mode 100644
index 000000000..53e678c88
--- /dev/null
+++ b/cw_wownero/lib/api/structs/ut8_box.dart
@@ -0,0 +1,8 @@
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+class Utf8Box extends Struct {
+  external Pointer<Utf8> value;
+
+  String getValue() => value.toDartString();
+}
diff --git a/cw_wownero/lib/cw_wownero.dart b/cw_wownero/lib/cw_wownero.dart
new file mode 100644
index 000000000..33a55e305
--- /dev/null
+++ b/cw_wownero/lib/cw_wownero.dart
@@ -0,0 +1,8 @@
+
+import 'cw_wownero_platform_interface.dart';
+
+class CwWownero {
+  Future<String?> getPlatformVersion() {
+    return CwWowneroPlatform.instance.getPlatformVersion();
+  }
+}
diff --git a/cw_wownero/lib/cw_wownero_method_channel.dart b/cw_wownero/lib/cw_wownero_method_channel.dart
new file mode 100644
index 000000000..d797f5f81
--- /dev/null
+++ b/cw_wownero/lib/cw_wownero_method_channel.dart
@@ -0,0 +1,17 @@
+import 'package:flutter/foundation.dart';
+import 'package:flutter/services.dart';
+
+import 'cw_wownero_platform_interface.dart';
+
+/// An implementation of [CwWowneroPlatform] that uses method channels.
+class MethodChannelCwWownero extends CwWowneroPlatform {
+  /// The method channel used to interact with the native platform.
+  @visibleForTesting
+  final methodChannel = const MethodChannel('cw_wownero');
+
+  @override
+  Future<String?> getPlatformVersion() async {
+    final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
+    return version;
+  }
+}
diff --git a/cw_wownero/lib/cw_wownero_platform_interface.dart b/cw_wownero/lib/cw_wownero_platform_interface.dart
new file mode 100644
index 000000000..78b21592c
--- /dev/null
+++ b/cw_wownero/lib/cw_wownero_platform_interface.dart
@@ -0,0 +1,29 @@
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
+
+import 'cw_wownero_method_channel.dart';
+
+abstract class CwWowneroPlatform extends PlatformInterface {
+  /// Constructs a CwWowneroPlatform.
+  CwWowneroPlatform() : super(token: _token);
+
+  static final Object _token = Object();
+
+  static CwWowneroPlatform _instance = MethodChannelCwWownero();
+
+  /// The default instance of [CwWowneroPlatform] to use.
+  ///
+  /// Defaults to [MethodChannelCwWownero].
+  static CwWowneroPlatform get instance => _instance;
+
+  /// Platform-specific implementations should set this with their own
+  /// platform-specific class that extends [CwWowneroPlatform] when
+  /// they register themselves.
+  static set instance(CwWowneroPlatform instance) {
+    PlatformInterface.verifyToken(instance, _token);
+    _instance = instance;
+  }
+
+  Future<String?> getPlatformVersion() {
+    throw UnimplementedError('platformVersion() has not been implemented.');
+  }
+}
diff --git a/cw_wownero/lib/mywownero.dart b/cw_wownero/lib/mywownero.dart
new file mode 100644
index 000000000..d50e48b64
--- /dev/null
+++ b/cw_wownero/lib/mywownero.dart
@@ -0,0 +1,1689 @@
+const prefixLength = 3;
+
+String swapEndianBytes(String original) {
+  if (original.length != 8) {
+    return '';
+  }
+
+  return original[6] +
+      original[7] +
+      original[4] +
+      original[5] +
+      original[2] +
+      original[3] +
+      original[0] +
+      original[1];
+}
+
+List<String> tructWords(List<String> wordSet) {
+  final start = 0;
+  final end = prefixLength;
+
+  return wordSet.map((word) => word.substring(start, end)).toList();
+}
+
+String mnemonicDecode(String seed) {
+  final n = englistWordSet.length;
+  var out = '';
+  var wlist = seed.split(' ');
+  wlist.removeLast();
+
+  for (var i = 0; i < wlist.length; i += 3) {
+    final w1 =
+        tructWords(englistWordSet).indexOf(wlist[i].substring(0, prefixLength));
+    final w2 = tructWords(englistWordSet)
+        .indexOf(wlist[i + 1].substring(0, prefixLength));
+    final w3 = tructWords(englistWordSet)
+        .indexOf(wlist[i + 2].substring(0, prefixLength));
+
+    if (w1 == -1 || w2 == -1 || w3 == -1) {
+      print("invalid word in mnemonic");
+      return '';
+    }
+
+    final x = w1 + n * (((n - w1) + w2) % n) + n * n * (((n - w2) + w3) % n);
+
+    if (x % n != w1) {
+      print("Something went wrong when decoding your private key, please try again");
+      return '';
+    }
+
+    final _res = '0000000' + x.toRadixString(16);
+    final start = _res.length - 8;
+    final end = _res.length;
+    final res = _res.substring(start, end);
+
+    out += swapEndianBytes(res);
+  }
+
+  return out;
+}
+
+final englistWordSet = [
+  "abbey",
+  "abducts",
+  "ability",
+  "ablaze",
+  "abnormal",
+  "abort",
+  "abrasive",
+  "absorb",
+  "abyss",
+  "academy",
+  "aces",
+  "aching",
+  "acidic",
+  "acoustic",
+  "acquire",
+  "across",
+  "actress",
+  "acumen",
+  "adapt",
+  "addicted",
+  "adept",
+  "adhesive",
+  "adjust",
+  "adopt",
+  "adrenalin",
+  "adult",
+  "adventure",
+  "aerial",
+  "afar",
+  "affair",
+  "afield",
+  "afloat",
+  "afoot",
+  "afraid",
+  "after",
+  "against",
+  "agenda",
+  "aggravate",
+  "agile",
+  "aglow",
+  "agnostic",
+  "agony",
+  "agreed",
+  "ahead",
+  "aided",
+  "ailments",
+  "aimless",
+  "airport",
+  "aisle",
+  "ajar",
+  "akin",
+  "alarms",
+  "album",
+  "alchemy",
+  "alerts",
+  "algebra",
+  "alkaline",
+  "alley",
+  "almost",
+  "aloof",
+  "alpine",
+  "already",
+  "also",
+  "altitude",
+  "alumni",
+  "always",
+  "amaze",
+  "ambush",
+  "amended",
+  "amidst",
+  "ammo",
+  "amnesty",
+  "among",
+  "amply",
+  "amused",
+  "anchor",
+  "android",
+  "anecdote",
+  "angled",
+  "ankle",
+  "annoyed",
+  "answers",
+  "antics",
+  "anvil",
+  "anxiety",
+  "anybody",
+  "apart",
+  "apex",
+  "aphid",
+  "aplomb",
+  "apology",
+  "apply",
+  "apricot",
+  "aptitude",
+  "aquarium",
+  "arbitrary",
+  "archer",
+  "ardent",
+  "arena",
+  "argue",
+  "arises",
+  "army",
+  "around",
+  "arrow",
+  "arsenic",
+  "artistic",
+  "ascend",
+  "ashtray",
+  "aside",
+  "asked",
+  "asleep",
+  "aspire",
+  "assorted",
+  "asylum",
+  "athlete",
+  "atlas",
+  "atom",
+  "atrium",
+  "attire",
+  "auburn",
+  "auctions",
+  "audio",
+  "august",
+  "aunt",
+  "austere",
+  "autumn",
+  "avatar",
+  "avidly",
+  "avoid",
+  "awakened",
+  "awesome",
+  "awful",
+  "awkward",
+  "awning",
+  "awoken",
+  "axes",
+  "axis",
+  "axle",
+  "aztec",
+  "azure",
+  "baby",
+  "bacon",
+  "badge",
+  "baffles",
+  "bagpipe",
+  "bailed",
+  "bakery",
+  "balding",
+  "bamboo",
+  "banjo",
+  "baptism",
+  "basin",
+  "batch",
+  "bawled",
+  "bays",
+  "because",
+  "beer",
+  "befit",
+  "begun",
+  "behind",
+  "being",
+  "below",
+  "bemused",
+  "benches",
+  "berries",
+  "bested",
+  "betting",
+  "bevel",
+  "beware",
+  "beyond",
+  "bias",
+  "bicycle",
+  "bids",
+  "bifocals",
+  "biggest",
+  "bikini",
+  "bimonthly",
+  "binocular",
+  "biology",
+  "biplane",
+  "birth",
+  "biscuit",
+  "bite",
+  "biweekly",
+  "blender",
+  "blip",
+  "bluntly",
+  "boat",
+  "bobsled",
+  "bodies",
+  "bogeys",
+  "boil",
+  "boldly",
+  "bomb",
+  "border",
+  "boss",
+  "both",
+  "bounced",
+  "bovine",
+  "bowling",
+  "boxes",
+  "boyfriend",
+  "broken",
+  "brunt",
+  "bubble",
+  "buckets",
+  "budget",
+  "buffet",
+  "bugs",
+  "building",
+  "bulb",
+  "bumper",
+  "bunch",
+  "business",
+  "butter",
+  "buying",
+  "buzzer",
+  "bygones",
+  "byline",
+  "bypass",
+  "cabin",
+  "cactus",
+  "cadets",
+  "cafe",
+  "cage",
+  "cajun",
+  "cake",
+  "calamity",
+  "camp",
+  "candy",
+  "casket",
+  "catch",
+  "cause",
+  "cavernous",
+  "cease",
+  "cedar",
+  "ceiling",
+  "cell",
+  "cement",
+  "cent",
+  "certain",
+  "chlorine",
+  "chrome",
+  "cider",
+  "cigar",
+  "cinema",
+  "circle",
+  "cistern",
+  "citadel",
+  "civilian",
+  "claim",
+  "click",
+  "clue",
+  "coal",
+  "cobra",
+  "cocoa",
+  "code",
+  "coexist",
+  "coffee",
+  "cogs",
+  "cohesive",
+  "coils",
+  "colony",
+  "comb",
+  "cool",
+  "copy",
+  "corrode",
+  "costume",
+  "cottage",
+  "cousin",
+  "cowl",
+  "criminal",
+  "cube",
+  "cucumber",
+  "cuddled",
+  "cuffs",
+  "cuisine",
+  "cunning",
+  "cupcake",
+  "custom",
+  "cycling",
+  "cylinder",
+  "cynical",
+  "dabbing",
+  "dads",
+  "daft",
+  "dagger",
+  "daily",
+  "damp",
+  "dangerous",
+  "dapper",
+  "darted",
+  "dash",
+  "dating",
+  "dauntless",
+  "dawn",
+  "daytime",
+  "dazed",
+  "debut",
+  "decay",
+  "dedicated",
+  "deepest",
+  "deftly",
+  "degrees",
+  "dehydrate",
+  "deity",
+  "dejected",
+  "delayed",
+  "demonstrate",
+  "dented",
+  "deodorant",
+  "depth",
+  "desk",
+  "devoid",
+  "dewdrop",
+  "dexterity",
+  "dialect",
+  "dice",
+  "diet",
+  "different",
+  "digit",
+  "dilute",
+  "dime",
+  "dinner",
+  "diode",
+  "diplomat",
+  "directed",
+  "distance",
+  "ditch",
+  "divers",
+  "dizzy",
+  "doctor",
+  "dodge",
+  "does",
+  "dogs",
+  "doing",
+  "dolphin",
+  "domestic",
+  "donuts",
+  "doorway",
+  "dormant",
+  "dosage",
+  "dotted",
+  "double",
+  "dove",
+  "down",
+  "dozen",
+  "dreams",
+  "drinks",
+  "drowning",
+  "drunk",
+  "drying",
+  "dual",
+  "dubbed",
+  "duckling",
+  "dude",
+  "duets",
+  "duke",
+  "dullness",
+  "dummy",
+  "dunes",
+  "duplex",
+  "duration",
+  "dusted",
+  "duties",
+  "dwarf",
+  "dwelt",
+  "dwindling",
+  "dying",
+  "dynamite",
+  "dyslexic",
+  "each",
+  "eagle",
+  "earth",
+  "easy",
+  "eating",
+  "eavesdrop",
+  "eccentric",
+  "echo",
+  "eclipse",
+  "economics",
+  "ecstatic",
+  "eden",
+  "edgy",
+  "edited",
+  "educated",
+  "eels",
+  "efficient",
+  "eggs",
+  "egotistic",
+  "eight",
+  "either",
+  "eject",
+  "elapse",
+  "elbow",
+  "eldest",
+  "eleven",
+  "elite",
+  "elope",
+  "else",
+  "eluded",
+  "emails",
+  "ember",
+  "emerge",
+  "emit",
+  "emotion",
+  "empty",
+  "emulate",
+  "energy",
+  "enforce",
+  "enhanced",
+  "enigma",
+  "enjoy",
+  "enlist",
+  "enmity",
+  "enough",
+  "enraged",
+  "ensign",
+  "entrance",
+  "envy",
+  "epoxy",
+  "equip",
+  "erase",
+  "erected",
+  "erosion",
+  "error",
+  "eskimos",
+  "espionage",
+  "essential",
+  "estate",
+  "etched",
+  "eternal",
+  "ethics",
+  "etiquette",
+  "evaluate",
+  "evenings",
+  "evicted",
+  "evolved",
+  "examine",
+  "excess",
+  "exhale",
+  "exit",
+  "exotic",
+  "exquisite",
+  "extra",
+  "exult",
+  "fabrics",
+  "factual",
+  "fading",
+  "fainted",
+  "faked",
+  "fall",
+  "family",
+  "fancy",
+  "farming",
+  "fatal",
+  "faulty",
+  "fawns",
+  "faxed",
+  "fazed",
+  "feast",
+  "february",
+  "federal",
+  "feel",
+  "feline",
+  "females",
+  "fences",
+  "ferry",
+  "festival",
+  "fetches",
+  "fever",
+  "fewest",
+  "fiat",
+  "fibula",
+  "fictional",
+  "fidget",
+  "fierce",
+  "fifteen",
+  "fight",
+  "films",
+  "firm",
+  "fishing",
+  "fitting",
+  "five",
+  "fixate",
+  "fizzle",
+  "fleet",
+  "flippant",
+  "flying",
+  "foamy",
+  "focus",
+  "foes",
+  "foggy",
+  "foiled",
+  "folding",
+  "fonts",
+  "foolish",
+  "fossil",
+  "fountain",
+  "fowls",
+  "foxes",
+  "foyer",
+  "framed",
+  "friendly",
+  "frown",
+  "fruit",
+  "frying",
+  "fudge",
+  "fuel",
+  "fugitive",
+  "fully",
+  "fuming",
+  "fungal",
+  "furnished",
+  "fuselage",
+  "future",
+  "fuzzy",
+  "gables",
+  "gadget",
+  "gags",
+  "gained",
+  "galaxy",
+  "gambit",
+  "gang",
+  "gasp",
+  "gather",
+  "gauze",
+  "gave",
+  "gawk",
+  "gaze",
+  "gearbox",
+  "gecko",
+  "geek",
+  "gels",
+  "gemstone",
+  "general",
+  "geometry",
+  "germs",
+  "gesture",
+  "getting",
+  "geyser",
+  "ghetto",
+  "ghost",
+  "giant",
+  "giddy",
+  "gifts",
+  "gigantic",
+  "gills",
+  "gimmick",
+  "ginger",
+  "girth",
+  "giving",
+  "glass",
+  "gleeful",
+  "glide",
+  "gnaw",
+  "gnome",
+  "goat",
+  "goblet",
+  "godfather",
+  "goes",
+  "goggles",
+  "going",
+  "goldfish",
+  "gone",
+  "goodbye",
+  "gopher",
+  "gorilla",
+  "gossip",
+  "gotten",
+  "gourmet",
+  "governing",
+  "gown",
+  "greater",
+  "grunt",
+  "guarded",
+  "guest",
+  "guide",
+  "gulp",
+  "gumball",
+  "guru",
+  "gusts",
+  "gutter",
+  "guys",
+  "gymnast",
+  "gypsy",
+  "gyrate",
+  "habitat",
+  "hacksaw",
+  "haggled",
+  "hairy",
+  "hamburger",
+  "happens",
+  "hashing",
+  "hatchet",
+  "haunted",
+  "having",
+  "hawk",
+  "haystack",
+  "hazard",
+  "hectare",
+  "hedgehog",
+  "heels",
+  "hefty",
+  "height",
+  "hemlock",
+  "hence",
+  "heron",
+  "hesitate",
+  "hexagon",
+  "hickory",
+  "hiding",
+  "highway",
+  "hijack",
+  "hiker",
+  "hills",
+  "himself",
+  "hinder",
+  "hippo",
+  "hire",
+  "history",
+  "hitched",
+  "hive",
+  "hoax",
+  "hobby",
+  "hockey",
+  "hoisting",
+  "hold",
+  "honked",
+  "hookup",
+  "hope",
+  "hornet",
+  "hospital",
+  "hotel",
+  "hounded",
+  "hover",
+  "howls",
+  "hubcaps",
+  "huddle",
+  "huge",
+  "hull",
+  "humid",
+  "hunter",
+  "hurried",
+  "husband",
+  "huts",
+  "hybrid",
+  "hydrogen",
+  "hyper",
+  "iceberg",
+  "icing",
+  "icon",
+  "identity",
+  "idiom",
+  "idled",
+  "idols",
+  "igloo",
+  "ignore",
+  "iguana",
+  "illness",
+  "imagine",
+  "imbalance",
+  "imitate",
+  "impel",
+  "inactive",
+  "inbound",
+  "incur",
+  "industrial",
+  "inexact",
+  "inflamed",
+  "ingested",
+  "initiate",
+  "injury",
+  "inkling",
+  "inline",
+  "inmate",
+  "innocent",
+  "inorganic",
+  "input",
+  "inquest",
+  "inroads",
+  "insult",
+  "intended",
+  "inundate",
+  "invoke",
+  "inwardly",
+  "ionic",
+  "irate",
+  "iris",
+  "irony",
+  "irritate",
+  "island",
+  "isolated",
+  "issued",
+  "italics",
+  "itches",
+  "items",
+  "itinerary",
+  "itself",
+  "ivory",
+  "jabbed",
+  "jackets",
+  "jaded",
+  "jagged",
+  "jailed",
+  "jamming",
+  "january",
+  "jargon",
+  "jaunt",
+  "javelin",
+  "jaws",
+  "jazz",
+  "jeans",
+  "jeers",
+  "jellyfish",
+  "jeopardy",
+  "jerseys",
+  "jester",
+  "jetting",
+  "jewels",
+  "jigsaw",
+  "jingle",
+  "jittery",
+  "jive",
+  "jobs",
+  "jockey",
+  "jogger",
+  "joining",
+  "joking",
+  "jolted",
+  "jostle",
+  "journal",
+  "joyous",
+  "jubilee",
+  "judge",
+  "juggled",
+  "juicy",
+  "jukebox",
+  "july",
+  "jump",
+  "junk",
+  "jury",
+  "justice",
+  "juvenile",
+  "kangaroo",
+  "karate",
+  "keep",
+  "kennel",
+  "kept",
+  "kernels",
+  "kettle",
+  "keyboard",
+  "kickoff",
+  "kidneys",
+  "king",
+  "kiosk",
+  "kisses",
+  "kitchens",
+  "kiwi",
+  "knapsack",
+  "knee",
+  "knife",
+  "knowledge",
+  "knuckle",
+  "koala",
+  "laboratory",
+  "ladder",
+  "lagoon",
+  "lair",
+  "lakes",
+  "lamb",
+  "language",
+  "laptop",
+  "large",
+  "last",
+  "later",
+  "launching",
+  "lava",
+  "lawsuit",
+  "layout",
+  "lazy",
+  "lectures",
+  "ledge",
+  "leech",
+  "left",
+  "legion",
+  "leisure",
+  "lemon",
+  "lending",
+  "leopard",
+  "lesson",
+  "lettuce",
+  "lexicon",
+  "liar",
+  "library",
+  "licks",
+  "lids",
+  "lied",
+  "lifestyle",
+  "light",
+  "likewise",
+  "lilac",
+  "limits",
+  "linen",
+  "lion",
+  "lipstick",
+  "liquid",
+  "listen",
+  "lively",
+  "loaded",
+  "lobster",
+  "locker",
+  "lodge",
+  "lofty",
+  "logic",
+  "loincloth",
+  "long",
+  "looking",
+  "lopped",
+  "lordship",
+  "losing",
+  "lottery",
+  "loudly",
+  "love",
+  "lower",
+  "loyal",
+  "lucky",
+  "luggage",
+  "lukewarm",
+  "lullaby",
+  "lumber",
+  "lunar",
+  "lurk",
+  "lush",
+  "luxury",
+  "lymph",
+  "lynx",
+  "lyrics",
+  "macro",
+  "madness",
+  "magically",
+  "mailed",
+  "major",
+  "makeup",
+  "malady",
+  "mammal",
+  "maps",
+  "masterful",
+  "match",
+  "maul",
+  "maverick",
+  "maximum",
+  "mayor",
+  "maze",
+  "meant",
+  "mechanic",
+  "medicate",
+  "meeting",
+  "megabyte",
+  "melting",
+  "memoir",
+  "menu",
+  "merger",
+  "mesh",
+  "metro",
+  "mews",
+  "mice",
+  "midst",
+  "mighty",
+  "mime",
+  "mirror",
+  "misery",
+  "mittens",
+  "mixture",
+  "moat",
+  "mobile",
+  "mocked",
+  "mohawk",
+  "moisture",
+  "molten",
+  "moment",
+  "money",
+  "moon",
+  "mops",
+  "morsel",
+  "mostly",
+  "motherly",
+  "mouth",
+  "movement",
+  "mowing",
+  "much",
+  "muddy",
+  "muffin",
+  "mugged",
+  "mullet",
+  "mumble",
+  "mundane",
+  "muppet",
+  "mural",
+  "musical",
+  "muzzle",
+  "myriad",
+  "mystery",
+  "myth",
+  "nabbing",
+  "nagged",
+  "nail",
+  "names",
+  "nanny",
+  "napkin",
+  "narrate",
+  "nasty",
+  "natural",
+  "nautical",
+  "navy",
+  "nearby",
+  "necklace",
+  "needed",
+  "negative",
+  "neither",
+  "neon",
+  "nephew",
+  "nerves",
+  "nestle",
+  "network",
+  "neutral",
+  "never",
+  "newt",
+  "nexus",
+  "nibs",
+  "niche",
+  "niece",
+  "nifty",
+  "nightly",
+  "nimbly",
+  "nineteen",
+  "nirvana",
+  "nitrogen",
+  "nobody",
+  "nocturnal",
+  "nodes",
+  "noises",
+  "nomad",
+  "noodles",
+  "northern",
+  "nostril",
+  "noted",
+  "nouns",
+  "novelty",
+  "nowhere",
+  "nozzle",
+  "nuance",
+  "nucleus",
+  "nudged",
+  "nugget",
+  "nuisance",
+  "null",
+  "number",
+  "nuns",
+  "nurse",
+  "nutshell",
+  "nylon",
+  "oaks",
+  "oars",
+  "oasis",
+  "oatmeal",
+  "obedient",
+  "object",
+  "obliged",
+  "obnoxious",
+  "observant",
+  "obtains",
+  "obvious",
+  "occur",
+  "ocean",
+  "october",
+  "odds",
+  "odometer",
+  "offend",
+  "often",
+  "oilfield",
+  "ointment",
+  "okay",
+  "older",
+  "olive",
+  "olympics",
+  "omega",
+  "omission",
+  "omnibus",
+  "onboard",
+  "oncoming",
+  "oneself",
+  "ongoing",
+  "onion",
+  "online",
+  "onslaught",
+  "onto",
+  "onward",
+  "oozed",
+  "opacity",
+  "opened",
+  "opposite",
+  "optical",
+  "opus",
+  "orange",
+  "orbit",
+  "orchid",
+  "orders",
+  "organs",
+  "origin",
+  "ornament",
+  "orphans",
+  "oscar",
+  "ostrich",
+  "otherwise",
+  "otter",
+  "ouch",
+  "ought",
+  "ounce",
+  "ourselves",
+  "oust",
+  "outbreak",
+  "oval",
+  "oven",
+  "owed",
+  "owls",
+  "owner",
+  "oxidant",
+  "oxygen",
+  "oyster",
+  "ozone",
+  "pact",
+  "paddles",
+  "pager",
+  "pairing",
+  "palace",
+  "pamphlet",
+  "pancakes",
+  "paper",
+  "paradise",
+  "pastry",
+  "patio",
+  "pause",
+  "pavements",
+  "pawnshop",
+  "payment",
+  "peaches",
+  "pebbles",
+  "peculiar",
+  "pedantic",
+  "peeled",
+  "pegs",
+  "pelican",
+  "pencil",
+  "people",
+  "pepper",
+  "perfect",
+  "pests",
+  "petals",
+  "phase",
+  "pheasants",
+  "phone",
+  "phrases",
+  "physics",
+  "piano",
+  "picked",
+  "pierce",
+  "pigment",
+  "piloted",
+  "pimple",
+  "pinched",
+  "pioneer",
+  "pipeline",
+  "pirate",
+  "pistons",
+  "pitched",
+  "pivot",
+  "pixels",
+  "pizza",
+  "playful",
+  "pledge",
+  "pliers",
+  "plotting",
+  "plus",
+  "plywood",
+  "poaching",
+  "pockets",
+  "podcast",
+  "poetry",
+  "point",
+  "poker",
+  "polar",
+  "ponies",
+  "pool",
+  "popular",
+  "portents",
+  "possible",
+  "potato",
+  "pouch",
+  "poverty",
+  "powder",
+  "pram",
+  "present",
+  "pride",
+  "problems",
+  "pruned",
+  "prying",
+  "psychic",
+  "public",
+  "puck",
+  "puddle",
+  "puffin",
+  "pulp",
+  "pumpkins",
+  "punch",
+  "puppy",
+  "purged",
+  "push",
+  "putty",
+  "puzzled",
+  "pylons",
+  "pyramid",
+  "python",
+  "queen",
+  "quick",
+  "quote",
+  "rabbits",
+  "racetrack",
+  "radar",
+  "rafts",
+  "rage",
+  "railway",
+  "raking",
+  "rally",
+  "ramped",
+  "randomly",
+  "rapid",
+  "rarest",
+  "rash",
+  "rated",
+  "ravine",
+  "rays",
+  "razor",
+  "react",
+  "rebel",
+  "recipe",
+  "reduce",
+  "reef",
+  "refer",
+  "regular",
+  "reheat",
+  "reinvest",
+  "rejoices",
+  "rekindle",
+  "relic",
+  "remedy",
+  "renting",
+  "reorder",
+  "repent",
+  "request",
+  "reruns",
+  "rest",
+  "return",
+  "reunion",
+  "revamp",
+  "rewind",
+  "rhino",
+  "rhythm",
+  "ribbon",
+  "richly",
+  "ridges",
+  "rift",
+  "rigid",
+  "rims",
+  "ringing",
+  "riots",
+  "ripped",
+  "rising",
+  "ritual",
+  "river",
+  "roared",
+  "robot",
+  "rockets",
+  "rodent",
+  "rogue",
+  "roles",
+  "romance",
+  "roomy",
+  "roped",
+  "roster",
+  "rotate",
+  "rounded",
+  "rover",
+  "rowboat",
+  "royal",
+  "ruby",
+  "rudely",
+  "ruffled",
+  "rugged",
+  "ruined",
+  "ruling",
+  "rumble",
+  "runway",
+  "rural",
+  "rustled",
+  "ruthless",
+  "sabotage",
+  "sack",
+  "sadness",
+  "safety",
+  "saga",
+  "sailor",
+  "sake",
+  "salads",
+  "sample",
+  "sanity",
+  "sapling",
+  "sarcasm",
+  "sash",
+  "satin",
+  "saucepan",
+  "saved",
+  "sawmill",
+  "saxophone",
+  "sayings",
+  "scamper",
+  "scenic",
+  "school",
+  "science",
+  "scoop",
+  "scrub",
+  "scuba",
+  "seasons",
+  "second",
+  "sedan",
+  "seeded",
+  "segments",
+  "seismic",
+  "selfish",
+  "semifinal",
+  "sensible",
+  "september",
+  "sequence",
+  "serving",
+  "session",
+  "setup",
+  "seventh",
+  "sewage",
+  "shackles",
+  "shelter",
+  "shipped",
+  "shocking",
+  "shrugged",
+  "shuffled",
+  "shyness",
+  "siblings",
+  "sickness",
+  "sidekick",
+  "sieve",
+  "sifting",
+  "sighting",
+  "silk",
+  "simplest",
+  "sincerely",
+  "sipped",
+  "siren",
+  "situated",
+  "sixteen",
+  "sizes",
+  "skater",
+  "skew",
+  "skirting",
+  "skulls",
+  "skydive",
+  "slackens",
+  "sleepless",
+  "slid",
+  "slower",
+  "slug",
+  "smash",
+  "smelting",
+  "smidgen",
+  "smog",
+  "smuggled",
+  "snake",
+  "sneeze",
+  "sniff",
+  "snout",
+  "snug",
+  "soapy",
+  "sober",
+  "soccer",
+  "soda",
+  "software",
+  "soggy",
+  "soil",
+  "solved",
+  "somewhere",
+  "sonic",
+  "soothe",
+  "soprano",
+  "sorry",
+  "southern",
+  "sovereign",
+  "sowed",
+  "soya",
+  "space",
+  "speedy",
+  "sphere",
+  "spiders",
+  "splendid",
+  "spout",
+  "sprig",
+  "spud",
+  "spying",
+  "square",
+  "stacking",
+  "stellar",
+  "stick",
+  "stockpile",
+  "strained",
+  "stunning",
+  "stylishly",
+  "subtly",
+  "succeed",
+  "suddenly",
+  "suede",
+  "suffice",
+  "sugar",
+  "suitcase",
+  "sulking",
+  "summon",
+  "sunken",
+  "superior",
+  "surfer",
+  "sushi",
+  "suture",
+  "swagger",
+  "swept",
+  "swiftly",
+  "sword",
+  "swung",
+  "syllabus",
+  "symptoms",
+  "syndrome",
+  "syringe",
+  "system",
+  "taboo",
+  "tacit",
+  "tadpoles",
+  "tagged",
+  "tail",
+  "taken",
+  "talent",
+  "tamper",
+  "tanks",
+  "tapestry",
+  "tarnished",
+  "tasked",
+  "tattoo",
+  "taunts",
+  "tavern",
+  "tawny",
+  "taxi",
+  "teardrop",
+  "technical",
+  "tedious",
+  "teeming",
+  "tell",
+  "template",
+  "tender",
+  "tepid",
+  "tequila",
+  "terminal",
+  "testing",
+  "tether",
+  "textbook",
+  "thaw",
+  "theatrics",
+  "thirsty",
+  "thorn",
+  "threaten",
+  "thumbs",
+  "thwart",
+  "ticket",
+  "tidy",
+  "tiers",
+  "tiger",
+  "tilt",
+  "timber",
+  "tinted",
+  "tipsy",
+  "tirade",
+  "tissue",
+  "titans",
+  "toaster",
+  "tobacco",
+  "today",
+  "toenail",
+  "toffee",
+  "together",
+  "toilet",
+  "token",
+  "tolerant",
+  "tomorrow",
+  "tonic",
+  "toolbox",
+  "topic",
+  "torch",
+  "tossed",
+  "total",
+  "touchy",
+  "towel",
+  "toxic",
+  "toyed",
+  "trash",
+  "trendy",
+  "tribal",
+  "trolling",
+  "truth",
+  "trying",
+  "tsunami",
+  "tubes",
+  "tucks",
+  "tudor",
+  "tuesday",
+  "tufts",
+  "tugs",
+  "tuition",
+  "tulips",
+  "tumbling",
+  "tunnel",
+  "turnip",
+  "tusks",
+  "tutor",
+  "tuxedo",
+  "twang",
+  "tweezers",
+  "twice",
+  "twofold",
+  "tycoon",
+  "typist",
+  "tyrant",
+  "ugly",
+  "ulcers",
+  "ultimate",
+  "umbrella",
+  "umpire",
+  "unafraid",
+  "unbending",
+  "uncle",
+  "under",
+  "uneven",
+  "unfit",
+  "ungainly",
+  "unhappy",
+  "union",
+  "unjustly",
+  "unknown",
+  "unlikely",
+  "unmask",
+  "unnoticed",
+  "unopened",
+  "unplugs",
+  "unquoted",
+  "unrest",
+  "unsafe",
+  "until",
+  "unusual",
+  "unveil",
+  "unwind",
+  "unzip",
+  "upbeat",
+  "upcoming",
+  "update",
+  "upgrade",
+  "uphill",
+  "upkeep",
+  "upload",
+  "upon",
+  "upper",
+  "upright",
+  "upstairs",
+  "uptight",
+  "upwards",
+  "urban",
+  "urchins",
+  "urgent",
+  "usage",
+  "useful",
+  "usher",
+  "using",
+  "usual",
+  "utensils",
+  "utility",
+  "utmost",
+  "utopia",
+  "uttered",
+  "vacation",
+  "vague",
+  "vain",
+  "value",
+  "vampire",
+  "vane",
+  "vapidly",
+  "vary",
+  "vastness",
+  "vats",
+  "vaults",
+  "vector",
+  "veered",
+  "vegan",
+  "vehicle",
+  "vein",
+  "velvet",
+  "venomous",
+  "verification",
+  "vessel",
+  "veteran",
+  "vexed",
+  "vials",
+  "vibrate",
+  "victim",
+  "video",
+  "viewpoint",
+  "vigilant",
+  "viking",
+  "village",
+  "vinegar",
+  "violin",
+  "vipers",
+  "virtual",
+  "visited",
+  "vitals",
+  "vivid",
+  "vixen",
+  "vocal",
+  "vogue",
+  "voice",
+  "volcano",
+  "vortex",
+  "voted",
+  "voucher",
+  "vowels",
+  "voyage",
+  "vulture",
+  "wade",
+  "waffle",
+  "wagtail",
+  "waist",
+  "waking",
+  "wallets",
+  "wanted",
+  "warped",
+  "washing",
+  "water",
+  "waveform",
+  "waxing",
+  "wayside",
+  "weavers",
+  "website",
+  "wedge",
+  "weekday",
+  "weird",
+  "welders",
+  "went",
+  "wept",
+  "were",
+  "western",
+  "wetsuit",
+  "whale",
+  "when",
+  "whipped",
+  "whole",
+  "wickets",
+  "width",
+  "wield",
+  "wife",
+  "wiggle",
+  "wildly",
+  "winter",
+  "wipeout",
+  "wiring",
+  "wise",
+  "withdrawn",
+  "wives",
+  "wizard",
+  "wobbly",
+  "woes",
+  "woken",
+  "wolf",
+  "womanly",
+  "wonders",
+  "woozy",
+  "worry",
+  "wounded",
+  "woven",
+  "wrap",
+  "wrist",
+  "wrong",
+  "yacht",
+  "yahoo",
+  "yanks",
+  "yard",
+  "yawning",
+  "yearbook",
+  "yellow",
+  "yesterday",
+  "yeti",
+  "yields",
+  "yodel",
+  "yoga",
+  "younger",
+  "yoyo",
+  "zapped",
+  "zeal",
+  "zebra",
+  "zero",
+  "zesty",
+  "zigzags",
+  "zinger",
+  "zippers",
+  "zodiac",
+  "zombie",
+  "zones",
+  "zoom"
+];
diff --git a/cw_wownero/pubspec.lock b/cw_wownero/pubspec.lock
index c90340800..b0347c023 100644
--- a/cw_wownero/pubspec.lock
+++ b/cw_wownero/pubspec.lock
@@ -41,6 +41,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.11.0"
+  bluez:
+    dependency: transitive
+    description:
+      name: bluez
+      sha256: "203a1924e818a9dd74af2b2c7a8f375ab8e5edf0e486bba8f90a0d8a17ed9fce"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.8.2"
   boolean_selector:
     dependency: transitive
     description:
@@ -209,6 +217,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.2.4"
+  dbus:
+    dependency: transitive
+    description:
+      name: dbus
+      sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.7.10"
   encrypt:
     dependency: "direct main"
     description:
@@ -267,6 +283,14 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_web_bluetooth:
+    dependency: transitive
+    description:
+      name: flutter_web_bluetooth
+      sha256: "52ce64f65d7321c4bf6abfe9dac02fb888731339a5e0ad6de59fb916c20c9f02"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.2.3"
   frontend_server_client:
     dependency: transitive
     description:
@@ -403,6 +427,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.0.1"
+  ledger_flutter_plus:
+    dependency: transitive
+    description:
+      name: ledger_flutter_plus
+      sha256: ea3ed586e1697776dacf42ac979095f1ca3bd143bf007cbe5c78e09cb6943f42
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.5"
+  ledger_usb_plus:
+    dependency: transitive
+    description:
+      name: ledger_usb_plus
+      sha256: "21cc5d976cf7edb3518bd2a0c4164139cbb0817d2e4f2054707fc4edfdf9ce87"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.4"
   logging:
     dependency: transitive
     description:
@@ -463,8 +503,8 @@ packages:
     dependency: "direct main"
     description:
       path: "impls/monero.dart"
-      ref: "6eb571ea498ed7b854934785f00fabfd0dadf75b"
-      resolved-ref: "6eb571ea498ed7b854934785f00fabfd0dadf75b"
+      ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
+      resolved-ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
       url: "https://github.com/mrcyjanek/monero_c"
     source: git
     version: "0.0.0"
@@ -540,6 +580,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.2.1"
+  petitparser:
+    dependency: transitive
+    description:
+      name: petitparser
+      sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
+      url: "https://pub.dev"
+    source: hosted
+    version: "6.0.2"
   platform:
     dependency: transitive
     description:
@@ -552,10 +600,10 @@ packages:
     dependency: transitive
     description:
       name: plugin_platform_interface
-      sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a
+      sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.3"
+    version: "2.1.8"
   pointycastle:
     dependency: transitive
     description:
@@ -596,6 +644,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.2.1"
+  rxdart:
+    dependency: transitive
+    description:
+      name: rxdart
+      sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.28.0"
   shelf:
     dependency: transitive
     description:
@@ -721,6 +777,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.1"
+  universal_ble:
+    dependency: transitive
+    description:
+      name: universal_ble
+      sha256: "0dfbd6b64bff3ad61ed7a895c232530d9614e9b01ab261a74433a43267edb7f3"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.12.0"
+  universal_platform:
+    dependency: transitive
+    description:
+      name: universal_platform
+      sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.1.0"
   unorm_dart:
     dependency: transitive
     description:
@@ -777,6 +849,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.4"
+  xml:
+    dependency: transitive
+    description:
+      name: xml
+      sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
+      url: "https://pub.dev"
+    source: hosted
+    version: "6.5.0"
   yaml:
     dependency: transitive
     description:
@@ -786,5 +866,5 @@ packages:
     source: hosted
     version: "3.1.1"
 sdks:
-  dart: ">=3.2.0-0 <4.0.0"
-  flutter: ">=3.7.0"
+  dart: ">=3.3.0 <4.0.0"
+  flutter: ">=3.19.0"
diff --git a/cw_wownero/pubspec.yaml b/cw_wownero/pubspec.yaml
index 6943e60c3..582c15447 100644
--- a/cw_wownero/pubspec.yaml
+++ b/cw_wownero/pubspec.yaml
@@ -25,7 +25,8 @@ dependencies:
   monero:
     git:
       url: https://github.com/mrcyjanek/monero_c
-      ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash
+      ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
+#      ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash
       path: impls/monero.dart
   mutex: ^3.1.0
 
diff --git a/lib/core/wallet_loading_service.dart b/lib/core/wallet_loading_service.dart
index e58e14652..10e438e0c 100644
--- a/lib/core/wallet_loading_service.dart
+++ b/lib/core/wallet_loading_service.dart
@@ -14,7 +14,11 @@ import 'package:flutter/material.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 
 class WalletLoadingService {
-  WalletLoadingService(this.sharedPreferences, this.keyService, this.walletServiceFactory);
+  WalletLoadingService(
+    this.sharedPreferences,
+    this.keyService,
+    this.walletServiceFactory,
+  );
 
   final SharedPreferences sharedPreferences;
   final KeyService keyService;
@@ -77,7 +81,8 @@ class WalletLoadingService {
             await updateMoneroWalletPassword(wallet);
           }
 
-          await sharedPreferences.setString(PreferencesKey.currentWalletName, wallet.name);
+          await sharedPreferences.setString(
+              PreferencesKey.currentWalletName, wallet.name);
           await sharedPreferences.setInt(
               PreferencesKey.currentWalletType, serializeToInt(wallet.type));
 
@@ -129,4 +134,9 @@ class WalletLoadingService {
 
     return "\n\n$type ($name): ${await walletService.getSeeds(name, password, type)}";
   }
+
+  bool requireHardwareWalletConnection(WalletType type, String name) {
+    final walletService = walletServiceFactory.call(type);
+    return walletService.requireHardwareWalletConnection(name);
+  }
 }
diff --git a/lib/di.dart b/lib/di.dart
index 8dd1029a9..facdec912 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -32,12 +32,14 @@ import 'package:cake_wallet/entities/biometric_auth.dart';
 import 'package:cake_wallet/entities/contact.dart';
 import 'package:cake_wallet/entities/contact_record.dart';
 import 'package:cake_wallet/entities/exchange_api_mode.dart';
+import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart';
 import 'package:cake_wallet/entities/parse_address_from_domain.dart';
 import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
 import 'package:cake_wallet/entities/wallet_manager.dart';
 import 'package:cake_wallet/src/screens/buy/buy_sell_options_page.dart';
 import 'package:cake_wallet/src/screens/buy/payment_method_options_page.dart';
 import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
+import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart';
 import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart';
 import 'package:cake_wallet/src/screens/settings/mweb_node_page.dart';
 import 'package:cake_wallet/view_model/link_view_model.dart';
@@ -184,7 +186,6 @@ import 'package:cake_wallet/src/screens/transaction_details/transaction_details_
 import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart';
 import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart';
 import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
-import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart';
 import 'package:cake_wallet/store/app_store.dart';
 import 'package:cake_wallet/store/authentication_store.dart';
 import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
@@ -586,7 +587,7 @@ Future<void> setup({
         );
       } else {
         // wallet is already loaded:
-        if (appStore.wallet != null) {
+        if (appStore.wallet != null || requireHardwareWalletConnection()) {
           // goes to the dashboard:
           authStore.allowed();
           // trigger any deep links:
@@ -780,10 +781,12 @@ Future<void> setup({
     );
   }
 
-  getIt.registerFactory(() => WalletListPage(
-        walletListViewModel: getIt.get<WalletListViewModel>(),
-        authService: getIt.get<AuthService>(),
-      ));
+  getIt.registerFactoryParam<WalletListPage, Function(BuildContext)?, void>(
+      (Function(BuildContext)? onWalletLoaded, _) => WalletListPage(
+            walletListViewModel: getIt.get<WalletListViewModel>(),
+            authService: getIt.get<AuthService>(),
+            onWalletLoaded: onWalletLoaded,
+          ));
 
   getIt.registerFactoryParam<WalletEditViewModel, WalletListViewModel, void>(
     (WalletListViewModel walletListViewModel, _) => WalletEditViewModel(
diff --git a/lib/entities/hardware_wallet/require_hardware_wallet_connection.dart b/lib/entities/hardware_wallet/require_hardware_wallet_connection.dart
new file mode 100644
index 000000000..a64fa5873
--- /dev/null
+++ b/lib/entities/hardware_wallet/require_hardware_wallet_connection.dart
@@ -0,0 +1,25 @@
+import 'package:cake_wallet/core/wallet_loading_service.dart';
+import 'package:cake_wallet/di.dart';
+import 'package:cake_wallet/entities/preferences_key.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+bool requireHardwareWalletConnection() {
+  final name = getIt
+      .get<SharedPreferences>()
+      .getString(PreferencesKey.currentWalletName);
+  final typeRaw =
+      getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType);
+
+  if (typeRaw == null) {
+    return false;
+  }
+
+  if (name == null) {
+    throw Exception('Incorrect current wallet name: $name');
+  }
+
+  final type = deserializeFromInt(typeRaw);
+  final walletLoadingService = getIt.get<WalletLoadingService>();
+  return walletLoadingService.requireHardwareWalletConnection(type, name);
+}
diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart
index dfda4d600..09d9889c5 100644
--- a/lib/monero/cw_monero.dart
+++ b/lib/monero/cw_monero.dart
@@ -225,6 +225,19 @@ class CWMonero extends Monero {
           language: language,
           height: height);
 
+  @override
+  WalletCredentials createMoneroRestoreWalletFromHardwareCredentials({
+    required String name,
+    required String password,
+    required int height,
+    required ledger.LedgerConnection ledgerConnection,
+  }) =>
+      MoneroRestoreWalletFromHardwareCredentials(
+          name: name,
+          password: password,
+          height: height,
+          ledgerConnection: ledgerConnection);
+
   @override
   WalletCredentials createMoneroRestoreWalletFromSeedCredentials(
           {required String name,
@@ -383,6 +396,18 @@ class CWMonero extends Monero {
     checkIfMoneroCIsFine();
   }
 
+  @override
+  void setLedgerConnection(Object wallet, ledger.LedgerConnection connection) {
+    final moneroWallet = wallet as MoneroWallet;
+    moneroWallet.setLedgerConnection(connection);
+  }
+
+  @override
+  void setGlobalLedgerConnection(ledger.LedgerConnection connection) {
+    gLedger = connection;
+    keepAlive(connection);
+  }
+
   bool isViewOnly() {
     return isViewOnlyBySpendKey();
   }
diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart
index 1aa0a12c6..b411c5a15 100644
--- a/lib/reactions/on_authentication_state_change.dart
+++ b/lib/reactions/on_authentication_state_change.dart
@@ -1,18 +1,28 @@
 import 'dart:async';
 
+import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
+import 'package:cake_wallet/di.dart';
+import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart';
+import 'package:cake_wallet/entities/load_current_wallet.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/monero/monero.dart';
 import 'package:cake_wallet/routes.dart';
-import 'package:cake_wallet/utils/exception_handler.dart';
+import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
+import 'package:cake_wallet/store/authentication_store.dart';
 import 'package:cake_wallet/store/settings_store.dart';
+import 'package:cake_wallet/utils/exception_handler.dart';
+import 'package:cake_wallet/utils/show_pop_up.dart';
+import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/widgets.dart';
 import 'package:mobx/mobx.dart';
-import 'package:cake_wallet/entities/load_current_wallet.dart';
-import 'package:cake_wallet/store/authentication_store.dart';
 import 'package:rxdart/subjects.dart';
 
 ReactionDisposer? _onAuthenticationStateChange;
 
 dynamic loginError;
-StreamController<dynamic> authenticatedErrorStreamController = BehaviorSubject<dynamic>();
+StreamController<dynamic> authenticatedErrorStreamController =
+    BehaviorSubject<dynamic>();
 
 void startAuthenticationStateChange(
   AuthenticationStore authenticationStore,
@@ -27,18 +37,49 @@ void startAuthenticationStateChange(
   _onAuthenticationStateChange ??= autorun((_) async {
     final state = authenticationStore.state;
 
-    if (state == AuthenticationState.installed && !SettingsStoreBase.walletPasswordDirectInput) {
+    if (state == AuthenticationState.installed &&
+        !SettingsStoreBase.walletPasswordDirectInput) {
       try {
-        await loadCurrentWallet();
+        if (!requireHardwareWalletConnection()) await loadCurrentWallet();
       } catch (error, stack) {
         loginError = error;
-        ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
+        ExceptionHandler.onError(
+            FlutterErrorDetails(exception: error, stack: stack));
       }
       return;
     }
 
     if (state == AuthenticationState.allowed) {
-      await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
+      if (requireHardwareWalletConnection()) {
+        await navigatorKey.currentState!.pushNamedAndRemoveUntil(
+          Routes.connectDevices,
+          (route) => false,
+          arguments: ConnectDevicePageParams(
+            walletType: WalletType.monero,
+            onConnectDevice: (context, ledgerVM) async {
+              monero!.setGlobalLedgerConnection(ledgerVM.connection);
+                showPopUp<void>(
+                  context: context,
+                  builder: (BuildContext context) => AlertWithOneAction(
+                      alertTitle: S.of(context).proceed_on_device,
+                      alertContent: S.of(context).proceed_on_device_description,
+                      buttonText: S.of(context).cancel,
+                      buttonAction: () => Navigator.of(context).pop()),
+                );
+              await loadCurrentWallet();
+              getIt.get<BottomSheetService>().resetCurrentSheet();
+              await navigatorKey.currentState!
+                  .pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
+            },
+            allowChangeWallet: true,
+          ),
+        );
+
+        // await navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.connectDevices, (route) => false, arguments: ConnectDevicePageParams(walletType: walletType, onConnectDevice: onConnectDevice));
+      } else {
+        await navigatorKey.currentState!
+            .pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
+      }
       if (!(await authenticatedErrorStreamController.stream.isEmpty)) {
         ExceptionHandler.showError(
             (await authenticatedErrorStreamController.stream.first).toString());
diff --git a/lib/router.dart b/lib/router.dart
index 781a6e057..1382da28f 100644
--- a/lib/router.dart
+++ b/lib/router.dart
@@ -24,6 +24,7 @@ import 'package:cake_wallet/src/screens/buy/webview_page.dart';
 import 'package:cake_wallet/src/screens/cake_pay/auth/cake_pay_account_page.dart';
 import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
 import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
+import 'package:cake_wallet/src/screens/connect_device/monero_hardware_wallet_options_page.dart';
 import 'package:cake_wallet/src/screens/connect_device/select_hardware_wallet_account_page.dart';
 import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
 import 'package:cake_wallet/src/screens/contact/contact_page.dart';
@@ -212,6 +213,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
       final type = arguments[0] as WalletType;
       final walletVM = getIt.get<WalletHardwareRestoreViewModel>(param1: type);
 
+      if (type == WalletType.monero)
+        return CupertinoPageRoute<void>(builder: (_) => MoneroHardwareWalletOptionsPage(walletVM));
+
       return CupertinoPageRoute<void>(builder: (_) => SelectHardwareWalletAccountPage(walletVM));
 
     case Routes.setupPin:
@@ -403,8 +407,11 @@ Route<dynamic> createRoute(RouteSettings settings) {
       return CupertinoPageRoute<void>(builder: (_) => getIt.get<NanoChangeRepPage>());
 
     case Routes.walletList:
+      final onWalletLoaded = settings.arguments as Function(BuildContext)?;
       return MaterialPageRoute<void>(
-          fullscreenDialog: true, builder: (_) => getIt.get<WalletListPage>());
+        fullscreenDialog: true,
+        builder: (_) => getIt.get<WalletListPage>(param1: onWalletLoaded),
+      );
 
     case Routes.walletEdit:
       return MaterialPageRoute<void>(
diff --git a/lib/src/screens/connect_device/connect_device_page.dart b/lib/src/screens/connect_device/connect_device_page.dart
index 9e331e818..c2cc40229 100644
--- a/lib/src/screens/connect_device/connect_device_page.dart
+++ b/lib/src/screens/connect_device/connect_device_page.dart
@@ -2,9 +2,12 @@ import 'dart:async';
 import 'dart:io';
 
 import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/src/screens/base_page.dart';
 import 'package:cake_wallet/src/screens/connect_device/widgets/device_tile.dart';
+import 'package:cake_wallet/src/widgets/primary_button.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
+import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
 import 'package:cw_core/wallet_type.dart';
@@ -17,35 +20,46 @@ typedef OnConnectDevice = void Function(BuildContext, LedgerViewModel);
 class ConnectDevicePageParams {
   final WalletType walletType;
   final OnConnectDevice onConnectDevice;
+  final bool allowChangeWallet;
 
-  ConnectDevicePageParams(
-      {required this.walletType, required this.onConnectDevice});
+  ConnectDevicePageParams({
+    required this.walletType,
+    required this.onConnectDevice,
+    this.allowChangeWallet = false,
+  });
 }
 
 class ConnectDevicePage extends BasePage {
   final WalletType walletType;
   final OnConnectDevice onConnectDevice;
+  final bool allowChangeWallet;
   final LedgerViewModel ledgerVM;
 
   ConnectDevicePage(ConnectDevicePageParams params, this.ledgerVM)
       : walletType = params.walletType,
-        onConnectDevice = params.onConnectDevice;
+        onConnectDevice = params.onConnectDevice,
+        allowChangeWallet = params.allowChangeWallet;
 
   @override
   String get title => S.current.restore_title_from_hardware_wallet;
 
   @override
-  Widget body(BuildContext context) =>
-      ConnectDevicePageBody(walletType, onConnectDevice, ledgerVM);
+  Widget body(BuildContext context) => ConnectDevicePageBody(
+      walletType, onConnectDevice, allowChangeWallet, ledgerVM);
 }
 
 class ConnectDevicePageBody extends StatefulWidget {
   final WalletType walletType;
   final OnConnectDevice onConnectDevice;
+  final bool allowChangeWallet;
   final LedgerViewModel ledgerVM;
 
   const ConnectDevicePageBody(
-      this.walletType, this.onConnectDevice, this.ledgerVM);
+    this.walletType,
+    this.onConnectDevice,
+    this.allowChangeWallet,
+    this.ledgerVM,
+  );
 
   @override
   ConnectDevicePageBodyState createState() => ConnectDevicePageBodyState();
@@ -102,14 +116,16 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
 
   Future<void> _refreshBleDevices() async {
     try {
-      _bleRefresh = widget.ledgerVM
-          .scanForBleDevices()
-          .listen((device) => setState(() => bleDevices.add(device)))
-        ..onError((e) {
-          throw e.toString();
-        });
-      _bleRefreshTimer?.cancel();
-      _bleRefreshTimer = null;
+      if (widget.ledgerVM.bleIsEnabled) {
+        _bleRefresh = widget.ledgerVM
+            .scanForBleDevices()
+            .listen((device) => setState(() => bleDevices.add(device)))
+          ..onError((e) {
+            throw e.toString();
+          });
+        _bleRefreshTimer?.cancel();
+        _bleRefreshTimer = null;
+      }
     } catch (e) {
       print(e);
     }
@@ -227,9 +243,7 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
                       style: TextStyle(
                         fontSize: 14,
                         fontWeight: FontWeight.w400,
-                        color: Theme.of(context)
-                            .extension<CakeTextTheme>()!
-                            .titleColor,
+                        color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
                       ),
                     ),
                   ),
@@ -247,11 +261,27 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
                       ),
                     )
                     .toList(),
-              ]
+              ],
+              if (widget.allowChangeWallet) ...[
+                PrimaryButton(
+                  text: S.of(context).wallets,
+                  color: Theme.of(context).extension<WalletListTheme>()!.createNewWalletButtonBackgroundColor,
+                  textColor: Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor,
+                  onPressed: _onChangeWallet,
+                )
+              ],
             ],
           ),
         ),
       ),
     );
   }
+
+  void _onChangeWallet() {
+    Navigator.of(context).pushNamed(
+      Routes.walletList,
+      arguments: (BuildContext context) => Navigator.of(context)
+          .pushNamedAndRemoveUntil(Routes.dashboard, (route) => false),
+    );
+  }
 }
diff --git a/lib/src/screens/connect_device/monero_hardware_wallet_options_page.dart b/lib/src/screens/connect_device/monero_hardware_wallet_options_page.dart
new file mode 100644
index 000000000..f8ace97bc
--- /dev/null
+++ b/lib/src/screens/connect_device/monero_hardware_wallet_options_page.dart
@@ -0,0 +1,230 @@
+import 'package:cake_wallet/core/wallet_name_validator.dart';
+import 'package:cake_wallet/entities/generate_name.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/screens/base_page.dart';
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
+import 'package:cake_wallet/src/widgets/blockchain_height_widget.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/themes/extensions/cake_text_theme.dart';
+import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
+import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
+import 'package:cake_wallet/utils/responsive_layout_util.dart';
+import 'package:cake_wallet/utils/show_pop_up.dart';
+import 'package:cake_wallet/view_model/wallet_hardware_restore_view_model.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:mobx/mobx.dart';
+
+class MoneroHardwareWalletOptionsPage extends BasePage {
+  MoneroHardwareWalletOptionsPage(this._walletHardwareRestoreVM);
+
+  final WalletHardwareRestoreViewModel _walletHardwareRestoreVM;
+
+  @override
+  String get title => S.current.restore_title_from_hardware_wallet;
+
+  @override
+  Widget body(BuildContext context) =>
+      _MoneroHardwareWalletOptionsForm(_walletHardwareRestoreVM);
+}
+
+class _MoneroHardwareWalletOptionsForm extends StatefulWidget {
+  const _MoneroHardwareWalletOptionsForm(this._walletHardwareRestoreVM);
+
+  final WalletHardwareRestoreViewModel _walletHardwareRestoreVM;
+
+  @override
+  _MoneroHardwareWalletOptionsFormState createState() =>
+      _MoneroHardwareWalletOptionsFormState(_walletHardwareRestoreVM);
+}
+
+class _MoneroHardwareWalletOptionsFormState
+    extends State<_MoneroHardwareWalletOptionsForm> {
+  _MoneroHardwareWalletOptionsFormState(this._walletHardwareRestoreVM)
+      : _formKey = GlobalKey<FormState>(),
+        _blockchainHeightKey = GlobalKey<BlockchainHeightState>(),
+        _blockHeightFocusNode = FocusNode(),
+        _controller = TextEditingController();
+
+  final GlobalKey<FormState> _formKey;
+  final GlobalKey<BlockchainHeightState> _blockchainHeightKey;
+  final FocusNode _blockHeightFocusNode;
+  final WalletHardwareRestoreViewModel _walletHardwareRestoreVM;
+  final TextEditingController _controller;
+
+  @override
+  void initState() {
+    super.initState();
+    _setEffects(context);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: EdgeInsets.only(top: 24),
+      child: ScrollableWithBottomSection(
+        contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
+        content: Center(
+          child: ConstrainedBox(
+            constraints: BoxConstraints(
+                maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
+            child: Column(
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                Padding(
+                  padding: EdgeInsets.only(top: 0),
+                  child: Form(
+                    key: _formKey,
+                    child: Stack(
+                      alignment: Alignment.centerRight,
+                      children: [
+                        TextFormField(
+                          onChanged: (value) =>
+                              _walletHardwareRestoreVM.name = value,
+                          controller: _controller,
+                          style: TextStyle(
+                            fontSize: 20.0,
+                            fontWeight: FontWeight.w600,
+                            color: Theme.of(context)
+                                .extension<CakeTextTheme>()!
+                                .titleColor,
+                          ),
+                          decoration: InputDecoration(
+                            hintStyle: TextStyle(
+                              fontSize: 18.0,
+                              fontWeight: FontWeight.w500,
+                              color: Theme.of(context)
+                                  .extension<NewWalletTheme>()!
+                                  .hintTextColor,
+                            ),
+                            hintText: S.of(context).wallet_name,
+                            focusedBorder: UnderlineInputBorder(
+                              borderSide: BorderSide(
+                                color: Theme.of(context)
+                                    .extension<NewWalletTheme>()!
+                                    .underlineColor,
+                                width: 1.0,
+                              ),
+                            ),
+                            enabledBorder: UnderlineInputBorder(
+                              borderSide: BorderSide(
+                                color: Theme.of(context)
+                                    .extension<NewWalletTheme>()!
+                                    .underlineColor,
+                                width: 1.0,
+                              ),
+                            ),
+                            suffixIcon: Semantics(
+                              label: S.of(context).generate_name,
+                              child: IconButton(
+                                onPressed: _onGenerateName,
+                                icon: Container(
+                                  padding: const EdgeInsets.all(8),
+                                  decoration: BoxDecoration(
+                                    borderRadius: BorderRadius.circular(6.0),
+                                    color: Theme.of(context).hintColor,
+                                  ),
+                                  width: 34,
+                                  height: 34,
+                                  child: Image.asset(
+                                    'assets/images/refresh_icon.png',
+                                    color: Theme.of(context)
+                                        .extension<SendPageTheme>()!
+                                        .textFieldButtonIconColor,
+                                  ),
+                                ),
+                              ),
+                            ),
+                          ),
+                          validator: WalletNameValidator(),
+                        ),
+                      ],
+                    ),
+                  ),
+                ),
+                Padding(
+                  padding: EdgeInsets.only(top: 20),
+                  child: BlockchainHeightWidget(
+                    focusNode: _blockHeightFocusNode,
+                    key: _blockchainHeightKey,
+                    hasDatePicker: true,
+                    walletType: WalletType.monero,
+                  ),
+                ),
+              ],
+            ),
+          ),
+        ),
+        bottomSectionPadding: EdgeInsets.all(24),
+        bottomSection: Observer(
+          builder: (context) => LoadingPrimaryButton(
+            onPressed: _confirmForm,
+            text: S.of(context).seed_language_next,
+            color: Colors.green,
+            textColor: Colors.white,
+            isDisabled: _walletHardwareRestoreVM.name.isEmpty,
+          ),
+        ),
+      ),
+    );
+  }
+
+  Future<void> _onGenerateName() async {
+    final rName = await generateName();
+    FocusManager.instance.primaryFocus?.unfocus();
+
+    setState(() {
+      _controller.text = rName;
+      _walletHardwareRestoreVM.name = rName;
+      _controller.selection = TextSelection.fromPosition(
+          TextPosition(offset: _controller.text.length));
+    });
+  }
+
+  Future<void> _confirmForm() async {
+    showPopUp<void>(
+      context: context,
+      builder: (BuildContext context) => AlertWithOneAction(
+        alertTitle: S.of(context).proceed_on_device,
+        alertContent: S.of(context).proceed_on_device_description,
+        buttonText: S.of(context).cancel,
+        buttonAction: () => Navigator.of(context).pop(),
+      ),
+    );
+
+    final options = {'height': _blockchainHeightKey.currentState?.height ?? -1};
+    await _walletHardwareRestoreVM.create(options: options);
+  }
+
+  bool _effectsInstalled = false;
+
+  void _setEffects(BuildContext context) {
+    if (_effectsInstalled) return;
+
+    reaction((_) => _walletHardwareRestoreVM.error, (String? error) {
+      if (error != null) {
+        if (error == S.current.ledger_connection_error)
+          Navigator.of(context).pop();
+
+        WidgetsBinding.instance.addPostFrameCallback((_) {
+          showPopUp<void>(
+            context: context,
+            builder: (BuildContext context) => AlertWithOneAction(
+              alertTitle: S.of(context).error,
+              alertContent: error,
+              buttonText: S.of(context).ok,
+              buttonAction: () {
+                _walletHardwareRestoreVM.error = null;
+                Navigator.of(context).pop();
+              },
+            ),
+          );
+        });
+      }
+    });
+
+    _effectsInstalled = true;
+  }
+}
diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart
index a9a9d9413..46eaa6143 100644
--- a/lib/src/screens/wallet_list/wallet_list_page.dart
+++ b/lib/src/screens/wallet_list/wallet_list_page.dart
@@ -1,44 +1,56 @@
+import 'package:another_flushbar/flushbar.dart';
+import 'package:cake_wallet/core/auth_service.dart';
 import 'package:cake_wallet/core/new_wallet_arguments.dart';
 import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
 import 'package:cake_wallet/entities/wallet_list_order_types.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/monero/monero.dart';
+import 'package:cake_wallet/routes.dart';
+import 'package:cake_wallet/src/screens/auth/auth_page.dart';
+import 'package:cake_wallet/src/screens/base_page.dart';
+import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
 import 'package:cake_wallet/src/screens/dashboard/widgets/filter_list_widget.dart';
 import 'package:cake_wallet/src/screens/new_wallet/widgets/grouped_wallet_expansion_tile.dart';
 import 'package:cake_wallet/src/screens/wallet_list/edit_wallet_button_widget.dart';
 import 'package:cake_wallet/src/screens/wallet_list/filtered_list.dart';
 import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.dart';
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
+import 'package:cake_wallet/src/widgets/primary_button.dart';
 import 'package:cake_wallet/store/settings_store.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
-import 'package:cake_wallet/src/screens/auth/auth_page.dart';
-import 'package:cake_wallet/core/auth_service.dart';
 import 'package:cake_wallet/themes/extensions/filter_theme.dart';
 import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
 import 'package:cake_wallet/utils/responsive_layout_util.dart';
 import 'package:cake_wallet/utils/show_bar.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
-import 'package:another_flushbar/flushbar.dart';
+import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
+import 'package:cake_wallet/wallet_type_utils.dart';
+import 'package:cw_core/wallet_type.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_mobx/flutter_mobx.dart';
-import 'package:cake_wallet/routes.dart';
-import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cw_core/wallet_type.dart';
-import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
-import 'package:cake_wallet/src/widgets/primary_button.dart';
-import 'package:cake_wallet/src/screens/base_page.dart';
-import 'package:cake_wallet/wallet_type_utils.dart';
 
 class WalletListPage extends BasePage {
-  WalletListPage({required this.walletListViewModel, required this.authService});
+  WalletListPage({
+    required this.walletListViewModel,
+    required this.authService,
+    this.onWalletLoaded,
+  });
 
   final WalletListViewModel walletListViewModel;
   final AuthService authService;
+  final Function(BuildContext)? onWalletLoaded;
 
   @override
   String get title => S.current.wallets;
 
   @override
-  Widget body(BuildContext context) =>
-      WalletListBody(walletListViewModel: walletListViewModel, authService: authService);
+  Widget body(BuildContext context) => WalletListBody(
+        walletListViewModel: walletListViewModel,
+        authService: authService,
+        onWalletLoaded:
+            onWalletLoaded ?? (context) => Navigator.of(context).pop(),
+      );
 
   @override
   Widget trailing(BuildContext context) {
@@ -89,10 +101,15 @@ class WalletListPage extends BasePage {
 }
 
 class WalletListBody extends StatefulWidget {
-  WalletListBody({required this.walletListViewModel, required this.authService});
+  WalletListBody({
+    required this.walletListViewModel,
+    required this.authService,
+    required this.onWalletLoaded,
+  });
 
   final WalletListViewModel walletListViewModel;
   final AuthService authService;
+  final Function(BuildContext) onWalletLoaded;
 
   @override
   WalletListBodyState createState() => WalletListBodyState();
@@ -118,8 +135,8 @@ class WalletListBodyState extends State<WalletListBody> {
 
   @override
   Widget build(BuildContext context) {
-    final newWalletImage =
-        Image.asset('assets/images/new_wallet.png', height: 12, width: 12, color: Colors.white);
+    final newWalletImage = Image.asset('assets/images/new_wallet.png',
+        height: 12, width: 12, color: Colors.white);
     final restoreWalletImage = Image.asset('assets/images/restore_wallet.png',
         height: 12,
         width: 12,
@@ -180,8 +197,7 @@ class WalletListBodyState extends State<WalletListBody> {
                               trailingWidget: EditWalletButtonWidget(
                                 width: 74,
                                 isGroup: true,
-                                isExpanded:
-                                    widget.walletListViewModel.expansionTileStateTrack[index]!,
+                                isExpanded: widget.walletListViewModel.expansionTileStateTrack[index]!,
                                 onTap: () {
                                   final wallet = widget.walletListViewModel
                                       .convertWalletInfoToWalletListItem(group.wallets.first);
@@ -198,8 +214,7 @@ class WalletListBodyState extends State<WalletListBody> {
                                 },
                               ),
                               childWallets: group.wallets.map((walletInfo) {
-                                return widget.walletListViewModel
-                                    .convertWalletInfoToWalletListItem(walletInfo);
+                                return widget.walletListViewModel.convertWalletInfoToWalletListItem(walletInfo);
                               }).toList(),
                               isSelected: false,
                               onChildItemTapped: (wallet) =>
@@ -329,8 +344,7 @@ class WalletListBodyState extends State<WalletListBody> {
                           arguments: NewWalletArguments(
                             type: widget.walletListViewModel.currentWalletType,
                           ),
-                          conditionToDetermineIfToUse2FA:
-                              widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
+                          conditionToDetermineIfToUse2FA: widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
                         );
                       } else {
                         Navigator.of(context).pushNamed(
@@ -345,8 +359,7 @@ class WalletListBodyState extends State<WalletListBody> {
                         widget.authService.authenticateAction(
                           context,
                           route: Routes.newWalletType,
-                          conditionToDetermineIfToUse2FA:
-                              widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
+                          conditionToDetermineIfToUse2FA: widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
                         );
                       } else {
                         Navigator.of(context).pushNamed(Routes.newWalletType);
@@ -367,8 +380,7 @@ class WalletListBodyState extends State<WalletListBody> {
                         context,
                         route: Routes.restoreOptions,
                         arguments: false,
-                        conditionToDetermineIfToUse2FA:
-                            widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
+                        conditionToDetermineIfToUse2FA: widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
                       );
                     } else {
                       Navigator.of(context).pushNamed(Routes.restoreOptions, arguments: false);
@@ -387,39 +399,6 @@ class WalletListBodyState extends State<WalletListBody> {
     );
   }
 
-  Image _imageFor({required WalletType type, bool? isTestnet}) {
-    switch (type) {
-      case WalletType.bitcoin:
-        if (isTestnet == true) {
-          return tBitcoinIcon;
-        }
-        return bitcoinIcon;
-      case WalletType.monero:
-        return moneroIcon;
-      case WalletType.litecoin:
-        return litecoinIcon;
-      case WalletType.haven:
-        return havenIcon;
-      case WalletType.ethereum:
-        return ethereumIcon;
-      case WalletType.bitcoinCash:
-        return bitcoinCashIcon;
-      case WalletType.nano:
-      case WalletType.banano:
-        return nanoIcon;
-      case WalletType.polygon:
-        return polygonIcon;
-      case WalletType.solana:
-        return solanaIcon;
-      case WalletType.tron:
-        return tronIcon;
-      case WalletType.wownero:
-        return wowneroIcon;
-      case WalletType.none:
-        return nonWalletTypeIcon;
-    }
-  }
-
   Future<void> _loadWallet(WalletListItem wallet) async {
     if (SettingsStoreBase.walletPasswordDirectInput) {
       Navigator.of(context).pushNamed(Routes.walletUnlockLoadable,
@@ -438,12 +417,36 @@ class WalletListBodyState extends State<WalletListBody> {
     await widget.authService.authenticateAction(
       context,
       onAuthSuccess: (isAuthenticatedSuccessfully) async {
-        if (!isAuthenticatedSuccessfully) {
-          return;
-        }
+        if (!isAuthenticatedSuccessfully) return;
 
         try {
-          changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name));
+          if (widget.walletListViewModel
+              .requireHardwareWalletConnection(wallet)) {
+            await Navigator.of(context).pushNamed(
+              Routes.connectDevices,
+              arguments: ConnectDevicePageParams(
+                walletType: WalletType.monero,
+                onConnectDevice: (context, ledgerVM) async {
+                  monero!.setGlobalLedgerConnection(ledgerVM.connection);
+                  Navigator.of(context).pop();
+                },
+              ),
+            );
+
+            showPopUp<void>(
+              context: context,
+              builder: (BuildContext context) => AlertWithOneAction(
+                  alertTitle: S.of(context).proceed_on_device,
+                  alertContent: S.of(context).proceed_on_device_description,
+                  buttonText: S.of(context).cancel,
+                  buttonAction: () => Navigator.of(context).pop()),
+            );
+          }
+
+
+
+          changeProcessText(
+              S.of(context).wallet_list_loading_wallet(wallet.name));
           await widget.walletListViewModel.loadWallet(wallet);
           await hideProgressText();
           // only pop the wallets route in mobile as it will go back to dashboard page
@@ -451,13 +454,15 @@ class WalletListBodyState extends State<WalletListBody> {
           if (responsiveLayoutUtil.shouldRenderMobileUI) {
             WidgetsBinding.instance.addPostFrameCallback((_) {
               if (this.mounted) {
-                Navigator.of(context).pop();
+                widget.onWalletLoaded.call(context);
               }
             });
           }
         } catch (e) {
           if (this.mounted) {
-            changeProcessText(S.of(context).wallet_list_failed_to_load(wallet.name, e.toString()));
+            changeProcessText(S
+                .of(context)
+                .wallet_list_failed_to_load(wallet.name, e.toString()));
           }
         }
       },
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index a78012ae9..808657f66 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -428,7 +428,7 @@ abstract class DashboardViewModelBase with Store {
       // to not cause work duplication, this will do the job as well, it will be slightly less precise
       // about what happened - but still enough.
       // if (keys['privateSpendKey'] == List.generate(64, (index) => "0").join("")) "Private spend key is 0",
-      if (keys['privateViewKey'] == List.generate(64, (index) => "0").join(""))
+      if (keys['privateViewKey'] == List.generate(64, (index) => "0").join("") && !wallet.isHardwareWallet)
         "private view key is 0",
       // if (keys['publicSpendKey'] == List.generate(64, (index) => "0").join("")) "public spend key is 0",
       if (keys['publicViewKey'] == List.generate(64, (index) => "0").join(""))
diff --git a/lib/view_model/hardware_wallet/ledger_view_model.dart b/lib/view_model/hardware_wallet/ledger_view_model.dart
index 19b190fe3..96f5930c0 100644
--- a/lib/view_model/hardware_wallet/ledger_view_model.dart
+++ b/lib/view_model/hardware_wallet/ledger_view_model.dart
@@ -4,6 +4,7 @@ import 'dart:io';
 import 'package:cake_wallet/bitcoin/bitcoin.dart';
 import 'package:cake_wallet/ethereum/ethereum.dart';
 import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/monero/monero.dart';
 import 'package:cake_wallet/polygon/polygon.dart';
 import 'package:cake_wallet/utils/device_info.dart';
 import 'package:cake_wallet/wallet_type_utils.dart';
@@ -114,6 +115,8 @@ abstract class LedgerViewModelBase with Store {
 
   void setLedger(WalletBase wallet) {
     switch (wallet.type) {
+      case WalletType.monero:
+        return monero!.setLedgerConnection(wallet, connection);
       case WalletType.bitcoin:
       case WalletType.litecoin:
         return bitcoin!.setLedgerConnection(wallet, connection);
diff --git a/lib/view_model/wallet_hardware_restore_view_model.dart b/lib/view_model/wallet_hardware_restore_view_model.dart
index 91e0de685..0971622a5 100644
--- a/lib/view_model/wallet_hardware_restore_view_model.dart
+++ b/lib/view_model/wallet_hardware_restore_view_model.dart
@@ -1,7 +1,9 @@
 import 'package:cake_wallet/bitcoin/bitcoin.dart';
+import 'package:cake_wallet/core/generate_wallet_password.dart';
 import 'package:cake_wallet/core/wallet_creation_service.dart';
 import 'package:cake_wallet/ethereum/ethereum.dart';
 import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/monero/monero.dart';
 import 'package:cake_wallet/polygon/polygon.dart';
 import 'package:cake_wallet/store/app_store.dart';
 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
@@ -56,8 +58,8 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
       List<HardwareAccountData> accounts;
       switch (type) {
         case WalletType.bitcoin:
-        accounts = await bitcoin!
-            .getHardwareWalletBitcoinAccounts(ledgerViewModel, index: _nextIndex, limit: limit);
+          accounts = await bitcoin!
+              .getHardwareWalletBitcoinAccounts(ledgerViewModel, index: _nextIndex, limit: limit);
         break;
       case WalletType.litecoin:
         accounts = await bitcoin!
@@ -104,6 +106,15 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
       case WalletType.polygon:
         credentials = polygon!.createPolygonHardwareWalletCredentials(name: name, hwAccountData: selectedAccount!);
         break;
+      case WalletType.monero:
+        final password = walletPassword ?? generateWalletPassword();
+
+        credentials = monero!.createMoneroRestoreWalletFromHardwareCredentials(
+          name: name,
+          ledgerConnection: ledgerViewModel.connection,
+          password: password,
+          height: _options['height'] as int? ?? 0,
+        );
       default:
         throw Exception('Unexpected type: ${type.toString()}');
     }
diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart
index 725af843f..c903b535f 100644
--- a/lib/view_model/wallet_list/wallet_list_view_model.dart
+++ b/lib/view_model/wallet_list/wallet_list_view_model.dart
@@ -68,6 +68,10 @@ abstract class WalletListViewModelBase with Store {
 
   WalletType get currentWalletType => _appStore.wallet!.type;
 
+  bool requireHardwareWalletConnection(WalletListItem walletItem) =>
+      _walletLoadingService.requireHardwareWalletConnection(
+          walletItem.type, walletItem.name);
+
   @action
   Future<void> loadWallet(WalletListItem walletItem) async {
     // bool switchingToSameWalletType = walletItem.type == _appStore.wallet?.type;
@@ -87,7 +91,8 @@ abstract class WalletListViewModelBase with Store {
     singleWalletsList.clear();
 
     wallets.addAll(
-      _walletInfoSource.values.map((info) => convertWalletInfoToWalletListItem(info)),
+      _walletInfoSource.values
+          .map((info) => convertWalletInfoToWalletListItem(info)),
     );
 
     //========== Split into shared seed groups and single wallets list
@@ -95,7 +100,8 @@ abstract class WalletListViewModelBase with Store {
 
     for (var group in _walletManager.walletGroups) {
       if (group.wallets.length == 1) {
-        singleWalletsList.add(convertWalletInfoToWalletListItem(group.wallets.first));
+        singleWalletsList
+            .add(convertWalletInfoToWalletListItem(group.wallets.first));
       } else {
         multiWalletGroups.add(group);
       }
@@ -148,9 +154,11 @@ abstract class WalletListViewModelBase with Store {
     List<WalletInfo> walletInfoSourceCopy = _walletInfoSource.values.toList();
     await _walletInfoSource.clear();
     if (ascending) {
-      walletInfoSourceCopy.sort((a, b) => a.type.toString().compareTo(b.type.toString()));
+      walletInfoSourceCopy
+          .sort((a, b) => a.type.toString().compareTo(b.type.toString()));
     } else {
-      walletInfoSourceCopy.sort((a, b) => b.type.toString().compareTo(a.type.toString()));
+      walletInfoSourceCopy
+          .sort((a, b) => b.type.toString().compareTo(a.type.toString()));
     }
     await _walletInfoSource.addAll(walletInfoSourceCopy);
     updateList();
@@ -213,7 +221,8 @@ abstract class WalletListViewModelBase with Store {
       name: info.name,
       type: info.type,
       key: info.key,
-      isCurrent: info.name == _appStore.wallet?.name && info.type == _appStore.wallet?.type,
+      isCurrent: info.name == _appStore.wallet?.name &&
+          info.type == _appStore.wallet?.type,
       isEnabled: availableWalletTypes.contains(info.type),
       isTestnet: info.network?.toLowerCase().contains('testnet') ?? false,
     );
diff --git a/scripts/prepare_moneroc.sh b/scripts/prepare_moneroc.sh
index 24f4d201c..0d90e431a 100755
--- a/scripts/prepare_moneroc.sh
+++ b/scripts/prepare_moneroc.sh
@@ -6,9 +6,9 @@ cd "$(dirname "$0")"
 
 if [[ ! -d "monero_c" ]];
 then
-    git clone https://github.com/mrcyjanek/monero_c --branch rewrite-wip
+    git clone https://github.com/mrcyjanek/monero_c --branch master
     cd monero_c
-    git checkout 6eb571ea498ed7b854934785f00fabfd0dadf75b
+    git checkout 1d8e0fb30b53c28756f23676d5a3e1a99a9b3051
     git reset --hard
     git submodule update --init --force --recursive
     ./apply_patches.sh monero
diff --git a/tool/configure.dart b/tool/configure.dart
index c5d4a6863..fb8291385 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -270,20 +270,22 @@ import 'package:cw_core/output_info.dart';
 import 'package:cake_wallet/view_model/send/output.dart';
 import 'package:cw_core/wallet_service.dart';
 import 'package:hive/hive.dart';
+import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
 import 'package:polyseed/polyseed.dart';""";
   const moneroCWHeaders = """
+import 'package:cw_core/account.dart' as monero_account;
 import 'package:cw_core/get_height_by_date.dart';
 import 'package:cw_core/monero_amount_format.dart';
 import 'package:cw_core/monero_transaction_priority.dart';
+import 'package:cw_monero/api/wallet_manager.dart';
+import 'package:cw_monero/api/wallet.dart' as monero_wallet_api;
+import 'package:cw_monero/ledger.dart';
 import 'package:cw_monero/monero_unspent.dart';
 import 'package:cw_monero/api/account_list.dart';
 import 'package:cw_monero/monero_wallet_service.dart';
-import 'package:cw_monero/api/wallet_manager.dart';
 import 'package:cw_monero/monero_wallet.dart';
 import 'package:cw_monero/monero_transaction_info.dart';
 import 'package:cw_monero/monero_transaction_creation_credentials.dart';
-import 'package:cw_core/account.dart' as monero_account;
-import 'package:cw_monero/api/wallet.dart' as monero_wallet_api;
 import 'package:cw_monero/mnemonics/english.dart';
 import 'package:cw_monero/mnemonics/chinese_simplified.dart';
 import 'package:cw_monero/mnemonics/dutch.dart';
@@ -395,6 +397,7 @@ abstract class Monero {
     required String language,
     required int height});
   WalletCredentials createMoneroRestoreWalletFromSeedCredentials({required String name, required String password, required int height, required String mnemonic});
+  WalletCredentials createMoneroRestoreWalletFromHardwareCredentials({required String name, required String password, required int height, required ledger.LedgerConnection ledgerConnection});
   WalletCredentials createMoneroNewWalletCredentials({required String name, required String language, required bool isPolyseed, String? password});
   Map<String, String> getKeys(Object wallet);
   int? getRestoreHeight(Object wallet);
@@ -411,6 +414,8 @@ abstract class Monero {
   int getTransactionInfoAccountId(TransactionInfo tx);
   WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource);
   Map<String, String> pendingTransactionInfo(Object transaction);
+  void setLedgerConnection(Object wallet, ledger.LedgerConnection connection);
+  void setGlobalLedgerConnection(ledger.LedgerConnection connection);
 }
 
 abstract class MoneroSubaddressList {

From 96db38c0aa3b2628118302e137e7b1969b5367d0 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Tue, 12 Nov 2024 05:29:32 +0200
Subject: [PATCH 44/50] Cw 744 improve address book (#1771)

* add sort function to contact list

* fix UI

* prevent duplicate contact names

* dispose contact source subscription

* fix custom order issue

* update the address book UI

* fix saving custom order

* fix merge conflict issue

* fix the address book filter by the selected currency

* add dropdown for wallets with multiple address types

* minor fixes

* add dropdown for wallets with multiple address types

* Update lib/entities/contact.dart [skip ci]

* Update lib/src/screens/contact/contact_list_page.dart [skip ci]

* Update lib/src/screens/contact/contact_list_page.dart [skip ci]

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
---
 .../screens/contact/contact_list_page.dart    | 62 ++++++++++++++++---
 .../contact_list/contact_list_view_model.dart | 35 +++++++----
 2 files changed, 75 insertions(+), 22 deletions(-)

diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart
index 130380b09..f71747953 100644
--- a/lib/src/screens/contact/contact_list_page.dart
+++ b/lib/src/screens/contact/contact_list_page.dart
@@ -11,6 +11,7 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
 import 'package:cake_wallet/src/widgets/standard_list.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
 import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
+import 'package:cake_wallet/themes/extensions/filter_theme.dart';
 import 'package:cake_wallet/utils/show_bar.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
@@ -160,25 +161,60 @@ class _ContactPageBodyState extends State<ContactPageBody> with SingleTickerProv
   Widget _buildWalletContacts(BuildContext context) {
     final walletContacts = widget.contactListViewModel.walletContactsToShow;
 
+    final groupedContacts = <String, List<ContactBase>>{};
+    for (var contact in walletContacts) {
+      final baseName = _extractBaseName(contact.name);
+      groupedContacts.putIfAbsent(baseName, () => []).add(contact);
+    }
+
     return ListView.builder(
-      shrinkWrap: true,
-      itemCount: walletContacts.length * 2,
+      itemCount: groupedContacts.length * 2,
       itemBuilder: (context, index) {
         if (index.isOdd) {
           return StandardListSeparator();
         } else {
-          final walletInfo = walletContacts[index ~/ 2];
-          return generateRaw(context, walletInfo);
+          final groupIndex = index ~/ 2;
+          final groupName = groupedContacts.keys.elementAt(groupIndex);
+          final groupContacts = groupedContacts[groupName]!;
+
+          if (groupContacts.length == 1) {
+            final contact = groupContacts[0];
+            return generateRaw(context, contact);
+          } else {
+            final activeContact = groupContacts.firstWhere(
+              (contact) => contact.name.contains('Active'),
+              orElse: () => groupContacts[0],
+            );
+
+            return ExpansionTile(
+              title: Text(
+                groupName,
+                style: TextStyle(
+                  fontSize: 14,
+                  fontWeight: FontWeight.normal,
+                  color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
+                ),
+              ),
+              leading: _buildCurrencyIcon(activeContact),
+              tilePadding: EdgeInsets.zero,
+              childrenPadding: const EdgeInsets.only(left: 16),
+              expandedCrossAxisAlignment: CrossAxisAlignment.start,
+              expandedAlignment: Alignment.topLeft,
+              children: groupContacts.map((contact) => generateRaw(context, contact)).toList(),
+            );
+          }
         }
       },
     );
   }
 
+  String _extractBaseName(String name) {
+    final bracketIndex = name.indexOf('(');
+    return (bracketIndex != -1) ? name.substring(0, bracketIndex).trim() : name;
+  }
+
   Widget generateRaw(BuildContext context, ContactBase contact) {
-    final image = contact.type.iconPath;
-    final currencyIcon = image != null
-        ? Image.asset(image, height: 24, width: 24)
-        : const SizedBox(height: 24, width: 24);
+    final currencyIcon = _buildCurrencyIcon(contact);
 
     return GestureDetector(
       onTap: () async {
@@ -219,6 +255,13 @@ class _ContactPageBodyState extends State<ContactPageBody> with SingleTickerProv
     );
   }
 
+  Widget _buildCurrencyIcon(ContactBase contact) {
+    final image = contact.type.iconPath;
+    return image != null
+        ? Image.asset(image, height: 24, width: 24)
+        : const SizedBox(height: 24, width: 24);
+  }
+
   Future<bool> showNameAndAddressDialog(BuildContext context, String name, String address) async {
     return await showPopUp<bool>(
             context: context,
@@ -263,12 +306,13 @@ class _ContactListBodyState extends State<ContactListBody> {
   @override
   void dispose() {
     widget.tabController.removeListener(_handleTabChange);
+    widget.contactListViewModel.dispose();
     super.dispose();
   }
 
   @override
   Widget build(BuildContext context) {
-    final contacts = widget.contactListViewModel.contacts;
+    final contacts = widget.contactListViewModel.contactsToShow;
     return Scaffold(
       body: Container(
         child: FilteredList(
diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart
index 0015463a5..25f222891 100644
--- a/lib/view_model/contact_list/contact_list_view_model.dart
+++ b/lib/view_model/contact_list/contact_list_view_model.dart
@@ -28,7 +28,8 @@ abstract class ContactListViewModelBase with Store {
         isAutoGenerateEnabled =
             settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.enabled {
     walletInfoSource.values.forEach((info) {
-      if ([WalletType.monero, WalletType.wownero, WalletType.haven].contains(info.type) && info.addressInfos != null) {
+      if ([WalletType.monero, WalletType.wownero, WalletType.haven].contains(info.type) &&
+          info.addressInfos != null) {
         for (var key in info.addressInfos!.keys) {
           final value = info.addressInfos![key];
           final address = value?.first;
@@ -60,15 +61,19 @@ abstract class ContactListViewModelBase with Store {
               address,
               name,
               walletTypeToCryptoCurrency(info.type,
-                  isTestnet:
-                      info.network == null ? false : info.network!.toLowerCase().contains("testnet")),
+                  isTestnet: info.network == null
+                      ? false
+                      : info.network!.toLowerCase().contains("testnet")),
             ));
           });
         }
       } else {
         walletContacts.add(WalletContact(
           info.address,
-          _createName(info.name, "", key: [WalletType.monero, WalletType.wownero, WalletType.haven].contains(info.type) ? 0 : null),
+          _createName(info.name, "",
+              key: [WalletType.monero, WalletType.wownero, WalletType.haven].contains(info.type)
+                  ? 0
+                  : null),
           walletTypeToCryptoCurrency(info.type),
         ));
       }
@@ -82,8 +87,11 @@ abstract class ContactListViewModelBase with Store {
   }
 
   String _createName(String walletName, String label, {int? key = null}) {
-    final actualLabel = label.replaceAll(RegExp(r'active', caseSensitive: false), S.current.active).replaceAll(RegExp(r'silent payments', caseSensitive: false), S.current.silent_payments);
-    return '$walletName${key == null ? "" : " [#${key}]"} ${actualLabel.isNotEmpty ? "($actualLabel)" : ""}'.trim();
+    final actualLabel = label
+        .replaceAll(RegExp(r'active', caseSensitive: false), S.current.active)
+        .replaceAll(RegExp(r'silent payments', caseSensitive: false), S.current.silent_payments);
+    return '$walletName${key == null ? "" : " [#${key}]"} ${actualLabel.isNotEmpty ? "($actualLabel)" : ""}'
+        .trim();
   }
 
   final bool isAutoGenerateEnabled;
@@ -108,18 +116,19 @@ abstract class ContactListViewModelBase with Store {
   Future<void> delete(ContactRecord contact) async => contact.original.delete();
 
   ObservableList<ContactRecord> get contactsToShow =>
-      ObservableList.of(contacts.where((element) => _isValidForCurrency(element)));
+      ObservableList.of(contacts.where((element) => _isValidForCurrency(element, false)));
 
   @computed
   List<WalletContact> get walletContactsToShow =>
-      walletContacts.where((element) => _isValidForCurrency(element)).toList();
+      walletContacts.where((element) => _isValidForCurrency(element, true)).toList();
 
-  bool _isValidForCurrency(ContactBase element) {
-    if (element.name.contains('Silent Payments')) return false;
-    if (element.name.contains('MWEB')) return false;
+  bool _isValidForCurrency(ContactBase element, bool isWalletContact) {
+    if (_currency == null) return true;
+    if (!element.name.contains('Active') &&
+        isWalletContact &&
+        (element.type == CryptoCurrency.btc || element.type == CryptoCurrency.ltc)) return false;
 
-    return _currency == null ||
-        element.type == _currency ||
+    return element.type == _currency ||
         (element.type.tag != null &&
             _currency?.tag != null &&
             element.type.tag == _currency?.tag) ||

From c4698576a3fc8c2d1da51ebdb82267e456b9d014 Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Wed, 13 Nov 2024 01:19:50 +0200
Subject: [PATCH 45/50] add xmr to unstoppable domain (#1800)

---
 lib/entities/parse_address_from_domain.dart | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart
index 481db5620..11ba4724c 100644
--- a/lib/entities/parse_address_from_domain.dart
+++ b/lib/entities/parse_address_from_domain.dart
@@ -41,7 +41,8 @@ class AddressResolver {
     'kresus',
     'anime',
     'manga',
-    'binanceus'
+    'binanceus',
+    'xmr',
   ];
 
   static String? extractAddressByType({required String raw, required CryptoCurrency type}) {

From 0adb69d095a80526c02101877b2141ac20e133ab Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Wed, 13 Nov 2024 10:44:43 +0100
Subject: [PATCH 46/50] Better Ledger Connection handling (#1802)

---
 cw_monero/lib/ledger.dart                             | 6 +-----
 cw_monero/lib/monero_wallet_service.dart              | 5 +++++
 lib/monero/cw_monero.dart                             | 4 ++++
 lib/view_model/hardware_wallet/ledger_view_model.dart | 4 +++-
 tool/configure.dart                                   | 1 +
 5 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/cw_monero/lib/ledger.dart b/cw_monero/lib/ledger.dart
index 074975df3..c947d0944 100644
--- a/cw_monero/lib/ledger.dart
+++ b/cw_monero/lib/ledger.dart
@@ -47,10 +47,6 @@ void enableLedgerExchange(monero.wallet ptr, LedgerConnection connection) {
 
 void keepAlive(LedgerConnection connection) {
   if (connection.connectionType == ConnectionType.ble) {
-    UniversalBle.onConnectionChange = (String deviceId, bool isConnected) {
-      print("[Monero] Ledger Disconnected");
-      _ledgerKeepAlive?.cancel();
-    };
     _ledgerKeepAlive = Timer.periodic(Duration(seconds: 10), (_) async {
       try {
         UniversalBle.setNotifiable(
@@ -59,7 +55,7 @@ void keepAlive(LedgerConnection connection) {
           connection.device.deviceInfo.notifyCharacteristicKey,
           BleInputProperty.notification,
         );
-      } catch (_){}
+      } catch (_) {}
     });
   }
 }
diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart
index b2089dfc7..6f49640be 100644
--- a/cw_monero/lib/monero_wallet_service.dart
+++ b/cw_monero/lib/monero_wallet_service.dart
@@ -146,6 +146,11 @@ class MoneroWalletService extends WalletService<
           password: password);
       final isValid = wallet.walletAddresses.validate();
 
+      if (wallet.isHardwareWallet) {
+        wallet.setLedgerConnection(gLedger!);
+        gLedger = null;
+      }
+
       if (!isValid) {
         await restoreOrResetWalletFiles(name);
         wallet.close(shouldCleanup: false);
diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart
index 09d9889c5..89b1579fc 100644
--- a/lib/monero/cw_monero.dart
+++ b/lib/monero/cw_monero.dart
@@ -402,6 +402,10 @@ class CWMonero extends Monero {
     moneroWallet.setLedgerConnection(connection);
   }
 
+  void resetLedgerConnection() {
+    disableLedgerExchange();
+  }
+
   @override
   void setGlobalLedgerConnection(ledger.LedgerConnection connection) {
     gLedger = connection;
diff --git a/lib/view_model/hardware_wallet/ledger_view_model.dart b/lib/view_model/hardware_wallet/ledger_view_model.dart
index 96f5930c0..3cd131efa 100644
--- a/lib/view_model/hardware_wallet/ledger_view_model.dart
+++ b/lib/view_model/hardware_wallet/ledger_view_model.dart
@@ -98,7 +98,9 @@ abstract class LedgerViewModelBase with Store {
         print('Ledger Device State Changed: $event');
         if (event == sdk.BleConnectionState.disconnected) {
           _connection = null;
-          _connectionChangeListener?.cancel();
+          if (type == WalletType.monero) {
+            monero!.resetLedgerConnection();
+          }
         }
       });
     }
diff --git a/tool/configure.dart b/tool/configure.dart
index fb8291385..f0f79cfb1 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -415,6 +415,7 @@ abstract class Monero {
   WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource);
   Map<String, String> pendingTransactionInfo(Object transaction);
   void setLedgerConnection(Object wallet, ledger.LedgerConnection connection);
+  void resetLedgerConnection();
   void setGlobalLedgerConnection(ledger.LedgerConnection connection);
 }
 

From ed5e701d801cd88d4905a06a6f9e2b3aa6dca510 Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Wed, 13 Nov 2024 11:55:46 +0200
Subject: [PATCH 47/50] Potential fix for the race condition of loading a
 wallet while the name in the shared prefs hasn't updated yet (#1801)

---
 lib/reactions/on_current_wallet_change.dart | 7 -------
 lib/store/app_store.dart                    | 7 +++++++
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart
index 6630f1dfc..d7e6f90c0 100644
--- a/lib/reactions/on_current_wallet_change.dart
+++ b/lib/reactions/on_current_wallet_change.dart
@@ -10,9 +10,6 @@ import 'package:cw_core/transaction_history.dart';
 import 'package:cw_core/balance.dart';
 import 'package:cw_core/transaction_info.dart';
 import 'package:mobx/mobx.dart';
-import 'package:shared_preferences/shared_preferences.dart';
-import 'package:cake_wallet/di.dart';
-import 'package:cake_wallet/entities/preferences_key.dart';
 import 'package:cake_wallet/reactions/check_connection.dart';
 import 'package:cake_wallet/reactions/on_wallet_sync_status_change.dart';
 import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
@@ -65,10 +62,6 @@ void startCurrentWalletChangeReaction(
 
       startWalletSyncStatusChangeReaction(wallet, fiatConversionStore);
       startCheckConnectionReaction(wallet, settingsStore);
-      await getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name);
-      await getIt
-          .get<SharedPreferences>()
-          .setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type));
 
       if (wallet.type == WalletType.monero ||
           wallet.type == WalletType.wownero ||
diff --git a/lib/store/app_store.dart b/lib/store/app_store.dart
index cd8881633..24d5dc6a4 100644
--- a/lib/store/app_store.dart
+++ b/lib/store/app_store.dart
@@ -1,8 +1,10 @@
 import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
 import 'package:cake_wallet/di.dart';
+import 'package:cake_wallet/entities/preferences_key.dart';
 import 'package:cake_wallet/reactions/wallet_connect.dart';
 import 'package:cake_wallet/utils/exception_handler.dart';
 import 'package:cw_core/transaction_info.dart';
+import 'package:cw_core/wallet_type.dart';
 import 'package:mobx/mobx.dart';
 import 'package:cw_core/balance.dart';
 import 'package:cw_core/wallet_base.dart';
@@ -11,6 +13,7 @@ import 'package:cake_wallet/store/wallet_list_store.dart';
 import 'package:cake_wallet/store/authentication_store.dart';
 import 'package:cake_wallet/store/settings_store.dart';
 import 'package:cake_wallet/store/node_list_store.dart';
+import 'package:shared_preferences/shared_preferences.dart';
 
 part 'app_store.g.dart';
 
@@ -47,5 +50,9 @@ abstract class AppStoreBase with Store {
       getIt.get<Web3WalletService>().create();
       await getIt.get<Web3WalletService>().init();
     }
+    await getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name);
+    await getIt
+        .get<SharedPreferences>()
+        .setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type));
   }
 }

From cf7f019a925bec52086a63f6785e4c4dfa329298 Mon Sep 17 00:00:00 2001
From: Serhii <borodenko.sv@gmail.com>
Date: Thu, 14 Nov 2024 03:20:08 +0200
Subject: [PATCH 48/50] fix the UI issue with address book (#1803)

---
 .../screens/contact/contact_list_page.dart    | 19 +++++++++++++------
 .../contact_list/contact_list_view_model.dart |  7 ++++---
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart
index f71747953..878a8bb54 100644
--- a/lib/src/screens/contact/contact_list_page.dart
+++ b/lib/src/screens/contact/contact_list_page.dart
@@ -1,4 +1,5 @@
 import 'package:cake_wallet/core/auth_service.dart';
+import 'package:cake_wallet/entities/contact.dart';
 import 'package:cake_wallet/entities/contact_base.dart';
 import 'package:cake_wallet/entities/contact_record.dart';
 import 'package:cake_wallet/entities/wallet_list_order_types.dart';
@@ -11,14 +12,12 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
 import 'package:cake_wallet/src/widgets/standard_list.dart';
 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
 import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
-import 'package:cake_wallet/themes/extensions/filter_theme.dart';
 import 'package:cake_wallet/utils/show_bar.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
-import 'package:flutter/widgets.dart';
 import 'package:flutter_slidable/flutter_slidable.dart';
 
 class ContactListPage extends BasePage {
@@ -92,16 +91,19 @@ class ContactPageBody extends StatefulWidget {
 
 class _ContactPageBodyState extends State<ContactPageBody> with SingleTickerProviderStateMixin {
   late TabController _tabController;
+  late ContactListViewModel contactListViewModel;
 
   @override
   void initState() {
     super.initState();
     _tabController = TabController(length: 2, vsync: this);
+    contactListViewModel = widget.contactListViewModel;
   }
 
   @override
   void dispose() {
     _tabController.dispose();
+    contactListViewModel.dispose();
     super.dispose();
   }
 
@@ -306,13 +308,17 @@ class _ContactListBodyState extends State<ContactListBody> {
   @override
   void dispose() {
     widget.tabController.removeListener(_handleTabChange);
-    widget.contactListViewModel.dispose();
+    if (widget.contactListViewModel.settingsStore.contactListOrder == FilterListOrderType.Custom) {
+      widget.contactListViewModel.saveCustomOrder();
+    }
     super.dispose();
   }
 
   @override
   Widget build(BuildContext context) {
-    final contacts = widget.contactListViewModel.contactsToShow;
+    final contacts = widget.contactListViewModel.isEditable
+        ? widget.contactListViewModel.contacts
+        : widget.contactListViewModel.contactsToShow;
     return Scaffold(
       body: Container(
         child: FilteredList(
@@ -351,8 +357,9 @@ class _ContactListBodyState extends State<ContactListBody> {
           },
         ),
       ),
-      floatingActionButton:
-          _isContactsTabActive ? filterButtonWidget(context, widget.contactListViewModel) : null,
+      floatingActionButton: _isContactsTabActive && widget.contactListViewModel.isEditable
+          ? filterButtonWidget(context, widget.contactListViewModel)
+          : null,
     );
   }
 
diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart
index 25f222891..eb3fb837e 100644
--- a/lib/view_model/contact_list/contact_list_view_model.dart
+++ b/lib/view_model/contact_list/contact_list_view_model.dart
@@ -136,10 +136,11 @@ abstract class ContactListViewModelBase with Store {
         _currency?.tag == element.type.toString();
   }
 
-  void dispose() async {
-    _subscription?.cancel();
+  void dispose() => _subscription?.cancel();
+
+  void saveCustomOrder() {
     final List<Contact> contactsSourceCopy = contacts.map((e) => e.original).toList();
-    await reorderContacts(contactsSourceCopy);
+    reorderContacts(contactsSourceCopy);
   }
 
   void reorderAccordingToContactList() =>

From 9be990a3c094b76a22e55e89c4144ecbfeee9ca6 Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Sat, 16 Nov 2024 11:06:49 -0600
Subject: [PATCH 49/50] Move the api key of trocador to the headers (#1808)

---
 .../provider/trocador_exchange_provider.dart       | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart
index 652543607..5529d824a 100644
--- a/lib/exchange/provider/trocador_exchange_provider.dart
+++ b/lib/exchange/provider/trocador_exchange_provider.dart
@@ -89,13 +89,12 @@ class TrocadorExchangeProvider extends ExchangeProvider {
       required CryptoCurrency to,
       required bool isFixedRateMode}) async {
     final params = {
-      'api_key': apiKey,
       'ticker': _normalizeCurrency(from),
       'name': from.name,
     };
 
     final uri = await _getUri(coinPath, params);
-    final response = await get(uri);
+    final response = await get(uri, headers: {'API-Key': apiKey});
 
     if (response.statusCode != 200)
       throw Exception('Unexpected http status: ${response.statusCode}');
@@ -123,7 +122,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
       if (amount == 0) return 0.0;
 
       final params = <String, String>{
-        'api_key': apiKey,
         'ticker_from': _normalizeCurrency(from),
         'ticker_to': _normalizeCurrency(to),
         'network_from': _networkFor(from),
@@ -136,7 +134,8 @@ class TrocadorExchangeProvider extends ExchangeProvider {
       };
 
       final uri = await _getUri(newRatePath, params);
-      final response = await get(uri);
+      final response = await get(uri, headers: {'API-Key': apiKey});
+
       final responseJSON = json.decode(response.body) as Map<String, dynamic>;
       final fromAmount = double.parse(responseJSON['amount_from'].toString());
       final toAmount = double.parse(responseJSON['amount_to'].toString());
@@ -161,7 +160,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
     required bool isSendAll,
   }) async {
     final params = {
-      'api_key': apiKey,
       'ticker_from': _normalizeCurrency(request.fromCurrency),
       'ticker_to': _normalizeCurrency(request.toCurrency),
       'network_from': _networkFor(request.fromCurrency),
@@ -202,7 +200,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
     params['provider'] = firstAvailableProvider;
 
     final uri = await _getUri(createTradePath, params);
-    final response = await get(uri);
+    final response = await get(uri, headers: {'API-Key': apiKey});
 
     if (response.statusCode == 400) {
       final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@@ -248,8 +246,8 @@ class TrocadorExchangeProvider extends ExchangeProvider {
 
   @override
   Future<Trade> findTradeById({required String id}) async {
-    final uri = await _getUri(tradePath, {'api_key': apiKey, 'id': id});
-    return get(uri).then((response) {
+    final uri = await _getUri(tradePath, {'id': id});
+    return get(uri, headers: {'API-Key': apiKey}).then((response) {
       if (response.statusCode != 200)
         throw Exception('Unexpected http status: ${response.statusCode}');
 

From ff5fbd794649619085568e6ff572227a83fff23e Mon Sep 17 00:00:00 2001
From: Omar Hatem <omarh.ismail1@gmail.com>
Date: Sat, 16 Nov 2024 16:23:54 -0600
Subject: [PATCH 50/50] v4.21.0 Release Candidate (#1795)

* new versions

* minor fix of cache key

* fix cache hit

* - potential improvement for sync status
- update with latest main

* disable thorchain by default [skip ci]

* update monero_c commit hash

* minor fixes
update versions

* remove monero ledger

* increase macos build number [skip ci]
---
 assets/text/Monerocom_Release_Notes.txt       |  4 +-
 assets/text/Release_Notes.txt                 | 10 +--
 cw_bitcoin/lib/electrum_wallet.dart           |  9 +-
 cw_bitcoin/pubspec.lock                       |  4 +-
 .../lib/hardware/device_connection_type.dart  |  2 +-
 cw_monero/pubspec.lock                        |  4 +-
 cw_monero/pubspec.yaml                        |  2 +-
 cw_wownero/pubspec.lock                       | 88 +------------------
 cw_wownero/pubspec.yaml                       |  2 +-
 ios/Podfile.lock                              | 38 +++-----
 ios/Runner.xcodeproj/project.pbxproj          | 18 ++++
 lib/buy/meld/meld_buy_provider.dart           |  4 -
 lib/entities/default_settings_migration.dart  |  8 +-
 .../screens/contact/contact_list_page.dart    | 18 ++--
 .../screens/restore/restore_options_page.dart |  5 +-
 linux/flutter/generated_plugins.cmake         |  1 +
 macos/Flutter/GeneratedPluginRegistrant.swift |  2 +
 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/prepare_moneroc.sh                    |  2 +-
 scripts/windows/build_exe_installer.iss       |  2 +-
 windows/flutter/generated_plugins.cmake       |  1 +
 24 files changed, 92 insertions(+), 160 deletions(-)

diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt
index 613ea4281..46f21e172 100644
--- a/assets/text/Monerocom_Release_Notes.txt
+++ b/assets/text/Monerocom_Release_Notes.txt
@@ -1,3 +1,3 @@
-Monero enhancements
-Introducing StealthEx and LetxExchange
+Add airgapped Monero wallet support (best used with our new offline app Cupcake)
+New Buy & Sell flow
 Bug fixes
\ No newline at end of file
diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt
index 61aafb6e4..6764826a7 100644
--- a/assets/text/Release_Notes.txt
+++ b/assets/text/Release_Notes.txt
@@ -1,7 +1,5 @@
-Added Litecoin MWEB
-Added wallet groups
-Silent Payment enhancements for speed & reliability
-Monero enhancements
-Introducing StealthEx and LetxExchange
-Additional ERC20 tokens scam detection
+Add Litecoin Ledger support
+Add airgapped Monero wallet support (best used with our new offline app Cupcake)
+MWEB fixes and enhancements
+New Buy & Sell flow
 Bug fixes
\ No newline at end of file
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 6245aa787..e58fad00f 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -574,6 +574,8 @@ abstract class ElectrumWalletBase
   Future<void> connectToNode({required Node node}) async {
     this.node = node;
 
+    if (syncStatus is ConnectingSyncStatus) return;
+
     try {
       syncStatus = ConnectingSyncStatus();
 
@@ -2216,13 +2218,14 @@ abstract class ElectrumWalletBase
         if (syncStatus is NotConnectedSyncStatus ||
             syncStatus is LostConnectionSyncStatus ||
             syncStatus is ConnectingSyncStatus) {
-          syncStatus = AttemptingSyncStatus();
-          startSync();
+          syncStatus = ConnectedSyncStatus();
         }
 
         break;
       case ConnectionStatus.disconnected:
-        if (syncStatus is! NotConnectedSyncStatus) {
+        if (syncStatus is! NotConnectedSyncStatus &&
+            syncStatus is! ConnectingSyncStatus &&
+            syncStatus is! SyncronizingSyncStatus) {
           syncStatus = NotConnectedSyncStatus();
         }
         break;
diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock
index 8eafb2a44..c8a83f90c 100644
--- a/cw_bitcoin/pubspec.lock
+++ b/cw_bitcoin/pubspec.lock
@@ -87,8 +87,8 @@ packages:
     dependency: "direct overridden"
     description:
       path: "."
-      ref: cake-update-v8
-      resolved-ref: fc045a11db3d85d806ca67f75e8b916c706745a2
+      ref: cake-update-v9
+      resolved-ref: "86969a14e337383e14965f5fb45a72a63e5009bc"
       url: "https://github.com/cake-tech/bitcoin_base"
     source: git
     version: "4.7.0"
diff --git a/cw_core/lib/hardware/device_connection_type.dart b/cw_core/lib/hardware/device_connection_type.dart
index 76a501af1..466d58e2a 100644
--- a/cw_core/lib/hardware/device_connection_type.dart
+++ b/cw_core/lib/hardware/device_connection_type.dart
@@ -7,7 +7,7 @@ enum DeviceConnectionType {
   static List<DeviceConnectionType> supportedConnectionTypes(WalletType walletType,
       [bool isIOS = false]) {
     switch (walletType) {
-      case WalletType.monero:
+      // case WalletType.monero:
       case WalletType.bitcoin:
       case WalletType.litecoin:
       case WalletType.ethereum:
diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock
index a6a03dce5..31d44ac63 100644
--- a/cw_monero/pubspec.lock
+++ b/cw_monero/pubspec.lock
@@ -503,8 +503,8 @@ packages:
     dependency: "direct main"
     description:
       path: "impls/monero.dart"
-      ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
-      resolved-ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
+      ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
+      resolved-ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
       url: "https://github.com/mrcyjanek/monero_c"
     source: git
     version: "0.0.0"
diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml
index 6fa235ee4..71cbfa243 100644
--- a/cw_monero/pubspec.yaml
+++ b/cw_monero/pubspec.yaml
@@ -25,7 +25,7 @@ dependencies:
   monero:
     git:
       url: https://github.com/mrcyjanek/monero_c
-      ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
+      ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
 #      ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash
       path: impls/monero.dart
   mutex: ^3.1.0
diff --git a/cw_wownero/pubspec.lock b/cw_wownero/pubspec.lock
index b0347c023..a861c6bac 100644
--- a/cw_wownero/pubspec.lock
+++ b/cw_wownero/pubspec.lock
@@ -41,14 +41,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.11.0"
-  bluez:
-    dependency: transitive
-    description:
-      name: bluez
-      sha256: "203a1924e818a9dd74af2b2c7a8f375ab8e5edf0e486bba8f90a0d8a17ed9fce"
-      url: "https://pub.dev"
-    source: hosted
-    version: "0.8.2"
   boolean_selector:
     dependency: transitive
     description:
@@ -217,14 +209,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.2.4"
-  dbus:
-    dependency: transitive
-    description:
-      name: dbus
-      sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
-      url: "https://pub.dev"
-    source: hosted
-    version: "0.7.10"
   encrypt:
     dependency: "direct main"
     description:
@@ -283,14 +267,6 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
-  flutter_web_bluetooth:
-    dependency: transitive
-    description:
-      name: flutter_web_bluetooth
-      sha256: "52ce64f65d7321c4bf6abfe9dac02fb888731339a5e0ad6de59fb916c20c9f02"
-      url: "https://pub.dev"
-    source: hosted
-    version: "0.2.3"
   frontend_server_client:
     dependency: transitive
     description:
@@ -427,22 +403,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.0.1"
-  ledger_flutter_plus:
-    dependency: transitive
-    description:
-      name: ledger_flutter_plus
-      sha256: ea3ed586e1697776dacf42ac979095f1ca3bd143bf007cbe5c78e09cb6943f42
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.2.5"
-  ledger_usb_plus:
-    dependency: transitive
-    description:
-      name: ledger_usb_plus
-      sha256: "21cc5d976cf7edb3518bd2a0c4164139cbb0817d2e4f2054707fc4edfdf9ce87"
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.0.4"
   logging:
     dependency: transitive
     description:
@@ -503,8 +463,8 @@ packages:
     dependency: "direct main"
     description:
       path: "impls/monero.dart"
-      ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
-      resolved-ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
+      ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
+      resolved-ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
       url: "https://github.com/mrcyjanek/monero_c"
     source: git
     version: "0.0.0"
@@ -580,14 +540,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.2.1"
-  petitparser:
-    dependency: transitive
-    description:
-      name: petitparser
-      sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
-      url: "https://pub.dev"
-    source: hosted
-    version: "6.0.2"
   platform:
     dependency: transitive
     description:
@@ -644,14 +596,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.2.1"
-  rxdart:
-    dependency: transitive
-    description:
-      name: rxdart
-      sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
-      url: "https://pub.dev"
-    source: hosted
-    version: "0.28.0"
   shelf:
     dependency: transitive
     description:
@@ -777,22 +721,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.1"
-  universal_ble:
-    dependency: transitive
-    description:
-      name: universal_ble
-      sha256: "0dfbd6b64bff3ad61ed7a895c232530d9614e9b01ab261a74433a43267edb7f3"
-      url: "https://pub.dev"
-    source: hosted
-    version: "0.12.0"
-  universal_platform:
-    dependency: transitive
-    description:
-      name: universal_platform
-      sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.1.0"
   unorm_dart:
     dependency: transitive
     description:
@@ -849,14 +777,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.4"
-  xml:
-    dependency: transitive
-    description:
-      name: xml
-      sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
-      url: "https://pub.dev"
-    source: hosted
-    version: "6.5.0"
   yaml:
     dependency: transitive
     description:
@@ -866,5 +786,5 @@ packages:
     source: hosted
     version: "3.1.1"
 sdks:
-  dart: ">=3.3.0 <4.0.0"
-  flutter: ">=3.19.0"
+  dart: ">=3.2.0-0 <4.0.0"
+  flutter: ">=3.7.0"
diff --git a/cw_wownero/pubspec.yaml b/cw_wownero/pubspec.yaml
index 582c15447..28ece82ef 100644
--- a/cw_wownero/pubspec.yaml
+++ b/cw_wownero/pubspec.yaml
@@ -25,7 +25,7 @@ dependencies:
   monero:
     git:
       url: https://github.com/mrcyjanek/monero_c
-      ref: caaf1e56b1d2a254b332fdf848926fb963af4a3b
+      ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
 #      ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash
       path: impls/monero.dart
   mutex: ^3.1.0
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 470bdf4e7..abcac01fb 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,8 +1,4 @@
 PODS:
-  - barcode_scan2 (0.0.1):
-    - Flutter
-    - MTBBarcodeScanner
-    - SwiftProtobuf
   - connectivity_plus (0.0.1):
     - Flutter
     - ReachabilitySwift
@@ -76,6 +72,8 @@ PODS:
   - DKPhotoGallery/Resource (0.0.19):
     - SDWebImage
     - SwiftyGif
+  - fast_scanner (5.1.1):
+    - Flutter
   - file_picker (0.0.1):
     - DKImagePickerController/PhotoGallery
     - Flutter
@@ -100,7 +98,6 @@ PODS:
     - Flutter
   - integration_test (0.0.1):
     - Flutter
-  - MTBBarcodeScanner (5.0.11)
   - OrderedSet (5.0.0)
   - package_info_plus (0.4.5):
     - Flutter
@@ -109,12 +106,7 @@ PODS:
     - FlutterMacOS
   - permission_handler_apple (9.1.1):
     - Flutter
-  - Protobuf (3.28.2)
   - ReachabilitySwift (5.2.3)
-  - reactive_ble_mobile (0.0.1):
-    - Flutter
-    - Protobuf (~> 3.5)
-    - SwiftProtobuf (~> 1.0)
   - SDWebImage (5.19.7):
     - SDWebImage/Core (= 5.19.7)
   - SDWebImage/Core (5.19.7)
@@ -127,11 +119,13 @@ PODS:
     - FlutterMacOS
   - sp_scanner (0.0.1):
     - Flutter
-  - SwiftProtobuf (1.27.1)
   - SwiftyGif (5.4.5)
   - Toast (4.1.1)
   - uni_links (0.0.1):
     - Flutter
+  - universal_ble (0.0.1):
+    - Flutter
+    - FlutterMacOS
   - url_launcher_ios (0.0.1):
     - Flutter
   - wakelock_plus (0.0.1):
@@ -140,7 +134,6 @@ PODS:
     - Flutter
 
 DEPENDENCIES:
-  - barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
   - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
   - CryptoSwift
   - cw_haven (from `.symlinks/plugins/cw_haven/ios`)
@@ -149,6 +142,7 @@ DEPENDENCIES:
   - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
   - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
   - devicelocale (from `.symlinks/plugins/devicelocale/ios`)
+  - fast_scanner (from `.symlinks/plugins/fast_scanner/ios`)
   - file_picker (from `.symlinks/plugins/file_picker/ios`)
   - Flutter (from `Flutter`)
   - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
@@ -161,12 +155,12 @@ DEPENDENCIES:
   - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
   - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
   - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
-  - reactive_ble_mobile (from `.symlinks/plugins/reactive_ble_mobile/ios`)
   - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
   - share_plus (from `.symlinks/plugins/share_plus/ios`)
   - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
   - sp_scanner (from `.symlinks/plugins/sp_scanner/ios`)
   - uni_links (from `.symlinks/plugins/uni_links/ios`)
+  - universal_ble (from `.symlinks/plugins/universal_ble/darwin`)
   - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
   - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
   - workmanager (from `.symlinks/plugins/workmanager/ios`)
@@ -176,18 +170,13 @@ SPEC REPOS:
     - CryptoSwift
     - DKImagePickerController
     - DKPhotoGallery
-    - MTBBarcodeScanner
     - OrderedSet
-    - Protobuf
     - ReachabilitySwift
     - SDWebImage
-    - SwiftProtobuf
     - SwiftyGif
     - Toast
 
 EXTERNAL SOURCES:
-  barcode_scan2:
-    :path: ".symlinks/plugins/barcode_scan2/ios"
   connectivity_plus:
     :path: ".symlinks/plugins/connectivity_plus/ios"
   cw_haven:
@@ -202,6 +191,8 @@ EXTERNAL SOURCES:
     :path: ".symlinks/plugins/device_info_plus/ios"
   devicelocale:
     :path: ".symlinks/plugins/devicelocale/ios"
+  fast_scanner:
+    :path: ".symlinks/plugins/fast_scanner/ios"
   file_picker:
     :path: ".symlinks/plugins/file_picker/ios"
   Flutter:
@@ -226,8 +217,6 @@ EXTERNAL SOURCES:
     :path: ".symlinks/plugins/path_provider_foundation/darwin"
   permission_handler_apple:
     :path: ".symlinks/plugins/permission_handler_apple/ios"
-  reactive_ble_mobile:
-    :path: ".symlinks/plugins/reactive_ble_mobile/ios"
   sensitive_clipboard:
     :path: ".symlinks/plugins/sensitive_clipboard/ios"
   share_plus:
@@ -238,6 +227,8 @@ EXTERNAL SOURCES:
     :path: ".symlinks/plugins/sp_scanner/ios"
   uni_links:
     :path: ".symlinks/plugins/uni_links/ios"
+  universal_ble:
+    :path: ".symlinks/plugins/universal_ble/darwin"
   url_launcher_ios:
     :path: ".symlinks/plugins/url_launcher_ios/ios"
   wakelock_plus:
@@ -246,7 +237,6 @@ EXTERNAL SOURCES:
     :path: ".symlinks/plugins/workmanager/ios"
 
 SPEC CHECKSUMS:
-  barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
   connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
   CryptoSwift: c63a805d8bb5e5538e88af4e44bb537776af11ea
   cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
@@ -257,6 +247,7 @@ SPEC CHECKSUMS:
   devicelocale: b22617f40038496deffba44747101255cee005b0
   DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
   DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
+  fast_scanner: 44c00940355a51258cd6c2085734193cd23d95bc
   file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de
   Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
   flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0
@@ -266,23 +257,20 @@ SPEC CHECKSUMS:
   fluttertoast: 48c57db1b71b0ce9e6bba9f31c940ff4b001293c
   in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
   integration_test: 13825b8a9334a850581300559b8839134b124670
-  MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
   OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
   package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
   path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
   permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
-  Protobuf: 28c89b24435762f60244e691544ed80f50d82701
   ReachabilitySwift: 7f151ff156cea1481a8411701195ac6a984f4979
-  reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c
   SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3
   sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
   share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
   shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
   sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12
-  SwiftProtobuf: b109bd17979d7993a84da14b1e1fdd8b0ded934a
   SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
   Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
   uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
+  universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
   url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
   wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1
   workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 09c75feee..85d39167a 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -230,6 +230,7 @@
 				97C146EC1CF9000F007C117D /* Resources */,
 				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
 				F6F67323547956BC4F7B67F1 /* [CP] Embed Pods Frameworks */,
+				777FE2B16F25A3E820834145 /* [CP] Copy Pods Resources */,
 			);
 			buildRules = (
 			);
@@ -343,6 +344,23 @@
 			shellPath = /bin/sh;
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
 		};
+		777FE2B16F25A3E820834145 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
 		9740EEB61CF901F6004384FC /* Run Script */ = {
 			isa = PBXShellScriptBuildPhase;
 			alwaysOutOfDate = 1;
diff --git a/lib/buy/meld/meld_buy_provider.dart b/lib/buy/meld/meld_buy_provider.dart
index 696301f2e..1ac3931d1 100644
--- a/lib/buy/meld/meld_buy_provider.dart
+++ b/lib/buy/meld/meld_buy_provider.dart
@@ -5,14 +5,10 @@ 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/entities/provider_types.dart';
 import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cake_wallet/routes.dart';
 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
-import 'package:cake_wallet/utils/device_info.dart';
 import 'package:cake_wallet/utils/show_pop_up.dart';
 import 'package:cw_core/crypto_currency.dart';
-import 'package:cw_core/currency.dart';
 import 'package:cw_core/wallet_base.dart';
 import 'package:flutter/material.dart';
 import 'dart:developer';
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index d863b136e..f873314c0 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -252,7 +252,7 @@ Future<void> defaultSettingsMigration(
           await removeMoneroWorld(sharedPreferences: sharedPreferences, nodes: nodes);
           break;
         case 41:
-          _deselectQuantex(sharedPreferences);
+          _deselectExchangeProvider(sharedPreferences, "Quantex");
           await _addSethNode(nodes, sharedPreferences);
           await updateTronNodesWithNowNodes(sharedPreferences: sharedPreferences, nodes: nodes);
           break;
@@ -261,6 +261,8 @@ Future<void> defaultSettingsMigration(
           break;
         case 43:
           _updateCakeXmrNode(nodes);
+          _deselectExchangeProvider(sharedPreferences, "THORChain");
+          _deselectExchangeProvider(sharedPreferences, "SimpleSwap");
           break;
 
         default:
@@ -295,12 +297,12 @@ void updateBtcElectrumNodeToUseSSL(Box<Node> nodes, SharedPreferences sharedPref
   }
 }
 
-void _deselectQuantex(SharedPreferences sharedPreferences) {
+void _deselectExchangeProvider(SharedPreferences sharedPreferences, String providerName) {
   final Map<String, dynamic> exchangeProvidersSelection =
       json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}")
           as Map<String, dynamic>;
 
-  exchangeProvidersSelection['Quantex'] = false;
+  exchangeProvidersSelection[providerName] = false;
 
   sharedPreferences.setString(
     PreferencesKey.exchangeProvidersSelection,
diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart
index 878a8bb54..166288135 100644
--- a/lib/src/screens/contact/contact_list_page.dart
+++ b/lib/src/screens/contact/contact_list_page.dart
@@ -240,14 +240,16 @@ class _ContactPageBodyState extends State<ContactPageBody> with SingleTickerProv
           mainAxisAlignment: MainAxisAlignment.start,
           children: <Widget>[
             currencyIcon,
-            Padding(
-              padding: EdgeInsets.only(left: 12),
-              child: Text(
-                contact.name,
-                style: TextStyle(
-                  fontSize: 14,
-                  fontWeight: FontWeight.normal,
-                  color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
+            Expanded(
+              child: Padding(
+                padding: EdgeInsets.only(left: 12),
+                child: Text(
+                  contact.name,
+                  style: TextStyle(
+                    fontSize: 14,
+                    fontWeight: FontWeight.normal,
+                    color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
+                  ),
                 ),
               ),
             ),
diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart
index 299846a72..d1d419d60 100644
--- a/lib/src/screens/restore/restore_options_page.dart
+++ b/lib/src/screens/restore/restore_options_page.dart
@@ -56,8 +56,9 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
     }
 
     if (isMoneroOnly) {
-      return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS)
-          .isNotEmpty;
+      // return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS)
+      //     .isNotEmpty;
+      return false;
     }
 
     return true;
diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake
index 4b9eb3b2d..f52be7481 100644
--- a/linux/flutter/generated_plugins.cmake
+++ b/linux/flutter/generated_plugins.cmake
@@ -10,6 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
 )
 
 list(APPEND FLUTTER_FFI_PLUGIN_LIST
+  sp_scanner
 )
 
 set(PLUGIN_BUNDLED_LIBRARIES)
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 52b44e53e..42b9fa84c 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -6,6 +6,7 @@ import FlutterMacOS
 import Foundation
 
 import connectivity_plus
+import cw_mweb
 import device_info_plus
 import devicelocale
 import fast_scanner
@@ -23,6 +24,7 @@ import wakelock_plus
 
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
   ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
+  CwMwebPlugin.register(with: registry.registrar(forPlugin: "CwMwebPlugin"))
   DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
   DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
   MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh
index 8beffbcc2..7eee6d6ae 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.17.0"
-MONERO_COM_BUILD_NUMBER=103
+MONERO_COM_VERSION="1.18.0"
+MONERO_COM_BUILD_NUMBER=105
 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.20.1"
-CAKEWALLET_BUILD_NUMBER=233
+CAKEWALLET_VERSION="4.21.0"
+CAKEWALLET_BUILD_NUMBER=236
 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 bc3b39747..fe18758c8 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.17.0"
-MONERO_COM_BUILD_NUMBER=101
+MONERO_COM_VERSION="1.18.0"
+MONERO_COM_BUILD_NUMBER=103
 MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="4.20.1"
-CAKEWALLET_BUILD_NUMBER=277
+CAKEWALLET_VERSION="4.21.0"
+CAKEWALLET_BUILD_NUMBER=281
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 HAVEN_NAME="Haven"
diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh
index 2dabf083b..1cdb43ced 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.10.1"
-CAKEWALLET_BUILD_NUMBER=37
+CAKEWALLET_VERSION="1.11.0"
+CAKEWALLET_BUILD_NUMBER=38
 
 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 026ea034b..8f3b68ab5 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.7.0"
-MONERO_COM_BUILD_NUMBER=34
+MONERO_COM_VERSION="1.8.0"
+MONERO_COM_BUILD_NUMBER=36
 MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
 
 CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="1.13.1"
-CAKEWALLET_BUILD_NUMBER=93
+CAKEWALLET_VERSION="1.14.0"
+CAKEWALLET_BUILD_NUMBER=95
 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
 
 if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
diff --git a/scripts/prepare_moneroc.sh b/scripts/prepare_moneroc.sh
index 0d90e431a..3596bd18b 100755
--- a/scripts/prepare_moneroc.sh
+++ b/scripts/prepare_moneroc.sh
@@ -8,7 +8,7 @@ if [[ ! -d "monero_c" ]];
 then
     git clone https://github.com/mrcyjanek/monero_c --branch master
     cd monero_c
-    git checkout 1d8e0fb30b53c28756f23676d5a3e1a99a9b3051
+    git checkout d72c15f4339791a7bbdf17e9d827b7b56ca144e4
     git reset --hard
     git submodule update --init --force --recursive
     ./apply_patches.sh monero
diff --git a/scripts/windows/build_exe_installer.iss b/scripts/windows/build_exe_installer.iss
index f65900cca..25f94cb1f 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.1.1"
+#define MyAppVersion "0.2.0"
 #define MyAppPublisher "Cake Labs LLC"
 #define MyAppURL "https://cakewallet.com/"
 #define MyAppExeName "CakeWallet.exe"
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index 26d481f85..92431a6fb 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -13,6 +13,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
 )
 
 list(APPEND FLUTTER_FFI_PLUGIN_LIST
+  sp_scanner
 )
 
 set(PLUGIN_BUNDLED_LIBRARIES)