Skip to content

Commit

Permalink
✨ (core) [DSDK-298]: Implement Open Application command (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
jiyuzhuang authored May 24, 2024
2 parents a30ff2e + 06f2f60 commit 367da2d
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-maps-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/device-sdk-core": minor
---

Implement Open Application command.
36 changes: 36 additions & 0 deletions packages/core/src/api/command/os/OpenAppCommand.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ApduResponse } from "@api/device-session/ApduResponse";

import { OpenAppCommand } from "./OpenAppCommand";

describe("OpenAppCommand", () => {
let openAppCommand: OpenAppCommand;

beforeEach(() => {
openAppCommand = new OpenAppCommand();
});

it("should return the correct APDU for opening an application", () => {
const appName = "MyApp";
const expectedApdu = Uint8Array.from([
0xe0, 0xd8, 0x00, 0x00, 0x05, 0x4d, 0x79, 0x41, 0x70, 0x70,
]);
const apdu = openAppCommand.getApdu(appName);
expect(apdu.getRawApdu()).toStrictEqual(expectedApdu);
});

it("should not throw error when command is successful", () => {
const apduResponse: ApduResponse = new ApduResponse({
statusCode: new Uint8Array([0x90, 0x00]),
data: new Uint8Array([]),
});
expect(() => openAppCommand.parseResponse(apduResponse)).not.toThrow();
});

it("should throw error when command is unsuccessful", () => {
const apduResponse: ApduResponse = new ApduResponse({
statusCode: new Uint8Array([0x6a, 0x81]),
data: new Uint8Array([]),
});
expect(() => openAppCommand.parseResponse(apduResponse)).toThrow();
});
});
36 changes: 36 additions & 0 deletions packages/core/src/api/command/os/OpenAppCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Apdu } from "@api/apdu/model/Apdu";
import { ApduBuilder, ApduBuilderArgs } from "@api/apdu/utils/ApduBuilder";
import { ApduParser } from "@api/apdu/utils/ApduParser";
import { Command } from "@api/command/Command";
import { InvalidStatusWordError } from "@api/command/Errors";
import { CommandUtils } from "@api/command/utils/CommandUtils";
import { ApduResponse } from "@api/device-session/ApduResponse";

/**
* The command to open an application on the device.
*/
export class OpenAppCommand implements Command<void, string> {
getApdu(appName: string): Apdu {
const openAppApduArgs: ApduBuilderArgs = {
cla: 0xe0,
ins: 0xd8,
p1: 0x00,
p2: 0x00,
} as const;
return new ApduBuilder(openAppApduArgs)
.addAsciiStringToData(appName)
.build();
}

parseResponse(apduResponse: ApduResponse): void {
const parser = new ApduParser(apduResponse);

if (!CommandUtils.isSuccessResponse(apduResponse)) {
throw new InvalidStatusWordError(
`Unexpected status word: ${parser.encodeToHexaString(
apduResponse.statusCode,
)}`,
);
}
}
}

0 comments on commit 367da2d

Please sign in to comment.