saturn_mempool_oracle/
ops.rs

1use borsh::{BorshDeserialize, BorshSerialize};
2use serde::{Deserialize, Serialize};
3
4use crate::{mempool_entry::MempoolEntry, txid::Txid};
5
6#[derive(Debug, BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)]
7pub enum UpdateMempoolEntriesInstruction {
8    InitializeProgram,
9    ResizeAccounts,
10    ModifyEntries(Vec<UpdateMempoolEntriesOp>),
11    GetEntries(Vec<[u8; 32]>),
12}
13
14#[derive(Debug, BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone)]
15pub struct UpdateMempoolEntries(Vec<UpdateMempoolEntriesOp>);
16
17impl UpdateMempoolEntries {
18    pub fn new() -> Self {
19        Self(Vec::new())
20    }
21
22    pub fn get_entry(&self, index: usize) -> Option<&UpdateMempoolEntriesOp> {
23        self.0.get(index)
24    }
25
26    pub fn is_empty(&self) -> bool {
27        self.0.is_empty()
28    }
29
30    pub fn len(&self) -> usize {
31        self.0.len()
32    }
33
34    pub fn push(&mut self, op: UpdateMempoolEntriesOp) {
35        self.0.push(op);
36    }
37
38    pub fn iter(&self) -> impl Iterator<Item = &UpdateMempoolEntriesOp> {
39        self.0.iter()
40    }
41
42    pub fn into_iter(self) -> impl Iterator<Item = UpdateMempoolEntriesOp> {
43        self.0.into_iter()
44    }
45
46    pub fn split_by_size(
47        &self,
48        max_size: usize,
49    ) -> Result<Vec<UpdateMempoolEntries>, std::io::Error> {
50        let mut result = Vec::new();
51        let mut current = UpdateMempoolEntries::new();
52
53        for op in &self.0 {
54            // Try adding the operation to the current batch
55            current.push(op.clone());
56
57            let serialized = borsh::to_vec(&current.0)?;
58
59            // Check if we've exceeded the max size
60            if serialized.len() > max_size {
61                // Remove the last added operation
62                current.0.pop();
63
64                // Only add non-empty batches to the result
65                if !current.0.is_empty() {
66                    result.push(current);
67                    current = UpdateMempoolEntries::new();
68
69                    // Add the operation to the new batch
70                    current.push(op.clone());
71                }
72            }
73        }
74
75        // Add the final batch if it's not empty
76        if !current.0.is_empty() {
77            result.push(current);
78        }
79
80        Ok(result)
81    }
82}
83
84impl Into<UpdateMempoolEntriesInstruction> for UpdateMempoolEntries {
85    fn into(self) -> UpdateMempoolEntriesInstruction {
86        UpdateMempoolEntriesInstruction::ModifyEntries(self.0)
87    }
88}
89
90impl Into<UpdateMempoolEntriesInstruction> for &UpdateMempoolEntries {
91    fn into(self) -> UpdateMempoolEntriesInstruction {
92        UpdateMempoolEntriesInstruction::ModifyEntries(self.0.clone())
93    }
94}
95
96impl FromIterator<UpdateMempoolEntriesOp> for UpdateMempoolEntries {
97    fn from_iter<I: IntoIterator<Item = UpdateMempoolEntriesOp>>(iter: I) -> Self {
98        Self(iter.into_iter().collect())
99    }
100}
101
102impl IntoIterator for UpdateMempoolEntries {
103    type Item = UpdateMempoolEntriesOp;
104    type IntoIter = std::vec::IntoIter<Self::Item>;
105
106    fn into_iter(self) -> Self::IntoIter {
107        self.0.into_iter()
108    }
109}
110
111impl<'a> IntoIterator for &'a UpdateMempoolEntries {
112    type Item = &'a UpdateMempoolEntriesOp;
113    type IntoIter = std::slice::Iter<'a, UpdateMempoolEntriesOp>;
114
115    fn into_iter(self) -> Self::IntoIter {
116        self.0.iter()
117    }
118}
119
120#[derive(
121    Debug, BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, PartialEq, Eq, Hash,
122)]
123#[serde(tag = "operation", content = "data")]
124pub enum UpdateMempoolEntriesOp {
125    #[serde(rename = "add_entry")]
126    #[serde(serialize_with = "serialize_entry")]
127    AddEntry(MempoolEntry),
128    #[serde(rename = "delete_entry")]
129    #[serde(serialize_with = "serialize_txid")]
130    DeleteEntry(Txid),
131    #[serde(rename = "update_entry")]
132    #[serde(serialize_with = "serialize_entry")]
133    UpdateEntry(MempoolEntry),
134}
135
136fn serialize_entry<S>(entry: &MempoolEntry, serializer: S) -> Result<S::Ok, S::Error>
137where
138    S: serde::Serializer,
139{
140    use serde::ser::SerializeStruct;
141
142    let mut state = serializer.serialize_struct("EntryWithTxid", 2)?;
143    state.serialize_field("txid", &entry.txid)?;
144    state.serialize_field("entry", entry)?;
145    state.end()
146}
147
148fn serialize_txid<S>(txid: &Txid, serializer: S) -> Result<S::Ok, S::Error>
149where
150    S: serde::Serializer,
151{
152    use serde::ser::SerializeStruct;
153
154    let mut state = serializer.serialize_struct("TxidOnly", 1)?;
155    state.serialize_field("txid", &txid)?;
156    state.end()
157}
158
159impl UpdateMempoolEntriesOp {
160    pub fn txid(&self) -> &Txid {
161        match self {
162            UpdateMempoolEntriesOp::AddEntry(entry) => &entry.txid,
163            UpdateMempoolEntriesOp::DeleteEntry(txid) => txid,
164            UpdateMempoolEntriesOp::UpdateEntry(entry) => &entry.txid,
165        }
166    }
167}