Add Runtime API to execute runtime calls (#777)

* rpc: Add RuntimeAPI call via `state_call` method

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* subxt: Add runtime API

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Expose the RuntimeAPI client

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* tests: Test the runtime API call against the metadata

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* client: Fetch the metadata from runtime API

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* blocks: Fix doc typo

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* blocks: Use &str instead of String to identify fn names

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Update subxt/src/runtime_api/runtime_client.rs

Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
This commit is contained in:
Alexandru Vasile
2023-01-18 17:49:20 +02:00
committed by GitHub
parent 8ef80638d0
commit b4bb17662a
10 changed files with 252 additions and 1 deletions
@@ -3,6 +3,11 @@
// see LICENSE for license details.
use crate::test_context;
use codec::{
Compact,
Decode,
};
use frame_metadata::RuntimeMetadataPrefixed;
use futures::StreamExt;
// Check that we can subscribe to non-finalized blocks.
@@ -87,3 +92,30 @@ async fn missing_block_headers_will_be_filled_in() -> Result<(), subxt::Error> {
assert!(last_block_number.is_some());
Ok(())
}
// Check that we can subscribe to non-finalized blocks.
#[tokio::test]
async fn runtime_api_call() -> Result<(), subxt::Error> {
let ctx = test_context().await;
let api = ctx.client();
let mut sub = api.blocks().subscribe_best().await?;
let block = sub.next().await.unwrap()?;
let rt = block.runtime_api().await?;
let bytes = rt.call_raw("Metadata_metadata", None).await?;
let cursor = &mut &*bytes;
let _ = <Compact<u32>>::decode(cursor)?;
let meta: RuntimeMetadataPrefixed = Decode::decode(cursor)?;
let metadata_call = match meta.1 {
frame_metadata::RuntimeMetadata::V14(metadata) => metadata,
_ => panic!("Metadata V14 unavailable"),
};
// Compare the runtime API call against the `state_getMetadata`.
let metadata = api.rpc().metadata(None).await?;
let metadata = metadata.runtime_metadata();
assert_eq!(&metadata_call, metadata);
Ok(())
}
@@ -11,6 +11,11 @@ use crate::{
wait_for_blocks,
},
};
use codec::{
Compact,
Decode,
};
use frame_metadata::RuntimeMetadataPrefixed;
use sp_core::{
sr25519::Pair as Sr25519Pair,
storage::well_known_keys,
@@ -250,3 +255,29 @@ async fn unsigned_extrinsic_is_same_shape_as_polkadotjs() {
// Make sure our encoding is the same as the encoding polkadot UI created.
assert_eq!(actual_tx_bytes, expected_tx_bytes);
}
#[tokio::test]
async fn rpc_state_call() {
let ctx = test_context().await;
let api = ctx.client();
// Call into the runtime of the chain to get the Metadata.
let metadata_bytes = api
.rpc()
.state_call("Metadata_metadata", None, None)
.await
.unwrap();
let cursor = &mut &*metadata_bytes;
let _ = <Compact<u32>>::decode(cursor).unwrap();
let meta: RuntimeMetadataPrefixed = Decode::decode(cursor).unwrap();
let metadata_call = match meta.1 {
frame_metadata::RuntimeMetadata::V14(metadata) => metadata,
_ => panic!("Metadata V14 unavailable"),
};
// Compare the runtime API call against the `state_getMetadata`.
let metadata = api.rpc().metadata(None).await.unwrap();
let metadata = metadata.runtime_metadata();
assert_eq!(&metadata_call, metadata);
}