From db88528921289164bd2547fdf208ff9223e4e97a Mon Sep 17 00:00:00 2001 From: willclarktech Date: Thu, 1 Oct 2020 13:26:35 +0200 Subject: [PATCH 01/11] launchpad-ledger: Pass transport as argument --- .../launchpad-ledger/src/launchpadledger.ts | 137 +++--------------- packages/launchpad-ledger/src/ledgersigner.ts | 5 +- .../types/launchpadledger.d.ts | 17 +-- .../launchpad-ledger/types/ledgersigner.d.ts | 4 +- 4 files changed, 32 insertions(+), 131 deletions(-) diff --git a/packages/launchpad-ledger/src/launchpadledger.ts b/packages/launchpad-ledger/src/launchpadledger.ts index fd773ec5..0d296a0f 100644 --- a/packages/launchpad-ledger/src/launchpadledger.ts +++ b/packages/launchpad-ledger/src/launchpadledger.ts @@ -2,7 +2,7 @@ import { HdPath, Secp256k1Signature } from "@cosmjs/crypto"; import { fromUtf8 } from "@cosmjs/encoding"; import { makeCosmoshubPath } from "@cosmjs/launchpad"; import { assert } from "@cosmjs/utils"; -import Transport from "@ledgerhq/hw-transport"; +import LedgerTransport from "@ledgerhq/hw-transport"; import CosmosApp, { AppInfoResponse, PublicKeyResponse, @@ -18,37 +18,13 @@ export interface LedgerAppErrorResponse { } /* eslint-enable */ -interface ConnectedApp { - /** The transport used by the app */ - readonly transport: Transport; - readonly app: CosmosApp; -} - -/** Time to establish a connection in milliseconds */ -const defaultOpenTimeout = 120_000; -const requiredCosmosAppVersion = "1.5.3"; - -function isWindows(platform: string): boolean { - return platform.indexOf("Win") > -1; -} - -function verifyBrowserIsSupported(platform: string, userAgent: string | null): void { - if (isWindows(platform)) { - throw new Error("Windows is not currently supported."); - } - - const isChromeOrBrave = userAgent && /chrome|crios/i.test(userAgent) && !/edge|opr\//i.test(userAgent); - if (!isChromeOrBrave) { - throw new Error("Your browser does not support Ledger devices."); - } -} - function unharden(hdPath: HdPath): number[] { return hdPath.map((n) => (n.isHardened() ? n.toNumber() - 2 ** 31 : n.toNumber())); } const cosmosHdPath = makeCosmoshubPath(0); const cosmosBech32Prefix = "cosmos"; +const requiredCosmosAppVersion = "1.5.3"; export interface LaunchpadLedgerOptions { readonly hdPaths?: readonly HdPath[]; @@ -60,11 +36,10 @@ export class LaunchpadLedger { private readonly testModeAllowed: boolean; private readonly hdPaths: readonly HdPath[]; private readonly prefix: string; - private connectedApp: ConnectedApp | null; - public readonly platform: string; - public readonly userAgent: string | null; + private readonly transport: LedgerTransport; + private app: CosmosApp | null; - public constructor(options: LaunchpadLedgerOptions = {}) { + public constructor(transport: LedgerTransport, options: LaunchpadLedgerOptions = {}) { const defaultOptions = { hdPaths: [cosmosHdPath], prefix: cosmosBech32Prefix, @@ -77,22 +52,15 @@ export class LaunchpadLedger { this.testModeAllowed = testModeAllowed; this.hdPaths = hdPaths; this.prefix = prefix; - this.connectedApp = null; - - try { - this.platform = navigator.platform; - this.userAgent = navigator.userAgent; - } catch (error) { - this.platform = "node"; - this.userAgent = null; - } + this.transport = transport; + this.app = new CosmosApp(transport); } public async getCosmosAppVersion(): Promise { - await this.ensureConnected(); - assert(this.connectedApp, "Cosmos Ledger App is not connected"); + await this.verifyCosmosAppIsOpen(); + assert(this.app, "Cosmos Ledger App is not connected"); - const response = await this.connectedApp.app.getVersion(); + const response = await this.app.getVersion(); this.handleLedgerErrors(response); // eslint-disable-next-line @typescript-eslint/naming-convention const { major, minor, patch, test_mode: testMode } = response as VersionResponse; @@ -101,12 +69,12 @@ export class LaunchpadLedger { } public async getPubkey(hdPath?: HdPath): Promise { - await this.ensureConnected(); - assert(this.connectedApp, "Cosmos Ledger App is not connected"); + await this.verifyDeviceIsReady(); + assert(this.app, "Cosmos Ledger App is not connected"); const hdPathToUse = hdPath || this.hdPaths[0]; // ledger-cosmos-js hardens the first three indices - const response = await this.connectedApp.app.publicKey(unharden(hdPathToUse)); + const response = await this.app.publicKey(unharden(hdPathToUse)); this.handleLedgerErrors(response); return Uint8Array.from((response as PublicKeyResponse).compressed_pk); } @@ -125,82 +93,20 @@ export class LaunchpadLedger { } public async sign(message: Uint8Array, hdPath?: HdPath): Promise { - await this.ensureConnected(); - assert(this.connectedApp, "Cosmos Ledger App is not connected"); + await this.verifyDeviceIsReady(); + assert(this.app, "Cosmos Ledger App is not connected"); const hdPathToUse = hdPath || this.hdPaths[0]; // ledger-cosmos-js hardens the first three indices - const response = await this.connectedApp.app.sign(unharden(hdPathToUse), fromUtf8(message)); + const response = await this.app.sign(unharden(hdPathToUse), fromUtf8(message)); this.handleLedgerErrors(response, "Transaction signing request was rejected by the user"); return Secp256k1Signature.fromDer((response as SignResponse).signature).toFixedLength(); } public async disconnect(): Promise { - if (this.connectedApp) { - await this.connectedApp.transport.close(); - this.connectedApp = null; - } - } - - private async ensureConnected(): Promise { - // assume good connection if connected once - if (this.connectedApp) { - return; - } - - if (this.platform !== "node") { - verifyBrowserIsSupported(this.platform, this.userAgent); - } - - const transport = await this.createTransport(defaultOpenTimeout); - this.connectedApp = { - transport: transport, - app: new CosmosApp(transport), - }; - - await this.verifyDeviceIsReady(); - } - - /** - * @param openTimeout The time to establish a connection in milliseconds. This is - * [passed into as the second argument into Transport.open](https://github.com/LedgerHQ/ledgerjs/blob/v5.25.2/packages/hw-transport/src/Transport.js#L235), - * which is ignored by both [TransportWebUSB.open](https://github.com/LedgerHQ/ledgerjs/blob/v5.25.2/packages/hw-transport-webusb/src/TransportWebUSB.js#L116) - * and [TransportNodeHid.open](https://github.com/LedgerHQ/ledgerjs/blob/v5.25.2/packages/hw-transport-node-hid/src/TransportNodeHid.js#L115). - */ - private async createTransport(openTimeout: number): Promise { - // HACK: Use a variable to get webpack to ignore this - const nodeJsTransportPackageName = "@ledgerhq/hw-transport-node-hid"; - /* eslint-disable-next-line @typescript-eslint/naming-convention */ - const { default: TransportClass } = - this.platform === "node" - ? await import(nodeJsTransportPackageName) - : await import("@ledgerhq/hw-transport-webusb"); - - try { - const transport = await TransportClass.create(openTimeout); - return transport; - } catch (error) { - const trimmedErrorMessage = error.message.trim(); - if (trimmedErrorMessage.startsWith("No WebUSB interface found for your Ledger device")) { - throw new Error( - "Could not connect to a Ledger device. Please use Ledger Live to upgrade the Ledger firmware to version 1.5.5 or later.", - ); - } - if (trimmedErrorMessage.startsWith("Unable to claim interface")) { - throw new Error("Could not access Ledger device. Is it being used in another tab?"); - } - if (trimmedErrorMessage.startsWith("Not supported")) { - throw new Error( - "Your browser does not seem to support WebUSB yet. Try updating it to the latest version.", - ); - } - if (trimmedErrorMessage.startsWith("No device selected")) { - throw new Error( - "You did not select a Ledger device. If you did not see your Ledger, check if the Ledger is plugged in and unlocked.", - ); - } - - throw error; + if (this.app) { + await this.transport.close(); + this.app = null; } } @@ -211,10 +117,9 @@ export class LaunchpadLedger { } private async getOpenAppName(): Promise { - await this.ensureConnected(); - assert(this.connectedApp, "Cosmos Ledger App is not connected"); + assert(this.app, "Cosmos Ledger App is not connected"); - const response = await this.connectedApp.app.appInfo(); + const response = await this.app.appInfo(); this.handleLedgerErrors(response); return (response as AppInfoResponse).appName; } diff --git a/packages/launchpad-ledger/src/ledgersigner.ts b/packages/launchpad-ledger/src/ledgersigner.ts index 8c863165..6e548c07 100644 --- a/packages/launchpad-ledger/src/ledgersigner.ts +++ b/packages/launchpad-ledger/src/ledgersigner.ts @@ -7,6 +7,7 @@ import { StdSignDoc, } from "@cosmjs/launchpad"; import { serializeSignDoc, SignResponse } from "@cosmjs/launchpad"; +import LedgerTransport from "@ledgerhq/hw-transport"; import { LaunchpadLedger, LaunchpadLedgerOptions } from "./launchpadledger"; @@ -15,9 +16,9 @@ export class LedgerSigner implements OfflineSigner { private readonly hdPaths: readonly HdPath[]; private accounts?: readonly AccountData[]; - public constructor(options: LaunchpadLedgerOptions = {}) { + public constructor(transport: LedgerTransport, options: LaunchpadLedgerOptions = {}) { this.hdPaths = options.hdPaths || [makeCosmoshubPath(0)]; - this.ledger = new LaunchpadLedger(options); + this.ledger = new LaunchpadLedger(transport, options); } public async getAccounts(): Promise { diff --git a/packages/launchpad-ledger/types/launchpadledger.d.ts b/packages/launchpad-ledger/types/launchpadledger.d.ts index 25443745..e2bb37d5 100644 --- a/packages/launchpad-ledger/types/launchpadledger.d.ts +++ b/packages/launchpad-ledger/types/launchpadledger.d.ts @@ -1,4 +1,6 @@ +/// import { HdPath } from "@cosmjs/crypto"; +import LedgerTransport from "@ledgerhq/hw-transport"; export interface LedgerAppErrorResponse { readonly error_message?: string; readonly device_locked?: boolean; @@ -12,24 +14,15 @@ export declare class LaunchpadLedger { private readonly testModeAllowed; private readonly hdPaths; private readonly prefix; - private connectedApp; - readonly platform: string; - readonly userAgent: string | null; - constructor(options?: LaunchpadLedgerOptions); + private readonly transport; + private app; + constructor(transport: LedgerTransport, options?: LaunchpadLedgerOptions); getCosmosAppVersion(): Promise; getPubkey(hdPath?: HdPath): Promise; getPubkeys(): Promise; getCosmosAddress(pubkey?: Uint8Array): Promise; sign(message: Uint8Array, hdPath?: HdPath): Promise; disconnect(): Promise; - private ensureConnected; - /** - * @param openTimeout The time to establish a connection in milliseconds. This is - * [passed into as the second argument into Transport.open](https://github.com/LedgerHQ/ledgerjs/blob/v5.25.2/packages/hw-transport/src/Transport.js#L235), - * which is ignored by both [TransportWebUSB.open](https://github.com/LedgerHQ/ledgerjs/blob/v5.25.2/packages/hw-transport-webusb/src/TransportWebUSB.js#L116) - * and [TransportNodeHid.open](https://github.com/LedgerHQ/ledgerjs/blob/v5.25.2/packages/hw-transport-node-hid/src/TransportNodeHid.js#L115). - */ - private createTransport; private verifyAppMode; private getOpenAppName; private verifyAppVersion; diff --git a/packages/launchpad-ledger/types/ledgersigner.d.ts b/packages/launchpad-ledger/types/ledgersigner.d.ts index 8a81c649..63792bea 100644 --- a/packages/launchpad-ledger/types/ledgersigner.d.ts +++ b/packages/launchpad-ledger/types/ledgersigner.d.ts @@ -1,11 +1,13 @@ +/// import { AccountData, OfflineSigner, StdSignDoc } from "@cosmjs/launchpad"; import { SignResponse } from "@cosmjs/launchpad"; +import LedgerTransport from "@ledgerhq/hw-transport"; import { LaunchpadLedgerOptions } from "./launchpadledger"; export declare class LedgerSigner implements OfflineSigner { private readonly ledger; private readonly hdPaths; private accounts?; - constructor(options?: LaunchpadLedgerOptions); + constructor(transport: LedgerTransport, options?: LaunchpadLedgerOptions); getAccounts(): Promise; sign(signerAddress: string, signDoc: StdSignDoc): Promise; disconnect(): Promise; From 3ed2380c7c0734bac7088a6bed1be4d0052dee98 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Thu, 1 Oct 2020 13:27:04 +0200 Subject: [PATCH 02/11] launchpad-ledger: Update tests for transport argument --- .../launchpad-ledger/src/ledgersigner.spec.ts | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/launchpad-ledger/src/ledgersigner.spec.ts b/packages/launchpad-ledger/src/ledgersigner.spec.ts index 9ab4addf..09fce517 100644 --- a/packages/launchpad-ledger/src/ledgersigner.spec.ts +++ b/packages/launchpad-ledger/src/ledgersigner.spec.ts @@ -12,12 +12,29 @@ import { StdFee, } from "@cosmjs/launchpad"; import { assert, sleep } from "@cosmjs/utils"; +import LedgerTransport from "@ledgerhq/hw-transport"; import { LedgerSigner } from "./ledgersigner"; import { pendingWithoutLedger, pendingWithoutWasmd, wasmd } from "./testutils.spec"; const interactiveTimeout = 120_000; +async function createLedgerTransport(): Promise { + let platform: string; + try { + platform = navigator.platform; + } catch (error) { + platform = "node"; + } + // HACK: Use a variable to get webpack to ignore this + const nodeJsTransportPackageName = "@ledgerhq/hw-transport-node-hid"; + const { default: TransportClass } = + platform === "node" + ? await import(nodeJsTransportPackageName) + : await import("@ledgerhq/hw-transport-webusb"); + return TransportClass.create(interactiveTimeout, interactiveTimeout); +} + describe("LedgerSigner", () => { const defaultChainId = "testing"; const defaultFee: StdFee = { @@ -32,7 +49,8 @@ describe("LedgerSigner", () => { describe("getAccount", () => { it("works", async () => { pendingWithoutLedger(); - const signer = new LedgerSigner({ + const ledgerTransport = await createLedgerTransport(); + const signer = new LedgerSigner(ledgerTransport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], }); @@ -71,7 +89,8 @@ describe("LedgerSigner", () => { "returns valid signature", async () => { pendingWithoutLedger(); - const signer = new LedgerSigner({ + const ledgerTransport = await createLedgerTransport(); + const signer = new LedgerSigner(ledgerTransport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], }); @@ -115,7 +134,8 @@ describe("LedgerSigner", () => { async () => { pendingWithoutLedger(); pendingWithoutWasmd(); - const signer = new LedgerSigner({ + const ledgerTransport = await createLedgerTransport(); + const signer = new LedgerSigner(ledgerTransport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], }); From 610411bb5fb01e6a2d286c11aa8990434b63c166 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Thu, 1 Oct 2020 13:27:21 +0200 Subject: [PATCH 03/11] launchpad-ledger: Update demos for transport argument --- packages/launchpad-ledger/demo/index.html | 4 +-- packages/launchpad-ledger/demo/node.js | 8 +++--- packages/launchpad-ledger/src/demo/node.ts | 18 +++++++++---- packages/launchpad-ledger/src/demo/web.ts | 31 +++++++++++++++++----- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/packages/launchpad-ledger/demo/index.html b/packages/launchpad-ledger/demo/index.html index 7da23c11..bb483690 100644 --- a/packages/launchpad-ledger/demo/index.html +++ b/packages/launchpad-ledger/demo/index.html @@ -19,7 +19,7 @@
-
@@ -38,7 +38,7 @@
-
diff --git a/packages/launchpad-ledger/demo/node.js b/packages/launchpad-ledger/demo/node.js index 86c7e904..6d9fe3a0 100644 --- a/packages/launchpad-ledger/demo/node.js +++ b/packages/launchpad-ledger/demo/node.js @@ -1,14 +1,16 @@ const demo = require("../build/demo/node"); async function run() { + const signer = await demo.createSigner(); + const accountNumbers = [0, 1, 2, 10]; - const accounts = await demo.getAccounts(); + const accounts = await demo.getAccounts(signer); console.info("Accounts from Ledger device:"); console.table(accounts.map((account, i) => ({ ...account, accountNumber: accountNumbers[i] }))); const accountNumber0 = 0; const address0 = accounts[accountNumber0].address; - const signature0 = await demo.sign(accountNumber0, address0, address0); + const signature0 = await demo.sign(signer, accountNumber0, address0, address0); console.info(`Signature from Ledger device for account number 0 (${address0}):`); console.info(signature0); @@ -17,7 +19,7 @@ async function run() { const accountNumber10 = 10; const address10 = accounts[accountNumbers.findIndex((n) => n === accountNumber10)].address; - const signature1 = await demo.sign(accountNumber10, address10, address10); + const signature1 = await demo.sign(signer, accountNumber10, address10, address10); console.info(`Signature from Ledger device for account number 10 (${address10}):`); console.info(signature1); } diff --git a/packages/launchpad-ledger/src/demo/node.ts b/packages/launchpad-ledger/src/demo/node.ts index f90e45e4..2b98a716 100644 --- a/packages/launchpad-ledger/src/demo/node.ts +++ b/packages/launchpad-ledger/src/demo/node.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { toBase64 } from "@cosmjs/encoding"; import { makeCosmoshubPath, makeSignDoc, StdFee, StdSignature } from "@cosmjs/launchpad"; +import LedgerTransport from "@ledgerhq/hw-transport-node-hid"; import { LedgerSigner } from "../ledgersigner"; @@ -12,12 +13,18 @@ const defaultFee: StdFee = { const defaultMemo = "Some memo"; const defaultSequence = "0"; -const signer = new LedgerSigner({ - testModeAllowed: true, - hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(2), makeCosmoshubPath(10)], -}); +export async function createSigner(): Promise { + const interactiveTimeout = 120_000; + const ledgerTransport = await LedgerTransport.create(interactiveTimeout, interactiveTimeout); + return new LedgerSigner(ledgerTransport, { + testModeAllowed: true, + hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(2), makeCosmoshubPath(10)], + }); +} -export async function getAccounts(): Promise< +export async function getAccounts( + signer: LedgerSigner, +): Promise< ReadonlyArray<{ readonly algo: string; readonly address: string; @@ -29,6 +36,7 @@ export async function getAccounts(): Promise< } export async function sign( + signer: LedgerSigner, accountNumber: number, fromAddress: string, toAddress: string, diff --git a/packages/launchpad-ledger/src/demo/web.ts b/packages/launchpad-ledger/src/demo/web.ts index c9297c47..1fa9cf3b 100644 --- a/packages/launchpad-ledger/src/demo/web.ts +++ b/packages/launchpad-ledger/src/demo/web.ts @@ -2,6 +2,7 @@ import { toBase64 } from "@cosmjs/encoding"; import { AccountData, makeCosmoshubPath, StdSignDoc } from "@cosmjs/launchpad"; import { Uint53 } from "@cosmjs/math"; import { assert } from "@cosmjs/utils"; +import LedgerTransport from "@ledgerhq/hw-transport-webusb"; import { LedgerSigner } from "../ledgersigner"; @@ -43,11 +44,6 @@ function createSignDoc(accountNumber: number, address: string): string { return JSON.stringify(signDoc, null, 2); } -const signer = new LedgerSigner({ - testModeAllowed: true, - hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(2)], -}); - window.updateMessage = (accountNumberInput: unknown) => { assert(typeof accountNumberInput === "string"); const accountNumber = Uint53.fromString(accountNumberInput).toNumber(); @@ -63,7 +59,20 @@ window.updateMessage = (accountNumberInput: unknown) => { signDocTextArea.textContent = createSignDoc(accountNumber, address); }; -window.getAccounts = async function getAccounts(): Promise { +window.createSigner = async function createSigner(): Promise { + const interactiveTimeout = 120_000; + const ledgerTransport = await LedgerTransport.create(interactiveTimeout, interactiveTimeout); + return new LedgerSigner(ledgerTransport, { + testModeAllowed: true, + hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(2)], + }); +}; + +window.getAccounts = async function getAccounts(signer: LedgerSigner | undefined): Promise { + if (signer === undefined) { + console.error("Please wait for transport to connect"); + return; + } const accountNumberInput = document.getElementById("account-number"); const addressInput = document.getElementById("address"); const accountsDiv = document.getElementById("accounts"); @@ -88,7 +97,11 @@ window.getAccounts = async function getAccounts(): Promise { } }; -window.sign = async function sign(): Promise { +window.sign = async function sign(signer: LedgerSigner | undefined): Promise { + if (signer === undefined) { + console.error("Please wait for transport to connect"); + return; + } const signatureDiv = document.getElementById("signature"); signatureDiv.textContent = "Loading..."; @@ -102,3 +115,7 @@ window.sign = async function sign(): Promise { signatureDiv.textContent = error; } }; + +window.onload = async function onLoad(): Promise { + window.signer = await window.createSigner(); +}; From 974ed65c92ddeab2c1da611d67879d874659571d Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 6 Oct 2020 11:41:20 +0200 Subject: [PATCH 04/11] launchpad-ledger: Remove @ledgerhq optionalDependencies --- packages/launchpad-ledger/package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/launchpad-ledger/package.json b/packages/launchpad-ledger/package.json index 022644b0..af3eb986 100644 --- a/packages/launchpad-ledger/package.json +++ b/packages/launchpad-ledger/package.json @@ -47,10 +47,6 @@ "ledger-cosmos-js": "^2.1.7", "semver": "^7.3.2" }, - "optionalDependencies": { - "@ledgerhq/hw-transport-node-hid": "^5.23.2", - "@ledgerhq/hw-transport-webusb": "^5.23.0" - }, "devDependencies": { "@ledgerhq/hw-transport-node-hid": "^5.23.2", "@ledgerhq/hw-transport-webusb": "^5.23.0", From a8c325ba62063da1a8d2007deb3470ceae4558b5 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 6 Oct 2020 11:46:06 +0200 Subject: [PATCH 05/11] launchpad-ledger: Remove disconnect method --- packages/launchpad-ledger/src/launchpadledger.ts | 11 +---------- packages/launchpad-ledger/src/ledgersigner.spec.ts | 6 ------ packages/launchpad-ledger/src/ledgersigner.ts | 4 ---- packages/launchpad-ledger/types/launchpadledger.d.ts | 4 +--- packages/launchpad-ledger/types/ledgersigner.d.ts | 1 - 5 files changed, 2 insertions(+), 24 deletions(-) diff --git a/packages/launchpad-ledger/src/launchpadledger.ts b/packages/launchpad-ledger/src/launchpadledger.ts index 0d296a0f..994c7800 100644 --- a/packages/launchpad-ledger/src/launchpadledger.ts +++ b/packages/launchpad-ledger/src/launchpadledger.ts @@ -36,8 +36,7 @@ export class LaunchpadLedger { private readonly testModeAllowed: boolean; private readonly hdPaths: readonly HdPath[]; private readonly prefix: string; - private readonly transport: LedgerTransport; - private app: CosmosApp | null; + private readonly app: CosmosApp | null; public constructor(transport: LedgerTransport, options: LaunchpadLedgerOptions = {}) { const defaultOptions = { @@ -52,7 +51,6 @@ export class LaunchpadLedger { this.testModeAllowed = testModeAllowed; this.hdPaths = hdPaths; this.prefix = prefix; - this.transport = transport; this.app = new CosmosApp(transport); } @@ -103,13 +101,6 @@ export class LaunchpadLedger { return Secp256k1Signature.fromDer((response as SignResponse).signature).toFixedLength(); } - public async disconnect(): Promise { - if (this.app) { - await this.transport.close(); - this.app = null; - } - } - private verifyAppMode(testMode: boolean): void { if (testMode && !this.testModeAllowed) { throw new Error(`DANGER: The Cosmos Ledger app is in test mode and should not be used on mainnet!`); diff --git a/packages/launchpad-ledger/src/ledgersigner.spec.ts b/packages/launchpad-ledger/src/ledgersigner.spec.ts index 09fce517..38f96e64 100644 --- a/packages/launchpad-ledger/src/ledgersigner.spec.ts +++ b/packages/launchpad-ledger/src/ledgersigner.spec.ts @@ -74,8 +74,6 @@ describe("LedgerSigner", () => { pubkey: fromBase64("A2ZnLEcbpyjS30H5UF1vezq29aBcT9oo5EARATIW9Cpj"), }, ]); - - await signer.disconnect(); }); }); @@ -123,8 +121,6 @@ describe("LedgerSigner", () => { fistAccount.pubkey, ); expect(valid).toEqual(true); - - await signer.disconnect(); }, interactiveTimeout, ); @@ -144,8 +140,6 @@ describe("LedgerSigner", () => { const client = new SigningCosmosClient(wasmd.endpoint, fistAccount.address, signer); const result = await client.sendTokens(defaultRecipient, coins(1234567, "ucosm")); assert(isBroadcastTxSuccess(result)); - - await signer.disconnect(); }, interactiveTimeout, ); diff --git a/packages/launchpad-ledger/src/ledgersigner.ts b/packages/launchpad-ledger/src/ledgersigner.ts index 6e548c07..7f74b9c0 100644 --- a/packages/launchpad-ledger/src/ledgersigner.ts +++ b/packages/launchpad-ledger/src/ledgersigner.ts @@ -53,8 +53,4 @@ export class LedgerSigner implements OfflineSigner { signature: encodeSecp256k1Signature(accountForAddress.pubkey, signature), }; } - - public async disconnect(): Promise { - return this.ledger.disconnect(); - } } diff --git a/packages/launchpad-ledger/types/launchpadledger.d.ts b/packages/launchpad-ledger/types/launchpadledger.d.ts index e2bb37d5..514eb9d2 100644 --- a/packages/launchpad-ledger/types/launchpadledger.d.ts +++ b/packages/launchpad-ledger/types/launchpadledger.d.ts @@ -14,15 +14,13 @@ export declare class LaunchpadLedger { private readonly testModeAllowed; private readonly hdPaths; private readonly prefix; - private readonly transport; - private app; + private readonly app; constructor(transport: LedgerTransport, options?: LaunchpadLedgerOptions); getCosmosAppVersion(): Promise; getPubkey(hdPath?: HdPath): Promise; getPubkeys(): Promise; getCosmosAddress(pubkey?: Uint8Array): Promise; sign(message: Uint8Array, hdPath?: HdPath): Promise; - disconnect(): Promise; private verifyAppMode; private getOpenAppName; private verifyAppVersion; diff --git a/packages/launchpad-ledger/types/ledgersigner.d.ts b/packages/launchpad-ledger/types/ledgersigner.d.ts index 63792bea..22f1302f 100644 --- a/packages/launchpad-ledger/types/ledgersigner.d.ts +++ b/packages/launchpad-ledger/types/ledgersigner.d.ts @@ -10,5 +10,4 @@ export declare class LedgerSigner implements OfflineSigner { constructor(transport: LedgerTransport, options?: LaunchpadLedgerOptions); getAccounts(): Promise; sign(signerAddress: string, signDoc: StdSignDoc): Promise; - disconnect(): Promise; } From 49ed3194c3ca6d10bd52abd0d1564fc4c72bb9b7 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 6 Oct 2020 11:51:00 +0200 Subject: [PATCH 06/11] launchpad-ledger: Align Ledger transport class names --- packages/launchpad-ledger/src/demo/node.ts | 4 ++-- packages/launchpad-ledger/src/demo/web.ts | 4 ++-- packages/launchpad-ledger/src/launchpadledger.ts | 6 +++--- packages/launchpad-ledger/types/launchpadledger.d.ts | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/launchpad-ledger/src/demo/node.ts b/packages/launchpad-ledger/src/demo/node.ts index 2b98a716..015a2bde 100644 --- a/packages/launchpad-ledger/src/demo/node.ts +++ b/packages/launchpad-ledger/src/demo/node.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { toBase64 } from "@cosmjs/encoding"; import { makeCosmoshubPath, makeSignDoc, StdFee, StdSignature } from "@cosmjs/launchpad"; -import LedgerTransport from "@ledgerhq/hw-transport-node-hid"; +import TransportNodeHid from "@ledgerhq/hw-transport-node-hid"; import { LedgerSigner } from "../ledgersigner"; @@ -15,7 +15,7 @@ const defaultSequence = "0"; export async function createSigner(): Promise { const interactiveTimeout = 120_000; - const ledgerTransport = await LedgerTransport.create(interactiveTimeout, interactiveTimeout); + const ledgerTransport = await TransportNodeHid.create(interactiveTimeout, interactiveTimeout); return new LedgerSigner(ledgerTransport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(2), makeCosmoshubPath(10)], diff --git a/packages/launchpad-ledger/src/demo/web.ts b/packages/launchpad-ledger/src/demo/web.ts index 1fa9cf3b..cc217945 100644 --- a/packages/launchpad-ledger/src/demo/web.ts +++ b/packages/launchpad-ledger/src/demo/web.ts @@ -2,7 +2,7 @@ import { toBase64 } from "@cosmjs/encoding"; import { AccountData, makeCosmoshubPath, StdSignDoc } from "@cosmjs/launchpad"; import { Uint53 } from "@cosmjs/math"; import { assert } from "@cosmjs/utils"; -import LedgerTransport from "@ledgerhq/hw-transport-webusb"; +import TransportWebUSB from "@ledgerhq/hw-transport-webusb"; import { LedgerSigner } from "../ledgersigner"; @@ -61,7 +61,7 @@ window.updateMessage = (accountNumberInput: unknown) => { window.createSigner = async function createSigner(): Promise { const interactiveTimeout = 120_000; - const ledgerTransport = await LedgerTransport.create(interactiveTimeout, interactiveTimeout); + const ledgerTransport = await TransportWebUSB.create(interactiveTimeout, interactiveTimeout); return new LedgerSigner(ledgerTransport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(2)], diff --git a/packages/launchpad-ledger/src/launchpadledger.ts b/packages/launchpad-ledger/src/launchpadledger.ts index 994c7800..a3f42e27 100644 --- a/packages/launchpad-ledger/src/launchpadledger.ts +++ b/packages/launchpad-ledger/src/launchpadledger.ts @@ -2,7 +2,7 @@ import { HdPath, Secp256k1Signature } from "@cosmjs/crypto"; import { fromUtf8 } from "@cosmjs/encoding"; import { makeCosmoshubPath } from "@cosmjs/launchpad"; import { assert } from "@cosmjs/utils"; -import LedgerTransport from "@ledgerhq/hw-transport"; +import Transport from "@ledgerhq/hw-transport"; import CosmosApp, { AppInfoResponse, PublicKeyResponse, @@ -36,9 +36,9 @@ export class LaunchpadLedger { private readonly testModeAllowed: boolean; private readonly hdPaths: readonly HdPath[]; private readonly prefix: string; - private readonly app: CosmosApp | null; + private readonly app: CosmosApp; - public constructor(transport: LedgerTransport, options: LaunchpadLedgerOptions = {}) { + public constructor(transport: Transport, options: LaunchpadLedgerOptions = {}) { const defaultOptions = { hdPaths: [cosmosHdPath], prefix: cosmosBech32Prefix, diff --git a/packages/launchpad-ledger/types/launchpadledger.d.ts b/packages/launchpad-ledger/types/launchpadledger.d.ts index 514eb9d2..525d297a 100644 --- a/packages/launchpad-ledger/types/launchpadledger.d.ts +++ b/packages/launchpad-ledger/types/launchpadledger.d.ts @@ -1,6 +1,6 @@ /// import { HdPath } from "@cosmjs/crypto"; -import LedgerTransport from "@ledgerhq/hw-transport"; +import Transport from "@ledgerhq/hw-transport"; export interface LedgerAppErrorResponse { readonly error_message?: string; readonly device_locked?: boolean; @@ -15,7 +15,7 @@ export declare class LaunchpadLedger { private readonly hdPaths; private readonly prefix; private readonly app; - constructor(transport: LedgerTransport, options?: LaunchpadLedgerOptions); + constructor(transport: Transport, options?: LaunchpadLedgerOptions); getCosmosAppVersion(): Promise; getPubkey(hdPath?: HdPath): Promise; getPubkeys(): Promise; From 46d84455ec1bc2f579ebfaae55e8fb60338abda0 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 6 Oct 2020 12:21:42 +0200 Subject: [PATCH 07/11] launchpad-ledger: Fix tests --- packages/launchpad-ledger/src/ledgersigner.spec.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/launchpad-ledger/src/ledgersigner.spec.ts b/packages/launchpad-ledger/src/ledgersigner.spec.ts index 38f96e64..3ce47eea 100644 --- a/packages/launchpad-ledger/src/ledgersigner.spec.ts +++ b/packages/launchpad-ledger/src/ledgersigner.spec.ts @@ -45,11 +45,19 @@ describe("LedgerSigner", () => { const defaultSequence = "0"; const defaultAccountNumber = "42"; const defaultRecipient = "cosmos1p6xs63q4g7np99ttv5nd3yzkt8n4qxa47w8aea"; + let ledgerTransport: LedgerTransport; + + beforeEach(async () => { + ledgerTransport = await createLedgerTransport(); + }); + + afterEach(async () => { + await ledgerTransport.close(); + }); describe("getAccount", () => { it("works", async () => { pendingWithoutLedger(); - const ledgerTransport = await createLedgerTransport(); const signer = new LedgerSigner(ledgerTransport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], @@ -87,7 +95,6 @@ describe("LedgerSigner", () => { "returns valid signature", async () => { pendingWithoutLedger(); - const ledgerTransport = await createLedgerTransport(); const signer = new LedgerSigner(ledgerTransport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], @@ -130,7 +137,6 @@ describe("LedgerSigner", () => { async () => { pendingWithoutLedger(); pendingWithoutWasmd(); - const ledgerTransport = await createLedgerTransport(); const signer = new LedgerSigner(ledgerTransport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], From 00e3701234d876dc9e50bdcc7a1ddb1cb7b0a4ca Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 6 Oct 2020 12:33:53 +0200 Subject: [PATCH 08/11] launchpad-ledger: Update README for transport restructure --- packages/launchpad-ledger/README.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/launchpad-ledger/README.md b/packages/launchpad-ledger/README.md index b1c736ad..71c35023 100644 --- a/packages/launchpad-ledger/README.md +++ b/packages/launchpad-ledger/README.md @@ -4,25 +4,16 @@ ## Supported platforms -This library works with Node.js as well as certain browsers. We use the +This library must be provided with a Ledger transport, and has been tested with +appropriate transports for Node.js as well as certain browsers. In our demo code +we use +[@ledgerhq/hw-transport-node-hid](https://github.com/LedgerHQ/ledgerjs/tree/master/packages/hw-transport-node-hid) +to connect to Ledger devices from Node.js. We use the [@ledgerhq/hw-transport-webusb](https://github.com/LedgerHQ/ledgerjs/tree/master/packages/hw-transport-webusb) library to connect to Ledger devices from the browser via USB. You can check the support status of this library [here](https://github.com/LedgerHQ/ledgerjs/tree/master/packages/hw-transport-webusb#support-status). -Note the optional dependencies: - -```json -"optionalDependencies": { - "@ledgerhq/hw-transport-node-hid": "^5.23.2", - "@ledgerhq/hw-transport-webusb": "^5.23.0" -} -``` - -If you are using this library with Node.js you must install -`@ledgerhq/hw-transport-node-hid`. You’ll need `@ledgerhq/hw-transport-webusb` -for the browser. - ## Running the demo ### Node.js From aead09686c5f657e3bb45a9f27644a9028745c4b Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 6 Oct 2020 14:32:49 +0200 Subject: [PATCH 09/11] root: Install libusb on CI --- .circleci/config.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 141c4db7..b1d12e77 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -41,6 +41,9 @@ jobs: name: Restore Yarn Package Cache keys: - yarn-packages-{{ checksum "yarn.lock" }} + - run: + name: Install libusb + command: sudo apt-get install libusb-1.0-0-dev - run: name: Install Dependencies command: yarn install --frozen-lockfile @@ -111,6 +114,11 @@ jobs: name: Restore Yarn Package Cache keys: - yarn-packages-{{ checksum "yarn.lock" }} + - run: + name: Install libusb + command: | + wget -O "$HOME/libusb.deb" http://de.archive.ubuntu.com/ubuntu/pool/main/libu/libusb-1.0/libusb-1.0-0-dev_1.0.20-1_amd64.deb + sudo dpkg -i "$HOME/libusb.deb" - run: name: Install Dependencies command: yarn install --frozen-lockfile @@ -214,6 +222,11 @@ jobs: name: Restore Yarn Package Cache keys: - yarn-packages-{{ checksum "yarn.lock" }} + - run: + name: Install libusb + command: | + wget -O "$HOME/libusb.deb" http://de.archive.ubuntu.com/ubuntu/pool/main/libu/libusb-1.0/libusb-1.0-0-dev_1.0.20-1_amd64.deb + sudo dpkg -i "$HOME/libusb.deb" - run: name: Install Dependencies command: yarn install --frozen-lockfile @@ -298,6 +311,11 @@ jobs: name: Restore Yarn Package Cache keys: - yarn-packages-{{ checksum "yarn.lock" }} + - run: + name: Install libusb + command: | + wget -O "$HOME/libusb.deb" http://de.archive.ubuntu.com/ubuntu/pool/main/libu/libusb-1.0/libusb-1.0-0-dev_1.0.20-1_amd64.deb + sudo dpkg -i "$HOME/libusb.deb" - run: name: Install Dependencies command: yarn install --frozen-lockfile @@ -344,6 +362,9 @@ jobs: name: Restore Yarn Package Cache keys: - yarn-packages-{{ checksum "yarn.lock" }} + - run: + name: Install libusb + command: sudo apt-get install libusb-1.0-0-dev - run: name: Install Dependencies command: yarn install --frozen-lockfile @@ -391,6 +412,9 @@ jobs: name: Restore Yarn Package Cache keys: - yarn-packages-{{ checksum "yarn.lock" }} + - run: + name: Install libusb + command: sudo apt-get install libusb-1.0-0-dev - run: name: Install Dependencies command: yarn install --frozen-lockfile From 73bc1ba22acc85526d8de5fbdd32396fba0e94a9 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 6 Oct 2020 16:50:38 +0200 Subject: [PATCH 10/11] launchpad-ledger: Finish aligning Ledger transport names --- .../launchpad-ledger/src/ledgersigner.spec.ts | 16 ++++++++-------- packages/launchpad-ledger/src/ledgersigner.ts | 4 ++-- .../launchpad-ledger/types/ledgersigner.d.ts | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/launchpad-ledger/src/ledgersigner.spec.ts b/packages/launchpad-ledger/src/ledgersigner.spec.ts index 3ce47eea..a1e3a995 100644 --- a/packages/launchpad-ledger/src/ledgersigner.spec.ts +++ b/packages/launchpad-ledger/src/ledgersigner.spec.ts @@ -12,14 +12,14 @@ import { StdFee, } from "@cosmjs/launchpad"; import { assert, sleep } from "@cosmjs/utils"; -import LedgerTransport from "@ledgerhq/hw-transport"; +import Transport from "@ledgerhq/hw-transport"; import { LedgerSigner } from "./ledgersigner"; import { pendingWithoutLedger, pendingWithoutWasmd, wasmd } from "./testutils.spec"; const interactiveTimeout = 120_000; -async function createLedgerTransport(): Promise { +async function createTransport(): Promise { let platform: string; try { platform = navigator.platform; @@ -45,20 +45,20 @@ describe("LedgerSigner", () => { const defaultSequence = "0"; const defaultAccountNumber = "42"; const defaultRecipient = "cosmos1p6xs63q4g7np99ttv5nd3yzkt8n4qxa47w8aea"; - let ledgerTransport: LedgerTransport; + let transport: Transport; beforeEach(async () => { - ledgerTransport = await createLedgerTransport(); + transport = await createTransport(); }); afterEach(async () => { - await ledgerTransport.close(); + await transport.close(); }); describe("getAccount", () => { it("works", async () => { pendingWithoutLedger(); - const signer = new LedgerSigner(ledgerTransport, { + const signer = new LedgerSigner(transport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], }); @@ -95,7 +95,7 @@ describe("LedgerSigner", () => { "returns valid signature", async () => { pendingWithoutLedger(); - const signer = new LedgerSigner(ledgerTransport, { + const signer = new LedgerSigner(transport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], }); @@ -137,7 +137,7 @@ describe("LedgerSigner", () => { async () => { pendingWithoutLedger(); pendingWithoutWasmd(); - const signer = new LedgerSigner(ledgerTransport, { + const signer = new LedgerSigner(transport, { testModeAllowed: true, hdPaths: [makeCosmoshubPath(0), makeCosmoshubPath(1), makeCosmoshubPath(10)], }); diff --git a/packages/launchpad-ledger/src/ledgersigner.ts b/packages/launchpad-ledger/src/ledgersigner.ts index 7f74b9c0..f8ba9f32 100644 --- a/packages/launchpad-ledger/src/ledgersigner.ts +++ b/packages/launchpad-ledger/src/ledgersigner.ts @@ -7,7 +7,7 @@ import { StdSignDoc, } from "@cosmjs/launchpad"; import { serializeSignDoc, SignResponse } from "@cosmjs/launchpad"; -import LedgerTransport from "@ledgerhq/hw-transport"; +import Transport from "@ledgerhq/hw-transport"; import { LaunchpadLedger, LaunchpadLedgerOptions } from "./launchpadledger"; @@ -16,7 +16,7 @@ export class LedgerSigner implements OfflineSigner { private readonly hdPaths: readonly HdPath[]; private accounts?: readonly AccountData[]; - public constructor(transport: LedgerTransport, options: LaunchpadLedgerOptions = {}) { + public constructor(transport: Transport, options: LaunchpadLedgerOptions = {}) { this.hdPaths = options.hdPaths || [makeCosmoshubPath(0)]; this.ledger = new LaunchpadLedger(transport, options); } diff --git a/packages/launchpad-ledger/types/ledgersigner.d.ts b/packages/launchpad-ledger/types/ledgersigner.d.ts index 22f1302f..9c2c6c5d 100644 --- a/packages/launchpad-ledger/types/ledgersigner.d.ts +++ b/packages/launchpad-ledger/types/ledgersigner.d.ts @@ -1,13 +1,13 @@ /// import { AccountData, OfflineSigner, StdSignDoc } from "@cosmjs/launchpad"; import { SignResponse } from "@cosmjs/launchpad"; -import LedgerTransport from "@ledgerhq/hw-transport"; +import Transport from "@ledgerhq/hw-transport"; import { LaunchpadLedgerOptions } from "./launchpadledger"; export declare class LedgerSigner implements OfflineSigner { private readonly ledger; private readonly hdPaths; private accounts?; - constructor(transport: LedgerTransport, options?: LaunchpadLedgerOptions); + constructor(transport: Transport, options?: LaunchpadLedgerOptions); getAccounts(): Promise; sign(signerAddress: string, signDoc: StdSignDoc): Promise; } From 033a9339dc605a2364590cfe41525b449b585572 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 6 Oct 2020 17:05:08 +0200 Subject: [PATCH 11/11] launchpad-ledger: Add missing @ledgerhq/hw-transport devDependency --- packages/launchpad-ledger/package.json | 1 + yarn.lock | 28 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/packages/launchpad-ledger/package.json b/packages/launchpad-ledger/package.json index af3eb986..3dee1e4c 100644 --- a/packages/launchpad-ledger/package.json +++ b/packages/launchpad-ledger/package.json @@ -48,6 +48,7 @@ "semver": "^7.3.2" }, "devDependencies": { + "@ledgerhq/hw-transport": "^5.25.0", "@ledgerhq/hw-transport-node-hid": "^5.23.2", "@ledgerhq/hw-transport-webusb": "^5.23.0", "@types/ledgerhq__hw-transport-node-hid": "^4.22.1", diff --git a/yarn.lock b/yarn.lock index 083e63cf..fe82d263 100644 --- a/yarn.lock +++ b/yarn.lock @@ -315,6 +315,15 @@ "@ledgerhq/logs" "^5.23.0" rxjs "^6.6.3" +"@ledgerhq/devices@^5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.25.0.tgz#c9522d7495e7be41fad59eb7d5e4e3e1030fd205" + integrity sha512-3wsxVDkUYd5ERA5KVy99wEGbHAkfsuWbQ8b2ruzr8JX9wIxUS8mu1XkdoDt5M+H4jXP9C8ZGj9YT3VsiiIzfxg== + dependencies: + "@ledgerhq/errors" "^5.25.0" + "@ledgerhq/logs" "^5.25.0" + rxjs "^6.6.3" + "@ledgerhq/errors@^4.78.0": version "4.78.0" resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-4.78.0.tgz#23daf3af54d03b1bda3e616002b555da1bdb705a" @@ -325,6 +334,11 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.23.0.tgz#30a0338dafba8264556011604abed08bf24979f3" integrity sha512-qtpX8aFrUUlYfOMu7BxTvxqUa8CniE+tEBpVEjYUhVbFdVJjM4ouwJD++RtQkMAU2c5jE7xb12WnUnf5BlAgLQ== +"@ledgerhq/errors@^5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.25.0.tgz#2a24b7ad6a88719046de4fcdf0b4c27b9ba79523" + integrity sha512-+FyyweA9odaWRwRkS35Wf0n2gC4tGsBlgW6VMhT7m1kcwVzUqNFyQzqMKqYvYEAga0P0X59wE+IAlqokkG7Usg== + "@ledgerhq/hw-transport-node-hid-noevents@^5.23.2": version "5.23.2" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-5.23.2.tgz#0ee4b54c62d23b0f0cce258fe2c612f71b8d454a" @@ -378,6 +392,15 @@ "@ledgerhq/errors" "^5.23.0" events "^3.2.0" +"@ledgerhq/hw-transport@^5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.25.0.tgz#e04e2130fedcb433ee68f25125e6ac49efa0aede" + integrity sha512-q6hhWWwbSZPmzdTaQMowY+uQYwCC4xRqRQFQFgF6BjZFn2n+AwGOEU9mDmHnjL6XxkQfj8CjWuPJSRRv5OLmlg== + dependencies: + "@ledgerhq/devices" "^5.25.0" + "@ledgerhq/errors" "^5.25.0" + events "^3.2.0" + "@ledgerhq/logs@^4.72.0": version "4.72.0" resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-4.72.0.tgz#43df23af013ad1135407e5cf33ca6e4c4c7708d5" @@ -388,6 +411,11 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.23.0.tgz#7a86b1e6479c8aa8e8b9affe00eb8e369efdbc3b" integrity sha512-88M8RkVHl44k6MAhfrYhx25opnJV24/2XpuTUVklID11f9rBdE+6RZ9OMs39dyX2sDv7TuzIPi5nTRoCqZMDYw== +"@ledgerhq/logs@^5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.25.0.tgz#94dd930a33fd05e3897532f554e31397a45247b6" + integrity sha512-OPlkvufjwJWQR+Jp7C6GaEeub+ZHzh3x0xyQMVLL62O7VGrhpzjwq2il/aLNt687k7mKJ+Vg6lFL1B6gO1ZiIg== + "@lerna/add@3.21.0": version "3.21.0" resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.21.0.tgz#27007bde71cc7b0a2969ab3c2f0ae41578b4577b"