Skip to content

TypeError: transaction.setSenderIfNotSet is not a function #28

@martins-ojakominor

Description

@martins-ojakominor

I'm having an issue where i keep getting an error saying "TypeError: transaction.setSenderIfNotSet is not a function", when trying to swap tokens using "@cetusprotocol/cetus-sui-clmm-sdk": "^5.3.4". My full code is below if anyone can help.

`import React, { useCallback, useEffect, useState } from "react"
import BN from "bn.js"
import {
adjustForSlippage,
d,
initCetusSDK,
Percentage,
} from "@cetusprotocol/cetus-sui-clmm-sdk"
import { getKeypairFromMnemonic } from "./utils/getKeypairFromMnemonic"
import { getPoolAddress } from "./utils/getPoolAddress"

const cetusSDK = initCetusSDK({ network: 'mainnet' })

const tokens = [
{
symbol: "USDC",
address: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
decimals: 6,
},
{
symbol: "SUI",
address: "0x2::sui::SUI",
decimals: 9,
},
// Add more tokens here as needed
]

const CetusSwap =()=> {
const [tokenA, setTokenA] = useState(tokens[0])
const [tokenB, setTokenB] = useState(tokens[1])
const [estimate, setEstimate] = useState({})
const [fetchingEstimate, setFetchingEstimate] = useState(false)
const [isSwappingTokenAToTokenB, setIsSwappingTokenAToTokenB] = useState(true) // checking if we are swapping tokenA to tokenB or vice versa
const [amount, setAmount] = useState("")
const [slippage, setSlippage] = useState("1")
const [loading, setLoading] = useState(false)
const [txHash, setTxHash] = useState("")
const [address, setAddress] = useState('address');

const getEstimate = async()=>{
    setFetchingEstimate(true);
    
    try {
        const byAmountIn = true // or false, based on your token selection
        const coinAmount = new BN(Math.floor(Number(amount) * 10 ** tokenA.decimals)) // convert amount to BN
        // 1. Fetch pool - replace with correct pool address
        const { poolAddress, error, coinsPool } = await getPoolAddress({ coinA: tokenA.address, coinB: tokenB.address })
        const pool = await cetusSDK.Pool.getPool(poolAddress)
        let swappingTokenAtoB;
        
        // checking if the token is swapping from tokenA to tokenB
        if (coinsPool.coinTypeA===tokenA.address && coinsPool.coinTypeB===tokenB.address) {
            swappingTokenAtoB = true;
            setIsSwappingTokenAToTokenB(true);
        } else if(coinsPool.coinTypeA===tokenB.address && coinsPool.coinTypeB===tokenA.address) {
            swappingTokenAtoB = false; 
            setIsSwappingTokenAToTokenB(false);
        }


    
        // 2. Estimate swap
        const res = await cetusSDK.Swap.preswap({
            pool,
            current_sqrt_price: pool.current_sqrt_price,
            coinTypeA: pool.coinTypeA,
            coinTypeB: pool.coinTypeB,
            decimalsA: tokenA.decimals,
            decimalsB: tokenB.decimals,
            a2b: swappingTokenAtoB,
            byAmountIn: byAmountIn, // using camelCase correctly
            amount: coinAmount,
        })
    
        const toAmount = byAmountIn ? res.estimatedAmountOut : res.estimatedAmountIn

        console.log(res)

        setEstimate(res);
    } catch (error) {
        console.error(error)
    } finally {
        setFetchingEstimate(false);
    }
}

const onAmountChange =(e)=>{
    const value = e.target.value;

    if(!isNaN(value)){
        setAmount(value);

        getEstimate();
    }
}

const handleSwap = async () => {
setLoading(true)

try {
  const byAmountIn = true // or false, based on your token selection
  const coinAmount = new BN(Math.floor(Number(amount) * 10 ** tokenA.decimals)) // convert amount to BN
  const slippagePct = Percentage.fromDecimal(d(Number(slippage))) // slippage percentage

  // Ensure the amount is a BN object for correct multiplication
  const toAmountBN = new BN(coinAmount.toString()) // Ensure toAmount is a BN
  const amountLimit = adjustForSlippage(toAmountBN, slippagePct, !byAmountIn) // Pass BN objects

  // Set the sender address (replace with the actual address of the wallet you're using to sign the transaction)
  cetusSDK.senderAddress = address // Make sure the `address` here is valid and corresponds to your wallet
  
  // 1. Fetch pool - replace with correct pool address
  const { poolAddress, error } = await getPoolAddress({ coinA: tokenA.address, coinB: tokenB.address })
  const pool = await cetusSDK.Pool.getPool(poolAddress)

  // 3. Create Swap Transaction
  const swapPayload  = cetusSDK.Swap.createSwapTransactionPayload({
    pool_id: pool.poolAddress,
    coinTypeA: pool.coinTypeA,
    coinTypeB: pool.coinTypeB,
    a2b: isSwappingTokenAToTokenB,
    by_amount_in: byAmountIn,
    amount: coinAmount.toString(),
    amount_limit: amountLimit.toString(),
  })

  console.log('Swap Payload:', swapPayload);

  const keypair = await getKeypairFromMnemonic();
  (await swapPayload).setSender(address);

  const result = await cetusSDK.fullClient.sendTransaction(keypair, swapPayload)
  console.log(result)
  // setTxHash(result.digest)
} catch (err) {
  console.log("Swap failed", err)
  alert("Swap failed. Check the console for details.")
}
setLoading(false) 

}

return (


Token Swap


{isSwappingTokenAToTokenB.toString()}

  <div className="mb-3">
    <label className="block font-semibold mb-1">From</label>
    <select
      className="w-full p-2 border rounded"
      value={tokenA.symbol}
      onChange={(e) =>
        setTokenA(tokens.find((t) => t.symbol === e.target.value))
      }
    > 
      {tokens.map((t) => (
        <option key={t.symbol} value={t.symbol}>
          {t.symbol} 
        </option>
      ))}
    </select>
  </div>

  <div className="mb-3">
    <label className="block font-semibold mb-1">To</label>
    <select
      className="w-full p-2 border rounded"
      value={tokenB.symbol}
      onChange={(e) =>
        setTokenB(tokens.find((t) => t.symbol === e.target.value))
      }
    >
      {tokens.map((t) => (
        <option key={t.symbol} value={t.symbol}>
          {t.symbol}
        </option>
      ))}
    </select>
  </div>

  <div className="mb-3">
    <label className="block font-semibold mb-1">Amount</label>
    <input
      type="number"
      className="w-full p-2 border rounded"
      value={amount}
      onChange={(e) => onAmountChange(e)}
      placeholder="0.0"
    />
  </div>

  <div className="mb-3">
    <label className="block font-semibold mb-1">Slippage (%)</label>
    <input
      type="number"
      className="w-full p-2 border rounded"
      value={slippage}
      onChange={(e) => setSlippage(e.target.value)}
      placeholder="1"
    />
  </div>

  <button
    className="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700 transition disabled:opacity-50"
    onClick={handleSwap}
    disabled={loading || !amount}
  >
    {loading ? "Swapping..." : "Swap"}
  </button>

  {txHash && (
    <div className="mt-4 text-sm text-green-600 break-words">
      Swap submitted! <br />
      Tx: <code>{txHash}</code>
    </div>
  )}
</div>

)
}

export default CetusSwap;`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions