mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 18:11:10 +00:00
ac606cf625
* Rename traits to renmove T suffix * Fix doc links * Fix straggler doc links
86 lines
3.3 KiB
Rust
86 lines
3.3 KiB
Rust
// Copyright 2019-2024 Parity Technologies (UK) Ltd.
|
|
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
|
// see LICENSE for license details.
|
|
|
|
//! Access constants from metadata.
|
|
//!
|
|
//! Use [`get`] to retrieve a constant from some metadata, or [`validate`] to check that a static
|
|
//! constant address lines up with the value seen in the metadata.
|
|
//!
|
|
//! # Example
|
|
//!
|
|
//! ```rust
|
|
//! use subxt_macro::subxt;
|
|
//! use subxt_core::constants;
|
|
//! use subxt_core::metadata;
|
|
//!
|
|
//! // If we generate types without `subxt`, we need to point to `::subxt_core`:
|
|
//! #[subxt(
|
|
//! crate = "::subxt_core",
|
|
//! runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale",
|
|
//! )]
|
|
//! pub mod polkadot {}
|
|
//!
|
|
//! // Some metadata we'd like to access constants in:
|
|
//! let metadata_bytes = include_bytes!("../../../artifacts/polkadot_metadata_small.scale");
|
|
//! let metadata = metadata::decode_from(&metadata_bytes[..]).unwrap();
|
|
//!
|
|
//! // We can use a static address to obtain some constant:
|
|
//! let address = polkadot::constants().balances().existential_deposit();
|
|
//!
|
|
//! // This validates that the address given is in line with the metadata
|
|
//! // we're trying to access the constant in:
|
|
//! constants::validate(&address, &metadata).expect("is valid");
|
|
//!
|
|
//! // This acquires the constant (and internally also validates it):
|
|
//! let ed = constants::get(&address, &metadata).expect("can decode constant");
|
|
//!
|
|
//! assert_eq!(ed, 33_333_333);
|
|
//! ```
|
|
|
|
pub mod address;
|
|
|
|
use address::Address;
|
|
use alloc::borrow::ToOwned;
|
|
|
|
use crate::{error::MetadataError, metadata::DecodeWithMetadata, Error, Metadata};
|
|
|
|
/// When the provided `address` is statically generated via the `#[subxt]` macro, this validates
|
|
/// that the shape of the constant value is the same as the shape expected by the static address.
|
|
///
|
|
/// When the provided `address` is dynamic (and thus does not come with any expectation of the
|
|
/// shape of the constant value), this just returns `Ok(())`
|
|
pub fn validate<Addr: Address>(address: &Addr, metadata: &Metadata) -> Result<(), Error> {
|
|
if let Some(actual_hash) = address.validation_hash() {
|
|
let expected_hash = metadata
|
|
.pallet_by_name_err(address.pallet_name())?
|
|
.constant_hash(address.constant_name())
|
|
.ok_or_else(|| {
|
|
MetadataError::ConstantNameNotFound(address.constant_name().to_owned())
|
|
})?;
|
|
if actual_hash != expected_hash {
|
|
return Err(MetadataError::IncompatibleCodegen.into());
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Fetch a constant out of the metadata given a constant address. If the `address` has been
|
|
/// statically generated, this will validate that the constant shape is as expected, too.
|
|
pub fn get<Addr: Address>(address: &Addr, metadata: &Metadata) -> Result<Addr::Target, Error> {
|
|
// 1. Validate constant shape if hash given:
|
|
validate(address, metadata)?;
|
|
|
|
// 2. Attempt to decode the constant into the type given:
|
|
let constant = metadata
|
|
.pallet_by_name_err(address.pallet_name())?
|
|
.constant_by_name(address.constant_name())
|
|
.ok_or_else(|| MetadataError::ConstantNameNotFound(address.constant_name().to_owned()))?;
|
|
let value = <Addr::Target as DecodeWithMetadata>::decode_with_metadata(
|
|
&mut constant.value(),
|
|
constant.ty(),
|
|
metadata,
|
|
)?;
|
|
Ok(value)
|
|
}
|