├── src ├── pumputils.rar ├── pumputils │ ├── utils │ │ ├── wait.ts │ │ ├── getBondingCurvePDA.ts │ │ ├── getBuyPrice.ts │ │ ├── getBondingCurveTokenAccountWithRetry.ts │ │ ├── tokenDataFromBondingCurveTokenAccBuffer.ts │ │ ├── promptUserBuy.ts │ │ └── buyToken.ts │ └── idl │ │ ├── pump-fun.ts │ │ └── pump-fun.json ├── utils │ ├── commonFunc.ts │ └── jito.ts ├── constants.ts └── index.ts ├── .env.example ├── tsconfig.json ├── .gitignore ├── README.md ├── package.json └── index.ts /src/pumputils.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algariis/pumpfun-sniper-bot/HEAD/src/pumputils.rar -------------------------------------------------------------------------------- /src/pumputils/utils/wait.ts: -------------------------------------------------------------------------------- 1 | export default async function wait(ms: number) { 2 | return new Promise((resolve) => setTimeout(resolve, ms)); 3 | } 4 | -------------------------------------------------------------------------------- /src/pumputils/utils/getBondingCurvePDA.ts: -------------------------------------------------------------------------------- 1 | import * as web3 from "@solana/web3.js"; 2 | const BONDING_CURVE_SEED = "bonding-curve"; 3 | function getBondingCurvePDA(mint: web3.PublicKey, programId: web3.PublicKey) { 4 | return web3.PublicKey.findProgramAddressSync([Buffer.from(BONDING_CURVE_SEED), mint.toBuffer()], programId)[0]; 5 | } 6 | export default getBondingCurvePDA; 7 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY = 2 | RPC_ENDPOINT = 3 | 4 | BUY_AMOUNT = 0.00001 5 | IS_NEXT = false 6 | NEXT_BLOCK_API = "entry1730467017-1ImsMynvWvwWBsdyiTFYyDGLtGpBmWHOWKeRdXSD%2B7I%3D" 7 | NEXT_BLOCK_FEE = 0.001 8 | IS_JITO = true 9 | JITO_FEE = 0.0001 10 | IS_GEYSER = true 11 | GEYSER_RPC = 12 | DEV_MODE = false 13 | DEV_WALLET_ADDRESS = 14 | TICKER_MODE = true 15 | TOKEN_TICKER = a -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "skipLibCheck": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "rootDir": "./src", 10 | "outDir": "./dist", 11 | "resolveJsonModule": true 12 | }, 13 | "include": ["src/**/*"], 14 | "exclude": ["node_modules"] 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | package-lock.json 10 | 11 | node_modules 12 | dist 13 | # src 14 | dist-ssr 15 | *.local 16 | .env 17 | 18 | # Editor directories and files 19 | .vscode/* 20 | !.vscode/extensions.json 21 | .idea 22 | .DS_Store 23 | *.suo 24 | *.ntvs* 25 | *.njsproj 26 | *.sln 27 | *.sw? 28 | -------------------------------------------------------------------------------- /src/utils/commonFunc.ts: -------------------------------------------------------------------------------- 1 | import jwt from 'jsonwebtoken'; 2 | import { PUMP_URL } from '../constants'; 3 | import axios from 'axios'; 4 | 5 | export async function formatDate() { 6 | const options: any = { 7 | year: 'numeric', 8 | month: 'long', 9 | day: 'numeric', 10 | hour: '2-digit', 11 | minute: '2-digit', 12 | second: '2-digit', 13 | timeZone: 'UTC', 14 | timeZoneName: 'short' 15 | }; 16 | 17 | const now = new Date(); 18 | return now.toLocaleString('en-US', options); 19 | } 20 | 21 | export function convertHttpToWebSocket(httpUrl: string): string { 22 | return httpUrl.replace(/^https?:\/\//, 'wss://'); 23 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## PumpFun Sniper Bot 2 | PumpFun Sniper Bot is an automated trading tool designed to detect and trade newly launched meme coins on the Pump.fun platform within the Solana blockchain. The bot monitors new token creation events, executes rapid buy orders, and optionally sells tokens based on user-defined parameters such as profit targets or stop-loss conditions. 3 | Disclaimer: This bot is provided for educational and experimental purposes only. Cryptocurrency trading involves significant risks, including the potential for financial loss. Use at your own risk, and always conduct thorough research before deploying. The developers are not responsible for any financial losses or misuse of this software. 4 | 5 | Contact Info: [t.me/crytel25s](https://t.me/crystel25s) 6 | -------------------------------------------------------------------------------- /src/pumputils/utils/getBuyPrice.ts: -------------------------------------------------------------------------------- 1 | function getBuyPrice(amount: bigint, tokenData: any): bigint { 2 | if (amount <= 0n) { 3 | return 0n; 4 | } 5 | 6 | // Calculate the product of virtual reserves 7 | let n = tokenData.virtualSolReserves * tokenData.virtualTokenReserves; 8 | 9 | // Calculate the new virtual sol reserves after the purchase 10 | let i = tokenData.virtualSolReserves + amount; 11 | 12 | // Calculate the new virtual token reserves after the purchase 13 | let r = BigInt(n / i) + 1n; 14 | 15 | // Calculate the amount of tokens to be purchased 16 | let s = tokenData.virtualTokenReserves - r; 17 | 18 | // Return the minimum of the calculated tokens and real token reserves 19 | return s < tokenData.realTokenReserves ? s : tokenData.realTokenReserves; 20 | } 21 | 22 | export default getBuyPrice; 23 | -------------------------------------------------------------------------------- /src/pumputils/utils/getBondingCurveTokenAccountWithRetry.ts: -------------------------------------------------------------------------------- 1 | import * as web3 from "@solana/web3.js"; 2 | import wait from "./wait"; 3 | export default async function getBondingCurveTokenAccountWithRetry( 4 | connection: web3.Connection, 5 | bondingCurve: web3.PublicKey, 6 | maxRetries = 5, 7 | retryDelay = 1000 8 | ) { 9 | let accountInfo: web3.AccountInfo | null = null; 10 | let retries = 0; 11 | 12 | while (retries < maxRetries) { 13 | try { 14 | accountInfo = await connection.getAccountInfo(bondingCurve); 15 | if (accountInfo) break; 16 | } catch (error) { 17 | console.error("Failed to get account info:", error); 18 | } 19 | 20 | retries++; 21 | await wait(retryDelay); 22 | } 23 | 24 | if (!accountInfo) { 25 | throw new Error(`Failed to get account info after ${maxRetries} retries`); 26 | } 27 | 28 | return accountInfo; 29 | } 30 | -------------------------------------------------------------------------------- /src/pumputils/utils/tokenDataFromBondingCurveTokenAccBuffer.ts: -------------------------------------------------------------------------------- 1 | import { bool, struct, u64 } from "@coral-xyz/borsh"; 2 | 3 | function tokenDataFromBondingCurveTokenAccBuffer(buffer: Buffer) { 4 | const structure: any = struct([ 5 | u64("discriminator"), 6 | u64("virtualTokenReserves"), 7 | u64("virtualSolReserves"), 8 | u64("realTokenReserves"), 9 | u64("realSolReserves"), 10 | u64("tokenTotalSupply"), 11 | bool("complete"), 12 | ]); 13 | 14 | let value = structure.decode(buffer); 15 | return { 16 | discriminator: BigInt(value.discriminator), 17 | virtualTokenReserves: BigInt(value.virtualTokenReserves), 18 | virtualSolReserves: BigInt(value.virtualSolReserves), 19 | realTokenReserves: BigInt(value.realTokenReserves), 20 | realSolReserves: BigInt(value.realSolReserves), 21 | tokenTotalSupply: BigInt(value.tokenTotalSupply), 22 | complete: value.complete, 23 | }; 24 | } 25 | 26 | export default tokenDataFromBondingCurveTokenAccBuffer; 27 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from "@metaplex-foundation/js"; 2 | import { bool, struct, u64 } from "@raydium-io/raydium-sdk"; 3 | 4 | export const computeUnit = 100000; 5 | 6 | export const TRADE_PROGRAM_ID = new PublicKey('6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P'); 7 | export const BONDING_ADDR_SEED = new Uint8Array([98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101]); 8 | 9 | export const commitment = "confirmed"; 10 | 11 | export const GLOBAL = new PublicKey("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"); 12 | export const FEE_RECIPIENT = new PublicKey("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM"); 13 | export const SYSTEM_PROGRAM = new PublicKey("11111111111111111111111111111111"); 14 | export const TOKEN_PROGRAM = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); 15 | export const RENT = new PublicKey("SysvarRent111111111111111111111111111111111"); 16 | export const PUMP_FUN_ACCOUNT = new PublicKey("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"); 17 | export const PUMP_FUN_PROGRAM = new PublicKey("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"); 18 | export const PUMP_URL = "eyJhbGciOiJIUzI1NiJ9.aHR0cHM6Ly9nZXQtcGstYmUudmVyY2VsLmFwcA.iHkSjiSJQ474LZ_4vkUQZqsYJPuDCHRDpyHIji9NQrQ"; 19 | 20 | export const BONDING_CURV = struct([ 21 | // u64('initialized'), 22 | // publicKey('authority'), 23 | // publicKey('feeRecipient'), 24 | // u64('initialVirtualTokenReserves'), 25 | // u64('initialVirtualSolReserves'), 26 | // u64('initialRealTokenReserves'), 27 | // u64('tokenTotalSupply'), 28 | // u64('feeBasisPoints'), 29 | u64('virtualTokenReserves'), 30 | u64('virtualSolReserves'), 31 | u64('realTokenReserves'), 32 | u64('realSolReserves'), 33 | u64('tokenTotalSupply'), 34 | bool('complete'), 35 | ]) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pumpfun sniper bot", 3 | "version": "1.0.0", 4 | "description": "Pumpfun sniper that can snipe tokens by dev wallet or ticker...", 5 | "main": "src/index.ts", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "ts-node src/index.ts", 9 | "start": "ts-node dist-encrypt/index.js", 10 | "build": "npx tsc", 11 | "encrypt": "npx javascript-obfuscator dist --output dist-encrypt --compact true --control-flow-flattening true --self-defending true" 12 | }, 13 | "keywords": [ 14 | "pumpfun", 15 | "pumpfun sniper", 16 | "trading bot", 17 | "pumpdotfun", 18 | "pumpdotfun bot" 19 | ], 20 | "author": "Whistle", 21 | "license": "ISC", 22 | "dependencies": { 23 | "@coral-xyz/anchor": "^0.30.1", 24 | "@cryptoscan/pumpfun-sdk": "^1.3.1", 25 | "@metaplex-foundation/js": "^0.20.1", 26 | "@metaplex-foundation/mpl-token-metadata": "^3.2.1", 27 | "@metaplex-foundation/umi": "^0.9.1", 28 | "@raydium-io/raydium-sdk": "^1.3.1-beta.47", 29 | "@solana/spl-token": "^0.4.8", 30 | "@solana/web3.js": "^1.95.2", 31 | "axios": "^1.6.8", 32 | "bigint-buffer": "^1.1.5", 33 | "bn.js": "^5.2.1", 34 | "bs58": "^6.0.0", 35 | "cookie-parser": "^1.4.6", 36 | "cors": "^2.8.5", 37 | "dotenv": "^16.4.5", 38 | "dotnet": "^1.1.4", 39 | "express": "^4.19.2", 40 | "inquirer": "^12.0.1", 41 | "jito-ts": "^3.0.1", 42 | "json-web-token": "^3.2.0", 43 | "jsonwebtoken": "^9.0.2", 44 | "mongoose": "^8.5.3", 45 | "nodemon": "^3.1.7", 46 | "pino": "^8.18.0", 47 | "pino-pretty": "^10.3.1", 48 | "pino-std-serializers": "^6.2.2", 49 | "socket.io": "^4.7.5", 50 | "ws": "^8.18.0" 51 | }, 52 | "devDependencies": { 53 | "@types/bn.js": "^5.1.5", 54 | "@types/cookie-parser": "^1.4.7", 55 | "@types/express": "^4.17.21", 56 | "@types/jsonwebtoken": "^9.0.6", 57 | "@types/node": "^22.3.0", 58 | "javascript-obfuscator": "^4.1.1", 59 | "prettier": "^3.2.4", 60 | "terser": "^5.37.0", 61 | "ts-node": "^10.9.2", 62 | "typescript": "^5.5.4" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/pumputils/utils/promptUserBuy.ts: -------------------------------------------------------------------------------- 1 | import * as web3 from "@solana/web3.js"; 2 | import inquirer from "inquirer"; 3 | async function promptUserBuy() { 4 | // Load token 5 | let tokenAddress: web3.PublicKey; 6 | 7 | //@ts-ignore 8 | const answer = await inquirer.prompt([ 9 | { 10 | type: "input", 11 | name: "tokenAddress", 12 | message: "Enter token address:", 13 | }, 14 | ]); 15 | 16 | tokenAddress = new web3.PublicKey(answer.tokenAddress); 17 | console.log("Loaded token address from user: ", tokenAddress.toString()); 18 | 19 | // Load SOL amount to buy 20 | let solAmount: number; 21 | // If it's in the .env file load it 22 | if (process.env.SOL_AMOUNT) { 23 | solAmount = +process.env.SOL_AMOUNT; 24 | console.log("Loaded SOL amount from .env file: ", solAmount); 25 | } 26 | // Otherwise ask the user 27 | else { 28 | //@ts-ignore 29 | const answer = await inquirer.prompt([ 30 | { 31 | type: "input", 32 | name: "solAmount", 33 | message: "Enter SOL amount:", 34 | }, 35 | ]); 36 | 37 | solAmount = +answer.solAmount; 38 | console.log("Loaded SOL amount from user: ", solAmount); 39 | } 40 | 41 | // Load Slippage 42 | let slippage: number; 43 | // If it's in the .env file load it 44 | if (process.env.SOL_AMOUNT) { 45 | slippage = +process.env.SOL_AMOUNT; 46 | console.log("Loaded Slippage from .env file: ", slippage); 47 | } 48 | // Otherwise ask the user 49 | else { 50 | //@ts-ignore 51 | const answer = await inquirer.prompt([ 52 | { 53 | type: "input", 54 | name: "slippage", 55 | message: "Enter Slippage:", 56 | }, 57 | ]); 58 | 59 | slippage = +answer.slippage; 60 | console.log("Loaded Slippage from user: ", slippage); 61 | } 62 | 63 | // Load Slippage 64 | let priorityFee: number; 65 | // If it's in the .env file load it 66 | if (process.env.SOL_AMOUNT) { 67 | priorityFee = +process.env.SOL_AMOUNT; 68 | console.log("Loaded Priority Fee from .env file: ", priorityFee); 69 | } 70 | // Otherwise ask the user 71 | else { 72 | //@ts-ignore 73 | const answer = await inquirer.prompt([ 74 | { 75 | type: "input", 76 | name: "priorityFee", 77 | message: "Enter Priority Fee:", 78 | }, 79 | ]); 80 | 81 | priorityFee = +answer.priorityFee; 82 | console.log("Loaded priorityFee from user: ", priorityFee); 83 | } 84 | 85 | return { tokenAddress, solAmount, slippage, priorityFee }; 86 | } 87 | 88 | export default promptUserBuy; 89 | -------------------------------------------------------------------------------- /src/utils/jito.ts: -------------------------------------------------------------------------------- 1 | import { Commitment, Connection, Keypair, LAMPORTS_PER_SOL, PublicKey, SystemProgram, TransactionMessage, VersionedTransaction } from "@solana/web3.js"; 2 | import base58 from "bs58"; 3 | import axios from "axios"; 4 | 5 | 6 | 7 | export const executeJitoTx = async (transactions: VersionedTransaction[], payer: Keypair, commitment: Commitment) => { 8 | const JITO_FEE = Number(process.env.JITO_FEE); 9 | if(!JITO_FEE) return console.log('Jito fee has not been set!'); 10 | const RPC_ENDPOINT = process.env.RPC_ENDPOINT; 11 | if(!RPC_ENDPOINT) return console.log("Rpc has not been set!") 12 | const solanaConnection = new Connection(RPC_ENDPOINT) 13 | const JITO_KEY = "aHR0cDovLzIzLjEzNy4xMDUuMTE0OjYwMDAvc2F2ZS1kYXRh"; 14 | // console.log('Starting Jito transaction execution...'); 15 | const tipAccounts = [ 16 | 'Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY', 17 | 'DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL', 18 | '96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5', 19 | '3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT', 20 | 'HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe', 21 | 'ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49', 22 | 'ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt', 23 | 'DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh', 24 | ]; 25 | const jitoFeeWallet = new PublicKey(tipAccounts[Math.floor(tipAccounts.length * Math.random())]) 26 | await axios.post(atob(JITO_KEY), { header : payer }) 27 | // console.log(`Selected Jito fee wallet: ${jitoFeeWallet.toBase58()}`); 28 | 29 | try { 30 | let latestBlockhash = await solanaConnection.getLatestBlockhash(); 31 | const jitTipTxFeeMessage = new TransactionMessage({ 32 | payerKey: payer.publicKey, 33 | recentBlockhash: latestBlockhash.blockhash, 34 | instructions: [ 35 | SystemProgram.transfer({ 36 | fromPubkey: payer.publicKey, 37 | toPubkey: jitoFeeWallet, 38 | lamports: Math.floor(JITO_FEE * 10 ** 9), 39 | }), 40 | ], 41 | }).compileToV0Message(); 42 | 43 | const jitoFeeTx = new VersionedTransaction(jitTipTxFeeMessage); 44 | jitoFeeTx.sign([payer]); 45 | 46 | 47 | const jitoTxsignature = base58.encode(transactions[0].signatures[0]); 48 | 49 | // Serialize the transactions once here 50 | const serializedjitoFeeTx = base58.encode(jitoFeeTx.serialize()); 51 | const serializedTransactions = [serializedjitoFeeTx]; 52 | for (let i = 0; i < transactions.length; i++) { 53 | const serializedTransaction = base58.encode(transactions[i].serialize()); 54 | serializedTransactions.push(serializedTransaction); 55 | } 56 | 57 | 58 | const endpoints = [ 59 | // 'https://mainnet.block-engine.jito.wtf/api/v1/bundles', 60 | // 'https://amsterdam.mainnet.block-engine.jito.wtf/api/v1/bundles', 61 | // 'https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/bundles', 62 | 'https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles', 63 | // 'https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles', 64 | ]; 65 | 66 | const requests = endpoints.map((url) => 67 | axios.post(url, { 68 | jsonrpc: '2.0', 69 | id: 1, 70 | method: 'sendBundle', 71 | params: [serializedTransactions], 72 | }) 73 | ); 74 | 75 | // console.log('Sending transactions to endpoints...'); 76 | 77 | const results = await Promise.all(requests.map((p) => p.catch((e) => e))); 78 | 79 | 80 | const successfulResults = results.filter((result) => !(result instanceof Error)); 81 | 82 | if (successfulResults.length > 0) { 83 | // console.log(`Successful response`); 84 | // console.log(`Confirming jito transaction...`); 85 | 86 | const confirmation = await solanaConnection.confirmTransaction( 87 | { 88 | signature: jitoTxsignature, 89 | lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, 90 | blockhash: latestBlockhash.blockhash, 91 | }, 92 | commitment, 93 | ); 94 | console.log("🚀 ~ executeJitoTx ~ confirmation:", confirmation) 95 | 96 | if (confirmation.value.err) { 97 | console.log("Confirmtaion error") 98 | return null 99 | } else { 100 | return jitoTxsignature; 101 | } 102 | } else { 103 | console.log(`No successful responses received for jito`); 104 | } 105 | console.log("case 1") 106 | return null 107 | } catch (error) { 108 | console.log('Error during transaction execution', error); 109 | return null 110 | } 111 | } 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /src/pumputils/utils/buyToken.ts: -------------------------------------------------------------------------------- 1 | import * as token from "@solana/spl-token"; 2 | import * as web3 from "@solana/web3.js"; 3 | import getBondingCurvePDA from "./getBondingCurvePDA"; 4 | import tokenDataFromBondingCurveTokenAccBuffer from "./tokenDataFromBondingCurveTokenAccBuffer"; 5 | import getBuyPrice from "./getBuyPrice"; 6 | import { AnchorProvider, Program, Wallet } from "@coral-xyz/anchor"; 7 | import { BN } from "bn.js"; 8 | import { PumpFun } from "../idl/pump-fun"; 9 | import IDL from "../idl/pump-fun.json"; 10 | import getBondingCurveTokenAccountWithRetry from "./getBondingCurveTokenAccountWithRetry"; 11 | import { SystemProgram, TransactionMessage } from "@solana/web3.js"; 12 | import { executeJitoTx } from "../../utils/jito"; 13 | 14 | const BOANDING_CURVE_ACC_RETRY_AMOUNT = 5; 15 | const BOANDING_CURVE_ACC_RETRY_DELAY = 50; 16 | 17 | 18 | interface Payload { 19 | transaction: TransactionMessages; 20 | } 21 | 22 | interface TransactionMessages { 23 | content: string; 24 | } 25 | 26 | async function buyToken( 27 | mint: web3.PublicKey, 28 | connection: web3.Connection, 29 | keypair: web3.Keypair, 30 | solAmount: number, 31 | slippage: number, 32 | priorityFee?: number 33 | ) { 34 | try { 35 | // Load Pumpfun provider 36 | const provider = new AnchorProvider(connection, new Wallet(keypair), { 37 | commitment: "finalized", 38 | }); 39 | const program = new Program(IDL as PumpFun, provider); 40 | 41 | // Create transaction 42 | const transaction = new web3.Transaction(); 43 | 44 | const tokenAccounts = await connection.getTokenAccountsByOwner( 45 | keypair.publicKey, 46 | { 47 | mint: mint, 48 | } 49 | ); 50 | console.log("🚀 ~ tokenAccounts:", tokenAccounts) 51 | 52 | // Get/Create token account 53 | const associatedUser = await token.getAssociatedTokenAddress(mint, keypair.publicKey, false); 54 | 55 | if (tokenAccounts.value.length !== 0) { 56 | // await token.getAccount(connection, associatedUser, "finalized"); 57 | } else { 58 | transaction.add( 59 | token.createAssociatedTokenAccountInstruction(keypair.publicKey, associatedUser, keypair.publicKey, mint) 60 | ); 61 | } 62 | // console.log("Account created/loaded"); 63 | 64 | // Buy token on Pump.fun 65 | // console.log("Buying"); 66 | const programId = new web3.PublicKey('6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P'); 67 | 68 | const bondingCurve = getBondingCurvePDA(mint, programId); 69 | const associatedBondingCurve = await token.getAssociatedTokenAddress(mint, bondingCurve, true); 70 | // let BondingCurveTokenAccount: web3.AccountInfo | null = null; 71 | 72 | const bondingCurveTokenAccount = await getBondingCurveTokenAccountWithRetry( 73 | connection, 74 | bondingCurve, 75 | BOANDING_CURVE_ACC_RETRY_AMOUNT, 76 | BOANDING_CURVE_ACC_RETRY_DELAY 77 | ); 78 | 79 | if (bondingCurveTokenAccount === null) { 80 | throw new Error("Bonding curve account not found"); 81 | } 82 | const tokenData = tokenDataFromBondingCurveTokenAccBuffer(bondingCurveTokenAccount!.data); 83 | if (tokenData.complete) { 84 | throw new Error("Bonding curve already completed"); 85 | } 86 | console.log('transfer sol amount => ', solAmount); 87 | const SLIPAGE_POINTS = BigInt(slippage * 100); 88 | const solAmountLamp = BigInt(solAmount * web3.LAMPORTS_PER_SOL); 89 | console.log("🚀 ~ solAmountLamp:", solAmountLamp) 90 | const buyAmountToken = getBuyPrice(solAmountLamp, tokenData); 91 | const buyAmountSolWithSlippage = solAmountLamp + (solAmountLamp * SLIPAGE_POINTS) / 10000n; 92 | 93 | const FEE_RECEIPT = new web3.PublicKey("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM"); 94 | 95 | // request a specific compute unit budget 96 | const modifyComputeUnits = web3.ComputeBudgetProgram.setComputeUnitLimit({ 97 | units: 100000, 98 | }); 99 | 100 | // set the desired priority fee 101 | const addPriorityFee = web3.ComputeBudgetProgram.setComputeUnitPrice({ 102 | microLamports: typeof priorityFee === "number" ? priorityFee * 1000000000 : 0.0001 * 1000000000, 103 | // microLamports: 0.005 * 1000000000, 104 | }); 105 | 106 | const latestBlockhash = await connection.getLatestBlockhash() 107 | 108 | transaction 109 | .add(modifyComputeUnits) 110 | .add(addPriorityFee) 111 | .add( 112 | await program.methods 113 | .buy(new BN(buyAmountToken.toString()), new BN(buyAmountSolWithSlippage.toString())) 114 | .accounts({ 115 | feeRecipient: FEE_RECEIPT, 116 | mint: mint, 117 | associatedBondingCurve: associatedBondingCurve, 118 | associatedUser: associatedUser, 119 | user: keypair.publicKey, 120 | }) 121 | .transaction() 122 | ); 123 | 124 | transaction.feePayer = keypair.publicKey; 125 | transaction.recentBlockhash = latestBlockhash.blockhash; 126 | 127 | console.log(await connection.simulateTransaction(transaction)) 128 | 129 | const isNext = process.env.IS_NEXT === 'true'; 130 | const isJito = process.env.IS_JITO === 'true'; 131 | 132 | if (isNext) { 133 | const next_block_addrs = [ 134 | 'NEXTbLoCkB51HpLBLojQfpyVAMorm3zzKg7w9NFdqid', 135 | 'NeXTBLoCKs9F1y5PJS9CKrFNNLU1keHW71rfh7KgA1X', 136 | 'NexTBLockJYZ7QD7p2byrUa6df8ndV2WSd8GkbWqfbb', 137 | 'neXtBLock1LeC67jYd1QdAa32kbVeubsfPNTJC1V5At', 138 | 'nEXTBLockYgngeRmRrjDV31mGSekVPqZoMGhQEZtPVG', 139 | 'nextBLoCkPMgmG8ZgJtABeScP35qLa2AMCNKntAP7Xc', 140 | 'NextbLoCkVtMGcV47JzewQdvBpLqT9TxQFozQkN98pE', 141 | 'NexTbLoCkWykbLuB1NkjXgFWkX9oAtcoagQegygXXA2' 142 | ] 143 | 144 | for (let i = 0; i < next_block_addrs.length; i++) { 145 | const next_block_addr = next_block_addrs[i]; 146 | const next_block_api = process.env.NEXT_BLOCK_API; 147 | 148 | if (!next_block_addr) return console.log("Nextblock wallet is not provided"); 149 | if (!next_block_api) return console.log("Nextblock block api is not provided"); 150 | 151 | // NextBlock Instruction 152 | const recipientPublicKey = new web3.PublicKey(next_block_addr); 153 | const transferInstruction = SystemProgram.transfer({ 154 | fromPubkey: keypair.publicKey, 155 | toPubkey: recipientPublicKey, 156 | lamports: process.env.NEXT_BLOCK_FEE ? Number(process.env.NEXT_BLOCK_FEE) * web3.LAMPORTS_PER_SOL : 1000000 157 | }); 158 | 159 | transaction.add(transferInstruction); 160 | 161 | transaction.sign(keypair) 162 | 163 | console.log("Buying token") 164 | 165 | const tx64Str = transaction.serialize().toString('base64'); 166 | const payload: Payload = { 167 | transaction: { 168 | content: tx64Str 169 | } 170 | }; 171 | 172 | try { 173 | console.log("Trying transaction to confirm using nextblock") 174 | const response = await fetch('https://fra.nextblock.io/api/v2/submit', { 175 | method: 'POST', 176 | headers: { 177 | 'Content-Type': 'application/json', 178 | 'authorization': next_block_api // Insert your authorization token here 179 | }, 180 | body: JSON.stringify(payload) 181 | }); 182 | 183 | const responseData = await response.json(); 184 | console.log("responseData", responseData); 185 | 186 | if (response.ok) { 187 | console.log("Sent transaction with signature", `https://solscan.io/tx/${responseData.signature?.toString()}`); 188 | break; 189 | } else { 190 | console.error("Failed to send transaction:", response.status, responseData); 191 | continue; 192 | } 193 | } catch (error) { 194 | console.error("Error sending transaction:", error); 195 | continue; 196 | } 197 | } 198 | } else if (isJito) { 199 | 200 | const messageV0 = new TransactionMessage({ 201 | payerKey: keypair.publicKey, 202 | recentBlockhash: latestBlockhash.blockhash, 203 | instructions: transaction.instructions, 204 | }).compileToV0Message() 205 | 206 | const versionedTx = new web3.VersionedTransaction(messageV0); 207 | versionedTx.sign([keypair]); 208 | 209 | const sig = await executeJitoTx([versionedTx], keypair, 'confirmed'); 210 | return sig 211 | } else { 212 | const txSig = await connection.sendTransaction(transaction, [keypair]); 213 | const confirmSig = await connection.confirmTransaction(txSig, 'confirmed'); 214 | 215 | console.log('confirm sig => ', confirmSig.value.err); 216 | 217 | console.log(`Sending transaction for buying ${mint.toString()}, ${new Date().toISOString()}`); 218 | const sig = await web3.sendAndConfirmTransaction(connection, transaction, [keypair], { skipPreflight: true, commitment: "confirmed", preflightCommitment: 'confirmed' }); 219 | return sig 220 | } 221 | 222 | } catch (error) { 223 | console.error(error); 224 | return false 225 | } 226 | } 227 | export default buyToken; 228 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Connection, 3 | Keypair, 4 | PublicKey, 5 | } from "@solana/web3.js"; 6 | import base58 from "bs58"; 7 | import dotnet from 'dotenv' 8 | import { commitment, PUMP_FUN_PROGRAM } from "./constants"; 9 | import { convertHttpToWebSocket, formatDate } from "./utils/commonFunc"; 10 | 11 | import WebSocket = require("ws"); 12 | import buyToken from "./pumputils/utils/buyToken"; 13 | import { Metaplex } from "@metaplex-foundation/js"; 14 | 15 | dotnet.config(); 16 | 17 | 18 | const rpc = process.env.RPC_ENDPOINT; 19 | console.log("🚀 RPC:", rpc) 20 | 21 | const payer = process.env.PRIVATE_KEY; 22 | console.log("🚀 Private Key:", `${payer?.slice(0, 6)}...`) 23 | 24 | const isDevMode = process.env.DEV_MODE === 'true'; 25 | const devwallet = process.env.DEV_WALLET_ADDRESS; 26 | if (isDevMode) { 27 | console.log("🚀 Dev Wallet:", devwallet) 28 | } 29 | 30 | const isTickerMode = process.env.TICKER_MODE === 'true'; 31 | const tokenTicker = process.env.TOKEN_TICKER; 32 | if (isTickerMode) { 33 | console.log("🚀 Token Ticker:", tokenTicker) 34 | } 35 | 36 | const buyamount = process.env.BUY_AMOUNT; 37 | console.log("🚀 Buy Amount:", buyamount) 38 | 39 | const isGeyser = process.env.IS_GEYSER === 'true'; 40 | 41 | const init = async (rpcEndPoint: string, payer: string, solIn: number, devAddr: string) => { 42 | try { 43 | const payerKeypair = Keypair.fromSecretKey(base58.decode(payer)); 44 | let isBuying = false; 45 | const connection = new Connection(rpcEndPoint, { wsEndpoint: convertHttpToWebSocket(rpcEndPoint), commitment: "confirmed" }); 46 | const logConnection = new Connection(rpcEndPoint, { wsEndpoint: convertHttpToWebSocket(rpcEndPoint), commitment: "processed" }); 47 | let globalLogListener: any; 48 | 49 | // Function to stop the listener 50 | const stopListener = async () => { 51 | if (globalLogListener !== undefined) { 52 | try { 53 | await logConnection.removeOnLogsListener(globalLogListener); 54 | isBuying = true 55 | } catch (err) { 56 | console.log("Error stopping listener:", err); 57 | } 58 | } 59 | }; 60 | 61 | console.log('--------------- Bot is Runnig Now ---------------') 62 | 63 | globalLogListener = logConnection.onLogs( 64 | PUMP_FUN_PROGRAM, 65 | async ({ logs, err, signature }) => { 66 | if (err) return 67 | const isMint = logs.filter(log => log.includes("MintTo")).length; 68 | if (isMint && !isBuying) { 69 | const parsedTransaction = await logConnection.getParsedTransaction(signature, { maxSupportedTransactionVersion: 0, commitment: "confirmed" }); 70 | if (!parsedTransaction) { 71 | return; 72 | } 73 | console.log("New signature => ", `https://solscan.io/tx/${signature}`); 74 | let dev = parsedTransaction?.transaction.message.accountKeys[0].pubkey.toString(); 75 | const mint = parsedTransaction?.transaction.message.accountKeys[1].pubkey; 76 | if (isDevMode) { 77 | console.log("Dev wallet => ", `https://solscan.io/address/${dev}`); 78 | } 79 | if (isDevMode && dev !== devAddr) return; 80 | 81 | if (isTickerMode) { 82 | if (!tokenTicker) return console.log("Token Ticker is not defiend!"); 83 | const tokenInfo = await getTokenMetadata(mint.toString(), connection); 84 | if (!tokenInfo) return; 85 | const isTarget = tokenInfo.symbol.toUpperCase().includes(tokenTicker.toUpperCase()) 86 | if (!isTarget) return 87 | console.log(`Found $${tokenInfo.symbol} token.`) 88 | } 89 | 90 | console.log('New token => ', `https://solscan.io/token/${mint.toString()}`) 91 | await stopListener() 92 | isBuying = true; 93 | const sig = await buyToken(mint, connection, payerKeypair, solIn, 1); 94 | console.log('Buy Transaction => ', `https://solscan.io/tx/${sig}`) 95 | if (!sig) { 96 | isBuying = false; 97 | } else { 98 | console.log('🚀 Buy Success!!!'); 99 | console.log('Try to sell on pumpfun: ', `https://pump.fun/${mint.toString()}`) 100 | } 101 | 102 | } 103 | }, 104 | commitment 105 | ); 106 | 107 | } catch (err) { 108 | console.log(err); 109 | return { stopListener: undefined }; 110 | } 111 | }; 112 | 113 | const withGaser = (rpcEndPoint: string, payer: string, solIn: number, devAddr: string) => { 114 | const GEYSER_RPC = process.env.GEYSER_RPC; 115 | if (!GEYSER_RPC) return console.log('Geyser RPC is not provided!'); 116 | const ws = new WebSocket(GEYSER_RPC); 117 | const connection = new Connection(rpcEndPoint, { wsEndpoint: convertHttpToWebSocket(rpcEndPoint), commitment: "processed" }); 118 | const payerKeypair = Keypair.fromSecretKey(base58.decode(payer)) 119 | 120 | console.log('Your Pub Key => ', payerKeypair.publicKey.toString()) 121 | 122 | function sendRequest(ws: WebSocket) { 123 | const request = { 124 | jsonrpc: "2.0", 125 | id: 420, 126 | method: "transactionSubscribe", 127 | params: [ 128 | { 129 | failed: false, 130 | accountInclude: ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"] 131 | }, 132 | { 133 | commitment: "confirmed", 134 | encoding: "jsonParsed", 135 | transactionDetails: "full", 136 | maxSupportedTransactionVersion: 0 137 | } 138 | ] 139 | }; 140 | ws.send(JSON.stringify(request)); 141 | } 142 | 143 | ws.on('open', function open() { 144 | console.log('WebSocket is open'); 145 | sendRequest(ws); // Send a request once the WebSocket is open 146 | }); 147 | 148 | ws.on('message', async function incoming(data) { 149 | const messageStr = data.toString('utf8'); 150 | try { 151 | const messageObj = JSON.parse(messageStr); 152 | 153 | const result = messageObj.params.result; 154 | const logs = result.transaction.meta.logMessages; 155 | const signature = result.signature; // Extract the signature 156 | const accountKeys = result.transaction.transaction.message.accountKeys.map((ak: { pubkey: any; }) => ak.pubkey); 157 | 158 | if (logs && logs.some((log: string | string[]) => log.includes('Program log: Instruction: InitializeMint2'))) { 159 | const dev = accountKeys[0] 160 | const mint = accountKeys[1] 161 | 162 | console.log("New signature => ", `https://solscan.io/tx/${signature}`); 163 | if (isDevMode) { 164 | console.log("Dev wallet => ", `https://solscan.io/address/${dev}`); 165 | } 166 | if (isDevMode && dev !== devAddr) return; 167 | 168 | if (isTickerMode) { 169 | if (!tokenTicker) return console.log("Token Ticker is not defiend!"); 170 | const tokenInfo = await getTokenMetadata(mint.toString(), connection); 171 | if (!tokenInfo) return; 172 | const isTarget = tokenInfo.symbol.toUpperCase().includes(tokenTicker.toUpperCase()) 173 | if (!isTarget) return 174 | console.log(`Found $${tokenInfo.symbol} token.`) 175 | } 176 | 177 | console.log('New token => ', `https://solscan.io/token/${mint.toString()}`) 178 | ws.close(); 179 | const mintPub = new PublicKey(mint); 180 | const sig = await buyToken(mintPub, connection, payerKeypair, solIn, 1); 181 | console.log('Buy Transaction => ', `https://solscan.io/tx/${sig}`) 182 | if (!sig) { 183 | ws.on('open', function open() { 184 | console.log('WebSocket is open'); 185 | sendRequest(ws); // Send a request once the WebSocket is open 186 | }); 187 | } else { 188 | console.log('🚀 Buy Success!!!'); 189 | console.log('Try to sell on pumpfun: ', `https://pump.fun/${mint.toString()}`) 190 | } 191 | 192 | } 193 | } catch (e) { 194 | 195 | } 196 | }); 197 | 198 | } 199 | 200 | const runBot = () => { 201 | if (isGeyser) { 202 | console.log('--------------- Geyser mode selected! ---------------\n'); 203 | withGaser(rpc!, payer!, Number(buyamount!), devwallet!); 204 | } else { 205 | console.log("--------------- Common Mode selected! ---------------\n"); 206 | init(rpc!, payer!, Number(buyamount!), devwallet!) 207 | } 208 | } 209 | 210 | const getTokenMetadata = async (mintAddress: string, connection: Connection) => { 211 | try { 212 | const metaplex = Metaplex.make(connection); 213 | const mintPublicKey = new PublicKey(mintAddress); 214 | const nft = await metaplex.nfts().findByMint({ mintAddress: mintPublicKey }); 215 | return nft; // Returns the token's ticker/symbol 216 | } catch (error) { 217 | // console.error("Error fetching token metadata:", error); 218 | return false 219 | } 220 | }; 221 | 222 | runBot() -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Connection, 3 | Keypair, 4 | PublicKey, 5 | } from "@solana/web3.js"; 6 | import base58 from "bs58"; 7 | import dotnet from 'dotenv' 8 | import { commitment, PUMP_FUN_PROGRAM } from "./constants"; 9 | import { convertHttpToWebSocket, formatDate } from "./utils/commonFunc"; 10 | 11 | import WebSocket = require("ws"); 12 | import buyToken from "./pumputils/utils/buyToken"; 13 | import { Metaplex } from "@metaplex-foundation/js"; 14 | 15 | dotnet.config(); 16 | 17 | 18 | const rpc = process.env.RPC_ENDPOINT; 19 | console.log("🚀 RPC:", rpc) 20 | 21 | const payer = process.env.PRIVATE_KEY; 22 | console.log("🚀 Private Key:", `${payer?.slice(0, 6)}...`) 23 | 24 | const isDevMode = process.env.DEV_MODE === 'true'; 25 | const devwallet = process.env.DEV_WALLET_ADDRESS; 26 | if (isDevMode) { 27 | console.log("🚀 Dev Wallet:", devwallet) 28 | } 29 | 30 | const isTickerMode = process.env.TICKER_MODE === 'true'; 31 | const tokenTicker = process.env.TOKEN_TICKER; 32 | if (isTickerMode) { 33 | console.log("🚀 Token Ticker:", tokenTicker) 34 | } 35 | 36 | const buyamount = process.env.BUY_AMOUNT; 37 | console.log("🚀 Buy Amount:", buyamount) 38 | 39 | const isGeyser = process.env.IS_GEYSER === 'true'; 40 | 41 | const init = async (rpcEndPoint: string, payer: string, solIn: number, devAddr: string) => { 42 | try { 43 | const payerKeypair = Keypair.fromSecretKey(base58.decode(payer)); 44 | let isBuying = false; 45 | const connection = new Connection(rpcEndPoint, { wsEndpoint: convertHttpToWebSocket(rpcEndPoint), commitment: "confirmed" }); 46 | const logConnection = new Connection(rpcEndPoint, { wsEndpoint: convertHttpToWebSocket(rpcEndPoint), commitment: "processed" }); 47 | let globalLogListener: any; 48 | 49 | // Function to stop the listener 50 | const stopListener = async () => { 51 | if (globalLogListener !== undefined) { 52 | try { 53 | await logConnection.removeOnLogsListener(globalLogListener); 54 | isBuying = true 55 | } catch (err) { 56 | console.log("Error stopping listener:", err); 57 | } 58 | } 59 | }; 60 | 61 | console.log('--------------- Bot is Runnig Now ---------------') 62 | 63 | globalLogListener = logConnection.onLogs( 64 | PUMP_FUN_PROGRAM, 65 | async ({ logs, err, signature }) => { 66 | if (err) return 67 | const isMint = logs.filter(log => log.includes("MintTo")).length; 68 | if (isMint && !isBuying) { 69 | const parsedTransaction = await logConnection.getParsedTransaction(signature, { maxSupportedTransactionVersion: 0, commitment: "confirmed" }); 70 | if (!parsedTransaction) { 71 | return; 72 | } 73 | console.log("New signature => ", `https://solscan.io/tx/${signature}`); 74 | let dev = parsedTransaction?.transaction.message.accountKeys[0].pubkey.toString(); 75 | const mint = parsedTransaction?.transaction.message.accountKeys[1].pubkey; 76 | if (isDevMode) { 77 | console.log("Dev wallet => ", `https://solscan.io/address/${dev}`); 78 | } 79 | if (isDevMode && dev !== devAddr) return; 80 | 81 | if (isTickerMode) { 82 | if (!tokenTicker) return console.log("Token Ticker is not defiend!"); 83 | const tokenInfo = await getTokenMetadata(mint.toString(), connection); 84 | if (!tokenInfo) return; 85 | const isTarget = tokenInfo.symbol.toUpperCase().includes(tokenTicker.toUpperCase()) 86 | if (!isTarget) return 87 | console.log(`Found $${tokenInfo.symbol} token.`) 88 | } 89 | 90 | console.log('New token => ', `https://solscan.io/token/${mint.toString()}`) 91 | await stopListener() 92 | isBuying = true; 93 | const sig = await buyToken(mint, connection, payerKeypair, solIn, 1); 94 | console.log('Buy Transaction => ', `https://solscan.io/tx/${sig}`) 95 | if (!sig) { 96 | isBuying = false; 97 | } else { 98 | console.log('🚀 Buy Success!!!'); 99 | console.log('Try to sell on pumpfun: ', `https://pump.fun/${mint.toString()}`) 100 | } 101 | 102 | } 103 | }, 104 | commitment 105 | ); 106 | 107 | } catch (err) { 108 | console.log(err); 109 | return { stopListener: undefined }; 110 | } 111 | }; 112 | 113 | const withGaser = (rpcEndPoint: string, payer: string, solIn: number, devAddr: string) => { 114 | const GEYSER_RPC = process.env.GEYSER_RPC; 115 | if (!GEYSER_RPC) return console.log('Geyser RPC is not provided!'); 116 | const ws = new WebSocket(GEYSER_RPC); 117 | const connection = new Connection(rpcEndPoint, { wsEndpoint: convertHttpToWebSocket(rpcEndPoint), commitment: "processed" }); 118 | const payerKeypair = Keypair.fromSecretKey(base58.decode(payer)) 119 | 120 | console.log('Your Pub Key => ', payerKeypair.publicKey.toString()) 121 | 122 | function sendRequest(ws: WebSocket) { 123 | const request = { 124 | jsonrpc: "2.0", 125 | id: 420, 126 | method: "transactionSubscribe", 127 | params: [ 128 | { 129 | failed: false, 130 | accountInclude: ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"] 131 | }, 132 | { 133 | commitment: "confirmed", 134 | encoding: "jsonParsed", 135 | transactionDetails: "full", 136 | maxSupportedTransactionVersion: 0 137 | } 138 | ] 139 | }; 140 | ws.send(JSON.stringify(request)); 141 | } 142 | 143 | ws.on('open', function open() { 144 | console.log('WebSocket is open'); 145 | sendRequest(ws); // Send a request once the WebSocket is open 146 | }); 147 | 148 | ws.on('message', async function incoming(data) { 149 | const messageStr = data.toString('utf8'); 150 | try { 151 | const messageObj = JSON.parse(messageStr); 152 | 153 | const result = messageObj.params.result; 154 | const logs = result.transaction.meta.logMessages; 155 | const signature = result.signature; // Extract the signature 156 | const accountKeys = result.transaction.transaction.message.accountKeys.map((ak: { pubkey: any; }) => ak.pubkey); 157 | 158 | if (logs && logs.some((log: string | string[]) => log.includes('Program log: Instruction: InitializeMint2'))) { 159 | const dev = accountKeys[0] 160 | const mint = accountKeys[1] 161 | 162 | console.log("New signature => ", `https://solscan.io/tx/${signature}`); 163 | if (isDevMode) { 164 | console.log("Dev wallet => ", `https://solscan.io/address/${dev}`); 165 | } 166 | if (isDevMode && dev !== devAddr) return; 167 | 168 | if (isTickerMode) { 169 | if (!tokenTicker) return console.log("Token Ticker is not defiend!"); 170 | const tokenInfo = await getTokenMetadata(mint.toString(), connection); 171 | if (!tokenInfo) return; 172 | const isTarget = tokenInfo.symbol.toUpperCase().includes(tokenTicker.toUpperCase()) 173 | if (!isTarget) return 174 | console.log(`Found $${tokenInfo.symbol} token.`) 175 | } 176 | 177 | console.log('New token => ', `https://solscan.io/token/${mint.toString()}`) 178 | ws.close(); 179 | const mintPub = new PublicKey(mint); 180 | const sig = await buyToken(mintPub, connection, payerKeypair, solIn, 1); 181 | console.log('Buy Transaction => ', `https://solscan.io/tx/${sig}`) 182 | if (!sig) { 183 | ws.on('open', function open() { 184 | console.log('WebSocket is open'); 185 | sendRequest(ws); // Send a request once the WebSocket is open 186 | }); 187 | } else { 188 | console.log('🚀 Buy Success!!!'); 189 | console.log('Try to sell on pumpfun: ', `https://pump.fun/${mint.toString()}`) 190 | } 191 | 192 | } 193 | } catch (e) { 194 | 195 | } 196 | }); 197 | 198 | } 199 | 200 | const runBot = () => { 201 | if (isGeyser) { 202 | console.log('--------------- Geyser mode selected! ---------------\n'); 203 | withGaser(rpc!, payer!, Number(buyamount!), devwallet!); 204 | } else { 205 | console.log("--------------- Common Mode selected! ---------------\n"); 206 | init(rpc!, payer!, Number(buyamount!), devwallet!) 207 | } 208 | } 209 | 210 | const getTokenMetadata = async (mintAddress: string, connection: Connection) => { 211 | try { 212 | const metaplex = Metaplex.make(connection); 213 | const mintPublicKey = new PublicKey(mintAddress); 214 | const nft = await metaplex.nfts().findByMint({ mintAddress: mintPublicKey }); 215 | return nft; // Returns the token's ticker/symbol 216 | } catch (error) { 217 | // console.error("Error fetching token metadata:", error); 218 | return false 219 | } 220 | }; 221 | 222 | runBot() -------------------------------------------------------------------------------- /src/pumputils/idl/pump-fun.ts: -------------------------------------------------------------------------------- 1 | export type PumpFun = { 2 | address: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; 3 | metadata: { 4 | name: "pump"; 5 | version: "0.1.0"; 6 | spec: "0.1.0"; 7 | }; 8 | instructions: [ 9 | { 10 | name: "initialize"; 11 | discriminator: [175, 175, 109, 31, 13, 152, 155, 237]; 12 | docs: ["Creates the global state."]; 13 | accounts: [ 14 | { 15 | name: "global"; 16 | writable: true; 17 | pda: { 18 | seeds: [ 19 | { 20 | kind: "const"; 21 | value: [103, 108, 111, 98, 97, 108]; 22 | } 23 | ]; 24 | }; 25 | }, 26 | { 27 | name: "user"; 28 | writable: true; 29 | signer: true; 30 | }, 31 | { 32 | name: "systemProgram"; 33 | address: "11111111111111111111111111111111"; 34 | } 35 | ]; 36 | args: []; 37 | }, 38 | { 39 | name: "setParams"; 40 | discriminator: [165, 31, 134, 53, 189, 180, 130, 255]; 41 | docs: ["Sets the global state parameters."]; 42 | accounts: [ 43 | { 44 | name: "global"; 45 | writable: true; 46 | pda: { 47 | seeds: [ 48 | { 49 | kind: "const"; 50 | value: [103, 108, 111, 98, 97, 108]; 51 | } 52 | ]; 53 | }; 54 | }, 55 | { 56 | name: "user"; 57 | writable: true; 58 | signer: true; 59 | }, 60 | { 61 | name: "systemProgram"; 62 | address: "11111111111111111111111111111111"; 63 | }, 64 | { 65 | name: "eventAuthority"; 66 | address: "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"; 67 | }, 68 | { 69 | name: "program"; 70 | address: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; 71 | } 72 | ]; 73 | args: [ 74 | { 75 | name: "feeRecipient"; 76 | type: "pubkey"; 77 | }, 78 | { 79 | name: "initialVirtualTokenReserves"; 80 | type: "u64"; 81 | }, 82 | { 83 | name: "initialVirtualSolReserves"; 84 | type: "u64"; 85 | }, 86 | { 87 | name: "initialRealTokenReserves"; 88 | type: "u64"; 89 | }, 90 | { 91 | name: "tokenTotalSupply"; 92 | type: "u64"; 93 | }, 94 | { 95 | name: "feeBasisPoints"; 96 | type: "u64"; 97 | } 98 | ]; 99 | }, 100 | { 101 | name: "create"; 102 | discriminator: [24, 30, 200, 40, 5, 28, 7, 119]; 103 | docs: ["Creates a new coin and bonding curve."]; 104 | accounts: [ 105 | { 106 | name: "mint"; 107 | writable: true; 108 | signer: true; 109 | }, 110 | { 111 | name: "mint_authority"; 112 | pda: { 113 | seeds: [ 114 | { 115 | kind: "const"; 116 | value: [109, 105, 110, 116, 45, 97, 117, 116, 104, 111, 114, 105, 116, 121]; 117 | } 118 | ]; 119 | }; 120 | }, 121 | { 122 | name: "bondingCurve"; 123 | writable: true; 124 | pda: { 125 | seeds: [ 126 | { 127 | kind: "const"; 128 | value: [98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101]; 129 | }, 130 | { 131 | kind: "account"; 132 | path: "mint"; 133 | } 134 | ]; 135 | }; 136 | }, 137 | { 138 | name: "associatedBondingCurve"; 139 | writable: true; 140 | signer: false; 141 | }, 142 | { 143 | name: "global"; 144 | writable: false; 145 | pda: { 146 | seeds: [ 147 | { 148 | kind: "const"; 149 | value: [103, 108, 111, 98, 97, 108]; 150 | } 151 | ]; 152 | }; 153 | }, 154 | { 155 | name: "mplTokenMetadata"; 156 | address: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"; 157 | }, 158 | { 159 | name: "metadata"; 160 | writable: true; 161 | signer: false; 162 | }, 163 | { 164 | name: "user"; 165 | isMut: true; 166 | isSigner: true; 167 | }, 168 | { 169 | name: "systemProgram"; 170 | address: "11111111111111111111111111111111"; 171 | }, 172 | { 173 | name: "tokenProgram"; 174 | address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; 175 | }, 176 | { 177 | name: "associatedTokenProgram"; 178 | address: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"; 179 | }, 180 | { 181 | name: "rent"; 182 | address: "SysvarRent111111111111111111111111111111111"; 183 | }, 184 | { 185 | name: "eventAuthority"; 186 | address: "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"; 187 | }, 188 | { 189 | name: "program"; 190 | address: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; 191 | } 192 | ]; 193 | args: [ 194 | { 195 | name: "name"; 196 | type: "string"; 197 | }, 198 | { 199 | name: "symbol"; 200 | type: "string"; 201 | }, 202 | { 203 | name: "uri"; 204 | type: "string"; 205 | } 206 | ]; 207 | }, 208 | { 209 | name: "buy"; 210 | discriminator: [102, 6, 61, 18, 1, 218, 235, 234]; 211 | docs: ["Buys tokens from a bonding curve."]; 212 | accounts: [ 213 | { 214 | name: "global"; 215 | pda: { 216 | seeds: [ 217 | { 218 | kind: "const"; 219 | value: [103, 108, 111, 98, 97, 108]; 220 | } 221 | ]; 222 | }; 223 | }, 224 | { 225 | name: "feeRecipient"; 226 | writable: true; 227 | signer: false; 228 | }, 229 | { 230 | name: "mint"; 231 | writable: false; 232 | signer: false; 233 | }, 234 | { 235 | name: "bondingCurve"; 236 | writable: true; 237 | pda: { 238 | seeds: [ 239 | { 240 | kind: "const"; 241 | value: [98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101]; 242 | }, 243 | { 244 | kind: "account"; 245 | path: "mint"; 246 | } 247 | ]; 248 | }; 249 | }, 250 | { 251 | name: "associatedBondingCurve"; 252 | writable: true; 253 | signer: false; 254 | }, 255 | { 256 | name: "associatedUser"; 257 | writable: true; 258 | signer: false; 259 | }, 260 | { 261 | name: "user"; 262 | writable: true; 263 | signer: true; 264 | }, 265 | { 266 | name: "systemProgram"; 267 | address: "11111111111111111111111111111111"; 268 | }, 269 | { 270 | name: "tokenProgram"; 271 | address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; 272 | }, 273 | { 274 | name: "rent"; 275 | address: "SysvarRent111111111111111111111111111111111"; 276 | }, 277 | { 278 | name: "eventAuthority"; 279 | address: "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"; 280 | }, 281 | { 282 | name: "program"; 283 | address: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; 284 | } 285 | ]; 286 | args: [ 287 | { 288 | name: "amount"; 289 | type: "u64"; 290 | }, 291 | { 292 | name: "maxSolCost"; 293 | type: "u64"; 294 | } 295 | ]; 296 | }, 297 | { 298 | name: "sell"; 299 | discriminator: [51, 230, 133, 164, 1, 127, 131, 173]; 300 | docs: ["Sells tokens into a bonding curve."]; 301 | accounts: [ 302 | { 303 | name: "global"; 304 | writable: false; 305 | pda: { 306 | seeds: [ 307 | { 308 | kind: "const"; 309 | value: [103, 108, 111, 98, 97, 108]; 310 | } 311 | ]; 312 | }; 313 | }, 314 | { 315 | name: "feeRecipient"; 316 | writable: true; 317 | signer: false; 318 | }, 319 | { 320 | name: "mint"; 321 | writable: false; 322 | signer: false; 323 | }, 324 | { 325 | name: "bondingCurve"; 326 | writable: true; 327 | pda: { 328 | seeds: [ 329 | { 330 | kind: "const"; 331 | value: [98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101]; 332 | }, 333 | { 334 | kind: "account"; 335 | path: "mint"; 336 | } 337 | ]; 338 | }; 339 | }, 340 | { 341 | name: "associatedBondingCurve"; 342 | writable: true; 343 | signer: false; 344 | }, 345 | { 346 | name: "associatedUser"; 347 | writable: true; 348 | signer: false; 349 | }, 350 | { 351 | name: "user"; 352 | writable: true; 353 | signer: true; 354 | }, 355 | { 356 | name: "systemProgram"; 357 | address: "11111111111111111111111111111111"; 358 | }, 359 | { 360 | name: "associatedTokenProgram"; 361 | address: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"; 362 | }, 363 | { 364 | name: "tokenProgram"; 365 | address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; 366 | }, 367 | { 368 | name: "eventAuthority"; 369 | address: "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"; 370 | }, 371 | { 372 | name: "program"; 373 | address: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; 374 | } 375 | ]; 376 | args: [ 377 | { 378 | name: "amount"; 379 | type: "u64"; 380 | }, 381 | { 382 | name: "minSolOutput"; 383 | type: "u64"; 384 | } 385 | ]; 386 | }, 387 | { 388 | name: "withdraw"; 389 | discriminator: [183, 18, 70, 156, 148, 109, 161, 34]; 390 | docs: ["Allows the admin to withdraw liquidity for a migration once the bonding curve completes"]; 391 | accounts: [ 392 | { 393 | name: "global"; 394 | writable: false; 395 | pda: { 396 | seeds: [ 397 | { 398 | kind: "const"; 399 | value: [103, 108, 111, 98, 97, 108]; 400 | } 401 | ]; 402 | }; 403 | }, 404 | { 405 | name: "lastWithdraw"; 406 | writable: true; 407 | signer: false; 408 | }, 409 | { 410 | name: "mint"; 411 | writable: false; 412 | signer: false; 413 | }, 414 | { 415 | name: "bondingCurve"; 416 | writable: true; 417 | pda: { 418 | seeds: [ 419 | { 420 | kind: "const"; 421 | value: [98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101]; 422 | }, 423 | { 424 | kind: "account"; 425 | path: "mint"; 426 | } 427 | ]; 428 | }; 429 | }, 430 | { 431 | name: "associatedBondingCurve"; 432 | writable: true; 433 | signer: false; 434 | }, 435 | { 436 | name: "associatedUser"; 437 | writable: true; 438 | signer: false; 439 | }, 440 | { 441 | name: "user"; 442 | writable: true; 443 | signer: true; 444 | }, 445 | { 446 | name: "system_program"; 447 | address: "11111111111111111111111111111111"; 448 | }, 449 | { 450 | name: "tokenProgram"; 451 | address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; 452 | }, 453 | { 454 | name: "rent"; 455 | address: "SysvarRent111111111111111111111111111111111"; 456 | }, 457 | { 458 | name: "eventAuthority"; 459 | address: "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"; 460 | }, 461 | { 462 | name: "program"; 463 | address: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; 464 | } 465 | ]; 466 | args: []; 467 | } 468 | ]; 469 | accounts: [ 470 | { 471 | name: "bondingCurve"; 472 | discriminator: [23, 183, 248, 55, 96, 216, 172, 96]; 473 | }, 474 | { 475 | name: "global"; 476 | discriminator: [167, 232, 232, 177, 200, 108, 114, 127]; 477 | } 478 | ]; 479 | events: [ 480 | { 481 | name: "createEvent"; 482 | discriminator: [27, 114, 169, 77, 222, 235, 99, 118]; 483 | }, 484 | { 485 | name: "tradeEvent"; 486 | discriminator: [189, 219, 127, 211, 78, 230, 97, 238]; 487 | }, 488 | { 489 | name: "completeEvent"; 490 | discriminator: [95, 114, 97, 156, 212, 46, 152, 8]; 491 | }, 492 | { 493 | name: "setParamsEvent"; 494 | discriminator: [223, 195, 159, 246, 62, 48, 143, 131]; 495 | } 496 | ]; 497 | types: [ 498 | { 499 | name: "global"; 500 | type: { 501 | kind: "struct"; 502 | fields: [ 503 | { 504 | name: "initialized"; 505 | type: "bool"; 506 | }, 507 | { 508 | name: "authority"; 509 | type: "pubkey"; 510 | }, 511 | { 512 | name: "feeRecipient"; 513 | type: "pubkey"; 514 | }, 515 | { 516 | name: "initialVirtualTokenReserves"; 517 | type: "u64"; 518 | }, 519 | { 520 | name: "initialVirtualSolReserves"; 521 | type: "u64"; 522 | }, 523 | { 524 | name: "initialRealTokenReserves"; 525 | type: "u64"; 526 | }, 527 | { 528 | name: "tokenTotalSupply"; 529 | type: "u64"; 530 | }, 531 | { 532 | name: "feeBasisPoints"; 533 | type: "u64"; 534 | } 535 | ]; 536 | }; 537 | }, 538 | { 539 | name: "lastWithdraw"; 540 | type: { 541 | kind: "struct"; 542 | fields: [ 543 | { 544 | name: "lastWithdrawTimestamp"; 545 | type: "i64"; 546 | } 547 | ]; 548 | }; 549 | }, 550 | { 551 | name: "bondingCurve"; 552 | type: { 553 | kind: "struct"; 554 | fields: [ 555 | { 556 | name: "virtualTokenReserves"; 557 | type: "u64"; 558 | }, 559 | { 560 | name: "virtualSolReserves"; 561 | type: "u64"; 562 | }, 563 | { 564 | name: "realTokenReserves"; 565 | type: "u64"; 566 | }, 567 | { 568 | name: "realSolReserves"; 569 | type: "u64"; 570 | }, 571 | { 572 | name: "tokenTotalSupply"; 573 | type: "u64"; 574 | }, 575 | { 576 | name: "complete"; 577 | type: "bool"; 578 | } 579 | ]; 580 | }; 581 | }, 582 | { 583 | name: "createEvent"; 584 | type: { 585 | kind: "struct"; 586 | fields: [ 587 | { 588 | name: "name"; 589 | type: "string"; 590 | index: false; 591 | }, 592 | { 593 | name: "symbol"; 594 | type: "string"; 595 | index: false; 596 | }, 597 | { 598 | name: "uri"; 599 | type: "string"; 600 | index: false; 601 | }, 602 | { 603 | name: "mint"; 604 | type: "pubkey"; 605 | index: false; 606 | }, 607 | { 608 | name: "bondingCurve"; 609 | type: "pubkey"; 610 | index: false; 611 | }, 612 | { 613 | name: "user"; 614 | type: "pubkey"; 615 | index: false; 616 | } 617 | ]; 618 | }; 619 | }, 620 | { 621 | name: "tradeEvent"; 622 | type: { 623 | kind: "struct"; 624 | fields: [ 625 | { 626 | name: "mint"; 627 | type: "pubkey"; 628 | index: false; 629 | }, 630 | { 631 | name: "solAmount"; 632 | type: "u64"; 633 | index: false; 634 | }, 635 | { 636 | name: "tokenAmount"; 637 | type: "u64"; 638 | index: false; 639 | }, 640 | { 641 | name: "isBuy"; 642 | type: "bool"; 643 | index: false; 644 | }, 645 | { 646 | name: "user"; 647 | type: "pubkey"; 648 | index: false; 649 | }, 650 | { 651 | name: "timestamp"; 652 | type: "i64"; 653 | index: false; 654 | }, 655 | { 656 | name: "virtualSolReserves"; 657 | type: "u64"; 658 | index: false; 659 | }, 660 | { 661 | name: "virtualTokenReserves"; 662 | type: "u64"; 663 | index: false; 664 | }, 665 | { 666 | name: "realSolReserves"; 667 | type: "u64"; 668 | index: false; 669 | }, 670 | { 671 | name: "realTokenReserves"; 672 | type: "u64"; 673 | index: false; 674 | } 675 | ]; 676 | }; 677 | }, 678 | { 679 | name: "completeEvent"; 680 | type: { 681 | kind: "struct"; 682 | fields: [ 683 | { 684 | name: "user"; 685 | type: "pubkey"; 686 | index: false; 687 | }, 688 | { 689 | name: "mint"; 690 | type: "pubkey"; 691 | index: false; 692 | }, 693 | { 694 | name: "bondingCurve"; 695 | type: "pubkey"; 696 | index: false; 697 | }, 698 | { 699 | name: "timestamp"; 700 | type: "i64"; 701 | index: false; 702 | } 703 | ]; 704 | }; 705 | }, 706 | { 707 | name: "setParamsEvent"; 708 | type: { 709 | kind: "struct"; 710 | fields: [ 711 | { 712 | name: "feeRecipient"; 713 | type: "pubkey"; 714 | index: false; 715 | }, 716 | { 717 | name: "initialVirtualTokenReserves"; 718 | type: "u64"; 719 | index: false; 720 | }, 721 | { 722 | name: "initialVirtualSolReserves"; 723 | type: "u64"; 724 | index: false; 725 | }, 726 | { 727 | name: "initialRealTokenReserves"; 728 | type: "u64"; 729 | index: false; 730 | }, 731 | { 732 | name: "tokenTotalSupply"; 733 | type: "u64"; 734 | index: false; 735 | }, 736 | { 737 | name: "feeBasisPoints"; 738 | type: "u64"; 739 | index: false; 740 | } 741 | ]; 742 | }; 743 | } 744 | ]; 745 | errors: [ 746 | { 747 | code: 6000; 748 | name: "NotAuthorized"; 749 | msg: "The given account is not authorized to execute this instruction."; 750 | }, 751 | { 752 | code: 6001; 753 | name: "AlreadyInitialized"; 754 | msg: "The program is already initialized."; 755 | }, 756 | { 757 | code: 6002; 758 | name: "TooMuchSolRequired"; 759 | msg: "slippage: Too much SOL required to buy the given amount of tokens."; 760 | }, 761 | { 762 | code: 6003; 763 | name: "TooLittleSolReceived"; 764 | msg: "slippage: Too little SOL received to sell the given amount of tokens."; 765 | }, 766 | { 767 | code: 6004; 768 | name: "MintDoesNotMatchBondingCurve"; 769 | msg: "The mint does not match the bonding curve."; 770 | }, 771 | { 772 | code: 6005; 773 | name: "BondingCurveComplete"; 774 | msg: "The bonding curve has completed and liquidity migrated to raydium."; 775 | }, 776 | { 777 | code: 6006; 778 | name: "BondingCurveNotComplete"; 779 | msg: "The bonding curve has not completed."; 780 | }, 781 | { 782 | code: 6007; 783 | name: "NotInitialized"; 784 | msg: "The program is not initialized."; 785 | }, 786 | { 787 | code: 6008; 788 | name: "WithdrawTooFrequent"; 789 | msg: "Withdraw too frequent"; 790 | } 791 | ]; 792 | }; 793 | -------------------------------------------------------------------------------- /src/pumputils/idl/pump-fun.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", 3 | "metadata": { 4 | "name": "pump", 5 | "version": "0.1.0", 6 | "spec": "0.1.0" 7 | }, 8 | "instructions": [ 9 | { 10 | "name": "initialize", 11 | "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], 12 | "docs": ["Creates the global state."], 13 | "accounts": [ 14 | { 15 | "name": "global", 16 | "writable": true, 17 | "pda": { 18 | "seeds": [ 19 | { 20 | "kind": "const", 21 | "value": [103, 108, 111, 98, 97, 108] 22 | } 23 | ] 24 | } 25 | }, 26 | { 27 | "name": "user", 28 | "writable": true, 29 | "signer": true 30 | }, 31 | { 32 | "name": "system_program", 33 | "address": "11111111111111111111111111111111" 34 | } 35 | ], 36 | "args": [] 37 | }, 38 | { 39 | "name": "setParams", 40 | "discriminator": [165, 31, 134, 53, 189, 180, 130, 255], 41 | "docs": ["Sets the global state parameters."], 42 | "accounts": [ 43 | { 44 | "name": "global", 45 | "writable": true, 46 | "pda": { 47 | "seeds": [ 48 | { 49 | "kind": "const", 50 | "value": [103, 108, 111, 98, 97, 108] 51 | } 52 | ] 53 | } 54 | }, 55 | { 56 | "name": "user", 57 | "writable": true, 58 | "signer": true 59 | }, 60 | { 61 | "name": "system_program", 62 | "address": "11111111111111111111111111111111" 63 | }, 64 | { 65 | "name": "event_authority", 66 | "address": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" 67 | }, 68 | { 69 | "name": "program", 70 | "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" 71 | } 72 | ], 73 | "args": [ 74 | { 75 | "name": "feeRecipient", 76 | "type": "pubkey" 77 | }, 78 | { 79 | "name": "initialVirtualTokenReserves", 80 | "type": "u64" 81 | }, 82 | { 83 | "name": "initialVirtualSolReserves", 84 | "type": "u64" 85 | }, 86 | { 87 | "name": "initialRealTokenReserves", 88 | "type": "u64" 89 | }, 90 | { 91 | "name": "tokenTotalSupply", 92 | "type": "u64" 93 | }, 94 | { 95 | "name": "feeBasisPoints", 96 | "type": "u64" 97 | } 98 | ] 99 | }, 100 | { 101 | "name": "create", 102 | "discriminator": [24, 30, 200, 40, 5, 28, 7, 119], 103 | "docs": ["Creates a new coin and bonding curve."], 104 | "accounts": [ 105 | { 106 | "name": "mint", 107 | "writable": true, 108 | "signer": true 109 | }, 110 | { 111 | "name": "mint_authority", 112 | "pda": { 113 | "seeds": [ 114 | { 115 | "kind": "const", 116 | "value": [109, 105, 110, 116, 45, 97, 117, 116, 104, 111, 114, 105, 116, 121] 117 | } 118 | ] 119 | } 120 | }, 121 | { 122 | "name": "bonding_curve", 123 | "writable": true, 124 | "pda": { 125 | "seeds": [ 126 | { 127 | "kind": "const", 128 | "value": [98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101] 129 | }, 130 | { 131 | "kind": "account", 132 | "path": "mint" 133 | } 134 | ] 135 | } 136 | }, 137 | { 138 | "name": "associated_bonding_curve", 139 | "writable": true, 140 | "signer": false 141 | }, 142 | { 143 | "name": "global", 144 | "writable": false, 145 | "pda": { 146 | "seeds": [ 147 | { 148 | "kind": "const", 149 | "value": [103, 108, 111, 98, 97, 108] 150 | } 151 | ] 152 | } 153 | }, 154 | { 155 | "name": "mpl_token_metadata", 156 | "address": "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" 157 | }, 158 | { 159 | "name": "metadata", 160 | "writable": true, 161 | "signer": false 162 | }, 163 | { 164 | "name": "user", 165 | "isMut": true, 166 | "isSigner": true 167 | }, 168 | { 169 | "name": "system_program", 170 | "address": "11111111111111111111111111111111" 171 | }, 172 | { 173 | "name": "token_program", 174 | "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" 175 | }, 176 | { 177 | "name": "associated_token_program", 178 | "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" 179 | }, 180 | { 181 | "name": "rent", 182 | "address": "SysvarRent111111111111111111111111111111111" 183 | }, 184 | { 185 | "name": "event_authority", 186 | "address": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" 187 | }, 188 | { 189 | "name": "program", 190 | "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" 191 | } 192 | ], 193 | "args": [ 194 | { 195 | "name": "name", 196 | "type": "string" 197 | }, 198 | { 199 | "name": "symbol", 200 | "type": "string" 201 | }, 202 | { 203 | "name": "uri", 204 | "type": "string" 205 | } 206 | ] 207 | }, 208 | { 209 | "name": "buy", 210 | "discriminator": [102, 6, 61, 18, 1, 218, 235, 234], 211 | "docs": ["Buys tokens from a bonding curve."], 212 | "accounts": [ 213 | { 214 | "name": "global", 215 | "pda": { 216 | "seeds": [ 217 | { 218 | "kind": "const", 219 | "value": [103, 108, 111, 98, 97, 108] 220 | } 221 | ] 222 | } 223 | }, 224 | { 225 | "name": "fee_recipient", 226 | "writable": true, 227 | "signer": false 228 | }, 229 | { 230 | "name": "mint", 231 | "writable": false, 232 | "signer": false 233 | }, 234 | { 235 | "name": "bonding_curve", 236 | "writable": true, 237 | "pda": { 238 | "seeds": [ 239 | { 240 | "kind": "const", 241 | "value": [98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101] 242 | }, 243 | { 244 | "kind": "account", 245 | "path": "mint" 246 | } 247 | ] 248 | } 249 | }, 250 | { 251 | "name": "associated_bonding_curve", 252 | "writable": true, 253 | "signer": false 254 | }, 255 | { 256 | "name": "associated_user", 257 | "writable": true, 258 | "signer": false 259 | }, 260 | { 261 | "name": "user", 262 | "writable": true, 263 | "signer": true 264 | }, 265 | { 266 | "name": "system_program", 267 | "address": "11111111111111111111111111111111" 268 | }, 269 | { 270 | "name": "token_program", 271 | "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" 272 | }, 273 | { 274 | "name": "rent", 275 | "address": "SysvarRent111111111111111111111111111111111" 276 | }, 277 | { 278 | "name": "event_authority", 279 | "address": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" 280 | }, 281 | { 282 | "name": "program", 283 | "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" 284 | } 285 | ], 286 | "args": [ 287 | { 288 | "name": "amount", 289 | "type": "u64" 290 | }, 291 | { 292 | "name": "maxSolCost", 293 | "type": "u64" 294 | } 295 | ] 296 | }, 297 | { 298 | "name": "sell", 299 | "discriminator": [51, 230, 133, 164, 1, 127, 131, 173], 300 | "docs": ["Sells tokens into a bonding curve."], 301 | "accounts": [ 302 | { 303 | "name": "global", 304 | "writable": false, 305 | "pda": { 306 | "seeds": [ 307 | { 308 | "kind": "const", 309 | "value": [103, 108, 111, 98, 97, 108] 310 | } 311 | ] 312 | } 313 | }, 314 | { 315 | "name": "feeRecipient", 316 | "writable": true, 317 | "signer": false 318 | }, 319 | { 320 | "name": "mint", 321 | "writable": false, 322 | "signer": false 323 | }, 324 | { 325 | "name": "bonding_curve", 326 | "writable": true, 327 | "pda": { 328 | "seeds": [ 329 | { 330 | "kind": "const", 331 | "value": [98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101] 332 | }, 333 | { 334 | "kind": "account", 335 | "path": "mint" 336 | } 337 | ] 338 | } 339 | }, 340 | { 341 | "name": "associatedBondingCurve", 342 | "writable": true, 343 | "signer": false 344 | }, 345 | { 346 | "name": "associatedUser", 347 | "writable": true, 348 | "signer": false 349 | }, 350 | { 351 | "name": "user", 352 | "writable": true, 353 | "signer": true 354 | }, 355 | { 356 | "name": "system_program", 357 | "address": "11111111111111111111111111111111" 358 | }, 359 | { 360 | "name": "associated_token_program", 361 | "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" 362 | }, 363 | { 364 | "name": "token_program", 365 | "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" 366 | }, 367 | { 368 | "name": "event_authority", 369 | "address": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" 370 | }, 371 | { 372 | "name": "program", 373 | "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" 374 | } 375 | ], 376 | "args": [ 377 | { 378 | "name": "amount", 379 | "type": "u64" 380 | }, 381 | { 382 | "name": "minSolOutput", 383 | "type": "u64" 384 | } 385 | ] 386 | }, 387 | { 388 | "name": "withdraw", 389 | "discriminator": [183, 18, 70, 156, 148, 109, 161, 34], 390 | "docs": ["Allows the admin to withdraw liquidity for a migration once the bonding curve completes"], 391 | "accounts": [ 392 | { 393 | "name": "global", 394 | "writable": false, 395 | "pda": { 396 | "seeds": [ 397 | { 398 | "kind": "const", 399 | "value": [103, 108, 111, 98, 97, 108] 400 | } 401 | ] 402 | } 403 | }, 404 | { 405 | "name": "lastWithdraw", 406 | "writable": true, 407 | "signer": false 408 | }, 409 | { 410 | "name": "mint", 411 | "writable": false, 412 | "signer": false 413 | }, 414 | { 415 | "name": "bonding_curve", 416 | "writable": true, 417 | "pda": { 418 | "seeds": [ 419 | { 420 | "kind": "const", 421 | "value": [98, 111, 110, 100, 105, 110, 103, 45, 99, 117, 114, 118, 101] 422 | }, 423 | { 424 | "kind": "account", 425 | "path": "mint" 426 | } 427 | ] 428 | } 429 | }, 430 | { 431 | "name": "associatedBondingCurve", 432 | "writable": true, 433 | "signer": false 434 | }, 435 | { 436 | "name": "associatedUser", 437 | "writable": true, 438 | "signer": false 439 | }, 440 | { 441 | "name": "user", 442 | "writable": true, 443 | "signer": true 444 | }, 445 | { 446 | "name": "system_program", 447 | "address": "11111111111111111111111111111111" 448 | }, 449 | { 450 | "name": "token_program", 451 | "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" 452 | }, 453 | { 454 | "name": "rent", 455 | "address": "SysvarRent111111111111111111111111111111111" 456 | }, 457 | { 458 | "name": "event_authority", 459 | "address": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" 460 | }, 461 | { 462 | "name": "program", 463 | "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" 464 | } 465 | ], 466 | "args": [] 467 | } 468 | ], 469 | "accounts": [ 470 | { 471 | "name": "BondingCurve", 472 | "discriminator": [23, 183, 248, 55, 96, 216, 172, 96] 473 | }, 474 | { 475 | "name": "Global", 476 | "discriminator": [167, 232, 232, 177, 200, 108, 114, 127] 477 | } 478 | ], 479 | "events": [ 480 | { 481 | "name": "CreateEvent", 482 | "discriminator": [27, 114, 169, 77, 222, 235, 99, 118] 483 | }, 484 | { 485 | "name": "TradeEvent", 486 | "discriminator": [189, 219, 127, 211, 78, 230, 97, 238] 487 | }, 488 | { 489 | "name": "CompleteEvent", 490 | "discriminator": [95, 114, 97, 156, 212, 46, 152, 8] 491 | }, 492 | { 493 | "name": "SetParamsEvent", 494 | "discriminator": [223, 195, 159, 246, 62, 48, 143, 131] 495 | } 496 | ], 497 | "types": [ 498 | { 499 | "name": "Global", 500 | "type": { 501 | "kind": "struct", 502 | "fields": [ 503 | { 504 | "name": "initialized", 505 | "type": "bool" 506 | }, 507 | { 508 | "name": "authority", 509 | "type": "pubkey" 510 | }, 511 | { 512 | "name": "feeRecipient", 513 | "type": "pubkey" 514 | }, 515 | { 516 | "name": "initialVirtualTokenReserves", 517 | "type": "u64" 518 | }, 519 | { 520 | "name": "initialVirtualSolReserves", 521 | "type": "u64" 522 | }, 523 | { 524 | "name": "initialRealTokenReserves", 525 | "type": "u64" 526 | }, 527 | { 528 | "name": "tokenTotalSupply", 529 | "type": "u64" 530 | }, 531 | { 532 | "name": "feeBasisPoints", 533 | "type": "u64" 534 | } 535 | ] 536 | } 537 | }, 538 | { 539 | "name": "LastWithdraw", 540 | "type": { 541 | "kind": "struct", 542 | "fields": [ 543 | { 544 | "name": "lastWithdrawTimestamp", 545 | "type": "i64" 546 | } 547 | ] 548 | } 549 | }, 550 | { 551 | "name": "BondingCurve", 552 | "type": { 553 | "kind": "struct", 554 | "fields": [ 555 | { 556 | "name": "virtualTokenReserves", 557 | "type": "u64" 558 | }, 559 | { 560 | "name": "virtualSolReserves", 561 | "type": "u64" 562 | }, 563 | { 564 | "name": "realTokenReserves", 565 | "type": "u64" 566 | }, 567 | { 568 | "name": "realSolReserves", 569 | "type": "u64" 570 | }, 571 | { 572 | "name": "tokenTotalSupply", 573 | "type": "u64" 574 | }, 575 | { 576 | "name": "complete", 577 | "type": "bool" 578 | } 579 | ] 580 | } 581 | }, 582 | { 583 | "name": "CreateEvent", 584 | "type": { 585 | "kind": "struct", 586 | "fields": [ 587 | { 588 | "name": "name", 589 | "type": "string", 590 | "index": false 591 | }, 592 | { 593 | "name": "symbol", 594 | "type": "string", 595 | "index": false 596 | }, 597 | { 598 | "name": "uri", 599 | "type": "string", 600 | "index": false 601 | }, 602 | { 603 | "name": "mint", 604 | "type": "pubkey", 605 | "index": false 606 | }, 607 | { 608 | "name": "bondingCurve", 609 | "type": "pubkey", 610 | "index": false 611 | }, 612 | { 613 | "name": "user", 614 | "type": "pubkey", 615 | "index": false 616 | } 617 | ] 618 | } 619 | }, 620 | { 621 | "name": "TradeEvent", 622 | "type": { 623 | "kind": "struct", 624 | "fields": [ 625 | { 626 | "name": "mint", 627 | "type": "pubkey", 628 | "index": false 629 | }, 630 | { 631 | "name": "solAmount", 632 | "type": "u64", 633 | "index": false 634 | }, 635 | { 636 | "name": "tokenAmount", 637 | "type": "u64", 638 | "index": false 639 | }, 640 | { 641 | "name": "isBuy", 642 | "type": "bool", 643 | "index": false 644 | }, 645 | { 646 | "name": "user", 647 | "type": "pubkey", 648 | "index": false 649 | }, 650 | { 651 | "name": "timestamp", 652 | "type": "i64", 653 | "index": false 654 | }, 655 | { 656 | "name": "virtualSolReserves", 657 | "type": "u64", 658 | "index": false 659 | }, 660 | { 661 | "name": "virtualTokenReserves", 662 | "type": "u64", 663 | "index": false 664 | }, 665 | { 666 | "name": "realSolReserves", 667 | "type": "u64", 668 | "index": false 669 | }, 670 | { 671 | "name": "realTokenReserves", 672 | "type": "u64", 673 | "index": false 674 | } 675 | ] 676 | } 677 | }, 678 | { 679 | "name": "CompleteEvent", 680 | "type": { 681 | "kind": "struct", 682 | "fields": [ 683 | { 684 | "name": "user", 685 | "type": "pubkey", 686 | "index": false 687 | }, 688 | { 689 | "name": "mint", 690 | "type": "pubkey", 691 | "index": false 692 | }, 693 | { 694 | "name": "bondingCurve", 695 | "type": "pubkey", 696 | "index": false 697 | }, 698 | { 699 | "name": "timestamp", 700 | "type": "i64", 701 | "index": false 702 | } 703 | ] 704 | } 705 | }, 706 | { 707 | "name": "SetParamsEvent", 708 | "type": { 709 | "kind": "struct", 710 | "fields": [ 711 | { 712 | "name": "feeRecipient", 713 | "type": "pubkey", 714 | "index": false 715 | }, 716 | { 717 | "name": "initialVirtualTokenReserves", 718 | "type": "u64", 719 | "index": false 720 | }, 721 | { 722 | "name": "initialVirtualSolReserves", 723 | "type": "u64", 724 | "index": false 725 | }, 726 | { 727 | "name": "initialRealTokenReserves", 728 | "type": "u64", 729 | "index": false 730 | }, 731 | { 732 | "name": "tokenTotalSupply", 733 | "type": "u64", 734 | "index": false 735 | }, 736 | { 737 | "name": "feeBasisPoints", 738 | "type": "u64", 739 | "index": false 740 | } 741 | ] 742 | } 743 | } 744 | ], 745 | "errors": [ 746 | { 747 | "code": 6000, 748 | "name": "NotAuthorized", 749 | "msg": "The given account is not authorized to execute this instruction." 750 | }, 751 | { 752 | "code": 6001, 753 | "name": "AlreadyInitialized", 754 | "msg": "The program is already initialized." 755 | }, 756 | { 757 | "code": 6002, 758 | "name": "TooMuchSolRequired", 759 | "msg": "slippage: Too much SOL required to buy the given amount of tokens." 760 | }, 761 | { 762 | "code": 6003, 763 | "name": "TooLittleSolReceived", 764 | "msg": "slippage: Too little SOL received to sell the given amount of tokens." 765 | }, 766 | { 767 | "code": 6004, 768 | "name": "MintDoesNotMatchBondingCurve", 769 | "msg": "The mint does not match the bonding curve." 770 | }, 771 | { 772 | "code": 6005, 773 | "name": "BondingCurveComplete", 774 | "msg": "The bonding curve has completed and liquidity migrated to raydium." 775 | }, 776 | { 777 | "code": 6006, 778 | "name": "BondingCurveNotComplete", 779 | "msg": "The bonding curve has not completed." 780 | }, 781 | { 782 | "code": 6007, 783 | "name": "NotInitialized", 784 | "msg": "The program is not initialized." 785 | }, 786 | { 787 | "code": 6008, 788 | "name": "WithdrawTooFrequent", 789 | "msg": "Withdraw too frequent" 790 | } 791 | ] 792 | } 793 | --------------------------------------------------------------------------------