mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 20:01:08 +00:00
Add runtime_metadata_url to pull metadata directly from a node (#689)
* Allow metadata to be pulled directly from a node with runtime_metadata_url * Update docs * https too, and abstract out block_on fn * tweak a comment in the example
This commit is contained in:
+11
-13
@@ -4,12 +4,7 @@
|
||||
|
||||
use clap::Parser as ClapParser;
|
||||
use color_eyre::eyre;
|
||||
use frame_metadata::RuntimeMetadataPrefixed;
|
||||
use jsonrpsee::client_transport::ws::Uri;
|
||||
use scale::{
|
||||
Decode,
|
||||
Input,
|
||||
};
|
||||
use std::{
|
||||
fs,
|
||||
io::Read,
|
||||
@@ -48,7 +43,7 @@ pub async fn run(opts: Opts) -> color_eyre::Result<()> {
|
||||
let mut file = fs::File::open(file)?;
|
||||
let mut bytes = Vec::new();
|
||||
file.read_to_end(&mut bytes)?;
|
||||
codegen(&mut &bytes[..], opts.derives, opts.crate_path)?;
|
||||
codegen(&bytes, opts.derives, opts.crate_path)?;
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
@@ -57,18 +52,16 @@ pub async fn run(opts: Opts) -> color_eyre::Result<()> {
|
||||
.parse::<Uri>()
|
||||
.expect("default url is valid")
|
||||
});
|
||||
let (_, bytes) = super::metadata::fetch_metadata(&url).await?;
|
||||
codegen(&mut &bytes[..], opts.derives, opts.crate_path)?;
|
||||
let bytes = subxt_codegen::utils::fetch_metadata_bytes(&url).await?;
|
||||
codegen(&bytes, opts.derives, opts.crate_path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn codegen<I: Input>(
|
||||
encoded: &mut I,
|
||||
fn codegen(
|
||||
metadata_bytes: &[u8],
|
||||
raw_derives: Vec<String>,
|
||||
crate_path: Option<String>,
|
||||
) -> color_eyre::Result<()> {
|
||||
let metadata = <RuntimeMetadataPrefixed as Decode>::decode(encoded)?;
|
||||
let generator = subxt_codegen::RuntimeGenerator::new(metadata);
|
||||
let item_mod = syn::parse_quote!(
|
||||
pub mod api {}
|
||||
);
|
||||
@@ -82,7 +75,12 @@ fn codegen<I: Input>(
|
||||
let mut derives = DerivesRegistry::new(&crate_path);
|
||||
derives.extend_for_all(p.into_iter());
|
||||
|
||||
let runtime_api = generator.generate_runtime(item_mod, derives, crate_path);
|
||||
let runtime_api = subxt_codegen::generate_runtime_api_from_bytes(
|
||||
item_mod,
|
||||
metadata_bytes,
|
||||
derives,
|
||||
crate_path,
|
||||
);
|
||||
println!("{}", runtime_api);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ async fn handle_full_metadata(nodes: &[Uri]) -> color_eyre::Result<()> {
|
||||
}
|
||||
|
||||
async fn fetch_runtime_metadata(url: &Uri) -> color_eyre::Result<RuntimeMetadataV14> {
|
||||
let (_, bytes) = super::metadata::fetch_metadata(url).await?;
|
||||
let bytes = subxt_codegen::utils::fetch_metadata_bytes(url).await?;
|
||||
|
||||
let metadata = <RuntimeMetadataPrefixed as Decode>::decode(&mut &bytes[..])?;
|
||||
if metadata.0 != META_RESERVED {
|
||||
|
||||
@@ -5,24 +5,13 @@
|
||||
use clap::Parser as ClapParser;
|
||||
use color_eyre::eyre;
|
||||
use frame_metadata::RuntimeMetadataPrefixed;
|
||||
use jsonrpsee::{
|
||||
async_client::ClientBuilder,
|
||||
client_transport::ws::{
|
||||
Uri,
|
||||
WsTransportClientBuilder,
|
||||
},
|
||||
core::{
|
||||
client::ClientT,
|
||||
Error,
|
||||
},
|
||||
http_client::HttpClientBuilder,
|
||||
rpc_params,
|
||||
};
|
||||
use jsonrpsee::client_transport::ws::Uri;
|
||||
use scale::Decode;
|
||||
use std::io::{
|
||||
self,
|
||||
Write,
|
||||
};
|
||||
use subxt_codegen::utils::fetch_metadata_hex;
|
||||
|
||||
/// Download metadata from a substrate node, for use with `subxt` codegen.
|
||||
#[derive(Debug, ClapParser)]
|
||||
@@ -41,10 +30,11 @@ pub struct Opts {
|
||||
}
|
||||
|
||||
pub async fn run(opts: Opts) -> color_eyre::Result<()> {
|
||||
let (hex_data, bytes) = fetch_metadata(&opts.url).await?;
|
||||
let hex_data = fetch_metadata_hex(&opts.url).await?;
|
||||
|
||||
match opts.format.as_str() {
|
||||
"json" => {
|
||||
let bytes = hex::decode(hex_data.trim_start_matches("0x"))?;
|
||||
let metadata = <RuntimeMetadataPrefixed as Decode>::decode(&mut &bytes[..])?;
|
||||
let json = serde_json::to_string_pretty(&metadata)?;
|
||||
println!("{}", json);
|
||||
@@ -54,7 +44,10 @@ pub async fn run(opts: Opts) -> color_eyre::Result<()> {
|
||||
println!("{}", hex_data);
|
||||
Ok(())
|
||||
}
|
||||
"bytes" => Ok(io::stdout().write_all(&bytes)?),
|
||||
"bytes" => {
|
||||
let bytes = hex::decode(hex_data.trim_start_matches("0x"))?;
|
||||
Ok(io::stdout().write_all(&bytes)?)
|
||||
}
|
||||
_ => {
|
||||
Err(eyre::eyre!(
|
||||
"Unsupported format `{}`, expected `json`, `hex` or `bytes`",
|
||||
@@ -63,40 +56,3 @@ pub async fn run(opts: Opts) -> color_eyre::Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_metadata(url: &Uri) -> color_eyre::Result<(String, Vec<u8>)> {
|
||||
let hex_data = match url.scheme_str() {
|
||||
Some("http") => fetch_metadata_http(url).await,
|
||||
Some("ws") | Some("wss") => fetch_metadata_ws(url).await,
|
||||
invalid_scheme => {
|
||||
let scheme = invalid_scheme.unwrap_or("no scheme");
|
||||
Err(eyre::eyre!(format!(
|
||||
"`{}` not supported, expects 'http', 'ws', or 'wss'",
|
||||
scheme
|
||||
)))
|
||||
}
|
||||
}?;
|
||||
|
||||
let bytes = hex::decode(hex_data.trim_start_matches("0x"))?;
|
||||
|
||||
Ok((hex_data, bytes))
|
||||
}
|
||||
|
||||
async fn fetch_metadata_ws(url: &Uri) -> color_eyre::Result<String> {
|
||||
let (sender, receiver) = WsTransportClientBuilder::default()
|
||||
.build(url.to_string().parse::<Uri>().unwrap())
|
||||
.await
|
||||
.map_err(|e| Error::Transport(e.into()))?;
|
||||
|
||||
let client = ClientBuilder::default()
|
||||
.max_notifs_per_subscription(4096)
|
||||
.build_with_tokio(sender, receiver);
|
||||
|
||||
Ok(client.request("state_getMetadata", rpc_params![]).await?)
|
||||
}
|
||||
|
||||
async fn fetch_metadata_http(url: &Uri) -> color_eyre::Result<String> {
|
||||
let client = HttpClientBuilder::default().build(url.to_string())?;
|
||||
|
||||
Ok(client.request::<String>("state_getMetadata", None).await?)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user