Giter Club home page Giter Club logo

Comments (11)

ricmoo avatar ricmoo commented on May 29, 2024 1

Ah yes... Because Arrays use an anonymous coder for their child... Looking into it.

from ethers.js.

ricmoo avatar ricmoo commented on May 29, 2024 1

I think it's because your return type is (Validator[] calldata validators, PageResponse calldata pageResponse), which has 2 values.

So (I think?) what you would really want is const [ validators, pageResponses ] = await staking.validators(status, pageReqquest)?

Might be more obvious if you had const result = await stacking.validators(...); const validators = result[0]; for (const validator of validators) { ... }.

from ethers.js.

ricmoo avatar ricmoo commented on May 29, 2024

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 foo then result.foo also works.

There is also a result.toObject() return a normal object with properties set on it and a result,toArray() which will return a non-proxy bare Array.

I think that should do what you need?

from ethers.js.

luchenqun avatar luchenqun commented on May 29, 2024

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?

from ethers.js.

ricmoo avatar ricmoo commented on May 29, 2024

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 toObject(deep?: boolean)?

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. :)

from ethers.js.

luchenqun avatar luchenqun commented on May 29, 2024

Thank you for your response. I think adding an optional parameter deep is a great design.

from ethers.js.

ricmoo avatar ricmoo commented on May 29, 2024

Added in v6.12.0. Try it out and let me know if you have any problems.

Thanks! :)

from ethers.js.

luchenqun avatar luchenqun commented on May 29, 2024

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.

node_modules/ethers/lib.esm/utils/errors.js:124
            error = new Error(message);
                    ^

Error: value at index ${ index } unnamed (operation="toObject()", code=UNSUPPORTED_OPERATION, version=6.12.0)
    at makeError (file:///Users/lcq/Code/ethos/precompile/node_modules/ethers/lib.esm/utils/errors.js:124:21)
    at assert (file:///Users/lcq/Code/ethos/precompile/node_modules/ethers/lib.esm/utils/errors.js:143:15)
    at file:///Users/lcq/Code/ethos/precompile/node_modules/ethers/lib.esm/abi/coders/abstract-coder.js:135:13
    at Array.reduce (<anonymous>)
    at Result.toObject (file:///Users/lcq/Code/ethos/precompile/node_modules/ethers/lib.esm/abi/coders/abstract-coder.js:134:28)
    at Proxy.<anonymous> (file:///Users/lcq/Code/ethos/precompile/node_modules/ethers/lib.esm/abi/coders/abstract-coder.js:93:42)
    at file:///Users/lcq/Code/ethos/precompile/node_modules/ethers/lib.esm/abi/coders/abstract-coder.js:142:35
    at Array.reduce (<anonymous>)
    at Result.toObject (file:///Users/lcq/Code/ethos/precompile/node_modules/ethers/lib.esm/abi/coders/abstract-coder.js:134:28)
    at Proxy.<anonymous> (file:///Users/lcq/Code/ethos/precompile/node_modules/ethers/lib.esm/abi/coders/abstract-coder.js:93:42) {
  code: 'UNSUPPORTED_OPERATION',
  operation: 'toObject()',
  shortMessage: 'value at index ${ index } unnamed'
}

from ethers.js.

ricmoo avatar ricmoo commented on May 29, 2024

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 string | null | undefined, where null is unnamed, and undefined is "nameless" (such as an array). The change is quite simple, but breaks backwards compatibility.

For now, What do you think of this idea (inside toObject per child):

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 Record<string, any>, the top level must always be named. Perhaps in a future version the return type should be Record<string, ResultType> | Array<ResultType> (where ResultType is narrowed only to the types that Results can contain).

from ethers.js.

luchenqun avatar luchenqun commented on May 29, 2024

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 validators[0] instead of iterating over validators directly?

from ethers.js.

luchenqun avatar luchenqun commented on May 29, 2024

Sorry, it was my mistake. Your are completely correct. It should indeed be written like this:

const [validators, pageResponses] = await staking.validators(status, pageRequest);

from ethers.js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.