From 82391d4a5b1b96961d43ed17a3b4853e8062f219 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich 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 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 { @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 { } Future _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 { textAlign: TextAlign.center, ), ), + // DeviceTile( + // onPressed: () => Navigator.of(context).push( + // MaterialPageRoute( + // 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( - 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( + 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}) {