1use std::collections::{BTreeMap, VecDeque};
2
3use mina_p2p_messages::v2::{
4 LedgerHash, MinaBaseAccountBinableArgStableV2, MinaBaseTransactionStatusStableV2,
5 MinaBaseUserCommandStableV2, NonZeroCurvePoint, StateHash, TransactionHash,
6};
7use serde::{Deserialize, Serialize};
8
9use crate::p2p::PeerId;
10
11#[derive(Serialize, Deserialize, Debug, Clone)]
12pub struct WatchedAccountBlockInfo {
13 pub level: u32,
14 pub hash: StateHash,
15 pub pred_hash: StateHash,
16 pub staged_ledger_hash: LedgerHash,
17}
18
19#[derive(Serialize, Deserialize, Debug, Clone)]
20pub struct Transaction {
21 pub hash: Option<TransactionHash>,
22 pub data: MinaBaseUserCommandStableV2,
23 pub status: MinaBaseTransactionStatusStableV2,
24}
25
26#[derive(Serialize, Deserialize, Debug, Clone)]
27pub enum WatchedAccountsLedgerInitialStateGetError {
28 PeerDisconnected,
29 P2pRpcError(mina_p2p_messages::core::Info),
31}
32
33#[derive(Serialize, Deserialize, Debug, Clone)]
34#[serde(tag = "state")]
35pub enum WatchedAccountLedgerInitialState {
36 Idle {
37 time: redux::Timestamp,
38 },
39 Pending {
40 time: redux::Timestamp,
41 block: WatchedAccountBlockInfo,
42 peer_id: PeerId,
43 },
44 Error {
45 time: redux::Timestamp,
46 error: WatchedAccountsLedgerInitialStateGetError,
47 peer_id: PeerId,
48 },
49 Success {
50 time: redux::Timestamp,
51 block: WatchedAccountBlockInfo,
52 data: Option<Box<MinaBaseAccountBinableArgStableV2>>,
53 },
54}
55
56impl WatchedAccountLedgerInitialState {
57 pub fn block(&self) -> Option<&WatchedAccountBlockInfo> {
58 match self {
59 Self::Pending { block, .. } => Some(block),
60 _ => None,
61 }
62 }
63
64 pub fn data(&self) -> Option<&MinaBaseAccountBinableArgStableV2> {
65 match self {
66 Self::Success { data, .. } => data.as_ref().map(AsRef::as_ref),
67 _ => None,
68 }
69 }
70
71 pub fn is_success(&self) -> bool {
72 matches!(self, Self::Success { .. })
73 }
74}
75
76#[derive(Serialize, Deserialize, Debug, Clone)]
77#[serde(tag = "state")]
78pub enum WatchedAccountBlockState {
79 TransactionsInBlockBody {
81 block: WatchedAccountBlockInfo,
82 transactions: Vec<Transaction>,
84 },
85 LedgerAccountGetPending {
87 block: WatchedAccountBlockInfo,
88 transactions: Vec<Transaction>,
90 },
91 LedgerAccountGetSuccess {
93 block: WatchedAccountBlockInfo,
94 transactions: Vec<Transaction>,
96 ledger_account: Box<MinaBaseAccountBinableArgStableV2>,
97 },
98}
99
100impl WatchedAccountBlockState {
101 pub fn block(&self) -> &WatchedAccountBlockInfo {
102 match self {
103 Self::TransactionsInBlockBody { block, .. } => block,
104 Self::LedgerAccountGetPending { block, .. } => block,
105 Self::LedgerAccountGetSuccess { block, .. } => block,
106 }
107 }
108
109 pub fn transactions(&self) -> &[Transaction] {
110 match self {
111 Self::TransactionsInBlockBody { transactions, .. } => transactions,
112 Self::LedgerAccountGetPending { transactions, .. } => transactions,
113 Self::LedgerAccountGetSuccess { transactions, .. } => transactions,
114 }
115 }
116
117 pub fn ledger_account(&self) -> Option<&MinaBaseAccountBinableArgStableV2> {
118 match self {
119 Self::TransactionsInBlockBody { .. } => None,
120 Self::LedgerAccountGetPending { .. } => None,
121 Self::LedgerAccountGetSuccess { ledger_account, .. } => Some(ledger_account),
122 }
123 }
124}
125
126#[derive(Serialize, Deserialize, Debug, Clone)]
127pub struct WatchedAccountState {
128 pub initial_state: WatchedAccountLedgerInitialState,
129
130 pub blocks: VecDeque<WatchedAccountBlockState>,
132 }
135
136impl WatchedAccountState {
137 pub fn block_find_by_hash(&self, hash: &StateHash) -> Option<&WatchedAccountBlockState> {
138 self.blocks.iter().rev().find(|b| &b.block().hash == hash)
139 }
140
141 pub fn block_find_by_hash_mut(
142 &mut self,
143 hash: &StateHash,
144 ) -> Option<&mut WatchedAccountBlockState> {
145 self.blocks
146 .iter_mut()
147 .rev()
148 .find(|b| &b.block().hash == hash)
149 }
150}
151
152#[derive(Serialize, Deserialize, Debug, Clone, Default)]
153pub struct WatchedAccountsState {
154 list: BTreeMap<NonZeroCurvePoint, WatchedAccountState>,
155}
156
157impl WatchedAccountsState {
158 pub fn new() -> Self {
159 Self::default()
160 }
161
162 pub fn contains(&self, key: &NonZeroCurvePoint) -> bool {
163 self.list.contains_key(key)
164 }
165
166 pub fn get(&self, key: &NonZeroCurvePoint) -> Option<&WatchedAccountState> {
167 self.list.get(key)
168 }
169
170 pub fn get_mut(&mut self, key: &NonZeroCurvePoint) -> Option<&mut WatchedAccountState> {
171 self.list.get_mut(key)
172 }
173
174 pub fn insert(&mut self, key: NonZeroCurvePoint, value: WatchedAccountState) {
175 self.list.insert(key, value);
176 }
177
178 pub fn iter(
179 &self,
180 ) -> impl '_ + Iterator<Item = (&'_ NonZeroCurvePoint, &'_ WatchedAccountState)> {
181 self.list.iter()
182 }
183
184 pub fn accounts(&self) -> Vec<NonZeroCurvePoint> {
185 self.iter().map(|v| v.0.clone()).collect()
186 }
187}