barreleye_common/chain/
mod.rs1use async_trait::async_trait;
2use chrono::NaiveDateTime;
3use derive_more::Display;
4use eyre::Result;
5use std::{collections::HashSet, ops::AddAssign, sync::Arc};
6
7pub use crate::chain::bitcoin::Bitcoin;
8use crate::{
9 models::{Balance, Link, Network, Transfer},
10 utils, BlockHeight, PrimaryId, RateLimiter, Warehouse,
11};
12pub use evm::Evm;
13pub use u256::U256;
14
15pub mod bitcoin;
16pub mod evm;
17pub mod u256;
18
19pub type BoxedChain = Box<dyn ChainTrait>;
20
21#[repr(u16)]
22#[derive(Display, Debug, Copy, Clone, PartialEq, Eq, Hash)]
23pub enum ModuleId {
24 BitcoinCoinbase = 101,
25 BitcoinTransfer = 102,
26 BitcoinBalance = 103,
27 BitcoinLink = 104,
28 EvmTransfer = 201,
29 EvmBalance = 202,
30 EvmTokenTransfer = 203,
31 EvmTokenBalance = 204,
32}
33
34#[async_trait]
35pub trait ChainTrait: Send + Sync {
36 async fn connect(&mut self) -> Result<bool>;
37 fn is_connected(&self) -> bool;
38
39 fn get_network(&self) -> Network;
40 fn get_rpc(&self) -> Option<String>;
41 fn get_module_ids(&self) -> Vec<ModuleId>;
42 fn format_address(&self, address: &str) -> String;
43 fn get_rate_limiter(&self) -> Option<Arc<RateLimiter>>;
44
45 async fn get_block_height(&self) -> Result<BlockHeight>;
46
47 async fn process_block(
48 &self,
49 block_height: BlockHeight,
50 modules: Vec<ModuleId>,
51 ) -> Result<Option<WarehouseData>>;
52
53 async fn rate_limit(&self) {
54 if let Some(rate_limiter) = &self.get_rate_limiter() {
55 rate_limiter.until_ready().await;
56 }
57 }
58}
59
60#[async_trait]
61pub trait ModuleTrait {
62 fn new(network_id: PrimaryId) -> Self
63 where
64 Self: Sized;
65 fn get_id(&self) -> ModuleId;
66}
67
68#[derive(Debug, Default, Clone)]
69pub struct WarehouseData {
70 saved_at: NaiveDateTime,
71 transfers: HashSet<Transfer>,
72 balances: HashSet<Balance>,
73 links: HashSet<Link>,
74}
75
76impl WarehouseData {
77 pub fn new() -> Self {
78 Self { saved_at: utils::now(), ..Default::default() }
79 }
80
81 pub fn len(&self) -> usize {
82 self.transfers.len() + self.balances.len() + self.links.len()
83 }
84
85 pub fn is_empty(&self) -> bool {
86 self.len() == 0
87 }
88
89 pub fn should_commit(&self) -> bool {
90 utils::ago_in_seconds(5) > self.saved_at && self.len() > 10_000
91 }
92
93 pub async fn commit(&mut self, warehouse: &Warehouse) -> Result<()> {
94 if !self.transfers.is_empty() {
95 Transfer::create_many(warehouse, self.transfers.clone().into_iter().collect()).await?;
96 }
97
98 if !self.balances.is_empty() {
99 Balance::create_many(warehouse, self.balances.clone().into_iter().collect()).await?;
100 }
101
102 if !self.links.is_empty() {
103 Link::create_many(warehouse, self.links.clone().into_iter().collect()).await?;
104 }
105
106 self.clear();
107
108 Ok(())
109 }
110
111 pub fn clear(&mut self) {
112 self.saved_at = utils::now();
113
114 self.transfers.clear();
115 self.balances.clear();
116 self.links.clear();
117 }
118}
119
120impl AddAssign for WarehouseData {
121 fn add_assign(&mut self, rhs: WarehouseData) {
122 self.transfers.extend(rhs.transfers);
123 self.balances.extend(rhs.balances);
124 self.links.extend(rhs.links);
125 }
126}