dev
dart 79 lines 2.57 KB
Raw
1 import 'dart:async';
2 import 'dart:typed_data';
3
4 import 'package:bitbox_flutter/bitbox_manager.dart';
5 import 'package:cw_core/hardware/device_not_connected_exception.dart' as exception;
6 import 'package:web3dart/crypto.dart';
7 import 'package:web3dart/web3dart.dart';
8
9 class EvmBitboxCredentials extends CredentialsWithKnownAddress {
10 final String _address;
11
12 BitboxManager? bitboxManager;
13 String? derivationPath;
14
15 EvmBitboxCredentials(this._address);
16
17 @override
18 EthereumAddress get address => EthereumAddress.fromHex(_address);
19
20 void setBitbox(BitboxManager connection, [String? derivationPath_]) {
21 bitboxManager = connection;
22 derivationPath = derivationPath_ ?? "m/44'/60'/0'/0/0";
23 }
24
25 @override
26 MsgSignature signToEcSignature(Uint8List payload, {int? chainId, bool isEIP1559 = false}) =>
27 throw UnimplementedError("EvmLedgerCredentials.signToEcSignature");
28
29 @override
30 Future<MsgSignature> signToSignature(Uint8List payload,
31 {int? chainId, bool isEIP1559 = false}) async {
32 if (bitboxManager == null) {
33 throw exception.DeviceNotConnectedException();
34 }
35
36 if (isEIP1559) payload = payload.sublist(1);
37 final sig = await bitboxManager!
38 .signETHRLPTransaction(chainId ?? 1, derivationPath!, bytesToHex(payload), isEIP1559);
39
40 final r = bytesToHex(sig.sublist(0, 32));
41 final s = bytesToHex(sig.sublist(32, 32 + 32));
42 final v = sig.last.toInt();
43
44 if (isEIP1559) {
45 return MsgSignature(BigInt.parse(r, radix: 16), BigInt.parse(s, radix: 16), v);
46 }
47
48 var truncChainId = chainId ?? 1;
49 while (truncChainId.bitLength > 32) {
50 truncChainId >>= 8;
51 }
52
53 final truncTarget = truncChainId * 2 + 35;
54
55 int parity = v;
56 if (truncTarget & 0xff == v) {
57 parity = 0;
58 } else if ((truncTarget + 1) & 0xff == v) {
59 parity = 1;
60 }
61
62 // https://github.com/ethereumjs/ethereumjs-util/blob/8ffe697fafb33cefc7b7ec01c11e3a7da787fe0e/src/signature.ts#L26
63 final chainIdV = chainId != null ? (parity + (chainId * 2 + 35)) : parity;
64
65 return MsgSignature(BigInt.parse(r, radix: 16), BigInt.parse(s, radix: 16), chainIdV);
66 }
67
68 @override
69 Future<Uint8List> signPersonalMessage(Uint8List payload, {int? chainId}) async {
70 if (isNotConnected) throw exception.DeviceNotConnectedException();
71 return await bitboxManager!.signETHMessage(chainId ?? 1, derivationPath!, payload);
72 }
73
74 @override
75 Uint8List signPersonalMessageToUint8List(Uint8List payload, {int? chainId}) =>
76 throw UnimplementedError("EvmLedgerCredentials.signPersonalMessageToUint8List");
77
78 bool get isNotConnected => bitboxManager == null;
79 }