copy_trading/position/
create_checked.rs1use crate::types::position::Position;
18use crate::types::position_close_reason::PositionCloseReason;
19use crate::types::position_config::PositionConfig;
20use crate::types::position_manager::PositionManager;
21use crate::types::position_status::PositionStatus;
22use rand::Rng;
23use solana_central::Pools;
24use solana_central::SwapTx;
25use solana_central::is_legit_token;
26use solana_sdk::native_token::LAMPORTS_PER_SOL;
27use solana_sdk::pubkey::Pubkey;
28use std::collections::HashMap;
29use std::sync::{Arc, Mutex};
30
31impl Position {
32 pub fn create_checked(
37 token_address: Pubkey,
38 sol_token_a: bool,
39 swap_tx: &SwapTx,
40 mut config: PositionConfig,
41 open_positions: &HashMap<Pubkey, Arc<Mutex<Position>>>,
42 position_manager: &Arc<PositionManager>,
43 ) -> Option<Position> {
44 if open_positions.contains_key(&swap_tx.market_address) {
46 return None;
47 }
48
49 if !is_legit_token(&token_address, &position_manager.central_context) {
51 println!(
52 "Not opening position, token not legit: {}, wallet: {:?}, signature: {}",
53 token_address, swap_tx.signers, swap_tx.signature
54 );
55 return None;
56 }
57
58 let pool = position_manager.central_context.pools_map.read().unwrap();
59 let pool = pool.get(&swap_tx.market_address).unwrap();
60
61 let (pool_type, sol_liquidity_lp) = {
63 let pool = pool.read().unwrap();
64 if sol_token_a {
65 (*pool.pool_type(), pool.token_a_amount_units())
66 } else {
67 (*pool.pool_type(), pool.token_b_amount_units())
68 }
69 };
70 if pool_type == Pools::MeteoraDammV2 || pool_type == Pools::MeteoraDbc {
71 return None;
72 }
73 let too_low_liquidity =
76 if pool_type == Pools::PfBondingCurve || pool_type == Pools::RaydiumLaunchpad {
77 sol_liquidity_lp < 15 * LAMPORTS_PER_SOL
78 } else {
79 sol_liquidity_lp < 75 * LAMPORTS_PER_SOL
80 };
81 if too_low_liquidity {
82 println!(
83 "Not opening position, too low liquidity: token: {}, wallet: {:?}, signature: {}, liquidity observed: {:?}",
84 token_address, swap_tx.signers, swap_tx.signature, sol_liquidity_lp
85 );
86 return None;
87 }
88
89 let buy_amount_lp = {
93 if config.buy_amount_lp > swap_tx.swapped_amount_in {
94 rand::rng().random_range(85..100) * swap_tx.swapped_amount_in / 100
95 } else {
96 config.buy_amount_lp
97 }
98 };
99 config.buy_amount_lp = buy_amount_lp;
100
101 println!(
102 "POSITION: Opening, token: {}, wallet: {:?}, tx: {}",
103 token_address, swap_tx.signers, swap_tx.signature
104 );
105
106 Some(Self {
107 config,
108 token_address,
109 pool: pool.clone(),
110 status: PositionStatus::Created,
111 migrated: false,
112 pool_address: swap_tx.market_address,
113 open_time: 0,
114 buy_confirmation_time: 0,
115 sell_confirmation_time: 0,
116 close_time: 0,
117 entry_price_lp: 0,
118 exit_price_lp: 0,
119 stop_loss_price_lp: 0,
120 wallet: position_manager.wallet.clone(),
121 sol_token_a,
122 lowest_acceptable_price_lp: 0,
123 tokens_purchased: 0,
124 close_reason: PositionCloseReason::HoldTime,
125 sell_amount_lp: 0,
126 })
127 }
128}