Skip to content

Commit

Permalink
🐛 (context-module): Iterate on transaction calldata
Browse files Browse the repository at this point in the history
  • Loading branch information
aussedatlo committed Dec 16, 2024
1 parent 53a74b1 commit 34236f9
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: No generic descriptor for contract 0x0abc",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x0abc and selector 0x01ff",
),
),
);
Expand Down Expand Up @@ -471,6 +471,50 @@ describe("HttpTransactionDataSource", () => {
]);
});

it("Calldata on third array element", async () => {
// GIVEN
const calldataDTO = createCalldata(
transactionInfo,
[],
[fieldAmount, fieldDatetime, fieldUnit, fieldDuration],
);
jest
.spyOn(axios, "request")
.mockResolvedValue({ data: [{}, {}, calldataDTO] });

// WHEN
const result = await datasource.getTransactionDescriptors({
chainId: 1,
address: "0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9",
selector: "0x69328dec",
});

// THEN
expect(result.extract()).toEqual([
{
payload:
"0001000108000000000000000102147d2768de32b0b80b7a3454c06bdac94a69ddc7a9030469328dec04207d5e9ed0004b8035b164edd9d78c37415ad6b1d123be4943d0abd5a50035cae3050857697468647261770604416176650708416176652044414f081068747470733a2f2f616176652e636f6d0a045fc4ba9c81ff473045022100eb67599abfd9c7360b07599a2a2cb769c6e3f0f74e1e52444d788c8f577a16d20220402e92b0adbf97d890fa2f9654bc30c7bd70dacabe870f160e6842d9eb73d36f",
type: "transactionInfo",
},
{
type: "transactionFieldDescription",
payload: fieldAmount.descriptor,
},
{
type: "transactionFieldDescription",
payload: fieldDatetime.descriptor,
},
{
type: "transactionFieldDescription",
payload: fieldUnit.descriptor,
},
{
type: "transactionFieldDescription",
payload: fieldDuration.descriptor,
},
]);
});

it("Calldata without fields references and transaction info signature length % 2 different from 0", async () => {
// GIVEN
const newTransactionInfo: CalldataTransactionInfoV1 = {
Expand Down Expand Up @@ -549,7 +593,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand Down Expand Up @@ -582,7 +626,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand All @@ -608,7 +652,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand All @@ -634,7 +678,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand Down Expand Up @@ -669,7 +713,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand All @@ -695,7 +739,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand Down Expand Up @@ -728,7 +772,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand Down Expand Up @@ -761,7 +805,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand Down Expand Up @@ -800,7 +844,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand Down Expand Up @@ -833,7 +877,7 @@ describe("HttpTransactionDataSource", () => {
expect(result).toEqual(
Left(
new Error(
"[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
"[ContextModule] HttpTransactionDataSource: Invalid response for contract 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9 and selector 0x69328dec",
),
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class HttpTransactionDataSource implements TransactionDataSource {
}: GetTransactionDescriptorsParams): Promise<
Either<Error, ClearSignContextSuccess[]>
> {
let calldata: CalldataDto | undefined;
let dto: CalldataDto[] | undefined;
try {
const response = await axios.request<CalldataDto[]>({
method: "GET",
Expand All @@ -62,7 +62,7 @@ export class HttpTransactionDataSource implements TransactionDataSource {
"X-Ledger-Client-Version": `context-module/${PACKAGE.version}`,
},
});
calldata = response.data?.[0];
dto = response.data;
} catch (error) {
return Left(
new Error(
Expand All @@ -71,73 +71,70 @@ export class HttpTransactionDataSource implements TransactionDataSource {
);
}

if (!calldata) {
return Left(
new Error(
`[ContextModule] HttpTransactionDataSource: No generic descriptor for contract ${address}`,
),
);
}

// Normalize the address and selector
address = address.toLowerCase();
selector = `0x${selector.slice(2).toLowerCase()}`;

const calldataDescriptor =
calldata.descriptors_calldata?.[address]?.[selector];
if (!calldataDescriptor) {
if (!Array.isArray(dto)) {
return Left(
new Error(
`[ContextModule] HttpTransactionDataSource: Invalid response for contract ${address} and selector ${selector}`,
),
);
}

if (
!this.isCalldataDescriptorV1(calldataDescriptor, this.config.cal.mode)
) {
return Left(
new Error(
`[ContextModule] HttpTransactionDataSource: Failed to decode transaction descriptor for contract ${address} and selector ${selector}`,
),
);
}
for (const calldata of dto) {
// Normalize the address and selector
address = address.toLowerCase();
selector = `0x${selector.slice(2).toLowerCase()}`;
const calldataDescriptor =
calldata.descriptors_calldata?.[address]?.[selector];

const infoData = calldataDescriptor.transaction_info.descriptor.data;
const infoSignature =
calldataDescriptor.transaction_info.descriptor.signatures[
this.config.cal.mode
];
const info: ClearSignContextSuccess = {
type: ClearSignContextType.TRANSACTION_INFO,
payload: this.formatTransactionInfo(infoData, infoSignature),
};
const enums: ClearSignContextSuccess[] = [];
for (const [id, values] of Object.entries(calldataDescriptor.enums)) {
for (const [
value,
{ data, signatures },
] of Object.entries<CalldataTransactionDescriptor>(values)) {
enums.push({
type: ClearSignContextType.ENUM,
id: Number(id),
value: Number(value),
payload: this.formatTransactionInfo(
data,
signatures[this.config.cal.mode]!, // the enum is validated by isCalldataDescriptorV1
),
});
if (
!calldataDescriptor ||
!this.isCalldataDescriptorV1(calldataDescriptor, this.config.cal.mode)
) {
continue;
}

const infoData = calldataDescriptor.transaction_info.descriptor.data;
const infoSignature =
calldataDescriptor.transaction_info.descriptor.signatures[
this.config.cal.mode
];
const info: ClearSignContextSuccess = {
type: ClearSignContextType.TRANSACTION_INFO,
payload: this.formatTransactionInfo(infoData, infoSignature),
};
const enums: ClearSignContextSuccess[] = [];
for (const [id, values] of Object.entries(calldataDescriptor.enums)) {
for (const [
value,
{ data, signatures },
] of Object.entries<CalldataTransactionDescriptor>(values)) {
enums.push({
type: ClearSignContextType.ENUM,
id: Number(id),
value: Number(value),
payload: this.formatTransactionInfo(
data,
signatures[this.config.cal.mode]!, // the enum is validated by isCalldataDescriptorV1
),
});
}
}

const fields: ClearSignContextSuccess[] = calldataDescriptor.fields.map(
(field) => ({
type: ClearSignContextType.TRANSACTION_FIELD_DESCRIPTION,
payload: field.descriptor,
reference: this.getReference(field.param),
}),
);
return Right([info, ...enums, ...fields]);
}

const fields: ClearSignContextSuccess[] = calldataDescriptor.fields.map(
(field) => ({
type: ClearSignContextType.TRANSACTION_FIELD_DESCRIPTION,
payload: field.descriptor,
reference: this.getReference(field.param),
}),
return Left(
new Error(
`[ContextModule] HttpTransactionDataSource: Invalid response for contract ${address} and selector ${selector}`,
),
);
return Right([info, ...enums, ...fields]);
}

private formatTransactionInfo(
Expand Down

0 comments on commit 34236f9

Please sign in to comment.