polkascan / py-substrate-interface

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

Easier way to retrieve param type information when querying storage function #189

Closed arjanz closed 2 years ago

arjanz commented 2 years ago

When for example querying storage function Tokens.TotalIssuance on Karura, which need 1 param, it is quitte cumbersome without prior example to figure out the format of the param:

# Retrieve storage function to get information about value and param types
storage_function = substrate.get_metadata_storage_function("Tokens", "TotalIssuance")

# Amount of params
print(len(storage_function.get_params_type_string())) # 1

# Retrieve a SCALE object of the param type
param_type = substrate.create_scale_object(storage_function.get_params_type_string()[0])

# Possible options of Enum type
print(param_type.type_mapping)
# [('Token', 'scale_info::42'), ('DexShare', '(scale_info::43, scale_info::43)'), ('Erc20', 'scale_info::44'), ('StableAssetPoolToken', 'scale_info::4'), ('LiquidCrowdloan', 'scale_info::4'), ('ForeignAsset', 'scale_info::35')]

# So if I want to use the 'Token' option: SCALE type is 'scale_info::42'
token_param = substrate.create_scale_object(param_type.type_mapping[0][1])

# Show possible options of Tokens
print(token_param.type_mapping)
# [('ACA', 'Null'), ('AUSD', 'Null'), ('DOT', 'Null'), ('LDOT', 'Null'), (None, 'Null'), (None, 'Null') ....

# So now if I want to show the TotalIssuance of the `Token` `KSM`:
result = substrate.query(
    module='Tokens',
    storage_function='TotalIssuance',
    params=[{'Token': 'KSM'}]
)

# Result is U128 object with value 81190424615873229
print(result.value)
# 81190424615873229

It becomes more clear when using the query_map() function (get all results, omitting the param)

# Query the Mapped storage function
result_map = substrate.query_map(module='Tokens', storage_function='TotalIssuance')

print(list(result_map))
# [[<scale_info::41(value={'DexShare': ({'Token': 'KSM'}, {'Token': 'LKSM'})})>, <U128(value=19811150500020714)>], [<scale_info::41(value={'DexShare': ({'Token': 'KUSD'}, {'Token': 'BNC'})})>, <U128(value=2953340214648797607)>], [<scale_info::41(value={'DexShare': ({'Token': 'KSM'}, {'ForeignAsset': 0})})>, <U128(value=5454135724694137)>], ...

Idea could be to create a new method like storage_function.show_param_specification() that returns a dict like:

[{'type': 'variant', 'variants': [{'name': 'Token', 'type': 'variant', 'variants': [{'name': 'ACA', 'index': 0}, {'name': 'AUSD', 'index': 1}, {'name': 'DOT', 'index': 2}, ...]}, {'name': 'DexShare', 'type': 'variant', 'variants': [...]}]

Which can easier lead to figuring out the input e.g. {'Token': 'DOT'}