subxt_core/
dynamic.rs

1// Copyright 2019-2024 Parity Technologies (UK) Ltd.
2// This file is dual-licensed as Apache-2.0 or GPL-3.0.
3// see LICENSE for license details.
4
5//! This module provides the entry points to create dynamic
6//! transactions, storage and constant lookups.
7
8use crate::metadata::{DecodeWithMetadata, Metadata};
9use alloc::vec::Vec;
10use scale_decode::DecodeAsType;
11pub use scale_value::{At, Value};
12
13/// A [`scale_value::Value`] type endowed with contextual information
14/// regarding what type was used to decode each part of it. This implements
15/// [`crate::metadata::DecodeWithMetadata`], and is used as a return type
16/// for dynamic requests.
17pub type DecodedValue = scale_value::Value<u32>;
18
19// Submit dynamic transactions.
20pub use crate::tx::payload::dynamic as tx;
21
22// Lookup constants dynamically.
23pub use crate::constants::address::dynamic as constant;
24
25// Lookup storage values dynamically.
26pub use crate::storage::address::dynamic as storage;
27
28// Execute runtime API function call dynamically.
29pub use crate::runtime_api::payload::dynamic as runtime_api_call;
30
31// Execute View Function API function call dynamically.
32pub use crate::view_functions::payload::dynamic as view_function_call;
33
34/// This is the result of making a dynamic request to a node. From this,
35/// we can return the raw SCALE bytes that we were handed back, or we can
36/// complete the decoding of the bytes into a [`DecodedValue`] type.
37pub struct DecodedValueThunk {
38    type_id: u32,
39    metadata: Metadata,
40    scale_bytes: Vec<u8>,
41}
42
43impl DecodeWithMetadata for DecodedValueThunk {
44    fn decode_with_metadata(
45        bytes: &mut &[u8],
46        type_id: u32,
47        metadata: &Metadata,
48    ) -> Result<Self, scale_decode::Error> {
49        let mut v = Vec::with_capacity(bytes.len());
50        v.extend_from_slice(bytes);
51        *bytes = &[];
52        Ok(DecodedValueThunk {
53            type_id,
54            metadata: metadata.clone(),
55            scale_bytes: v,
56        })
57    }
58}
59
60impl DecodedValueThunk {
61    /// Return the SCALE encoded bytes handed back from the node.
62    pub fn into_encoded(self) -> Vec<u8> {
63        self.scale_bytes
64    }
65    /// Return the SCALE encoded bytes handed back from the node without taking ownership of them.
66    pub fn encoded(&self) -> &[u8] {
67        &self.scale_bytes
68    }
69    /// Decode the SCALE encoded storage entry into a dynamic [`DecodedValue`] type.
70    pub fn to_value(&self) -> Result<DecodedValue, scale_decode::Error> {
71        let val = scale_value::scale::decode_as_type(
72            &mut &*self.scale_bytes,
73            self.type_id,
74            self.metadata.types(),
75        )?;
76        Ok(val)
77    }
78    /// decode the `DecodedValueThunk` into a concrete type.
79    pub fn as_type<T: DecodeAsType>(&self) -> Result<T, scale_decode::Error> {
80        T::decode_as_type(
81            &mut &self.scale_bytes[..],
82            self.type_id,
83            self.metadata.types(),
84        )
85    }
86}