-
Notifications
You must be signed in to change notification settings - Fork 41
Description
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;`