Support v16 metadata and use it by default if it's available (#1999)

* Support v16 metadata and use it by default if it's available

* lockfile

* fix blocks test; new transaction extension in kitchensink runtime

* Bump scale-typegen to 0.11.1 to cater for Duration prelude type

* fmt

* Fix no-std test building

* Cargo update and bump substrate deps

* Update test and no-std deps

* fmt

* fix test
This commit is contained in:
James Wilson
2025-05-08 14:44:44 +01:00
committed by GitHub
parent 4524590821
commit 9ba89e3ed7
16 changed files with 1674 additions and 1223 deletions
+28 -30
View File
@@ -90,23 +90,23 @@ async fn fetch_metadata_http(url: Url, version: MetadataVersion) -> Result<Vec<u
async fn fetch_metadata(client: impl ClientT, version: MetadataVersion) -> Result<Vec<u8>, Error> {
const UNSTABLE_METADATA_VERSION: u32 = u32::MAX;
// Fetch available metadata versions. If error, revert to legacy metadata code.
async fn fetch_available_versions(
client: &impl ClientT,
) -> Result<Vec<u32>, Error> {
let res: String = client
.request("state_call", rpc_params!["Metadata_metadata_versions", "0x"])
.await?;
let raw_bytes = hex::decode(res.trim_start_matches("0x"))?;
Decode::decode(&mut &raw_bytes[..]).map_err(Into::into)
}
// Fetch metadata using the "new" state_call interface
async fn fetch_inner(
client: &impl ClientT,
version: MetadataVersion,
supported_versions: Vec<u32>,
) -> Result<Vec<u8>, Error> {
// Look up supported versions:
let supported_versions: Vec<u32> = {
let res: String = client
.request(
"state_call",
rpc_params!["Metadata_metadata_versions", "0x"],
)
.await?;
let raw_bytes = hex::decode(res.trim_start_matches("0x"))?;
Decode::decode(&mut &raw_bytes[..])?
};
// Return the version the user wants if it's supported:
let version = match version {
MetadataVersion::Latest => *supported_versions
@@ -128,7 +128,7 @@ async fn fetch_metadata(client: impl ClientT, version: MetadataVersion) -> Resul
version
} else {
return Err(Error::Other(format!(
"The node does not have version {version} available"
"The node does not have metadata version {version} available"
)));
}
}
@@ -150,7 +150,7 @@ async fn fetch_metadata(client: impl ClientT, version: MetadataVersion) -> Resul
Decode::decode(&mut &metadata_bytes[..])?;
let Some(metadata) = metadata else {
return Err(Error::Other(format!(
"The node does not have version {version} available"
"The node does not have metadata version {version} available"
)));
};
Ok(metadata.0)
@@ -159,19 +159,7 @@ async fn fetch_metadata(client: impl ClientT, version: MetadataVersion) -> Resul
// Fetch metadata using the "old" state_call interface
async fn fetch_inner_legacy(
client: &impl ClientT,
version: MetadataVersion,
) -> Result<Vec<u8>, Error> {
// If the user specifically asks for anything other than version 14 or "latest", error.
if !matches!(
version,
MetadataVersion::Latest | MetadataVersion::Version(14)
) {
return Err(Error::Other(
"The node can only return version 14 metadata using the legacy API but you've asked for something else"
.to_string(),
));
}
// Fetch the metadata.
let metadata_string: String = client
.request("state_call", rpc_params!["Metadata_metadata", "0x"])
@@ -183,9 +171,19 @@ async fn fetch_metadata(client: impl ClientT, version: MetadataVersion) -> Resul
Ok(metadata.0)
}
// Fetch using the new interface, falling back to trying old one if there's an error.
match fetch_inner(&client, version).await {
Ok(s) => Ok(s),
Err(_) => fetch_inner_legacy(&client, version).await,
match fetch_available_versions(&client).await {
Ok(supported_versions) => {
fetch_inner(&client, version, supported_versions).await
},
Err(e) => {
// The "new" interface failed. if the user is asking for V14 or the "latest"
// metadata then try the legacy interface instead. Else, just return the
// reason for failure.
if matches!(version, MetadataVersion::Version(14) | MetadataVersion::Latest) {
fetch_inner_legacy(&client).await
} else {
Err(e)
}
}
}
}