mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
* refactor: migrate hardware wallet resources to `new-ui`, add Trezor model support, and streamline hardware wallet handling across services * refactor: migrate hardware wallet resources to `new-ui`, add Trezor model support, and streamline hardware wallet handling across services * fix: correctly check for Ledger hardware wallet type in `isHardwareWallet` logic * refactor: unify `isConnected` method for hardware wallets, add Trezor-specific support, and update Monero sync logic * refactor: add Trezor transaction signing support, streamline hardware wallet handling, and update Monero dependency * refactor: improve Trezor transaction handling, adjust hardware wallet state logic, and update Monero dependency references * fix: non-hww tx commit() in xmr fix: prod monero_c fix: keyImage import workaround for Trezor/Cupcake chore: add kotlin's .salive to .gitignore * fix: universal_ble builds on iOS chore: remove prints fix: proper CI prebuilt for linux * new trezor connection ui * fix page title * typo * fix page title anim * refactor: enhance Trezor pairing flow, update state management, and simplify UI logic in hardware wallet integration * fix: correct widget indentation in Trezor pairing failure state UI * fix: extract Trezor pairing failure state UI to `_errorBox` widget and update Trezor dependency reference * refactor: simplify hardware wallet pairing error UI, optimize `_errorBox` layout, and streamline widget logic * Update cw_monero/lib/pending_monero_transaction.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * Update lib/buy/robinhood/robinhood_buy_provider.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * feat: add USB intent filters, device filter for hardware wallets, and update Trezor dependency reference * Update cw_monero/pubspec.yaml [skip ci] * Update cw_wownero/pubspec.yaml [skip ci] * Update cw_zano/pubspec.yaml [skip ci] * fix: use CryptoCurrency.title instead of amount-refactor-only .symbol getter new_wallet_type_page used curr.symbol, which only exists on the amount-refactor branch (String get symbol => title). On dev the equivalent is curr.title. Adapts the Trezor feature to dev's API without pulling in amount-refactor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix wallet list screen not scrollable minor fixes --------- Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com> Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net> Co-authored-by: Robert Malikowski <malikowskirobert@gmail.com> Co-authored-by: Konstantin Ullrich <konstantin@cakewallet.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
129 lines
3.8 KiB
Dart
129 lines
3.8 KiB
Dart
import 'dart:async';
|
|
import 'dart:ffi';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:cw_core/hardware/hardware_wallet_service.dart';
|
|
import 'package:cw_core/utils/print_verbose.dart';
|
|
import 'package:ffi/ffi.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
|
|
import 'package:ledger_flutter_plus/ledger_flutter_plus_dart.dart';
|
|
import 'package:monero/src/monero.dart' as api;
|
|
|
|
LedgerConnection? gLedger;
|
|
String? latestLedgerCommand;
|
|
|
|
typedef LedgerCallback = Void Function(Pointer<UnsignedChar>, UnsignedInt);
|
|
NativeCallable<LedgerCallback>? callable;
|
|
|
|
Future<void> enableLedgerExchange(LedgerConnection connection) async {
|
|
callable?.close();
|
|
|
|
void callback(Pointer<UnsignedChar> request, int requestLength) async {
|
|
final ledgerRequest = request.cast<Uint8>().asTypedList(requestLength);
|
|
|
|
_logLedgerCommand(ledgerRequest, false);
|
|
final response = await exchange(connection, ledgerRequest);
|
|
_logLedgerCommand(response, true);
|
|
|
|
final Pointer<Uint8> result = malloc<Uint8>(response.length);
|
|
for (var i = 0; i < response.length; i++) {
|
|
result.asTypedList(response.length)[i] = response[i];
|
|
}
|
|
|
|
latestLedgerCommand = _ledgerMoneroCommands[ledgerRequest[1]];
|
|
|
|
api.MoneroWallet.setDeviceReceivedData(
|
|
result.cast<UnsignedChar>(), response.length);
|
|
malloc.free(result);
|
|
// api.MoneroFree().free(result.cast());
|
|
}
|
|
|
|
callable = NativeCallable<LedgerCallback>.listener(callback);
|
|
api.MoneroWallet.setLedgerCallback(callable!.nativeFunction);
|
|
}
|
|
|
|
void disableLedgerExchange() {
|
|
callable?.close();
|
|
gLedger?.disconnect();
|
|
gLedger = null;
|
|
latestLedgerCommand = null;
|
|
}
|
|
|
|
Future<Uint8List> exchange(LedgerConnection connection, Uint8List data) async =>
|
|
connection.sendOperation<Uint8List>(ExchangeOperation(data));
|
|
|
|
class ExchangeOperation extends LedgerRawOperation<Uint8List> {
|
|
final Uint8List inputData;
|
|
|
|
ExchangeOperation(this.inputData);
|
|
|
|
@override
|
|
Future<Uint8List> read(ByteDataReader reader) async =>
|
|
reader.read(reader.remainingLength);
|
|
|
|
@override
|
|
Future<List<Uint8List>> write(ByteDataWriter writer) async => [inputData];
|
|
}
|
|
|
|
const _ledgerMoneroCommands = {
|
|
0x00: "INS_NONE",
|
|
0x02: "INS_RESET",
|
|
0x20: "INS_GET_KEY",
|
|
0x21: "INS_DISPLAY_ADDRESS",
|
|
0x22: "INS_PUT_KEY",
|
|
0x24: "INS_GET_CHACHA8_PREKEY",
|
|
0x26: "INS_VERIFY_KEY",
|
|
0x28: "INS_MANAGE_SEEDWORDS",
|
|
0x30: "INS_SECRET_KEY_TO_PUBLIC_KEY",
|
|
0x32: "INS_GEN_KEY_DERIVATION",
|
|
0x34: "INS_DERIVATION_TO_SCALAR",
|
|
0x36: "INS_DERIVE_PUBLIC_KEY",
|
|
0x38: "INS_DERIVE_SECRET_KEY",
|
|
0x3A: "INS_GEN_KEY_IMAGE",
|
|
0x3B: "INS_DERIVE_VIEW_TAG",
|
|
0x3C: "INS_SECRET_KEY_ADD",
|
|
0x3E: "INS_SECRET_KEY_SUB",
|
|
0x40: "INS_GENERATE_KEYPAIR",
|
|
0x42: "INS_SECRET_SCAL_MUL_KEY",
|
|
0x44: "INS_SECRET_SCAL_MUL_BASE",
|
|
0x46: "INS_DERIVE_SUBADDRESS_PUBLIC_KEY",
|
|
0x48: "INS_GET_SUBADDRESS",
|
|
0x4A: "INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY",
|
|
0x4C: "INS_GET_SUBADDRESS_SECRET_KEY",
|
|
0x70: "INS_OPEN_TX",
|
|
0x72: "INS_SET_SIGNATURE_MODE",
|
|
0x74: "INS_GET_ADDITIONAL_KEY",
|
|
0x76: "INS_STEALTH",
|
|
0x77: "INS_GEN_COMMITMENT_MASK",
|
|
0x78: "INS_BLIND",
|
|
0x7A: "INS_UNBLIND",
|
|
0x7B: "INS_GEN_TXOUT_KEYS",
|
|
0x7D: "INS_PREFIX_HASH",
|
|
0x7C: "INS_VALIDATE",
|
|
0x7E: "INS_MLSAG",
|
|
0x7F: "INS_CLSAG",
|
|
0x80: "INS_CLOSE_TX",
|
|
0xA0: "INS_GET_TX_PROOF",
|
|
0xC0: "INS_GET_RESPONSE"
|
|
};
|
|
|
|
void _logLedgerCommand(Uint8List command, [bool isResponse = true]) {
|
|
String toHexString(Uint8List data) =>
|
|
data.map((e) => e.toRadixString(16).padLeft(2, '0')).join();
|
|
|
|
if (isResponse) {
|
|
printV("< ${toHexString(command)}");
|
|
} else {
|
|
printV(
|
|
"> ${_ledgerMoneroCommands[command[1]]} ${toHexString(command.sublist(2))}");
|
|
}
|
|
}
|
|
|
|
class MoneroLedgerService extends HardwareWalletService {
|
|
final LedgerConnection connection;
|
|
|
|
MoneroLedgerService(this.connection);
|
|
}
|
|
|