1use nautilus_common::{
22 clients::log_command_error,
23 messages::defi::{
24 DefiRequestCommand, DefiSubscribeCommand, DefiUnsubscribeCommand, RequestPoolSnapshot,
25 SubscribeBlocks, SubscribePool, SubscribePoolFeeCollects, SubscribePoolFlashEvents,
26 SubscribePoolLiquidityUpdates, SubscribePoolSwaps, UnsubscribeBlocks, UnsubscribePool,
27 UnsubscribePoolFeeCollects, UnsubscribePoolFlashEvents, UnsubscribePoolLiquidityUpdates,
28 UnsubscribePoolSwaps,
29 },
30};
31
32use crate::{
33 client::DataClientAdapter,
34 subscription::{DefiSubscriptionKey, SubscriptionRelease},
35};
36
37impl DataClientAdapter {
38 #[inline]
39 pub fn execute_defi_subscribe(&mut self, cmd: DefiSubscribeCommand) {
40 self.execute_defi_subscribe_with_retained(cmd, false);
41 }
42
43 pub(crate) fn execute_defi_subscribe_with_retained(
44 &mut self,
45 cmd: DefiSubscribeCommand,
46 retain_on_failure: bool,
47 ) {
48 #[rustfmt::skip]
49 let key = match &cmd {
50 DefiSubscribeCommand::Blocks(command) => DefiSubscriptionKey::Blocks(command.chain),
51 DefiSubscribeCommand::Pool(command) => DefiSubscriptionKey::Pool(command.instrument_id),
52 DefiSubscribeCommand::PoolSwaps(command) => DefiSubscriptionKey::PoolSwaps(command.instrument_id),
53 DefiSubscribeCommand::PoolLiquidityUpdates(command) => DefiSubscriptionKey::PoolLiquidityUpdates(command.instrument_id),
54 DefiSubscribeCommand::PoolFeeCollects(command) => DefiSubscriptionKey::PoolFeeCollects(command.instrument_id),
55 DefiSubscribeCommand::PoolFlashEvents(command) => DefiSubscriptionKey::PoolFlashEvents(command.instrument_id),
56 };
57 #[rustfmt::skip]
58 let active = match &key {
59 DefiSubscriptionKey::Blocks(chain) => self.subscriptions_blocks.contains(chain),
60 DefiSubscriptionKey::Pool(id) => self.subscriptions_pools.contains(id),
61 DefiSubscriptionKey::PoolSwaps(id) => self.subscriptions_pool_swaps.contains(id),
62 DefiSubscriptionKey::PoolLiquidityUpdates(id) => self.subscriptions_pool_liquidity_updates.contains(id),
63 DefiSubscriptionKey::PoolFeeCollects(id) => self.subscriptions_pool_fee_collects.contains(id),
64 DefiSubscriptionKey::PoolFlashEvents(id) => self.subscriptions_pool_flash.contains(id),
65 };
66
67 if active {
68 self.subscriptions_active_defi
69 .retain(key, cmd.command_id(), cmd);
70 return;
71 }
72
73 let retained = cmd.clone();
74 let cmd_debug = format!("{cmd:?}");
75 #[rustfmt::skip]
76 let result = match cmd {
77 DefiSubscribeCommand::Blocks(cmd) => self.subscribe_blocks(cmd),
78 DefiSubscribeCommand::Pool(cmd) => self.subscribe_pool(cmd),
79 DefiSubscribeCommand::PoolSwaps(cmd) => self.subscribe_pool_swaps(cmd),
80 DefiSubscribeCommand::PoolLiquidityUpdates(cmd) => self.subscribe_pool_liquidity_updates(cmd),
81 DefiSubscribeCommand::PoolFeeCollects(cmd) => self.subscribe_pool_fee_collects(cmd),
82 DefiSubscribeCommand::PoolFlashEvents(cmd) => self.subscribe_pool_flash_events(cmd),
83 };
84
85 if let Err(e) = result {
86 if retain_on_failure {
87 self.subscriptions_active_defi
88 .retain(key, retained.command_id(), retained);
89 }
90
91 log_command_error(&cmd_debug, &e);
92 return;
93 }
94
95 if let Some(subscription) = self.subscriptions_active_defi.get_mut(&key) {
96 subscription.command = retained.clone();
97 }
98 self.subscriptions_active_defi
99 .retain(key, retained.command_id(), retained);
100 }
101
102 #[inline]
103 pub fn execute_defi_unsubscribe(&mut self, cmd: &DefiUnsubscribeCommand) {
104 #[rustfmt::skip]
105 let key = match cmd {
106 DefiUnsubscribeCommand::Blocks(command) => DefiSubscriptionKey::Blocks(command.chain),
107 DefiUnsubscribeCommand::Pool(command) => DefiSubscriptionKey::Pool(command.instrument_id),
108 DefiUnsubscribeCommand::PoolSwaps(command) => DefiSubscriptionKey::PoolSwaps(command.instrument_id),
109 DefiUnsubscribeCommand::PoolLiquidityUpdates(command) => DefiSubscriptionKey::PoolLiquidityUpdates(command.instrument_id),
110 DefiUnsubscribeCommand::PoolFeeCollects(command) => DefiSubscriptionKey::PoolFeeCollects(command.instrument_id),
111 DefiUnsubscribeCommand::PoolFlashEvents(command) => DefiSubscriptionKey::PoolFlashEvents(command.instrument_id),
112 };
113 let command = match self.subscriptions_active_defi.release(&key) {
114 SubscriptionRelease::Retained => return,
115 SubscriptionRelease::Final(subscribe) => {
116 subscribe.into_unsubscribe(cmd.command_id(), cmd.ts_init())
117 }
118 SubscriptionRelease::Untracked => cmd.clone(),
119 };
120
121 #[rustfmt::skip]
122 let unsub_result = match &command {
123 DefiUnsubscribeCommand::Blocks(cmd) => self.unsubscribe_blocks(cmd),
124 DefiUnsubscribeCommand::Pool(cmd) => self.unsubscribe_pool(cmd),
125 DefiUnsubscribeCommand::PoolSwaps(cmd) => self.unsubscribe_pool_swaps(cmd),
126 DefiUnsubscribeCommand::PoolLiquidityUpdates(cmd) => self.unsubscribe_pool_liquidity_updates(cmd),
127 DefiUnsubscribeCommand::PoolFeeCollects(cmd) => self.unsubscribe_pool_fee_collects(cmd),
128 DefiUnsubscribeCommand::PoolFlashEvents(cmd) => self.unsubscribe_pool_flash_events(cmd),
129 };
130
131 if let Err(e) = unsub_result {
132 log_command_error(&command, &e);
133 } else {
134 self.subscriptions_active_defi.remove(&key);
135 }
136 }
137
138 #[inline]
144 pub fn execute_defi_request(&self, cmd: DefiRequestCommand) -> anyhow::Result<()> {
145 match cmd {
146 DefiRequestCommand::PoolSnapshot(cmd) => self.request_pool_snapshot(cmd),
147 }
148 }
149
150 fn subscribe_blocks(&mut self, cmd: SubscribeBlocks) -> anyhow::Result<()> {
156 Self::execute_tracked_subscribe(
157 self.client.as_mut(),
158 &mut self.subscriptions_blocks,
159 cmd.chain,
160 "blocks",
161 |client| client.subscribe_blocks(cmd),
162 )
163 }
164
165 fn unsubscribe_blocks(&mut self, cmd: &UnsubscribeBlocks) -> anyhow::Result<()> {
171 Self::execute_tracked_unsubscribe(
172 self.client.as_mut(),
173 &mut self.subscriptions_blocks,
174 &cmd.chain,
175 "blocks",
176 |client| client.unsubscribe_blocks(cmd),
177 )
178 }
179
180 fn subscribe_pool(&mut self, cmd: SubscribePool) -> anyhow::Result<()> {
186 Self::execute_tracked_subscribe(
187 self.client.as_mut(),
188 &mut self.subscriptions_pools,
189 cmd.instrument_id,
190 "pool",
191 |client| client.subscribe_pool(cmd),
192 )
193 }
194
195 fn subscribe_pool_swaps(&mut self, cmd: SubscribePoolSwaps) -> anyhow::Result<()> {
201 Self::execute_tracked_subscribe(
202 self.client.as_mut(),
203 &mut self.subscriptions_pool_swaps,
204 cmd.instrument_id,
205 "pool swaps",
206 |client| client.subscribe_pool_swaps(cmd),
207 )
208 }
209
210 fn subscribe_pool_liquidity_updates(
216 &mut self,
217 cmd: SubscribePoolLiquidityUpdates,
218 ) -> anyhow::Result<()> {
219 Self::execute_tracked_subscribe(
220 self.client.as_mut(),
221 &mut self.subscriptions_pool_liquidity_updates,
222 cmd.instrument_id,
223 "pool liquidity updates",
224 |client| client.subscribe_pool_liquidity_updates(cmd),
225 )
226 }
227
228 fn subscribe_pool_fee_collects(&mut self, cmd: SubscribePoolFeeCollects) -> anyhow::Result<()> {
234 Self::execute_tracked_subscribe(
235 self.client.as_mut(),
236 &mut self.subscriptions_pool_fee_collects,
237 cmd.instrument_id,
238 "pool fee collects",
239 |client| client.subscribe_pool_fee_collects(cmd),
240 )
241 }
242
243 fn subscribe_pool_flash_events(&mut self, cmd: SubscribePoolFlashEvents) -> anyhow::Result<()> {
249 Self::execute_tracked_subscribe(
250 self.client.as_mut(),
251 &mut self.subscriptions_pool_flash,
252 cmd.instrument_id,
253 "pool flash events",
254 |client| client.subscribe_pool_flash_events(cmd),
255 )
256 }
257
258 fn unsubscribe_pool(&mut self, cmd: &UnsubscribePool) -> anyhow::Result<()> {
264 Self::execute_tracked_unsubscribe(
265 self.client.as_mut(),
266 &mut self.subscriptions_pools,
267 &cmd.instrument_id,
268 "pool",
269 |client| client.unsubscribe_pool(cmd),
270 )
271 }
272
273 fn unsubscribe_pool_swaps(&mut self, cmd: &UnsubscribePoolSwaps) -> anyhow::Result<()> {
279 Self::execute_tracked_unsubscribe(
280 self.client.as_mut(),
281 &mut self.subscriptions_pool_swaps,
282 &cmd.instrument_id,
283 "pool swaps",
284 |client| client.unsubscribe_pool_swaps(cmd),
285 )
286 }
287
288 fn unsubscribe_pool_liquidity_updates(
294 &mut self,
295 cmd: &UnsubscribePoolLiquidityUpdates,
296 ) -> anyhow::Result<()> {
297 Self::execute_tracked_unsubscribe(
298 self.client.as_mut(),
299 &mut self.subscriptions_pool_liquidity_updates,
300 &cmd.instrument_id,
301 "pool liquidity updates",
302 |client| client.unsubscribe_pool_liquidity_updates(cmd),
303 )
304 }
305
306 fn unsubscribe_pool_fee_collects(
312 &mut self,
313 cmd: &UnsubscribePoolFeeCollects,
314 ) -> anyhow::Result<()> {
315 Self::execute_tracked_unsubscribe(
316 self.client.as_mut(),
317 &mut self.subscriptions_pool_fee_collects,
318 &cmd.instrument_id,
319 "pool fee collects",
320 |client| client.unsubscribe_pool_fee_collects(cmd),
321 )
322 }
323
324 fn unsubscribe_pool_flash_events(
330 &mut self,
331 cmd: &UnsubscribePoolFlashEvents,
332 ) -> anyhow::Result<()> {
333 Self::execute_tracked_unsubscribe(
334 self.client.as_mut(),
335 &mut self.subscriptions_pool_flash,
336 &cmd.instrument_id,
337 "pool flash events",
338 |client| client.unsubscribe_pool_flash_events(cmd),
339 )
340 }
341
342 pub fn request_pool_snapshot(&self, req: RequestPoolSnapshot) -> anyhow::Result<()> {
348 self.client.request_pool_snapshot(req)
349 }
350}