subxt_core/view_functions/
payload.rs1use alloc::vec::Vec;
9use core::marker::PhantomData;
10use derive_where::derive_where;
11use scale_encode::EncodeAsFields;
12use scale_value::Composite;
13
14use crate::Error;
15use crate::dynamic::DecodedValueThunk;
16use crate::error::MetadataError;
17
18use crate::metadata::{DecodeWithMetadata, Metadata};
19
20pub trait Payload {
36 type ReturnType: DecodeWithMetadata;
40
41 fn query_id(&self) -> &[u8; 32];
43
44 fn encode_args_to(&self, metadata: &Metadata, out: &mut Vec<u8>) -> Result<(), Error>;
46
47 fn encode_args(&self, metadata: &Metadata) -> Result<Vec<u8>, Error> {
50 let mut v = Vec::new();
51 self.encode_args_to(metadata, &mut v)?;
52 Ok(v)
53 }
54
55 fn validation_hash(&self) -> Option<[u8; 32]> {
57 None
58 }
59}
60
61#[derive_where(Clone, Debug, Eq, Ord, PartialEq, PartialOrd; ArgsData)]
67pub struct DefaultPayload<ArgsData, ReturnTy> {
68 query_id: [u8; 32],
69 args_data: ArgsData,
70 validation_hash: Option<[u8; 32]>,
71 _marker: PhantomData<ReturnTy>,
72}
73
74pub type StaticPayload<ArgsData, ReturnTy> = DefaultPayload<ArgsData, ReturnTy>;
76pub type DynamicPayload = DefaultPayload<Composite<()>, DecodedValueThunk>;
78
79impl<ArgsData: EncodeAsFields, ReturnTy: DecodeWithMetadata> Payload
80 for DefaultPayload<ArgsData, ReturnTy>
81{
82 type ReturnType = ReturnTy;
83
84 fn query_id(&self) -> &[u8; 32] {
85 &self.query_id
86 }
87
88 fn encode_args_to(&self, metadata: &Metadata, out: &mut Vec<u8>) -> Result<(), Error> {
89 let view_function = metadata
90 .view_function_by_query_id(&self.query_id)
91 .ok_or(MetadataError::ViewFunctionNotFound(self.query_id))?;
92 let mut fields = view_function
93 .inputs()
94 .map(|input| scale_encode::Field::named(input.ty, &input.name));
95
96 self.args_data
97 .encode_as_fields_to(&mut fields, metadata.types(), out)?;
98
99 Ok(())
100 }
101
102 fn validation_hash(&self) -> Option<[u8; 32]> {
103 self.validation_hash
104 }
105}
106
107impl<ReturnTy, ArgsData> DefaultPayload<ArgsData, ReturnTy> {
108 pub fn new(query_id: [u8; 32], args_data: ArgsData) -> Self {
110 DefaultPayload {
111 query_id,
112 args_data,
113 validation_hash: None,
114 _marker: PhantomData,
115 }
116 }
117
118 #[doc(hidden)]
123 pub fn new_static(
124 query_id: [u8; 32],
125 args_data: ArgsData,
126 hash: [u8; 32],
127 ) -> DefaultPayload<ArgsData, ReturnTy> {
128 DefaultPayload {
129 query_id,
130 args_data,
131 validation_hash: Some(hash),
132 _marker: core::marker::PhantomData,
133 }
134 }
135
136 pub fn unvalidated(self) -> Self {
138 Self {
139 validation_hash: None,
140 ..self
141 }
142 }
143
144 pub fn args_data(&self) -> &ArgsData {
146 &self.args_data
147 }
148}
149
150pub fn dynamic(query_id: [u8; 32], args_data: impl Into<Composite<()>>) -> DynamicPayload {
152 DefaultPayload::new(query_id, args_data.into())
153}