Created
January 30, 2024 03:10
-
-
Save mavenharry1/132888e70e0a98bc0df60a1cd4d13d57 to your computer and use it in GitHub Desktop.
Jupiter Token Swap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import axios from 'axios'; | |
| import { Connection, Keypair, VersionedTransaction } from '@solana/web3.js'; | |
| import { Wallet } from '@project-serum/anchor'; | |
| import { bs58 } from '@project-serum/anchor/dist/cjs/utils/bytes'; | |
| const RPC_HTTP_NODE = "https://grateful-jerrie-fast-mainnet.helius-rpc.com"; //YOU CAN CHANGE TO YOUR RPC | |
| const WALLET_PRIVATE_KEY = ""; //YOUR PRIVATE KEY - ALWAYS KEEP THIS A SECRET | |
| const CONNECTION = new Connection(RPC_HTTP_NODE); | |
| const WALLET = new Wallet(Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY || ''))); | |
| const PAIR_TOKEN = { | |
| address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", //USDC - YOU CAN CHANGE TO ANY TOKEN e.g; SOL | |
| decimals: 6 | |
| } | |
| export class TradeToken { | |
| private fromToken: string; | |
| private toToken: string; | |
| private amount: number; | |
| private slippage: number; | |
| private decimals: number; | |
| constructor(action: "buy" | "sell", token: string, amount: number, slippage: number, decimals: number) { | |
| this.amount = amount; | |
| this.slippage = slippage; | |
| this.fromToken = action === "buy" ? PAIR_TOKEN.address : token; | |
| this.toToken = action === "buy" ? token : PAIR_TOKEN.address; | |
| this.decimals = action === "buy" ? PAIR_TOKEN.decimals : decimals; | |
| this.run(); | |
| } | |
| private async run() { | |
| try { | |
| const quote = await this.getQuote(); | |
| const swapTransaction = await this.createSwapTransaction(quote); | |
| if(swapTransaction) { | |
| const signedTransaction = await this.signTransaction(swapTransaction); | |
| await this.executeTransaction(signedTransaction); | |
| } else { | |
| console.error('No swap transaction found'); | |
| } | |
| } catch (error) { | |
| console.error('Error:', error); | |
| } | |
| } | |
| private async getQuote() { | |
| try { | |
| console.log('Fetching quote...'); | |
| const response = await axios.get('https://quote-api.jup.ag/v6/quote', { | |
| params: { | |
| inputMint: this.fromToken, | |
| outputMint: this.toToken, | |
| amount: Math.floor(this.amount * Math.pow(10, this.decimals)), | |
| slippageBps: this.slippage * 100, | |
| onlyDirectRoutes: false, | |
| asLegacyTransaction: false, | |
| maxAccounts: 64, | |
| experimentalDexes: "Jupiter LO" | |
| } | |
| }); | |
| return response?.data; | |
| } catch (error) { | |
| console.error('Error fetching quote:', error?.response?.data?.error); | |
| } | |
| } | |
| private async createSwapTransaction(quote: any) { | |
| try { | |
| console.log('Creating swap transaction...'); | |
| const response = await axios.post('https://quote-api.jup.ag/v6/swap', { | |
| quoteResponse: quote, | |
| userPublicKey: WALLET.publicKey?.toBase58(), | |
| wrapAndUnwrapSol: true, | |
| prioritizationFeeLamports: "auto", | |
| asLegacyTransaction: false, | |
| dynamicComputeUnitLimit: true | |
| }); | |
| return response?.data?.swapTransaction; | |
| } catch (error) { | |
| console.error('Error creating swap transaction:', error?.response?.data?.error); | |
| } | |
| } | |
| private async signTransaction(txn: any) { | |
| try { | |
| console.log('Signing transaction...'); | |
| const swapTransactionBuf = Buffer.from(txn, 'base64'); | |
| const transaction = VersionedTransaction.deserialize(swapTransactionBuf); | |
| transaction.sign([WALLET.payer]); | |
| return transaction; | |
| } catch (error) { | |
| console.error('Error signing transaction:', error?.response?.data?.error); | |
| } | |
| } | |
| private async executeTransaction(txn: any) { | |
| try { | |
| console.log('Executing transaction...'); | |
| const rawTransaction = txn.serialize(); | |
| txn.feePayer = WALLET.publicKey; | |
| txn.recentBlockhash = (await CONNECTION.getLatestBlockhash()).blockhash; | |
| const signature = await CONNECTION.sendRawTransaction(rawTransaction, { | |
| skipPreflight: false, | |
| maxRetries: 5, | |
| preflightCommitment: 'confirmed', | |
| }); | |
| await CONNECTION.confirmTransaction(signature, "confirmed"); | |
| console.log(`https://solana.fm/tx/${signature}`); | |
| } catch (error) { | |
| console.error('Error executing transaction:', error?.message); | |
| } | |
| } | |
| } | |
| // Arguments | |
| const action = process.argv[2]; | |
| const token = process.argv[3]; | |
| const decimals = Number(process.argv[4]); | |
| const amount = Number(process.argv[5]); | |
| const slippage = Number(process.argv[6]); | |
| if (action && token && amount && slippage && decimals) { | |
| new TradeToken(action as "buy" | "sell", token, amount, slippage, decimals); | |
| } else { | |
| console.error('Provide a valid action (buy/sell) | token (address) | decimals | amount | slippage'); | |
| process.exit(1); | |
| } | |
| // RUN COMMAND | |
| // ts-node trade-token.ts [action] [token address] [token decimal] [amount] [slippage] | |
| // EXAMPLES; | |
| // ts-node trade-token.ts buy WENWENvqqNya429ubCdR81ZmD69brwQaaBYY6p3LCpk 5 100 0.5 | |
| // ts-node trade-token.ts sell WENWENvqqNya429ubCdR81ZmD69brwQaaBYY6p3LCpk 5 34978.98922 1 | |
| // NB: For very volatile tokens, increase slippage to a higher value e.g; 10 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment