Skip to main content

nautilus_common/defi/
cache.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! DeFi-specific cache functionality.
17
18use ahash::AHashMap;
19use nautilus_model::{
20    defi::{Pool, PoolProfiler},
21    identifiers::{InstrumentId, Venue},
22};
23
24use crate::cache::Cache;
25
26/// DeFi-specific cache state.
27#[derive(Clone, Debug, Default)]
28pub(crate) struct DefiCache {
29    pub(crate) pools: AHashMap<InstrumentId, Pool>,
30    pub(crate) pool_profilers: AHashMap<InstrumentId, PoolProfiler>,
31}
32
33impl Cache {
34    /// Adds a `Pool` to the cache.
35    ///
36    /// This function does not return errors; the result type matches the other add methods.
37    #[allow(
38        clippy::missing_errors_doc,
39        reason = "this method only inserts into the in-memory cache"
40    )]
41    pub fn add_pool(&mut self, pool: Pool) -> anyhow::Result<()> {
42        log::debug!("Adding `Pool` {}", pool.instrument_id);
43
44        self.defi.pools.insert(pool.instrument_id, pool);
45        Ok(())
46    }
47
48    /// Adds a `PoolProfiler` to the cache.
49    ///
50    /// This function does not return errors; the result type matches the other add methods.
51    #[allow(
52        clippy::missing_errors_doc,
53        reason = "this method only inserts into the in-memory cache"
54    )]
55    pub fn add_pool_profiler(&mut self, pool_profiler: PoolProfiler) -> anyhow::Result<()> {
56        let instrument_id = pool_profiler.pool.instrument_id;
57        log::debug!("Adding `PoolProfiler` {instrument_id}");
58
59        self.defi
60            .pool_profilers
61            .insert(instrument_id, pool_profiler);
62        Ok(())
63    }
64
65    /// Gets a reference to the pool for the `instrument_id`.
66    #[must_use]
67    pub fn pool(&self, instrument_id: &InstrumentId) -> Option<&Pool> {
68        self.defi.pools.get(instrument_id)
69    }
70
71    /// Gets a mutable reference to the pool for the `instrument_id`.
72    #[must_use]
73    pub fn pool_mut(&mut self, instrument_id: &InstrumentId) -> Option<&mut Pool> {
74        self.defi.pools.get_mut(instrument_id)
75    }
76
77    /// Returns the instrument IDs of all pools in the cache, optionally filtered by `venue`.
78    #[must_use]
79    pub fn pool_ids(&self, venue: Option<&Venue>) -> Vec<InstrumentId> {
80        match venue {
81            Some(v) => self
82                .defi
83                .pools
84                .keys()
85                .filter(|id| &id.venue == v)
86                .copied()
87                .collect(),
88            None => self.defi.pools.keys().copied().collect(),
89        }
90    }
91
92    /// Returns references to all pools in the cache, optionally filtered by `venue`.
93    #[must_use]
94    pub fn pools(&self, venue: Option<&Venue>) -> Vec<&Pool> {
95        match venue {
96            Some(v) => self
97                .defi
98                .pools
99                .values()
100                .filter(|p| &p.instrument_id.venue == v)
101                .collect(),
102            None => self.defi.pools.values().collect(),
103        }
104    }
105
106    /// Gets a reference to the pool profiler for the `instrument_id`.
107    #[must_use]
108    pub fn pool_profiler(&self, instrument_id: &InstrumentId) -> Option<&PoolProfiler> {
109        self.defi.pool_profilers.get(instrument_id)
110    }
111
112    /// Gets a mutable reference to the pool profiler for the `instrument_id`.
113    #[must_use]
114    pub fn pool_profiler_mut(&mut self, instrument_id: &InstrumentId) -> Option<&mut PoolProfiler> {
115        self.defi.pool_profilers.get_mut(instrument_id)
116    }
117
118    /// Returns the instrument IDs of all pool profilers in the cache, optionally filtered by `venue`.
119    #[must_use]
120    pub fn pool_profiler_ids(&self, venue: Option<&Venue>) -> Vec<InstrumentId> {
121        match venue {
122            Some(v) => self
123                .defi
124                .pool_profilers
125                .keys()
126                .filter(|id| &id.venue == v)
127                .copied()
128                .collect(),
129            None => self.defi.pool_profilers.keys().copied().collect(),
130        }
131    }
132
133    /// Returns references to all pool profilers in the cache, optionally filtered by `venue`.
134    #[must_use]
135    pub fn pool_profilers(&self, venue: Option<&Venue>) -> Vec<&PoolProfiler> {
136        match venue {
137            Some(v) => self
138                .defi
139                .pool_profilers
140                .values()
141                .filter(|p| &p.pool.instrument_id.venue == v)
142                .collect(),
143            None => self.defi.pool_profilers.values().collect(),
144        }
145    }
146}