const swaoRouterV3Abi = [ { inputs: [ { internalType: "address", name: "_factoryV2", type: "address" }, { internalType: "address", name: "factoryV3", type: "address" }, { internalType: "address", name: "_positionManager", type: "address" }, { internalType: "address", name: "_WETH9", type: "address" }, ], stateMutability: "nonpayable", type: "constructor", }, { inputs: [], name: "WETH9", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "token", type: "address" }], name: "approveMax", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [{ internalType: "address", name: "token", type: "address" }], name: "approveMaxMinusOne", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [{ internalType: "address", name: "token", type: "address" }], name: "approveZeroThenMax", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [{ internalType: "address", name: "token", type: "address" }], name: "approveZeroThenMaxMinusOne", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [{ internalType: "bytes", name: "data", type: "bytes" }], name: "callPositionManager", outputs: [{ internalType: "bytes", name: "result", type: "bytes" }], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "bytes[]", name: "paths", type: "bytes[]" }, { internalType: "uint128[]", name: "amounts", type: "uint128[]" }, { internalType: "uint24", name: "maximumTickDivergence", type: "uint24" }, { internalType: "uint32", name: "secondsAgo", type: "uint32" }, ], name: "checkOracleSlippage", outputs: [], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "bytes", name: "path", type: "bytes" }, { internalType: "uint24", name: "maximumTickDivergence", type: "uint24" }, { internalType: "uint32", name: "secondsAgo", type: "uint32" }, ], name: "checkOracleSlippage", outputs: [], stateMutability: "view", type: "function", }, { inputs: [ { components: [ { internalType: "bytes", name: "path", type: "bytes" }, { internalType: "address", name: "recipient", type: "address" }, { internalType: "uint256", name: "amountIn", type: "uint256" }, { internalType: "uint256", name: "amountOutMinimum", type: "uint256", }, ], internalType: "struct IV3SwapRouter.ExactInputParams", name: "params", type: "tuple", }, ], name: "exactInput", outputs: [{ internalType: "uint256", name: "amountOut", type: "uint256" }], stateMutability: "payable", type: "function", }, { inputs: [ { components: [ { internalType: "address", name: "tokenIn", type: "address" }, { internalType: "address", name: "tokenOut", type: "address" }, { internalType: "uint24", name: "fee", type: "uint24" }, { internalType: "address", name: "recipient", type: "address" }, { internalType: "uint256", name: "amountIn", type: "uint256" }, { internalType: "uint256", name: "amountOutMinimum", type: "uint256", }, { internalType: "uint160", name: "sqrtPriceLimitX96", type: "uint160", }, ], internalType: "struct IV3SwapRouter.ExactInputSingleParams", name: "params", type: "tuple", }, ], name: "exactInputSingle", outputs: [{ internalType: "uint256", name: "amountOut", type: "uint256" }], stateMutability: "payable", type: "function", }, { inputs: [ { components: [ { internalType: "bytes", name: "path", type: "bytes" }, { internalType: "address", name: "recipient", type: "address" }, { internalType: "uint256", name: "amountOut", type: "uint256" }, { internalType: "uint256", name: "amountInMaximum", type: "uint256" }, ], internalType: "struct IV3SwapRouter.ExactOutputParams", name: "params", type: "tuple", }, ], name: "exactOutput", outputs: [{ internalType: "uint256", name: "amountIn", type: "uint256" }], stateMutability: "payable", type: "function", }, { inputs: [ { components: [ { internalType: "address", name: "tokenIn", type: "address" }, { internalType: "address", name: "tokenOut", type: "address" }, { internalType: "uint24", name: "fee", type: "uint24" }, { internalType: "address", name: "recipient", type: "address" }, { internalType: "uint256", name: "amountOut", type: "uint256" }, { internalType: "uint256", name: "amountInMaximum", type: "uint256" }, { internalType: "uint160", name: "sqrtPriceLimitX96", type: "uint160", }, ], internalType: "struct IV3SwapRouter.ExactOutputSingleParams", name: "params", type: "tuple", }, ], name: "exactOutputSingle", outputs: [{ internalType: "uint256", name: "amountIn", type: "uint256" }], stateMutability: "payable", type: "function", }, { inputs: [], name: "factory", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [], name: "factoryV2", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "amount", type: "uint256" }, ], name: "getApprovalType", outputs: [ { internalType: "enum IApproveAndCall.ApprovalType", name: "", type: "uint8", }, ], stateMutability: "nonpayable", type: "function", }, { inputs: [ { components: [ { internalType: "address", name: "token0", type: "address" }, { internalType: "address", name: "token1", type: "address" }, { internalType: "uint256", name: "tokenId", type: "uint256" }, { internalType: "uint256", name: "amount0Min", type: "uint256" }, { internalType: "uint256", name: "amount1Min", type: "uint256" }, ], internalType: "struct IApproveAndCall.IncreaseLiquidityParams", name: "params", type: "tuple", }, ], name: "increaseLiquidity", outputs: [{ internalType: "bytes", name: "result", type: "bytes" }], stateMutability: "payable", type: "function", }, { inputs: [ { components: [ { internalType: "address", name: "token0", type: "address" }, { internalType: "address", name: "token1", type: "address" }, { internalType: "uint24", name: "fee", type: "uint24" }, { internalType: "int24", name: "tickLower", type: "int24" }, { internalType: "int24", name: "tickUpper", type: "int24" }, { internalType: "uint256", name: "amount0Min", type: "uint256" }, { internalType: "uint256", name: "amount1Min", type: "uint256" }, { internalType: "address", name: "recipient", type: "address" }, ], internalType: "struct IApproveAndCall.MintParams", name: "params", type: "tuple", }, ], name: "mint", outputs: [{ internalType: "bytes", name: "result", type: "bytes" }], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "bytes32", name: "previousBlockhash", type: "bytes32" }, { internalType: "bytes[]", name: "data", type: "bytes[]" }, ], name: "multicall", outputs: [{ internalType: "bytes[]", name: "", type: "bytes[]" }], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "deadline", type: "uint256" }, { internalType: "bytes[]", name: "data", type: "bytes[]" }, ], name: "multicall", outputs: [{ internalType: "bytes[]", name: "", type: "bytes[]" }], stateMutability: "payable", type: "function", }, { inputs: [{ internalType: "bytes[]", name: "data", type: "bytes[]" }], name: "multicall", outputs: [{ internalType: "bytes[]", name: "results", type: "bytes[]" }], stateMutability: "payable", type: "function", }, { inputs: [], name: "positionManager", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "value", type: "uint256" }, ], name: "pull", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [], name: "refundETH", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "value", type: "uint256" }, { internalType: "uint256", name: "deadline", type: "uint256" }, { internalType: "uint8", name: "v", type: "uint8" }, { internalType: "bytes32", name: "r", type: "bytes32" }, { internalType: "bytes32", name: "s", type: "bytes32" }, ], name: "selfPermit", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "nonce", type: "uint256" }, { internalType: "uint256", name: "expiry", type: "uint256" }, { internalType: "uint8", name: "v", type: "uint8" }, { internalType: "bytes32", name: "r", type: "bytes32" }, { internalType: "bytes32", name: "s", type: "bytes32" }, ], name: "selfPermitAllowed", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "nonce", type: "uint256" }, { internalType: "uint256", name: "expiry", type: "uint256" }, { internalType: "uint8", name: "v", type: "uint8" }, { internalType: "bytes32", name: "r", type: "bytes32" }, { internalType: "bytes32", name: "s", type: "bytes32" }, ], name: "selfPermitAllowedIfNecessary", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "value", type: "uint256" }, { internalType: "uint256", name: "deadline", type: "uint256" }, { internalType: "uint8", name: "v", type: "uint8" }, { internalType: "bytes32", name: "r", type: "bytes32" }, { internalType: "bytes32", name: "s", type: "bytes32" }, ], name: "selfPermitIfNecessary", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountIn", type: "uint256" }, { internalType: "uint256", name: "amountOutMin", type: "uint256" }, { internalType: "address[]", name: "path", type: "address[]" }, { internalType: "address", name: "to", type: "address" }, ], name: "swapExactTokensForTokens", outputs: [{ internalType: "uint256", name: "amountOut", type: "uint256" }], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountOut", type: "uint256" }, { internalType: "uint256", name: "amountInMax", type: "uint256" }, { internalType: "address[]", name: "path", type: "address[]" }, { internalType: "address", name: "to", type: "address" }, ], name: "swapTokensForExactTokens", outputs: [{ internalType: "uint256", name: "amountIn", type: "uint256" }], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "amountMinimum", type: "uint256" }, { internalType: "address", name: "recipient", type: "address" }, ], name: "sweepToken", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "amountMinimum", type: "uint256" }, ], name: "sweepToken", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "amountMinimum", type: "uint256" }, { internalType: "uint256", name: "feeBips", type: "uint256" }, { internalType: "address", name: "feeRecipient", type: "address" }, ], name: "sweepTokenWithFee", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "address", name: "token", type: "address" }, { internalType: "uint256", name: "amountMinimum", type: "uint256" }, { internalType: "address", name: "recipient", type: "address" }, { internalType: "uint256", name: "feeBips", type: "uint256" }, { internalType: "address", name: "feeRecipient", type: "address" }, ], name: "sweepTokenWithFee", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "int256", name: "amount0Delta", type: "int256" }, { internalType: "int256", name: "amount1Delta", type: "int256" }, { internalType: "bytes", name: "_data", type: "bytes" }, ], name: "uniswapV3SwapCallback", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountMinimum", type: "uint256" }, { internalType: "address", name: "recipient", type: "address" }, ], name: "unwrapWETH9", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountMinimum", type: "uint256" }, ], name: "unwrapWETH9", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountMinimum", type: "uint256" }, { internalType: "address", name: "recipient", type: "address" }, { internalType: "uint256", name: "feeBips", type: "uint256" }, { internalType: "address", name: "feeRecipient", type: "address" }, ], name: "unwrapWETH9WithFee", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountMinimum", type: "uint256" }, { internalType: "uint256", name: "feeBips", type: "uint256" }, { internalType: "address", name: "feeRecipient", type: "address" }, ], name: "unwrapWETH9WithFee", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [{ internalType: "uint256", name: "value", type: "uint256" }], name: "wrapETH", outputs: [], stateMutability: "payable", type: "function", }, { stateMutability: "payable", type: "receive" }, ]; const SwapButton = styled.button` width: 100%; height: 60px; border-radius: 10px; background-color: ${props.theme.buttonColor}; color: #fff; font-size: 18px; line-height: 22px; border: none; transition: 0.5s; cursor: pointer; :hover { opacity: 0.8; } &:disabled { opacity: 0.5; pointer-events: none; } @media (max-width: 900px) { height: 40px; font-size: 16px; } `; const account = Ethers.send("eth_requestAccounts", [])[0]; if (props.noPair) { return <SwapButton disabled>Insufficient Liquidity</SwapButton>; } if (props.loading) { return <SwapButton disabled>Getting Trade Info...</SwapButton>; } const { inputCurrency, outputCurrency, inputCurrencyAmount, outputCurrencyAmount, maxInputBalance, onSuccess, routerAddress, wethAddress, title, fee, uniType, } = props; const expandToken = (value, decimals) => { return new Big(value).mul(new Big(10).pow(decimals)); }; if (Big(inputCurrencyAmount || 0).eq(0)) { return <SwapButton disabled>Enter An Amount</SwapButton>; } if (!inputCurrency || !outputCurrency) { return <SwapButton disabled>Select a token</SwapButton>; } if (Big(inputCurrencyAmount || 0).gt(maxInputBalance)) { return ( <SwapButton disabled> Insufficient {inputCurrency?.symbol} Balance </SwapButton> ); } State.init({ isApproved: false, approving: false, swapping: false, wrapping: false, }); const getAllowance = () => { const TokenContract = new ethers.Contract( inputCurrency.address, [ { constant: true, inputs: [ { name: "_owner", type: "address", }, { name: "_spender", type: "address", }, ], name: "allowance", outputs: [ { name: "", type: "uint256", }, ], payable: false, stateMutability: "view", type: "function", }, ], Ethers.provider().getSigner() ); TokenContract.allowance(account, routerAddress).then((allowanceRaw) => { State.update({ isApproved: !Big(Number(allowanceRaw._hex)).eq(0), }); }); }; if (inputCurrency.address !== "native") { getAllowance(); } else { State.update({ isApproved: true }); } const wrapType = inputCurrency.address === "native" && outputCurrency.symbol === "WETH" ? 1 : inputCurrency.symbol === "WETH" && outputCurrency.address === "native" ? 2 : 0; const handleApprove = () => { State.update({ approving: true, }); const TokenContract = new ethers.Contract( inputCurrency.address, [ { constant: false, inputs: [ { name: "_spender", type: "address", }, { name: "_value", type: "uint256", }, ], name: "approve", outputs: [ { name: "", type: "bool", }, ], payable: false, stateMutability: "nonpayable", type: "function", }, ], Ethers.provider().getSigner() ); TokenContract.approve( routerAddress, ethers.utils.parseUnits(inputCurrencyAmount, inputCurrency.decimals) ) .then((tx) => { tx.wait().then((res) => { const { status, transactionHash } = res; State.update({ isApproved: status === 1, approving: false, }); }); }) .catch(() => { State.update({ approving: false, }); }); }; if (!state.isApproved && wrapType === 0) { return ( <SwapButton onClick={handleApprove} disabled={state.approving}> {state.approving ? " Approving..." : " Approve"} </SwapButton> ); } function add_action(param_body) { asyncFetch("https://bos-api.delink.one/add-action-data", { method: "post", headers: { "Content-Type": "application/json", }, body: JSON.stringify(param_body), }); } function successCallback(tx, callback) { tx.wait().then((res) => { const { status, transactionHash } = res; callback?.(); const uuid = Storage.get( "zkevm-warm-up-uuid", "bluebiu.near/widget/ZKEVMWarmUp.generage-uuid" ); add_action({ action_title: `Swap ${inputCurrencyAmount} ${inputCurrency.symbol} on ${title}`, action_type: "Swap", action_tokens: JSON.stringify([ `${inputCurrency.symbol}`, `${outputCurrency.symbol}`, ]), action_amount: inputCurrencyAmount, account_id: account, account_info: uuid, template: title, action_status: status === 1 ? "Success" : "Failed", tx_id: transactionHash, action_network_id: "Arbitrum One", }); if (status === 1) { onSuccess?.(); } }); } const handleWrap = (type, onSuccess, onError) => { const WethContract = new ethers.Contract( wethAddress, [ { constant: false, inputs: [], name: "deposit", outputs: [], payable: true, stateMutability: "payable", type: "function", }, { constant: false, inputs: [{ internalType: "uint256", name: "wad", type: "uint256" }], name: "withdraw", outputs: [], payable: false, stateMutability: "nonpayable", type: "function", }, ], Ethers.provider().getSigner() ); if (type === 1) { WethContract.deposit({ value: ethers.utils.parseEther(inputCurrencyAmount), }) .then((tx) => { tx.wait().then((res) => { onSuccess?.(res); }); }) .catch((err) => { onError?.(); }); } else { WethContract.withdraw(ethers.utils.parseEther(inputCurrencyAmount)) .then((tx) => { tx.wait().then((res) => { onSuccess?.(res); }); }) .catch((err) => { onError?.(); }); } }; if (wrapType) { return ( <SwapButton onClick={() => { State.update({ wrapping: true, }); handleWrap( wrapType, (res) => { successCallback(res, () => { State.update({ wrapping: false }); }); }, () => { State.update({ wrapping: false, }); } ); }} disabled={state.wrapping} > {wrapType === 1 ? state.wrapping ? "Wrapping..." : "Wrap" : state.wrapping ? "Unwrapping..." : "Unwrap"} </SwapButton> ); } const handleCamelotSwap = (type) => { const RouterContract = new ethers.Contract( routerAddress, [ { inputs: [ { internalType: "uint256", name: "amountIn", type: "uint256" }, { internalType: "uint256", name: "amountOutMin", type: "uint256", }, { internalType: "address[]", name: "path", type: "address[]" }, { internalType: "address", name: "to", type: "address" }, { internalType: "address", name: "referrer", type: "address" }, { internalType: "uint256", name: "deadline", type: "uint256" }, ], name: "swapExactTokensForTokensSupportingFeeOnTransferTokens", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountOutMin", type: "uint256", }, { internalType: "address[]", name: "path", type: "address[]" }, { internalType: "address", name: "to", type: "address" }, { internalType: "address", name: "referrer", type: "address" }, { internalType: "uint256", name: "deadline", type: "uint256" }, ], name: "swapExactETHForTokensSupportingFeeOnTransferTokens", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountIn", type: "uint256" }, { internalType: "uint256", name: "amountOutMin", type: "uint256", }, { internalType: "address[]", name: "path", type: "address[]" }, { internalType: "address", name: "to", type: "address" }, { internalType: "address", name: "referrer", type: "address" }, { internalType: "uint256", name: "deadline", type: "uint256" }, ], name: "swapExactTokensForETHSupportingFeeOnTransferTokens", outputs: [], stateMutability: "nonpayable", type: "function", }, ], Ethers.provider().getSigner() ); State.update({ swapping: true, }); if (type === 0) { RouterContract.swapExactTokensForTokensSupportingFeeOnTransferTokens( ethers.utils.parseUnits(inputCurrencyAmount, inputCurrency.decimals), ethers.utils.parseUnits(outputCurrencyAmount, outputCurrency.decimals), [inputCurrency.address, outputCurrency.address], account, "0x0000000000000000000000000000000000000000", Math.ceil(Date.now() / 1000) + 60, { gasLimit: 5000000 } ) .then((tx) => { successCallback(tx, () => { State.update({ swapping: false }); }); }) .catch((err) => { State.update({ swapping: false, }); }); return; } if (type === 1) { RouterContract.swapExactETHForTokensSupportingFeeOnTransferTokens( ethers.utils.parseUnits(outputCurrencyAmount, outputCurrency.decimals), [wethAddress, outputCurrency.address], account, "0x0000000000000000000000000000000000000000", Math.ceil(Date.now() / 1000) + 60, { gasLimit: 5000000, value: ethers.utils.parseEther(inputCurrencyAmount) } ) .then((tx) => { successCallback(tx, () => { State.update({ swapping: false }); }); }) .catch((err) => { State.update({ swapping: false, }); }); return; } if (type === 2) { RouterContract.swapExactTokensForETHSupportingFeeOnTransferTokens( ethers.utils.parseUnits(inputCurrencyAmount, inputCurrency.decimals), ethers.utils.parseUnits(outputCurrencyAmount, outputCurrency.decimals), [inputCurrency.address, wethAddress], account, "0x0000000000000000000000000000000000000000", Math.ceil(Date.now() / 1000) + 60, { gasLimit: 5000000 } ) .then((tx) => { successCallback(tx, () => { State.update({ swapping: false }); }); }) .catch((err) => { console.log(err); State.update({ swapping: false, }); }); } }; const handleSwap = () => { const type = inputCurrency.address === "native" ? 1 : outputCurrency.address === "native" ? 2 : 0; if (title === "Camelot") { handleCamelotSwap(type); return; } const RouterContract = new ethers.Contract( routerAddress, [ { inputs: [ { internalType: "uint256", name: "amountOut", type: "uint256", }, { internalType: "uint256", name: "amountInMax", type: "uint256", }, { internalType: "address[]", name: "path", type: "address[]", }, { internalType: "address", name: "to", type: "address", }, { internalType: "uint256", name: "deadline", type: "uint256", }, ], name: "swapExactTokensForTokens", outputs: [ { internalType: "uint256[]", name: "amounts", type: "uint256[]", }, ], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountOutMin", type: "uint256", }, { internalType: "address[]", name: "path", type: "address[]" }, { internalType: "address", name: "to", type: "address" }, { internalType: "uint256", name: "deadline", type: "uint256" }, ], name: "swapExactETHForTokens", outputs: [ { internalType: "uint256[]", name: "amounts", type: "uint256[]" }, ], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "amountIn", type: "uint256" }, { internalType: "uint256", name: "amountOutMin", type: "uint256", }, { internalType: "address[]", name: "path", type: "address[]" }, { internalType: "address", name: "to", type: "address" }, { internalType: "uint256", name: "deadline", type: "uint256" }, ], name: "swapExactTokensForETH", outputs: [ { internalType: "uint256[]", name: "amounts", type: "uint256[]" }, ], stateMutability: "nonpayable", type: "function", }, ], Ethers.provider().getSigner() ); State.update({ swapping: true, }); if (type === 0) { RouterContract.swapExactTokensForTokens( ethers.utils.parseUnits(inputCurrencyAmount, inputCurrency.decimals), "0", [inputCurrency.address, outputCurrency.address], account, Math.ceil(Date.now() / 1000) + 60, { gasLimit: 5000000 } ) .then((tx) => { successCallback(tx, () => { State.update({ swapping: false }); }); }) .catch((err) => { State.update({ swapping: false, }); }); return; } if (type === 1) { RouterContract.swapExactETHForTokens( "0", [wethAddress, outputCurrency.address], account, Math.ceil(Date.now() / 1000) + 60, { gasLimit: 5000000, value: ethers.utils.parseEther(inputCurrencyAmount) } ) .then((tx) => { successCallback(tx, () => { State.update({ swapping: false }); }); }) .catch((err) => { State.update({ swapping: false, }); }); return; } if (type === 2) { RouterContract.swapExactTokensForETH( ethers.utils.parseUnits(inputCurrencyAmount, inputCurrency.decimals), "0", [inputCurrency.address, wethAddress], account, Math.ceil(Date.now() / 1000) + 60, { gasLimit: 5000000 } ) .then((tx) => { successCallback(tx, () => { State.update({ swapping: false }); }); }) .catch((err) => { console.log(err); State.update({ swapping: false, }); }); } }; const handleSwapV3 = () => { const value = expandToken( inputCurrencyAmount, inputCurrency.decimals ).toFixed(0); const signer = Ethers.provider().getSigner(); const abi = swaoRouterV3Abi; const iface = new ethers.utils.Interface(abi); const deadline = new Big(Math.floor(Date.now() / 1000)).add(new Big(1800)); const tokenIn = inputCurrency.address === "native" ? wethAddress : inputCurrency.address; const tokenOut = outputCurrency.address === "native" ? wethAddress : outputCurrency.address; const options = { gasPrice: ethers.utils.parseUnits(gasPrice ?? "10", "gwei"), gasLimit: gasLimit ?? 300000, value: inputCurrency.address === "native" ? value : "0", }; const inputs = [ { tokenIn, tokenOut, fee: fee, recipient: outputCurrency.address === "native" ? "0x0000000000000000000000000000000000000000" : account, deadline: deadline.toFixed(), amountIn: value, amountOutMinimum: "0", sqrtPriceLimitX96: "0", }, ]; const multicallParams = []; const encodedDataCallSwap = iface.encodeFunctionData( "exactInputSingle", inputs ); multicallParams.push(encodedDataCallSwap); if (outputCurrency.address === "native") { multicallParams.push( iface.encodeFunctionData("unwrapWETH9", ["0", account]) ); } const multicallContract = new ethers.Contract(routerAddress, abi, signer); multicallContract .multicall(multicallParams, options) .then((res) => { successCallback(res, () => { State.update({ swapping: false }); }); }) .catch((err) => { console.log(err); State.update({ swapping: false, }); }); }; return ( <SwapButton onClick={uniType === "v3" && !wrapType ? handleSwapV3 : handleSwap} disabled={state.swapping} > {state.swapping ? "Swapping..." : "Swap"} </SwapButton> );