mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-16 17:27:37 +00:00
148 lines
4.4 KiB
Dart
148 lines
4.4 KiB
Dart
import 'dart:async';
|
|
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';
|
|
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_plus/ledger_flutter_plus.dart' as sdk;
|
|
import 'package:mobx/mobx.dart';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
|
|
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) {
|
|
return false;
|
|
}
|
|
|
|
if (isMoneroOnly) {
|
|
return DeviceConnectionType.supportedConnectionTypes(
|
|
WalletType.monero, Platform.isIOS)
|
|
.isNotEmpty;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
LedgerViewModelBase() {
|
|
if (_doesSupportHardwareWallets) {
|
|
reaction((_) => bleIsEnabled, (_) {
|
|
if (bleIsEnabled) _initBLE();
|
|
});
|
|
updateBleState();
|
|
|
|
if (!Platform.isIOS) {
|
|
ledgerPlusUSB = sdk.LedgerInterface.usb();
|
|
}
|
|
}
|
|
}
|
|
|
|
@observable
|
|
bool bleIsEnabled = false;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
Future<void> updateBleState() async {
|
|
final bleState = await sdk.UniversalBle.getBluetoothAvailabilityState();
|
|
|
|
final newState = bleState == sdk.AvailabilityState.poweredOn;
|
|
|
|
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;
|
|
if (type == WalletType.monero) {
|
|
monero!.resetLedgerConnection();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
_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.monero:
|
|
return monero!.setLedgerConnection(wallet, connection);
|
|
case WalletType.bitcoin:
|
|
case WalletType.litecoin:
|
|
return bitcoin!.setLedgerConnection(wallet, connection);
|
|
case WalletType.ethereum:
|
|
return ethereum!.setLedgerConnection(wallet, connection);
|
|
case WalletType.polygon:
|
|
return polygon!.setLedgerConnection(wallet, connection);
|
|
default:
|
|
throw Exception('Unexpected wallet type: ${wallet.type}');
|
|
}
|
|
}
|
|
|
|
String? interpretErrorCode(String errorCode) {
|
|
switch (errorCode) {
|
|
case "6985":
|
|
return S.current.ledger_error_tx_rejected_by_user;
|
|
case "5515":
|
|
return S.current.ledger_error_device_locked;
|
|
case "6d02": // UNKNOWN_APDU
|
|
case "6511":
|
|
case "6e00":
|
|
return S.current.ledger_error_wrong_app;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
}
|