use super::{
storage_type::{validate_storage_address, Storage},
utils, StorageAddress,
};
use crate::{
client::{OfflineClientT, OnlineClientT},
error::Error,
Config,
};
use derivative::Derivative;
use std::{future::Future, marker::PhantomData};
#[derive(Derivative)]
#[derivative(Clone(bound = "Client: Clone"))]
pub struct StorageClient<T, Client> {
client: Client,
_marker: PhantomData<T>,
}
impl<T, Client> StorageClient<T, Client> {
pub fn new(client: Client) -> Self {
Self {
client,
_marker: PhantomData,
}
}
}
impl<T, Client> StorageClient<T, Client>
where
T: Config,
Client: OfflineClientT<T>,
{
pub fn validate<Address: StorageAddress>(&self, address: &Address) -> Result<(), Error> {
let metadata = self.client.metadata();
let pallet_metadata = metadata.pallet_by_name_err(address.pallet_name())?;
validate_storage_address(address, pallet_metadata)
}
pub fn address_root_bytes<Address: StorageAddress>(&self, address: &Address) -> Vec<u8> {
utils::storage_address_root_bytes(address)
}
pub fn address_bytes<Address: StorageAddress>(
&self,
address: &Address,
) -> Result<Vec<u8>, Error> {
utils::storage_address_bytes(address, &self.client.metadata())
}
}
impl<T, Client> StorageClient<T, Client>
where
T: Config,
Client: OnlineClientT<T>,
{
pub fn at(&self, block_hash: T::Hash) -> Storage<T, Client> {
Storage::new(self.client.clone(), block_hash)
}
pub fn at_latest(
&self,
) -> impl Future<Output = Result<Storage<T, Client>, Error>> + Send + 'static {
let client = self.client.clone();
async move {
let block_hash = client
.rpc()
.block_hash(None)
.await?
.expect("didn't pass a block number; qed");
Ok(Storage::new(client, block_hash))
}
}
}