miden_client/rpc/domain/
sync.rs1use alloc::vec::Vec;
2
3use miden_protocol::Word;
4use miden_protocol::account::AccountId;
5use miden_protocol::block::{BlockHeader, BlockNumber};
6use miden_protocol::crypto::merkle::mmr::MmrDelta;
7use miden_protocol::note::NoteId;
8use miden_protocol::transaction::TransactionId;
9
10use super::note::CommittedNote;
11use super::transaction::TransactionInclusion;
12use crate::rpc::domain::MissingFieldHelper;
13use crate::rpc::{RpcError, generated as proto};
14
15pub struct StateSyncInfo {
20 pub chain_tip: BlockNumber,
22 pub block_header: BlockHeader,
24 pub mmr_delta: MmrDelta,
26 pub account_commitment_updates: Vec<(AccountId, Word)>,
28 pub note_inclusions: Vec<CommittedNote>,
30 pub transactions: Vec<TransactionInclusion>,
34}
35
36impl TryFrom<proto::rpc::SyncStateResponse> for StateSyncInfo {
40 type Error = RpcError;
41
42 fn try_from(value: proto::rpc::SyncStateResponse) -> Result<Self, Self::Error> {
43 let chain_tip = value.chain_tip;
44
45 let block_header: BlockHeader = value
47 .block_header
48 .ok_or(proto::rpc::SyncStateResponse::missing_field(stringify!(block_header)))?
49 .try_into()?;
50
51 let mmr_delta = value
53 .mmr_delta
54 .ok_or(proto::rpc::SyncStateResponse::missing_field(stringify!(mmr_delta)))?
55 .try_into()?;
56
57 let mut account_commitment_updates = vec![];
59 for update in value.accounts {
60 let account_id = update
61 .account_id
62 .ok_or(proto::rpc::SyncStateResponse::missing_field(stringify!(
63 accounts.account_id
64 )))?
65 .try_into()?;
66 let account_commitment = update
67 .account_commitment
68 .ok_or(proto::rpc::SyncStateResponse::missing_field(stringify!(
69 accounts.account_commitment
70 )))?
71 .try_into()?;
72 account_commitment_updates.push((account_id, account_commitment));
73 }
74
75 let mut note_inclusions = vec![];
77 for note in value.notes {
78 let note_id: NoteId = note
79 .note_id
80 .ok_or(proto::rpc::SyncStateResponse::missing_field(stringify!(notes.note_id)))?
81 .try_into()?;
82
83 let inclusion_path = note
84 .inclusion_path
85 .ok_or(proto::rpc::SyncStateResponse::missing_field(stringify!(
86 notes.inclusion_path
87 )))?
88 .try_into()?;
89
90 let metadata = note
91 .metadata
92 .ok_or(proto::rpc::SyncStateResponse::missing_field(stringify!(notes.metadata)))?
93 .try_into()?;
94
95 let committed_note = super::note::CommittedNote::new(
96 note_id,
97 u16::try_from(note.note_index_in_block).expect("note index out of range"),
98 inclusion_path,
99 metadata,
100 );
101
102 note_inclusions.push(committed_note);
103 }
104
105 let transactions = value
106 .transactions
107 .iter()
108 .map(|transaction_summary| {
109 let transaction_id = transaction_summary.transaction_id.ok_or(
110 proto::rpc::SyncStateResponse::missing_field(stringify!(
111 transactions.transaction_id
112 )),
113 )?;
114 let transaction_id = TransactionId::try_from(transaction_id)?;
115
116 let transaction_block_num = transaction_summary.block_num;
117
118 let transaction_account_id = transaction_summary.account_id.clone().ok_or(
119 proto::rpc::SyncStateResponse::missing_field(stringify!(
120 transactions.account_id
121 )),
122 )?;
123 let transaction_account_id = AccountId::try_from(transaction_account_id)?;
124
125 Ok(TransactionInclusion {
126 transaction_id,
127 block_num: transaction_block_num.into(),
128 account_id: transaction_account_id,
129 })
130 })
131 .collect::<Result<Vec<TransactionInclusion>, RpcError>>()?;
132
133 Ok(Self {
134 chain_tip: chain_tip.into(),
135 block_header,
136 mmr_delta,
137 account_commitment_updates,
138 note_inclusions,
139 transactions,
140 })
141 }
142}