copy_trading/position/
start_hold_time_task.rs

1use crate::types::position::Position;
2use crate::types::position_close_reason::PositionCloseReason;
3use crate::types::position_manager::PositionManager;
4use crate::types::position_status::PositionStatus;
5use solana_sdk::pubkey::Pubkey;
6use std::sync::{Arc, Mutex};
7use tokio::time::{Duration, sleep};
8
9impl Position {
10  /// Start an async task that will close the position after the configured hold time expires.
11  /// Waits for the specified hold time duration, then closes the position if it's still open.
12  pub fn start_hold_time_task(
13    position: Arc<Mutex<Position>>,
14    hold_time_ms: u32,
15    token_address: Pubkey,
16    position_manager: Arc<PositionManager>,
17  ) {
18    tokio::spawn(async move {
19      sleep(Duration::from_millis(hold_time_ms as u64)).await;
20
21      // Check if position is still open before closing
22      let should_close = {
23        let position_guard = position.lock().unwrap();
24        // Open or opening because this runs before tx is confimred
25        if !(position_guard.status == PositionStatus::Open
26          || position_guard.status == PositionStatus::Opening)
27        {
28          println!(
29            "POSITION: Hold time expired for token: {} but position is already {:?}",
30            token_address.to_string(),
31            position_guard.status
32          );
33          false
34        } else {
35          true
36        }
37      };
38
39      if !should_close {
40        return;
41      }
42
43      println!(
44        "POSITION: Start close, token: {}. Reason: Hold time",
45        token_address.to_string()
46      );
47
48      Position::close_position(position, PositionCloseReason::HoldTime, position_manager);
49    });
50  }
51}