jup-ag / jupiter-quote-api-node

91 stars 32 forks source link

Why does using Jupiter API swap-instructions to invoke a wallet not show correct data, but using swapTransaction works fine? #33

Open yyidota opened 2 months ago

yyidota commented 2 months ago

I'm encountering an issue with the Jupiter API V6 Swap API when invoking a wallet. Using swapTransaction, everything works perfectly, but when using swap-instructions, the wallet does not display the correct data. Here is the relevant part of my code:

import { SOL_COIN_ADDR } from '@/config';
import { createJupiterApiClient } from '@jup-ag/api';
import { AddressLookupTableAccount, ComputeBudgetProgram, Connection, PublicKey, TransactionInstruction, TransactionMessage, VersionedTransaction } from '@solana/web3.js';

const jupiterQuoteApi = createJupiterApiClient();

const deserializeInstruction = (instruction) => {
  return new TransactionInstruction({
    programId: new PublicKey(instruction.programId),
    keys: instruction.accounts.map((key) => ({
      pubkey: new PublicKey(key.pubkey),
      isSigner: key.isSigner,
      isWritable: key.isWritable,
    })),
    data: Buffer.from(instruction.data, "base64"),
  });
};

const getAddressLookupTableAccounts = async (connection, keys) => {
  const addressLookupTableAccountInfos = await connection.getMultipleAccountsInfo(
    keys.map((key) => new PublicKey(key))
  );

  return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => {
    const addressLookupTableAddress = keys[index];
    if (accountInfo) {
      const addressLookupTableAccount = new AddressLookupTableAccount({
        key: new PublicKey(addressLookupTableAddress),
        state: AddressLookupTableAccount.deserialize(accountInfo.data),
      });
      acc.push(addressLookupTableAccount);
    }
    return acc;
  }, []);
};

export async function queryInfo() {
  const quote = await jupiterQuoteApi.quoteGet({
    inputMint: SOL_COIN_ADDR,
    outputMint: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
    amount: 0.001 * Math.pow(10, 9),
    slippageBps: 50,
    asLegacyTransaction: false,
  });

  return quote;
}

export async function getIns(quoteResponse, owner) {
  const instructions = await jupiterQuoteApi.swapInstructionsPost({
    swapRequest: {
      "quoteResponse": quoteResponse,
      "userPublicKey": owner.toString(),
      "asLegacyTransaction": false,
      "prioritizationFeeLamports": "auto",
      "feeAccount": "D2D7GpNq38G8fgZM6ujtaBEts7CsxHFmabzHojuPVPYp"
    }
  });

  return instructions;
}

export async function getJupTranstion(connection, instructions, owner) {
  const {
    computeBudgetInstructions,
    setupInstructions,
    swapInstruction: swapInstructionPayload,
    cleanupInstruction,
    addressLookupTableAddresses,
  } = instructions;

  const addressLookupTableAccounts = await getAddressLookupTableAccounts(connection, addressLookupTableAddresses);

  const computeUnitMaxLimit = 10000;
  const microLamports = 50000;

  const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnitMaxLimit });
  const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: Number(microLamports) });

  const swapInstruction = deserializeInstruction(swapInstructionPayload);

  const blockhash = (await connection.getLatestBlockhash()).blockhash;
  const messageV0 = new TransactionMessage({
    payerKey: owner,
    recentBlockhash: blockhash,
    instructions: [
      // Uncomment if needed
      // modifyComputeUnits,
      // addPriorityFee,
      swapInstruction,
      // Uncomment if needed
      // deserializeInstruction(cleanupInstruction),
    ],
  }).compileToV0Message(addressLookupTableAccounts);

  const transaction = new VersionedTransaction(messageV0);

  return {
    transaction,
    blockhash
  };
}
 async function jupSwap() {
    const  quote = await queryInfo()
    const ins = await getIns(quote, publicKey)
    const { transaction } = await getJupTranstion(connection, ins, publicKey)

    const signedTxns = await signAllTransactions([transaction]);

  }

log

{
    "context": {
        "apiVersion": "1.17.28",
        "slot": 266085023
    },
    "value": {
        "accounts": null,
        "err": {
            "InstructionError": [
                0,
                "ProgramFailedToComplete"
            ]
        },
        "logs": [
            "Program JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 invoke [1]",
            "Program log: Instruction: SharedAccountsRoute",
            "Program log: panicked at 'range end index 64 out of range for slice of length 0', src/token.rs:551:38",
            "Program JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 consumed 16399 of 200000 compute units",
            "Program JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 failed: SBF program panicked"
        ],
        "returnData": null,
        "unitsConsumed": 0
    }
}

When using swap-instructions, the wallet does not display the correct data, but with swapTransaction, it works fine. Could someone help me identify what might be going wrong? screenshot-20240516-102203

Additional Details: Solana Network Version: 1.9.25 Wallet: Phantom Thanks in advance for any insights!