UNPKG

@avalabs/hw-app-avalanche

Version:

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

161 lines (144 loc) 4.72 kB
import Transport from '@ledgerhq/hw-transport' export const CLA = 0x80 export const CLA_ETH = 0xe0 export const CHUNK_SIZE = 250 export const APP_KEY = 'AVAX' export const FIRST_MESSAGE = 0x01 export const LAST_MESSAGE = 0x02 export const NEXT_MESSAGE = 0x03 export const HASH_LEN = 32 export const COLLECTION_NAME_MAX_LEN = 70 export const CHAIN_ID_SIZE = 8 export const CONTRACT_ADDRESS_LEN = 20 export const TYPE_1 = 1 export const VERSION_1 = 1 export const ADDRESS_LENGTH = 20 export const ALGORITHM_ID_1 = 1 export const ALGORITHM_ID_SIZE = 1 export const TYPE_SIZE = 1 export const VERSION_SIZE = 1 export const SIGNATURE_LENGTH_SIZE = 1 export const ED25519_PK_SIZE = 32 export const INS = { GET_VERSION: 0x00, WALLET_ID: 0x01, GET_ADDR: 0x02, GET_EXTENDED_PUBLIC_KEY: 0x03, SIGN_HASH: 0x04, SIGN: 0x05, SIGN_MSG: 0x06, ETH_PROVIDE_NFT_INFO: 0x14, } export const PAYLOAD_TYPE = { INIT: 0x00, ADD: 0x01, LAST: 0x02, } export const P1_VALUES = { ONLY_RETRIEVE: 0x00, SHOW_ADDRESS_IN_DEVICE: 0x01, } export const P2_VALUES = { SECP256K1: 0x00, ED25519: 0x01, } export enum LedgerError { U2FUnknown = 1, U2FBadRequest = 2, U2FConfigurationUnsupported = 3, U2FDeviceIneligible = 4, U2FTimeout = 5, Timeout = 14, NoErrors = 0x9000, DeviceIsBusy = 0x9001, ErrorDerivingKeys = 0x6802, ExecutionError = 0x6400, WrongLength = 0x6700, EmptyBuffer = 0x6982, OutputBufferTooSmall = 0x6983, DataIsInvalid = 0x6a80, ConditionsNotSatisfied = 0x6985, TransactionRejected = 0x6986, BadKeyHandle = 0x6a81, InvalidP1P2 = 0x6b00, InstructionNotSupported = 0x6d00, AppDoesNotSeemToBeOpen = 0x6e01, UnknownError = 0x6f00, SignVerifyError = 0x6f01, } export const 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', } export function errorCodeToString(statusCode: LedgerError) { if (statusCode in ERROR_DESCRIPTION) return ERROR_DESCRIPTION[statusCode] return `Unknown Status Code: ${statusCode}` } function isDict(v: any) { return typeof v === 'object' && v !== null && !(v instanceof Array) && !(v instanceof Date) } export function processErrorResponse(response?: any) { if (response) { if (isDict(response)) { if (Object.prototype.hasOwnProperty.call(response, 'statusCode')) { return { returnCode: response.statusCode, errorMessage: errorCodeToString(response.statusCode), } } if (Object.prototype.hasOwnProperty.call(response, 'returnCode') && Object.prototype.hasOwnProperty.call(response, 'errorMessage')) { return response } } return { returnCode: 0xffff, errorMessage: response.toString(), } } return { returnCode: 0xffff, errorMessage: response.toString(), } } export async function getVersion(transport: Transport) { return transport.send(CLA, INS.GET_VERSION, 0, 0).then(response => { const errorCodeData = response.slice(-2) const returnCode = (errorCodeData[0] * 256 + errorCodeData[1]) as LedgerError let targetId = 0 if (response.length >= 9) { /* eslint-disable no-bitwise */ targetId = (response[5] << 24) + (response[6] << 16) + (response[7] << 8) + (response[8] << 0) /* eslint-enable no-bitwise */ } return { returnCode, errorMessage: errorCodeToString(returnCode), testMode: response[0] !== 0, major: response[1], minor: response[2], patch: response[3], deviceLocked: response[4] === 1, targetId: targetId.toString(16), } }, processErrorResponse) }