Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit 1f81ff0

Browse files
EtlesLYi Zhang
andauthored
fix 2d array bug of abiSchemaToJsonSchema in web3-validator (#6836)
* fix 2d array bug of abiSchemaToJsonSchema in web3-validator * fix 2d array bug of abiSchemaToJsonSchema in web3-validator(add comments) * fix abi json schema test case: - 123 cannot be uint - test case("nested tuple object in nested array") has a wrong data structure of tuple[][3] * fix function abiSchemaToJsonSchema in iterating over arraySizes array to each dimension * FIX: 1. fix function convertToZod to distinguish tuple and array, add checks in maxItems & minItems 2. revert abiSchemaToJsonSchema of utils and fix 3. add testcases in validator.validate * UPDATE: contract test --------- Co-authored-by: Yi Zhang <yi.y.zhang@maplequad.com>
1 parent f943944 commit 1f81ff0

File tree

6 files changed

+504
-415
lines changed

6 files changed

+504
-415
lines changed

packages/web3-eth-contract/test/unit/contract.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ describe('Contract', () => {
508508
expect(error).toBeInstanceOf(Web3ValidatorError);
509509
// eslint-disable-next-line jest/no-conditional-expect
510510
expect((error as Web3ValidatorError).message).toBe(
511-
'Web3 validator found 1 error[s]:\nmust NOT have more than 1 items',
511+
'Web3 validator found 2 error[s]:\nmust NOT have more than 1 items\nvalue "true" at "/1" must pass "string" validation',
512512
);
513513
}
514514

packages/web3-validator/CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,8 @@ Documentation:
162162

163163
- Fixed an issue with detecting Uint8Array (#6486)
164164

165-
## [Unreleased]
165+
## [Unreleased]
166+
167+
### Fixed
168+
169+
- Multi-dimensional arrays(with a fix length) are now handled properly when parsing ABIs (#6798)

packages/web3-validator/src/utils.ts

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ export const abiSchemaToJsonSchema = (
177177
for (let i = arraySizes.length - 1; i > 0; i -= 1) {
178178
childSchema = {
179179
type: 'array',
180+
$id: abiName,
180181
items: [],
181182
maxItems: arraySizes[i],
182183
minItems: arraySizes[i],
@@ -192,7 +193,7 @@ export const abiSchemaToJsonSchema = (
192193
lastSchema.items = [lastSchema.items as JsonSchema, childSchema];
193194
} // lastSchema.items is an empty Scheme array, set it to 'childSchema'
194195
else if (lastSchema.items.length === 0) {
195-
lastSchema.items = childSchema;
196+
lastSchema.items = [childSchema];
196197
} // lastSchema.items is a non-empty Scheme array, append 'childSchema'
197198
else {
198199
lastSchema.items.push(childSchema);
@@ -205,43 +206,31 @@ export const abiSchemaToJsonSchema = (
205206
nestedTuple.$id = abiName;
206207
(lastSchema.items as JsonSchema[]).push(nestedTuple);
207208
} else if (baseType === 'tuple' && isArray) {
208-
const arraySize = arraySizes[0];
209-
const item: JsonSchema = {
210-
$id: abiName,
211-
type: 'array',
212-
items: abiSchemaToJsonSchema(abiComponents, abiName),
213-
maxItems: arraySize,
214-
minItems: arraySize,
215-
};
216-
217-
if (arraySize < 0) {
218-
delete item.maxItems;
219-
delete item.minItems;
220-
}
221-
222-
(lastSchema.items as JsonSchema[]).push(item);
209+
const arraySize = arraySizes[0];
210+
const item: JsonSchema = {
211+
type: 'array',
212+
$id: abiName,
213+
items: abiSchemaToJsonSchema(abiComponents, abiName),
214+
...(arraySize >= 0 && { minItems: arraySize, maxItems: arraySize }),
215+
};
216+
217+
(lastSchema.items as JsonSchema[]).push(item);
223218
} else if (isArray) {
224-
const arraySize = arraySizes[0];
225-
const item: JsonSchema = {
226-
type: 'array',
227-
$id: abiName,
228-
items: convertEthType(String(baseType)),
229-
minItems: arraySize,
230-
maxItems: arraySize,
231-
};
232-
233-
if (arraySize < 0) {
234-
delete item.maxItems;
235-
delete item.minItems;
236-
}
237-
238-
(lastSchema.items as JsonSchema[]).push(item);
219+
const arraySize = arraySizes[0];
220+
const item: JsonSchema = {
221+
type: 'array',
222+
$id: abiName,
223+
items: convertEthType(abiType),
224+
...(arraySize >= 0 && { minItems: arraySize, maxItems: arraySize }),
225+
};
226+
227+
(lastSchema.items as JsonSchema[]).push(item);
239228
} else if (Array.isArray(lastSchema.items)) {
240229
// Array of non-tuple items
241230
lastSchema.items.push({ $id: abiName, ...convertEthType(abiType) });
242231
} else {
243232
// Nested object
244-
((lastSchema.items as JsonSchema).items as JsonSchema[]).push({
233+
(lastSchema.items as JsonSchema[]).push({
245234
$id: abiName,
246235
...convertEthType(abiType),
247236
});
@@ -505,4 +494,4 @@ export function ensureIfUint8Array<T = any>(data: T) {
505494
return Uint8Array.from(data as unknown as Uint8Array);
506495
}
507496
return data;
508-
}
497+
}

packages/web3-validator/src/validator.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ const convertToZod = (schema: JsonSchema): ZodType => {
4444
}
4545

4646
if (schema?.type === 'array' && schema?.items) {
47-
if (Array.isArray(schema.items) && schema.items.length > 0) {
47+
if (Array.isArray(schema.items) && schema.items.length > 1
48+
&& schema.maxItems !== undefined
49+
&& new Set(schema.items.map((item: JsonSchema) => item.$id)).size === schema.items.length) {
4850
const arr: Partial<[ZodTypeAny, ...ZodTypeAny[]]> = [];
4951
for (const item of schema.items) {
5052
const zItem = convertToZod(item);
@@ -54,7 +56,12 @@ const convertToZod = (schema: JsonSchema): ZodType => {
5456
}
5557
return z.tuple(arr as [ZodTypeAny, ...ZodTypeAny[]]);
5658
}
57-
return z.array(convertToZod(schema.items as JsonSchema));
59+
const nextSchema = Array.isArray(schema.items) ? schema.items[0] : schema.items;
60+
let zodArraySchema = z.array(convertToZod(nextSchema));
61+
62+
zodArraySchema = schema.minItems !== undefined ? zodArraySchema.min(schema.minItems) : zodArraySchema;
63+
zodArraySchema = schema.maxItems !== undefined ? zodArraySchema.max(schema.maxItems) : zodArraySchema;
64+
return zodArraySchema;
5865
}
5966

6067
if (schema.oneOf && Array.isArray(schema.oneOf)) {

0 commit comments

Comments
 (0)