feat: major refactor with calculation utilities and instruction optimization
- Add comprehensive calculation utilities for all protocols (bonk, pumpfun, pumpswap, raydium) - Refactor instruction modules to reduce code complexity and improve maintainability - Optimize trading parameters structure and enhance common utilities - Separate calculation logic from trading modules for better code organization - Update dependencies and module exports
This commit is contained in:
@@ -2,7 +2,7 @@ use crate::{
|
||||
common::SolanaRpcClient,
|
||||
constants::{
|
||||
self,
|
||||
raydium_cpmm::accounts::{self, WSOL_TOKEN_ACCOUNT},
|
||||
raydium_cpmm::accounts::{self},
|
||||
},
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
@@ -52,94 +52,6 @@ pub fn get_observation_state_pda(pool_state: &Pubkey) -> Option<Pubkey> {
|
||||
pda.map(|pubkey| pubkey.0)
|
||||
}
|
||||
|
||||
pub async fn get_buy_token_amount(
|
||||
rpc: &SolanaRpcClient,
|
||||
pool_state: &Pubkey,
|
||||
sol_amount: u64,
|
||||
) -> Result<u64, anyhow::Error> {
|
||||
let pool = fetch_pool_state(rpc, pool_state).await?;
|
||||
let is_token0_input = if pool.token0_mint == WSOL_TOKEN_ACCOUNT { true } else { false };
|
||||
let (token0_balance, token1_balance) =
|
||||
get_pool_token_balances(rpc, pool_state, &pool.token0_mint, &pool.token1_mint).await?;
|
||||
|
||||
// 使用恒定乘积公式计算
|
||||
|
||||
let (reserve_in, reserve_out) = if is_token0_input {
|
||||
(token0_balance, token1_balance)
|
||||
} else {
|
||||
(token1_balance, token0_balance)
|
||||
};
|
||||
|
||||
if reserve_in == 0 || reserve_out == 0 {
|
||||
return Err(anyhow!("池子储备金为零,无法进行交换"));
|
||||
}
|
||||
|
||||
// 使用 u128 防止溢出
|
||||
let amount_in_128 = sol_amount as u128;
|
||||
let reserve_in_128 = reserve_in as u128;
|
||||
let reserve_out_128 = reserve_out as u128;
|
||||
|
||||
// 恒定乘积公式: amount_out = (amount_in * reserve_out) / (reserve_in + amount_in)
|
||||
let numerator = amount_in_128 * reserve_out_128;
|
||||
let denominator = reserve_in_128 + amount_in_128;
|
||||
|
||||
if denominator == 0 {
|
||||
return Err(anyhow!("分母为零,计算错误"));
|
||||
}
|
||||
|
||||
let amount_out = numerator / denominator;
|
||||
|
||||
// 检查是否超出储备金
|
||||
if amount_out >= reserve_out_128 {
|
||||
return Err(anyhow!("输出数量超过池子储备金"));
|
||||
}
|
||||
|
||||
Ok(amount_out as u64)
|
||||
}
|
||||
|
||||
pub async fn get_sell_sol_amount(
|
||||
rpc: &SolanaRpcClient,
|
||||
pool_state: &Pubkey,
|
||||
token_amount: u64,
|
||||
) -> Result<u64, anyhow::Error> {
|
||||
let pool = fetch_pool_state(rpc, pool_state).await?;
|
||||
let is_token0_sol = if pool.token0_mint == WSOL_TOKEN_ACCOUNT { true } else { false };
|
||||
let (token0_balance, token1_balance) =
|
||||
get_pool_token_balances(rpc, pool_state, &pool.token0_mint, &pool.token1_mint).await?;
|
||||
|
||||
let (reserve_in, reserve_out) = if is_token0_sol {
|
||||
(token1_balance, token0_balance)
|
||||
} else {
|
||||
(token0_balance, token1_balance)
|
||||
};
|
||||
|
||||
if reserve_in == 0 || reserve_out == 0 {
|
||||
return Err(anyhow!("池子储备金为零,无法进行交换"));
|
||||
}
|
||||
|
||||
// 使用 u128 防止溢出
|
||||
let amount_in_128 = token_amount as u128;
|
||||
let reserve_in_128 = reserve_in as u128;
|
||||
let reserve_out_128 = reserve_out as u128;
|
||||
|
||||
// 恒定乘积公式: amount_out = (amount_in * reserve_out) / (reserve_in + amount_in)
|
||||
let numerator = amount_in_128 * reserve_out_128;
|
||||
let denominator = reserve_in_128 + amount_in_128;
|
||||
|
||||
if denominator == 0 {
|
||||
return Err(anyhow!("分母为零,计算错误"));
|
||||
}
|
||||
|
||||
let amount_out = numerator / denominator;
|
||||
|
||||
// 检查是否超出储备金
|
||||
if amount_out >= reserve_out_128 {
|
||||
return Err(anyhow!("输出数量超过池子储备金"));
|
||||
}
|
||||
|
||||
Ok(amount_out as u64)
|
||||
}
|
||||
|
||||
/// 获取池子中两个代币的余额
|
||||
///
|
||||
/// # 返回值
|
||||
|
||||
Reference in New Issue
Block a user