UNPKG

@zondax/ledger-lisk

Version:

Node API for the Lisk App (Ledger Nano S/X/S+)

155 lines (154 loc) 7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.serializePath = exports.getVersion = exports.processErrorResponse = exports.errorCodeToString = exports.ERROR_DESCRIPTION = exports.LedgerError = exports.ERROR_CODE = exports.P2_VALUES = exports.P1_VALUES = exports.PAYLOAD_TYPE = exports.CHUNK_SIZE = void 0; const config_1 = require("./config"); exports.CHUNK_SIZE = 250; exports.PAYLOAD_TYPE = { INIT: 0x00, ADD: 0x01, LAST: 0x02, }; exports.P1_VALUES = { ONLY_RETRIEVE: 0x00, SHOW_ADDRESS_IN_DEVICE: 0x01, }; exports.P2_VALUES = { DEFAULT: 0x00, }; exports.ERROR_CODE = { NoError: 0x9000, }; var LedgerError; (function (LedgerError) { LedgerError[LedgerError["U2FUnknown"] = 1] = "U2FUnknown"; LedgerError[LedgerError["U2FBadRequest"] = 2] = "U2FBadRequest"; LedgerError[LedgerError["U2FConfigurationUnsupported"] = 3] = "U2FConfigurationUnsupported"; LedgerError[LedgerError["U2FDeviceIneligible"] = 4] = "U2FDeviceIneligible"; LedgerError[LedgerError["U2FTimeout"] = 5] = "U2FTimeout"; LedgerError[LedgerError["Timeout"] = 14] = "Timeout"; LedgerError[LedgerError["NoErrors"] = 36864] = "NoErrors"; LedgerError[LedgerError["DeviceIsBusy"] = 36865] = "DeviceIsBusy"; LedgerError[LedgerError["ErrorDerivingKeys"] = 26626] = "ErrorDerivingKeys"; LedgerError[LedgerError["ExecutionError"] = 25600] = "ExecutionError"; LedgerError[LedgerError["WrongLength"] = 26368] = "WrongLength"; LedgerError[LedgerError["EmptyBuffer"] = 27010] = "EmptyBuffer"; LedgerError[LedgerError["OutputBufferTooSmall"] = 27011] = "OutputBufferTooSmall"; LedgerError[LedgerError["DataIsInvalid"] = 27012] = "DataIsInvalid"; LedgerError[LedgerError["ConditionsNotSatisfied"] = 27013] = "ConditionsNotSatisfied"; LedgerError[LedgerError["TransactionRejected"] = 27014] = "TransactionRejected"; LedgerError[LedgerError["BadKeyHandle"] = 27264] = "BadKeyHandle"; LedgerError[LedgerError["InvalidP1P2"] = 27392] = "InvalidP1P2"; LedgerError[LedgerError["InstructionNotSupported"] = 27904] = "InstructionNotSupported"; LedgerError[LedgerError["AppDoesNotSeemToBeOpen"] = 28161] = "AppDoesNotSeemToBeOpen"; LedgerError[LedgerError["UnknownError"] = 28416] = "UnknownError"; LedgerError[LedgerError["SignVerifyError"] = 28417] = "SignVerifyError"; })(LedgerError || (exports.LedgerError = LedgerError = {})); exports.ERROR_DESCRIPTION = { [LedgerError.U2FUnknown]: "U2F: Unknown", [LedgerError.U2FBadRequest]: "U2F: Bad request", [LedgerError.U2FConfigurationUnsupported]: "U2F: Configuration unsupported", [LedgerError.U2FDeviceIneligible]: "U2F: Device Ineligible", [LedgerError.U2FTimeout]: "U2F: Timeout", [LedgerError.Timeout]: "Timeout", [LedgerError.NoErrors]: "No errors", [LedgerError.DeviceIsBusy]: "Device is busy", [LedgerError.ErrorDerivingKeys]: "Error deriving keys", [LedgerError.ExecutionError]: "Execution Error", [LedgerError.WrongLength]: "Wrong Length", [LedgerError.EmptyBuffer]: "Empty Buffer", [LedgerError.OutputBufferTooSmall]: "Output buffer too small", [LedgerError.DataIsInvalid]: "Data is invalid", [LedgerError.ConditionsNotSatisfied]: "Conditions not satisfied", [LedgerError.TransactionRejected]: "Transaction rejected", [LedgerError.BadKeyHandle]: "Bad key handle", [LedgerError.InvalidP1P2]: "Invalid P1/P2", [LedgerError.InstructionNotSupported]: "Instruction not supported", [LedgerError.AppDoesNotSeemToBeOpen]: "App does not seem to be open", [LedgerError.UnknownError]: "Unknown error", [LedgerError.SignVerifyError]: "Sign/verify error", }; function errorCodeToString(statusCode) { if (statusCode in exports.ERROR_DESCRIPTION) return exports.ERROR_DESCRIPTION[statusCode]; return `Unknown Status Code: ${statusCode}`; } exports.errorCodeToString = errorCodeToString; function isDict(v) { return typeof v === "object" && v !== null && !(v instanceof Array) && !(v instanceof Date); } function processErrorResponse(response) { if (response) { if (isDict(response)) { if (Object.prototype.hasOwnProperty.call(response, "statusCode")) { return { returnCode: response.statusCode, errorMessage: errorCodeToString(response.statusCode), // legacy return_code: response.statusCode, error_message: errorCodeToString(response.statusCode), }; } if (Object.prototype.hasOwnProperty.call(response, "returnCode") && Object.prototype.hasOwnProperty.call(response, "errorMessage")) { return response; } } return { returnCode: 0xffff, errorMessage: response.toString(), // legacy return_code: 0xffff, error_message: response.toString(), }; } return { returnCode: 0xffff, errorMessage: response.toString(), }; } exports.processErrorResponse = processErrorResponse; async function getVersion(transport) { return await transport.send(config_1.CLA, 0 /* INS.GET_VERSION */, 0, 0).then((response) => { const errorCodeData = response.subarray(-2); const returnCode = (errorCodeData[0] * 256 + errorCodeData[1]); return { deviceLocked: response[4] === 1, major: response[1], minor: response[2], patch: response[3], test_mode: response[0] !== 0, return_code: returnCode, error_message: errorCodeToString(returnCode), }; }, processErrorResponse); } exports.getVersion = getVersion; const HARDENED = 0x80000000; const DER_PATH_LEN = 4; function serializePath(path) { if (!path.startsWith("m")) { throw new Error(`Path should start with "m" (e.g "m/44'/134'/5'")`); } const pathArray = path.split("/"); let allocSize = 0; if (pathArray.length !== DER_PATH_LEN) throw new Error(`Invalid path length. (e.g "m/44'/134'/0'")`); allocSize = (pathArray.length - 1) * 4 + 1; const buf = Buffer.alloc(allocSize); buf.writeUInt8(pathArray.length - 1, 0); for (let i = 1; i < pathArray.length; i += 1) { if (!pathArray[i].endsWith("'")) throw new Error(`All path components need to be hardened. (e.g "m/44'/134'/0'")`); const child = pathArray[i].slice(0, -1); const childNumber = Number(child); if (Number.isNaN(childNumber)) { throw new Error(`Invalid path : ${child} is not a number. (e.g "m/44'/134'/5'")`); } if (childNumber >= HARDENED) throw new Error("Incorrect child value (bigger or equal to 0x80000000)"); const value = HARDENED + childNumber; buf.writeUInt32LE(value, 4 * (i - 1) + 1); } return buf; } exports.serializePath = serializePath;