substrate_api_client/api/runtime_api/
metadata.rs1use super::{RuntimeApi, RuntimeApiClient};
15use crate::{api::Result, rpc::Request};
16use ac_node_api::{error::MetadataError, Metadata};
17use ac_primitives::config::Config;
18#[cfg(all(not(feature = "sync-api"), not(feature = "std")))]
19use alloc::boxed::Box;
20use alloc::{
21 string::{String, ToString},
22 vec,
23 vec::Vec,
24};
25use codec::Decode;
26use sp_core::{Encode, OpaqueMetadata};
27
28#[maybe_async::maybe_async(?Send)]
29pub trait MetadataApi: RuntimeApi {
30 type OpaqueMetadata;
31
32 async fn metadata(&self, at_block: Option<Self::Hash>) -> Result<Metadata>;
34
35 async fn opaque_metadata(&self, at_block: Option<Self::Hash>) -> Result<Self::OpaqueMetadata>;
37
38 async fn metadata_at_version(
40 &self,
41 version: u32,
42 at_block: Option<Self::Hash>,
43 ) -> Result<Option<Metadata>>;
44
45 async fn opaque_metadata_at_version(
47 &self,
48 version: u32,
49 at_block: Option<Self::Hash>,
50 ) -> Result<Option<Self::OpaqueMetadata>>;
51
52 async fn metadata_versions(&self, at_block: Option<Self::Hash>) -> Result<Vec<u32>>;
54
55 async fn list_traits(&self, at_block: Option<Self::Hash>) -> Result<Vec<String>>;
57
58 async fn list_methods_of_trait(
60 &self,
61 trait_name: &str,
62 at_block: Option<Self::Hash>,
63 ) -> Result<Vec<String>>;
64}
65
66#[maybe_async::maybe_async(?Send)]
67impl<T, Client> MetadataApi for RuntimeApiClient<T, Client>
68where
69 T: Config,
70 Client: Request,
71{
72 type OpaqueMetadata = OpaqueMetadata;
73
74 async fn metadata(&self, at_block: Option<Self::Hash>) -> Result<Metadata> {
75 let metadata_bytes = self.opaque_metadata(at_block).await?;
76 let metadata = Metadata::decode(&mut metadata_bytes.as_slice())?;
77 Ok(metadata)
78 }
79
80 async fn opaque_metadata(&self, at_block: Option<Self::Hash>) -> Result<Self::OpaqueMetadata> {
81 self.runtime_call("Metadata_metadata", vec![], at_block).await
82 }
83
84 async fn metadata_at_version(
85 &self,
86 version: u32,
87 at_block: Option<Self::Hash>,
88 ) -> Result<Option<Metadata>> {
89 let metadata_bytes = self.opaque_metadata_at_version(version, at_block).await?;
90 let metadata = match metadata_bytes {
91 Some(bytes) => Some(Metadata::decode(&mut bytes.as_slice())?),
92 None => None,
93 };
94 Ok(metadata)
95 }
96
97 async fn opaque_metadata_at_version(
98 &self,
99 version: u32,
100 at_block: Option<Self::Hash>,
101 ) -> Result<Option<Self::OpaqueMetadata>> {
102 self.runtime_call("Metadata_metadata_at_version", vec![version.encode()], at_block)
103 .await
104 }
105
106 async fn metadata_versions(&self, at_block: Option<Self::Hash>) -> Result<Vec<u32>> {
107 self.runtime_call("Metadata_metadata_versions", vec![], at_block).await
108 }
109
110 async fn list_traits(&self, at_block: Option<Self::Hash>) -> Result<Vec<String>> {
111 let metadata = self.get_metadata_v15(at_block).await?;
112 let trait_names = metadata
113 .runtime_api_traits()
114 .map(|substrate_trait| substrate_trait.name().to_string())
115 .collect();
116
117 Ok(trait_names)
118 }
119
120 async fn list_methods_of_trait(
121 &self,
122 trait_name: &str,
123 at_block: Option<Self::Hash>,
124 ) -> Result<Vec<String>> {
125 let metadata = self.get_metadata_v15(at_block).await?;
126 let maybe_runtime_api_metadata = metadata
127 .runtime_api_traits()
128 .find(|substrate_trait| substrate_trait.name() == trait_name);
129
130 let methods = match maybe_runtime_api_metadata {
131 Some(trait_metadata) =>
132 trait_metadata.methods().map(|method| method.name.clone()).collect(),
133 None => return Err(MetadataError::RuntimeApiNotFound(trait_name.to_string()).into()),
134 };
135 Ok(methods)
136 }
137}
138
139impl<T, Client> RuntimeApiClient<T, Client>
140where
141 T: Config,
142 Client: Request,
143{
144 #[maybe_async::maybe_async(?Send)]
145 async fn get_metadata_v15(&self, at_block: Option<T::Hash>) -> Result<Metadata> {
146 self.metadata_at_version(15, at_block)
147 .await?
148 .ok_or(MetadataError::RuntimeApiNotFound("No metadata v15 found".to_string()).into())
149 }
150}