diff --git a/bun.lockb b/bun.lockb index afbfed6..756881b 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index e848a36..a9966be 100644 --- a/package.json +++ b/package.json @@ -33,12 +33,12 @@ "format:check": "FORCE_COLOR=1 prettier --check .", "lint": "eslint .", "lint:fix": "eslint --fix .", - "test": "yarn build && ts-jest", + "test": "yarn build && jest .", "upgrade": "bunx npm-check-updates -i" }, "dependencies": { "@ledgerhq/hw-transport": "6.30.6", - "@zondax/ledger-js": "^0.8.0", + "@zondax/ledger-js": "^0.8.1", "axios": "^1.6.8" }, "devDependencies": { diff --git a/src/common.ts b/src/common.ts index 5bc6c9a..20ec7e2 100644 --- a/src/common.ts +++ b/src/common.ts @@ -17,6 +17,10 @@ import type Transport from '@ledgerhq/hw-transport' * limitations under the License. ******************************************************************************* */ +export type TransactionMetadataBlob = Buffer +export type TransactionBlob = Buffer +export type SS58Prefix = number + /** * @deprecated Moved to @zondax/ledger-js */ diff --git a/src/generic_app.ts b/src/generic_app.ts index 5486f7a..4125cc2 100644 --- a/src/generic_app.ts +++ b/src/generic_app.ts @@ -1,6 +1,5 @@ /** ****************************************************************************** - * (c) 2019 - 2022 Zondax AG - * (c) 2016-2017 Ledger + * (c) 2019 - 2024 Zondax AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +16,18 @@ import axios from 'axios' import type Transport from '@ledgerhq/hw-transport' -import BaseApp, { INSGeneric, LedgerError, numbersToBip32Path, processErrorResponse, processResponse } from '@zondax/ledger-js' +import BaseApp, { BIP32Path, INSGeneric, LedgerError, processErrorResponse, processResponse } from '@zondax/ledger-js' import { ResponseError } from '@zondax/ledger-js/dist/responseError' -import { GenericResponseSign, GenericeResponseAddress, P1_VALUES, TxMetadata } from './common' - -const GenericAppName = 'Polkadot' +import { + GenericResponseSign, + GenericeResponseAddress, + P1_VALUES, + SS58Prefix, + TransactionBlob, + TransactionMetadataBlob, + TxMetadata, +} from './common' export class PolkadotGenericApp extends BaseApp { static _INS = { @@ -40,17 +45,17 @@ export class PolkadotGenericApp extends BaseApp { requiredPathLengths: [5], } + txMetadataChainId?: string txMetadataSrvUrl?: string - txMetadataChainId: string /** * Constructs a new PolkadotGenericApp instance. - * @param {Transport} transport - The transport instance. - * @param {string} txMetadataChainId - The chain ID in the transaction metadata service. - * @param {string} [txMetadataSrvUrl] - The optional transaction metadata service URL. + * @param transport - The transport instance. + * @param txMetadataChainId - The chain ID in the transaction metadata service. + * @param txMetadataSrvUrl - The optional transaction metadata service URL. * @throws {Error} - If the transport is not defined. */ - constructor(transport: Transport, txMetadataChainId: string, txMetadataSrvUrl?: string) { + constructor(transport: Transport, txMetadataChainId?: string, txMetadataSrvUrl?: string) { super(transport, PolkadotGenericApp._params) this.txMetadataSrvUrl = txMetadataSrvUrl this.txMetadataChainId = txMetadataChainId @@ -62,18 +67,28 @@ export class PolkadotGenericApp extends BaseApp { /** * Retrieves transaction metadata from the metadata service. - * @param {Buffer} txBlob - The transaction blob. - * @returns {Promise} - The transaction metadata. - * @throws {Error} - If the txMetadataSrvUrl is not defined. + * @param txBlob - The transaction blob. + * @returns The transaction metadata. + * @throws {ResponseError} - If the txMetadataSrvUrl is not defined. */ - async getTxMetadata(txBlob: Buffer): Promise { - if (this.txMetadataSrvUrl === undefined) { - throw new Error('txMetadataSrvUrl is not defined') + async getTxMetadata(txBlob: TransactionBlob, txMetadataChainId: string, txMetadataSrvUrl: string): Promise { + if (!txMetadataSrvUrl) { + throw new ResponseError( + LedgerError.GenericError, + 'txMetadataSrvUrl is not defined or is empty. The use of the method requires access to a metadata shortening service.' + ) } - const resp = await axios.post(this.txMetadataSrvUrl, { + if (!txMetadataChainId) { + throw new ResponseError( + LedgerError.GenericError, + 'txMetadataChainId is not defined or is empty. These values are configured in the metadata shortening service. Check the corresponding configuration in the service.' + ) + } + + const resp = await axios.post(txMetadataSrvUrl, { txBlob: txBlob.toString('hex'), - chain: { id: this.txMetadataChainId }, + chain: { id: txMetadataChainId }, }) let txMetadata = resp.data.txMetadata @@ -86,13 +101,13 @@ export class PolkadotGenericApp extends BaseApp { /** * Retrieves the address for a given BIP44 path and SS58 prefix. - * @param {string} bip44Path - The BIP44 path. - * @param {number} ss58prefix - The SS58 prefix, must be an integer up to 65535. - * @param {boolean} [showAddrInDevice=false] - Whether to show the address on the device. - * @returns {Promise} - The address response. + * @param bip44Path - The BIP44 path. + * @param ss58prefix - The SS58 prefix, must be an integer up to 65535. + * @param showAddrInDevice - Whether to show the address on the device. + * @returns The address response. * @throws {ResponseError} If the response from the device indicates an error. */ - async getAddress(bip44Path: string, ss58prefix: number, showAddrInDevice = false): Promise { + async getAddress(bip44Path: BIP32Path, ss58prefix: SS58Prefix, showAddrInDevice = false): Promise { // needs to be integer, and up to 65535 if (!Number.isInteger(ss58prefix) || ss58prefix < 0 || ss58prefix >> 16 !== 0) { throw new ResponseError( @@ -139,7 +154,7 @@ export class PolkadotGenericApp extends BaseApp { return chunks } - private getSignReqChunks(path: string, txBlob: Buffer, metadata?: Buffer) { + private getSignReqChunks(path: BIP32Path, txBlob: TransactionBlob, metadata?: TransactionMetadataBlob) { const chunks: Buffer[] = [] const bip44Path = this.serializePath(path) @@ -159,13 +174,19 @@ export class PolkadotGenericApp extends BaseApp { /** * Signs a transaction blob. - * @param {string} path - The BIP44 path. - * @param {number} ins - The instruction for signing. - * @param {Buffer} blob - The transaction blob. - * @param {Buffer} [metadata] - The optional metadata. - * @returns {Promise} - The response containing the signature and status. + * @param path - The BIP44 path. + * @param ins - The instruction for signing. + * @param blob - The transaction blob. + * @param metadata - The optional metadata. + * @throws {ResponseError} If the response from the device indicates an error. + * @returns The response containing the signature and status. */ - private async signImpl(path: string, ins: number, blob: Buffer, metadata?: Buffer): Promise { + private async signImpl( + path: BIP32Path, + ins: number, + blob: TransactionBlob, + metadata?: TransactionMetadataBlob + ): Promise { const chunks = this.getSignReqChunks(path, blob, metadata) try { @@ -184,34 +205,82 @@ export class PolkadotGenericApp extends BaseApp { } /** - * Signs a transaction blob and retrieves the metadata. - * @param {string} path - The BIP44 path. - * @param {Buffer} txBlob - The transaction blob. - * @returns {Promise} - The response containing the signature and status. + * Signs a transaction blob retrieving the correct metadata from a metadata service. + * @param path - The BIP44 path. + * @param txBlob - The transaction blob. + * @throws {ResponseError} If the response from the device indicates an error. + * @returns The response containing the signature and status. */ - async sign(path: string, txBlob: Buffer) { - const txMetadata = await this.getTxMetadata(txBlob) + async sign(path: BIP32Path, txBlob: TransactionBlob) { + if (!this.txMetadataSrvUrl) { + throw new ResponseError( + LedgerError.GenericError, + 'txMetadataSrvUrl is not defined or is empty. The use of the method requires access to a metadata shortening service.' + ) + } + + if (!this.txMetadataChainId) { + throw new ResponseError( + LedgerError.GenericError, + 'txMetadataChainId is not defined or is empty. These values are configured in the metadata shortening service. Check the corresponding configuration in the service.' + ) + } + + const txMetadata = await this.getTxMetadata(txBlob, this.txMetadataSrvUrl, this.txMetadataChainId) return await this.signImpl(path, this.INS.SIGN, txBlob, txMetadata) } /** * Signs a transaction blob with provided metadata. - * @param {string} path - The BIP44 path. - * @param {Buffer} txBlob - The transaction blob. - * @param {Buffer} txMetadata - The transaction metadata. - * @returns {Promise} - The response containing the signature and status. + * @param path - The BIP44 path. + * @param txBlob - The transaction blob. + * @param txMetadataChainId - The optional chain ID for the transaction metadata service. This value temporarily overrides the one set in the constructor. + * @param txMetadataSrvUrl - The optional URL for the transaction metadata service. This value temporarily overrides the one set in the constructor. + * @throws {ResponseError} If the response from the device indicates an error. + * @returns The response containing the signature and status. */ - async signAdvanced(path: string, txBlob: Buffer, txMetadata: Buffer) { + async signMigration(path: BIP32Path, txBlob: TransactionBlob, txMetadataChainId?: string, txMetadataSrvUrl?: string) { + if (!this.txMetadataSrvUrl) { + throw new ResponseError( + LedgerError.GenericError, + 'txMetadataSrvUrl is not defined or is empty. The use of the method requires access to a metadata shortening service.' + ) + } + + if (!this.txMetadataChainId) { + throw new ResponseError( + LedgerError.GenericError, + 'txMetadataChainId is not defined or is empty. These values are configured in the metadata shortening service. Check the corresponding configuration in the service.' + ) + } + + const txMetadata = await this.getTxMetadata( + txBlob, + txMetadataChainId ?? this.txMetadataChainId, + txMetadataSrvUrl ?? this.txMetadataSrvUrl + ) return await this.signImpl(path, this.INS.SIGN, txBlob, txMetadata) } - /** * Signs a raw transaction blob. - * @param {string} path - The BIP44 path. - * @param {Buffer} txBlob - The transaction blob. - * @returns {Promise} - The response containing the signature and status. + * @param path - The BIP44 path. + * @param txBlob - The transaction blob. + * @throws {ResponseError} If the response from the device indicates an error. + * @returns The response containing the signature and status. */ - async signRaw(path: string, txBlob: Buffer) { + async signRaw(path: BIP32Path, txBlob: TransactionBlob) { return await this.signImpl(path, this.INS.SIGN_RAW, txBlob) } + + /** + * [Expert-only Method] Signs a transaction blob with provided metadata (this could be used also with a migration app) + * @param path - The BIP44 path. + * @param txBlob - The transaction blob. + * @param txMetadata - The transaction metadata. + * @throws {ResponseError} If the response from the device indicates an error. + * @returns The response containing the signature and status. + */ + async signWithMetadata(path: BIP32Path, txBlob: TransactionBlob, txMetadata: TransactionMetadataBlob) { + return await this.signImpl(path, this.INS.SIGN, txBlob, txMetadata) + } } diff --git a/src/generic_legacy.ts b/src/generic_legacy.ts index ae1f0cf..482eb5d 100644 --- a/src/generic_legacy.ts +++ b/src/generic_legacy.ts @@ -15,20 +15,39 @@ * limitations under the License. ******************************************************************************* */ import Transport from '@ledgerhq/hw-transport' -import { LedgerError, ResponseError, numbersToBip32Path } from '@zondax/ledger-js' +import { BIP32Path, LedgerError, ResponseError, numbersToBip32Path } from '@zondax/ledger-js' -import { ISubstrateAppLegacy, ResponseAddress, ResponseBase, ResponseSign, ResponseVersion, SCHEME } from './common' +import { ISubstrateAppLegacy, ResponseAddress, ResponseBase, ResponseSign, ResponseVersion, SCHEME, TransactionBlob } from './common' import { PolkadotGenericApp } from './generic_app' +/** + * Class representing a legacy Polkadot generic application. + * Implements the ISubstrateAppLegacy interface. + * @deprecated Use PolkadotGenericApp from generic_app.ts instead. + */ export class PolkadotGenericAppLegacy implements ISubstrateAppLegacy { genericApp: PolkadotGenericApp ss58prefix: number + /** + * Constructs a new PolkadotGenericAppLegacy instance. + * @param transport - The transport instance. + * @param ss58prefix - The SS58 prefix. + * @param txMetadataChainId - The chain ID in the transaction metadata service. + * @param txMetadataSrvUrl - The optional transaction metadata service URL. + * @deprecated Use PolkadotGenericApp constructor from generic_app.ts instead. + */ constructor(transport: Transport, ss58prefix: number, txMetadataChainId: string, txMetadataSrvUrl: string | undefined) { this.genericApp = new PolkadotGenericApp(transport, txMetadataChainId, txMetadataSrvUrl) this.ss58prefix = ss58prefix } + /** + * Converts a ResponseError to a legacy ResponseBase format. + * @param e - The ResponseError instance. + * @returns The legacy ResponseBase object. + * @deprecated + */ private convertToLegacyError(e: ResponseError): ResponseBase { return { error_message: e.errorMessage, @@ -36,10 +55,23 @@ export class PolkadotGenericAppLegacy implements ISubstrateAppLegacy { } } - private convertLegacyPath(account: number, change: number, addressIndex: number) { + /** + * Converts account, change, and addressIndex to a BIP32Path. + * @param account - The account number. + * @param change - The change number. + * @param addressIndex - The address index. + * @returns The BIP32Path. + * @deprecated + */ + private convertLegacyPath(account: number, change: number, addressIndex: number): BIP32Path { return numbersToBip32Path([0x8000002c, 0x80000162, account, change, addressIndex]) } + /** + * Retrieves the version of the application. + * @returns A promise that resolves to a ResponseVersion object. + * @deprecated Use getVersion method from PolkadotGenericApp in generic_app.ts instead. + */ async getVersion(): Promise { try { const version = await this.genericApp.getVersion() @@ -67,6 +99,11 @@ export class PolkadotGenericAppLegacy implements ISubstrateAppLegacy { } } + /** + * Retrieves application information. + * @returns A promise that resolves to an object containing application information. + * @deprecated Use appInfo method from PolkadotGenericApp in generic_app.ts instead. + */ async appInfo(): Promise { try { const info = await this.genericApp.appInfo() @@ -84,6 +121,17 @@ export class PolkadotGenericAppLegacy implements ISubstrateAppLegacy { } } + /** + * Retrieves the address for a given account, change, and address index. + * @param account - The account number. + * @param change - The change number. + * @param addressIndex - The address index. + * @param requireConfirmation - Whether to require confirmation on the device. + * @param scheme - The cryptographic scheme. + * @returns A promise that resolves to a ResponseAddress object. + * @throws {ResponseError} If the scheme is not supported. + * @deprecated Use getAddress method from PolkadotGenericApp in generic_app.ts instead. + */ async getAddress( account: number, change: number, @@ -114,7 +162,18 @@ export class PolkadotGenericAppLegacy implements ISubstrateAppLegacy { } } - async sign(account: number, change: number, addressIndex: number, message: Buffer, scheme?: SCHEME): Promise { + /** + * Signs a transaction blob. + * @param account - The account number. + * @param change - The change number. + * @param addressIndex - The address index. + * @param message - The transaction blob. + * @param scheme - The cryptographic scheme. + * @returns A promise that resolves to a ResponseSign object. + * @throws {ResponseError} If the scheme is not supported. + * @deprecated Use sign method from PolkadotGenericApp in generic_app.ts instead. + */ + async sign(account: number, change: number, addressIndex: number, message: TransactionBlob, scheme?: SCHEME): Promise { try { if (scheme !== SCHEME.ED25519) { throw ResponseError.fromReturnCode(LedgerError.AlgorithmNotSupported) @@ -137,7 +196,18 @@ export class PolkadotGenericAppLegacy implements ISubstrateAppLegacy { } } - async signRaw(account: number, change: number, addressIndex: number, message: Buffer, scheme?: SCHEME): Promise { + /** + * Signs a raw transaction blob. + * @param account - The account number. + * @param change - The change number. + * @param addressIndex - The address index. + * @param message - The transaction blob. + * @param scheme - The cryptographic scheme. + * @returns A promise that resolves to a ResponseSign object. + * @throws {ResponseError} If the scheme is not supported. + * @deprecated Use signRaw method from PolkadotGenericApp in generic_app.ts instead. + */ + async signRaw(account: number, change: number, addressIndex: number, message: TransactionBlob, scheme?: SCHEME): Promise { try { if (scheme !== SCHEME.ED25519) { throw ResponseError.fromReturnCode(LedgerError.AlgorithmNotSupported) diff --git a/src/index.ts b/src/index.ts index 71e1de4..d97f08d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,5 +17,6 @@ export * from './legacy_apps' export * from './generic_app' +export * from './generic_legacy' export { SubstrateApp } from './substrate_app' -export { newSubstrateApp, newMigrationGenericApp, supportedApps } from './supported_apps' +export { newSubstrateApp, supportedApps } from './supported_apps' diff --git a/src/substrate_app.ts b/src/substrate_app.ts index cddc864..d2de929 100644 --- a/src/substrate_app.ts +++ b/src/substrate_app.ts @@ -34,11 +34,20 @@ import { processErrorResponse, } from './common' +/** + * Class representing a Substrate application. + */ export class SubstrateApp implements ISubstrateAppLegacy { transport: Transport cla: number slip0044: number + /** + * Create a SubstrateApp instance. + * @param transport - The transport instance. + * @param cla - The CLA value. + * @param slip0044 - The SLIP-0044 value. + */ constructor(transport: Transport, cla: number, slip0044: number) { if (transport == null) { throw new Error('Transport has not been defined') @@ -48,6 +57,14 @@ export class SubstrateApp implements ISubstrateAppLegacy { this.slip0044 = slip0044 } + /** + * Serialize the BIP44 path. + * @param slip0044 - The SLIP-0044 value. + * @param account - The account index. + * @param change - The change index. + * @param addressIndex - The address index. + * @returns The serialized path. + */ static serializePath(slip0044: number, account: number, change: number, addressIndex: number) { if (!Number.isInteger(account)) throw new Error('Input must be an integer') if (!Number.isInteger(change)) throw new Error('Input must be an integer') @@ -62,6 +79,11 @@ export class SubstrateApp implements ISubstrateAppLegacy { return buf } + /** + * Split a message into chunks. + * @param message - The message to split. + * @returns The message chunks. + */ static GetChunks(message: Buffer) { const chunks = [] const buffer = Buffer.from(message) @@ -77,6 +99,15 @@ export class SubstrateApp implements ISubstrateAppLegacy { return chunks } + /** + * Get chunks for signing. + * @param slip0044 - The SLIP-0044 value. + * @param account - The account index. + * @param change - The change index. + * @param addressIndex - The address index. + * @param message - The message to sign. + * @returns The chunks for signing. + */ static signGetChunks(slip0044: number, account: number, change: number, addressIndex: number, message: Buffer) { const chunks = [] const bip44Path = SubstrateApp.serializePath(slip0044, account, change, addressIndex) @@ -85,6 +116,10 @@ export class SubstrateApp implements ISubstrateAppLegacy { return chunks } + /** + * Get the version of the application. + * @returns The version response. + */ async getVersion(): Promise { try { return await getVersion(this.transport, this.cla) @@ -93,6 +128,10 @@ export class SubstrateApp implements ISubstrateAppLegacy { } } + /** + * Get application information. + * @returns The application information. + */ async appInfo() { return await this.transport.send(0xb0, 0x01, 0, 0).then(response => { const errorCodeData = response.subarray(-2) @@ -126,23 +165,27 @@ export class SubstrateApp implements ISubstrateAppLegacy { return { return_code: returnCode, error_message: errorCodeToString(returnCode), - // // appName: appName === '' || 'err', appVersion: appVersion === '' || 'err', flagLen, flagsValue, - // eslint-disable-next-line no-bitwise flag_recovery: (flagsValue & 1) !== 0, - // eslint-disable-next-line no-bitwise flag_signed_mcu_code: (flagsValue & 2) !== 0, - // eslint-disable-next-line no-bitwise flag_onboarded: (flagsValue & 4) !== 0, - // eslint-disable-next-line no-bitwise flag_pin_validated: (flagsValue & 128) !== 0, } }, processErrorResponse) } + /** + * Get the address. + * @param account - The account index. + * @param change - The change index. + * @param addressIndex - The address index. + * @param [requireConfirmation=false] - Whether confirmation is required. + * @param [scheme=SCHEME.ED25519] - The scheme. + * @returns The address response. + */ async getAddress( account: number, change: number, @@ -171,6 +214,16 @@ export class SubstrateApp implements ISubstrateAppLegacy { }, processErrorResponse) } + /** + * Send a chunk for signing. + * @private + * @param chunkIdx - The chunk index. + * @param chunkNum - The total number of chunks. + * @param chunk - The chunk data. + * @param [scheme=SCHEME.ED25519] - The scheme. + * @param [ins=INS.SIGN] - The instruction. + * @returns The response. + */ private async signSendChunk(chunkIdx: number, chunkNum: number, chunk: Buffer, scheme = SCHEME.ED25519, ins: INS_SIGN = INS.SIGN) { let payloadType = PAYLOAD_TYPE.ADD if (chunkIdx === 1) { @@ -203,6 +256,17 @@ export class SubstrateApp implements ISubstrateAppLegacy { }, processErrorResponse) } + /** + * Implementation of the signing process. + * @private + * @param account - The account index. + * @param change - The change index. + * @param addressIndex - The address index. + * @param message - The message to sign. + * @param ins - The instruction. + * @param [scheme=SCHEME.ED25519] - The scheme. + * @returns The signing response. + */ private async signImpl( account: number, change: number, @@ -229,16 +293,36 @@ export class SubstrateApp implements ISubstrateAppLegacy { }, processErrorResponse) } + /** + * Sign a message. + * @param account - The account index. + * @param change - The change index. + * @param addressIndex - The address index. + * @param message - The message to sign. + * @param [scheme=SCHEME.ED25519] - The scheme. + * @returns The signing response. + */ async sign(account: number, change: number, addressIndex: number, message: Buffer, scheme = SCHEME.ED25519) { return await this.signImpl(account, change, addressIndex, message, INS.SIGN, scheme) } + /** + * Sign a raw message. + * @param account - The account index. + * @param change - The change index. + * @param addressIndex - The address index. + * @param message - The message to sign. + * @param [scheme=SCHEME.ED25519] - The scheme. + * @returns The signing response. + */ async signRaw(account: number, change: number, addressIndex: number, message: Buffer, scheme = SCHEME.ED25519) { return await this.signImpl(account, change, addressIndex, message, INS.SIGN_RAW, scheme) } /** * @deprecated This function is deprecated and will be removed in future versions. + * Get the allowlist public key. + * @returns The allowlist public key response. */ async getAllowlistPubKey(): Promise { return await this.transport.send(this.cla, INS.ALLOWLIST_GET_PUBKEY, 0, 0).then(response => { @@ -266,6 +350,9 @@ export class SubstrateApp implements ISubstrateAppLegacy { /** * @deprecated This function is deprecated and will be removed in future versions. + * Set the allowlist public key. + * @param pk - The public key. + * @returns The response. */ async setAllowlistPubKey(pk: Buffer) { return await this.transport.send(this.cla, INS.ALLOWLIST_SET_PUBKEY, 0, 0, pk).then(response => { @@ -281,6 +368,8 @@ export class SubstrateApp implements ISubstrateAppLegacy { /** * @deprecated This function is deprecated and will be removed in future versions. + * Get the allowlist hash. + * @returns The allowlist hash response. */ async getAllowlistHash(): Promise { return await this.transport.send(this.cla, INS.ALLOWLIST_GET_HASH, 0, 0).then(response => { @@ -308,6 +397,11 @@ export class SubstrateApp implements ISubstrateAppLegacy { /** * @deprecated This function is deprecated and will be removed in future versions. + * Send a chunk for uploading the allowlist. + * @param chunkIdx - The chunk index. + * @param chunkNum - The total number of chunks. + * @param chunk - The chunk data. + * @returns The response. */ async uploadSendChunk(chunkIdx: number, chunkNum: number, chunk: Buffer) { let payloadType = PAYLOAD_TYPE.ADD @@ -332,6 +426,9 @@ export class SubstrateApp implements ISubstrateAppLegacy { /** * @deprecated This function is deprecated and will be removed in future versions. + * Upload the allowlist. + * @param message - The allowlist message. + * @returns The response. */ async uploadAllowlist(message: Buffer) { const chunks: Buffer[] = [] @@ -347,7 +444,6 @@ export class SubstrateApp implements ISubstrateAppLegacy { } for (let i = 1; i < chunks.length; i += 1) { - // eslint-disable-next-line no-await-in-loop,no-param-reassign result = await this.uploadSendChunk(1 + i, chunks.length, chunks[i]) if (result.return_code !== ERROR_CODE.NoError) { break diff --git a/src/supported_apps.ts b/src/supported_apps.ts index 6cf88ec..2e96de1 100644 --- a/src/supported_apps.ts +++ b/src/supported_apps.ts @@ -17,7 +17,6 @@ import type Transport from '@ledgerhq/hw-transport' import { type SubstrateAppParams } from './common' -import { PolkadotGenericApp } from './generic_app' import { SubstrateApp } from './substrate_app' export function newSubstrateApp(transport: Transport, chainName: string) { diff --git a/tests/integration.test.ts b/tests/integration.test.ts index 9f58630..e52786f 100644 --- a/tests/integration.test.ts +++ b/tests/integration.test.ts @@ -1,4 +1,3 @@ -// TODO: Use mock transport // /** ****************************************************************************** // * (c) 2018 - 2022 Zondax AG // * @@ -15,11 +14,10 @@ // * limitations under the License. // ******************************************************************************* */ // import { blake2bFinal, blake2bInit, blake2bUpdate } from 'blakejs' - -// import { MockTransport } from '@ledgerhq/hw-transport-mocker' // import { ed25519 } from '@noble/curves/ed25519' // import { newSubstrateApp } from '../src' +// import { openTransportReplayer, RecordStore } from '@ledgerhq/hw-transport-mocker' // const CHAIN = 'Kusama' // const YOUR_PUBKEY = 'd280b24dface41f31006e5a2783971fc5a66c862dd7d08f97603d2902b75e47a' @@ -27,13 +25,22 @@ // const YOUR_BLOB = // '040000313233343536373839303132333435363738393031323334353637383930313233158139ae28a3dfaac5fe1560a5e9e05cd5038d2433158139ae28a3dfaac5fe1560a5e9e05c362400000c000000b0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafeb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe' -// let transport = {} - // jest.setTimeout(60000) // describe('Integration', function () { // test('get version', async () => { -// // @ts-expect-error transport will be there +// const store = RecordStore.fromString(` +// => e016000000 +// <= 000000050107426974636f696e034254439000 +// => e001000000 +// <= 3110000405312e352e35042300000004312e37002013fe17e06cf2f710d33328aa46d1053f8fadd48dcaeca2c5512dd79e2158d5779000 +// `, +// { +// autoSkipUnknownApdu: true, +// } +// ); +// const transport = await openTransportReplayer(store) + // const app = newSubstrateApp(transport, CHAIN) // const resp = await app.getVersion() // console.log(resp) @@ -47,72 +54,72 @@ // expect(resp.test_mode).toEqual(false) // }) -// test('get address', async () => { -// // @ts-expect-error transport will be there -// const app = newSubstrateApp(transport, CHAIN) +// // test('get address', async () => { +// // // @ts-expect-error transport will be there +// // const app = newSubstrateApp(transport, CHAIN) -// const pathAccount = 0x80000000 -// const pathChange = 0x80000000 -// const pathIndex = 0x80000005 +// // const pathAccount = 0x80000000 +// // const pathChange = 0x80000000 +// // const pathIndex = 0x80000005 -// const response = await app.getAddress(pathAccount, pathChange, pathIndex) -// console.log(response) +// // const response = await app.getAddress(pathAccount, pathChange, pathIndex) +// // console.log(response) -// expect(response.return_code).toEqual(0x9000) -// expect(response.error_message).toEqual('No errors') -// expect(response).toHaveProperty('pubKey') -// expect(response.pubKey).toEqual(YOUR_PUBKEY) -// expect(response.address).toEqual(YOUR_ADDRESS) -// }) +// // expect(response.return_code).toEqual(0x9000) +// // expect(response.error_message).toEqual('No errors') +// // expect(response).toHaveProperty('pubKey') +// // expect(response.pubKey).toEqual(YOUR_PUBKEY) +// // expect(response.address).toEqual(YOUR_ADDRESS) +// // }) -// test('show address', async () => { -// // @ts-expect-error transport will be there -// const app = newSubstrateApp(transport, CHAIN) +// // test('show address', async () => { +// // // @ts-expect-error transport will be there +// // const app = newSubstrateApp(transport, CHAIN) -// const pathAccount = 0x80000000 -// const pathChange = 0x80000000 -// const pathIndex = 0x80000005 -// const response = await app.getAddress(pathAccount, pathChange, pathIndex, true) +// // const pathAccount = 0x80000000 +// // const pathChange = 0x80000000 +// // const pathIndex = 0x80000005 +// // const response = await app.getAddress(pathAccount, pathChange, pathIndex, true) -// console.log(response) +// // console.log(response) -// expect(response.return_code).toEqual(0x9000) -// expect(response.error_message).toEqual('No errors') +// // expect(response.return_code).toEqual(0x9000) +// // expect(response.error_message).toEqual('No errors') -// expect(response).toHaveProperty('address') -// expect(response).toHaveProperty('pubKey') +// // expect(response).toHaveProperty('address') +// // expect(response).toHaveProperty('pubKey') -// expect(response.pubKey).toEqual(YOUR_PUBKEY) -// expect(response.address).toEqual(YOUR_ADDRESS) -// }) +// // expect(response.pubKey).toEqual(YOUR_PUBKEY) +// // expect(response.address).toEqual(YOUR_ADDRESS) +// // }) -// test('sign2_and_verify', async () => { -// const txBlob = Buffer.from(YOUR_BLOB, 'hex') +// // test('sign2_and_verify', async () => { +// // const txBlob = Buffer.from(YOUR_BLOB, 'hex') -// // @ts-expect-error transport will be there -// const app = newSubstrateApp(transport, CHAIN) +// // // @ts-expect-error transport will be there +// // const app = newSubstrateApp(transport, CHAIN) -// const pathAccount = 0x80000000 -// const pathChange = 0x80000000 -// const pathIndex = 0x80000000 +// // const pathAccount = 0x80000000 +// // const pathChange = 0x80000000 +// // const pathIndex = 0x80000000 -// const responseAddr = await app.getAddress(pathAccount, pathChange, pathIndex) -// const responseSign = await app.sign(pathAccount, pathChange, pathIndex, txBlob) +// // const responseAddr = await app.getAddress(pathAccount, pathChange, pathIndex) +// // const responseSign = await app.sign(pathAccount, pathChange, pathIndex, txBlob) -// const pubkey = responseAddr.pubKey +// // const pubkey = responseAddr.pubKey -// console.log(responseAddr) -// console.log(responseSign) +// // console.log(responseAddr) +// // console.log(responseSign) -// // Check signature is valid -// let prehash = txBlob -// if (txBlob.length > 256) { -// const context = blake2bInit(32) -// blake2bUpdate(context, txBlob) -// prehash = Buffer.from(blake2bFinal(context)) -// } +// // // Check signature is valid +// // let prehash = txBlob +// // if (txBlob.length > 256) { +// // const context = blake2bInit(32) +// // blake2bUpdate(context, txBlob) +// // prehash = Buffer.from(blake2bFinal(context)) +// // } -// const valid = await ed25519.verify(responseSign.signature.subarray(1), prehash, pubkey) -// expect(valid).toEqual(true) -// }) +// // const valid = ed25519.verify(responseSign.signature.subarray(1), prehash, pubkey) +// // expect(valid).toEqual(true) +// // }) // }) diff --git a/yarn.lock b/yarn.lock index 880a25d..a004eaf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1119,10 +1119,10 @@ "@typescript-eslint/types" "7.9.0" eslint-visitor-keys "^3.4.3" -"@zondax/ledger-js@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@zondax/ledger-js/-/ledger-js-0.8.0.tgz#cca9182ce5bd89d00800d5db098193183ec477a1" - integrity sha512-G61wAtj5mBI3EbBe3wB2NXfA4fkBxjxexiCaLOa+akNNhYH0kWFImI7oWfQGMt+epQatvBLg5h0sgNLVge+GRQ== +"@zondax/ledger-js@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@zondax/ledger-js/-/ledger-js-0.8.1.tgz#b4d09d7778592ce350f8646713ff3a9ee069f0ef" + integrity sha512-mr/lHdN73UzsY4FkUOAoCyP5GsxCTbCCKv+fQfE+ENOxI+iv5raFB+V7cCbhKuQdH6kdKhT+wYD2zA6Jv19rGQ== dependencies: "@ledgerhq/hw-transport" "6.30.6"