miden_client/rpc/domain/
account_vault.rs1use alloc::string::ToString;
2use alloc::vec::Vec;
3
4use miden_objects::DecodeMessageExt;
5use miden_protocol::Word;
6use miden_protocol::account::AccountVaultPatch;
7use miden_protocol::asset::{Asset, AssetId};
8use miden_protocol::block::BlockNumber;
9
10use crate::rpc::domain::MissingFieldHelper;
11use crate::rpc::{RpcError, generated as proto};
12
13pub struct AccountVaultInfo {
22 pub chain_tip: BlockNumber,
24 pub block_number: BlockNumber,
26 pub vault_patch: AccountVaultPatch,
28}
29
30impl TryFrom<proto::rpc::SyncAccountVaultResponse> for AccountVaultInfo {
34 type Error = RpcError;
35
36 fn try_from(value: proto::rpc::SyncAccountVaultResponse) -> Result<Self, Self::Error> {
37 let pagination_info =
38 value
39 .pagination_info
40 .ok_or(proto::rpc::SyncAccountVaultResponse::missing_field(stringify!(
41 pagination_info
42 )))?;
43
44 let mut updates = value
45 .updates
46 .into_iter()
47 .map(vault_update_from_proto)
48 .collect::<Result<Vec<_>, _>>()?;
49
50 updates.sort_by_key(|(block_num, ..)| *block_num);
54 let mut vault_patch = AccountVaultPatch::default();
55 for (_, asset_id, asset) in updates {
56 match asset {
57 Some(asset) => vault_patch.insert_asset(asset),
58 None => vault_patch.remove_asset(asset_id),
59 }
60 }
61
62 Ok(Self {
63 chain_tip: pagination_info.chain_tip.into(),
64 block_number: pagination_info.block_num.into(),
65 vault_patch,
66 })
67 }
68}
69
70fn vault_update_from_proto(
76 value: proto::rpc::AccountVaultUpdate,
77) -> Result<(BlockNumber, AssetId, Option<Asset>), RpcError> {
78 let block_num = BlockNumber::from(value.block_num);
79
80 let asset_id: Word = value
81 .vault_key
82 .ok_or(proto::rpc::SyncAccountVaultResponse::missing_field(stringify!(asset_id)))?
83 .try_into()?;
84 let asset_id =
85 AssetId::try_from(asset_id).map_err(|e| RpcError::InvalidResponse(e.to_string()))?;
86
87 let asset: Option<Asset> = value.asset.map(DecodeMessageExt::decode_and_verify).transpose()?;
88
89 if let Some(ref asset) = asset
90 && asset.id() != asset_id
91 {
92 return Err(RpcError::InvalidResponse(
93 "account vault update returned mismatched asset key".to_string(),
94 ));
95 }
96
97 Ok((block_num, asset_id, asset))
98}