import { PublicKey, TransactionInstruction } from "@solana/web3.js"; export function processJupInstruction(instruction: { programId: string; accounts: { pubkey: string; isSigner: boolean; isWritable: boolean; }[]; data: string; }): TransactionInstruction { return { programId: new PublicKey(instruction.programId), keys: instruction.accounts.map((a: { pubkey: string; isSigner: boolean; isWritable: boolean; }) => ({ ...a, pubkey: new PublicKey(a.pubkey) })), data: Buffer.from(instruction.data, "base64") }; } export async function getJupQuote(params: { keeper: PublicKey, basketMintIn: PublicKey, basketMintOut: PublicKey, basketAmountIn: number, basketAmountOut: number, swapMode: "exact_in" | "exact_out" | "ioc", apiKey: string, maxJupAccounts: number, }): Promise<{ mode: string, inputMint: string, outputMint: string, inAmount: number, outAmount: number, swapUsdValue: number, routePlan: any, transaction: string, }> { let options = {method: 'GET', headers: {'x-api-key': params.apiKey}}; let reqUrl = 'https://api.jup.ag/swap/v1/quote' + '?inputMint=' + params.basketMintOut.toBase58() + '&outputMint=' + params.basketMintIn.toBase58() + '&amount=' + (params.swapMode == "exact_in" ? params.basketAmountIn : params.basketAmountOut) + '&swapMode=' + (params.swapMode == "exact_in" ? "ExactOut" : "ExactIn") + '&maxAccounts=' + params.maxJupAccounts; let res = await fetch(reqUrl, options).then(res => res.json()) return res; } export async function getJupSwapInstructions(params: { keeper: PublicKey, quoteResponse: any, apiKey: string, }): Promise { let reqUrl = 'https://api.jup.ag/swap/v1/swap-instructions' let body = { userPublicKey: params.keeper.toBase58(), quoteResponse: params.quoteResponse, wrapAndUnwrapSol: false, useTokenLedger: true, } let options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': params.apiKey }, body: JSON.stringify(body), }; let res = await fetch(reqUrl, options).then(res => res.json()) return res; } export async function getJupTokenLedgerAndSwapInstructions(params: { keeper: PublicKey, basketMintIn: PublicKey, basketMintOut: PublicKey, basketAmountIn: number, basketAmountOut: number, swapMode: "exact_in" | "exact_out" | "ioc", apiKey: string, maxJupAccounts: number, }): Promise<{ tokenLedgerInstruction: TransactionInstruction, swapInstruction: TransactionInstruction, addressLookupTableAddresses: PublicKey[], quoteResponse: any, }> { try { let quoteResponse = await getJupQuote(params); let swapInstructions = await getJupSwapInstructions({ ...params, quoteResponse }); return { tokenLedgerInstruction: processJupInstruction(swapInstructions.tokenLedgerInstruction), swapInstruction: processJupInstruction(swapInstructions.swapInstruction), addressLookupTableAddresses: swapInstructions.addressLookupTableAddresses.map((a: string) => new PublicKey(a)), quoteResponse: quoteResponse, }; } catch (e) { console.log("Error getting Jup Instructions:", params.basketMintOut.toBase58(), params.basketMintIn.toBase58(), params.basketAmountOut); return { tokenLedgerInstruction: undefined as any, swapInstruction: undefined as any, addressLookupTableAddresses: [], quoteResponse: undefined, }; } }