kabu_types_events/
swap_compose.rs

1use crate::tx_compose::TxComposeData;
2use crate::Message;
3use alloy_eips::eip2718::Encodable2718;
4use alloy_primitives::{Bytes, TxHash, U256};
5use eyre::{eyre, Result};
6use kabu_types_blockchain::{KabuDataTypes, KabuDataTypesEthereum};
7use kabu_types_entities::{PoolId, Swap};
8use revm::DatabaseRef;
9use std::ops::Deref;
10
11#[derive(Clone, Debug)]
12pub enum TxState<LDT: KabuDataTypes = KabuDataTypesEthereum> {
13    Stuffing(LDT::Transaction),
14    SignatureRequired(LDT::TransactionRequest),
15    ReadyForBroadcast(Bytes),
16    ReadyForBroadcastStuffing(Bytes),
17}
18
19impl TxState {
20    pub fn rlp(&self) -> Result<Bytes> {
21        match self {
22            TxState::Stuffing(t) => Ok(Bytes::from(t.clone().inner.encoded_2718())),
23            TxState::ReadyForBroadcast(t) | TxState::ReadyForBroadcastStuffing(t) => Ok(t.clone()),
24            _ => Err(eyre!("NOT_READY_FOR_BROADCAST")),
25        }
26    }
27}
28
29#[derive(Clone, Debug)]
30pub enum SwapComposeMessage<DB, LDT: KabuDataTypes = KabuDataTypesEthereum> {
31    Prepare(SwapComposeData<DB, LDT>),
32    Estimate(SwapComposeData<DB, LDT>),
33    Ready(SwapComposeData<DB, LDT>),
34}
35
36impl<DB, LDT: KabuDataTypes> Deref for SwapComposeMessage<DB, LDT> {
37    type Target = SwapComposeData<DB, LDT>;
38
39    fn deref(&self) -> &Self::Target {
40        self.data()
41    }
42}
43
44impl<DB, LDT: KabuDataTypes> SwapComposeMessage<DB, LDT> {
45    pub fn data(&self) -> &SwapComposeData<DB, LDT> {
46        match self {
47            SwapComposeMessage::Prepare(x) | SwapComposeMessage::Estimate(x) | SwapComposeMessage::Ready(x) => x,
48        }
49    }
50}
51
52#[derive(Clone, Debug)]
53pub struct SwapComposeData<DB, LDT: KabuDataTypes = KabuDataTypesEthereum> {
54    pub tx_compose: TxComposeData<LDT>,
55    pub swap: Swap,
56    pub prestate: Option<DB>,
57    pub poststate: Option<DB>,
58    pub poststate_update: Option<Vec<LDT::StateUpdate>>,
59    pub origin: Option<String>,
60    pub tips_pct: Option<u32>,
61    pub tips: Option<U256>,
62}
63
64impl<DB: Clone + 'static, LDT: KabuDataTypes> SwapComposeData<DB, LDT> {
65    pub fn same_stuffing(&self, others_stuffing_txs_hashes: &[TxHash]) -> bool {
66        let tx_len = self.tx_compose.stuffing_txs_hashes.len();
67
68        if tx_len != others_stuffing_txs_hashes.len() {
69            false
70        } else if tx_len == 0 {
71            true
72        } else {
73            others_stuffing_txs_hashes.iter().all(|x| self.tx_compose.stuffing_txs_hashes.contains(x))
74        }
75    }
76
77    pub fn cross_pools(&self, others_pools: &[PoolId]) -> bool {
78        self.swap.get_pool_id_vec().iter().any(|x| others_pools.contains(x))
79    }
80
81    pub fn first_stuffing_hash(&self) -> TxHash {
82        self.tx_compose.stuffing_txs_hashes.first().map_or(TxHash::default(), |x| *x)
83    }
84
85    pub fn tips_gas_ratio(&self) -> U256 {
86        if self.tx_compose.gas == 0 {
87            U256::ZERO
88        } else {
89            self.tips.unwrap_or_default() / U256::from(self.tx_compose.gas)
90        }
91    }
92
93    pub fn profit_eth_gas_ratio(&self) -> U256 {
94        if self.tx_compose.gas == 0 {
95            U256::ZERO
96        } else {
97            self.swap.arb_profit_eth() / U256::from(self.tx_compose.gas)
98        }
99    }
100
101    pub fn gas_price(&self) -> u128 {
102        self.tx_compose.next_block_base_fee as u128 + self.tx_compose.priority_gas_fee as u128
103    }
104
105    pub fn gas_cost(&self) -> u128 {
106        self.tx_compose.gas as u128 * (self.tx_compose.next_block_base_fee as u128 + self.tx_compose.priority_gas_fee as u128)
107    }
108}
109
110impl<DB: DatabaseRef + Send + Sync + Clone + 'static, LDT: KabuDataTypes> Default for SwapComposeData<DB, LDT> {
111    fn default() -> Self {
112        Self {
113            tx_compose: Default::default(),
114            swap: Swap::None,
115            prestate: None,
116            poststate: None,
117            poststate_update: None,
118            origin: None,
119            tips_pct: None,
120            tips: None,
121        }
122    }
123}
124
125pub type MessageSwapCompose<DB, LDT = KabuDataTypesEthereum> = Message<SwapComposeMessage<DB, LDT>>;
126
127impl<DB, LDT: KabuDataTypes> MessageSwapCompose<DB, LDT> {
128    pub fn prepare(data: SwapComposeData<DB, LDT>) -> Self {
129        Message::new(SwapComposeMessage::Prepare(data))
130    }
131
132    pub fn estimate(data: SwapComposeData<DB, LDT>) -> Self {
133        Message::new(SwapComposeMessage::Estimate(data))
134    }
135
136    pub fn ready(data: SwapComposeData<DB, LDT>) -> Self {
137        Message::new(SwapComposeMessage::Ready(data))
138    }
139}