Skip to content

Commit

Permalink
✨ (context-module) [DSDK-586]: Implement transaction fields loader (#513
Browse files Browse the repository at this point in the history
)
  • Loading branch information
paoun-ledger authored Dec 2, 2024
2 parents 56164a3 + fa9c3d6 commit bb46c9d
Show file tree
Hide file tree
Showing 37 changed files with 877 additions and 339 deletions.
5 changes: 5 additions & 0 deletions .changeset/fifty-taxis-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/context-module": minor
---

Implement transaction fields loader
6 changes: 5 additions & 1 deletion packages/signer/context-module/src/ContextModule.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { type ClearSignContext } from "@/shared/model/ClearSignContext";

import { type TransactionContext } from "./shared/model/TransactionContext";
import {
type TransactionContext,
type TransactionFieldContext,
} from "./shared/model/TransactionContext";
import { type TypedDataClearSignContext } from "./shared/model/TypedDataClearSignContext";
import { type TypedDataContext } from "./shared/model/TypedDataContext";

export interface ContextModule {
getContext(field: TransactionFieldContext): Promise<ClearSignContext>;
getContexts(transaction: TransactionContext): Promise<ClearSignContext[]>;
getTypedDataFilters(
typedData: TypedDataContext,
Expand Down
66 changes: 64 additions & 2 deletions packages/signer/context-module/src/DefaultContextModule.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { type ContextModuleConfig } from "./config/model/ContextModuleConfig";
import { type TransactionContext } from "./shared/model/TransactionContext";
import {
type TransactionContext,
type TransactionFieldContext,
} from "./shared/model/TransactionContext";
import { type TypedDataContext } from "./shared/model/TypedDataContext";
import type { TypedDataContextLoader } from "./typed-data/domain/TypedDataContextLoader";
import { DefaultContextModule } from "./DefaultContextModule";

const contextLoaderStubBuilder = () => {
return { load: jest.fn() };
return { load: jest.fn(), loadField: jest.fn() };
};

describe("DefaultContextModule", () => {
Expand Down Expand Up @@ -87,4 +90,63 @@ describe("DefaultContextModule", () => {

expect(typedDataLoader.load).toHaveBeenCalledTimes(1);
});

it("should return a single context", async () => {
const loader = contextLoaderStubBuilder();
const responses = [null, { type: "token", payload: "payload" }];
jest
.spyOn(loader, "loadField")
.mockResolvedValueOnce(responses[0])
.mockResolvedValueOnce(responses[1]);
const contextModule = new DefaultContextModule({
...defaultContextModuleConfig,
customLoaders: [loader, { load: jest.fn() }, loader],
});

const res = await contextModule.getContext({
type: "token",
} as TransactionFieldContext);

expect(loader.loadField).toHaveBeenCalledTimes(2);
expect(res).toEqual({ type: "token", payload: "payload" });
});

it("context field not supported", async () => {
const loader = contextLoaderStubBuilder();
const responses = [null, null];
jest
.spyOn(loader, "loadField")
.mockResolvedValueOnce(responses[0])
.mockResolvedValueOnce(responses[1]);
const contextModule = new DefaultContextModule({
...defaultContextModuleConfig,
customLoaders: [loader, { load: jest.fn() }, loader],
});

const res = await contextModule.getContext({
type: "token",
} as TransactionFieldContext);

expect(loader.loadField).toHaveBeenCalledTimes(2);
expect(res).toEqual({
type: "error",
error: new Error("Field type not supported: token"),
});
});

it("getField not implemented", async () => {
const contextModule = new DefaultContextModule({
...defaultContextModuleConfig,
customLoaders: [{ load: jest.fn() }],
});

const res = await contextModule.getContext({
type: "token",
} as TransactionFieldContext);

expect(res).toEqual({
type: "error",
error: new Error("Field type not supported: token"),
});
});
});
33 changes: 27 additions & 6 deletions packages/signer/context-module/src/DefaultContextModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@ import { type Container } from "inversify";
import type { TypedDataClearSignContext } from "@/shared/model/TypedDataClearSignContext";
import type { TypedDataContext } from "@/shared/model/TypedDataContext";
import { transactionTypes } from "@/transaction/di/transactionTypes";
import { trustedNameTypes } from "@/trusted-name/di/trustedNameTypes";

import { type ContextModuleConfig } from "./config/model/ContextModuleConfig";
import { externalPluginTypes } from "./external-plugin/di/externalPluginTypes";
import { type ExternalPluginContextLoader } from "./external-plugin/domain/ExternalPluginContextLoader";
import { forwardDomainTypes } from "./forward-domain/di/forwardDomainTypes";
import { type ForwardDomainContextLoader } from "./forward-domain/domain/ForwardDomainContextLoader";
import { nftTypes } from "./nft/di/nftTypes";
import { type NftContextLoader } from "./nft/domain/NftContextLoader";
import { type ContextLoader } from "./shared/domain/ContextLoader";
import { type ClearSignContext } from "./shared/model/ClearSignContext";
import { type TransactionContext } from "./shared/model/TransactionContext";
import {
type ClearSignContext,
ClearSignContextType,
} from "./shared/model/ClearSignContext";
import {
type TransactionContext,
type TransactionFieldContext,
} from "./shared/model/TransactionContext";
import { tokenTypes } from "./token/di/tokenTypes";
import { type TokenContextLoader } from "./token/domain/TokenContextLoader";
import { type TransactionContextLoader } from "./transaction/domain/TransactionContextLoader";
import { type TrustedNameContextLoader } from "./trusted-name/domain/TrustedNameContextLoader";
import { typedDataTypes } from "./typed-data/di/typedDataTypes";
import type { TypedDataContextLoader } from "./typed-data/domain/TypedDataContextLoader";
import { type ContextModule } from "./ContextModule";
Expand All @@ -40,8 +46,8 @@ export class DefaultContextModule implements ContextModule {
this._container.get<ExternalPluginContextLoader>(
externalPluginTypes.ExternalPluginContextLoader,
),
this._container.get<ForwardDomainContextLoader>(
forwardDomainTypes.ForwardDomainContextLoader,
this._container.get<TrustedNameContextLoader>(
trustedNameTypes.TrustedNameContextLoader,
),
this._container.get<NftContextLoader>(nftTypes.NftContextLoader),
this._container.get<TokenContextLoader>(tokenTypes.TokenContextLoader),
Expand All @@ -65,6 +71,21 @@ export class DefaultContextModule implements ContextModule {
return responses.flat();
}

public async getContext(
field: TransactionFieldContext,
): Promise<ClearSignContext> {
const promises = this._loaders
.filter((fetcher) => fetcher.loadField)
.map((fetcher) => fetcher.loadField!(field));
const responses = await Promise.all(promises);
return (
responses.find((resp) => resp !== null) || {
type: ClearSignContextType.ERROR,
error: new Error(`Field type not supported: ${field.type}`),
}
);
}

public async getTypedDataFilters(
typedData: TypedDataContext,
): Promise<TypedDataClearSignContext> {
Expand Down
4 changes: 2 additions & 2 deletions packages/signer/context-module/src/di.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { Container } from "inversify";
import { configModuleFactory } from "@/config/di/configModuleFactory";
import { type ContextModuleConfig } from "@/config/model/ContextModuleConfig";
import { externalPluginModuleFactory } from "@/external-plugin/di/externalPluginModuleFactory";
import { forwardDomainModuleFactory } from "@/forward-domain/di/forwardDomainModuleFactory";
import { nftModuleFactory } from "@/nft/di/nftModuleFactory";
import { tokenModuleFactory } from "@/token/di/tokenModuleFactory";
import { transactionModuleFactory } from "@/transaction/di/transactionModuleFactory";
import { trustedNameModuleFactory } from "@/trusted-name/di/trustedNameModuleFactory";
import { typedDataModuleFactory } from "@/typed-data/di/typedDataModuleFactory";

type MakeContainerArgs = {
Expand All @@ -19,10 +19,10 @@ export const makeContainer = ({ config }: MakeContainerArgs) => {
container.load(
configModuleFactory(config),
externalPluginModuleFactory(),
forwardDomainModuleFactory(),
nftModuleFactory(),
tokenModuleFactory(),
transactionModuleFactory(),
trustedNameModuleFactory(),
typedDataModuleFactory(),
);

Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit bb46c9d

Please sign in to comment.