copy_trading/position/
start.rs

1use crate::types::position::Position;
2use crate::types::position_manager::PositionManager;
3use crate::types::position_status::PositionStatus;
4use solana_central::SwapDirection;
5use solana_exec::SwapConfig;
6use solana_exec::create_tx_from_swap_configs;
7// use solana_client::rpc_config::RpcSendTransactionConfig;
8use solana_sdk::signature::Signer;
9use std::sync::{Arc, Mutex};
10use std::time::SystemTime;
11
12impl Position {
13  /// Start a position by creating and sending a buy transaction to the blockchain. Validates 
14  /// position state, creates a buy swap transaction, sends it via Jito bundles, and sets up a
15  /// timeout to close the position if confirmation doesn't arrive within 5 seconds.
16  pub fn start(position: Arc<Mutex<Position>>, position_manager: Arc<PositionManager>) {
17    let token_address;
18    let market_address;
19    let tx = {
20      let mut position = position.lock().unwrap();
21      if !(position.status == PositionStatus::Created || position.status == PositionStatus::Closed)
22      {
23        // Add the unix timestamp to this log message
24        println!(
25          "POSITION: Position is not in a valid state to start. The token address is: {}. The timestamp is: {:?}",
26          position.token_address,
27          SystemTime::now()
28        );
29        return;
30      }
31
32      // Update status to Opening
33      position.status = PositionStatus::Opening;
34
35      // Figure out which way we need to swap in this liquidity pool
36      let buy_direction;
37      if position.sol_token_a {
38        buy_direction = SwapDirection::AToB;
39      } else {
40        buy_direction = SwapDirection::BToA;
41      }
42
43      let buy_swap_config = SwapConfig {
44        pool: position.pool.clone(),
45        direction: buy_direction,
46        amount_in: position.config.buy_amount_lp,
47        slippage_lp: position.config.slippage_lps,
48        open_token_account: true,
49        close_token_account: false,
50        wallet: position.wallet.pubkey(),
51      };
52      token_address = position.token_address;
53      market_address = position.pool_address;
54      create_tx_from_swap_configs(
55        &vec![buy_swap_config],
56        &position_manager.central_context,
57        true,
58        position.config.jito_tip_buy_lp,
59        &position.wallet,
60      )
61    };
62
63    // Do all async operations on a new thread
64    let e = position_manager.execution_context.clone();
65    tokio::spawn(async move {
66      e.jito_be_client.send_bundle(vec![tx]).await.unwrap();
67      // position_manager
68      //   .central_context
69      //   .json_rpc_client
70      //   .send_transaction_with_config(
71      //     &tx,
72      //     RpcSendTransactionConfig {
73      //       skip_preflight: true,
74      //       preflight_commitment: Some(solana_sdk::commitment_config::CommitmentLevel::Confirmed),
75      //       ..RpcSendTransactionConfig::default()
76      //     },
77      //   )
78      //   .unwrap();
79
80    //   println!(
81    //     "POSITION: Buy transaction sent to Jito for token: {}. Starting hold.",
82    //     token_address
83    //   );
84      // Sleep for 5 seconds
85      tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
86      /*
87      Check position status. If it's still opening, then close it. It will still be opening if the
88      buy never landed and was not confirmed on chain and we didn't get a reading of what price we
89      entered at and etc so we have nothing to base stop loss calculations on etc.
90      */
91      if position.lock().unwrap().status != PositionStatus::Opening {
92        return;
93      }
94      // Remove this position from the position manager
95      position_manager
96        .open_positions
97        .write()
98        .unwrap()
99        .remove(&market_address);
100      println!(
101        "POSITION: Position closed due to no buy tx confirmation after 5 seconds. Token adddress: {}",
102        token_address
103      );
104    });
105  }
106}