diff --git a/packages/hw-ledger/package.json b/packages/hw-ledger/package.json index 42cfb842a..bbe5a3a2d 100644 --- a/packages/hw-ledger/package.json +++ b/packages/hw-ledger/package.json @@ -22,7 +22,7 @@ "dependencies": { "@polkadot/hw-ledger-transports": "13.4.4", "@polkadot/util": "13.4.4", - "@zondax/ledger-substrate": "1.0.0", + "@zondax/ledger-substrate": "1.1.1", "tslib": "^2.8.0" } } diff --git a/packages/hw-ledger/src/LedgerGeneric.ts b/packages/hw-ledger/src/LedgerGeneric.ts index 1f0636eb4..2955abfff 100644 --- a/packages/hw-ledger/src/LedgerGeneric.ts +++ b/packages/hw-ledger/src/LedgerGeneric.ts @@ -46,8 +46,8 @@ async function wrapError (promise: Promise): Promis return result; } -/** @internal Wraps a sign/signRaw call and returns the associated signature */ -function sign (method: 'sign' | 'signRaw', message: Uint8Array, slip44: number, accountIndex = 0, addressOffset = 0): (app: PolkadotGenericApp) => Promise { +/** @internal Wraps a signEd25519/signRawEd25519 call and returns the associated signature */ +function sign (method: 'signEd25519' | 'signRawEd25519', message: Uint8Array, slip44: number, accountIndex = 0, addressOffset = 0): (app: PolkadotGenericApp) => Promise { const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`; return async (app: PolkadotGenericApp): Promise => { @@ -59,7 +59,22 @@ function sign (method: 'sign' | 'signRaw', message: Uint8Array, slip44: number, }; } -/** @internal Wraps a signWithMetadata call and returns the associated signature */ +/** @internal Wraps a signEcdsa/signRawEcdsa call and returns the associated signature */ +function signEcdsa (method: 'signEcdsa' | 'signRawEcdsa', message: Uint8Array, slip44: number, accountIndex = 0, addressOffset = 0): (app: PolkadotGenericApp) => Promise { + const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`; + + return async (app: PolkadotGenericApp): Promise => { + const { r, s, v } = await wrapError(app[method](bip42Path, u8aToBuffer(message))); + + const signature = Buffer.concat([r, s, v]); + + return { + signature: hexAddPrefix(signature.toString('hex')) + }; + }; +} + +/** @internal Wraps a signWithMetadataEd25519 call and returns the associated signature */ function signWithMetadata (message: Uint8Array, slip44: number, accountIndex = 0, addressOffset = 0, { metadata }: Partial = {}): (app: PolkadotGenericApp) => Promise { const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`; @@ -70,7 +85,28 @@ function signWithMetadata (message: Uint8Array, slip44: number, accountIndex = 0 const bufferMsg = Buffer.from(message); - const { signature } = await wrapError(app.signWithMetadata(bip42Path, bufferMsg, metadata)); + const { signature } = await wrapError(app.signWithMetadataEd25519(bip42Path, bufferMsg, metadata)); + + return { + signature: hexAddPrefix(signature.toString('hex')) + }; + }; +} + +/** @internal Wraps a signWithMetadataEcdsa call and returns the associated signature */ +function signWithMetadataEcdsa (message: Uint8Array, slip44: number, accountIndex = 0, addressOffset = 0, { metadata }: Partial = {}): (app: PolkadotGenericApp) => Promise { + const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`; + + return async (app: PolkadotGenericApp): Promise => { + if (!metadata) { + throw new Error('The metadata option must be present when using signWithMetadata'); + } + + const bufferMsg = Buffer.from(message); + + const { r, s, v } = await wrapError(app.signWithMetadataEcdsa(bip42Path, bufferMsg, metadata)); + + const signature = Buffer.concat([r, s, v]); return { signature: hexAddPrefix(signature.toString('hex')) @@ -119,14 +155,31 @@ export class LedgerGeneric { } /** - * @description Returns the address associated with a specific account & address offset. Optionally + * @description Returns the address associated with a specific Ed25519 account & address offset. Optionally * asks for on-device confirmation */ public async getAddress (ss58Prefix: number, confirm = false, accountIndex = 0, addressOffset = 0): Promise { const bip42Path = `m/44'/${this.#slip44}'/${accountIndex}'/${0}'/${addressOffset}'`; return this.withApp(async (app: PolkadotGenericApp): Promise => { - const { address, pubKey } = await wrapError(app.getAddress(bip42Path, ss58Prefix, confirm)); + const { address, pubKey } = await wrapError(app.getAddressEd25519(bip42Path, ss58Prefix, confirm)); + + return { + address, + publicKey: hexAddPrefix(pubKey) + }; + }); + } + + /** + * @description Returns the address associated with a specific ecdsa account & address offset. Optionally + * asks for on-device confirmation + */ + public async getAddressEcdsa (confirm = false, accountIndex = 0, addressOffset = 0) { + const bip42Path = `m/44'/${this.#slip44}'/${accountIndex}'/${0}'/${addressOffset}'`; + + return this.withApp(async (app: PolkadotGenericApp): Promise => { + const { address, pubKey } = await wrapError(app.getAddressEcdsa(bip42Path, confirm)); return { address, @@ -154,14 +207,28 @@ export class LedgerGeneric { * @description Signs a transaction on the Ledger device. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl` */ public async sign (message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise { - return this.withApp(sign('sign', message, this.#slip44, accountIndex, addressOffset)); + return this.withApp(sign('signEd25519', message, this.#slip44, accountIndex, addressOffset)); } /** * @description Signs a message (non-transactional) on the Ledger device */ public async signRaw (message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise { - return this.withApp(sign('signRaw', u8aWrapBytes(message), this.#slip44, accountIndex, addressOffset)); + return this.withApp(sign('signRawEd25519', u8aWrapBytes(message), this.#slip44, accountIndex, addressOffset)); + } + + /** + * @description Signs a transaction on the Ledger device with Ecdsa. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl` + */ + public async signEcdsa (message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise { + return this.withApp(signEcdsa('signEcdsa', u8aWrapBytes(message), this.#slip44, accountIndex, addressOffset)); + } + + /** + * @description Signs a message with Ecdsa (non-transactional) on the Ledger device + */ + public async signRawEcdsa (message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise { + return this.withApp(signEcdsa('signRawEcdsa', u8aWrapBytes(message), this.#slip44, accountIndex, addressOffset)); } /** @@ -171,6 +238,13 @@ export class LedgerGeneric { return this.withApp(signWithMetadata(message, this.#slip44, accountIndex, addressOffset, options)); } + /** + * @description Signs a transaction on the ledger device for an ecdsa signature provided some metadata. + */ + public async signWithMetadataEcdsa (message: Uint8Array, accountIndex?: number, addressOffset?: number, options?: Partial) { + return this.withApp(signWithMetadataEcdsa(message, this.#slip44, accountIndex, addressOffset, options)); + } + /** * @internal * diff --git a/yarn.lock b/yarn.lock index 3576a8821..ba0d5d249 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1207,7 +1207,7 @@ __metadata: languageName: node linkType: hard -"@ledgerhq/devices@npm:^8.3.0, @ledgerhq/devices@npm:^8.4.2, @ledgerhq/devices@npm:^8.4.4": +"@ledgerhq/devices@npm:^8.4.4": version: 8.4.4 resolution: "@ledgerhq/devices@npm:8.4.4" dependencies: @@ -1219,7 +1219,7 @@ __metadata: languageName: node linkType: hard -"@ledgerhq/errors@npm:^6.16.4, @ledgerhq/errors@npm:^6.18.0, @ledgerhq/errors@npm:^6.19.1": +"@ledgerhq/errors@npm:^6.19.1": version: 6.19.1 resolution: "@ledgerhq/errors@npm:6.19.1" checksum: 10/8265c6d73c314a4aabbe060ec29e2feebb4e904fe811bf7a9c53cde08e713dcbceded9d927ebb2f0ffc47a7b16524379d4a7e9aa3d61945b8a832be7cd5cf69b @@ -1278,31 +1278,7 @@ __metadata: languageName: node linkType: hard -"@ledgerhq/hw-transport@npm:6.30.6": - version: 6.30.6 - resolution: "@ledgerhq/hw-transport@npm:6.30.6" - dependencies: - "@ledgerhq/devices": "npm:^8.3.0" - "@ledgerhq/errors": "npm:^6.16.4" - "@ledgerhq/logs": "npm:^6.12.0" - events: "npm:^3.3.0" - checksum: 10/4fc71409e1ff906e479f2e45c386a9db2d062271908a86d09a59587652d485b80200a5335e7e9dbaf5264c0af4b8e6c36d24e7db921b10f4cc420b51e9ca3c00 - languageName: node - linkType: hard - -"@ledgerhq/hw-transport@npm:6.31.2": - version: 6.31.2 - resolution: "@ledgerhq/hw-transport@npm:6.31.2" - dependencies: - "@ledgerhq/devices": "npm:^8.4.2" - "@ledgerhq/errors": "npm:^6.18.0" - "@ledgerhq/logs": "npm:^6.12.0" - events: "npm:^3.3.0" - checksum: 10/b712b0c5a409d8bca254daa16b2867110132d44382dfb758e4ab0d710656d85c6b3fd9e42565ec9959db9a7f57b430d04d9db5556fb64727d7dc0a8e7a92d165 - languageName: node - linkType: hard - -"@ledgerhq/hw-transport@npm:^6.31.4": +"@ledgerhq/hw-transport@npm:6.31.4, @ledgerhq/hw-transport@npm:^6.31.4": version: 6.31.4 resolution: "@ledgerhq/hw-transport@npm:6.31.4" dependencies: @@ -1620,7 +1596,7 @@ __metadata: dependencies: "@polkadot/hw-ledger-transports": "npm:13.4.4" "@polkadot/util": "npm:13.4.4" - "@zondax/ledger-substrate": "npm:1.0.0" + "@zondax/ledger-substrate": "npm:1.1.1" tslib: "npm:^2.8.0" languageName: unknown linkType: soft @@ -3213,23 +3189,23 @@ __metadata: languageName: node linkType: hard -"@zondax/ledger-js@npm:^0.11.0": - version: 0.11.0 - resolution: "@zondax/ledger-js@npm:0.11.0" +"@zondax/ledger-js@npm:^1.2.0": + version: 1.2.0 + resolution: "@zondax/ledger-js@npm:1.2.0" dependencies: - "@ledgerhq/hw-transport": "npm:6.30.6" - checksum: 10/52a5e2aa66db1554365d733b3d38f286a0bbb192e1a2911c526f44f058a2e6c1fc6e0ca67a6dc824bb89ce694bd4554c39809d0290141de97675bb48677c3985 + "@ledgerhq/hw-transport": "npm:6.31.4" + checksum: 10/5852b340efd421f96d4e52d0a93d4e8464604c070939dd42fade5a495010a08d730b03e1b7ab3ff0f26f13075d8a0a5226a748a41986f2ed087fca4471f24e4e languageName: node linkType: hard -"@zondax/ledger-substrate@npm:1.0.0": - version: 1.0.0 - resolution: "@zondax/ledger-substrate@npm:1.0.0" +"@zondax/ledger-substrate@npm:1.1.1": + version: 1.1.1 + resolution: "@zondax/ledger-substrate@npm:1.1.1" dependencies: - "@ledgerhq/hw-transport": "npm:6.31.2" - "@zondax/ledger-js": "npm:^0.11.0" - axios: "npm:^1.7.4" - checksum: 10/5324da85746c160dd2400286c38ff0f90fae0147ad7e275b382b20b50acdee99c57941366531dc663931da5cb41144770888e3c6250b3f632b097d8bb7c7182f + "@ledgerhq/hw-transport": "npm:6.31.4" + "@zondax/ledger-js": "npm:^1.2.0" + axios: "npm:^1.8.4" + checksum: 10/039ffef55b31870f82c6b0f20b518089ad9ce0295d695f880640cb586256adacd4a326c10157ccaf82e897abde7358f9e4e02c069dac672ec90881e21d250722 languageName: node linkType: hard @@ -3771,14 +3747,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.7.4": - version: 1.7.7 - resolution: "axios@npm:1.7.7" +"axios@npm:^1.8.4": + version: 1.9.0 + resolution: "axios@npm:1.9.0" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 10/7f875ea13b9298cd7b40fd09985209f7a38d38321f1118c701520939de2f113c4ba137832fe8e3f811f99a38e12c8225481011023209a77b0c0641270e20cde1 + checksum: 10/a2f90bba56820883879f32a237e2b9ff25c250365dcafd41cec41b3406a3df334a148f90010182dfdadb4b41dc59f6f0b3e8898ff41b666d1157b5f3f4523497 languageName: node linkType: hard