Files
pezkuwi-subxt/testing/test-runtime/build.rs
T
Alexandru Vasile 432e856c37 Metadata V15: Generate Runtime APIs (#918)
* Update frame-metadata to v15.1.0

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

* Enable V15 unstable metadata in frame-metadata

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

* metadata: Move validation hashing to dedicated file

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

* Use sp-metadata-ir from substrate to work with metadata

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

* Revert using sp-metadata-ir in favor of conversion to v15

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

* metadata: Convert v14 to v15

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

* metadata: Use v15 for validation

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

* codegen: Use v15 for codegen

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

* metadata/bench: Use v15

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

* Adjust to v15 metadata

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

* Adjust testing

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

* Improve documentation

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

* force CI

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

* rpc: Fetch metadata at version

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

* artifacts: Update polkadot.scale from commit 6dc9e84dde2

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

* codegen: Fetch V15 using the new API

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

* codegen: Add runtime API interface

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

* metadata: Hash runtime API metadata for validation

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

* metadata: Extract runtime API metadata wrapper from subxt::Metadata

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

* subxt: Adjust hashing cache to reflect root+item keys

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

* rpc: Add raw state_call API method

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

* runtime_api: Add payload with static and dynamic variants

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

* subxt: Allow payloads to call into the runtime

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

* examples: Add example to make a runtime API call both static and dynamic

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

* Update polkadot.rs

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

* codegen: Simplify client fetching

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

* Address feedback and fallback to old API if needed

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

* runtime_api: Make mutability conditional on input params

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

* Regenerate polkadot.rs

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

* metadata: Retain only pallets without runtime API info

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

* codegen: Retry via `Metadata_metadata` without conversion

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

* payload: Remove `Decode` and change validation fn

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

* metadata: Retain runtime API types

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

* codegen: Runtime APIs documentation based on flag

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

* Update examples/examples/custom_metadata_url.rs

Co-authored-by: James Wilson <james@jsdw.me>

* Update artifacts from polkadot-a6cfdb16e9

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

* Update polkadot.rs with polkadot-a6cfdb16e9

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

* codegen: Generate input structures for runtime API

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

* runtime_api: Remove the static paylaod and use single impl

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

* examples: Fetch account nonce

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

* testing: Adjust build script to fetch latest metadata

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

* testing: Check account nonce from runtime API

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

* Update cargo.lock

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

* codegen: Fix doc generation for runtime types

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

* codegen: Rename `inputs` runtime calls module to `types`

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

* codegen: Generate Calls structs inside the types module

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

* testing: Check Alice account nonce before submitting the tx

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

* cli: Add metadata version option flag supporting v14 and unstable

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

* cli: Specify version to fetch

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

* subxt: Fallback to fetching latest stable metadata

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

* subxt: Add unstable-metadata feature to fetch the latest

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

* RuntimeVersion with Latest and Version(u32)

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

* Update polkadot.rs

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

* codegen: Adjust fetch_metadata to inspect version list

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

* testing: Adjust metadata to metadata_legacy

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

* events: Adjust docs to use metadata_legacy

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

* have a pass over fetch_metadata

* cargo fmt

* Option<String> when fetch metadata via latest API

* clippy

* fmt

* cli: Use the MetadataVersion from codegen

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

* cli: Specify latest as default for MetadataVersion

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

* cli: Remove version from metadata and use the one from file_or_url

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

* Fix clippy

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

* codegen: Decode metadata independently for different RPC calls

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

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Co-authored-by: James Wilson <james@jsdw.me>
2023-05-03 17:31:27 +03:00

126 lines
4.7 KiB
Rust

// Copyright 2019-2023 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use codec::{Decode, Encode};
use std::{env, fs, path::Path};
use substrate_runner::{Error as SubstrateNodeError, SubstrateNode};
static SUBSTRATE_BIN_ENV_VAR: &str = "SUBSTRATE_NODE_PATH";
#[tokio::main]
async fn main() {
run().await;
}
async fn run() {
// Select substrate binary to run based on env var.
let substrate_bin = env::var(SUBSTRATE_BIN_ENV_VAR).unwrap_or_else(|_| "substrate".to_owned());
let mut node_builder = SubstrateNode::builder();
node_builder.binary_path(substrate_bin.clone());
let node = match node_builder.spawn() {
Ok(node) => node,
Err(SubstrateNodeError::Io(e)) if e.kind() == std::io::ErrorKind::NotFound => {
panic!(
"A substrate binary should be installed on your path for testing purposes. \
See https://github.com/paritytech/subxt/tree/master#integration-testing"
)
}
Err(e) => {
panic!("Cannot spawn substrate command '{substrate_bin}': {e}")
}
};
let port = node.ws_port();
// Download metadata from binary. Avoid Subxt dep on `subxt::rpc::types::Bytes`and just impl here.
// This may at least prevent this script from running so often (ie whenever we change Subxt).
const V15_METADATA_VERSION: u32 = u32::MAX;
let bytes = V15_METADATA_VERSION.encode();
let version: String = format!("0x{}", hex::encode(&bytes));
let raw: String = {
use client::ClientT;
client::build(&format!("ws://localhost:{port}"))
.await
.unwrap_or_else(|e| panic!("Failed to connect to node: {e}"))
.request(
"state_call",
client::rpc_params!["Metadata_metadata_at_version", &version],
)
.await
.unwrap_or_else(|e| panic!("Failed to obtain metadata from node: {e}"))
};
let raw_bytes = hex::decode(raw.trim_start_matches("0x"))
.unwrap_or_else(|e| panic!("Failed to hex-decode metadata: {e}"));
let bytes: Option<Vec<u8>> = Decode::decode(&mut &raw_bytes[..])
.unwrap_or_else(|e| panic!("Failed to decode metadata bytes: {e}"));
let metadata_bytes = bytes.expect("Metadata version not found");
// Save metadata to a file:
let out_dir = env::var_os("OUT_DIR").unwrap();
let metadata_path = Path::new(&out_dir).join("metadata.scale");
fs::write(&metadata_path, metadata_bytes).expect("Couldn't write metadata output");
// Write out our expression to generate the runtime API to a file. Ideally, we'd just write this code
// in lib.rs, but we must pass a string literal (and not `concat!(..)`) as an arg to `runtime_metadata_path`,
// and so we need to spit it out here and include it verbatim instead.
let runtime_api_contents = format!(
r#"
#[subxt::subxt(
runtime_metadata_path = "{}",
derive_for_all_types = "Eq, PartialEq",
)]
pub mod node_runtime {{}}
"#,
metadata_path
.to_str()
.expect("Path to metadata should be stringifiable")
);
let runtime_path = Path::new(&out_dir).join("runtime.rs");
fs::write(runtime_path, runtime_api_contents).expect("Couldn't write runtime rust output");
let substrate_path =
which::which(substrate_bin).expect("Cannot resolve path to substrate binary");
// Re-build if the substrate binary we're pointed to changes (mtime):
println!(
"cargo:rerun-if-changed={}",
substrate_path.to_string_lossy()
);
// Re-build if we point to a different substrate binary:
println!("cargo:rerun-if-env-changed={SUBSTRATE_BIN_ENV_VAR}");
// Re-build if this file changes:
println!("cargo:rerun-if-changed=build.rs");
}
// Use jsonrpsee to obtain metadata from the node.
mod client {
pub use jsonrpsee::{
client_transport::ws::{InvalidUri, Receiver, Sender, Uri, WsTransportClientBuilder},
core::{
client::{Client, ClientBuilder},
Error,
},
};
pub use jsonrpsee::core::{client::ClientT, rpc_params};
/// Build WS RPC client from URL
pub async fn build(url: &str) -> Result<Client, Error> {
let (sender, receiver) = ws_transport(url).await?;
Ok(ClientBuilder::default().build_with_tokio(sender, receiver))
}
async fn ws_transport(url: &str) -> Result<(Sender, Receiver), Error> {
let url: Uri = url
.parse()
.map_err(|e: InvalidUri| Error::Transport(e.into()))?;
WsTransportClientBuilder::default()
.build(url)
.await
.map_err(|e| Error::Transport(e.into()))
}
}