Skip to content

Commit

Permalink
🩹 (signer-eth): Provide web3checks with generic parser context
Browse files Browse the repository at this point in the history
  • Loading branch information
aussedatlo committed Feb 3, 2025
1 parent 31b6056 commit 6e943ad
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 9 deletions.
3 changes: 2 additions & 1 deletion packages/signer/context-module/src/DefaultContextModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { type NftContextLoader } from "./nft/domain/NftContextLoader";
import { type ContextLoader } from "./shared/domain/ContextLoader";
import {
type ClearSignContext,
type ClearSignContextSuccess,
ClearSignContextType,
} from "./shared/model/ClearSignContext";
import {
Expand Down Expand Up @@ -106,7 +107,7 @@ export class DefaultContextModule implements ContextModule {

public async getWeb3Checks(
transactionContext: Web3CheckContext,
): Promise<ClearSignContext | null> {
): Promise<ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null> {
const web3Checks = await this._web3CheckLoader.load(transactionContext);

if (web3Checks.isLeft()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
type ClearSignContextSuccess,
type ClearSignContextType,
type ContextModule,
} from "@ledgerhq/context-module";
import {
Expand Down Expand Up @@ -52,7 +53,7 @@ export type SignTransactionDAInternalState = {
readonly error: SignTransactionDAError | null;
readonly challenge: string | null;
readonly clearSignContexts: ClearSignContextSuccess[] | GenericContext | null;
readonly web3Check: ClearSignContextSuccess | null;
readonly web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;
readonly serializedTransaction: Uint8Array | null;
readonly chainId: number | null;
readonly transactionType: TransactionType | null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
type ClearSignContextSuccess,
type ClearSignContextType,
type ContextModule,
} from "@ledgerhq/context-module";
import {
Expand Down Expand Up @@ -78,7 +79,7 @@ export type MachineDependencies = {
readonly provideContext: (arg0: {
input: {
clearSignContexts: ClearSignContextSuccess[];
web3Check: ClearSignContextSuccess | null;
web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;
};
}) => Promise<Maybe<CommandErrorResult<EthErrorCodes>>>;
readonly provideGenericContext: (arg0: {
Expand All @@ -89,6 +90,7 @@ export type MachineDependencies = {
derivationPath: string;
serializedTransaction: Uint8Array;
context: GenericContext;
web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;
};
}) => Promise<
Maybe<CommandErrorResult<ProvideTransactionGenericContextTaskErrorCodes>>
Expand Down Expand Up @@ -389,6 +391,7 @@ export class SignTransactionDeviceAction extends XStateDeviceAction<
context._internalState.serializedTransaction!,
context: context._internalState
.clearSignContexts as GenericContext,
web3Check: context._internalState.web3Check,
}),
onDone: {
actions: assign({
Expand Down Expand Up @@ -499,7 +502,7 @@ export class SignTransactionDeviceAction extends XStateDeviceAction<
const provideContext = async (arg0: {
input: {
clearSignContexts: ClearSignContextSuccess[];
web3Check: ClearSignContextSuccess | null;
web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;
};
}) =>
new ProvideTransactionContextTask(internalApi, {
Expand All @@ -515,6 +518,7 @@ export class SignTransactionDeviceAction extends XStateDeviceAction<
derivationPath: string;
serializedTransaction: Uint8Array;
context: GenericContext;
web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;
};
}) =>
new ProvideTransactionGenericContextTask(internalApi, {
Expand All @@ -524,6 +528,7 @@ export class SignTransactionDeviceAction extends XStateDeviceAction<
derivationPath: arg0.input.derivationPath,
serializedTransaction: arg0.input.serializedTransaction,
context: arg0.input.context,
web3Check: arg0.input.web3Check,
}).run();

const signTransaction = async (arg0: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,36 @@ describe("GetWeb3CheckTask", () => {
error: new InvalidStatusWordError("error"),
});
});

it("should return null if the type is not a ClearSignContextSuccess web3check", async () => {
// GIVEN
mapperMock.mapTransactionToSubset.mockReturnValue(
Right({ subset: {}, serializedTransaction: new Uint8Array() }),
);
apiMock.sendCommand.mockResolvedValueOnce(
CommandResultFactory({ data: { web3ChecksEnabled: true } }),
);
apiMock.sendCommand.mockResolvedValueOnce(
CommandResultFactory({ data: { address: "address" } }),
);
contextModuleMock.getWeb3Checks.mockResolvedValue({
type: "invalid-type",
id: 1,
});

// WHEN
const result = await new GetWeb3CheckTask(apiMock, {
contextModule: contextModuleMock as unknown as ContextModule,
mapper: mapperMock as unknown as TransactionMapperService,
transaction,
derivationPath,
}).run();

// THEN
expect(result).toEqual({
web3Check: null,
});
});
});

describe("success", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { type TransactionMapperService } from "@internal/transaction/service/map

export type GetWeb3CheckTaskResult =
| {
readonly web3Check: ClearSignContextSuccess | null;
readonly web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;
}
| {
readonly web3Check: null;
Expand Down Expand Up @@ -90,7 +90,7 @@ export class GetWeb3CheckTask {

if (
web3CheckContext === null ||
web3CheckContext?.type === ClearSignContextType.ERROR
web3CheckContext?.type !== ClearSignContextType.WEB3_CHECK
) {
return {
web3Check: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export type ProvideTransactionContextTaskArgs = {
* The valid clear sign contexts offerred by the `BuildTrancationContextTask`.
*/
clearSignContexts: ClearSignContextSuccess[];
web3Check: ClearSignContextSuccess | null;
web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;
};

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
type ClearSignContextSuccess,
type ClearSignContextSuccessType,
type ClearSignContextType,
ClearSignContextType,
type ContextModule,
type PkiCertificate,
} from "@ledgerhq/context-module";
Expand Down Expand Up @@ -52,6 +52,7 @@ describe("ProvideTransactionGenericContextTask", () => {
chainId,
transactionParser,
contextModule,
web3Check: null,
};

const apiMock = makeDeviceActionInternalApiMock();
Expand Down Expand Up @@ -293,5 +294,39 @@ describe("ProvideTransactionGenericContextTask", () => {
// THEN
expect(apiMock.sendCommand).toHaveBeenCalledTimes(1);
});

it("should load the web3 check certificate", async () => {
// GIVEN
const web3Check: ClearSignContextSuccess = {
type: ClearSignContextType.WEB3_CHECK,
certificate: {
keyUsageNumber: 0,
payload: new Uint8Array([0x12, 0x34]),
},
payload: "0x01020304",
};
jest.spyOn(SendCommandInChunksTask.prototype, "run").mockResolvedValue(
CommandResultFactory({
data: "0x1234",
}),
);
jest.spyOn(SendPayloadInChunksTask.prototype, "run").mockResolvedValue(
CommandResultFactory({
data: "0x5678",
}),
);
jest
.spyOn(ProvideTransactionFieldDescriptionTask.prototype, "run")
.mockResolvedValue(Nothing);

// WHEN
await new ProvideTransactionGenericContextTask(apiMock, {
...defaultArgs,
web3Check,
}).run();

// THEN
expect(apiMock.sendCommand).toHaveBeenCalledTimes(3);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export type ProvideTransactionGenericContextTaskArgs = {
readonly derivationPath: string;
readonly serializedTransaction: Uint8Array;
readonly context: GenericContext;
readonly web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;
};

export type ProvideTransactionGenericContextTaskErrorCodes =
Expand Down Expand Up @@ -100,8 +101,13 @@ export class ProvideTransactionGenericContextTask {
return Just(transactionInfoResult);
}

// If there is a web3 check, add it to the transactionField array
const fields = this.args.web3Check
? [...this.args.context.transactionFields, this.args.web3Check]
: this.args.context.transactionFields;

// Provide the transaction field description and according metadata reference
for (const field of this.args.context.transactionFields) {
for (const field of fields) {
const result = await new ProvideTransactionFieldDescriptionTask(
this.api,
{
Expand Down

0 comments on commit 6e943ad

Please sign in to comment.