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
+66
View File
@@ -0,0 +1,66 @@
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use super::runtime_types::RuntimeApi;
use crate::{
client::OnlineClientT,
error::Error,
Config,
};
use derivative::Derivative;
use std::{
future::Future,
marker::PhantomData,
};
/// Execute runtime API calls.
#[derive(Derivative)]
#[derivative(Clone(bound = "Client: Clone"))]
pub struct RuntimeApiClient<T, Client> {
client: Client,
_marker: PhantomData<T>,
}
impl<T, Client> RuntimeApiClient<T, Client> {
/// Create a new [`RuntimeApiClient`]
pub fn new(client: Client) -> Self {
Self {
client,
_marker: PhantomData,
}
}
}
impl<T, Client> RuntimeApiClient<T, Client>
where
T: Config,
Client: OnlineClientT<T>,
{
/// Obtain a runtime API at some block hash.
pub fn at(
&self,
block_hash: Option<T::Hash>,
) -> impl Future<Output = Result<RuntimeApi<T, Client>, Error>> + Send + 'static {
// Clone and pass the client in like this so that we can explicitly
// return a Future that's Send + 'static, rather than tied to &self.
let client = self.client.clone();
async move {
// If block hash is not provided, get the hash
// for the latest block and use that.
let block_hash = match block_hash {
Some(hash) => hash,
None => {
client
.rpc()
.block_hash(None)
.await?
.expect("substrate RPC returns the best block when no block number is provided; qed")
}
};
Ok(RuntimeApi::new(client, block_hash))
}
}
}