diff --git a/newsfragments/2312.feature.rst b/newsfragments/2312.feature.rst new file mode 100644 index 0000000000..902b51b134 --- /dev/null +++ b/newsfragments/2312.feature.rst @@ -0,0 +1 @@ +Allow NamedTuples in ABI inputs diff --git a/tests/core/utilities/test_abi.py b/tests/core/utilities/test_abi.py index 571585006f..b861ee83ab 100644 --- a/tests/core/utilities/test_abi.py +++ b/tests/core/utilities/test_abi.py @@ -1,5 +1,8 @@ import json import pytest +from typing import ( + NamedTuple, +) from web3._utils.abi import ( abi_data_tree, @@ -41,6 +44,15 @@ def test_get_tuple_type_str_parts(input, expected): assert get_tuple_type_str_parts(input) == expected +MyXYTuple = NamedTuple( + "MyXYTuple", + [ + ("x", int), + ("y", int), + ] +) + + TEST_FUNCTION_ABI_JSON = """ { "constant": false, @@ -165,6 +177,15 @@ def test_get_tuple_type_str_parts(input, expected): ), GET_ABI_INPUTS_OUTPUT, ), + ( + TEST_FUNCTION_ABI, + { + 's': {'a': 1, 'b': [2, 3, 4], 'c': [(5, 6), (7, 8), MyXYTuple(x=9, y=10)]}, + 't': MyXYTuple(x=11, y=12), + 'a': 13, + }, + GET_ABI_INPUTS_OUTPUT, + ), ( {}, (), diff --git a/web3/_utils/abi.py b/web3/_utils/abi.py index 28f1d0c72a..698f4151cd 100644 --- a/web3/_utils/abi.py +++ b/web3/_utils/abi.py @@ -551,7 +551,10 @@ def _align_abi_input(arg_abi: ABIFunctionParams, arg: Any) -> Tuple[Any, ...]: ), ) - return type(aligned_arg)( + # convert NamedTuple to regular tuple + typing = tuple if isinstance(aligned_arg, tuple) else type(aligned_arg) + + return typing( _align_abi_input(sub_abi, sub_arg) for sub_abi, sub_arg in zip(sub_abis, aligned_arg) )