Skip to content

Commit

Permalink
feat(context-module): add external plugin loader
Browse files Browse the repository at this point in the history
  • Loading branch information
aussedatlo committed May 15, 2024
1 parent b76691c commit e546470
Show file tree
Hide file tree
Showing 14 changed files with 1,057 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export interface DappDTO {
b2c: B2c;
abis: Abis;
b2c_signatures: B2cSignatures;
}

export interface B2c {
blockchainName: string;
chainId: number;
contracts: Contract[];
name: string;
}

interface Contract {
address: string;
contractName: string;
selectors: { [selector: string]: ContractSelector };
}

interface ContractSelector {
erc20OfInterest: string[];
method: string;
plugin: string;
}

export interface Abis {
[address: string]: object;
}

export interface B2cSignatures {
[address: string]: {
[selector: string]: B2cSignature;
};
}

interface B2cSignature {
plugin: string;
serialized_data: string;
signature: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DappInfos } from "../model/DappInfos";

export type GetDappInfos = {
address: string;
selector: `0x${string}`;
chainId: number;
};

export interface ExternalPluginDataSource {
getDappInfos(params: GetDappInfos): Promise<DappInfos | undefined>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
import axios from "axios";
import { HttpExternalPluginDataSource } from "./HttpExternalPluginDataSource";
import { Abis, B2c, B2cSignatures, DappDTO } from "./DappDTO";
import ABI from "../domain/__tests__/abi.json";

jest.mock("axios");

const axiosResponseBuilder = (dappDTO: Partial<DappDTO>[]) => {
return { data: dappDTO };
};

describe("HttpExternalPuginDataSource", () => {
const exampleB2c: B2c = {
blockchainName: "ethereum",
chainId: 1,
contracts: [
{
address: "0x0",
contractName: "name",
selectors: { "0x01": { erc20OfInterest: ["fromToken"], method: "swap", plugin: "plugin" } },
},
],
name: "test",
};
const exampleAbis: Abis = { "0x0": ABI };
const exampleB2cSignatures: B2cSignatures = {
"0x0": { "0x01": { plugin: "plugin", serialized_data: "0x001", signature: "0x002" } },
};

beforeAll(() => {
jest.clearAllMocks();
});

it("should return undefined when no b2c data", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const response = axiosResponseBuilder([]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no abis is undefined", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const response = axiosResponseBuilder([
{ b2c: exampleB2c, b2c_signatures: exampleB2cSignatures },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no abis data", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const response = axiosResponseBuilder([
{ abis: {}, b2c: exampleB2c, b2c_signatures: exampleB2cSignatures },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no abis data for the contract address", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const abis: Abis = { "0x1": ABI };
const response = axiosResponseBuilder([
{ abis, b2c: exampleB2c, b2c_signatures: exampleB2cSignatures },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no b2c signature", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const response = axiosResponseBuilder([{ b2c: exampleB2c, abis: exampleAbis }]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no ecc20OfInterest", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const b2c = {
blockchainName: "ethereum",
chainId: 1,
contracts: [
{
address: "0x0",
contractName: "name",
selectors: {
"0x01": { method: "swap", plugin: "plugin" },
},
},
],
name: "test",
} as unknown as B2c;
const response = axiosResponseBuilder([
{ b2c, abis: exampleAbis, b2c_signatures: exampleB2cSignatures },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no method", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const b2c = {
blockchainName: "ethereum",
chainId: 1,
contracts: [
{
address: "0x0",
contractName: "name",
selectors: {
"0x01": { erc20OfInterest: ["fromToken"], plugin: "plugin" },
},
},
],
name: "test",
} as unknown as B2c;
const response = axiosResponseBuilder([
{ b2c, abis: exampleAbis, b2c_signatures: exampleB2cSignatures },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no plugin", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const b2c = {
blockchainName: "ethereum",
chainId: 1,
contracts: [
{
address: "0x0",
contractName: "name",
selectors: {
"0x01": { erc20OfInterest: ["fromToken"], method: "swap" },
},
},
],
name: "test",
} as unknown as B2c;
const response = axiosResponseBuilder([
{ b2c, abis: exampleAbis, b2c_signatures: exampleB2cSignatures },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no method", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const b2c = {
blockchainName: "ethereum",
chainId: 1,
contracts: [
{
address: "0x0",
contractName: "name",
selectors: {
"0x01": { erc20OfInterest: ["fromToken"], plugin: "plugin" },
},
},
],
name: "test",
} as unknown as B2c;
const response = axiosResponseBuilder([
{ b2c, abis: exampleAbis, b2c_signatures: exampleB2cSignatures },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no signature", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const B2CSignature = {
"0x0": { "0x01": { plugin: "plugin", serialized_data: "0x001" } },
} as unknown as B2cSignatures;

// FIXME
const response = axiosResponseBuilder([
{ b2c: exampleB2c, abis: exampleAbis, b2c_signatures: B2CSignature },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return undefined when no serialized data", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const B2CSignature = {
"0x0": { "0x01": { plugin: "plugin", signature: "0x002" } },
} as unknown as B2cSignatures;

// FIXME
const response = axiosResponseBuilder([
{ b2c: exampleB2c, abis: exampleAbis, b2c_signatures: B2CSignature },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual(undefined);
});

it("should return a correct response", async () => {
// GIVEN
const datasource = new HttpExternalPluginDataSource();
const response = axiosResponseBuilder([
{ b2c: exampleB2c, abis: exampleAbis, b2c_signatures: exampleB2cSignatures },
]);
jest.spyOn(axios, "request").mockResolvedValue(response);

// WHEN
const result = await datasource.getDappInfos({ chainId: 1, address: "0x0", selector: "0x01" });

// THEN
expect(result).toEqual({
abi: JSON.stringify(ABI),
selectorDetails: {
erc20OfInterest: ["fromToken"],
method: "swap",
plugin: "plugin",
serializedData: "0x001",
signature: "0x002",
},
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import axios from "axios";
import { ExternalPluginDataSource, GetDappInfos } from "./ExternalPluginDataSource";
import { DappDTO } from "./DappDTO";
import { DappInfos } from "../model/DappInfos";
import { SelectorDetails } from "../model/SelectorDetails";

export class HttpExternalPluginDataSource implements ExternalPluginDataSource {
constructor() {}

async getDappInfos({ chainId, address, selector }: GetDappInfos): Promise<DappInfos | undefined> {
const dappInfos = await axios.request<DappDTO[]>({
method: "GET",
url: "https://crypto-assets-service.api.ledger.com/v1/dapps",
params: { output: "b2c,b2c_signatures,abis", chain_id: chainId, contracts: address },
});

const { erc20OfInterest, method, plugin } =
dappInfos.data[0]?.b2c.contracts?.[0]?.selectors?.[selector] || {};
const { signature, serialized_data: serializedData } =
dappInfos.data[0]?.b2c_signatures?.[address]?.[selector] || {};

if (!erc20OfInterest || !method || !plugin || !signature || !serializedData) {
return;
}

const abi = dappInfos.data[0].abis?.[address];

if (!abi) {
return;
}

const selectorDetails: SelectorDetails = {
method,
plugin,
erc20OfInterest,
signature,
serializedData,
};

return { selectorDetails, abi: JSON.stringify(abi) };
}
}

0 comments on commit e546470

Please sign in to comment.