raydium-io / raydium-sdk-V2-demo

Open-source Typescript SDK demos
48 stars 31 forks source link

Token swap not happening for the entire amount I pass in case of CPMM tokens #55

Closed tushar-sahoo closed 2 months ago

tushar-sahoo commented 3 months ago

While trying to swap CPMM tokens to SOL there is always I small residue amount left in the token wallet even though I am passing the entire token balance for swap. Do I need to make any changes in the code to achieve this?

 const reserveA =
                (poolInfo.mintA.address.toString() === SOLANA_ADDRESS) ===
                bIsTokenSwap
                    ? rpcData.quoteReserve
                    : rpcData.baseReserve;
            const reserveB =
                (poolInfo.mintA.address.toString() === SOLANA_ADDRESS) ===
                bIsTokenSwap
                    ? rpcData.baseReserve
                    : rpcData.quoteReserve;
            const baseIn =
                (poolInfo.mintA.address.toString() === SOLANA_ADDRESS) ===
                bIsTokenSwap
                    ? false
                    : true;

            const swapResult = CurveCalculator.swap(
                inputAmount,
                reserveA,
                reserveB,
                rpcData.configInfo.tradeFeeRate,
            );

            if (!swapResult) {
                log.red('Error in computing CPMM swap result');
                return false;
            }

            const swap = await raydium.cpmm.swap({
                poolInfo,
                swapResult,
                slippage: 0.005,
                baseIn: baseIn,
                computeBudgetConfig: {
                    units: 200000,
                    microLamports: 250000,
                },
            });
cruzshia commented 3 months ago

if the pool you want to swap doesn't have enough liquidity, swap amount might not be fully charged, also if the input token is token 2022 with transfer fee, there might be little amount left in tx, because we can't estimate the fee with 100% correct the same with on chian data.

tushar-sahoo commented 3 months ago

This is a transaction I did using raydium v3 UI: https://solscan.io/tx/4qiYAPe2RQXwDitf2YHSkVmniBdb9sP62JBZciYtNiZ8sYL4uzEm6drzE3NUwp1uFtCuvZAqYjjFdZ95wa34fucc

And this is a transaction I did using the code provided in the demo: https://solscan.io/tx/ZWKNQbN8LMPAwuCrBk7c7e6r3wGNFdhNn5J91sFn9fVifY3sesDLSucUJfDhKWAGUok1yVyKunnfhUxqqHHrcx5

Both are for the same token and in both cases I am trying to swap the entire balance of the tokens available. While it works perfectly in raydium v3 UI, it leaves around 200 something tokens while trying to swap using the demo code.

cruzshia commented 3 months ago

after reviewing code, did you modify inputMint to HBoNJ5v8g71s2boRivrHnfSB5MVPLDHHyVjruPfhGkvL ? const inputMint = 'HBoNJ5v8g71s2boRivrHnfSB5MVPLDHHyVjruPfhGkvL' and then baseIn should be false

I think the issue was caused by passing wrong baseReserve and quoteReserve to

const swapResult = CurveCalculator.swap(
                inputAmount,
                reserveA,
                reserveB,
                rpcData.configInfo.tradeFeeRate,
            );

I don't know what bIsTokenSwap means , but second and third params for CurveCalculator.swap should be decided by baseIn

cruzshia commented 3 months ago

here the full code, all token will be swapped.

const raydium = await initSdk()

  // SOL - USDC pool
  const poolId = 'CpoYFgaNA6MJRuJSGeXu9mPdghmtwd5RvYesgej4Zofj'
  let poolInfo: ApiV3PoolInfoStandardItemCpmm
  let poolKeys: CpmmKeys | undefined
  let rpcData: CpmmRpcData

  if (raydium.cluster === 'mainnet') {
    // note: api doesn't support get devnet pool info, so in devnet else we go rpc method
    // if you wish to get pool info from rpc, also can modify logic to go rpc method directly
    const data = await raydium.api.fetchPoolById({ ids: poolId })
    poolInfo = data[0] as ApiV3PoolInfoStandardItemCpmm
    if (!isValidCpmm(poolInfo.programId)) throw new Error('target pool is not CPMM pool')
    rpcData = await raydium.cpmm.getRpcPoolInfo(poolInfo.id, true)
  } else {
    const data = await raydium.cpmm.getPoolInfoFromRpc(poolId)
    poolInfo = data.poolInfo
    poolKeys = data.poolKeys
    rpcData = data.rpcData
  }

  const inputAmount = new BN(430395)
  const inputMint = 'HBoNJ5v8g71s2boRivrHnfSB5MVPLDHHyVjruPfhGkvL'
  const baseIn = inputMint === poolInfo.mintA.address

  // swap pool mintA for mintB
  const swapResult = CurveCalculator.swap(
    inputAmount,
    baseIn ? rpcData.baseReserve : rpcData.quoteReserve,
    baseIn ? rpcData.quoteReserve : rpcData.baseReserve,
    rpcData.configInfo!.tradeFeeRate
  )

  /**
   * swapResult.sourceAmountSwapped -> input amount
   * swapResult.destinationAmountSwapped -> output amount
   * swapResult.tradeFee -> this swap fee, charge input mint
   */

  const { execute } = await raydium.cpmm.swap({
    poolInfo,
    poolKeys,
    swapResult,
    slippage: 0.1, // range: 1 ~ 0.0001, means 100% ~ 0.01%
    baseIn,
    // optional: set up priority fee here
    // computeBudgetConfig: {
    //   units: 600000,
    //   microLamports: 100000000,
    // },
  })
cruzshia commented 2 months ago

since there's no more questions, I'll close this issue. also remind that update sdk to latest version 0.1.44-alpha, it update some cpmm swap logic.

tushar-sahoo commented 2 months ago

Hi @cruzshia sorry I missed your reply. I tried the newer sdk versions but faced the same issue. The issue was calling swap base out where the fixed side was SOL in place of the token. So created the transaction instructions required for the swap and used swap base in with tokens as the fixed side and it worked fine for me.