polkascan / py-substrate-interface

Python Substrate Interface
https://polkascan.github.io/py-substrate-interface/
Apache License 2.0
239 stars 110 forks source link

example for get_storage(module, function, params) please #3

Closed drandreaskrueger closed 4 years ago

drandreaskrueger commented 4 years ago

I have been going through all the functions:

Connected to: https://dev-node.substrate.dev:9933/

[no parameters]
          get_system_name : substrate-node
              get_version : 2.0.0
 get_chain_finalised_head : 0x189dafe56cf99d25ddf6a8a6eec2e08834d3435d721a91b898c633573e8ba7a0
           get_chain_head : 0xd41eade474e58b90bbe7d7b490c0306da66dc1b36cdd4d6595aeda847a03ef8f

[param block_hash=0xd41eade474e58b90bbe7d7b490c0306da66dc1b36cdd4d6595aeda847a03ef8f]
          get_chain_block : dict_keys(['block', 'justification'])  -->  block : dict_keys(['extrinsics', 'header']) 
         get_block_header : dict_keys(['digest', 'extrinsicsRoot', 'number', 'parentHash', 'stateRoot'])  -->  digest : dict_keys(['logs']) 
         get_block_events : dict_keys(['jsonrpc', 'result', 'id']) 
get_block_runtime_version : dict_keys(['apis', 'authoringVersion', 'implName', 'implVersion', 'specName', 'specVersion']) 
         get_block_number : 905 

[param block_hash=0xd41eade474e58b90bbe7d7b490c0306da66dc1b36cdd4d6595aeda847a03ef8f]
       get_block_metadata : dict_keys(['magicNumber', 'metadata'])
                         -->
                  magicNumber : 1635018093
                          key : MetadataV8
      MetadataV8-->modules[0] : dict_keys(['name', 'prefix', 'storage', 'calls', 'events', 'constants', 'errors'])

[param block_id=905]
          get_chain_block : dict_keys(['block', 'justification'])  -->  block : dict_keys(['extrinsics', 'header']) 
           get_block_hash : 0xd41eade474e58b90bbe7d7b490c0306da66dc1b36cdd4d6595aeda847a03ef8f 

[params: storage_key=xxh6464('Sudo Key')='0x50a63a871aced22e88ee6466fe5aa5d9', block_hash=0xd41eade474e58b90bbe7d7b490c0306da66dc1b36cdd4d6595aeda847a03ef8f]
get_storage_by_key(storage_key='0x50a63a871aced22e88ee6466fe5aa5d9', block_hash=0xd41eade474e58b90bbe7d7b490c0306da66dc1b36cdd4d6595aeda847a03ef8f)
'0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'

Now that worked all very well. Thanks a lot. Makes my life much easier.
The last one could benefit from one small improvement, see that feature request.

However, this remaining 1, I could not yet get working:

get_storage(module='Balances', function='FreeBalance', params='d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', block_hash=0xd41eade474e58b90bbe7d7b490c0306da66dc1b36cdd4d6595aeda847a03ef8f)

results in

None

Which is better than an exception, so the query seems to be well-formed at least; it is just asking for the wrong thing probably? Following Shawn's tutorial, it should accept a list of parameters, right? But it doesn't want to take a list.

I have tried some permutations of possible parameters, using the instructions over there; but obviously I have't understood the role of the arguments (module, function, params) yet.

For most of your other functions in this library, we can live well without unittests - but please you give one or two working examples for get_storage(). Perhaps connecting to "https://dev-node.substrate.dev:9933/" because then I can easily replicate it here.

Thanks. A lot.

emielsebastiaan commented 4 years ago

Hi @drandreaskrueger

Yeah thank you. We won't be merging that. We are working on a generalized solution for exactly this. You can find the spec here: https://github.com/w3f/Web3-collaboration/blob/master/grants/speculative/python_substrate_api.md

We hope to finish that by the end of the year. Therefore, I am closing this issue.

drandreaskrueger commented 4 years ago

This was not about a pull request to be merged. Please reopen this issue, thanks.

drandreaskrueger commented 4 years ago

However, this remaining 1, I could not yet get working:

I cannot get this beast

