Repository: cutupdev/Solana-Raydium-Sniper-Bot
Branch: main
Commit: 829594cb9c47
Files: 17
Total size: 25.9 KB
Directory structure:
gitextract_3q5qaqtw/
├── .gitignore
├── Cargo.toml
├── README.md
├── src/
│ ├── common/
│ │ ├── logger.rs
│ │ ├── mod.rs
│ │ └── utils.rs
│ ├── core/
│ │ ├── mod.rs
│ │ ├── token.rs
│ │ └── tx.rs
│ ├── dex/
│ │ ├── mod.rs
│ │ └── raydium.rs
│ ├── engine/
│ │ ├── mod.rs
│ │ └── monitor/
│ │ └── mod.rs
│ ├── lib.rs
│ ├── main.rs
│ └── services/
│ └── mod.rs
└── trial/
└── blacklist.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.env
target
================================================
FILE: Cargo.toml
================================================
[package]
name = "raydium-sniper-bot"
version = "0.1.0"
edition = "2021"
================================================
FILE: README.md
================================================
# Solana Raydium Sniper Bot
This bot fetches to new Raydium pools and buys as soon as possible. If RPC or node is good, it commonly buy tokens before token is availabel on Raydium UI, can buy tokens than the others. It's free, basic version, and I have advanced version for it. I updated codebase with Rust to boost speed and performance. Feel free to contact with me to get advanced version. [Telegram: https://t.me/DevCutup, Whatsapp: https://wa.me/13137423660]. This is just version to give vision about raydium dex and sniper bot.
## Features
### Speed and Efficiency
- **Lightning-Quick Transactions**: Leveraging Rust's exceptional performance, our bot allows you to snipe new tokens almost instantly. Say goodbye to delays and seize opportunities as they arise!
### Safety First
- **Robust Security**: Rust's safety guarantees minimize bugs and vulnerabilities, ensuring your trading activities are secure. Trade with confidence and peace of mind.
### Multiple gRPC Connections
- **Stay Updated**: Effortlessly connect to top Solana data providers like **Helius** and **Yellowstone** through multiple gRPC connections. Get real-time updates and make informed trading decisions.
### User-Friendly Interface
- **Intuitive Design**: My sniper bot features a clean and accessible interface, making it easy for users of all experience levels to navigate. Start trading in no time!
## Advanced Features
- **jito-confirm**: Engage in low-latency transactions on platforms like Raydium and Pumpfun.
- **jito-bundle**: Bundle buy/sell actions with up to **20 wallets** in Raydium/Pumpfun, enhancing your trading strategy and flexibility.
---
## Directory Structure
```
src/
├── core/
│ ├── token.rs # Token definitions and handling
│ └── tx.rs # Transaction handling
| └── mod.rs # mod file
|
├── engine/
│ ├── swap.rs # Token swap(buy/sell) functionalities in various Dexs
│ └── monitor # New token monitoring(and parse tx) in Dexs using geyser rpc, and normal rpc
│ └── helius.rs # Helius gRpc for tx listen and parse.
│ └── yellowstone.rs # Yellowstone gRpc for tx listen and parse.
| └── mod.rs # mod file
|
├── dex/
│ ├── raydium.rs # Raydium
| └── mod.rs # mod file
│
├── services/
│ ├── jito.rs # Jito service provides ultra-fast transaction confirmation
│ ├── nozomi.rs # Jito service provides ultra-fast transaction confirmation
│ ├── zeroslot.rs # Jito service provides ultra-fast transaction confirmation
│ └── nextblock.rs # NextBlock service provides the ultra-fast transaction confirmation in unique way
| └── mod.rs # mod file
|
├── common/
│ ├── logger.rs # Logs to be clean and convenient to monitor.
│ └── utils.rs # Utility functions used across the project
| └── mod.rs # mod file
│
├── lib.rs
└── main.rs
```
---
### Setup
1. Environment Variables Settings
```plaintext
PRIVATE_KEY= # your wallet priv_key
RPC_API_KEY= #your helius rpc api-key (Please use premium version that has Geyser Enhanced Websocket)
SLIPPAGE=10
JITO_BLOCK_ENGINE_URL=https://ny.mainnet.block-engine.jito.wtf
JITO_TIP_VALUE=0.00927
TIME_EXCEED=60 # seconds; time limit for volume non-increasing
TOKEN_AMOUNT=0.0000001 # token amount to purchase
TP=3 #3 times
SL=0.5 #50 percentage
```
2. Add the wallet address you want to block on a new line and save the file.
```
3NQmnSXfGqtgxFTZ82gS7Pwt2btn3fEPb6EiX5ax5bvr
```
3. Run `trial/raydium-sniper.exe`.
### Test Result(Same Block)
- Detect: https://solscan.io/tx/5o7ajnZ9CRf7FBYEvydu8vapJJDWtKCvRFiTUBmbeu2FmmDhAQQy3c9YFFhpTucr2SZcrf2aUsDanEVjYgwN9kBc
- Bought: https://solscan.io/tx/3vgim3MwJsdtahXqfW2DrzTAWpVQ8EUTed2cjzHuqxSfUpfp72mgzZhiVosWaCUHdqJTDHpQaYh5xN7rkHGmzqWv
- Dexscreener: https://dexscreener.com/solana/A1zZXCq2DmqwVD4fLDzmgQ3ceY6LQnMBVokejqnHpump
### Contact Information
- Telegram: https://t.me/DevCutup
- Whatsapp: https://wa.me/13137423660
- Twitter: https://x.com/devcutup
================================================
FILE: src/common/logger.rs
================================================
use chrono::Local;
const LOG_LEVEL: &str = "LOG";
pub struct Logger {
prefix: String,
date_format: String,
}
impl Logger {
// Constructor function to create a new Logger instance
pub fn new(prefix: String) -> Self {
Logger {
prefix,
date_format: String::from("%Y-%m-%d %H:%M:%S"),
}
}
// Method to log a message with a prefix
pub fn log(&self, message: String) -> String {
let log = format!("{} {}", self.prefix_with_date(), message);
println!("{}", log);
log
}
pub fn debug(&self, message: String) -> String {
let log = format!("{} [{}] {}", self.prefix_with_date(), "DEBUG", message);
if LogLevel::new().is_debug() {
println!("{}", log);
}
log
}
pub fn error(&self, message: String) -> String {
let log = format!("{} [{}] {}", self.prefix_with_date(), "ERROR", message);
println!("{}", log);
log
}
fn prefix_with_date(&self) -> String {
let date = Local::now();
format!(
"[{}] {}",
date.format(self.date_format.as_str()),
self.prefix
)
}
}
struct LogLevel<'a> {
level: &'a str,
}
impl LogLevel<'_> {
fn new() -> Self {
let level = LOG_LEVEL;
LogLevel { level }
}
fn is_debug(&self) -> bool {
self.level.to_lowercase().eq("debug")
}
}
================================================
FILE: src/common/mod.rs
================================================
pub mod logger;
pub mod utils;
================================================
FILE: src/common/utils.rs
================================================
use anyhow::Result;
use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair};
use std::{env, sync::Arc};
#[derive(Clone)]
pub struct AppState {
pub rpc_client: Arc<solana_client::rpc_client::RpcClient>,
pub rpc_nonblocking_client: Arc<solana_client::nonblocking::rpc_client::RpcClient>,
pub wallet: Arc<Keypair>,
}
pub fn import_env_var(key: &str) -> String {
env::var(key).unwrap_or_else(|_| panic!("Environment variable {} is not set", key))
}
pub fn create_rpc_client() -> Result<Arc<solana_client::rpc_client::RpcClient>> {
let rpc_https = import_env_var("RPC_HTTPS");
let rpc_client = solana_client::rpc_client::RpcClient::new_with_commitment(
rpc_https,
CommitmentConfig::processed(),
);
Ok(Arc::new(rpc_client))
}
pub async fn create_nonblocking_rpc_client(
) -> Result<Arc<solana_client::nonblocking::rpc_client::RpcClient>> {
let rpc_https = import_env_var("RPC_HTTPS");
let rpc_client = solana_client::nonblocking::rpc_client::RpcClient::new_with_commitment(
rpc_https,
CommitmentConfig::processed(),
);
Ok(Arc::new(rpc_client))
}
pub fn import_wallet() -> Result<Arc<Keypair>> {
let priv_key = import_env_var("PRIVATE_KEY");
let wallet: Keypair = Keypair::from_base58_string(priv_key.as_str());
Ok(Arc::new(wallet))
}
================================================
FILE: src/core/mod.rs
================================================
pub mod token;
pub mod tx;
================================================
FILE: src/core/token.rs
================================================
use solana_sdk::{pubkey::Pubkey, signature::Keypair};
use spl_token_2022::{
extension::StateWithExtensionsOwned,
state::{Account, Mint},
};
use spl_token_client::{
client::{ProgramClient, ProgramRpcClient, ProgramRpcClientSendTransaction},
token::{Token, TokenError, TokenResult},
};
use std::sync::Arc;
pub fn get_associated_token_address(
client: Arc<solana_client::nonblocking::rpc_client::RpcClient>,
keypair: Arc<Keypair>,
address: &Pubkey,
owner: &Pubkey,
) -> Pubkey {
let token_client = Token::new(
Arc::new(ProgramRpcClient::new(
client.clone(),
ProgramRpcClientSendTransaction,
)),
&spl_token::ID,
address,
None,
Arc::new(Keypair::from_bytes(&keypair.to_bytes()).expect("failed to copy keypair")),
);
token_client.get_associated_token_address(owner)
}
pub async fn get_account_info(
client: Arc<solana_client::nonblocking::rpc_client::RpcClient>,
_keypair: Arc<Keypair>,
address: &Pubkey,
account: &Pubkey,
) -> TokenResult<StateWithExtensionsOwned<Account>> {
let program_client = Arc::new(ProgramRpcClient::new(
client.clone(),
ProgramRpcClientSendTransaction,
));
let account = program_client
.get_account(*account)
.await
.map_err(TokenError::Client)?
.ok_or(TokenError::AccountNotFound)
.inspect_err(|err| println!("get_account_info: {} {}: mint {}", account, err, address))?;
if account.owner != spl_token::ID {
return Err(TokenError::AccountInvalidOwner);
}
let account = StateWithExtensionsOwned::<Account>::unpack(account.data)?;
if account.base.mint != *address {
return Err(TokenError::AccountInvalidMint);
}
Ok(account)
}
pub async fn get_mint_info(
client: Arc<solana_client::nonblocking::rpc_client::RpcClient>,
_keypair: Arc<Keypair>,
address: &Pubkey,
) -> TokenResult<StateWithExtensionsOwned<Mint>> {
let program_client = Arc::new(ProgramRpcClient::new(
client.clone(),
ProgramRpcClientSendTransaction,
));
let account = program_client
.get_account(*address)
.await
.map_err(TokenError::Client)?
.ok_or(TokenError::AccountNotFound)
.inspect_err(|err| println!("{} {}: mint {}", address, err, address))?;
if account.owner != spl_token::ID {
return Err(TokenError::AccountInvalidOwner);
}
let mint_result = StateWithExtensionsOwned::<Mint>::unpack(account.data).map_err(Into::into);
let decimals: Option<u8> = None;
if let (Ok(mint), Some(decimals)) = (&mint_result, decimals) {
if decimals != mint.base.decimals {
return Err(TokenError::InvalidDecimals);
}
}
mint_result
}
================================================
FILE: src/core/tx.rs
================================================
use std::{env, sync::Arc, time::Duration};
use anyhow::Result;
use jito_json_rpc_client::jsonrpc_client::rpc_client::RpcClient as JitoRpcClient;
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
instruction::Instruction,
signature::Keypair,
signer::Signer,
system_transaction,
transaction::{Transaction, VersionedTransaction},
};
use spl_token::ui_amount_to_amount;
use std::str::FromStr;
use tokio::time::Instant;
use crate::{
common::logger::Logger,
services::jito::{self, get_tip_account, get_tip_value, wait_for_bundle_confirmation},
};
// prioritization fee = UNIT_PRICE * UNIT_LIMIT
fn get_unit_price() -> u64 {
env::var("UNIT_PRICE")
.ok()
.and_then(|v| u64::from_str(&v).ok())
.unwrap_or(1)
}
fn get_unit_limit() -> u32 {
env::var("UNIT_LIMIT")
.ok()
.and_then(|v| u32::from_str(&v).ok())
.unwrap_or(300_000)
}
pub async fn new_signed_and_send(
client: &RpcClient,
keypair: &Keypair,
mut instructions: Vec<Instruction>,
use_jito: bool,
logger: &Logger,
) -> Result<Vec<String>> {
let unit_price = get_unit_price();
let unit_limit = get_unit_limit();
// If not using Jito, manually set the compute unit price and limit
if !use_jito {
let modify_compute_units =
solana_sdk::compute_budget::ComputeBudgetInstruction::set_compute_unit_price(
unit_price,
);
let add_priority_fee =
solana_sdk::compute_budget::ComputeBudgetInstruction::set_compute_unit_limit(
unit_limit,
);
instructions.insert(0, modify_compute_units);
instructions.insert(1, add_priority_fee);
}
// send init tx
let recent_blockhash = client.get_latest_blockhash()?;
let txn = Transaction::new_signed_with_payer(
&instructions,
Some(&keypair.pubkey()),
&vec![keypair],
recent_blockhash,
);
let start_time = Instant::now();
let mut txs = vec![];
if use_jito {
// jito
let tip_account = get_tip_account().await?;
let jito_client = Arc::new(JitoRpcClient::new(format!(
"{}/api/v1/bundles",
*jito::BLOCK_ENGINE_URL
)));
// jito tip, the upper limit is 0.1
let mut tip = get_tip_value().await?;
tip = tip.min(0.1);
let tip_lamports = ui_amount_to_amount(tip, spl_token::native_mint::DECIMALS);
logger.log(format!(
"tip account: {}, tip(sol): {}, lamports: {}",
tip_account, tip, tip_lamports
));
// tip tx
let bundle: Vec<VersionedTransaction> = vec![
VersionedTransaction::from(txn),
VersionedTransaction::from(system_transaction::transfer(
keypair,
&tip_account,
tip_lamports,
recent_blockhash,
)),
];
let bundle_id = jito_client.send_bundle(&bundle).await?;
logger.log(format!("bundle_id: {}", bundle_id));
txs = wait_for_bundle_confirmation(
move |id: String| {
let client = Arc::clone(&jito_client);
async move {
let response = client.get_bundle_statuses(&[id]).await;
let statuses = response.inspect_err(|err| {
logger.log(format!("Error fetching bundle status: {:?}", err));
})?;
Ok(statuses.value)
}
},
bundle_id,
Duration::from_millis(1000),
Duration::from_secs(10),
)
.await?;
} else {
let sig = common::rpc::send_txn(client, &txn, true)?;
logger.log(format!("signature: {:#?}", sig));
txs.push(sig.to_string());
}
logger.log(format!("tx ellapsed: {:?}", start_time.elapsed()));
Ok(txs)
}
================================================
FILE: src/dex/mod.rs
================================================
pub mod pump_fun;
pub mod raydium;
pub mod meteora;
pub mod orca;
================================================
FILE: src/dex/raydium.rs
================================================
use crate::{
common::{
logger::Logger,
utils::{import_env_var, SwapConfig},
},
core::{
token::{get_account_info, get_associated_token_address, get_mint_info},
tx,
},
engine::swap::{SwapDirection, SwapInType},
};
use amm_cli::AmmSwapInfoResult;
use anyhow::{anyhow, Context, Result};
use bytemuck;
use raydium_amm::state::{AmmInfo, Loadable};
use reqwest::Proxy;
use serde::Deserialize;
use solana_client::rpc_filter::{Memcmp, RpcFilterType};
use solana_sdk::{
instruction::Instruction, program_pack::Pack, pubkey::Pubkey, signature::Keypair,
signer::Signer, system_instruction,
};
use spl_associated_token_account::instruction::create_associated_token_account;
use spl_token::{amount_to_ui_amount, state::Account, ui_amount_to_amount};
use spl_token_client::token::TokenError;
use std::{str::FromStr, sync::Arc};
pub const AMM_PROGRAM: &str = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";
#[derive(Debug, Deserialize)]
pub struct PoolInfo {
pub success: bool,
pub data: PoolData,
}
#[derive(Debug, Deserialize)]
pub struct PoolData {
// pub count: u32,
pub data: Vec<Pool>,
}
impl PoolData {
pub fn get_pool(&self) -> Option<Pool> {
self.data.first().cloned()
}
}
#[derive(Debug, Deserialize, Clone)]
pub struct Pool {
pub id: String,
#[serde(rename = "programId")]
pub program_id: String,
#[serde(rename = "mintA")]
pub mint_a: Mint,
#[serde(rename = "mintB")]
pub mint_b: Mint,
#[serde(rename = "marketId")]
pub market_id: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Mint {
pub address: String,
pub symbol: String,
pub name: String,
pub decimals: u8,
}
pub struct Raydium {
pub rpc_nonblocking_client: Arc<solana_client::nonblocking::rpc_client::RpcClient>,
pub rpc_client: Option<Arc<solana_client::rpc_client::RpcClient>>,
pub keypair: Arc<Keypair>,
pub pool_id: Option<String>,
}
impl Raydium {
pub fn new(
rpc_nonblocking_client: Arc<solana_client::nonblocking::rpc_client::RpcClient>,
rpc_client: Arc<solana_client::rpc_client::RpcClient>,
keypair: Arc<Keypair>,
) -> Self {
Self {
rpc_nonblocking_client,
keypair,
rpc_client: Some(rpc_client),
pool_id: None,
}
}
pub async fn swap(
&self,
swap_config: SwapConfig,
amm_pool_id: Pubkey,
pool_state: AmmInfo,
) -> Result<Vec<String>> {
let logger = Logger::new(format!(
"[SWAP IN RAYDIUM]({}) => ",
chrono::Utc::now().timestamp()
));
let slippage_bps = swap_config.slippage * 100;
let owner = self.keypair.pubkey();
let program_id = spl_token::ID;
let native_mint = spl_token::native_mint::ID;
let mint = pool_state.coin_vault_mint;
let (token_in, token_out, user_input_token, swap_base_in) = match (
swap_config.swap_direction.clone(),
pool_state.coin_vault_mint == native_mint,
) {
(SwapDirection::Buy, true) => (native_mint, mint, pool_state.coin_vault, true),
(SwapDirection::Buy, false) => (native_mint, mint, pool_state.pc_vault, true),
(SwapDirection::Sell, true) => (mint, native_mint, pool_state.pc_vault, true),
(SwapDirection::Sell, false) => (mint, native_mint, pool_state.coin_vault, true),
};
logger.log(format!(
"token_in:{}, token_out:{}, user_input_token:{}, swap_base_in:{}",
token_in, token_out, user_input_token, swap_base_in
));
let in_ata = get_associated_token_address(
self.rpc_nonblocking_client.clone(),
self.keypair.clone(),
&token_in,
&owner,
);
let out_ata = get_associated_token_address(
self.rpc_nonblocking_client.clone(),
self.keypair.clone(),
&token_out,
&owner,
);
let mut create_instruction = None;
let mut close_instruction = None;
tx::new_signed_and_send(
&client,
&self.keypair,
instructions,
swap_config.use_jito,
&logger,
)
.await
}
}
pub fn amm_swap(
amm_program: &Pubkey,
result: AmmSwapInfoResult,
user_owner: &Pubkey,
user_source: &Pubkey,
user_destination: &Pubkey,
amount_specified: u64,
other_amount_threshold: u64,
swap_base_in: bool,
) -> Result<Instruction> {
let swap_instruction = if swap_base_in {
raydium_amm::instruction::swap_base_in(
amm_program,
&result.pool_id,
&result.amm_authority,
&result.amm_open_orders,
&result.amm_coin_vault,
&result.amm_pc_vault,
&result.market_program,
&result.market,
&result.market_bids,
&result.market_asks,
&result.market_event_queue,
&result.market_coin_vault,
&result.market_pc_vault,
&result.market_vault_signer,
user_source,
user_destination,
user_owner,
amount_specified,
other_amount_threshold,
)?
} else {
raydium_amm::instruction::swap_base_out(
amm_program,
&result.pool_id,
&result.amm_authority,
&result.amm_open_orders,
&result.amm_coin_vault,
&result.amm_pc_vault,
&result.market_program,
&result.market,
&result.market_bids,
&result.market_asks,
&result.market_event_queue,
&result.market_coin_vault,
&result.market_pc_vault,
&result.market_vault_signer,
user_source,
user_destination,
user_owner,
other_amount_threshold,
amount_specified,
)?
};
Ok(swap_instruction)
}
pub async fn get_pool_state(
rpc_client: Arc<solana_client::rpc_client::RpcClient>,
pool_id: Option<&str>,
mint: Option<&str>,
logger: &Logger,
) -> Result<(Pubkey, AmmInfo)> {
if let Some(pool_id) = pool_id {
logger.log(format!("[FIND POOL STATE BY pool_id]: {}", pool_id));
let amm_pool_id = Pubkey::from_str(pool_id)?;
let pool_data = common::rpc::get_account(&rpc_client, &amm_pool_id)?
.ok_or(anyhow!("NotFoundPool: pool state not found"))?;
let pool_state: &AmmInfo =
bytemuck::from_bytes(&pool_data[0..core::mem::size_of::<AmmInfo>()]);
Ok((amm_pool_id, *pool_state))
} else if let Some(mint) = mint {
// find pool by mint via rpc
if let Ok(pool_state) = get_pool_state_by_mint(rpc_client.clone(), mint, logger).await {
return Ok(pool_state);
}
// find pool by mint via raydium api
let pool_data = get_pool_info(&spl_token::native_mint::ID.to_string(), mint).await;
if let Ok(pool_data) = pool_data {
let pool = pool_data
.get_pool()
.ok_or(anyhow!("NotFoundPool: pool not found in raydium api"))?;
let amm_pool_id = Pubkey::from_str(&pool.id)?;
logger.log(format!("[FIND POOL STATE BY raydium api]: {}", amm_pool_id));
let pool_data = common::rpc::get_account(&rpc_client, &amm_pool_id)?
.ok_or(anyhow!("NotFoundPool: pool state not found"))?;
let pool_state: &AmmInfo =
bytemuck::from_bytes(&pool_data[0..core::mem::size_of::<AmmInfo>()]);
return Ok((amm_pool_id, *pool_state));
}
Err(anyhow!("NotFoundPool: pool state not found"))
} else {
Err(anyhow!("NotFoundPool: pool state not found"))
}
}
pub async fn get_pool_state_by_mint(
rpc_client: Arc<solana_client::rpc_client::RpcClient>,
mint: &str,
logger: &Logger,
) -> Result<(Pubkey, AmmInfo)> {
logger.log(format!("[FIND POOL STATE BY mint]: {}", 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::<AmmInfo>() as u64;
let amm_program = Pubkey::from_str(AMM_PROGRAM)?;
// Find matching AMM pool from mint pairs by filter
let mut found_pools = None;
for (coin_mint, pc_mint) in pairs {
logger.log(format!(
"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;
}
}
match found_pools {
Some(pools) => {
let pool = &pools[0];
let pool_state = AmmInfo::load_from_bytes(&pools[0].1.data)?;
Ok((pool.0, *pool_state))
}
None => Err(anyhow!("NotFoundPool: pool state not found")),
}
}
// get pool info
// https://api-v3.raydium.io/pools/info/mint?mint1=So11111111111111111111111111111111111111112&mint2=EzM2d8JVpzfhV7km3tUsR1U1S4xwkrPnWkM4QFeTpump&poolType=standard&poolSortField=default&sortType=desc&pageSize=10&page=1
pub async fn get_pool_info(mint1: &str, mint2: &str) -> Result<PoolData> {
let mut client_builder = reqwest::Client::builder();
let http_proxy = import_env_var("HTTP_PROXY");
let proxy = Proxy::all(http_proxy)?;
client_builder = client_builder.proxy(proxy);
let client = client_builder.build()?;
let result = client
.get("https://api-v3.raydium.io/pools/info/mint")
.query(&[
("mint1", mint1),
("mint2", mint2),
("poolType", "standard"),
("poolSortField", "default"),
("sortType", "desc"),
("pageSize", "1"),
("page", "1"),
])
.send()
.await?
.json::<PoolInfo>()
.await
.context("Failed to parse pool info JSON")?;
Ok(result.data)
}
================================================
FILE: src/engine/mod.rs
================================================
pub mod monitor;
pub mod swap;
================================================
FILE: src/engine/monitor/mod.rs
================================================
pub mod helius;
pub mod yellowstone;
================================================
FILE: src/lib.rs
================================================
pub mod common;
pub mod core;
pub mod dex;
pub mod engine;
pub mod services;
================================================
FILE: src/main.rs
================================================
use dotenv::dotenv;
use raydium_pump_snipe_bot::{
common::{
logger::Logger,
utils::{
create_nonblocking_rpc_client, create_rpc_client, import_env_var, import_wallet,
AppState,
},
},
engine::monitor::{pumpfun_monitor, raydium_monitor},
services::jito,
};
use solana_sdk::signer::Signer;
#[tokio::main]
async fn main() {
let logger = Logger::new("[INIT] => ".to_string());
dotenv().ok();
let rpc_wss = import_env_var("RPC_WSS");
let rpc_client = create_rpc_client().unwrap();
let rpc_nonblocking_client = create_nonblocking_rpc_client().await.unwrap();
let wallet = import_wallet().unwrap();
let wallet_cloned = wallet.clone();
let state = AppState {
rpc_client,
rpc_nonblocking_client,
wallet,
};
let slippage = import_env_var("SLIPPAGE").parse::<u64>().unwrap_or(5);
let use_jito = true;
if use_jito {
jito::init_tip_accounts().await.unwrap();
}
logger.log(format!(
"Successfully Set the environment variables.\n\t\t\t\t [Web Socket RPC]: {},\n\t\t\t\t [Wallet]: {:?},\n\t\t\t\t [Slippage]: {}\n",
rpc_wss, wallet_cloned.pubkey(), slippage
));
// raydium_monitor(&rpc_wss, state, slippage, use_jito).await;
pumpfun_monitor(&rpc_wss, state, slippage, use_jito).await;
}
================================================
FILE: src/services/mod.rs
================================================
pub mod jito;
pub mod nextblock;
================================================
FILE: trial/blacklist.txt
================================================
gitextract_3q5qaqtw/
├── .gitignore
├── Cargo.toml
├── README.md
├── src/
│ ├── common/
│ │ ├── logger.rs
│ │ ├── mod.rs
│ │ └── utils.rs
│ ├── core/
│ │ ├── mod.rs
│ │ ├── token.rs
│ │ └── tx.rs
│ ├── dex/
│ │ ├── mod.rs
│ │ └── raydium.rs
│ ├── engine/
│ │ ├── mod.rs
│ │ └── monitor/
│ │ └── mod.rs
│ ├── lib.rs
│ ├── main.rs
│ └── services/
│ └── mod.rs
└── trial/
└── blacklist.txt
SYMBOL INDEX (35 symbols across 6 files)
FILE: src/common/logger.rs
constant LOG_LEVEL (line 3) | const LOG_LEVEL: &str = "LOG";
type Logger (line 5) | pub struct Logger {
method new (line 12) | pub fn new(prefix: String) -> Self {
method log (line 20) | pub fn log(&self, message: String) -> String {
method debug (line 26) | pub fn debug(&self, message: String) -> String {
method error (line 33) | pub fn error(&self, message: String) -> String {
method prefix_with_date (line 40) | fn prefix_with_date(&self) -> String {
type LogLevel (line 50) | struct LogLevel<'a> {
function new (line 54) | fn new() -> Self {
function is_debug (line 58) | fn is_debug(&self) -> bool {
FILE: src/common/utils.rs
type AppState (line 6) | pub struct AppState {
function import_env_var (line 12) | pub fn import_env_var(key: &str) -> String {
function create_rpc_client (line 16) | pub fn create_rpc_client() -> Result<Arc<solana_client::rpc_client::RpcC...
function create_nonblocking_rpc_client (line 25) | pub async fn create_nonblocking_rpc_client(
function import_wallet (line 35) | pub fn import_wallet() -> Result<Arc<Keypair>> {
FILE: src/core/token.rs
function get_associated_token_address (line 12) | pub fn get_associated_token_address(
function get_account_info (line 31) | pub async fn get_account_info(
function get_mint_info (line 59) | pub async fn get_mint_info(
FILE: src/core/tx.rs
function get_unit_price (line 24) | fn get_unit_price() -> u64 {
function get_unit_limit (line 31) | fn get_unit_limit() -> u32 {
function new_signed_and_send (line 38) | pub async fn new_signed_and_send(
FILE: src/dex/raydium.rs
constant AMM_PROGRAM (line 28) | pub const AMM_PROGRAM: &str = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1...
type PoolInfo (line 31) | pub struct PoolInfo {
type PoolData (line 37) | pub struct PoolData {
method get_pool (line 43) | pub fn get_pool(&self) -> Option<Pool> {
type Pool (line 49) | pub struct Pool {
type Mint (line 62) | pub struct Mint {
type Raydium (line 69) | pub struct Raydium {
method new (line 77) | pub fn new(
method swap (line 90) | pub async fn swap(
function amm_swap (line 148) | pub fn amm_swap(
function get_pool_state (line 207) | pub async fn get_pool_state(
function get_pool_state_by_mint (line 247) | pub async fn get_pool_state_by_mint(
function get_pool_info (line 312) | pub async fn get_pool_info(mint1: &str, mint2: &str) -> Result<PoolData> {
FILE: src/main.rs
function main (line 16) | async fn main() {
Condensed preview — 17 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (28K chars).
[
{
"path": ".gitignore",
"chars": 12,
"preview": ".env\ntarget\n"
},
{
"path": "Cargo.toml",
"chars": 73,
"preview": "[package]\nname = \"raydium-sniper-bot\"\nversion = \"0.1.0\"\nedition = \"2021\"\n"
},
{
"path": "README.md",
"chars": 4047,
"preview": "# Solana Raydium Sniper Bot \nThis bot fetches to new Raydium pools and buys as soon as possible. If RPC or node is good,"
},
{
"path": "src/common/logger.rs",
"chars": 1436,
"preview": "use chrono::Local;\n\nconst LOG_LEVEL: &str = \"LOG\";\n\npub struct Logger {\n prefix: String,\n date_format: String,\n}\n\n"
},
{
"path": "src/common/mod.rs",
"chars": 31,
"preview": "pub mod logger;\npub mod utils;\n"
},
{
"path": "src/common/utils.rs",
"chars": 1344,
"preview": "use anyhow::Result;\nuse solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair};\nuse std::{env, sync::Arc}"
},
{
"path": "src/core/mod.rs",
"chars": 27,
"preview": "pub mod token;\npub mod tx;\n"
},
{
"path": "src/core/token.rs",
"chars": 2792,
"preview": "use solana_sdk::{pubkey::Pubkey, signature::Keypair};\nuse spl_token_2022::{\n extension::StateWithExtensionsOwned,\n "
},
{
"path": "src/core/tx.rs",
"chars": 3924,
"preview": "use std::{env, sync::Arc, time::Duration};\n\nuse anyhow::Result;\nuse jito_json_rpc_client::jsonrpc_client::rpc_client::Rp"
},
{
"path": "src/dex/mod.rs",
"chars": 66,
"preview": "pub mod pump_fun;\npub mod raydium;\npub mod meteora;\npub mod orca;\n"
},
{
"path": "src/dex/raydium.rs",
"chars": 11225,
"preview": "use crate::{\n common::{\n logger::Logger,\n utils::{import_env_var, SwapConfig},\n },\n core::{\n "
},
{
"path": "src/engine/mod.rs",
"chars": 31,
"preview": "pub mod monitor;\npub mod swap;\n"
},
{
"path": "src/engine/monitor/mod.rs",
"chars": 37,
"preview": "pub mod helius;\npub mod yellowstone;\n"
},
{
"path": "src/lib.rs",
"chars": 77,
"preview": "pub mod common;\npub mod core;\npub mod dex;\npub mod engine;\npub mod services;\n"
},
{
"path": "src/main.rs",
"chars": 1354,
"preview": "use dotenv::dotenv;\nuse raydium_pump_snipe_bot::{\n common::{\n logger::Logger,\n utils::{\n cre"
},
{
"path": "src/services/mod.rs",
"chars": 33,
"preview": "pub mod jito;\npub mod nextblock;\n"
},
{
"path": "trial/blacklist.txt",
"chars": 0,
"preview": ""
}
]
About this extraction
This page contains the full source code of the cutupdev/Solana-Raydium-Sniper-Bot GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 17 files (25.9 KB), approximately 7.2k tokens, and a symbol index with 35 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.