Generic fixes (#1454)

* Handle Bluetooth is disabled

* Allow signMessage using ledger_bitcoin

* Fix desktop wallet selection dropdown
This commit is contained in:
Konstantin Ullrich 2024-05-17 08:15:19 -05:00 committed by GitHub
parent fbecc5c994
commit 82391d4a5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 77 additions and 44 deletions

View file

@ -1,23 +1,24 @@
import 'package:bitcoin_base/bitcoin_base.dart'; import 'dart:convert';
import 'package:convert/convert.dart';
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_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_bitcoin/psbt_transaction_builder.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/unspent_coins_info.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:hive/hive.dart';
import 'package:ledger_bitcoin/ledger_bitcoin.dart'; import 'package:ledger_bitcoin/ledger_bitcoin.dart';
import 'package:ledger_flutter/ledger_flutter.dart'; import 'package:ledger_flutter/ledger_flutter.dart';
import 'package:mobx/mobx.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'; 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); final rawHex = await _bitcoinLedgerApp!.signPsbt(_ledgerDevice!, psbt: psbt.psbt);
return BtcTransaction.fromRaw(hex.encode(rawHex)); 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);
}
} }

View file

@ -475,10 +475,10 @@ packages:
description: description:
path: "." path: "."
ref: HEAD ref: HEAD
resolved-ref: b6ed573cbeb57d5f0d39dfe4254bf9d15b620ab6 resolved-ref: f819d37e235e239c315e93856abbf5e5d3b71dab
url: "https://github.com/cake-tech/ledger-bitcoin.git" url: "https://github.com/cake-tech/ledger-bitcoin"
source: git source: git
version: "0.0.1" version: "0.0.2"
ledger_flutter: ledger_flutter:
dependency: "direct main" dependency: "direct main"
description: description:

View file

@ -38,7 +38,7 @@ dependencies:
ledger_flutter: ^1.0.1 ledger_flutter: ^1.0.1
ledger_bitcoin: ledger_bitcoin:
git: git:
url: https://github.com/cake-tech/ledger-bitcoin.git url: https://github.com/cake-tech/ledger-bitcoin
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View file

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.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/src/screens/connect_device/widgets/device_tile.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart';
@ -78,15 +79,13 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
Future.delayed( WidgetsBinding.instance.addPostFrameCallback((_) {
Duration(seconds: 1), _bleRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshBleDevices());
() => _bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device))),
);
// _bleRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshBleDevices());
if (Platform.isAndroid) { if (Platform.isAndroid) {
_usbRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices()); _usbRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices());
} }
});
} }
@override @override
@ -103,14 +102,16 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
} }
Future<void> _refreshBleDevices() async { Future<void> _refreshBleDevices() async {
final isBleEnabled = await Permission.bluetooth.serviceStatus.isEnabled; try {
_bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device)))
setState(() => bleIsEnabled = isBleEnabled); ..onError((e) {
throw e as Exception;
if (isBleEnabled) { });
_bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device))); setState(() => bleIsEnabled = true);
_bleRefreshTimer?.cancel(); _bleRefreshTimer?.cancel();
_bleRefreshTimer = null; _bleRefreshTimer = null;
} catch (e) {
setState(() => bleIsEnabled = false);
} }
} }
@ -142,6 +143,15 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
// DeviceTile(
// onPressed: () => Navigator.of(context).push(
// MaterialPageRoute<void>(
// builder: (BuildContext context) => DebugDevicePage(),
// ),
// ),
// title: "Debug Ledger",
// leading: imageLedger,
// ),
if (!bleIsEnabled) if (!bleIsEnabled)
Padding( Padding(
padding: EdgeInsets.only(left: 20, right: 20, bottom: 20), padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),

View file

@ -117,22 +117,25 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
if (selectedWallet.isCurrent || !selectedWallet.isEnabled) { if (selectedWallet.isCurrent || !selectedWallet.isEnabled) {
return; 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) { WidgetsBinding.instance.addPostFrameCallback((_) async {
await _loadWallet(selectedWallet); 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}) { Image _imageFor({required WalletType type}) {