Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions async_substrate_interface/async_substrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1587,11 +1587,11 @@ async def retrieve_pending_extrinsics(self) -> list:
return extrinsics

async def get_metadata_storage_functions(
self, block_hash=None, runtime: Optional[Runtime] = None
self, block_hash: Optional[str] = None, runtime: Optional[Runtime] = None
) -> list:
"""
Retrieves a list of all storage functions in metadata active at given block_hash (or chaintip if block_hash is
omitted)
Retrieves a list of all storage functions in metadata active at given block_hash (or chaintip if
block_hash and runtime are omitted)
Args:
block_hash: hash of the blockchain block whose runtime to use
Expand Down Expand Up @@ -4079,6 +4079,41 @@ async def result_handler(message: dict, subscription_id) -> tuple[dict, bool]:

return result

async def get_metadata_call_functions(
self, block_hash: Optional[str] = None, runtime: Optional[Runtime] = None
):
"""
Retrieves calls functions for the metadata at the specified block_hash or runtime. If neither are specified,
the metadata at chaintip is used.
Args:
block_hash: block hash to retrieve metadata for, unused if supplying runtime
runtime: Runtime object containing the metadata you wish to parse
Returns:
dict mapping {pallet name: {call name: {param name: param definition}}}
e.g.
{
"Sudo":{
"sudo": {
"_docs": "Authenticates the sudo key and dispatches a function call with `Root` origin.",
"call": {
"name": "call",
"type": 227,
"typeName": "Box<<T as Config>::RuntimeCall>",
"index": 0,
"_docs": ""
}
},
...
},
...
}
"""
if runtime is None:
runtime = await self.init_runtime(block_hash=block_hash)
return self._get_metadata_call_functions(runtime)

async def get_metadata_call_function(
self,
module_name: str,
Expand Down
31 changes: 31 additions & 0 deletions async_substrate_interface/sync_substrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3291,6 +3291,37 @@ def result_handler(message: dict, subscription_id) -> tuple[dict, bool]:

return result

def get_metadata_call_functions(self, block_hash: Optional[str] = None):
"""
Retrieves calls functions for the metadata at the specified block_hash. If not specified, the metadata at
chaintip is used.

Args:
block_hash: block hash to retrieve metadata for

Returns:
dict mapping {pallet name: {call name: {param name: param definition}}}
e.g.
{
"Sudo":{
"sudo": {
"_docs": "Authenticates the sudo key and dispatches a function call with `Root` origin.",
"call": {
"name": "call",
"type": 227,
"typeName": "Box<<T as Config>::RuntimeCall>",
"index": 0,
"_docs": ""
}
},
...
},
...
}
"""
runtime = self.init_runtime(block_hash=block_hash)
return self._get_metadata_call_functions(runtime)

def get_metadata_call_function(
self,
module_name: str,
Expand Down
18 changes: 18 additions & 0 deletions async_substrate_interface/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,3 +1002,21 @@ def generate_multisig_account(
)

return multi_sig_account

@staticmethod
def _get_metadata_call_functions(runtime: Runtime):
"""
See subclass `get_metadata_call_functions` for documentation.
"""
data = {}
for pallet in runtime.metadata.pallets:
data[pallet.name] = {}
for call in pallet.calls:
data[pallet.name][call.name] = {}
data[pallet.name][call.name]["_docs"] = " ".join(call["docs"].value)
for idx, field in enumerate(call.value.get("fields", [])):
field["index"] = idx
field_docs = field["docs"]
field["_docs"] = " ".join(field_docs)
data[pallet.name][call.name][field["name"]] = field
return data
4 changes: 1 addition & 3 deletions tests/e2e_tests/test_substrate_addons.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,7 @@ async def test_retry_async_substrate_runtime_call_with_keyword_args():

def test_retry_sync_substrate_runtime_call_with_keyword_args():
"""Test that runtime_call works with keyword arguments (parameter name conflict fix)."""
with RetrySyncSubstrate(
LATENT_LITE_ENTRYPOINT, retry_forever=True
) as substrate:
with RetrySyncSubstrate(LATENT_LITE_ENTRYPOINT, retry_forever=True) as substrate:
# This should not raise TypeError due to parameter name conflict
# The 'method' kwarg should not conflict with _retry's parameter
result = substrate.runtime_call(
Expand Down
Loading