Skip to content

Commit

Permalink
refactor raydium swap
Browse files Browse the repository at this point in the history
  • Loading branch information
wisarmy committed Nov 29, 2024
1 parent ed125fe commit 25cc74b
Show file tree
Hide file tree
Showing 8 changed files with 429 additions and 425 deletions.
396 changes: 133 additions & 263 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ solana-client = "=1.16.27"
solana-sdk = "=1.16.27"
solana-account-decoder = "=1.16.27"
spl-token-client = "=0.7.1"
raydium-library = { git = "https://github.com/raydium-io/raydium-library" }
# raydium-library = { git = "https://github.com/raydium-io/raydium-library" }
amm-cli = { git = "https://github.com/raydium-io/raydium-library" }
common = { git = "https://github.com/raydium-io/raydium-library" }

raydium_amm = { git = "https://github.com/raydium-io/raydium-amm", default-features = false, features = [
"client",
] }
Expand Down
66 changes: 65 additions & 1 deletion examples/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::{env, str::FromStr};

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 solana_client::rpc_client::GetConfirmedSignaturesForAddress2Config;
Expand All @@ -13,7 +15,69 @@ async fn main() -> Result<()> {
logger::init();

// get_signatures().await?;
connect_websocket().await?;
// connect_websocket().await?;
get_amm_info().await?;
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 pool_state =
common::rpc::get_account::<raydium_amm::state::AmmInfo>(&client, &amm_pool_id)?.unwrap();

println!("pool_state : {:#?}", pool_state);
let amm_program = Pubkey::from_str("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8")?;
let native_mint = spl_token::native_mint::ID;
let amount_specified = 100_000_000;
let slippage_bps = 10;
let swap_base_in = true;
let user_input_token = if pool_state.coin_vault_mint == native_mint {
pool_state.pc_vault
} else {
pool_state.coin_vault
};

let amm_keys = load_amm_keys(&client, &amm_program, &amm_pool_id).unwrap();
// reload accounts data to calculate amm pool vault amount
// get multiple accounts at the same time to ensure data consistency
let load_pubkeys = vec![
amm_pool_id,
amm_keys.amm_pc_vault,
amm_keys.amm_coin_vault,
user_input_token,
];
let rsps = common::rpc::get_multiple_accounts(&client, &load_pubkeys).unwrap();

println!("rsps: {:#?}", rsps);

let amm_pc_vault_account = rsps[1].clone();
let amm_coin_vault_account = rsps[2].clone();
let _token_in_account = rsps[3].clone();

let amm_pc_vault =
common_utils::unpack_token(&amm_pc_vault_account.as_ref().unwrap().data).unwrap();
let amm_coin_vault =
common_utils::unpack_token(&amm_coin_vault_account.as_ref().unwrap().data).unwrap();

println!("amm_pc_vault: {:#?}", amm_pc_vault.base.amount);
println!("amm_coin_vault: {:#?}", amm_coin_vault.base.amount);

let swap_info_result = amm_cli::calculate_swap_info(
&client,
amm_program,
amm_pool_id,
user_input_token,
amount_specified,
slippage_bps,
swap_base_in,
)
.unwrap();

println!("swap_info_result : {:#?}", swap_info_result);

Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ async fn main() -> Result<()> {
&token_account.mint,
)
.await?;
let pool_id = pool_info.data.get_pool().unwrap().id;
let pool_id = pool_info.get_pool().unwrap().id;
info!("pool id: {}", pool_id);
}
},
Expand Down
119 changes: 46 additions & 73 deletions src/pool.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use std::str::FromStr;

use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result};
use common::common_utils;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signer::Signer;
use spl_token_2022::amount_to_ui_amount;
use tracing::{debug, info, warn};
use tracing::{debug, warn};

use crate::{
helper::get_solana_price,
raydium::{get_pool_info_by_id, Raydium},
};
use crate::{helper::get_solana_price, raydium::Raydium};

