[
  {
    "path": ".gitignore",
    "content": "**/node_modules\n.DS_Store"
  },
  {
    "path": "README.md",
    "content": "# Solana SPL-Token Sniper\n## Overview\nThis project is Solana SPL-Token sniper which aims to swap (purchase) new Raydium liquidity pairs within the first price candle by scanning Solana blockchain transactions.\n## How the program works\n* Scans the Solana blockchain for an \"initialize market\" transaction which is decoded for all necessary liquidity pool keys and related information.\n* Begins sending/retrying the \"swap\" transaction until the liquidity pool is live, minimizing the time between the transaction and the creation of the LP.\n* Upon sending a valid transaction, begins to track the users position with current price/percent gain by scanning and decoding on-chain liquidity pool information in order to get the most accurate data.\n## Setup\nUse the following instructions to install and run the program (assume node is installed):\n1. Create a Solana wallet and obtain public and private keys (Phantom wallet recommended).\n2. Obtain a Solana RPC/websocket connection, can use `https://api.mainnet-beta.solana.com` and `wss://api.mainnet-beta.solana.com` for testing purposes.\n3. Run `npm install`.\n4. Inside the `utils/config.js` file, enter public key, private key, and both RPC connections. Also include amount of SOL to use per swap.\n## Running the scripts\nThis project contains two different strategies for sniping new liquidity pairs:\\\n### **Strategy #1:**\n* The first strategy obtains necessary liquidity pool keys from the transaction which creates the LP. To run this script with `node strategy1/start1.js`. The transaction may fail multiple times before succeeding as Solana transactions can be dropped with certain RPC nodes.\n* **NOTE:** this script is slower as it must wait for the \"add liquidity\" transaction to reach \"confirmed\" status before obtaining pool data. This results in ~30 seconds between the pool creation and swap transaction.\n### **Strategy #2:**\n* The second strategy obtains necessary liquidity pool keys from the \"initialize market\" transaction which typically occurs ~2 minutes before the LP is live on Raydium. This allows for all pool keys to be precomputed. This script also retries the swap transaction multiple times per second which allows for the swap to be sent during the \"processed\" state of the \"add liquidity\" transaction instead of \"confirmed\", greatly reducing the time between the creation of the LP and the swap transaction. This script can be run with `node strategy2/start2.js`.\n*Both scripts utilize the same swapping/position management system found in `./swap/swap1.js` and `/swap/swap2.js`.*\n### **Additional Notes:**\n* Once the program is started, an output will only be displayed once a new market id/pool is found.\n* \"the amm account owner is not match with this program + error 0x1b\": This error occurs when the program sends a swap tx to a pool that doesn't have liquidity yet. The tx spam is part of the sniping strategy and the error will occur until the swap to the pool goes through (moment liquidity is added).\n## Future improvements\n1. **Automatic position exit strategy:** Implementing an automatic exit strategy based on user-specified parameters. Currently have to manually swap the tokens back to SOL.\n2. **Rugpull prevention:** SPL-Token are often rugpulled after launch, prevent the purchase of tokens with low-liquidity and no social media pages.\n3. **Reducing tx time:** Reduce time between LP creation and swap tx by utilizing a faster RPC connection and minimizing RPC calls before sending swap tx.\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"dependencies\": {\n    \"@openbook-dex/openbook\": \"^0.0.9\",\n    \"@raydium-io/raydium-sdk\": \"^1.3.1-beta.46\",\n    \"@solana/spl-token\": \"^0.3.11\",\n    \"@solana/web3.js\": \"^1.87.6\",\n    \"borsh\": \"^2.0.0\",\n    \"bs64\": \"^0.1.0\",\n    \"node\": \"^21.2.0\"\n  },\n  \"name\": \"solana\",\n  \"version\": \"1.0.0\",\n  \"main\": \"tx.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"description\": \"\"\n}\n"
  },
  {
    "path": "strategy1/formatAmmKeysById.js",
    "content": "\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.formatAmmKeysById = void 0;\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst web3_js_1 = require(\"@solana/web3.js\");\nconst config_1 = require(\"../utils/config.js\");\nfunction formatAmmKeysById(id) {\n    return __awaiter(this, void 0, void 0, function* () {\n        const account = yield config_1.connection.getAccountInfo(new web3_js_1.PublicKey(id));\n        if (account === null)\n            throw Error(' get id info error ');\n        const info = raydium_sdk_1.LIQUIDITY_STATE_LAYOUT_V4.decode(account.data);\n        const marketId = info.marketId;\n        const marketAccount = yield config_1.connection.getAccountInfo(marketId);\n        if (marketAccount === null)\n            throw Error(' get market info error');\n        const marketInfo = raydium_sdk_1.MARKET_STATE_LAYOUT_V3.decode(marketAccount.data);\n        const lpMint = info.lpMint;\n        const lpMintAccount = yield config_1.connection.getAccountInfo(lpMint);\n        if (lpMintAccount === null)\n            throw Error(' get lp mint info error');\n        const lpMintInfo = raydium_sdk_1.SPL_MINT_LAYOUT.decode(lpMintAccount.data);\n        return {\n            id,\n            baseMint: info.baseMint.toString(),\n            quoteMint: info.quoteMint.toString(),\n            lpMint: info.lpMint.toString(),\n            baseDecimals: info.baseDecimal.toNumber(),\n            quoteDecimals: info.quoteDecimal.toNumber(),\n            // lpDecimals: lpMintInfo.decimals,\n            lpDecimals: info.baseDecimal.toNumber(),\n            version: 4,\n            programId: account.owner.toString(),\n            authority: raydium_sdk_1.Liquidity.getAssociatedAuthority({ programId: account.owner }).publicKey.toString(),\n            openOrders: info.openOrders.toString(),\n            targetOrders: info.targetOrders.toString(),\n            baseVault: info.baseVault.toString(),\n            quoteVault: info.quoteVault.toString(),\n            withdrawQueue: info.withdrawQueue.toString(),\n            lpVault: info.lpVault.toString(),\n            marketVersion: 3,\n            marketProgramId: info.marketProgramId.toString(),\n            marketId: info.marketId.toString(),\n            marketAuthority: raydium_sdk_1.Market.getAssociatedAuthority({ programId: info.marketProgramId, marketId: info.marketId }).publicKey.toString(),\n            marketBaseVault: marketInfo.baseVault.toString(),\n            marketQuoteVault: marketInfo.quoteVault.toString(),\n            marketBids: marketInfo.bids.toString(),\n            marketAsks: marketInfo.asks.toString(),\n            marketEventQueue: marketInfo.eventQueue.toString(),\n            lookupTableAccount: web3_js_1.PublicKey.default.toString()\n        };\n    });\n}\nexports.formatAmmKeysById = formatAmmKeysById;"
  },
  {
    "path": "strategy1/start1.js",
    "content": "const web3 = require('@solana/web3.js')\nconst WebSocket = require('ws')\nconst swap = require('./swap1.js')\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst config = require('../utils/config.js');\n\nconst connection = config.connection;\nconst ws = new WebSocket(config.websocketConnection)\n    ws.onopen = () => {\n        ws.send(\n            JSON.stringify({\n                jsonrpc: '2.0',\n                id: 1,\n                method: 'blockSubscribe',\n                params: [{\"mentionsAccountOrProgram\": \"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8\"}, {\"commitment\": \"confirmed\", \"maxSupportedTransactionVersion\": 0, \"encoding\": \"jsonParsed\"}]\n            })\n        )\n    }\n\nws.on('message', (evt) => {\n    try {\n        const buffer = evt.toString('utf8');\n        parseBlock(JSON.parse(buffer));\n        return;\n    } catch (e) {\n        console.log(e)\n    }\n})\n\nfunction isStatusError(status){\n    if(status.hasOwnProperty('Err')){\n        return true;\n    }\n    else if(status.hasOwnProperty('Ok')){\n        return false;\n    }\n}\n\nasync function getTx(tx){\n    return await connection.getTransaction(tx, {\n        \"commitment\": \"confirmed\",\n        \"maxSupportedTransactionVersion\": 0,\n        \"encoded\": \"jsonParsed\"\n    })\n}\n\nlet swapped = false;\nfunction parseBlock(transaction){\n    try{\n        const tx = transaction.params.result.value.block.transactions;\n        for(let i = 0; i < tx.length; i++){\n            if(tx[i].meta.innerInstructions !== undefined && tx[i].meta.innerInstructions.length !== 0){\n                if(tx[i].meta.innerInstructions[0].instructions.length === 32 && !isStatusError(tx[i].meta.status)){\n                    const signature = tx[i].transaction.signatures[0];\n                    console.log(tx[i].transaction.signatures);\n                    if(swapped === false){\n                        swapped = true;\n                        let now = new Date();\n                        let utcString = now.toUTCString();\n                        console.log(utcString);\n                        ws.close();\n                    }\n                }\n            }\n    }\n    } catch(error){\n        console.log(\"searching...\")\n    }\n}\n\nasync function getJsonPoolInfo(tx){\n    // market account\n    const marketAccount = await connection.getAccountInfo(new web3.PublicKey(tx.transaction.message.accountKeys[19].pubkey));\n    const marketInfo = raydium_sdk_1.MARKET_STATE_LAYOUT_V3.decode(marketAccount.data);\n    // get decimals\n    const getTokenAccount = await connection.getParsedAccountInfo(new web3.PublicKey(tx.transaction.message.accountKeys[17].pubkey));\n    const decimals = getTokenAccount.value.data.parsed.info.decimals;\n    // create poolKeys object\n    const keys = {\n        id: tx.transaction.message.accountKeys[2].pubkey,\n        baseMint: tx.transaction.message.accountKeys[17].pubkey,\n        quoteMint: 'So11111111111111111111111111111111111111112',\n        lpMint: tx.transaction.message.accountKeys[4].pubkey,\n        baseDecimals: decimals,\n        quoteDecimals: 9,\n        lpDecimals: decimals,\n        version: 4,\n        programId: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8',\n        authority: '5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1',\n        openOrders: tx.transaction.message.accountKeys[3].pubkey,\n        targetOrders: tx.transaction.message.accountKeys[7].pubkey,\n        baseVault: tx.transaction.message.accountKeys[5].pubkey,\n        quoteVault: tx.transaction.message.accountKeys[6].pubkey,\n        withdrawQueue: '11111111111111111111111111111111',\n        lpVault: '11111111111111111111111111111111',\n        marketVersion: 3,\n        marketProgramId: tx.transaction.message.accountKeys[22].pubkey,\n        marketId: tx.transaction.message.accountKeys[19].pubkey,\n        marketAuthority: raydium_sdk_1.Market.getAssociatedAuthority({ programId: new web3.PublicKey(tx.transaction.message.accountKeys[22].pubkey), marketId: new web3.PublicKey(tx.transaction.message.accountKeys[19].pubkey) }).publicKey.toString(),\n        marketBaseVault: marketInfo.baseVault.toString(),\n        marketQuoteVault: marketInfo.quoteVault.toString(),\n        marketBids: marketInfo.bids.toString(),\n        marketAsks: marketInfo.asks.toString(),\n        marketEventQueue: marketInfo.eventQueue.toString(),\n        lookupTableAccount: '11111111111111111111111111111111'\n    }\n    // convert poolKeys object to JSON\n    const jsonPoolKeys = raydium_sdk_1.jsonInfo2PoolKeys(keys);\n    swap.swap(jsonPoolKeys, tx.transaction.message.accountKeys[17].pubkey);\n}"
  },
  {
    "path": "strategy1/swap1.js",
    "content": "\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n    return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst assert_1 = __importDefault(require(\"assert\"));\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst config_1 = require(\"../utils/config.js\");\nconst formatAmmKeysById_1 = require(\"./formatAmmKeysById.js\");\nconst util_1 = require(\"../utils/util.js\");\nconst { LAMPORTS_PER_SOL } = require(\"@solana/web3.js\");\nconst web3 = require(\"@solana/web3.js\");\nconst connection = config_1.connection;\nfunction swapOnlyAmm(input) {\n    return __awaiter(this, void 0, void 0, function* () {\n        const outputToken = new raydium_sdk_1.Token(raydium_sdk_1.TOKEN_PROGRAM_ID, new web3.PublicKey(input.tokenAddress), input.poolKeys.lpDecimals);\n        const { innerTransactions } = yield raydium_sdk_1.Liquidity.makeSwapInstructionSimple({\n            connection: config_1.connection,\n            poolKeys: input.poolKeys,\n            userKeys: {\n                tokenAccounts: input.walletTokenAccounts,\n                owner: input.wallet.publicKey,\n            },\n            amountIn: input.inputTokenAmount,\n            amountOut: new raydium_sdk_1.TokenAmount(outputToken, 1),\n            fixedSide: 'in',\n            makeTxVersion: config_1.makeTxVersion,\n        });\n        return { txids: yield (0, util_1.buildAndSendTx)(innerTransactions) };\n    });\n}\n\nconst buyAmtSol = config_1.amtBuySol;\nfunction swap(poolKeys, tokenAddress) {\n    return __awaiter(this, void 0, void 0, function* () {\n        const ownerAddress = config_1.ownerAddress;\n        const inputToken = new raydium_sdk_1.Token(raydium_sdk_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey('So11111111111111111111111111111111111111112'), 9, 'WSOL', 'WSOL'); // WSOL\n        const inputTokenAmount = new raydium_sdk_1.TokenAmount(inputToken, LAMPORTS_PER_SOL * buyAmtSol);\n        const slippage = new raydium_sdk_1.Percent(1, 100);\n        const walletTokenAccounts = yield (0, util_1.getWalletTokenAccount)(config_1.connection, config_1.wallet.publicKey);\n        swapOnlyAmm({\n            poolKeys,\n            tokenAddress, \n            inputTokenAmount,\n            slippage,\n            walletTokenAccounts,\n            wallet: config_1.wallet,\n        }).then(({ txids }) => {\n            /** continue with txids */\n            console.log('txids', txids);\n            if(txids.length === 1){\n                monitorTokenSell(txids[0], tokenAddress, ownerAddress, poolKeys.baseVault.toString(), poolKeys.quoteVault.toString());\n            }\n        }).catch(error => {\n            console.log(error);\n            swap(poolKeys, tokenAddress);\n        })\n    });\n}\nexports.swap = swap\n\nasync function getTx(tx){\n    return await connection.getTransaction(tx, {\n        maxSupportedTransactionVersion: 0,\n        commitment: \"confirmed\"\n    })\n}\n\nasync function getBalances(tx, tokenAddress, ownerAddress){\n    let validTx = await getTx(tx);\n    while(validTx === null){\n        validTx = await getTx(tx);\n        if(validTx !== null){\n            for(const account of validTx.meta.postTokenBalances){\n                if(account.mint === tokenAddress && account.owner === ownerAddress){\n                    return account.uiTokenAmount.uiAmount;\n                }\n            }\n        }\n    }\n}\n\nasync function getTokenPriceInSol(baseVault, quoteVault){\n    const baseVaultAccount = await connection.getTokenAccountBalance(new web3.PublicKey(baseVault));\n    const quoteVaultAccount = await connection.getTokenAccountBalance(new web3.PublicKey(quoteVault));\n    const baseVaultAccountAmount = baseVaultAccount.value.uiAmount;\n    const quoteVaultAccountAmount = quoteVaultAccount.value.uiAmount;\n    return (quoteVaultAccountAmount / baseVaultAccountAmount);\n}\n\nasync function monitorTokenSell(tx, tokenAddress, ownerAddress, baseVault, quoteVault){\n    const tokenBalance = await getBalances(tx, tokenAddress, ownerAddress);\n    const buyPrice = (buyAmtSol / tokenBalance);\n    monitorToken(buyPrice, baseVault, quoteVault);\n}\n\nasync function monitorToken(buyPrice, baseVault, quoteVault){\n    let interval = setInterval(async () => {\n        const currentPrice = await getTokenPriceInSol(baseVault, quoteVault);\n        console.log(\"buy price: \" + buyPrice + \" current price: \" + currentPrice);\n        const percentIncrease = ((buyPrice - currentPrice) / buyPrice) * 100;\n        console.log(\"percent increase: \" + percentIncrease);\n    }, 500)\n}"
  },
  {
    "path": "strategy2/derivePoolKeys.js",
    "content": "const web3 = require('@solana/web3.js');\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst spl = require('@solana/spl-token');\nconst {Market} = require('@openbook-dex/openbook');\nconst config = require('../utils/config.js');\n\nconst connection = config.connection;\n\nconst wsolAddress = 'So11111111111111111111111111111111111111112';\nconst openbookProgramId = new web3.PublicKey('srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX');\n\nconst rayProgram = new web3.PublicKey('675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8');\nconst myAccount = new web3.PublicKey(config.ownerAddress);\n\nasync function derivePoolKeys(id){\n    console.log(id);\n    const marketId = new web3.PublicKey(id);\n\n    const marketInfo = await getMarketInfo(marketId);\n    const marketDeco = await getDecodedData(marketInfo);\n\n    const baseMint = marketDeco.baseMint;\n    const baseMintData = await getMintData(baseMint);\n    const baseDecimals = await getDecimals(baseMintData);\n    const ownerBaseAta = await getOwnerAta(baseMint, myAccount);\n    \n    const quoteMint = marketDeco.quoteMint;\n    const quoteMintData = await getMintData(quoteMint);\n    const quoteDecimals = await getDecimals(quoteMintData);\n    const ownerQuoteAta = await getOwnerAta(quoteMint, myAccount);\n\n    const authority = (raydium_sdk_1.findProgramAddress([Buffer.from([97, 109, 109, 32, 97, 117, 116, 104, 111, 114, 105, 116, 121])], rayProgram))['publicKey'];\n    // const marketAuthority = getVaultSigner(marketId, marketDeco);\n\n    const poolKeys = {\n        id: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('amm_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        baseMint: baseMint,\n        quoteMint, quoteMint,\n        lpMint: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('lp_mint_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        baseDecimals: baseDecimals,\n        quoteDecimals: quoteDecimals,\n        lpDecimals: baseDecimals,\n        version: 4,\n        programId: rayProgram,\n        authority: authority,\n        openOrders: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('open_order_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        targetOrders: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('target_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        baseVault: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('coin_vault_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        quoteVault: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('pc_vault_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        // withdrawQueue: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('withdraw_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        // lpVault: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('temp_lp_token_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        withdrawQueue: new web3.PublicKey('11111111111111111111111111111111'),\n        lpVault: new web3.PublicKey('11111111111111111111111111111111'),\n        marketVersion: 3,\n        marketProgramId: openbookProgramId,\n        // marketProgramId: new web3.PublicKey('9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'),\n        marketId: marketId,\n        marketAuthority: raydium_sdk_1.Market.getAssociatedAuthority({ programId: new web3.PublicKey('9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'), marketId: marketId }).publicKey,\n        marketBaseVault: marketDeco.baseVault,\n        marketQuoteVault: marketDeco.quoteVault,\n        marketBids: marketDeco.bids,\n        marketAsks: marketDeco.asks,\n        marketEventQueue: marketDeco.eventQueue,\n        // ownerBaseAta: ownerBaseAta,\n        // ownerQuoteAta: ownerQuoteAta,\n        // marketAuthority: marketAuthority,\n        // coinVault: raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), marketId.toBuffer(), Buffer.from('pc_vault_associated_seed', 'utf-8')], rayProgram)['publicKey'],\n        lookupTableAccount: web3.PublicKey.default\n    };\n    return poolKeys;\n}\nexports.derivePoolKeys = derivePoolKeys;\n\nasync function getMarketInfo(marketId){\n    const marketInfo = await connection.getAccountInfo(marketId);\n    return marketInfo;\n}\n\nasync function getDecodedData(marketInfo){\n    return await Market.getLayout(openbookProgramId).decode(marketInfo.data);\n}\n\nasync function getMintData(mint){\n    return await connection.getAccountInfo(mint);\n}\n\nasync function getDecimals(mintData){\n    return raydium_sdk_1.SPL_MINT_LAYOUT.decode(mintData.data).decimals;\n}\n\nasync function getOwnerAta(mint, publicKey){\n    const foundAta = web3.PublicKey.findProgramAddressSync([publicKey.toBuffer(), spl.TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()], spl.ASSOCIATED_TOKEN_PROGRAM_ID)[0];\n    return foundAta;\n}\n\nfunction getVaultSigner(marketId, marketDeco){\n    const seeds = [marketId.toBuffer()];\n    const seedsWithNonce = seeds.concat(Buffer.from([Number(marketDeco.vaultSignerNonce.toString())]), Buffer.alloc(7));\n    return web3.PublicKey.createProgramAddressSync(seedsWithNonce, openbookProgramId);\n}"
  },
  {
    "path": "strategy2/start2.js",
    "content": "const web3 = require('@solana/web3.js');\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst WebSocket = require('ws');\nconst derivePoolKeys = require('./derivePoolKeys.js');\nconst swap = require('./swap2.js');\nconst config = require('../utils/config.js');\n\nconst connection = config.connection;\n\nconst ws = new WebSocket(config.websocketConnection)\n    ws.onopen = () => {\n        ws.send(\n            JSON.stringify({\n                jsonrpc: '2.0',\n                id: 1,\n                method: 'blockSubscribe',\n                params: [{\"mentionsAccountOrProgram\": \"srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX\"}, {\"commitment\": \"confirmed\", \"maxSupportedTransactionVersion\": 0, \"encoding\": \"jsonParsed\"}]\n            })\n        )\n    }\n\nws.on('message', (evt) => {\n    try {\n        const buffer = evt.toString('utf8');\n        parseTxs(JSON.parse(buffer));\n        return;\n    } catch (e) {\n        console.log(e)\n    }\n})\n\nfunction parseTxs(txsFromBlock){\n    if(txsFromBlock.params === undefined){\n        return;\n    }\n    const allTx = txsFromBlock.params.result.value.block.transactions;\n    for(const tx of allTx){\n        if(parseLogs(tx.meta.logMessages) && tx.transaction.message.accountKeys.length === 13 && tx.transaction.message.instructions.length === 6){\n            ws.close();\n            console.log(tx.transaction.signatures)\n            parseAccountKeys(tx.transaction.message.accountKeys, tx.transaction.signatures);\n        }\n    }\n}\n\nfunction parseLogs(logs){\n    let invoke = 0;\n    let consumed = 0;\n    let success = 0;\n    for(const log of logs){\n        if(log.includes(\"Program srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX invoke\")){\n            invoke += 1;\n        }\n        if(log.includes(\"Program srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX consumed\")){\n            consumed += 1;\n        }\n        if(log.includes(\"Program srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX success\")){\n            success += 1;\n        }\n    }\n    if(invoke === 1 && consumed === 1 && success === 1){\n        return true;\n    } else{\n        return false;\n    }\n}\n\nasync function parseAccountKeys(keys, signature){\n    let marketId = null;\n    for(const key of keys){\n        console.log(key);\n        const keyData = await connection.getAccountInfo(new web3.PublicKey(key.pubkey));\n        if(keyData !== null && keyData.data.length === 388){\n            marketId = key.pubkey;\n        }\n    }\n    if(marketId === null){\n        parseAccountKeys(keys);\n    } else{\n        const poolKeys = await derivePoolKeys.derivePoolKeys(marketId);\n        swap.swap(poolKeys, signature);\n    }\n}"
  },
  {
    "path": "strategy2/swap2.js",
    "content": "\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n    return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst assert_1 = __importDefault(require(\"assert\"));\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst config_1 = require(\"../utils/config.js\");\nconst util_1 = require(\"../utils/util.js\");\nconst { LAMPORTS_PER_SOL } = require(\"@solana/web3.js\");\nconst web3 = require(\"@solana/web3.js\");\nconst connection = config_1.connection;\nfunction swapOnlyAmm(input) {\n    return __awaiter(this, void 0, void 0, function* () {\n        const outputToken = new raydium_sdk_1.Token(raydium_sdk_1.TOKEN_PROGRAM_ID, new web3.PublicKey(input.tokenAddress), input.poolKeys.lpDecimals);\n        const { innerTransactions } = yield raydium_sdk_1.Liquidity.makeSwapInstructionSimple({\n            connection: config_1.connection,\n            poolKeys: input.poolKeys,\n            userKeys: {\n                tokenAccounts: input.walletTokenAccounts,\n                owner: input.wallet.publicKey,\n            },\n            amountIn: input.inputTokenAmount,\n            amountOut: new raydium_sdk_1.TokenAmount(outputToken, 1),\n            fixedSide: 'in',\n            makeTxVersion: config_1.makeTxVersion,\n        });\n        return { txids: yield (0, util_1.buildAndSendTx)(innerTransactions) };\n    });\n}\n\nconst buyAmtSol = config_1.amtBuySol;\nfunction swap(poolKeys, signature) {\n    return __awaiter(this, void 0, void 0, function* () {\n        const ownerAddress = config_1.ownerAddress;\n        const inputToken = new raydium_sdk_1.Token(raydium_sdk_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey('So11111111111111111111111111111111111111112'), 9, 'WSOL', 'WSOL'); // WSOL\n        const inputTokenAmount = new raydium_sdk_1.TokenAmount(inputToken, LAMPORTS_PER_SOL * buyAmtSol);\n        const slippage = new raydium_sdk_1.Percent(1, 100);\n        const walletTokenAccounts = yield (0, util_1.getWalletTokenAccount)(config_1.connection, config_1.wallet.publicKey);\n        swapOnlyAmm({\n            poolKeys,\n            tokenAddress: poolKeys.baseMint.toString(), \n            inputTokenAmount,\n            slippage,\n            walletTokenAccounts,\n            wallet: config_1.wallet,\n        }).then(({ txids }) => {\n            /** continue with txids */\n            console.log('txids', txids);\n            if(txids.length === 1){\n                monitorTokenSell(txids[0], poolKeys.baseMint.toString(), ownerAddress, poolKeys.baseVault.toString(), poolKeys.quoteVault.toString());\n            }\n        }).catch(error => {\n            console.log(signature);\n            console.log(error);\n            swap(poolKeys, poolKeys.baseMint.toString());\n        })\n    });\n}\nexports.swap = swap\n\nasync function getTx(tx){\n    return await connection.getTransaction(tx, {\n        maxSupportedTransactionVersion: 0,\n        commitment: \"confirmed\"\n    })\n}\n\nasync function getBalances(tx, tokenAddress, ownerAddress){\n    let validTx = await getTx(tx);\n    while(validTx === null){\n        validTx = await getTx(tx);\n        if(validTx !== null){\n            for(const account of validTx.meta.postTokenBalances){\n                if(account.mint === tokenAddress && account.owner === ownerAddress){\n                    return account.uiTokenAmount.uiAmount;\n                }\n            }\n        }\n    }\n}\n\nasync function getTokenPriceInSol(baseVault, quoteVault){\n    const baseVaultAccount = await connection.getTokenAccountBalance(new web3.PublicKey(baseVault));\n    const quoteVaultAccount = await connection.getTokenAccountBalance(new web3.PublicKey(quoteVault));\n    const baseVaultAccountAmount = baseVaultAccount.value.uiAmount;\n    const quoteVaultAccountAmount = quoteVaultAccount.value.uiAmount;\n    return (quoteVaultAccountAmount / baseVaultAccountAmount);\n}\n\nasync function monitorTokenSell(tx, tokenAddress, ownerAddress, baseVault, quoteVault){\n    const tokenBalance = await getBalances(tx, tokenAddress, ownerAddress);\n    const buyPrice = (buyAmtSol / tokenBalance);\n    monitorToken(buyPrice, baseVault, quoteVault);\n}\n\nasync function monitorToken(buyPrice, baseVault, quoteVault){\n    let interval = setInterval(async () => {\n        const currentPrice = await getTokenPriceInSol(baseVault, quoteVault);\n        console.log(\"buy price: \" + buyPrice + \" current price: \" + currentPrice);\n        const percentIncrease = ((buyPrice - currentPrice) / buyPrice) * 100;\n        console.log(\"percent increase: \" + percentIncrease);\n    }, 500)\n}"
  },
  {
    "path": "utils/config.js",
    "content": "const bs58 = require('bs58');\n\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.DEFAULT_TOKEN = exports.addLookupTableInfo = exports.makeTxVersion = exports.RAYDIUM_MAINNET_API = exports.ENDPOINT = exports.PROGRAMIDS = exports.connection = exports.wallet = exports.rpcToken = exports.rpcUrl = void 0;\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst web3_js_1 = require(\"@solana/web3.js\");\nexports.ownerAddress = '<YOUR WALLET PUBLIC KEY>';\nexports.wallet = web3_js_1.Keypair.fromSecretKey(bs58.decode('<YOUR PRIVATE KEY>'));\nexports.connection = new web3_js_1.Connection('<YOUR RPC CONNECTION URL>');\nexports.websocketConnection = '<YOUR WEBSOCKET CONNECTION URL>';\nexports.amtBuySol = '<INTEGER AMOUNT OF SOL TO USER PER SWAP, EX. 0.001>';\nexports.PROGRAMIDS = raydium_sdk_1.MAINNET_PROGRAM_ID;\nexports.ENDPOINT = raydium_sdk_1.ENDPOINT;\nexports.RAYDIUM_MAINNET_API = raydium_sdk_1.RAYDIUM_MAINNET;\nexports.makeTxVersion = raydium_sdk_1.TxVersion.V0; // LEGACY\nexports.addLookupTableInfo = raydium_sdk_1.LOOKUP_TABLE_CACHE;\n"
  },
  {
    "path": "utils/decoderaylog.js",
    "content": "const web3 = require('@solana/web3.js');\nconst WebSocket = require('ws');\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst bs64 = require('bs64');\nconst config = require('./config');\n\nconst connection = config.connection;\n\nconst feeAddress = '7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5'\nconst rayProgram = new web3.PublicKey('675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8');\n\nconst ws = new WebSocket(config.websocketConnection)\n    ws.onopen = () => {\n        ws.send(\n            JSON.stringify({\n                jsonrpc: '2.0',\n                id: 1,\n                method: 'logsSubscribe',\n                params: [{\"mentions\": [feeAddress]}, {\"commitment\": \"processed\"}]\n            })\n        )\n    }\n\nws.on('message', (evt) => {\n    try {\n        const buffer = evt.toString('utf8');\n        parseLogs(JSON.parse(buffer));\n        return;\n    } catch (e) {\n        console.log(e)\n    }\n})\n\nfunction parseLogs(buffer){\n    if(buffer.params === undefined){\n        return;\n    }\n    let now = new Date();\n    let utcString = now.toUTCString();\n    console.log(utcString);\n    const allLogs = buffer.params.result.value.logs;\n    for(const log of allLogs){\n        if(log.includes(\"ray_log\")){\n            const rayLogSplit = log.split(\" \");\n            const rayLog = rayLogSplit[3];\n            const logData = Buffer.from(rayLog, \"base64\");\n            const market = new web3.PublicKey(logData.subarray(75 - 32), 75);\n            console.log(market)\n            const pool = raydium_sdk_1.findProgramAddress([rayProgram.toBuffer(), market.toBuffer(), Buffer.from('amm_associated_seed', 'utf-8')], rayProgram)['publicKey'];\n            console.log(pool);\n        }\n    }\n}"
  },
  {
    "path": "utils/util.js",
    "content": "\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.sleepTime = exports.getATAAddress = exports.buildAndSendTx = exports.getWalletTokenAccount = exports.sendTx = void 0;\nconst raydium_sdk_1 = require(\"@raydium-io/raydium-sdk\");\nconst web3_js_1 = require(\"@solana/web3.js\");\nconst config_1 = require(\"./config\");\nfunction sendTx(connection, payer, txs, options) {\n    return __awaiter(this, void 0, void 0, function* () {\n        const txids = [];\n        for (const iTx of txs) {\n            if (iTx instanceof web3_js_1.VersionedTransaction) {\n                iTx.sign([payer]);\n                txids.push(yield connection.sendTransaction(iTx, options));\n            }\n            else {\n                txids.push(yield connection.sendTransaction(iTx, [payer], options));\n            }\n        }\n        return txids;\n    });\n}\nexports.sendTx = sendTx;\nfunction getWalletTokenAccount(connection, wallet) {\n    return __awaiter(this, void 0, void 0, function* () {\n        const walletTokenAccount = yield connection.getTokenAccountsByOwner(wallet, {\n            programId: raydium_sdk_1.TOKEN_PROGRAM_ID,\n        });\n        return walletTokenAccount.value.map((i) => ({\n            pubkey: i.pubkey,\n            programId: i.account.owner,\n            accountInfo: raydium_sdk_1.SPL_ACCOUNT_LAYOUT.decode(i.account.data),\n        }));\n    });\n}\nexports.getWalletTokenAccount = getWalletTokenAccount;\nfunction buildAndSendTx(innerSimpleV0Transaction, options) {\n    return __awaiter(this, void 0, void 0, function* () {\n        const willSendTx = yield (0, raydium_sdk_1.buildSimpleTransaction)({\n            connection: config_1.connection,\n            makeTxVersion: config_1.makeTxVersion,\n            payer: config_1.wallet.publicKey,\n            innerTransactions: innerSimpleV0Transaction,\n            addLookupTableInfo: config_1.addLookupTableInfo,\n        });\n        return yield sendTx(config_1.connection, config_1.wallet, willSendTx, options);\n    });\n}\nexports.buildAndSendTx = buildAndSendTx;\nfunction getATAAddress(programId, owner, mint) {\n    const { publicKey, nonce } = (0, raydium_sdk_1.findProgramAddress)([owner.toBuffer(), programId.toBuffer(), mint.toBuffer()], new web3_js_1.PublicKey(\"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL\"));\n    return { publicKey, nonce };\n}\nexports.getATAAddress = getATAAddress;\nfunction sleepTime(ms) {\n    return __awaiter(this, void 0, void 0, function* () {\n        console.log((new Date()).toLocaleString(), 'sleepTime', ms);\n        return new Promise(resolve => setTimeout(resolve, ms));\n    });\n}\nexports.sleepTime = sleepTime;\n//# sourceMappingURL=util.js.map"
  }
]