import { VersionedTransaction, PublicKey, LAMPORTS_PER_SOL, } from "@solana/web3.js"; import { SolanaAgentKit } from "../index"; import { TOKENS, DEFAULT_OPTIONS, JUP_API, JUP_REFERRAL_ADDRESS, } from "../constants"; import dotenv from "dotenv"; // Load environment variables dotenv.config(); /** * Swap tokens using Jupiter Exchange * @param agent SolanaAgentKit instance * @param outputMint Target token mint address * @param inputAmount Amount to swap (in token decimals) * @param inputMint Source token mint address (defaults to USDC) * @param slippageBps Slippage tolerance in basis points (default: 300 = 3%) * @returns Transaction signature */ // Get Jupiter fee and referral account from environment variables const JUP_FEE_BPS = process.env.JUP_FEE_BPS ? parseInt(process.env.JUP_FEE_BPS) : ""; const JUP_REFERRAL_ACCOUNT = process.env.JUP_REFERRAL_ACCOUNT ? new PublicKey(process.env.JUP_REFERRAL_ACCOUNT) : ""; export async function trade( agent: SolanaAgentKit, outputMint: PublicKey, inputAmount: number, inputMint: PublicKey = TOKENS.USDC, slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS, ): Promise { try { const quoteResponse = await ( await fetch( `${JUP_API}/quote?` + `inputMint=${inputMint.toString()}` + `&outputMint=${outputMint.toString()}` + `&amount=${inputAmount * LAMPORTS_PER_SOL}` + `&slippageBps=${slippageBps}` + `&onlyDirectRoutes=true` + `&maxAccounts=20` + `${JUP_FEE_BPS ? `&platformFeeBps=${JUP_FEE_BPS}` : ""}`, ) ).json(); // Get serialized transaction let feeAccount; if (JUP_REFERRAL_ACCOUNT) { [feeAccount] = await PublicKey.findProgramAddressSync( [ Buffer.from("referral_ata"), new PublicKey(JUP_REFERRAL_ACCOUNT).toBuffer(), TOKENS.SOL.toBuffer(), ], new PublicKey(JUP_REFERRAL_ADDRESS), ); } const { swapTransaction } = await ( await fetch("https://quote-api.jup.ag/v6/swap", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ quoteResponse, userPublicKey: agent.wallet_address.toString(), wrapAndUnwrapSol: true, dynamicComputeUnitLimit: true, prioritizationFeeLamports: "auto", feeAccount: feeAccount ? feeAccount.toString() : null, }), }) ).json(); // Deserialize transaction const swapTransactionBuf = Buffer.from(swapTransaction, "base64"); const transaction = VersionedTransaction.deserialize(swapTransactionBuf); // Sign and send transaction transaction.sign([agent.wallet]); const signature = await agent.connection.sendTransaction(transaction); return signature; } catch (error: any) { throw new Error(`Swap failed: ${error.message}`); } }