diff --git a/examples/rpc.rs b/examples/rpc.rs index 89b4dbd..26a307f 100644 --- a/examples/rpc.rs +++ b/examples/rpc.rs @@ -4,7 +4,7 @@ use amm_cli::load_amm_keys; use anyhow::{Context, Result}; use common::common_utils; use futures_util::{SinkExt, StreamExt}; -use raytx::{get_rpc_client_blocking, logger, pump::PUMP_PROGRAM}; +use raytx::{get_rpc_client_blocking, logger, pump::PUMP_PROGRAM, raydium::get_pool_state_by_mint}; use solana_client::rpc_client::GetConfirmedSignaturesForAddress2Config; use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey}; use tokio_tungstenite::{connect_async, tungstenite::Message}; @@ -16,14 +16,26 @@ async fn main() -> Result<()> { // get_signatures().await?; // connect_websocket().await?; - get_amm_info().await?; + // get_amm_info().await?; + get_amm_info_by_mint().await?; + Ok(()) +} + +pub async fn get_amm_info_by_mint() -> Result<()> { + let client = get_rpc_client_blocking()?; + let mint = "DrEMQaQqGN2fQwiUgJi6NStLtmni8m3uSkUP678Apump"; + + let pool_state = get_pool_state_by_mint(client, mint).await?; + + println!("pool_state: {:#?}", pool_state); + Ok(()) } pub async fn get_amm_info() -> Result<()> { let client = get_rpc_client_blocking()?; // let amm_pool_id = Pubkey::from_str("3vehHGc8J9doSo6gJoWYG23JG54hc2i7wjdFReX3Rcah")?; - let amm_pool_id = Pubkey::from_str("5WGx6mE9Xww3ocYzSenGVQMJLCVVwK7ePnYV6cXcpJtK")?; + let amm_pool_id = Pubkey::from_str("7Sp76Pv48RaL4he2BfGUhvjqCtvjjfTSnXDXNvk845yL")?; let pool_state = common::rpc::get_account::(&client, &amm_pool_id)?.unwrap(); diff --git a/src/api.rs b/src/api.rs index cda138c..0acceff 100644 --- a/src/api.rs +++ b/src/api.rs @@ -129,11 +129,10 @@ pub async fn coins(State(state): State, Path(mint): Path) -> i return api_error(&err.to_string()); } }; - if pump_info.raydium_pool.is_some() { - let pool_id = pump_info.raydium_pool.clone().unwrap(); + if pump_info.complete { let mut swapx = Raydium::new(client, wallet); swapx.with_blocking_client(client_blocking); - match swapx.get_pool_price(&pool_id).await { + match swapx.get_pool_price(None, Some(mint.as_str())).await { Ok(data) => { pump_info.raydium_info = Some(RaydiumInfo { base: data.0, diff --git a/src/pool.rs b/src/pool.rs index 69d081e..40076b2 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -1,16 +1,16 @@ -use std::str::FromStr; - use anyhow::{Context, Result}; use common::common_utils; -use solana_sdk::pubkey::Pubkey; use spl_token_2022::amount_to_ui_amount; use tracing::{debug, warn}; -use crate::{helper::get_solana_price, raydium::Raydium}; +use crate::{ + helper::get_solana_price, + raydium::{get_pool_state, Raydium}, +}; impl Raydium { pub async fn get_pool(&self, pool_id: &str) -> Result<(f64, f64, f64, f64, f64)> { - let (base, quote, price) = self.get_pool_price(pool_id).await?; + let (base, quote, price) = self.get_pool_price(Some(pool_id), None).await?; let sol_price = get_solana_price() .await .inspect_err(|err| warn!("failed get solana price: {}", err))?; @@ -21,17 +21,17 @@ impl Raydium { Ok((base, quote, price, usd_price, sol_price)) } - pub async fn get_pool_price(&self, pool_id: &str) -> Result<(f64, f64, f64)> { - let amm_pool_id = - Pubkey::from_str(pool_id).inspect_err(|err| warn!("failed parse pool_id: {}", err))?; + pub async fn get_pool_price( + &self, + pool_id: Option<&str>, + mint: Option<&str>, + ) -> Result<(f64, f64, f64)> { let client = self .client_blocking .clone() .context("failed to get rpc client")?; - let pool_state = - common::rpc::get_account::(&client, &amm_pool_id)? - .unwrap(); + let (amm_pool_id, pool_state) = get_pool_state(client.clone(), pool_id, mint).await?; // debug!("pool_state : {:#?}", pool_state); diff --git a/src/raydium.rs b/src/raydium.rs index bd2f15f..0b6bef9 100644 --- a/src/raydium.rs +++ b/src/raydium.rs @@ -422,36 +422,63 @@ pub async fn get_pool_state_by_mint( mint: &str, ) -> Result<(Pubkey, AmmInfo)> { debug!("finding pool state by mint: {}", mint); - let pc_mint = Some(spl_token::native_mint::ID); - let coin_mint = Pubkey::from_str(mint).ok(); - // fetch pool by filters + // (pc_mint, coin_mint) + let pairs = vec![ + // pump pool + ( + Some(spl_token::native_mint::ID), + Pubkey::from_str(mint).ok(), + ), + // general pool + ( + Pubkey::from_str(mint).ok(), + Some(spl_token::native_mint::ID), + ), + ]; + let pool_len = core::mem::size_of::() as u64; - let filters = match (coin_mint, pc_mint) { - (None, None) => Some(vec![RpcFilterType::DataSize(pool_len)]), - (Some(coin_mint), None) => Some(vec![ - RpcFilterType::Memcmp(Memcmp::new_base58_encoded(400, &coin_mint.to_bytes())), - RpcFilterType::DataSize(pool_len), - ]), - (None, Some(pc_mint)) => Some(vec![ - RpcFilterType::Memcmp(Memcmp::new_base58_encoded(432, &pc_mint.to_bytes())), - RpcFilterType::DataSize(pool_len), - ]), - (Some(coin_mint), Some(pc_mint)) => Some(vec![ - RpcFilterType::Memcmp(Memcmp::new_base58_encoded(400, &coin_mint.to_bytes())), - RpcFilterType::Memcmp(Memcmp::new_base58_encoded(432, &pc_mint.to_bytes())), - RpcFilterType::DataSize(pool_len), - ]), - }; let amm_program = Pubkey::from_str(AMM_PROGRAM)?; - let pools = - common::rpc::get_program_accounts_with_filters(&rpc_client, amm_program, filters).unwrap(); + // Find matching AMM pool from mint pairs by filter + let mut found_pools = None; + for (coin_mint, pc_mint) in pairs { + debug!( + "get_pool_state_by_mint filter: coin_mint: {:?}, pc_mint: {:?}", + coin_mint, pc_mint + ); + let filters = match (coin_mint, pc_mint) { + (None, None) => Some(vec![RpcFilterType::DataSize(pool_len)]), + (Some(coin_mint), None) => Some(vec![ + RpcFilterType::Memcmp(Memcmp::new_base58_encoded(400, &coin_mint.to_bytes())), + RpcFilterType::DataSize(pool_len), + ]), + (None, Some(pc_mint)) => Some(vec![ + RpcFilterType::Memcmp(Memcmp::new_base58_encoded(432, &pc_mint.to_bytes())), + RpcFilterType::DataSize(pool_len), + ]), + (Some(coin_mint), Some(pc_mint)) => Some(vec![ + RpcFilterType::Memcmp(Memcmp::new_base58_encoded(400, &coin_mint.to_bytes())), + RpcFilterType::Memcmp(Memcmp::new_base58_encoded(432, &pc_mint.to_bytes())), + RpcFilterType::DataSize(pool_len), + ]), + }; + let pools = + common::rpc::get_program_accounts_with_filters(&rpc_client, amm_program, filters) + .unwrap(); + if !pools.is_empty() { + found_pools = Some(pools); + break; + } + } - if pools.len() > 1 { - let pool = &pools[0]; - let pool_state = raydium_amm::state::AmmInfo::load_from_bytes(&pools[0].1.data)?; - Ok((pool.0, pool_state.clone())) - } else { - return Err(anyhow!("NotFoundPool: pool state not found")); + match found_pools { + Some(pools) => { + let pool = &pools[0]; + let pool_state = raydium_amm::state::AmmInfo::load_from_bytes(&pools[0].1.data)?; + Ok((pool.0, pool_state.clone())) + } + None => { + return Err(anyhow!("NotFoundPool: pool state not found")); + } } }