mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 18:01:03 +00:00
Move subxt-new to be the new subxt, and get first example working
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
use crate::backend::BackendExt;
|
||||
use crate::client::{OfflineClientAtBlockT, OnlineClientAtBlockT};
|
||||
use crate::config::Config;
|
||||
use crate::error::StorageError;
|
||||
use crate::storage::address::Address;
|
||||
use crate::storage::{PrefixOf, StorageKeyValue, StorageValue};
|
||||
use crate::utils::YesMaybe;
|
||||
use core::marker::PhantomData;
|
||||
use frame_decode::storage::{IntoEncodableValues, StorageInfo, StorageTypeInfo};
|
||||
use futures::StreamExt;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// This represents a single storage entry (be it a plain value or map)
|
||||
/// and the operations that can be performed on it.
|
||||
#[derive(Debug)]
|
||||
pub struct StorageEntry<'atblock, T: Config, Client, Addr> {
|
||||
inner: Arc<StorageEntryInner<'atblock, Addr, Client>>,
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'atblock, T: Config, Client, Addr> Clone for StorageEntry<'atblock, T, Client, Addr> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: self.inner.clone(),
|
||||
marker: self.marker,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StorageEntryInner<'atblock, Addr, Client> {
|
||||
address: Addr,
|
||||
info: Arc<StorageInfo<'atblock, u32>>,
|
||||
client: &'atblock Client,
|
||||
}
|
||||
|
||||
impl<'atblock, T, Client, Addr> StorageEntry<'atblock, T, Client, Addr>
|
||||
where
|
||||
T: Config,
|
||||
Addr: Address,
|
||||
Client: OfflineClientAtBlockT<T>,
|
||||
{
|
||||
pub(crate) fn new(client: &'atblock Client, address: Addr) -> Result<Self, StorageError> {
|
||||
let info = client
|
||||
.metadata_ref()
|
||||
.storage_info(address.pallet_name(), address.entry_name())
|
||||
.map_err(|e| StorageError::StorageInfoError(e.into_owned()))?;
|
||||
|
||||
let inner = StorageEntryInner {
|
||||
address,
|
||||
info: Arc::new(info),
|
||||
client,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
inner: Arc::new(inner),
|
||||
marker: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
/// Name of the pallet containing this storage entry.
|
||||
pub fn pallet_name(&self) -> &str {
|
||||
self.inner.address.pallet_name()
|
||||
}
|
||||
|
||||
/// Name of the storage entry.
|
||||
pub fn entry_name(&self) -> &str {
|
||||
self.inner.address.entry_name()
|
||||
}
|
||||
|
||||
/// Is the storage entry a plain value?
|
||||
pub fn is_plain(&self) -> bool {
|
||||
self.inner.info.keys.is_empty()
|
||||
}
|
||||
|
||||
/// Is the storage entry a map?
|
||||
pub fn is_map(&self) -> bool {
|
||||
!self.is_plain()
|
||||
}
|
||||
|
||||
/// Return the default value for this storage entry, if there is one. Returns `None` if there
|
||||
/// is no default value.
|
||||
pub fn default_value(&self) -> Option<StorageValue<'atblock, Addr::Value>> {
|
||||
let info = &self.inner.info;
|
||||
let client = self.inner.client;
|
||||
info.default_value.as_ref().map(|default_value| {
|
||||
StorageValue::new(
|
||||
info.clone(),
|
||||
client.metadata_ref().types(),
|
||||
default_value.to_vec(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// The keys for plain storage values are always 32 byte hashes.
|
||||
pub fn key_prefix(&self) -> [u8; 32] {
|
||||
frame_decode::storage::encode_storage_key_prefix(self.pallet_name(), self.entry_name())
|
||||
}
|
||||
|
||||
/// This returns a full key to a single value in this storage entry.
|
||||
pub fn fetch_key(&self, key_parts: Addr::KeyParts) -> Result<Vec<u8>, StorageError> {
|
||||
self.key_from_any_parts(key_parts)
|
||||
}
|
||||
|
||||
/// This returns a valid key suitable for iterating over the values in this storage entry.
|
||||
pub fn iter_key<KeyParts: PrefixOf<Addr::KeyParts>>(
|
||||
&self,
|
||||
key_parts: KeyParts,
|
||||
) -> Result<Vec<u8>, StorageError> {
|
||||
let num_keys = self.inner.info.keys.len();
|
||||
if Addr::IsPlain::is_yes() {
|
||||
Err(StorageError::CannotIterPlainEntry {
|
||||
pallet_name: self.pallet_name().into(),
|
||||
entry_name: self.entry_name().into(),
|
||||
})
|
||||
} else if key_parts.num_encodable_values() >= num_keys {
|
||||
Err(StorageError::WrongNumberOfKeyPartsProvidedForIterating {
|
||||
max_expected: num_keys - 1,
|
||||
got: key_parts.num_encodable_values(),
|
||||
})
|
||||
} else {
|
||||
self.key_from_any_parts(key_parts)
|
||||
}
|
||||
}
|
||||
|
||||
// This has a more lax type signature than `.key` and so can be used in a couple of places internally.
|
||||
fn key_from_any_parts(
|
||||
&self,
|
||||
key_parts: impl IntoEncodableValues,
|
||||
) -> Result<Vec<u8>, StorageError> {
|
||||
let num_keys = self.inner.info.keys.len();
|
||||
if key_parts.num_encodable_values() != num_keys {
|
||||
return Err(StorageError::WrongNumberOfKeyPartsProvidedForFetching {
|
||||
expected: num_keys,
|
||||
got: key_parts.num_encodable_values(),
|
||||
});
|
||||
}
|
||||
|
||||
let key = frame_decode::storage::encode_storage_key_with_info(
|
||||
self.pallet_name(),
|
||||
self.entry_name(),
|
||||
key_parts,
|
||||
&self.inner.info,
|
||||
self.inner.client.metadata_ref().types(),
|
||||
)
|
||||
.map_err(StorageError::StorageKeyEncodeError)?;
|
||||
|
||||
Ok(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'atblock, T, Client, Addr> StorageEntry<'atblock, T, Client, Addr>
|
||||
where
|
||||
T: Config,
|
||||
Addr: Address,
|
||||
Client: OnlineClientAtBlockT<T>,
|
||||
{
|
||||
/// Fetch a storage value within this storage entry.
|
||||
///
|
||||
/// If the entry is a map, you'll need to provide the relevant values for each part of the storage
|
||||
/// key. If the entry is a plain value, you must provide an empty list of key parts, ie `()`.
|
||||
///
|
||||
/// The type of these key parts is determined by the [`Address`] of this storage entry. If the address
|
||||
/// is generated via the `#[subxt]` macro then it will ensure you provide a valid type.
|
||||
///
|
||||
/// If no value is found, the default value will be returned for this entry if one exists. If no value is
|
||||
/// found and no default value exists, an error will be returned.
|
||||
pub async fn fetch(
|
||||
&self,
|
||||
key_parts: Addr::KeyParts,
|
||||
) -> Result<StorageValue<'atblock, Addr::Value>, StorageError> {
|
||||
let value = self
|
||||
.try_fetch(key_parts)
|
||||
.await?
|
||||
.or_else(|| self.default_value())
|
||||
.ok_or(StorageError::NoValueFound)?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
/// Fetch a storage value within this storage entry.
|
||||
///
|
||||
/// If the entry is a map, you'll need to provide the relevant values for each part of the storage
|
||||
/// key. If the entry is a plain value, you must provide an empty list of key parts, ie `()`.
|
||||
///
|
||||
/// The type of these key parts is determined by the [`Address`] of this storage entry. If the address
|
||||
/// is generated via the `#[subxt]` macro then it will ensure you provide a valid type.
|
||||
///
|
||||
/// If no value is found, `None` will be returned.
|
||||
pub async fn try_fetch(
|
||||
&self,
|
||||
key_parts: Addr::KeyParts,
|
||||
) -> Result<Option<StorageValue<'atblock, Addr::Value>>, StorageError> {
|
||||
let key = self.fetch_key(key_parts)?;
|
||||
let block_hash = self.inner.client.block_hash();
|
||||
|
||||
let value = self
|
||||
.inner
|
||||
.client
|
||||
.backend()
|
||||
.storage_fetch_value(key, block_hash)
|
||||
.await
|
||||
.map_err(StorageError::CannotFetchValue)?
|
||||
.map(|bytes| {
|
||||
StorageValue::new(
|
||||
self.inner.info.clone(),
|
||||
self.inner.client.metadata_ref().types(),
|
||||
bytes,
|
||||
)
|
||||
})
|
||||
.or_else(|| self.default_value());
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
/// Iterate over storage values within this storage entry.
|
||||
///
|
||||
/// You'll need to provide a prefix of the key parts required to point to a single value in the map.
|
||||
/// Normally you will provide `()` to iterate over _everything_, `(first_key,)` to iterate over everything underneath
|
||||
/// `first_key` in the map, `(first_key, second_key)` to iterate over everything underneath `first_key`
|
||||
/// and `second_key` in the map, and so on, up to the actual depth of the map - 1.
|
||||
///
|
||||
/// The possible types of these key parts is determined by the [`Address`] of this storage entry.
|
||||
/// If the address is generated via the `#[subxt]` macro then it will ensure you provide a valid type.
|
||||
///
|
||||
/// For plain values, there is no valid type, since they cannot be iterated over.
|
||||
pub async fn iter<KeyParts: PrefixOf<Addr::KeyParts>>(
|
||||
&self,
|
||||
key_parts: KeyParts,
|
||||
) -> Result<
|
||||
impl futures::Stream<Item = Result<StorageKeyValue<'atblock, Addr>, StorageError>>
|
||||
+ use<'atblock, Addr, Client, T, KeyParts>,
|
||||
StorageError,
|
||||
> {
|
||||
let info = self.inner.info.clone();
|
||||
let types = self.inner.client.metadata_ref().types();
|
||||
let key_bytes = self.key_from_any_parts(key_parts)?;
|
||||
let block_hash = self.inner.client.block_hash();
|
||||
|
||||
let stream = self
|
||||
.inner
|
||||
.client
|
||||
.backend()
|
||||
.storage_fetch_descendant_values(key_bytes, block_hash)
|
||||
.await
|
||||
.map_err(StorageError::CannotIterateValues)?
|
||||
.map(move |kv| {
|
||||
let kv = match kv {
|
||||
Ok(kv) => kv,
|
||||
Err(e) => return Err(StorageError::StreamFailure(e)),
|
||||
};
|
||||
Ok(StorageKeyValue::new(
|
||||
info.clone(),
|
||||
types,
|
||||
kv.key.into(),
|
||||
kv.value,
|
||||
))
|
||||
});
|
||||
|
||||
Ok(Box::pin(stream))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user