Files
hash-wallet/lib/view_model/hardware_wallet/bitbox_view_model.dart
T
jwinterm dd449f2594 Merge upstream Cake Wallet v6.5.0
Catches up from the May 12 fork point (v6.1.2+23) through v6.5.0: 535
upstream commits, including the Monero silent-open fix, Monero on Trezor,
Ledger/Trezor BLE fixes, the new seed and history screens, quick Bitcoin
sync, git-pinned dependencies (pubspec_overrides.yaml), frozen Hive
adapters (*.part.dart), monero_c v0.18.4.6-RC2 and Flutter 3.41.9.

Merged with both sides normalized first (import rename, 100-column
format), which took the conflict count from 614 paths to 322. The
procedure is now scripts/upstream_sync.sh.

Kept from Hash Bags:
- WalletType enum order and Hive IDs. SQLite stores WalletType.index and
  our order differs from upstream's; taking theirs would reread saved
  wallets as other chains. Our frozen adapter keeps the shipped IDs.
- The 1.0.2 legacy PIN and wallet-password decode and self-heal.
- Removed chains (Solana, Tron, Zano, Zcash, Decred, Haven) and the new
  Robinhood chain stay out; Cake Pay and non-Trocador swaps stay out.
- Default nodes (node.wownero.org, sethforprivacy, Blockstream, bysh.me),
  converted to upstream's isDefault node-list key; Wownero is back in the
  node reset list.
- Privacy: address resolvers limited to domain-anchored sources again;
  prices.neroswap.com for fiat; upstream's charts tab, which reads
  prices.cakewallet.com, sits behind FeatureFlag.isChartsEnabled = false.
- Lightning stays behind FeatureFlag.isLightningEnabled, including
  upstream's new post-seed Lightning username step.
- Our icon pipeline, branding and bundle identifiers.

Twelve new upstream widget tests are skipped: test and code are unchanged
from v6.5.0 apart from renames (not rerun on a pristine upstream checkout;
upstream's top_bar_test does not compile against its own TopBar).
flutter analyze lib: 0 errors; flutter test: 345 passed, 12 skipped;
flutter build bundle compiles. Built with Flutter 3.41.9.
2026-10-24 23:49:29 -04:00

139 lines
4.2 KiB
Dart

import "dart:async";
import "dart:io";
import "package:bitbox_flutter/bitbox_flutter.dart" as sdk;
import "package:hash_wallet/bitcoin/bitcoin.dart";
import "package:hash_wallet/entities/hardware_wallet/hardware_wallet_device.dart";
import "package:hash_wallet/evm/evm.dart";
import "package:hash_wallet/view_model/hardware_wallet/hardware_wallet_view_model.dart";
import "package:hash_wallet/wallet_type_utils.dart";
import "package:cw_core/hardware/hardware_wallet_service.dart";
import "package:cw_core/root_dir.dart";
import "package:cw_core/utils/print_verbose.dart";
import "package:cw_core/wallet_base.dart";
import "package:cw_core/wallet_info.dart";
import "package:cw_core/wallet_type.dart";
import "package:mobx/mobx.dart";
part "bitbox_view_model.g.dart";
class BitboxViewModel = BitboxViewModelBase with _$BitboxViewModel;
abstract class BitboxViewModelBase extends HardwareWalletViewModel with Store {
BitboxViewModelBase() {
if (!Platform.isIOS && !isMoneroOnly) {
bitboxManager = sdk.BitboxManager();
}
}
late final sdk.BitboxManager bitboxManager;
BitboxHardwareWalletDevice? _connectedDevice;
Timer? _isConnectedTimer;
@override
HardwareWalletType get hardwareWalletType => HardwareWalletType.bitbox;
@override
@observable
bool isBleEnabled = false;
@override
@observable
bool isConnecting = false;
@override
bool get hasBluetooth => Platform.isIOS && false; // TODO(Konsti): remove when we enable bluetooth
@override
Future<void> updateBleState() async {}
@override
Stream<HardwareWalletDevice> scanForBleDevices() => throw UnimplementedError();
@override
Future<List<HardwareWalletDevice>> getAllUsbDevices() => bitboxManager.devices
.then((devices) => devices.map(BitboxHardwareWalletDevice.new).toList());
@override
Future<void> stopScanning() async {}
@override
@action
Future<bool> connectDevice(HardwareWalletDevice device, WalletType type) async {
if (device is! BitboxHardwareWalletDevice) {
return false;
}
if (isConnecting) {
return false;
}
isConnecting = true;
try {
final appDocDir = await getAppDir();
await bitboxManager.connect(device.device);
printV("Got Connection", file: "${appDocDir.path}/error.txt");
await bitboxManager.initBitBox();
printV("Bitbox initialized!", file: "${appDocDir.path}/error.txt");
await bitboxManager.channelHashVerify();
printV("Bitbox channel-hash verified!", file: "${appDocDir.path}/error.txt");
_connectedDevice = device;
_isConnectedTimer = Timer.periodic(const Duration(seconds: 1), (_) => _isStillConnected());
isConnecting = false;
return true;
} catch (e) {
printV(e);
}
isConnecting = false;
_connectedDevice = null;
_isConnectedTimer?.cancel();
_isConnectedTimer = null;
return false;
}
@override
bool isConnected(WalletType type) => _connectedDevice != null;
Future<void> _isStillConnected() async {
final devices = await getAllUsbDevices();
if (!devices.any((d) => d.name == _connectedDevice?.name)) {
_connectedDevice = null;
_isConnectedTimer?.cancel();
_isConnectedTimer = null;
}
}
@override
HardwareWalletService getHardwareWalletService(WalletType type) {
switch (type) {
case WalletType.bitcoin:
return bitcoin!.getBitboxHardwareWalletService(bitboxManager, true);
case WalletType.litecoin:
return bitcoin!.getBitboxHardwareWalletService(bitboxManager, false);
case WalletType.ethereum:
case WalletType.polygon:
return evm!.getBitboxHardwareWalletService(bitboxManager);
default:
throw UnimplementedError();
}
}
@override
Future<void> initWallet(WalletBase wallet) {
switch (wallet.type) {
case WalletType.bitcoin:
case WalletType.litecoin:
return bitcoin!
.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
case WalletType.ethereum:
case WalletType.polygon:
return evm!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
default:
throw Exception("Unexpected wallet type: ${wallet.type} for bitbox");
}
}
}