https://github.com/polkascan/py-substrate-interface/blob/7f64648d7baab4d63466563eed71006d95aeedc4/substrateinterface/__init__.py#L146-L147

working to replicate that simple example

https://www.shawntabrizi.com/substrate/querying-substrate-storage-via-rpc/#storage-map-query
--> Storage Map Query

I would think for one from your team, it would be a quick thing to just write down a Python threeliner example ... how to do the exact same but with your library substrateinterface. Please help.

Thanks a million.

arjanz commented 4 years ago

Hi @drandreaskrueger,

Here a quick example for the latest Kusama dev node (run with --dev), I used the same account as Shawn did (5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, which result in the public key 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d)

If you use hex values as params, you need to omit the '0x', so a quick example will be:

substrate = SubstrateInterface("http://127.0.0.1:9933")
result = substrate.get_storage(
            block_hash=None,
            module='Balances',
            function='FreeBalance',
            params='d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d',
            return_scale_type='Balance',
            hasher='Blake2_256'
        )
print(result)

Note that when None is passed as block_hash, it will retrieve the most recent state.

Moreover there is a more sophisticated Substrate interface in the making, which will make our life easier by extracting and autofill the 'hasher' and 'return_scale_type' from the runtime metadata and will do the account decoding to public key automatically.

drandreaskrueger commented 4 years ago

Ohhhh, thank you sooooooo much. You won't believe how much I tried. And then it was so easy:

 hasher='Blake2_256'

THAT was it. Hoooray, finally the result is not None anymore :-)

by extracting and autofill the 'hasher' and 'return_scale_type' from the runtime metadata

NOW other things start to make sense too. I can see this in the metadata:

'type': {'MapType': {'hasher': 'Blake2_256', ...

Oh cool, that's useful too:

return_scale_type='Balance',

Thanks, well done. And the "more sophisticated Substrate interface in the making" sounds great.


Now my next challenge is to read and write my own storage objects. In Python.

I would expect to be able to use the same API function at least for reading the data, no? So far no success though.

How would I access this through your library?

PUT MyModule.store_value(42)
GET MyModule.SomeValue()

The metadata section says this:

metadata --> Module 'mymodule':

{'calls': [{'args': [{'name': 'somevalue', 'type': 'u32'}],
            'docs': [],
            'name': 'store_value'}],
 'constants': [],
 'errors': [],
 'events': [{'args': ['u32', 'AccountId'],
             'docs': [],
             'name': 'SomeValueStored'}],
 'name': 'mymodule',
 'prefix': 'MyModule',
 'storage': [{'docs': [],
              'fallback': '0x00',
              'modifier': 'Optional',
              'name': 'SomeValue',
              'type': {'PlainType': 'u32'}}]}

via https://polkadot.js.org/apps/ I can write that extrinsics mymodule.store_value(42), and read the chain state mymodule.SomeValue(), no problem. Now how to get that into Python code? Any hints? .


Meta: All the tutorials, e.g. the substratekitties tutorial, are targeted at JavaScript only. What I am really missing here is one supersimple tutorial, which creates the simplemost substrate node (by now, I understood how to do that, but it took ages), which can only do 1 thing: just read and store/overwrite one integer - without fancy GUI and stuff, just showing the whole procedure from scratch, possibly even only with curl, because simple GET/POST requests can then be translated into ANY language.

Of course, what you are doing here, for us Pythonians, is super valuable. Hide the low levels. Great. Really looking forward to when it's ready. But for now the above would be everything I need short term. So if you could give me one more hint, that would be great.

Thanks!

drandreaskrueger commented 4 years ago

Hah! I got it, result 42 is:

'0x2a000000'

Yipppieh.

And ... wow, I see the light ...

return_scale_type='U32'

turns it into:

42

Great. .


What solved it:

then it worked. Great.


Now I have to learn how to store values, talking to MyModule.store_value(42)

But that is NOT part of the current py-substrate-interface yet, right? Any hints that might help me?

drandreaskrueger commented 4 years ago

Anyways, just want to say thanks again. Traveling now, continue probably end of next week. Thanks.

CanClose.

emielsebastiaan commented 4 years ago

Sure np!