1

I am building a somewhat generic client for Substrate-based chains in Rust using the subxt crate. To learn about runtime calls, my goal was to call the core.version runtime API directly using the RPC endpoint state_call.

Internally subxt uses a special RPC endpoint state_getRuntimeVersion, but that just gets redirected to the runtime at the specific block anyways:

    /// Fetch the runtime version
    pub async fn runtime_version(
        &self,
        at: Option<T::Hash>,
    ) -> Result<RuntimeVersion, BasicError> {
        let params = rpc_params![at];
        let version = self
            .client
            .request("state_getRuntimeVersion", params)
            .await?;
        Ok(version)
    }

This was my try to make the runtime call directly:

    let version: subxt::rpc::RuntimeVersion = rpc_client
        .rpc()
        .client
        .request("state_call", rpc_params!["core.version", ""])
        .await
        .unwrap();

But it just errs out with Exported method core.version is not found. How can I make this call work?

1
  • Opposed to polkadot.js, found out the method name needs to be Core_version. Still, decoding the RuntimeVersion from the returned JSON string and encoding the call parameters and the blockhash still seems to be missing an example.
    – wigy
    Jul 19, 2022 at 20:44

1 Answer 1

1

I think you've found this out, but for others: In chrome you can run polkadot js and then inspect the webpage and switch over to the network tab. From there if you click on ws to filter to the websockets you can see the request and response from the UI for any call whether that's a state query, rpc call, runtime call or submitting an extrinsic.

Here's the request you can see on the wire:

{
  "id":157,
  "jsonrpc":"2.0",
  "method":"state_call",
  "params":["Core_version","0x"]
}

The result is

{
  "jsonrpc":"2.0",
  "result":"0x20706f6c6b61646f743c7061726974792d706f6c6b61646f74000000000e2400000000000038df6acb689907609b0400000037e397fc7c91f5e40100000040fe3ad401f8959a06000000d2bc9897eed08f1503000000f78b278be53f454c02000000af2c0297a23e6d3d0200000049eaaf1b548a0cb00100000091d5df18b0d2cf5801000000ed99c5acb25eedf503000000cbca25e39f14238702000000687ad44ad37f03c201000000ab3c0572291feb8b01000000bc9d89904f5b923f0100000037c8bb1350a9a2a8010000000c00000000",
  "id":157
}

and we can see in polkadot js this decodes to

{
  "specName": "polkadot",
  "implName": "parity-polkadot",
  "authoringVersion": 0,
  "specVersion": 9230,
  "implVersion": 0,
  "apis": [
    [ "0xdf6acb689907609b", 4 ],
    [ "0x37e397fc7c91f5e4", 1 ],
    [ "0x40fe3ad401f8959a", 6 ],
    [ "0xd2bc9897eed08f15", 3 ],
    [ "0xf78b278be53f454c", 2 ],
    [ "0xaf2c0297a23e6d3d", 2 ],
    [ "0x49eaaf1b548a0cb0", 1 ],
    [ "0x91d5df18b0d2cf58", 1 ],
    [ "0xed99c5acb25eedf5", 3 ],
    [ "0xcbca25e39f142387", 2 ],
    [ "0x687ad44ad37f03c2", 1 ],
    [ "0xab3c0572291feb8b", 1 ],
    [ "0xbc9d89904f5b923f", 1 ],
    [ "0x37c8bb1350a9a2a8", 1 ]
  ],
  "transactionVersion": 12,
  "stateVersion": 0
}

polkadot in hex is 70 6f 6c 6b 61 64 6f 74 so that gives you a pretty good steer on the decoding front. The code is here to decode it. The 0x20 prefix will be a Compact<u32> saying what the string length is. But you should be able to call sp_version::RuntimeVersion::decode(&mut &bytes[..]) to decode it all in one go.

1
  • A slight inconvenience seems to be that neither sp-api nor sp-version is kept up-to-date on crates.io, neither subxt reexports it like is does with sp-runtime or sp-core. I guess the thinking was you depend on the client code of a single chain anyways, and that could reexport the correct versions of these crates?
    – wigy
    Jul 20, 2022 at 9:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.