From 82391d4a5b1b96961d43ed17a3b4853e8062f219 Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Fri, 17 May 2024 08:15:19 -0500
Subject: [PATCH] Generic fixes (#1454)

* Handle Bluetooth is disabled

* Allow signMessage using ledger_bitcoin

* Fix desktop wallet selection dropdown
---
 cw_bitcoin/lib/bitcoin_wallet.dart            | 42 ++++++++++++++-----
 cw_bitcoin/pubspec.lock                       |  6 +--
 cw_bitcoin/pubspec.yaml                       |  2 +-
 .../connect_device/connect_device_page.dart   | 38 ++++++++++-------
 .../desktop_wallet_selection_dropdown.dart    | 33 ++++++++-------
 5 files changed, 77 insertions(+), 44 deletions(-)

diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart
index f96b0e4da..b02116541 100644
--- a/cw_bitcoin/lib/bitcoin_wallet.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet.dart
@@ -1,23 +1,24 @@
-import 'package:bitcoin_base/bitcoin_base.dart';
-import 'package:convert/convert.dart';
+import 'dart:convert';
 
+import 'package:bip39/bip39.dart' as bip39;
+import 'package:bitcoin_base/bitcoin_base.dart';
+import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
+import 'package:convert/convert.dart';
+import 'package:cw_bitcoin/bitcoin_address_record.dart';
 import 'package:cw_bitcoin/bitcoin_mnemonic.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';
+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:mobx/mobx.dart';
-import 'package:flutter/foundation.dart';
-import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
-import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
-import 'package:cw_bitcoin/electrum_wallet.dart';
-import 'package:cw_core/wallet_info.dart';
-import 'package:cw_bitcoin/bitcoin_address_record.dart';
-import 'package:cw_bitcoin/electrum_balance.dart';
-import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
-import 'package:bip39/bip39.dart' as bip39;
 
 part 'bitcoin_wallet.g.dart';
 
@@ -215,4 +216,23 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
     final rawHex = await _bitcoinLedgerApp!.signPsbt(_ledgerDevice!, psbt: psbt.psbt);
     return BtcTransaction.fromRaw(hex.encode(rawHex));
   }
+
+  @override
+  Future<String> signMessage(String message, {String? address = null}) async {
+    if (walletInfo.isHardwareWallet) {
+      final addressEntry = address != null
+          ? 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 signature = await _bitcoinLedgerApp!
+          .signMessage(_ledgerDevice!, message: ascii.encode(message), signDerivationPath: derivationPath);
+      return base64Encode(signature);
+    }
+
+    return super.signMessage(message, address: address);
+  }
 }
diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock
index e6f0b34dd..7690c9c85 100644
--- a/cw_bitcoin/pubspec.lock
+++ b/cw_bitcoin/pubspec.lock
@@ -475,10 +475,10 @@ packages:
     description:
       path: "."
       ref: HEAD
-      resolved-ref: b6ed573cbeb57d5f0d39dfe4254bf9d15b620ab6
-      url: "https://github.com/cake-tech/ledger-bitcoin.git"
+      resolved-ref: f819d37e235e239c315e93856abbf5e5d3b71dab
+      url: "https://github.com/cake-tech/ledger-bitcoin"
     source: git
-    version: "0.0.1"
+    version: "0.0.2"
   ledger_flutter:
     dependency: "direct main"
     description:
diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml
index 84254b5b5..265d2f9a2 100644
--- a/cw_bitcoin/pubspec.yaml
+++ b/cw_bitcoin/pubspec.yaml
@@ -38,7 +38,7 @@ dependencies:
   ledger_flutter: ^1.0.1
   ledger_bitcoin:
     git:
-      url: https://github.com/cake-tech/ledger-bitcoin.git
+      url: https://github.com/cake-tech/ledger-bitcoin
 
 dev_dependencies:
   flutter_test:
diff --git a/lib/src/screens/connect_device/connect_device_page.dart b/lib/src/screens/connect_device/connect_device_page.dart
index dfb32beba..80b396a34 100644
--- a/lib/src/screens/connect_device/connect_device_page.dart
+++ b/lib/src/screens/connect_device/connect_device_page.dart
@@ -3,6 +3,7 @@ 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';
@@ -78,15 +79,13 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
   @override
   void initState() {
     super.initState();
-    Future.delayed(
-      Duration(seconds: 1),
-      () => _bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device))),
-    );
-    // _bleRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshBleDevices());
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      _bleRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshBleDevices());
 
-    if (Platform.isAndroid) {
-      _usbRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices());
-    }
+      if (Platform.isAndroid) {
+        _usbRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices());
+      }
+    });
   }
 
   @override
@@ -103,14 +102,16 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
   }
 
   Future<void> _refreshBleDevices() async {
-    final isBleEnabled = await Permission.bluetooth.serviceStatus.isEnabled;
-
-    setState(() => bleIsEnabled = isBleEnabled);
-
-    if (isBleEnabled) {
-      _bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device)));
+    try {
+      _bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device)))
+        ..onError((e) {
+          throw e as Exception;
+        });
+      setState(() => bleIsEnabled = true);
       _bleRefreshTimer?.cancel();
       _bleRefreshTimer = null;
+    } catch (e) {
+      setState(() => bleIsEnabled = false);
     }
   }
 
@@ -142,6 +143,15 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
                   textAlign: TextAlign.center,
                 ),
               ),
+              // DeviceTile(
+              //   onPressed: () => Navigator.of(context).push(
+              //     MaterialPageRoute<void>(
+              //       builder: (BuildContext context) => DebugDevicePage(),
+              //     ),
+              //   ),
+              //   title: "Debug Ledger",
+              //   leading: imageLedger,
+              // ),
               if (!bleIsEnabled)
                 Padding(
                   padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
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 18ab9d030..adf0840c9 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
@@ -117,22 +117,25 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
     if (selectedWallet.isCurrent || !selectedWallet.isEnabled) {
       return;
     }
-    final confirmed = await showPopUp<bool>(
-            context: context,
-            builder: (dialogContext) {
-              return AlertWithTwoActions(
-                  alertTitle: S.of(context).change_wallet_alert_title,
-                  alertContent: S.of(context).change_wallet_alert_content(selectedWallet.name),
-                  leftButtonText: S.of(context).cancel,
-                  rightButtonText: S.of(context).change,
-                  actionLeftButton: () => Navigator.of(dialogContext).pop(false),
-                  actionRightButton: () => Navigator.of(dialogContext).pop(true));
-            }) ??
-        false;
 
-    if (confirmed) {
-      await _loadWallet(selectedWallet);
-    }
+    WidgetsBinding.instance.addPostFrameCallback((_) async {
+      final confirmed = await showPopUp<bool>(
+          context: context,
+          builder: (dialogContext) {
+            return AlertWithTwoActions(
+                alertTitle: S.of(context).change_wallet_alert_title,
+                alertContent: S.of(context).change_wallet_alert_content(selectedWallet.name),
+                leftButtonText: S.of(context).cancel,
+                rightButtonText: S.of(context).change,
+                actionLeftButton: () => Navigator.of(dialogContext).pop(false),
+                actionRightButton: () => Navigator.of(dialogContext).pop(true));
+          }) ??
+          false;
+
+      if (confirmed) {
+        await _loadWallet(selectedWallet);
+      }
+    });
   }
 
   Image _imageFor({required WalletType type}) {