Skip to content

Commit

Permalink
✨ (signer-solana): Added getAppConfigurationCommand
Browse files Browse the repository at this point in the history
  • Loading branch information
fAnselmi-Ledger committed Oct 28, 2024
1 parent ef548be commit 703e661
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/fast-planes-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/device-signer-kit-solana": patch
---

Added getAppConfigurationCommand in solana-signer
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {
ApduResponse,
CommandResultFactory,
isSuccessCommandResult,
} from "@ledgerhq/device-management-kit";

import { GetAppConfigurationCommand } from "./GetAppConfigurationCommand";

const GET_APP_CONFIG_APDU = new Uint8Array([0xe0, 0x04, 0x00, 0x00, 0x00]);

const GET_APP_CONFIG_RESPONSE_DATA = new Uint8Array([
0x01, 0x00, 0x02, 0x05, 0x0a,
]);

const GET_APP_CONFIG_RESPONSE = new ApduResponse({
statusCode: Uint8Array.from([0x90, 0x00]),
data: GET_APP_CONFIG_RESPONSE_DATA,
});

describe("GetAppConfigurationCommand", () => {
let command: GetAppConfigurationCommand;

beforeEach(() => {
command = new GetAppConfigurationCommand();
jest.clearAllMocks();
jest.requireActual("@ledgerhq/device-management-kit");
});

describe("getApdu", () => {
it("should return the correct APDU", () => {
const apdu = command.getApdu();
expect(apdu.getRawApdu()).toEqual(GET_APP_CONFIG_APDU);
});
});

describe("parseResponse", () => {
it("should parse the response correctly", () => {
const parsed = command.parseResponse(GET_APP_CONFIG_RESPONSE);
expect(parsed).toStrictEqual(
CommandResultFactory({
data: {
blindSigningEnabled: true,
pubKeyDisplayMode: false,
version: "2.5.10",
},
}),
);
});

describe("error handling", () => {
it("should return error if response is not success", () => {
const response = new ApduResponse({
statusCode: Uint8Array.from([0x6a, 0x82]),
data: new Uint8Array(0),
});
const result = command.parseResponse(response);
expect(isSuccessCommandResult(result)).toBe(false);
if (!isSuccessCommandResult(result)) {
expect(result.error).toEqual(
expect.objectContaining({
message: "Unexpected device exchange error happened.",
}),
);
} else {
fail("Expected error");
}
});

it("should return error if response length is invalid", () => {
const response = new ApduResponse({
statusCode: Uint8Array.from([0x90, 0x00]),
data: new Uint8Array([0x01, 0x00]),
});
const result = command.parseResponse(response);
expect(isSuccessCommandResult(result)).toBe(false);
if (!isSuccessCommandResult(result)) {
expect(result.error.originalError).toEqual(
expect.objectContaining({
message: "Invalid response",
}),
);
} else {
fail("Expected error");
}
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import {
Apdu,
ApduBuilder,
ApduParser,
ApduResponse,
Command,
CommandResult,
CommandResultFactory,
CommandUtils,
GlobalCommandErrorHandler,
InvalidStatusWordError,
} from "@ledgerhq/device-management-kit";

type GetAppConfigurationCommandResponse = {
blindSigningEnabled: boolean;
pubKeyDisplayMode: boolean;
version: string;
};

type GetAppConfigurationCommandArgs = void;

export class GetAppConfigurationCommand
implements
Command<GetAppConfigurationCommandResponse, GetAppConfigurationCommandArgs>
{
args: GetAppConfigurationCommandArgs;

constructor(args: GetAppConfigurationCommandArgs) {
this.args = args;
}

getApdu(): Apdu {
return new ApduBuilder({
cla: 0xe0,
ins: 0x04,
p1: 0x00,
p2: 0x00,
}).build();
}

parseResponse(
response: ApduResponse,
): CommandResult<GetAppConfigurationCommandResponse> {
const parser = new ApduParser(response);

if (!CommandUtils.isSuccessResponse(response)) {
return CommandResultFactory({
error: GlobalCommandErrorHandler.handle(response),
});
}

const buffer = parser.extractFieldByLength(5);

if (
!buffer ||
buffer.length !== 5 ||
buffer.some((element) => element === undefined)
) {
return CommandResultFactory({
error: new InvalidStatusWordError("Invalid response"),
});
}

return CommandResultFactory({
data: {
blindSigningEnabled: Boolean(buffer[0]),
pubKeyDisplayMode: Boolean(buffer[1]),
version: `${buffer[2]}.${buffer[3]}.${buffer[4]}`,
},
});
}
}

0 comments on commit 703e661

Please sign in to comment.