@exodus/hw-ledger 2.9.5 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [2.10.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hw-ledger@2.9.5...@exodus/hw-ledger@2.10.0) (2024-09-16)
7
+
8
+ ### Features
9
+
10
+ - add bitcoin multisig support to ledger ([#9218](https://github.com/ExodusMovement/exodus-hydra/issues/9218)) ([1b63e8a](https://github.com/ExodusMovement/exodus-hydra/commit/1b63e8a6ac7bab9cd580f602f2fd0cbff48ed01c))
11
+
6
12
  ## [2.9.5](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hw-ledger@2.9.4...@exodus/hw-ledger@2.9.5) (2024-08-16)
7
13
 
8
14
  ### Bug Fixes
@@ -1,3 +1,4 @@
1
+ import type { Storage } from 'adapters/storage-interface';
1
2
  export type BluetoothStatus = {
2
3
  type: 'Unknown' | 'Resetting' | 'Unsupported' | 'Unauthorized' | 'PoweredOff' | 'PoweredOn';
3
4
  available: boolean;
@@ -16,3 +17,14 @@ export declare const bluetoothScanningAtomDefinition: {
16
17
  readonly dependencies: readonly [];
17
18
  readonly public: true;
18
19
  };
20
+ type Params = {
21
+ storage: Storage<Record<string, Buffer>>;
22
+ };
23
+ export declare const walletPolicyAtomDefinition: {
24
+ readonly id: "walletPolicyAtom";
25
+ readonly type: "atom";
26
+ readonly factory: ({ storage }: Params) => import("@exodus/atoms").Atom<Record<string, Buffer> | {}>;
27
+ readonly dependencies: readonly ["storage"];
28
+ readonly public: true;
29
+ };
30
+ export {};
@@ -1,4 +1,4 @@
1
- import { createInMemoryAtom } from '@exodus/atoms';
1
+ import { createInMemoryAtom, createStorageAtomFactory } from '@exodus/atoms';
2
2
  export const bluetoothStatusAtomDefinition = {
3
3
  id: 'bluetoothStatusAtom',
4
4
  type: 'atom',
@@ -15,3 +15,17 @@ export const bluetoothScanningAtomDefinition = {
15
15
  dependencies: [],
16
16
  public: true,
17
17
  };
18
+ export const walletPolicyAtomDefinition = {
19
+ id: 'walletPolicyAtom',
20
+ type: 'atom',
21
+ factory: ({ storage }) => {
22
+ const createStorageAtom = createStorageAtomFactory({ storage });
23
+ return createStorageAtom({
24
+ key: 'walletPolicy',
25
+ defaultValue: {},
26
+ isSoleWriter: true,
27
+ });
28
+ },
29
+ dependencies: ['storage'],
30
+ public: true,
31
+ };
package/lib/index.d.ts CHANGED
@@ -17,6 +17,16 @@ declare const hardwareWalletLedger: ({ bluetoothScannerTimeout, }?: Partial<HwLe
17
17
  readonly dependencies: readonly [];
18
18
  readonly public: true;
19
19
  };
20
+ }, {
21
+ readonly definition: {
22
+ readonly id: "walletPolicyAtom";
23
+ readonly type: "atom";
24
+ readonly factory: ({ storage }: {
25
+ storage: import("adapters/storage-interface").Storage<Record<string, Buffer>>;
26
+ }) => import("libraries/atoms/lib").Atom<Record<string, Buffer> | {}>;
27
+ readonly dependencies: readonly ["storage"];
28
+ readonly public: true;
29
+ };
20
30
  }, {
21
31
  readonly definition: {
22
32
  readonly id: "hardwareWalletLedgerPlugin";
@@ -39,7 +49,7 @@ declare const hardwareWalletLedger: ({ bluetoothScannerTimeout, }?: Partial<HwLe
39
49
  readonly id: "ledgerDiscovery";
40
50
  readonly type: "module";
41
51
  readonly factory: (deps: import("./module").Dependencies) => import("./module").LedgerDiscovery;
42
- readonly dependencies: readonly ["config", "logger", "transportsFactories", "bluetoothStatusAtom", "bluetoothScanningAtom"];
52
+ readonly dependencies: readonly ["config", "logger", "transportsFactories", "bluetoothStatusAtom", "bluetoothScanningAtom", "walletPolicyAtom"];
43
53
  readonly public: true;
44
54
  };
45
55
  readonly config: {
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { bluetoothStatusAtomDefinition, bluetoothScanningAtomDefinition } from './atoms';
1
+ import { bluetoothStatusAtomDefinition, bluetoothScanningAtomDefinition, walletPolicyAtomDefinition, } from './atoms';
2
2
  import ledgerDiscoveryDefinition from './module';
3
3
  import hardwareWalletLedgerPluginDefinition from './plugin';
4
4
  const hardwareWalletLedger = ({ bluetoothScannerTimeout = 10_000, } = {}) => {
@@ -11,6 +11,9 @@ const hardwareWalletLedger = ({ bluetoothScannerTimeout = 10_000, } = {}) => {
11
11
  {
12
12
  definition: bluetoothScanningAtomDefinition,
13
13
  },
14
+ {
15
+ definition: walletPolicyAtomDefinition,
16
+ },
14
17
  {
15
18
  definition: hardwareWalletLedgerPluginDefinition,
16
19
  },
@@ -1,4 +1,5 @@
1
1
  import type Transport from '@ledgerhq/hw-transport';
2
+ import type { Atom } from '@exodus/atoms';
2
3
  import type { Bytes, HardwareWalletAssetHandler } from '@exodus/hw-common';
3
4
  export interface BitcoinMessage {
4
5
  rawMessage?: Bytes;
@@ -7,7 +8,7 @@ export interface BitcoinMessage {
7
8
  message: Bytes;
8
9
  };
9
10
  }
10
- declare function createHandler(transport: Transport): Promise<HardwareWalletAssetHandler<BitcoinMessage>>;
11
+ declare function createHandler(transport: Transport, walletPolicyAtom?: Atom<Record<string, Buffer>>): Promise<HardwareWalletAssetHandler<BitcoinMessage>>;
11
12
  declare const metadata: {
12
13
  applications: {
13
14
  applicationName: string;
@@ -3,17 +3,25 @@ import { AppClient, PsbtV2 } from '@exodus/ledger-bitcoin';
3
3
  import { BIP322 } from '@exodus/bip322-js';
4
4
  import { splitBip44DerivationPath } from './utils';
5
5
  import assert from 'minimalistic-assert';
6
- import { assertPsbtOnlyHasAllowedDerivationPaths, tagPsbtWithDerivationPaths, getWalletPolicy, derivationPathsToWalletPolicy, addDummyInputs, } from './utils/psbt';
6
+ import { assertPsbtOnlyHasAllowedDerivationPaths, tagPsbtWithDerivationPaths, getWalletPolicy, getMultisigWalletPolicy, derivationPathsToWalletPolicy, addDummyInputs, } from './utils/psbt';
7
7
  import { buildBip322PSBT } from './utils/bip322';
8
8
  import applications from './applications';
9
- async function createHandler(transport) {
9
+ async function createHandler(transport, walletPolicyAtom) {
10
10
  const app = new AppClient(transport);
11
11
  const getAddress = async (params) => {
12
12
  const [purpose, coin, account, change, address] = splitBip44DerivationPath(params.derivationPath);
13
13
  const fpr = await app.getMasterFingerprint();
14
14
  const xpub = await app.getExtendedPubkey(`m/${purpose}/${coin}/${account}`);
15
- const walletPolicy = getWalletPolicy(fpr, xpub, purpose, coin, account);
16
- return app.getWalletAddress(walletPolicy, null, Number(change), Number(address), false);
15
+ let walletPolicy;
16
+ let hmac = null;
17
+ if (params.multisigData) {
18
+ walletPolicy = getMultisigWalletPolicy(fpr, xpub, purpose, coin, account, params.multisigData);
19
+ hmac = await registerWalletPolicy(walletPolicy);
20
+ }
21
+ else {
22
+ walletPolicy = getWalletPolicy(fpr, xpub, purpose, coin, account);
23
+ }
24
+ return app.getWalletAddress(walletPolicy, hmac, Number(change), Number(address), params.displayOnDevice ?? false);
17
25
  };
18
26
  const getXPub = async (params) => {
19
27
  return app.getExtendedPubkey(params.derivationPath);
@@ -28,19 +36,30 @@ async function createHandler(transport) {
28
36
  psbt.deserialize(psbtBuffer);
29
37
  const fpr = await app.getMasterFingerprint();
30
38
  const derivationPathToPublicKeyMap = Object.create(null);
39
+ const addressToDerivationPathMap = Object.create(null);
31
40
  for (const derivationPath of params.derivationPaths) {
32
- derivationPathToPublicKeyMap[derivationPath] = await getPublicKey({
41
+ if (params.multisigData) {
42
+ const address = await getAddress({
43
+ assetName: 'bitcoin',
44
+ derivationPath,
45
+ multisigData: params.multisigData,
46
+ });
47
+ addressToDerivationPathMap[address] = derivationPath;
48
+ }
49
+ const publicKey = await getPublicKey({
33
50
  assetName: 'bitcoin',
34
51
  derivationPath,
35
52
  });
53
+ derivationPathToPublicKeyMap[derivationPath] = publicKey;
36
54
  }
37
- tagPsbtWithDerivationPaths(psbt, fpr, derivationPathToPublicKeyMap);
55
+ tagPsbtWithDerivationPaths(psbt, fpr, derivationPathToPublicKeyMap, addressToDerivationPathMap);
38
56
  addDummyInputs(psbt);
39
57
  assertPsbtOnlyHasAllowedDerivationPaths(psbt, fpr, params.derivationPaths);
40
58
  const signatures = [];
41
- const walletPolicies = await derivationPathsToWalletPolicy(fpr, app, params.derivationPaths);
59
+ const walletPolicies = await derivationPathsToWalletPolicy(fpr, app, params.derivationPaths, params.multisigData);
42
60
  for (const walletPolicy of walletPolicies) {
43
- const _signatures = await app.signPsbt(psbt.serialize(), walletPolicy, null);
61
+ const hmac = params.multisigData ? await registerWalletPolicy(walletPolicy) : null;
62
+ const _signatures = await app.signPsbt(psbt.serialize(), walletPolicy, hmac);
44
63
  signatures.push(..._signatures);
45
64
  }
46
65
  const result = signatures.map(([inputIndex, partialSignature]) => ({
@@ -95,6 +114,18 @@ async function createHandler(transport) {
95
114
  }
96
115
  throw new Error('rawMessage or bip322Message must be defined');
97
116
  };
117
+ const registerWalletPolicy = async (walletPolicy) => {
118
+ const walletPolicies = (await walletPolicyAtom?.get()) ?? {};
119
+ const id = walletPolicy.getId().toString('hex');
120
+ let hmac = walletPolicies[id];
121
+ if (!hmac) {
122
+ const [, h] = await app.registerWallet(walletPolicy);
123
+ hmac = h;
124
+ const updatedPolicies = { ...walletPolicies, [id]: hmac };
125
+ await walletPolicyAtom?.set(updatedPolicies);
126
+ }
127
+ return hmac;
128
+ };
98
129
  return {
99
130
  getAddress,
100
131
  getPublicKey,
@@ -1,7 +1,7 @@
1
1
  import secp256k1 from '@exodus/secp256k1';
2
2
  import * as ethers from '@exodus/ethersproject-transactions';
3
3
  import AppEth, { ledgerService } from '@exodus/ledgerhq-hw-app-eth';
4
- import { TypedDataUtils, SignTypedDataVersion, } from '@metamask/eth-sig-util';
4
+ import { TypedDataUtils, SignTypedDataVersion } from '@metamask/eth-sig-util';
5
5
  import assert from 'minimalistic-assert';
6
6
  import { buildFauxXPUB } from './utils';
7
7
  import { RequiresBlindSigningError } from '../errors';
@@ -1,6 +1,7 @@
1
1
  import type Transport from '@ledgerhq/hw-transport';
2
2
  import type { HardwareWalletAssetHandler } from '@exodus/hw-common';
3
- type HandlerFactory = (transport: Transport) => Promise<HardwareWalletAssetHandler>;
3
+ import type { Atom } from '@exodus/atoms';
4
+ type HandlerFactory = (transport: Transport, walletPolicyAtom?: Atom<Record<string, Buffer>>) => Promise<HardwareWalletAssetHandler>;
4
5
  type AssetMetadata = {
5
6
  applications: {
6
7
  applicationName: string;
@@ -7,6 +7,7 @@ import applications from './applications';
7
7
  export const assetApplications = {
8
8
  basemainnet,
9
9
  bitcoin,
10
+ bitcoinregtest: bitcoin,
10
11
  matic,
11
12
  solana,
12
13
  ethereum,
@@ -1,6 +1,10 @@
1
- import { DefaultWalletPolicy, PsbtV2, WalletPolicy } from '@exodus/ledger-bitcoin';
1
+ import type { PsbtV2 } from '@exodus/ledger-bitcoin';
2
+ import { DefaultWalletPolicy, WalletPolicy } from '@exodus/ledger-bitcoin';
3
+ import type { MultisigData } from 'libraries/hw-common/lib';
2
4
  export declare function assertPsbtOnlyHasAllowedDerivationPaths(psbt: PsbtV2, masterFingerprint: string, derivationPaths: string[]): void;
3
- export declare function tagPsbtWithDerivationPaths(psbt: PsbtV2, masterFingerprint: string, derivationPathToPublicKeyMap: Record<string, Buffer>): void;
5
+ export declare function tagPsbtWithDerivationPaths(psbt: PsbtV2, masterFingerprint: string, derivationPathToPublicKeyMap: Record<string, Buffer>, addressToDerivationPathMap?: Record<string, string>): void;
4
6
  export declare const getWalletPolicy: (fpr: string, xpub: string, purpose: string, coin: string, account: string) => DefaultWalletPolicy;
5
- export declare function derivationPathsToWalletPolicy(fpr: string, app: any, derivationPaths: string[]): Promise<WalletPolicy[]>;
7
+ export declare const DUMMY_TAPROOT_XPUB = "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6QgnecKFpJFPpdzxKrwoaZoV44qAJewsc4kX9vGaCaBExuvJH57";
8
+ export declare const getMultisigWalletPolicy: (fpr: string, xpub: string, purpose: string, coin: string, account: string, multisigData: MultisigData) => WalletPolicy;
9
+ export declare function derivationPathsToWalletPolicy(fpr: string, app: any, derivationPaths: string[], multisigData?: MultisigData): Promise<WalletPolicy[]>;
6
10
  export declare function addDummyInputs(psbt: PsbtV2): void;
@@ -1,6 +1,6 @@
1
1
  import assert from 'minimalistic-assert';
2
- import { DefaultWalletPolicy, } from '@exodus/ledger-bitcoin';
3
- import { payments } from '@exodus/bitcoinjs-lib';
2
+ import { DefaultWalletPolicy, WalletPolicy } from '@exodus/ledger-bitcoin';
3
+ import { payments, address as baddress } from '@exodus/bitcoinjs-lib';
4
4
  import { buildBip44PathFromNumber, assertBip44PathNumber, splitBip44PathToNumber, splitBip44DerivationPath, } from './derivation-paths';
5
5
  export function assertPsbtOnlyHasAllowedDerivationPaths(psbt, masterFingerprint, derivationPaths) {
6
6
  for (let i = 0; i < psbt.getGlobalInputCount(); i++) {
@@ -31,14 +31,21 @@ function assertAllowedDerivation(bip32Derivation, masterFingerprint, derivationP
31
31
  assert(derivationPaths.includes(derivationPath), `found unsupported derivation path: ${derivationPath}`);
32
32
  }
33
33
  }
34
- export function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPathToPublicKeyMap) {
34
+ export function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPathToPublicKeyMap, addressToDerivationPathMap) {
35
35
  const masterFingerprintBuffer = Buffer.from(masterFingerprint, 'hex');
36
36
  const scriptPubKeyToDerivationPathMap = computeScriptPubKeyToDerivationPathMap(derivationPathToPublicKeyMap);
37
37
  for (let inputIndex = 0; inputIndex < psbt.getGlobalInputCount(); inputIndex++) {
38
38
  const witnessUtxo = psbt.getInputWitnessUtxo(inputIndex);
39
39
  assert(witnessUtxo, `witnessUtxo is currently the only supported type`);
40
40
  const scriptPubKey = witnessUtxo.scriptPubKey.toString('hex');
41
- const derivationPath = scriptPubKeyToDerivationPathMap[scriptPubKey];
41
+ let derivationPath = scriptPubKeyToDerivationPathMap[scriptPubKey];
42
+ if (addressToDerivationPathMap && !derivationPath) {
43
+ try {
44
+ const address = baddress.fromOutputScript(witnessUtxo.scriptPubKey);
45
+ derivationPath = addressToDerivationPathMap[address];
46
+ }
47
+ catch { }
48
+ }
42
49
  if (derivationPath) {
43
50
  const publicKey = derivationPathToPublicKeyMap[derivationPath];
44
51
  assert(Buffer.isBuffer(publicKey), `no public key found for derivation path`);
@@ -53,7 +60,14 @@ export function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPa
53
60
  }
54
61
  for (let outputIndex = 0; outputIndex < psbt.getGlobalOutputCount(); outputIndex++) {
55
62
  const scriptPubKey = psbt.getOutputScript(outputIndex);
56
- const derivationPath = scriptPubKeyToDerivationPathMap[scriptPubKey.toString('hex')];
63
+ let derivationPath = scriptPubKeyToDerivationPathMap[scriptPubKey.toString('hex')];
64
+ if (addressToDerivationPathMap && !derivationPath) {
65
+ try {
66
+ const address = baddress.fromOutputScript(scriptPubKey);
67
+ derivationPath = addressToDerivationPathMap[address];
68
+ }
69
+ catch { }
70
+ }
57
71
  if (derivationPath) {
58
72
  const publicKey = derivationPathToPublicKeyMap[derivationPath];
59
73
  assert(Buffer.isBuffer(publicKey), `no public key found for derivation path`);
@@ -104,7 +118,23 @@ export const getWalletPolicy = (fpr, xpub, purpose, coin, account) => {
104
118
  }[purpose];
105
119
  return new DefaultWalletPolicy(desc, `[${fpr}/${purpose}/${coin}/${account}]${xpub}`);
106
120
  };
107
- export async function derivationPathsToWalletPolicy(fpr, app, derivationPaths) {
121
+ export const DUMMY_TAPROOT_XPUB = 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6QgnecKFpJFPpdzxKrwoaZoV44qAJewsc4kX9vGaCaBExuvJH57';
122
+ export const getMultisigWalletPolicy = (fpr, xpub, purpose, coin, account, multisigData) => {
123
+ let template = `tr(@0/**,sortedmulti_a(${multisigData.threshold}`;
124
+ const keys = [DUMMY_TAPROOT_XPUB];
125
+ multisigData.xpubs.forEach((xpub2, i) => {
126
+ if (xpub === xpub2) {
127
+ keys.push(`[${fpr}/${purpose}/${coin}/${account}]${xpub}`);
128
+ }
129
+ else {
130
+ keys.push(xpub2);
131
+ }
132
+ template += `,@${i + 1}/**`;
133
+ });
134
+ template += '))';
135
+ return new WalletPolicy('Multisig', template, keys);
136
+ };
137
+ export async function derivationPathsToWalletPolicy(fpr, app, derivationPaths, multisigData) {
108
138
  const splittedDerivationPaths = derivationPaths.map(splitBip44DerivationPath);
109
139
  const dedupedPaths = Object.values(splittedDerivationPaths.reduce((prev, splittedDerivationPath) => {
110
140
  const [purpose, coin, account] = splittedDerivationPath;
@@ -115,7 +145,12 @@ export async function derivationPathsToWalletPolicy(fpr, app, derivationPaths) {
115
145
  for (const dedupedPath of dedupedPaths) {
116
146
  const [purpose, coin, account] = dedupedPath;
117
147
  const xpub = await app.getExtendedPubkey(`m/${purpose}/${coin}/${account}`);
118
- walletPolicies.push(getWalletPolicy(fpr, xpub, purpose, coin, account));
148
+ if (multisigData) {
149
+ walletPolicies.push(getMultisigWalletPolicy(fpr, xpub, purpose, coin, account, multisigData));
150
+ }
151
+ else {
152
+ walletPolicies.push(getWalletPolicy(fpr, xpub, purpose, coin, account));
153
+ }
119
154
  }
120
155
  return walletPolicies;
121
156
  }
@@ -1,13 +1,15 @@
1
1
  import type { GetAddressParams, GetPublicKeyParams, GetXPubParams, HardwareWalletDevice, SignMessageParams, SignTransactionParams } from '@exodus/hw-common';
2
2
  import type { TransportFactory } from './types';
3
+ import type { Atom } from '@exodus/atoms';
3
4
  export type Descriptor = unknown;
4
5
  export type Dependencies = {
5
6
  transportFactory: TransportFactory;
6
7
  descriptor: Descriptor;
8
+ walletPolicyAtom: Atom<Record<string, Buffer>>;
7
9
  };
8
10
  export declare class LedgerDevice implements HardwareWalletDevice {
9
11
  #private;
10
- constructor({ transportFactory, descriptor }: Dependencies);
12
+ constructor({ transportFactory, descriptor, walletPolicyAtom }: Dependencies);
11
13
  ensureApplicationIsOpened: (baseAssetName: string) => Promise<void>;
12
14
  listSupportedAssetNames: () => Promise<string[]>;
13
15
  listInstalledAssetNames: () => Promise<string[]>;
@@ -6,9 +6,11 @@ import { UnsupportedVersionError, ApplicationNotFoundError } from './errors';
6
6
  export class LedgerDevice {
7
7
  #transportFactory;
8
8
  #descriptor;
9
- constructor({ transportFactory, descriptor }) {
9
+ #walletPolicyAtom;
10
+ constructor({ transportFactory, descriptor, walletPolicyAtom }) {
10
11
  this.#transportFactory = transportFactory;
11
12
  this.#descriptor = descriptor;
13
+ this.#walletPolicyAtom = walletPolicyAtom;
12
14
  }
13
15
  #runInSession = async (operation, expectErrorWhenClosing = false) => {
14
16
  const transport = await this.#transportFactory.open(this.#descriptor);
@@ -119,7 +121,7 @@ export class LedgerDevice {
119
121
  getAddress = async (params) => {
120
122
  await this.ensureApplicationIsOpened(params.assetName);
121
123
  return this.#runInSession(async (transport) => {
122
- const handler = await this.#getAssetApplication(params.assetName).handler(transport);
124
+ const handler = await this.#getAssetApplication(params.assetName).handler(transport, this.#walletPolicyAtom);
123
125
  return handler.getAddress(params);
124
126
  });
125
127
  };
@@ -140,7 +142,7 @@ export class LedgerDevice {
140
142
  signTransaction = async (params) => {
141
143
  await this.ensureApplicationIsOpened(params.assetName);
142
144
  return this.#runInSession(async (transport) => {
143
- const handler = await this.#getAssetApplication(params.assetName).handler(transport);
145
+ const handler = await this.#getAssetApplication(params.assetName).handler(transport, this.#walletPolicyAtom);
144
146
  return handler.signTransaction(params);
145
147
  });
146
148
  };
@@ -1,4 +1,4 @@
1
- import { Logger } from '../shared/types';
1
+ import type { Logger } from '../shared/types';
2
2
  import type { Atom } from '@exodus/atoms';
3
3
  import type { HardwareWalletDescriptor, HardwareWalletDiscovery } from '@exodus/hw-common';
4
4
  import type { HwLedgerConfig, TransportFactories } from './types';
@@ -9,10 +9,11 @@ export type Dependencies = {
9
9
  transportsFactories: TransportFactories;
10
10
  bluetoothStatusAtom: Atom<BluetoothStatus>;
11
11
  bluetoothScanningAtom: Atom<boolean>;
12
+ walletPolicyAtom: Atom<Record<string, Buffer>>;
12
13
  };
13
14
  export declare class LedgerDiscovery implements HardwareWalletDiscovery {
14
15
  #private;
15
- constructor({ config, logger, transportsFactories, bluetoothStatusAtom, bluetoothScanningAtom, }: Dependencies);
16
+ constructor({ config, logger, transportsFactories, bluetoothStatusAtom, bluetoothScanningAtom, walletPolicyAtom, }: Dependencies);
16
17
  start: () => void;
17
18
  scan: () => Promise<void>;
18
19
  stopScan: (clearDevices?: boolean) => void;
@@ -24,7 +25,7 @@ declare const _default: {
24
25
  readonly id: "ledgerDiscovery";
25
26
  readonly type: "module";
26
27
  readonly factory: (deps: Dependencies) => LedgerDiscovery;
27
- readonly dependencies: readonly ["config", "logger", "transportsFactories", "bluetoothStatusAtom", "bluetoothScanningAtom"];
28
+ readonly dependencies: readonly ["config", "logger", "transportsFactories", "bluetoothStatusAtom", "bluetoothScanningAtom", "walletPolicyAtom"];
28
29
  readonly public: true;
29
30
  };
30
31
  export default _default;
@@ -11,11 +11,13 @@ export class LedgerDiscovery {
11
11
  #bluetoothStatusAtom;
12
12
  #scannerBluetooth;
13
13
  #bluetoothScanningAtom;
14
+ #walletPolicyAtom;
14
15
  #discoveredBluetoothDevices = Object.create(null);
15
- constructor({ config, logger, transportsFactories, bluetoothStatusAtom, bluetoothScanningAtom, }) {
16
+ constructor({ config, logger, transportsFactories, bluetoothStatusAtom, bluetoothScanningAtom, walletPolicyAtom, }) {
16
17
  this.#logger = logger;
17
18
  this.#bluetoothStatusAtom = bluetoothStatusAtom;
18
19
  this.#bluetoothScanningAtom = bluetoothScanningAtom;
20
+ this.#walletPolicyAtom = walletPolicyAtom;
19
21
  if (!(typeof transportsFactories === 'object' &&
20
22
  Object.keys(transportsFactories).length > 0 &&
21
23
  Object.entries(transportsFactories).every(([transportName, transportFactory]) => ['usb', 'bluetooth', 'tcp'].includes(transportName) &&
@@ -101,7 +103,11 @@ export class LedgerDiscovery {
101
103
  manufacturer: 'ledger',
102
104
  transport: 'usb',
103
105
  model: deviceModel?.id ?? 'unknown',
104
- get: async () => new LedgerDevice({ transportFactory, descriptor: hidDevice }),
106
+ get: async () => new LedgerDevice({
107
+ transportFactory,
108
+ descriptor: hidDevice,
109
+ walletPolicyAtom: this.#walletPolicyAtom,
110
+ }),
105
111
  };
106
112
  });
107
113
  descriptors.push(...usbDeviceList);
@@ -115,7 +121,11 @@ export class LedgerDiscovery {
115
121
  manufacturer: 'ledger',
116
122
  transport: 'bluetooth',
117
123
  model: deviceModel?.id ?? 'unknown',
118
- get: async () => new LedgerDevice({ transportFactory, descriptor: bluetoothDevice }),
124
+ get: async () => new LedgerDevice({
125
+ transportFactory,
126
+ descriptor: bluetoothDevice,
127
+ walletPolicyAtom: this.#walletPolicyAtom,
128
+ }),
119
129
  };
120
130
  });
121
131
  descriptors.push(...bluetoothDeviceList);
@@ -129,6 +139,7 @@ export class LedgerDiscovery {
129
139
  get: async () => new LedgerDevice({
130
140
  transportFactory,
131
141
  descriptor: { apduPort: APDU_PORT },
142
+ walletPolicyAtom: this.#walletPolicyAtom,
132
143
  }),
133
144
  });
134
145
  break;
@@ -160,6 +171,7 @@ export default {
160
171
  'transportsFactories',
161
172
  'bluetoothStatusAtom',
162
173
  'bluetoothScanningAtom',
174
+ 'walletPolicyAtom',
163
175
  ],
164
176
  public: true,
165
177
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/hw-ledger",
3
- "version": "2.9.5",
3
+ "version": "2.10.0",
4
4
  "description": "The ledger module",
5
5
  "author": "Exodus Movement, Inc.",
6
6
  "repository": {
@@ -25,7 +25,7 @@
25
25
  "test": "run -T jest --testMatch='**/*.unit.test.js' --coverageDirectory coverage/unit",
26
26
  "zemu:install": "docker pull zondax/builder-zemu:speculos-745fe46f81cfc18114b94a37beaefb58a09c0fcd",
27
27
  "test:integration": "yarn zemu:install && run -T jest --runInBand",
28
- "lint": "run -T eslint . --ignore-path ../../.gitignore",
28
+ "lint": "run -T eslint .",
29
29
  "lint:fix": "yarn lint --fix",
30
30
  "prepublishOnly": "yarn run -T build --scope @exodus/hw-ledger"
31
31
  },
@@ -34,7 +34,7 @@
34
34
  "@exodus/bip322-js": "^1.1.0-exodus.4",
35
35
  "@exodus/bitcoinjs-lib": "^6.1.5-exodus.0",
36
36
  "@exodus/ethersproject-transactions": "^5.4.2-exodus.0",
37
- "@exodus/hw-common": "^2.1.0",
37
+ "@exodus/hw-common": "^2.4.0",
38
38
  "@exodus/ledger-bitcoin": "^0.2.3-exodus.3",
39
39
  "@exodus/ledgerhq-devices": "^8.1.0-exodus.3",
40
40
  "@exodus/ledgerhq-hw-app-eth": "^6.33.7-exodus.8",
@@ -61,6 +61,7 @@
61
61
  "@types/jest-when": "^3.5.2",
62
62
  "@types/minimalistic-assert": "^1.0.1",
63
63
  "@types/secp256k1": "^4.0.3",
64
+ "@types/semver": "^7.3.5",
64
65
  "@zondax/zemu": "^0.43.1",
65
66
  "bitcoinjs-lib": "^6.1.3",
66
67
  "concurrently": "^7.6.0",
@@ -71,5 +72,5 @@
71
72
  "tiny-secp256k1": "^2.2.3",
72
73
  "ts-jest": "^29.0.3"
73
74
  },
74
- "gitHead": "6133e25d4d50f7737703294bdbb0699af419c0a7"
75
+ "gitHead": "d035797666e173e9cec145ddce8e137fe84dfb83"
75
76
  }