impl Raydium {
pub async fn get_pool(&self, pool_id: &str) -> Result<(f64, f64, f64, f64, f64)> {
Expand All @@ -19,91 +16,67 @@ impl Raydium {
.inspect_err(|err| warn!("failed get solana price: {}", err))?;
let usd_price = ((price * sol_price) * 1_000_000_000.0).round() / 1_000_000_000.0;

info!("sol price: {}, usd_price: {} ", sol_price, usd_price);
debug!("sol price: {}, usd_price: {} ", sol_price, usd_price);

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))?;
let pool_info = get_pool_info_by_id(pool_id)
.await?
.get_pool()
.ok_or(anyhow!("pool is empty"))?;
debug!("amm pool id: {:?}", amm_pool_id);

let client = self
.client_blocking
.clone()
.context("failed to get rpc client")?;
let owner = self.keypair.pubkey();
let amm_program = Pubkey::from_str("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8")?;
let market_program = Pubkey::from_str("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX")?;
let market_id = Pubkey::from_str(&pool_info.market_id)?;
let mint_a = (
Pubkey::from_str(&pool_info.mint_a.address)?,
pool_info.mint_a.decimals,
pool_info.mint_a.symbol,
);
let mint_b = (
Pubkey::from_str(&pool_info.mint_b.address)?,
pool_info.mint_b.decimals,
pool_info.mint_b.symbol,
);
debug!("{mint_a:#?}, {mint_b:#?}");

let amm_keys = raydium_library::amm::utils::get_amm_pda_keys(
&amm_program,
&market_program,
&market_id,
&mint_a.0,
&mint_b.0,
)?;
debug!("amm_keys: {amm_keys:#?}");
if amm_keys.amm_pool != amm_pool_id {
warn!("amm_keys's amm_pool not match input pool_id");
return Err(anyhow!("internal error"));
}
let pool_state =
common::rpc::get_account::<raydium_amm::state::AmmInfo>(&client, &amm_pool_id)?
.unwrap();

// debug!("pool_state : {:#?}", pool_state);

// load market keys
let market_keys = raydium_library::amm::openbook::get_keys_for_market(
&client,
&amm_keys.market_program,
&amm_keys.market,
)
.inspect_err(|e| {
warn!("failed to get market_keys: {}", e);
})?;
let load_pubkeys = vec![pool_state.pc_vault, pool_state.coin_vault];
let rsps = common::rpc::get_multiple_accounts(&client, &load_pubkeys).unwrap();

// calculate amm pool vault with load data at the same time or use simulate to calculate
let calculate_result = raydium_library::amm::calculate_pool_vault_amounts(
&client,
&amm_program,
&amm_pool_id,
&amm_keys,
&market_keys,
raydium_library::amm::utils::CalculateMethod::Simulate(owner),
)?;
debug!("calculate_pool result: {:#?}", calculate_result);
let amm_pc_vault_account = rsps[0].clone();
let amm_coin_vault_account = rsps[1].clone();

let mut pool_pc = (mint_b.clone(), calculate_result.pool_pc_vault_amount);
let mut pool_coin = (mint_a.clone(), calculate_result.pool_coin_vault_amount);
let amm_pc_vault =
common_utils::unpack_token(&amm_pc_vault_account.as_ref().unwrap().data).unwrap();
let amm_coin_vault =
common_utils::unpack_token(&amm_coin_vault_account.as_ref().unwrap().data).unwrap();

if amm_keys.amm_pc_mint != spl_token::native_mint::ID {
pool_pc = (mint_a, calculate_result.pool_coin_vault_amount);
pool_coin = (mint_b, calculate_result.pool_pc_vault_amount)
}
let (base_account, quote_account) = if amm_coin_vault.base.is_native() {
(
(
pool_state.pc_vault_mint,
amount_to_ui_amount(amm_pc_vault.base.amount, pool_state.pc_decimals as u8),
),
(
pool_state.coin_vault_mint,
amount_to_ui_amount(amm_coin_vault.base.amount, pool_state.coin_decimals as u8),
),
)
} else {
(
(
pool_state.coin_vault_mint,
amount_to_ui_amount(amm_coin_vault.base.amount, pool_state.coin_decimals as u8),
),
(
pool_state.pc_vault_mint,
amount_to_ui_amount(amm_pc_vault.base.amount, pool_state.pc_decimals as u8),
),
)
};

let pool_pc_ui_amount = amount_to_ui_amount(pool_pc.1, pool_pc.0 .1);
let pool_coin_ui_amount = amount_to_ui_amount(pool_coin.1, pool_coin.0 .1);
let price = pool_pc_ui_amount / pool_coin_ui_amount;
let price = quote_account.1 / base_account.1;

info!(
"calculate pool: {}: {}, {}: {}, price: {} sol",
pool_pc.0 .2, pool_pc_ui_amount, pool_coin.0 .2, pool_coin_ui_amount, price
debug!(
"calculate pool[{}]: {}: {}, {}: {}, price: {} sol",
amm_pool_id, base_account.0, base_account.1, quote_account.0, quote_account.1, price
);

Ok((pool_coin_ui_amount, pool_pc_ui_amount, price))
Ok((base_account.1, quote_account.1, price))
}
}
3 changes: 1 addition & 2 deletions src/pump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::{str::FromStr, sync::Arc};

use anyhow::{anyhow, Context, Result};
use raydium_amm::math::U128;
use raydium_library::amm::TEN_THOUSAND;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use solana_client::nonblocking::rpc_client::RpcClient;
Expand All @@ -24,7 +23,7 @@ use crate::{
swap::{SwapDirection, SwapInType},
token, tx,
};

pub const TEN_THOUSAND: u64 = 10000;
pub const TOKEN_PROGRAM: &str = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
pub const RENT_PROGRAM: &str = "SysvarRent111111111111111111111111111111111";
pub const ASSOCIATED_TOKEN_PROGRAM: &str = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
Expand Down
Loading

0 comments on commit 25cc74b

Please sign in to comment.