Skip to content

Commit

Permalink
Merge pull request #2272 from blockscout/tom2drum/issue-2271
Browse files Browse the repository at this point in the history
Fix args length and optional nested arrays in contract method form
  • Loading branch information
isstuev authored Sep 27, 2024
2 parents 075a5c0 + 32be80d commit 134b6a1
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const ContractMethodFieldInputTuple = ({ data, basePath, level, isDisabled, isOp
basePath={ `${ basePath }:${ index }` }
level={ level + 1 }
isDisabled={ isDisabled }
isOptional={ isOptional }
/>
);
}
Expand Down
23 changes: 23 additions & 0 deletions ui/address/contract/methods/form/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,27 @@ describe('transformFormDataToMethodArgs', () => {
],
]);
});

it('should transform all nested empty arrays to empty arrays', () => {
const formData = {
'0': '0x1D415D28380ff51A507F7B176ca5F27833F7FffD',
'1': '0x1D415D28380ff51A507F7B176ca5F27833F7FffD',
'2': '3160',
'3': true,
// tuple array without elements
'4:0:0:0': undefined,
'4:0:1:0': undefined,
'4:0:1:1': undefined,
'4:0:1:2': undefined,
'4:0:1:3': undefined,
};
const result = transformFormDataToMethodArgs(formData);
expect(result).toEqual([
'0x1D415D28380ff51A507F7B176ca5F27833F7FffD',
'0x1D415D28380ff51A507F7B176ca5F27833F7FffD',
'3160',
true,
[],
]);
});
});
19 changes: 18 additions & 1 deletion ui/address/contract/methods/form/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ export function transformFormDataToMethodArgs(formData: ContractMethodFormFields
_set(result, field.replaceAll(':', '.'), value);
}

return filterOutEmptyItems(result);
const filteredResult = filterOutEmptyItems(result);
const mappedResult = mapEmptyNestedArrays(filteredResult);
return mappedResult;
}

function filterOutEmptyItems(array: Array<unknown>): Array<unknown> {
Expand All @@ -90,11 +92,26 @@ function filterOutEmptyItems(array: Array<unknown>): Array<unknown> {
// The only optional field is the native coin value, which is safely handled in the form submit handler.
// 2. When the user adds and removes items from a field array.
// In this scenario, empty items need to be filtered out to maintain the correct sequence of arguments.
// We don't use isEmptyField() function here because of the second case otherwise it will not keep the correct order of arguments.
return array
.map((item) => Array.isArray(item) ? filterOutEmptyItems(item) : item)
.filter((item) => item !== undefined);
}

function isEmptyField(field: unknown): boolean {
// the empty string is meant that the field was touched but left empty
// the undefined is meant that the field was not touched
return field === undefined || field === '';
}

function isEmptyNestedArray(array: Array<unknown>): boolean {
return array.flat(Infinity).filter((item) => !isEmptyField(item)).length === 0;
}

function mapEmptyNestedArrays(array: Array<unknown>): Array<unknown> {
return array.map((item) => Array.isArray(item) && isEmptyNestedArray(item) ? [] : item);
}

export function getFieldLabel(input: ContractAbiItemInput, isRequired?: boolean) {
const name = input.name || input.internalType || '<unnamed argument>';
return `${ name } (${ input.type })${ isRequired ? '*' : '' }`;
Expand Down
5 changes: 4 additions & 1 deletion ui/address/contract/methods/useCallMethodPublicClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ export default function useCallMethodPublicClient(): (params: Params) => Promise
}

const address = getAddress(addressHash);
// for write payable methods we add additional input for native coin value
// so in simulate mode we need to strip it off
const _args = args.slice(0, item.inputs.length);

const params = {
abi: [ item ],
functionName: item.name,
args: args,
args: _args,
address,
account,
};
Expand Down

0 comments on commit 134b6a1

Please sign in to comment.