-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ (signer-utils): Create CommandErrorHelper
- Loading branch information
1 parent
df4ef37
commit a00e30c
Showing
4 changed files
with
112 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@ledgerhq/signer-utils": patch | ||
--- | ||
|
||
Create CommandErrorHelper to handle command errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from "./utils/CommandErrorHelper"; | ||
export * from "./utils/DerivationPathUtils"; |
62 changes: 62 additions & 0 deletions
62
packages/signer/signer-utils/src/utils/CommandErrorHelper.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { | ||
ApduResponse, | ||
CommandResultFactory, | ||
GlobalCommandErrorHandler, | ||
} from "@ledgerhq/device-management-kit"; | ||
|
||
import { CommandErrorHelper } from "./CommandErrorHelper"; | ||
|
||
describe("CommandErrorHelper", () => { | ||
it("should return the correct error args and call factory when error is found", () => { | ||
// given | ||
const errors = { | ||
"4224": { message: "An error occurred" }, | ||
}; | ||
const errorFactory = jest.fn(); | ||
const helper = new CommandErrorHelper(errors, errorFactory); | ||
const apduResponse = new ApduResponse({ | ||
statusCode: Uint8Array.from([0x42, 0x24]), | ||
data: Uint8Array.from([]), | ||
}); | ||
// when | ||
helper.getError(apduResponse); | ||
// then | ||
expect(errorFactory).toHaveBeenNthCalledWith(1, { | ||
...errors["4224"], | ||
errorCode: "4224", | ||
}); | ||
}); | ||
it("should return a global error when no error is found", () => { | ||
// given | ||
const errors = {}; | ||
const errorFactory = jest.fn(); | ||
const helper = new CommandErrorHelper(errors, errorFactory); | ||
const apduResponse = new ApduResponse({ | ||
statusCode: Uint8Array.from([0x55, 0x15]), | ||
data: Uint8Array.from([]), | ||
}); | ||
// when | ||
const error = helper.getError(apduResponse); | ||
// then | ||
expect(errorFactory).toHaveBeenCalledTimes(0); | ||
expect(error).toStrictEqual( | ||
CommandResultFactory({ | ||
error: GlobalCommandErrorHandler.handle(apduResponse), | ||
}), | ||
); | ||
}); | ||
it("should return undefined if success apdu response", () => { | ||
// given | ||
const errors = {}; | ||
const errorFactory = jest.fn(); | ||
const helper = new CommandErrorHelper(errors, errorFactory); | ||
const apduResponse = new ApduResponse({ | ||
statusCode: Uint8Array.from([0x90, 0x00]), | ||
data: Uint8Array.from([]), | ||
}); | ||
// when | ||
const error = helper.getError(apduResponse); | ||
// then | ||
expect(error).toBeUndefined(); | ||
}); | ||
}); |
44 changes: 44 additions & 0 deletions
44
packages/signer/signer-utils/src/utils/CommandErrorHelper.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { | ||
ApduParser, | ||
type ApduResponse, | ||
type CommandErrorArgs, | ||
type CommandErrors, | ||
type CommandResult, | ||
CommandResultFactory, | ||
CommandUtils, | ||
type DeviceExchangeError, | ||
GlobalCommandErrorHandler, | ||
isCommandErrorCode, | ||
} from "@ledgerhq/device-management-kit"; | ||
|
||
export class CommandErrorHelper<Response, ErrorCodes extends string> { | ||
constructor( | ||
private readonly _errors: CommandErrors<ErrorCodes>, | ||
private readonly _errorFactory: ( | ||
args: CommandErrorArgs<ErrorCodes>, | ||
) => DeviceExchangeError<ErrorCodes>, | ||
private readonly _isSuccessResponse = CommandUtils.isSuccessResponse, | ||
) {} | ||
|
||
getError( | ||
apduResponse: ApduResponse, | ||
): CommandResult<Response, ErrorCodes> | undefined { | ||
const apduParser = new ApduParser(apduResponse); | ||
const errorCode = apduParser.encodeToHexaString(apduResponse.statusCode); | ||
|
||
if (isCommandErrorCode(errorCode, this._errors)) { | ||
return CommandResultFactory<Response, ErrorCodes>({ | ||
error: this._errorFactory({ | ||
...this._errors[errorCode], | ||
errorCode, | ||
}), | ||
}); | ||
} | ||
if (!this._isSuccessResponse(apduResponse)) { | ||
return CommandResultFactory({ | ||
error: GlobalCommandErrorHandler.handle(apduResponse), | ||
}); | ||
} | ||
return undefined; | ||
} | ||
} |