Skip to content

Commit

Permalink
🩹 (signer-eth): Send web3checks partner certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
aussedatlo committed Feb 3, 2025
1 parent b559a45 commit 31b6056
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DeviceModelId } from "@ledgerhq/device-management-kit";
import { Left, Right } from "purify-ts";

import { type ContextModuleConfig } from "./config/model/ContextModuleConfig";
Expand Down Expand Up @@ -128,6 +129,7 @@ describe("DefaultContextModule", () => {
});

const res = await contextModule.getWeb3Checks({
deviceModelId: DeviceModelId.FLEX,
from: "from",
rawTx: "rawTx",
chainId: 1,
Expand All @@ -147,6 +149,7 @@ describe("DefaultContextModule", () => {
});

const res = await contextModule.getWeb3Checks({
deviceModelId: DeviceModelId.FLEX,
from: "from",
rawTx: "rawTx",
chainId: 1,
Expand Down
3 changes: 1 addition & 2 deletions packages/signer/context-module/src/DefaultContextModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,10 @@ export class DefaultContextModule implements ContextModule {
return null;
} else {
const web3ChecksValue = web3Checks.unsafeCoerce();
// add Nano PKI fetch here should looks like =>
// const web3CheckCertificate = await this._pkiCertificateLoader.fetchCertificate(...)
return {
type: ClearSignContextType.WEB3_CHECK,
payload: web3ChecksValue.descriptor,
certificate: web3ChecksValue.certificate,
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Left, Right } from "purify-ts";

import { type ContextModuleConfig } from "@/config/model/ContextModuleConfig";
import { HttpPkiCertificateDataSource } from "@/pki/data/HttpPkiCertificateDataSource";
import { type KeyId } from "@/pki/model/KeyId";
import { KeyUsage } from "@/pki/model/KeyUsage";
import { type PkiCertificateInfo } from "@/pki/model/PkiCertificateInfo";

Expand All @@ -23,7 +24,7 @@ describe("HttpPkiCertificateDataSource", () => {
const pkiCertificateInfo: PkiCertificateInfo = {
targetDevice: "targetDevice",
keyUsage: KeyUsage.Calldata,
keyId: "keyId",
keyId: "keyId" as KeyId,
};
jest.spyOn(axios, "request").mockResolvedValue({
status: 200,
Expand Down Expand Up @@ -60,7 +61,7 @@ describe("HttpPkiCertificateDataSource", () => {
const pkiCertificateInfo: PkiCertificateInfo = {
targetDevice: "targetDevice",
keyUsage: KeyUsage.Calldata,
keyId: "keyId",
keyId: "keyId" as KeyId,
};
jest.spyOn(axios, "request").mockResolvedValue({
status: 200,
Expand All @@ -87,7 +88,7 @@ describe("HttpPkiCertificateDataSource", () => {
const pkiCertificateInfo: PkiCertificateInfo = {
targetDevice: "targetDevice",
keyUsage: KeyUsage.Calldata,
keyId: "keyId",
keyId: "keyId" as KeyId,
};
jest.spyOn(axios, "request").mockRejectedValue(new Error("error"));

Expand All @@ -111,7 +112,7 @@ describe("HttpPkiCertificateDataSource", () => {
const pkiCertificateInfo: PkiCertificateInfo = {
targetDevice: "targetDevice",
keyUsage: KeyUsage.Calldata,
keyId: "keyId",
keyId: "keyId" as KeyId,
};
jest.spyOn(axios, "request").mockResolvedValue({
status: 200,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Right } from "purify-ts";

import { DefaultPkiCertificateLoader } from "@/pki/domain/DefaultPkiCertificateLoader";
import { KeyId } from "@/pki/model/KeyId";
import { KeyUsage } from "@/pki/model/KeyUsage";
import { type PkiCertificateInfo } from "@/pki/model/PkiCertificateInfo";

Expand All @@ -11,7 +12,7 @@ describe("DefaultPkiCertificateLoader", () => {
const certificateInfos: PkiCertificateInfo = {
targetDevice: "targetDevice",
keyUsage: KeyUsage.Calldata,
keyId: "keyId",
keyId: KeyId.CalNetwork,
};
const certificate = {
keyUsageNumber: 11,
Expand Down
1 change: 1 addition & 0 deletions packages/signer/context-module/src/pki/model/KeyId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export enum KeyId {
CalCalldataKey = "cal_calldata_key",
CalTrustedNameKey = "cal_trusted_name_key",
CalNetwork = "cal_network",
Blockaid = "blockaid",
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { KeyUsage } from "@/pki/model/KeyUsage";

import { type KeyId } from "./KeyId";

export type PkiCertificateInfo = {
targetDevice: string;
keyUsage: KeyUsage;
keyId?: string | undefined;
keyId: KeyId;
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { DeviceModelId } from "@ledgerhq/device-management-kit";
import axios from "axios";
import { Left, Right } from "purify-ts";

import { type ContextModuleConfig } from "@/config/model/ContextModuleConfig";
import { type PkiCertificateLoader } from "@/pki/domain/PkiCertificateLoader";
import { KeyId } from "@/pki/model/KeyId";
import { HttpWeb3CheckDataSource } from "@/web3-check/data/HttpWeb3CheckDataSource";
import { type Web3CheckDto } from "@/web3-check/data/Web3CheckDto";
import { type Web3CheckContext } from "@/web3-check/domain/web3CheckTypes";
Expand All @@ -14,6 +17,9 @@ describe("HttpWeb3CheckDataSource", () => {
url: "web3checksUrl",
},
} as ContextModuleConfig;
const certificateLoaderMock = {
loadCertificate: jest.fn(),
};

beforeEach(() => {
jest.resetAllMocks();
Expand All @@ -23,41 +29,90 @@ describe("HttpWeb3CheckDataSource", () => {
it("should return an object if the request is successful", async () => {
// GIVEN
const params: Web3CheckContext = {
deviceModelId: DeviceModelId.FLEX,
from: "from",
rawTx: "rawTx",
chainId: 1,
};
const dto: Web3CheckDto = {
block: 1,
public_key_id: "publicKeyId",
public_key_id: KeyId.Blockaid,
descriptor: "descriptor",
};
jest.spyOn(axios, "request").mockResolvedValue({ data: dto });
jest.spyOn(axios, "request").mockResolvedValueOnce({ data: dto });
jest
.spyOn(certificateLoaderMock, "loadCertificate")
.mockResolvedValueOnce(undefined);

// WHEN
const dataSource = new HttpWeb3CheckDataSource(config);
const dataSource = new HttpWeb3CheckDataSource(
config,
certificateLoaderMock as unknown as PkiCertificateLoader,
);
const result = await dataSource.getWeb3Checks(params);

// THEN
expect(result).toEqual(
Right({
publicKeyId: "publicKeyId",
publicKeyId: "blockaid",
descriptor: "descriptor",
}),
);
});

it("should return an object with a certificate if the request is successful", async () => {
// GIVEN
const params: Web3CheckContext = {
deviceModelId: DeviceModelId.FLEX,
from: "from",
rawTx: "rawTx",
chainId: 1,
};
const dto: Web3CheckDto = {
block: 1,
public_key_id: KeyId.Blockaid,
descriptor: "descriptor",
};
jest.spyOn(axios, "request").mockResolvedValueOnce({ data: dto });
jest
.spyOn(certificateLoaderMock, "loadCertificate")
.mockResolvedValueOnce({
keyUsageNumber: 11,
payload: new Uint8Array([0x01]),
});

// WHEN
const dataSource = new HttpWeb3CheckDataSource(
config,
certificateLoaderMock as unknown as PkiCertificateLoader,
);
const result = await dataSource.getWeb3Checks(params);

// THEN
expect(result).toEqual(
Right({
publicKeyId: "blockaid",
descriptor: "descriptor",
certificate: { keyUsageNumber: 11, payload: new Uint8Array([0x01]) },
}),
);
});

it("should return an error if the request fails", async () => {
// GIVEN
const params: Web3CheckContext = {
deviceModelId: DeviceModelId.FLEX,
from: "from",
rawTx: "rawTx",
chainId: 1,
};
jest.spyOn(axios, "request").mockRejectedValue(new Error("error"));

// WHEN
const dataSource = new HttpWeb3CheckDataSource(config);
const dataSource = new HttpWeb3CheckDataSource(
config,
certificateLoaderMock as unknown as PkiCertificateLoader,
);
const result = await dataSource.getWeb3Checks(params);

// THEN
Expand All @@ -73,15 +128,22 @@ describe("HttpWeb3CheckDataSource", () => {
it("should return an error if the response is invalid", async () => {
// GIVEN
const params: Web3CheckContext = {
deviceModelId: DeviceModelId.FLEX,
from: "from",
rawTx: "rawTx",
chainId: 1,
};
const dto = {};
jest.spyOn(axios, "request").mockResolvedValue({ data: dto });
jest
.spyOn(certificateLoaderMock, "loadCertificate")
.mockResolvedValue(undefined);

// WHEN
const dataSource = new HttpWeb3CheckDataSource(config);
const dataSource = new HttpWeb3CheckDataSource(
config,
certificateLoaderMock as unknown as PkiCertificateLoader,
);
const result = await dataSource.getWeb3Checks(params);

// THEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { Either, Left, Right } from "purify-ts";

import { configTypes } from "@/config/di/configTypes";
import type { ContextModuleConfig } from "@/config/model/ContextModuleConfig";
import { pkiTypes } from "@/pki/di/pkiTypes";
import { type PkiCertificateLoader } from "@/pki/domain/PkiCertificateLoader";
import { KeyUsage } from "@/pki/model/KeyUsage";
import {
type Web3CheckContext,
type Web3Checks,
Expand All @@ -17,20 +20,25 @@ import { GetWeb3ChecksRequestDto, Web3CheckDto } from "./Web3CheckDto";
export class HttpWeb3CheckDataSource implements Web3CheckDataSource {
constructor(
@inject(configTypes.Config) private readonly config: ContextModuleConfig,
@inject(pkiTypes.PkiCertificateLoader)
private readonly _certificateLoader: PkiCertificateLoader,
) {}

async getWeb3Checks(
params: Web3CheckContext,
): Promise<Either<Error, Web3Checks>> {
async getWeb3Checks({
chainId,
deviceModelId,
from,
rawTx,
}: Web3CheckContext): Promise<Either<Error, Web3Checks>> {
let web3CheckDto: Web3CheckDto;

try {
const requestDto: GetWeb3ChecksRequestDto = {
tx: {
from: params.from,
raw: params.rawTx,
from,
raw: rawTx,
},
chain: params.chainId,
chain: chainId,
preset: "blockaid",
};
const response = await axios.request<Web3CheckDto>({
Expand Down Expand Up @@ -59,9 +67,16 @@ export class HttpWeb3CheckDataSource implements Web3CheckDataSource {
);
}

const certificate = await this._certificateLoader.loadCertificate({
keyId: web3CheckDto.public_key_id,
keyUsage: "replace-me" as KeyUsage, // TODO: replace with the keyUsage given by the API
targetDevice: deviceModelId,
});

const result: Web3Checks = {
publicKeyId: web3CheckDto.public_key_id,
descriptor: web3CheckDto.descriptor,
certificate,
};

return Right(result);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { type KeyId } from "@/pki/model/KeyId";

export type GetWeb3ChecksRequestDto = {
tx: {
from: string;
Expand All @@ -9,7 +11,7 @@ export type GetWeb3ChecksRequestDto = {
};

export type Web3CheckDto = {
public_key_id: string;
public_key_id: KeyId;
descriptor: string;
block: number;
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class DefaultWeb3CheckContextLoader implements Web3CheckContextLoader {
async load(
web3CheckContext: Web3CheckContext,
): Promise<Either<Error, Web3Checks>> {
const { chainId, rawTx, from } = web3CheckContext;
const { rawTx, from } = web3CheckContext;

if (rawTx == undefined || typeof rawTx != "string") {
return Left(
Expand All @@ -40,10 +40,6 @@ export class DefaultWeb3CheckContextLoader implements Web3CheckContextLoader {
}

// Handle descritor payload
return await this._dataSource.getWeb3Checks({
chainId: chainId,
rawTx: rawTx,
from: from,
});
return await this._dataSource.getWeb3Checks(web3CheckContext);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { type DeviceModelId } from "@ledgerhq/device-management-kit";

import { type PkiCertificate } from "@/pki/model/PkiCertificate";

export type Web3CheckContext = {
from: string;
rawTx: string;
chainId: number;
deviceModelId: DeviceModelId;
};

export type Web3Checks = {
publicKeyId: string;
descriptor: string;
certificate?: PkiCertificate;
};
Loading

0 comments on commit 31b6056

Please sign in to comment.