solana_central/types/pool.rs
1use crate::CentralContext;
2use crate::types::pools::Pools;
3use crate::types::swap_direction::SwapDirection;
4use solana_sdk::pubkey::Pubkey;
5use std::any::Any;
6use std::sync::Arc;
7
8/// Base pool information shared by all pool types. Contains the essential addresses and
9/// identifiers that every pool implementation requires. Protocol-specific pool structs will embed
10/// this as an `info` field.
11#[derive(Debug)]
12pub struct Pool {
13 pub pool_address: Pubkey,
14 pub token_a_address: Pubkey,
15 pub token_b_address: Pubkey,
16 pub token_a_vault_address: Pubkey,
17 pub token_b_vault_address: Pubkey,
18 pub pool_type: Pools,
19}
20
21/// Trait for all pool types, providing a unified interface for DEX pools. All pools implement this
22/// trait to provide common functionality like price queries, fee calculations, and reserve
23/// lookups.
24pub trait PoolTrait: Any + Send + Sync {
25 /// Get the pool's on-chain address
26 fn pool_address(&self) -> &Pubkey;
27 /// Get the address of token A
28 fn token_a_address(&self) -> &Pubkey;
29 /// Get the address of token B
30 fn token_b_address(&self) -> &Pubkey;
31 /// Get the vault address for token A
32 fn token_a_vault_address(&self) -> &Pubkey;
33 /// Get the vault address for token B
34 fn token_b_vault_address(&self) -> &Pubkey;
35 /// Get the pool type enum variant
36 fn pool_type(&self) -> &Pools;
37
38 /// Get the total swap fee in lamports (10^9 lamports = 1 SOL)
39 fn total_swap_fee_lp(&self, central_context: &Arc<CentralContext>) -> u64;
40
41 /// Get a reference to the pool as `Any` for type downcasting
42 fn as_any(&self) -> &dyn Any;
43 /// Get a mutable reference to the pool as `Any` for type downcasting
44 fn as_any_mut(&mut self) -> &mut dyn Any;
45
46 /// Calculate the price of token A in terms of token B. Fx ticker equivalent: B/A. Returns how
47 /// many units of token A are needed to buy 1 unit of token B, in lamports. For AMMs, typically
48 /// calculated as: (A reserves * LAMPORTS_PER_SOL) / B reserves
49 fn price_a_over_b_lp(&self) -> u128;
50
51 /// Calculate the price of token B in terms of token A. Fx ticker equivalent: A/B. Returns how
52 /// many units of token A are needed to buy 1 unit of token B, in lamports. For AMMs, typically
53 /// calculated as: (B reserves * LAMPORTS_PER_SOL) / A reserves. Inverse of `price_a_over_b_lp`.
54 fn price_b_over_a_lp(&self) -> u128;
55
56 /// Fetch and update pool state from JSON RPC and immediately overrides the in-memory pool state.
57 /// Should not be used in production in favor of using gRPC streams.
58 fn fetch_market_state_from_rpc(&mut self, central_context: &Arc<CentralContext>);
59
60 /// Get the actual amount of token A in the pool, in token units. This is calculated dynamically
61 /// because some protocols (like Meteora) derive real token balances from LP token balances
62 /// rather than storing them directly in the pool account, and other protocols require excluding
63 /// collected fees from raw reserves.
64 fn token_a_amount_units(&self) -> u64;
65
66 /// Get the actual amount of token B in the pool, in token units. See `token_a_amount_units`
67 /// for details on why this is calculated dynamically.
68 fn token_b_amount_units(&self) -> u64;
69
70 /// Get directional swap fees as fractions for a given swap direction
71 ///
72 /// Returns `(fee_a_fraction, fee_b_fraction)` where each value is between 0.0 and 1.0
73 /// (e.g., 0.003 = 0.3%). The fees may differ based on swap direction for protocols
74 /// with asymmetric fee structures.
75 /// * `central_context` with updated current slot value - Needed for time-based fee calculations
76 /// in Meteora DAMMv2 and DBC
77 fn directional_fees(
78 &self,
79 direction: SwapDirection,
80 central_context: &Arc<CentralContext>,
81 ) -> (f64, f64);
82}