-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can a function that returns tuple data return an Object instead of an Array? #4681
Comments
The object returned from a call is a Result object, which sub-classes Array (so result[0] works), but the class is also implemented using an ES6 proxy, so if you have a property in your struct called There is also a I think that should do what you need? |
Thank you for your prompt reply. result.toObject() is very close to what I want. However, I found that the result returned by result.toObject() is as follows: {
"operatorAddress": "0x7a24464c2A92C3774f1C7b0FFCbeee759Fa9934E",
"consensusPubkey": "ckQp0mBGYUnbBf1v3PJC4nkdGDuSW2MYO5CazB83J+E=",
"jailed": false,
"status": "3",
"tokens": "100000000000000000000",
"delegatorShares": "100000000000000000000000000000000000000",
"description": [
"node0",
"",
"",
"",
""
],
"unbondingHeight": "0",
"unbondingTime": "0",
"commission": [
[
"100000000000000000",
"1000000000000000000",
"1000000000000000000"
],
"1712309039"
],
"minSelfDelegation": "1"
} Only the values corresponding to the keys in the first layer have been converted, while the second layer such as description and commission are still in array form. Do I have to recursively process the value corresponding to each key? |
Ah yes. I do believe it isn’t recursive. There was a reason for that, which I cannot recall. I can likely add a recursive version, perhaps add an optional parameter to I think it had to do with certain ABI (which were popular) that do not include names for deeply nested structs. But an optional parameter seems safe. Changing this issue to a feature request. :) |
Thank you for your response. I think adding an optional parameter deep is a great design. |
Added in v6.12.0. Try it out and let me know if you have any problems. Thanks! :) |
I just quickly tried it, and yes, the struct is working as expected for me now. However, there is still an issue with struct arrays. For example, with the following Solidity interface: function validators(
BondStatus status,
PageRequest calldata pagination
) external view returns (Validator[] calldata validators, PageResponse calldata pageResponse); When I call it using ethers like this: const validators = await staking.validators(status, pageRequest);
console.log('validators', validators.toObject(true)); I get the following error.
|
Ah yes... Because Arrays use an anonymous coder for their child... Looking into it. |
There isn't actually a (backwards compatible) way to detect if the type should be an array. In the future, I should have unpack return For now, What do you think of this idea (inside if (deep && child instanceof Result) {
try {
child = child.toObject(deep);
} catch (error) {
if (isError(error, "UNSUPPORTED_OPERATION") && error.operation === "toObject()") {
child = child.toArray();
} else {
throw error;
}
}
} This means that any Array will correctly get converted to an Array, but also any tuple with unnamed properties will get folded into an Array. This may be what we actually want anyways, as it makes the method more robust against lossy ABI fragments. However, to retain the top-level type of |
I just tried this way, and I can convert each element inside the array to an Object. const validators = await staking.validators(status, pageRequest);
// console.log('validators', validators.toObject());
for (const validator of validators[0]) {
console.log('validator', validator.toObject(true));
} But what confuses me is why iterate over |
I think it's because your return type is So (I think?) what you would really want is Might be more obvious if you had |
Sorry, it was my mistake. Your are completely correct. It should indeed be written like this: const [validators, pageResponses] = await staking.validators(status, pageRequest); |
Everything should be kosher with Array types now, as of v6.13.0. Let me know if you have any more issues. Thanks! :) |
Aiya. I’ll look into it first thing in the morning. :s |
I also see this happening: specially, empty arrays in properties get converted to empty objects |
@andrevmatos The objects returned are fully populated. The problem you are seeing is a limitation of The Result class is a sub-class of Array with a bunch of extra features, including dynamic access to any value by name (like you are looking for). Hope that helps. :) |
Yes, I understand that; What I'd like is some method which could convert a |
Ethers Version
6.11.1
Search Terms
tuple,object,array
Describe the Problem
This is an interface I defined for querying validators based on addresses. The data returned from the query is as follows:
However, returning data in the form of an Array is not very convenient for frontend usage. Is it possible to return the data in the form of an Object, like the following:
Code Snippet
Contract ABI
Errors
Environment
node.js (v12 or newer)
Environment (Other)
no
The text was updated successfully, but these errors were encountered: