Skip to main content

miden_client/rpc/domain/
account_vault.rs

1use alloc::string::ToString;
2use alloc::vec::Vec;
3
4use miden_protocol::Word;
5use miden_protocol::asset::{Asset, AssetVaultKey};
6use miden_protocol::block::BlockNumber;
7use miden_protocol::errors::AssetError;
8
9use crate::rpc::domain::MissingFieldHelper;
10use crate::rpc::{RpcError, generated as proto};
11
12// ACCOUNT VAULT INFO
13// ================================================================================================
14
15/// Represents a `proto::rpc::SyncAccountVaultResponse` with fields converted into domain
16/// types. Contains information of asset updates in a given range of blocks specified on request.
17/// Also provides the current chain tip while processing the request.
18pub struct AccountVaultInfo {
19    /// Current chain tip
20    pub chain_tip: BlockNumber,
21    /// The block number of the last check included in this response.
22    pub block_number: BlockNumber,
23    /// List of asset updates for the account.
24    pub updates: Vec<AccountVaultUpdate>,
25}
26
27// ACCOUNT VAULT CONVERSION
28// ================================================================================================
29
30impl TryFrom<proto::rpc::SyncAccountVaultResponse> for AccountVaultInfo {
31    type Error = RpcError;
32
33    fn try_from(value: proto::rpc::SyncAccountVaultResponse) -> Result<Self, Self::Error> {
34        let pagination_info =
35            value
36                .pagination_info
37                .ok_or(proto::rpc::SyncAccountVaultResponse::missing_field(stringify!(
38                    pagination_info
39                )))?;
40        let chain_tip = pagination_info.chain_tip;
41        let block_number = pagination_info.block_num;
42
43        let updates = value
44            .updates
45            .iter()
46            .map(|update| (*update).try_into())
47            .collect::<Result<Vec<_>, _>>()?;
48
49        Ok(Self {
50            chain_tip: chain_tip.into(),
51            block_number: block_number.into(),
52            updates,
53        })
54    }
55}
56
57// ACCOUNT VAULT UPDATE
58// ================================================================================================
59
60/// Represents an update to an account vault, including the vault key and asset value involved.
61pub struct AccountVaultUpdate {
62    /// Block number in which the slot was updated.
63    pub block_num: BlockNumber,
64    /// Asset value related to the vault key. If not present, the asset was removed from the vault.
65    pub asset: Option<Asset>,
66    /// Vault key associated with the asset.
67    pub vault_key: AssetVaultKey,
68}
69
70// ACCOUNT VAULT UPDATE CONVERSION
71// ================================================================================================
72
73impl TryFrom<proto::primitives::Asset> for Asset {
74    type Error = RpcError;
75
76    fn try_from(value: proto::primitives::Asset) -> Result<Self, Self::Error> {
77        let word: Word = value
78            .asset
79            .ok_or(proto::rpc::SyncAccountVaultResponse::missing_field(stringify!(asset)))?
80            .try_into()?;
81        word.try_into()
82            .map_err(|e: AssetError| RpcError::InvalidResponse(e.to_string()))
83    }
84}
85
86impl TryFrom<proto::rpc::AccountVaultUpdate> for AccountVaultUpdate {
87    type Error = RpcError;
88
89    fn try_from(value: proto::rpc::AccountVaultUpdate) -> Result<Self, Self::Error> {
90        let block_num = value.block_num;
91
92        let asset: Option<Asset> = value.asset.map(TryInto::try_into).transpose()?;
93
94        let vault_key_inner: Word = value
95            .vault_key
96            .ok_or(proto::rpc::SyncAccountVaultResponse::missing_field(stringify!(vault_key)))?
97            .try_into()?;
98        let vault_key = AssetVaultKey::new_unchecked(vault_key_inner);
99
100        Ok(Self {
101            block_num: block_num.into(),
102            asset,
103            vault_key,
104        })
105    }
106}