diff --git a/async_substrate_interface/async_substrate.py b/async_substrate_interface/async_substrate.py index 5fce7b8..c2342e8 100644 --- a/async_substrate_interface/async_substrate.py +++ b/async_substrate_interface/async_substrate.py @@ -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 @@ -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<::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, diff --git a/async_substrate_interface/sync_substrate.py b/async_substrate_interface/sync_substrate.py index 5349b31..373e8cd 100644 --- a/async_substrate_interface/sync_substrate.py +++ b/async_substrate_interface/sync_substrate.py @@ -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<::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, diff --git a/async_substrate_interface/types.py b/async_substrate_interface/types.py index f1b4917..008dd48 100644 --- a/async_substrate_interface/types.py +++ b/async_substrate_interface/types.py @@ -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 diff --git a/tests/e2e_tests/test_substrate_addons.py b/tests/e2e_tests/test_substrate_addons.py index bcf8750..bd91c99 100644 --- a/tests/e2e_tests/test_substrate_addons.py +++ b/tests/e2e_tests/test_substrate_addons.py @@ -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(