├── README.md └── sniper-jito.ts /README.md: -------------------------------------------------------------------------------- 1 | # Raydium Sniper Bot on Solana V2 2 | 3 | ## Overview 4 | 5 | Introducing a sophisticated Solana token sniper script designed for automated token acquisition on the Solana blockchain. Tailor its behavior with numerous configurable settings, optimizing your trading strategy. 6 | 7 | ## **Contact** 8 | - If you need help or interest, contact here: [Telegram](https://t.me/shiny0103) 9 | 10 | ## Getting Started 11 | 12 | 1. **RPC Configuration** 13 | 14 | - Configure your RPC endpoints with your provider credentials. Integrations with Shyft API are supported via API key. 15 | 16 | ```yaml 17 | RPC_WEBSOCKET_ENDPOINT: "wss://rpc.shyft.to?api_key=YOUR_API_KEY" 18 | RPC_ENDPOINT: "https://rpc.shyft.to?api_key=YOUR_API_KEY" 19 | ``` 20 | 21 | 2. **Wallet Integration** 22 | 23 | - Insert your wallet's secret key for seamless interaction. This key can typically be generated via wallet services or Telegram bots. 24 | 25 | ```yaml 26 | SNIPER_SECRET_KEY: 27 | ``` 28 | 29 | 3. **Purchase Configuration** 30 | 31 | - Fine-tune purchasing parameters to suit your trading strategy, including SOL allocation, transaction tips, and retry logic. 32 | 33 | ```yaml 34 | BUY_AMOUNT_SOL: 0.02 35 | JITO_TIP_AMOUNT: 0.005 36 | MIN_SOL_REQUIRED: 0.1 37 | MAX_BUY_RETRIES: 2 38 | BUY_DELAY: 0 39 | ``` 40 | 41 | 4. **Rug Pull Protection** 42 | 43 | - Customize filters to safeguard against potential rug pulls, setting criteria for liquidity and owner distribution. 44 | 45 | ```yaml 46 | MIN_SOL_LP: 6 47 | MAX_SOL_LP: 20 48 | MIN_TOKEN_LP_PERCENTAGE: 70 49 | MAX_TOP10_HOLDERS_PERCENTAGE: 30 50 | MAX_SINGLE_OWNER_PERCENTAGE: 10 51 | ``` 52 | 53 | 5. **Rug Check Activation** 54 | 55 | - Activate or deactivate specific rug check features tailored to your risk tolerance and operational needs. 56 | 57 | ```yaml 58 | ENABLE_RUG_CHECKS: true 59 | CHECK_MINTABLE_AND_FREEZABLE: true 60 | CHECK_TOP10_HOLDERS_PERCENTAGE: true 61 | CHECK_BURN: false 62 | CHECK_IF_SOCIALS: false 63 | ``` 64 | 65 | 6. **Sniper List Options** 66 | 67 | - Define sniper list preferences, adjust refresh intervals, and apply token symbol filters as necessary. 68 | 69 | ```yaml 70 | SNIPE_LIST_REFRESH_INTERVAL: 30000 71 | TOKEN_SYMBOL_FILTER: "BONK" 72 | 73 | USE_SNIPE_LIST: false 74 | CHECK_TOKEN_SYMBOL: false 75 | ``` 76 | 77 | 7. **Telegram Bot Configuration** 78 | - Set up a Telegram bot for autonomous token trading. Populate the relevant fields with your Telegram API credentials and bot details. 79 | ```yaml 80 | TG_API_ID: 81 | TG_API_HASH: 82 | TG_SESSION_ID: 83 | TG_BOT_USERNAME: "@hector_trojanbot" 84 | ``` 85 | 86 | Maximize your token acquisition efficiency on the Solana blockchain with this powerful sniping tool, meticulously designed to align with your strategic priorities and risk management protocols. 87 | -------------------------------------------------------------------------------- /sniper-jito.ts: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv"; 2 | import path from "path"; 3 | import { Connection, Keypair } from "@solana/web3.js"; 4 | import { LiquidityPoolKeysV4 } from "@raydium-io/raydium-sdk"; 5 | import { initializeConfigurations, setupSnipeListMonitoring, sleep, getTokenMetadataInfo } from "./utils"; 6 | import { logger, TOKEN_SYMBOL_FILTER, USE_PENDING_SNIPE_LIST, CHECK_TOKEN_SYMBOL } from "./constants"; 7 | import { extractMarketAndLpInfoFromLogs, getPoolKeysFromMarketId } from "./swapUtils"; 8 | 9 | dotenv.config(); 10 | 11 | let seenSignatures = new Set(); 12 | let pendingSnipeList: string[] = []; 13 | const tokenSymbolToSnipe = TOKEN_SYMBOL_FILTER.toLowerCase(); 14 | 15 | const monitorNewTokens = async (connection: Connection, sniperWallet: Keypair) => { 16 | try { 17 | await initializeConfigurations(); 18 | setupSnipeListMonitoring(pendingSnipeList, logger); 19 | logger.info(`Monitoring new Solana tokens...`); 20 | 21 | connection.onLogs("all", async ({ logs, err, signature }) => { 22 | if (err || seenSignatures.has(signature)) return; 23 | 24 | logger.info(`Found new token signature: ${signature}`); 25 | seenSignatures.add(signature); 26 | 27 | try { 28 | const parsedTransaction = await connection.getParsedTransaction(signature, { 29 | maxSupportedTransactionVersion: 0, 30 | commitment: "confirmed", 31 | }); 32 | 33 | if (!parsedTransaction || parsedTransaction.meta?.err) return; 34 | logger.info(`Parsed transaction for signature: ${signature}`); 35 | 36 | const lpInfo = extractMarketAndLpInfoFromLogs(logs); 37 | const poolKeys: LiquidityPoolKeysV4 | null = await getPoolKeysFromMarketId(lpInfo.marketId, connection); 38 | 39 | if (!poolKeys) { 40 | logger.error(`Unable to extract pool keys for signature: ${signature}`); 41 | return; 42 | } 43 | 44 | const poolOpenTime = parseInt(poolKeys.poolOpenTime.toString()); 45 | const currentTime = Math.floor(Date.now() / 1000); 46 | 47 | const isPendingPool = USE_PENDING_SNIPE_LIST && pendingSnipeList.includes(poolKeys.baseMint.toString()); 48 | 49 | if (!isPendingPool) { 50 | const tokenMetadata = await retrieveTokenMetadata(connection, poolKeys.baseMint.toString()); 51 | if (!tokenMetadata) return; 52 | 53 | const matchTokenSymbol = CHECK_TOKEN_SYMBOL && tokenMetadata.symbol.toLowerCase() === tokenSymbolToSnipe; 54 | if (!matchTokenSymbol) { 55 | logger.info(`Skipping token ${poolKeys.baseMint}. Symbol doesn't match filter.`); 56 | return; 57 | } 58 | } 59 | 60 | if (poolOpenTime > currentTime) { 61 | const delayMs = (poolOpenTime - currentTime) * 1000; 62 | logger.info(`Delaying transaction for ${delayMs / 1000} seconds until pool open time.`); 63 | await sleep(delayMs); 64 | } 65 | 66 | logger.info(`Executing actions for token ${poolKeys.baseMint}...`); 67 | // Additional logic to interact with the token can be added here 68 | 69 | } catch (error) { 70 | logger.error(`Error monitoring token: ${error.message}`, error); 71 | } 72 | }); 73 | } catch (error) { 74 | logger.error(`Critical error starting token monitoring: ${error.message}`, error); 75 | } 76 | }; 77 | 78 | const retrieveTokenMetadata = async (connection: Connection, baseMint: string) => { 79 | try { 80 | const tokenMetadata = await getTokenMetadataInfo(connection, baseMint); 81 | if (!tokenMetadata || !tokenMetadata.symbol) { 82 | logger.info(`Unable to retrieve metadata for token ${baseMint}. Skipping.`); 83 | return null; 84 | } 85 | return tokenMetadata; 86 | } catch (error) { 87 | logger.error(`Failed to retrieve token metadata: ${error.message}`); 88 | return null; 89 | } 90 | }; 91 | 92 | export default monitorNewTokens; 93 | --------------------------------------------------------------------------------