canvas-ui icon indicating copy to clipboard operation
canvas-ui copied to clipboard

RPC return type `Balance` is not always decoded

Open cmichi opened this issue 4 years ago • 4 comments

If ink!'s erc20 example is deployed with an initialSupply of 9999 the RPC method total_supply() does not decode the returned supply: screenshot-paritytech github io-2021 05 14-10_29_34

If 1000 is chosen for initialSupply the value is displayed as encoded. It also works for 9999 in polkadot-js: screenshot-polkadot js org-2021 05 14-10_31_31

Here's the contract: erc20.contract.zip.

The return type of total_supply is Balance. I suspect that there's an issue with decoding this type.

cmichi avatar May 14 '21 08:05 cmichi

I did a little debugging in Data.tsx::Data on this issue.

formatData for the Balance type yeilds a Type Codec. The if statement that catches this value is

if (type.info === _polkadot_types_types__WEBPACK_IMPORTED_MODULE_9__.TypeDefInfo.Plain) {
    return (0,_canvas_ui_react_util__WEBPACK_IMPORTED_MODULE_2__.truncate)((value === null || value === void 0 ? void 0 : value.toString()) || '()', TRUNCATE_TO); // TRUNCATE_TO === 16
}

When initialSupply = 1000, value === 1000000000000000 and typeof value === "number" and subsequently returns a nicely, non truncated base-10 number.

When initialSupply = 9999, value === "0x0000000000000000002386099b1bf000" and typeof value === "string" and subsequently returns a truncated copy of value.

Balance is defined in https://github.com/polkadot-js/api/blob/master/packages/types/src/interfaces/runtime/types.ts as extending u32 which eventually extends AbstractInt.

I think there are 2 questions to be answered here:

  1. Why doesn't a "Balance" type yeild a Type instead of AbstractInt Codec?
  2. Why is Data() invoked with value with two different types depending on its size?

awolokita avatar Jun 01 '21 05:06 awolokita

While digging around for #13 I found that codec.toHuman() gives us nice representations of lots of Codec types. In the case of Balance we get nice prefixed units.

For your case of a starting supply of 9999, codec.toHuman() yeilds "9.9990 kUnit". Instantiating with 1 Yotta gives us "1.0000 YUnit".

awolokita avatar Jun 01 '21 09:06 awolokita

@awolokita This seems to be an excellent solution, tried it and changed toJSON() to .toHuman() in the code. Thanks a lot for all your valuable contributions and sorry for not being responsive. canvas-ui is currently undergoing a re-write, please get in touch if would like to contribute to the new project at some point.

achimcc avatar Jul 21 '21 06:07 achimcc

@achimcc I'm glad the solution worked out well for you.

Looking forward to seeing the big refactor. I'd be happy to contribute more when the changes are up.

awolokita avatar Jul 21 '21 07:07 awolokita