use alloc::string::ToString;
use alloc::vec::Vec;
use miden_protocol::Word;
use miden_protocol::account::{StorageMapKey, StorageSlotName};
use miden_protocol::block::BlockNumber;
use crate::rpc::domain::MissingFieldHelper;
use crate::rpc::{RpcConversionError, RpcError, generated as proto};
pub struct StorageMapInfo {
pub chain_tip: BlockNumber,
pub block_number: BlockNumber,
pub updates: Vec<StorageMapUpdate>,
}
impl TryFrom<proto::rpc::SyncAccountStorageMapsResponse> for StorageMapInfo {
type Error = RpcError;
fn try_from(value: proto::rpc::SyncAccountStorageMapsResponse) -> Result<Self, Self::Error> {
let pagination_info = value.pagination_info.ok_or(
proto::rpc::SyncAccountStorageMapsResponse::missing_field(stringify!(pagination_info)),
)?;
let chain_tip = pagination_info.chain_tip;
let block_number = pagination_info.block_num;
let updates = value
.updates
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<_>, _>>()?;
Ok(Self {
chain_tip: chain_tip.into(),
block_number: block_number.into(),
updates,
})
}
}
pub struct StorageMapUpdate {
pub block_num: BlockNumber,
pub slot_name: StorageSlotName,
pub key: StorageMapKey,
pub value: Word,
}
impl TryFrom<proto::rpc::StorageMapUpdate> for StorageMapUpdate {
type Error = RpcConversionError;
fn try_from(value: proto::rpc::StorageMapUpdate) -> Result<Self, Self::Error> {
let block_num = value.block_num;
let slot_name = StorageSlotName::new(value.slot_name)
.map_err(|err| RpcConversionError::InvalidField(err.to_string()))?;
let key: StorageMapKey = value
.key
.ok_or(proto::rpc::StorageMapUpdate::missing_field(stringify!(key)))?
.try_into()?;
let value: Word = value
.value
.ok_or(proto::rpc::StorageMapUpdate::missing_field(stringify!(value)))?
.try_into()?;
Ok(Self {
block_num: block_num.into(),
slot_name,
key,
value,
})
}
}