1use std::{
2 collections::{HashMap, HashSet},
3 sync::Arc,
4};
5
6use chrono::NaiveDateTime;
7use deepsize::{Context, DeepSizeOf};
8use num_bigint::BigUint;
9use serde::{Deserialize, Serialize};
10
11use crate::{
12 models::{
13 token::Token, Address, AttrStoreKey, Balance, Chain, ChangeType, ComponentId, MergeError,
14 StoreVal, TxHash,
15 },
16 Bytes,
17};
18
19#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)]
31pub struct ProtocolComponent<Token: Into<Address> + Clone = Address> {
32 pub id: ComponentId,
33 pub protocol_system: String,
34 pub protocol_type_name: String,
35 pub chain: Chain,
36 pub tokens: Vec<Token>,
37 pub contract_addresses: Vec<Address>,
38 pub static_attributes: HashMap<AttrStoreKey, StoreVal>,
39 pub change: ChangeType,
40 pub creation_tx: TxHash,
41 pub created_at: NaiveDateTime,
42}
43
44impl<T> ProtocolComponent<T>
45where
46 T: Into<Address> + Clone,
47{
48 #[allow(clippy::too_many_arguments)]
49 pub fn new(
50 id: &str,
51 protocol_system: &str,
52 protocol_type_name: &str,
53 chain: Chain,
54 tokens: Vec<T>,
55 contract_addresses: Vec<Address>,
56 static_attributes: HashMap<AttrStoreKey, StoreVal>,
57 change: ChangeType,
58 creation_tx: TxHash,
59 created_at: NaiveDateTime,
60 ) -> Self {
61 Self {
62 id: id.to_string(),
63 protocol_system: protocol_system.to_string(),
64 protocol_type_name: protocol_type_name.to_string(),
65 chain,
66 tokens,
67 contract_addresses,
68 static_attributes,
69 change,
70 creation_tx,
71 created_at,
72 }
73 }
74}
75
76impl ProtocolComponent<Arc<Token>> {
77 pub fn get_token(&self, address: &Address) -> Option<Arc<Token>> {
78 self.tokens
79 .iter()
80 .find(|t| &t.address == address)
81 .map(Arc::clone)
82 }
83}
84
85impl DeepSizeOf for ProtocolComponent {
86 fn deep_size_of_children(&self, ctx: &mut Context) -> usize {
87 self.id.deep_size_of_children(ctx) +
88 self.protocol_system
89 .deep_size_of_children(ctx) +
90 self.protocol_type_name
91 .deep_size_of_children(ctx) +
92 self.chain.deep_size_of_children(ctx) +
93 self.tokens.deep_size_of_children(ctx) +
94 self.contract_addresses
95 .deep_size_of_children(ctx) +
96 self.static_attributes
97 .deep_size_of_children(ctx) +
98 self.change.deep_size_of_children(ctx) +
99 self.creation_tx
100 .deep_size_of_children(ctx)
101 }
102}
103
104#[derive(Debug, Clone, PartialEq)]
105pub struct ProtocolComponentState {
106 pub component_id: ComponentId,
107 pub attributes: HashMap<AttrStoreKey, StoreVal>,
108 pub balances: HashMap<Address, Balance>,
110}
111
112impl ProtocolComponentState {
113 pub fn new(
114 component_id: &str,
115 attributes: HashMap<AttrStoreKey, StoreVal>,
116 balances: HashMap<Address, Balance>,
117 ) -> Self {
118 Self { component_id: component_id.to_string(), attributes, balances }
119 }
120
121 pub fn apply_state_delta(
125 &mut self,
126 delta: &ProtocolComponentStateDelta,
127 ) -> Result<(), MergeError> {
128 if self.component_id != delta.component_id {
129 return Err(MergeError::IdMismatch(
130 "ProtocolComponentStates".to_string(),
131 self.component_id.clone(),
132 delta.component_id.clone(),
133 ));
134 }
135 self.attributes
136 .extend(delta.updated_attributes.clone());
137
138 self.attributes
139 .retain(|attr, _| !delta.deleted_attributes.contains(attr));
140
141 Ok(())
142 }
143
144 pub fn apply_balance_delta(
148 &mut self,
149 delta: &HashMap<Bytes, ComponentBalance>,
150 ) -> Result<(), MergeError> {
151 self.balances.extend(
152 delta
153 .iter()
154 .map(|(k, v)| (k.clone(), v.balance.clone())),
155 );
156
157 Ok(())
158 }
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, DeepSizeOf)]
162pub struct ProtocolComponentStateDelta {
163 pub component_id: ComponentId,
164 pub updated_attributes: HashMap<AttrStoreKey, StoreVal>,
165 pub deleted_attributes: HashSet<AttrStoreKey>,
166}
167
168impl ProtocolComponentStateDelta {
169 pub fn new(
170 component_id: &str,
171 updated_attributes: HashMap<AttrStoreKey, StoreVal>,
172 deleted_attributes: HashSet<AttrStoreKey>,
173 ) -> Self {
174 Self { component_id: component_id.to_string(), updated_attributes, deleted_attributes }
175 }
176
177 pub fn merge(&mut self, other: ProtocolComponentStateDelta) -> Result<(), MergeError> {
189 if self.component_id != other.component_id {
190 return Err(MergeError::IdMismatch(
191 "ProtocolComponentStateDeltas".to_string(),
192 self.component_id.clone(),
193 other.component_id.clone(),
194 ));
195 }
196 for attr in &other.deleted_attributes {
197 self.updated_attributes.remove(attr);
198 }
199 for attr in other.updated_attributes.keys() {
200 self.deleted_attributes.remove(attr);
201 }
202 self.updated_attributes
203 .extend(other.updated_attributes);
204 self.deleted_attributes
205 .extend(other.deleted_attributes);
206 Ok(())
207 }
208}
209
210#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, DeepSizeOf)]
211pub struct ComponentBalance {
212 pub token: Address,
213 pub balance: Balance,
214 pub balance_float: f64,
215 pub modify_tx: TxHash,
216 pub component_id: ComponentId,
217}
218
219impl ComponentBalance {
220 pub fn new(
221 token: Address,
222 new_balance: Balance,
223 balance_float: f64,
224 modify_tx: TxHash,
225 component_id: &str,
226 ) -> Self {
227 Self {
228 token,
229 balance: new_balance,
230 balance_float,
231 modify_tx,
232 component_id: component_id.to_string(),
233 }
234 }
235}
236
237#[derive(Debug, Clone)]
241pub struct QualityRange {
242 pub min: Option<i32>,
243 pub max: Option<i32>,
244}
245
246impl QualityRange {
247 pub fn new(min: i32, max: i32) -> Self {
248 Self { min: Some(min), max: Some(max) }
249 }
250
251 pub fn min_only(min: i32) -> Self {
252 Self { min: Some(min), max: None }
253 }
254
255 #[allow(non_snake_case)]
256 pub fn None() -> Self {
257 Self { min: None, max: None }
258 }
259}
260
261pub struct GetAmountOutParams {
262 pub amount_in: BigUint,
263 pub token_in: Bytes,
264 pub token_out: Bytes,
265 pub sender: Bytes,
266 pub receiver: Bytes,
267}
268
269#[cfg(test)]
270mod test {
271 use super::*;
272
273 fn create_state(id: String) -> ProtocolComponentStateDelta {
274 let attributes1: HashMap<String, Bytes> = vec![
275 ("reserve1".to_owned(), Bytes::from(1000u64).lpad(32, 0)),
276 ("reserve2".to_owned(), Bytes::from(500u64).lpad(32, 0)),
277 ("static_attribute".to_owned(), Bytes::from(1u64).lpad(32, 0)),
278 ]
279 .into_iter()
280 .collect();
281 ProtocolComponentStateDelta {
282 component_id: id,
283 updated_attributes: attributes1,
284 deleted_attributes: HashSet::new(),
285 }
286 }
287
288 #[test]
289 fn test_merge_protocol_state_updates() {
290 let mut state_1 = create_state("State1".to_owned());
291 state_1
292 .updated_attributes
293 .insert("to_be_removed".to_owned(), Bytes::from(1u64).lpad(32, 0));
294 state_1.deleted_attributes = vec!["to_add_back".to_owned()]
295 .into_iter()
296 .collect();
297
298 let attributes2: HashMap<String, Bytes> = vec![
299 ("reserve1".to_owned(), Bytes::from(900u64).lpad(32, 0)),
300 ("reserve2".to_owned(), Bytes::from(550u64).lpad(32, 0)),
301 ("new_attribute".to_owned(), Bytes::from(1u64).lpad(32, 0)),
302 ("to_add_back".to_owned(), Bytes::from(200u64).lpad(32, 0)),
303 ]
304 .into_iter()
305 .collect();
306 let del_attributes2: HashSet<String> = vec!["to_be_removed".to_owned()]
307 .into_iter()
308 .collect();
309 let mut state_2 = create_state("State1".to_owned());
310 state_2.updated_attributes = attributes2;
311 state_2.deleted_attributes = del_attributes2;
312
313 let res = state_1.merge(state_2);
314
315 assert!(res.is_ok());
316 let expected_attributes: HashMap<String, Bytes> = vec![
317 ("reserve1".to_owned(), Bytes::from(900u64).lpad(32, 0)),
318 ("reserve2".to_owned(), Bytes::from(550u64).lpad(32, 0)),
319 ("static_attribute".to_owned(), Bytes::from(1u64).lpad(32, 0)),
320 ("new_attribute".to_owned(), Bytes::from(1u64).lpad(32, 0)),
321 ("to_add_back".to_owned(), Bytes::from(200u64).lpad(32, 0)),
322 ]
323 .into_iter()
324 .collect();
325 assert_eq!(state_1.updated_attributes, expected_attributes);
326 let expected_del_attributes: HashSet<String> = vec!["to_be_removed".to_owned()]
327 .into_iter()
328 .collect();
329 assert_eq!(state_1.deleted_attributes, expected_del_attributes);
330 }
331
332 #[test]
333 fn test_merge_protocol_state_update_wrong_id() {
334 let mut state1 = create_state("State1".to_owned());
335 let state2 = create_state("State2".to_owned());
336
337 let res = state1.merge(state2);
338
339 assert_eq!(
340 res,
341 Err(MergeError::IdMismatch(
342 "ProtocolComponentStateDeltas".to_string(),
343 "State1".to_string(),
344 "State2".to_string(),
345 ))
346 );
347 }
348}