mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-18 05:51:34 +02:00
* feat: initial hive -> SQLite Includes migration script and initial work done to remove dependency on hive generators. Also contains some refactoring to make sync code async. Features new dev screen that lists all SQLite tables Aspects that need testing: - backups (from this version, and from previous versions as well) - wallet loading / wallet list - almost everything else - renaming - deletion - sorting in wallet list - wallet groups - wallet seed/keys - wallet switching - wallet creation / restore - all methods - wallet address page - hardware wallet connection (and prompts from mall screens) - contacts - advanced settings in wallet creation - derivation paths - some minor wownero fixes - base, hardware wallets * fix: build errors * fix: Bad state: No element in backup restore * address comments from review * fix: HardwareWalletType
110 lines
3.4 KiB
Dart
110 lines
3.4 KiB
Dart
import 'dart:async';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:cw_core/hardware/device_not_connected_exception.dart'
|
|
as exception;
|
|
import 'package:cw_core/utils/print_verbose.dart';
|
|
import 'package:ledger_ethereum/ledger_ethereum.dart';
|
|
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
|
|
import 'package:web3dart/crypto.dart';
|
|
import 'package:web3dart/web3dart.dart';
|
|
|
|
class EvmLedgerCredentials extends CredentialsWithKnownAddress {
|
|
final String _address;
|
|
|
|
EthereumLedgerApp? ethereumLedgerApp;
|
|
|
|
EvmLedgerCredentials(this._address);
|
|
|
|
@override
|
|
EthereumAddress get address => EthereumAddress.fromHex(_address);
|
|
|
|
Future<void> setLedgerConnection(LedgerConnection connection,
|
|
[String? derivationPath]) async {
|
|
ethereumLedgerApp = EthereumLedgerApp(connection,
|
|
derivationPath: derivationPath ?? "m/44'/60'/0'/0/0");
|
|
}
|
|
|
|
@override
|
|
MsgSignature signToEcSignature(Uint8List payload,
|
|
{int? chainId, bool isEIP1559 = false}) =>
|
|
throw UnimplementedError("EvmLedgerCredentials.signToEcSignature");
|
|
|
|
@override
|
|
Future<MsgSignature> signToSignature(Uint8List payload,
|
|
{int? chainId, bool isEIP1559 = false}) async {
|
|
if (ethereumLedgerApp == null) {
|
|
throw exception.DeviceNotConnectedException();
|
|
}
|
|
|
|
final sig = await ethereumLedgerApp!.signTransaction(payload);
|
|
|
|
final v = sig[0].toInt();
|
|
final r = bytesToHex(sig.sublist(1, 1 + 32));
|
|
final s = bytesToHex(sig.sublist(1 + 32, 1 + 32 + 32));
|
|
|
|
var truncChainId = chainId ?? 1;
|
|
while (truncChainId.bitLength > 32) {
|
|
truncChainId >>= 8;
|
|
}
|
|
|
|
final truncTarget = truncChainId * 2 + 35;
|
|
|
|
int parity = v;
|
|
if (truncTarget & 0xff == v) {
|
|
parity = 0;
|
|
} else if ((truncTarget + 1) & 0xff == v) {
|
|
parity = 1;
|
|
}
|
|
|
|
// https://github.com/ethereumjs/ethereumjs-util/blob/8ffe697fafb33cefc7b7ec01c11e3a7da787fe0e/src/signature.ts#L26
|
|
int chainIdV;
|
|
if (isEIP1559) {
|
|
chainIdV = v;
|
|
} else {
|
|
chainIdV = chainId != null ? (parity + (chainId * 2 + 35)) : parity;
|
|
}
|
|
|
|
return MsgSignature(
|
|
BigInt.parse(r, radix: 16), BigInt.parse(s, radix: 16), chainIdV);
|
|
}
|
|
|
|
@override
|
|
Future<Uint8List> signPersonalMessage(Uint8List payload,
|
|
{int? chainId}) async {
|
|
if (isNotConnected) throw exception.DeviceNotConnectedException();
|
|
|
|
final sig = await ethereumLedgerApp!.signMessage(payload);
|
|
|
|
if (sig.isEmpty) throw Exception("No Signature received from device!");
|
|
|
|
final r = sig.sublist(1, 1 + 32);
|
|
final s = sig.sublist(1 + 32, 1 + 32 + 32);
|
|
final v = [sig[0]];
|
|
|
|
// https://github.com/ethereumjs/ethereumjs-util/blob/8ffe697fafb33cefc7b7ec01c11e3a7da787fe0e/src/signature.ts#L63
|
|
return Uint8List.fromList(r + s + v);
|
|
}
|
|
|
|
@override
|
|
Uint8List signPersonalMessageToUint8List(Uint8List payload, {int? chainId}) =>
|
|
throw UnimplementedError(
|
|
"EvmLedgerCredentials.signPersonalMessageToUint8List");
|
|
|
|
Future<void> provideERC20Info(
|
|
String erc20ContractAddress, int chainId) async {
|
|
if (isNotConnected) throw exception.DeviceNotConnectedException();
|
|
|
|
try {
|
|
await ethereumLedgerApp!.getAndProvideERC20TokenInformation(
|
|
erc20ContractAddress: erc20ContractAddress, chainId: chainId);
|
|
} catch (e) {
|
|
printV(e);
|
|
rethrow;
|
|
// if (e.errorCode != -28672) rethrow;
|
|
}
|
|
}
|
|
|
|
bool get isNotConnected => ethereumLedgerApp == null || ethereumLedgerApp!.connection.isDisconnected;
|
|
}
|