{"version":3,"file":"Sui.mjs","names":["#verbose","#sendChunks","#log","#internalGetVersion","#checkAppVersion","#provideTrustedDynamicDescriptor","#handleBlocksProtocol"],"sources":["../src/Sui.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { DeviceModelId } from '@ledgerhq/devices';\nimport { LatestFirmwareVersionRequired, UpdateYourApp } from '@ledgerhq/errors';\nimport { loadPKI } from '@ledgerhq/hw-bolos';\nimport Transport, { TransportStatusError } from '@ledgerhq/hw-transport';\nimport calService from '@ledgerhq/ledger-cal-service';\nimport sha256 from 'fast-sha256';\nimport semver from 'semver';\n\nimport type { DescriptorInput } from './descriptor.js';\nimport { buildDescriptor } from './descriptor.js';\n\nexport type GetPublicKeyResult = {\n\tpublicKey: Uint8Array;\n\taddress: Uint8Array;\n};\n\nexport type SignTransactionResult = {\n\tsignature: Uint8Array;\n};\n\nexport type GetVersionResult = {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n};\n\nexport type Resolution = {\n\tdeviceModelId?: DeviceModelId | undefined;\n\tcertificateSignatureKind?: 'prod' | 'test' | undefined;\n\ttokenAddress?: string;\n\ttokenId?: string;\n};\n\nexport type AppConfig = {\n\tblindSigningEnabled: boolean;\n\tversion: string;\n};\n\nenum LedgerToHost {\n\tRESULT_ACCUMULATING = 0,\n\tRESULT_FINAL = 1,\n\tGET_CHUNK = 2,\n\tPUT_CHUNK = 3,\n}\n\nenum HostToLedger {\n\tSTART = 0,\n\tGET_CHUNK_RESPONSE_SUCCESS = 1,\n\tGET_CHUNK_RESPONSE_FAILURE = 2,\n\tPUT_CHUNK_RESPONSE = 3,\n\tRESULT_ACCUMULATING_RESPONSE = 4,\n}\n\nconst MIN_VERSION = '1.5.4';\nconst MANAGER_APP_NAME = 'Sui';\n\nfunction isPKIUnsupportedError(err: unknown): err is TransportStatusError {\n\treturn err instanceof TransportStatusError && err.message.includes('0x6a81');\n}\n\nasync function tryLoadPKI(...args: Parameters<typeof loadPKI>) {\n\ttry {\n\t\tawait loadPKI(...args);\n\t} catch (err) {\n\t\tif (isPKIUnsupportedError(err)) {\n\t\t\tthrow new LatestFirmwareVersionRequired('LatestFirmwareVersionRequired');\n\t\t}\n\t}\n}\n\n/**\n * Sui API\n *\n * @example\n * import Sui from \"@mysten/ledgerjs-hw-app-sui\";\n * const sui = new Sui(transport)\n */\nexport default class Sui {\n\ttransport: Transport;\n\treadonly #verbose: boolean;\n\n\tconstructor(transport: Transport, scrambleKey = 'default_sui_scramble_key', verbose = false) {\n\t\tthis.#verbose = verbose;\n\t\tthis.transport = transport;\n\t\tthis.transport.decorateAppAPIMethods(\n\t\t\tthis,\n\t\t\t['getPublicKey', 'signTransaction', 'getVersion', 'provideTrustedDynamicDescriptor'],\n\t\t\tscrambleKey,\n\t\t);\n\t}\n\n\t/**\n\t * Retrieves the public key associated with a particular BIP32 path from the Ledger app.\n\t *\n\t * @param path - the path to retrieve.\n\t * @param displayOnDevice - whether or not the address should be displayed on the device.\n\t *\n\t */\n\tasync getPublicKey(path: string, displayOnDevice = false): Promise<GetPublicKeyResult> {\n\t\tconst cla = 0x00;\n\t\tconst ins = displayOnDevice ? 0x01 : 0x02;\n\t\tconst p1 = 0;\n\t\tconst p2 = 0;\n\t\tconst payload = buildBip32KeyPayload(path);\n\t\tconst response = await this.#sendChunks(cla, ins, p1, p2, payload);\n\t\tconst keySize = response[0];\n\n\t\tconst publicKey = response.slice(1, keySize + 1); // slice uses end index.\n\t\tlet address: Uint8Array | null = null;\n\t\tif (response.length > keySize + 2) {\n\t\t\tconst addressSize = response[keySize + 1];\n\t\t\taddress = response.slice(keySize + 2, keySize + 2 + addressSize);\n\t\t}\n\t\tconst res: GetPublicKeyResult = {\n\t\t\tpublicKey: publicKey,\n\t\t\taddress: address!,\n\t\t};\n\t\treturn res;\n\t}\n\n\t/**\n\t * Sign a transaction with the key at a BIP32 path.\n\t *\n\t * @param txn - The transaction bytes to sign.\n\t * @param path - The path to use when signing the transaction.\n\t * @param options - Additional options used for clear signing purposes.\n\t * @param resolution - Additional data for token clear signing purposes.\n\t */\n\tasync signTransaction(\n\t\tpath: string,\n\t\ttxn: Uint8Array,\n\t\toptions?: {\n\t\t\tbcsObjects: Uint8Array[];\n\t\t},\n\t\tresolution?: Resolution,\n\t): Promise<SignTransactionResult> {\n\t\tconst cla = 0x00;\n\t\tconst ins = 0x03;\n\t\tconst p1 = 0;\n\t\tconst p2 = 0;\n\n\t\tif (this.#verbose) this.#log(txn);\n\n\t\t// Transaction payload is the byte length as uint32le followed by the bytes\n\t\tconst rawTxn = Buffer.from(txn);\n\t\tconst hashSize = Buffer.alloc(4);\n\t\thashSize.writeUInt32LE(rawTxn.length, 0);\n\n\t\t// Build transaction payload:\n\t\tconst payloadTxn = Buffer.concat([hashSize, rawTxn]);\n\t\tthis.#log('Payload Txn', payloadTxn);\n\n\t\tconst bip32KeyPayload = buildBip32KeyPayload(path);\n\t\tconst payloads = [payloadTxn, bip32KeyPayload];\n\n\t\t// The public getVersion is decorated with a lock in the constructor:\n\t\tconst { major } = await this.#internalGetVersion();\n\t\tthis.#log('App version', major);\n\n\t\tconst bcsObjects = options?.bcsObjects ?? [];\n\t\tthis.#log('Objects list length', bcsObjects.length);\n\n\t\tif (major > 0 && bcsObjects.length > 0) {\n\t\t\t// Build object list payload:\n\t\t\tconst numItems = Buffer.alloc(4);\n\t\t\tnumItems.writeUInt32LE(bcsObjects.length, 0);\n\n\t\t\tlet listData = Buffer.from(numItems);\n\n\t\t\t// Add each item with its length prefix:\n\t\t\tfor (const item of bcsObjects) {\n\t\t\t\tconst rawItem = Buffer.from(item);\n\t\t\t\tconst itemLen = Buffer.alloc(4);\n\t\t\t\titemLen.writeUInt32LE(rawItem.length, 0);\n\n\t\t\t\tlistData = Buffer.concat([listData, itemLen, rawItem]);\n\t\t\t}\n\n\t\t\tpayloads.push(listData);\n\t\t}\n\n\t\tif (resolution) {\n\t\t\tif (!resolution.deviceModelId) {\n\t\t\t\tthrow new Error('Resolution provided without a deviceModelId');\n\t\t\t}\n\n\t\t\tif (resolution.deviceModelId !== DeviceModelId.nanoS) {\n\t\t\t\tawait this.#checkAppVersion(MIN_VERSION, { throwOnOutdated: true });\n\n\t\t\t\tconst { descriptor, signature } = await calService.getCertificate(\n\t\t\t\t\tresolution.deviceModelId,\n\t\t\t\t\t'trusted_name',\n\t\t\t\t\t'latest',\n\t\t\t\t\t{ signatureKind: resolution.certificateSignatureKind },\n\t\t\t\t);\n\n\t\t\t\ttry {\n\t\t\t\t\tawait loadPKI(this.transport, 'TRUSTED_NAME', descriptor, signature);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (isPKIUnsupportedError(err)) {\n\t\t\t\t\t\tthrow new LatestFirmwareVersionRequired('LatestFirmwareVersionRequired');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (resolution.tokenId) {\n\t\t\t\t\tconst { descriptor: coinMetaDescriptor, signature: coinMetaSignature } =\n\t\t\t\t\t\tawait calService.getCertificate(resolution.deviceModelId, 'coin_meta', 'latest', {\n\t\t\t\t\t\t\tsignatureKind: resolution.certificateSignatureKind,\n\t\t\t\t\t\t});\n\n\t\t\t\t\tawait tryLoadPKI(this.transport, 'COIN_META', coinMetaDescriptor, coinMetaSignature);\n\n\t\t\t\t\tconst token = await calService.findToken(\n\t\t\t\t\t\t{ id: resolution.tokenId },\n\t\t\t\t\t\t{ signatureKind: resolution.certificateSignatureKind },\n\t\t\t\t\t);\n\n\t\t\t\t\tawait this.#provideTrustedDynamicDescriptor({\n\t\t\t\t\t\tdata: Buffer.from(token.descriptor.data, 'hex'),\n\t\t\t\t\t\tsignature: Buffer.from(token.descriptor.signature, 'hex'),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Send the chunks and return the signature\n\t\tconst signature = await this.#sendChunks(cla, ins, p1, p2, payloads);\n\t\treturn { signature };\n\t}\n\n\t/**\n\t * Retrieve the app version on the attached Ledger device.\n\t */\n\tasync #checkAppVersion(minVersion: string, { throwOnOutdated }: { throwOnOutdated: boolean }) {\n\t\tconst { major, minor, patch } = await this.#internalGetVersion();\n\t\tconst outdated = semver.lt(`${major}.${minor}.${patch}`, minVersion);\n\n\t\tif (outdated && throwOnOutdated) {\n\t\t\tthrow new UpdateYourApp(undefined, {\n\t\t\t\tmanagerAppName: MANAGER_APP_NAME,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Retrieve the app version on the attached Ledger device.\n\t */\n\tasync getVersion(): Promise<GetVersionResult> {\n\t\treturn await this.#internalGetVersion();\n\t}\n\n\tasync #internalGetVersion() {\n\t\tconst [major, minor, patch] = await this.#sendChunks(0x00, 0x00, 0x00, 0x00, Buffer.alloc(1));\n\t\treturn {\n\t\t\tmajor,\n\t\t\tminor,\n\t\t\tpatch,\n\t\t};\n\t}\n\n\t/**\n\t * Provides trusted dynamic and signed coin metadata\n\t *\n\t * @param data An object containing the descriptor and its signature from the CAL\n\t */\n\tasync #provideTrustedDynamicDescriptor(data: DescriptorInput): Promise<boolean> {\n\t\tawait this.#sendChunks(\n\t\t\t0x00, // CLA\n\t\t\t0x22, // Provide trusted dynamic descriptor\n\t\t\t0x00, // P1\n\t\t\t0x00, // P2\n\t\t\tbuildDescriptor(data),\n\t\t);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Convert a raw payload into what is essentially a singly-linked list of chunks, which\n\t * allows the ledger to re-seek the data in a secure fashion.\n\t */\n\tasync #sendChunks(\n\t\tcla: number,\n\t\tins: number,\n\t\tp1: number,\n\t\tp2: number,\n\t\tpayload: Buffer | Buffer[],\n\t\t// Constant (protocol dependent) data that the ledger may want to refer to\n\t\t// besides the payload.\n\t\textraData: Map<string, Buffer> = new Map<string, Buffer>(),\n\t): Promise<Buffer> {\n\t\tconst chunkSize = 180;\n\t\tif (!(payload instanceof Array)) {\n\t\t\tpayload = [payload];\n\t\t}\n\t\tconst parameterList: Buffer[] = [];\n\t\tlet data = new Map<string, Buffer>(extraData);\n\t\tfor (let j = 0; j < payload.length; j++) {\n\t\t\tconst chunkList: Buffer[] = [];\n\t\t\tfor (let i = 0; i < payload[j].length; i += chunkSize) {\n\t\t\t\tconst cur = payload[j].slice(i, i + chunkSize);\n\t\t\t\tchunkList.push(cur);\n\t\t\t}\n\t\t\t// Store the hash that points to the \"rest of the list of chunks\"\n\t\t\tlet lastHash = Buffer.alloc(32);\n\t\t\tthis.#log(lastHash);\n\t\t\t// Since we are doing a foldr, we process the last chunk first\n\t\t\t// We have to do it this way, because a block knows the hash of\n\t\t\t// the next block.\n\t\t\tdata = chunkList.reduceRight((blocks, chunk) => {\n\t\t\t\tconst linkedChunk = Buffer.concat([lastHash, chunk]);\n\t\t\t\tthis.#log('Chunk: ', chunk);\n\t\t\t\tthis.#log('linkedChunk: ', linkedChunk);\n\t\t\t\tlastHash = Buffer.from(sha256(linkedChunk));\n\t\t\t\tblocks.set(lastHash.toString('hex'), linkedChunk);\n\t\t\t\treturn blocks;\n\t\t\t}, data);\n\t\t\tparameterList.push(lastHash);\n\t\t\tlastHash = Buffer.alloc(32);\n\t\t}\n\t\tthis.#log(data);\n\t\treturn await this.#handleBlocksProtocol(\n\t\t\tcla,\n\t\t\tins,\n\t\t\tp1,\n\t\t\tp2,\n\t\t\tBuffer.concat(([Buffer.from([HostToLedger.START])] as Buffer[]).concat(parameterList)),\n\t\t\tdata,\n\t\t);\n\t}\n\n\tasync #handleBlocksProtocol(\n\t\tcla: number,\n\t\tins: number,\n\t\tp1: number,\n\t\tp2: number,\n\t\tinitialPayload: Buffer,\n\t\tdata: Map<string, Buffer>,\n\t): Promise<Buffer> {\n\t\tlet payload = initialPayload;\n\t\tlet result = Buffer.alloc(0);\n\t\tdo {\n\t\t\tthis.#log('Sending payload to ledger: ', payload.toString('hex'));\n\t\t\tconst rv = await this.transport.send(cla, ins, p1, p2, payload);\n\t\t\tthis.#log('Received response: ', rv);\n\t\t\tvar rv_instruction = rv[0];\n\t\t\tconst rv_payload = rv.slice(1, rv.length - 2); // Last two bytes are a return code.\n\t\t\tif (!(rv_instruction in LedgerToHost)) {\n\t\t\t\tthrow new TypeError('Unknown instruction returned from ledger');\n\t\t\t}\n\t\t\tswitch (rv_instruction) {\n\t\t\t\tcase LedgerToHost.RESULT_ACCUMULATING:\n\t\t\t\tcase LedgerToHost.RESULT_FINAL:\n\t\t\t\t\tresult = Buffer.concat([result, rv_payload]);\n\t\t\t\t\t// Won't actually send this if we drop out of the loop for RESULT_FINAL\n\t\t\t\t\tpayload = Buffer.from([HostToLedger.RESULT_ACCUMULATING_RESPONSE]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase LedgerToHost.GET_CHUNK:\n\t\t\t\t\tconst chunk = data.get(rv_payload.toString('hex'));\n\t\t\t\t\tthis.#log('Getting block ', rv_payload);\n\t\t\t\t\tthis.#log('Found block ', chunk);\n\t\t\t\t\tif (chunk) {\n\t\t\t\t\t\tpayload = Buffer.concat([\n\t\t\t\t\t\t\tBuffer.from([HostToLedger.GET_CHUNK_RESPONSE_SUCCESS]),\n\t\t\t\t\t\t\tchunk,\n\t\t\t\t\t\t]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpayload = Buffer.from([HostToLedger.GET_CHUNK_RESPONSE_FAILURE]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase LedgerToHost.PUT_CHUNK:\n\t\t\t\t\tdata.set(Buffer.from(sha256(rv_payload)).toString('hex'), rv_payload);\n\t\t\t\t\tpayload = Buffer.from([HostToLedger.PUT_CHUNK_RESPONSE]);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} while (rv_instruction !== LedgerToHost.RESULT_FINAL);\n\t\treturn result;\n\t}\n\n\t#log(...args: any[]) {\n\t\tif (this.#verbose) console.log(args);\n\t}\n}\n\nfunction buildBip32KeyPayload(path: string): Buffer {\n\tconst paths = splitPath(path);\n\t// Bip32Key payload is:\n\t// 1 byte with number of elements in u32 array path\n\t// Followed by the u32 array itself\n\tconst payload = Buffer.alloc(1 + paths.length * 4);\n\tpayload[0] = paths.length;\n\tpaths.forEach((element, index) => {\n\t\tpayload.writeUInt32LE(element, 1 + 4 * index);\n\t});\n\treturn payload;\n}\n\n// TODO use bip32-path library\nfunction splitPath(path: string): number[] {\n\tconst result: number[] = [];\n\tconst components = path.split('/');\n\tcomponents.forEach((element) => {\n\t\tlet number = parseInt(element, 10);\n\n\t\tif (isNaN(number)) {\n\t\t\treturn; // FIXME shouldn't it throws instead?\n\t\t}\n\n\t\tif (element.length > 1 && element[element.length - 1] === \"'\") {\n\t\t\tnumber += 0x80000000;\n\t\t}\n\n\t\tresult.push(number);\n\t});\n\treturn result;\n}\n"],"mappings":"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"}