raydium_amm_swap/lib.rs
1//! A high‑level client for interacting with Raydium AMM pools on Solana.
2//!
3//! This crate provides:
4//! - Retrieval of on‑chain and off‑chain pool data (`fetch_pool_info`, `fetch_pool_by_id`, etc.)
5//! - Computation of swap quotes with fee and slippage handling (`compute_amount_out`, `compute_amount_in`).
6//! - Execution of swaps against a given pool (`swap_amm`, `swap_clmm`).
7//! - Support for both standard AMM v4 pools and concentrated‑liquidity (CLMM) pools via
8//! `PoolType::Standard` and `PoolType::Concentrated`.
9//!
10//! # Examples
11//!
12//! ```rust
13//!
14//! use std::env;
15//! use std::str::FromStr;
16//! use anyhow::anyhow;
17//! use raydium_amm_swap::amm::client::AmmSwapClient;
18//! use raydium_amm_swap::consts::SOL_MINT;
19//! use raydium_amm_swap::helpers::from_bytes_to_key_pair;
20//! use raydium_amm_swap::interface::{AmmPool, ClmmPool, ClmmSwapParams, PoolKeys, PoolType};
21//! use solana_address::Address;
22//! use solana_sdk::pubkey::Pubkey;
23//! use solana_sdk::signature::Signer;
24//! use solana_client::nonblocking::rpc_client::RpcClient;
25//! use spl_associated_token_account::get_associated_token_address;
26//! use tracing::info;
27//!
28//!
29//! #[tokio::main]
30//! async fn main() -> anyhow::Result<()> {
31//! dotenvy::dotenv().ok();
32//! let amount_in: u64 = 1_000_000;
33//! let slippage: f64 = 0.01;
34//! let url = env::var("RPC_URL")?;
35//! let mint_a_str = env::var("MINT_1").unwrap_or(SOL_MINT.to_string());
36//! let mint_b_str = env::var("MINT_2")?;
37//! let rpc_client = RpcClient::new(url);
38//! let owner = env::var("KEYPAIR").expect("KEYPAIR env is not presented");
39//! let keypair = from_bytes_to_key_pair(owner);
40//! let owner_pubkey = keypair.pubkey();
41//! println!("Owner address {}", owner_pubkey.to_string());
42//! let amm_swap_client = AmmSwapClient::new(rpc_client, keypair);
43//!
44//! // Choose which kind of pool to query.
45//! // You can also pass `PoolType::Concentrated` to work with CLMM pools.
46//! let pool_type = PoolType::Standard;
47//!
48//! let all_mint_pools = amm_swap_client
49//! .fetch_pool_info(&mint_a_str, &mint_b_str, &pool_type, Some(100), None, None, None)
50//! .await
51//! .unwrap();
52//!
53//! match pool_type {
54//! PoolType::Standard => {
55//! let first_pool = all_mint_pools.first().ok_or_else(|| anyhow!("no pools"))?;
56//! let pool_id = Pubkey::from_str(&first_pool.id).unwrap();
57//! let pool_info = amm_swap_client.fetch_pool_by_id(&pool_id).await.unwrap();
58//! let pool_keys: PoolKeys<AmmPool> =
59//! amm_swap_client.fetch_pools_keys_by_id(&pool_id).await.unwrap();
60//!
61//! let rpc_data = amm_swap_client
62//! .get_rpc_pool_info(&pool_id)
63//! .await
64//! .map_err(|e| anyhow!("Error fetching rpc pool info {e:?}"))
65//! .unwrap();
66//! let pool = pool_info.data.get(0).unwrap();
67//! let compute = amm_swap_client
68//! .compute_amount_out(&rpc_data, pool, amount_in, slippage)
69//! .unwrap();
70//!
71//! let mint_a_addr = Address::from_str_const(&mint_a_str);
72//! let mint_b_addr = Address::from_str_const(&mint_b_str);
73//!
74//! let key = pool_keys.data.get(0).unwrap();
75//! info!("Standard pool key: {:?}", key);
76//!
77//! let signature = amm_swap_client
78//! .swap_amm(
79//! key,
80//! &mint_a_addr,
81//! &mint_b_addr,
82//! amount_in,
83//! compute.min_amount_out,
84//! None,
85//! )
86//! .await
87//! .unwrap();
88//! info!("{signature}");
89//! }
90//!
91//! PoolType::Concentrated => {
92//! let first_pool = all_mint_pools.first().ok_or_else(|| anyhow!("no pools"))?;
93//! let pool_id = Pubkey::from_str(&first_pool.id).unwrap();
94//! let pool_keys: PoolKeys<ClmmPool> = amm_swap_client
95//! .fetch_pools_keys_by_id(&pool_id)
96//! .await
97//! .unwrap();
98//! let key = pool_keys.data.get(0).unwrap();
99//! info!("Standard pool key: {:?}", key);
100//! let ata_a = solana_pubkey::Pubkey::from(
101//! get_associated_token_address(
102//! &owner_pubkey,
103//! &Address::from_str_const(&mint_a_str),
104//! )
105//! .to_bytes(),
106//! );
107//! let ata_b = solana_pubkey::Pubkey::from(
108//! get_associated_token_address(
109//! &owner_pubkey,
110//! &Address::from_str_const(&mint_b_str),
111//! )
112//! .to_bytes(),
113//! );
114//! println!("ata_a {}", ata_a.to_string());
115//! let keys = ClmmSwapParams {
116//! pool_id: solana_pubkey::Pubkey::from_str(&key.id).unwrap(),
117//! user_input_token: ata_a,
118//! user_output_token: ata_b,
119//! amount_specified: amount_in,
120//! limit_price: None,
121//! //! if false -> amount is amount_in
122//! base_out: false,
123//! slippage_bps: 100,
124//! };
125//!
126//! let sig = amm_swap_client.swap_clmm(keys).await.unwrap();
127//! info!("{sig}");
128//! }
129//! }
130//!
131//! Ok(())
132//! }
133//
134use anchor_lang::prelude::declare_id;
135
136// Raydium CLMM program id, used by Anchor
137// account/loader traits for on-chain types.
138declare_id!("CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK");
139pub mod amm;
140pub mod clmm;
141pub mod common;
142pub mod consts;
143pub mod helpers;
144pub mod interface;
145pub mod libraries;
146pub mod states;
147pub mod util;