Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default class BaseApp {
readonly P1_VALUES: P1_VALUESGeneric
readonly REQUIRED_PATH_LENGTHS?: number[]
readonly CHUNK_SIZE: number
readonly CUSTOM_APP_ERROR_DESCRIPTION?: Readonly<Record<LedgerError, string>>

/**
* Constructs a new BaseApp instance.
Expand All @@ -56,6 +57,7 @@ export default class BaseApp {
this.P1_VALUES = params.p1Values
this.CHUNK_SIZE = params.chunkSize
this.REQUIRED_PATH_LENGTHS = params.acceptedPathLengths
this.CUSTOM_APP_ERROR_DESCRIPTION = params.customAppErrorDescription
}

/**
Expand Down Expand Up @@ -125,7 +127,7 @@ export default class BaseApp {
const statusList = [LedgerError.NoErrors, LedgerError.DataIsInvalid, LedgerError.BadKeyHandle]

const responseBuffer = await this.transport.send(this.CLA, ins, payloadType, p2, chunk, statusList)
const response = processResponse(responseBuffer)
const response = processResponse(responseBuffer, this.CUSTOM_APP_ERROR_DESCRIPTION)

return response
}
Expand Down Expand Up @@ -154,7 +156,7 @@ export default class BaseApp {
async getVersion(): Promise<ResponseVersion> {
try {
const responseBuffer = await this.transport.send(this.CLA, this.INS.GET_VERSION, 0, 0)
const response = processResponse(responseBuffer)
const response = processResponse(responseBuffer, this.CUSTOM_APP_ERROR_DESCRIPTION)

// valid options are
// test mode: 1 byte
Expand Down Expand Up @@ -224,7 +226,7 @@ export default class BaseApp {
async appInfo(): Promise<ResponseAppInfo> {
try {
const responseBuffer = await this.transport.send(LEDGER_DASHBOARD_CLA, 0x01, 0, 0)
const response = processResponse(responseBuffer)
const response = processResponse(responseBuffer, this.CUSTOM_APP_ERROR_DESCRIPTION)

const formatId = response.readBytes(1).readUInt8()

Expand Down Expand Up @@ -264,7 +266,7 @@ export default class BaseApp {
async deviceInfo(): Promise<ResponseDeviceInfo> {
try {
const responseBuffer = await this.transport.send(0xe0, 0x01, 0, 0, Buffer.from([]), [LedgerError.NoErrors, 0x6e00])
const response = processResponse(responseBuffer)
const response = processResponse(responseBuffer, this.CUSTOM_APP_ERROR_DESCRIPTION)

const targetId = response.readBytes(4).toString('hex')

Expand Down
12 changes: 7 additions & 5 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
import { LedgerError } from './consts'
import { LedgerCustomError, LedgerError } from './consts'
import { errorCodeToString } from './errors'
import { ResponsePayload } from './payload'
import { ResponseError } from './responseError'
Expand All @@ -35,18 +35,19 @@ function isDict(v: any): boolean {
* the payload is returned directly. Otherwise, an error object is thrown.
*
* @param responseRaw - The raw response buffer from the device, potentially containing error codes or data.
* @param customErrorList - Custom error description list to convert error code with.
* @returns The payload as a buffer if no errors are found.
* @throws {ResponseError} An object detailing the error if any is found.
*/
export function processResponse(responseRaw: Buffer): ResponsePayload {
export function processResponse(responseRaw: Buffer, customErrorList?: Record<LedgerCustomError, string>): ResponsePayload {
// Ensure the buffer is large enough to contain a return code
if (responseRaw.length < 2) {
throw ResponseError.fromReturnCode(LedgerError.EmptyBuffer)
}

// Determine the return code from the last two bytes of the response
const returnCode = responseRaw.readUInt16BE(responseRaw.length - 2)
let errorMessage = errorCodeToString(returnCode)
let errorMessage = errorCodeToString(returnCode, customErrorList)

// Isolate the payload (all bytes except the last two)
const payload = responseRaw.subarray(0, responseRaw.length - 2)
Expand All @@ -70,12 +71,13 @@ export function processResponse(responseRaw: Buffer): ResponsePayload {
* This function is deprecated and should not be used in new implementations.
*
* @param response - The raw response object that may contain error details.
* @param customErrorList - Custom error description list to convert error code with.
* @returns A standardized error response object.
*/
export function processErrorResponse(response: any): ResponseError {
export function processErrorResponse(response: any, customErrorList?: Record<LedgerCustomError, string>): ResponseError {
if (isDict(response)) {
if (Object.prototype.hasOwnProperty.call(response, 'statusCode')) {
return ResponseError.fromReturnCode(response.statusCode)
return ResponseError.fromReturnCode(response.statusCode, customErrorList)
}

if (Object.prototype.hasOwnProperty.call(response, 'returnCode') && Object.prototype.hasOwnProperty.call(response, 'errorMessage')) {
Expand Down
6 changes: 4 additions & 2 deletions src/responseError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
import { LedgerCustomError } from './consts'
import { errorCodeToString } from './errors'

/**
Expand All @@ -37,9 +38,10 @@ export class ResponseError extends Error {
/**
* Creates a ResponseError instance from a return code.
* @param returnCode - The return code to convert into a ResponseError.
* @param customErrorList - Custom error description list to convert error code with.
* @returns A new instance of ResponseError.
*/
static fromReturnCode(returnCode: number): ResponseError {
return new ResponseError(returnCode, errorCodeToString(returnCode))
static fromReturnCode(returnCode: number, customErrorList?: Record<LedgerCustomError, string>): ResponseError {
return new ResponseError(returnCode, errorCodeToString(returnCode, customErrorList))
}
}
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
import { LedgerCustomError } from './consts'

/**
* Represents the version response from a device.
Expand Down Expand Up @@ -76,6 +77,7 @@ export interface ConstructorParams {
p1Values: P1_VALUESGeneric
chunkSize: number
acceptedPathLengths?: number[]
customAppErrorDescription?: Readonly<Record<LedgerCustomError, string>>
}

export type BIP32Path = string