gear_subxt/runtime_api/
runtime_payload.rs1use core::marker::PhantomData;
6use scale_encode::EncodeAsFields;
7use scale_value::Composite;
8use std::borrow::Cow;
9
10use crate::dynamic::DecodedValueThunk;
11use crate::error::MetadataError;
12use crate::{metadata::DecodeWithMetadata, Error, Metadata};
13
14pub trait RuntimeApiPayload {
35 type ReturnType: DecodeWithMetadata;
39
40 fn trait_name(&self) -> &str;
42
43 fn method_name(&self) -> &str;
45
46 fn encode_args_to(&self, metadata: &Metadata, out: &mut Vec<u8>) -> Result<(), Error>;
48
49 fn encode_args(&self, metadata: &Metadata) -> Result<Vec<u8>, Error> {
52 let mut v = Vec::new();
53 self.encode_args_to(metadata, &mut v)?;
54 Ok(v)
55 }
56
57 fn validation_hash(&self) -> Option<[u8; 32]> {
59 None
60 }
61}
62
63#[derive(Clone, Debug)]
69pub struct Payload<ArgsData, ReturnTy> {
70 trait_name: Cow<'static, str>,
71 method_name: Cow<'static, str>,
72 args_data: ArgsData,
73 validation_hash: Option<[u8; 32]>,
74 _marker: PhantomData<ReturnTy>,
75}
76
77impl<ArgsData: EncodeAsFields, ReturnTy: DecodeWithMetadata> RuntimeApiPayload
78 for Payload<ArgsData, ReturnTy>
79{
80 type ReturnType = ReturnTy;
81
82 fn trait_name(&self) -> &str {
83 &self.trait_name
84 }
85
86 fn method_name(&self) -> &str {
87 &self.method_name
88 }
89
90 fn encode_args_to(&self, metadata: &Metadata, out: &mut Vec<u8>) -> Result<(), Error> {
91 let api_method = metadata
92 .runtime_api_trait_by_name_err(&self.trait_name)?
93 .method_by_name(&self.method_name)
94 .ok_or_else(|| MetadataError::RuntimeMethodNotFound((*self.method_name).to_owned()))?;
95 let mut fields = api_method
96 .inputs()
97 .map(|input| scale_encode::Field::named(input.ty, &input.name));
98
99 self.args_data
100 .encode_as_fields_to(&mut fields, metadata.types(), out)?;
101 Ok(())
102 }
103
104 fn validation_hash(&self) -> Option<[u8; 32]> {
105 self.validation_hash
106 }
107}
108
109pub type DynamicRuntimeApiPayload = Payload<Composite<()>, DecodedValueThunk>;
111
112impl<ReturnTy, ArgsData> Payload<ArgsData, ReturnTy> {
113 pub fn new(
115 trait_name: impl Into<String>,
116 method_name: impl Into<String>,
117 args_data: ArgsData,
118 ) -> Self {
119 Payload {
120 trait_name: Cow::Owned(trait_name.into()),
121 method_name: Cow::Owned(method_name.into()),
122 args_data,
123 validation_hash: None,
124 _marker: PhantomData,
125 }
126 }
127
128 #[doc(hidden)]
133 pub fn new_static(
134 trait_name: &'static str,
135 method_name: &'static str,
136 args_data: ArgsData,
137 hash: [u8; 32],
138 ) -> Payload<ArgsData, ReturnTy> {
139 Payload {
140 trait_name: Cow::Borrowed(trait_name),
141 method_name: Cow::Borrowed(method_name),
142 args_data,
143 validation_hash: Some(hash),
144 _marker: std::marker::PhantomData,
145 }
146 }
147
148 pub fn unvalidated(self) -> Self {
150 Self {
151 validation_hash: None,
152 ..self
153 }
154 }
155
156 pub fn trait_name(&self) -> &str {
158 &self.trait_name
159 }
160
161 pub fn method_name(&self) -> &str {
163 &self.method_name
164 }
165
166 pub fn args_data(&self) -> &ArgsData {
168 &self.args_data
169 }
170}
171
172pub fn dynamic(
174 trait_name: impl Into<String>,
175 method_name: impl Into<String>,
176 args_data: impl Into<Composite<()>>,
177) -> DynamicRuntimeApiPayload {
178 Payload::new(trait_name, method_name, args_data.into())
179}