
{"id":39635,"date":"2025-01-28T11:33:49","date_gmt":"2025-01-28T11:33:49","guid":{"rendered":"https:\/\/mycryptomania.com\/?p=39635"},"modified":"2025-01-28T11:33:49","modified_gmt":"2025-01-28T11:33:49","slug":"how-to-programmatically-swap-a-v3-dex","status":"publish","type":"post","link":"https:\/\/mycryptomania.com\/?p=39635","title":{"rendered":"How to Programmatically Swap a V3 DEX"},"content":{"rendered":"<h3>Overview<\/h3>\n<p>Swaps can be done through a website or programmatically through a standard Uniswap V3 API interface.<\/p>\n<p>Below are the requirements<\/p>\n<p>Nodejsethersdotenv<\/p>\n<p>Below is the full source\u00a0code:<\/p>\n<p>import { ethers } from &#8220;ethers&#8221;;<br \/>import &#8220;dotenv\/config&#8221;;<\/p>\n<p>const QUOTER_CONTRACT_ADDRESS = &#8220;0x0880484412B5bAa18B3fa2904a500c08f0fE79D2&#8221;;<br \/>\/\/ prettier-ignore<br \/>const QUOTER_ABI = [ { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;_factory&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;_WETH9&#8221;, &#8220;type&#8221;: &#8220;address&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;constructor&#8221; }, { &#8220;inputs&#8221;: [], &#8220;name&#8221;: &#8220;WETH9&#8221;, &#8220;outputs&#8221;: [{ &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }], &#8220;stateMutability&#8221;: &#8220;view&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [], &#8220;name&#8221;: &#8220;factory&#8221;, &#8220;outputs&#8221;: [{ &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }], &#8220;stateMutability&#8221;: &#8220;view&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;bytes&#8221;, &#8220;name&#8221;: &#8220;path&#8221;, &#8220;type&#8221;: &#8220;bytes&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountIn&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;name&#8221;: &#8220;quoteExactInput&#8221;, &#8220;outputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountOut&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160[]&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceX96AfterList&#8221;, &#8220;type&#8221;: &#8220;uint160[]&#8221; }, { &#8220;internalType&#8221;: &#8220;uint32[]&#8221;, &#8220;name&#8221;: &#8220;initializedTicksCrossedList&#8221;, &#8220;type&#8221;: &#8220;uint32[]&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;gasEstimate&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;components&#8221;: [ { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;tokenIn&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;tokenOut&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountIn&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint24&#8221;, &#8220;name&#8221;: &#8220;fee&#8221;, &#8220;type&#8221;: &#8220;uint24&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceLimitX96&#8221;, &#8220;type&#8221;: &#8220;uint160&#8221; } ], &#8220;internalType&#8221;: &#8220;struct IQuoterV2.QuoteExactInputSingleParams&#8221;, &#8220;name&#8221;: &#8220;params&#8221;, &#8220;type&#8221;: &#8220;tuple&#8221; } ], &#8220;name&#8221;: &#8220;quoteExactInputSingle&#8221;, &#8220;outputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountOut&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceX96After&#8221;, &#8220;type&#8221;: &#8220;uint160&#8221; }, { &#8220;internalType&#8221;: &#8220;uint32&#8221;, &#8220;name&#8221;: &#8220;initializedTicksCrossed&#8221;, &#8220;type&#8221;: &#8220;uint32&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;gasEstimate&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;bytes&#8221;, &#8220;name&#8221;: &#8220;path&#8221;, &#8220;type&#8221;: &#8220;bytes&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountOut&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;name&#8221;: &#8220;quoteExactOutput&#8221;, &#8220;outputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountIn&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160[]&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceX96AfterList&#8221;, &#8220;type&#8221;: &#8220;uint160[]&#8221; }, { &#8220;internalType&#8221;: &#8220;uint32[]&#8221;, &#8220;name&#8221;: &#8220;initializedTicksCrossedList&#8221;, &#8220;type&#8221;: &#8220;uint32[]&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;gasEstimate&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;components&#8221;: [ { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;tokenIn&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;tokenOut&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amount&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint24&#8221;, &#8220;name&#8221;: &#8220;fee&#8221;, &#8220;type&#8221;: &#8220;uint24&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceLimitX96&#8221;, &#8220;type&#8221;: &#8220;uint160&#8221; } ], &#8220;internalType&#8221;: &#8220;struct IQuoterV2.QuoteExactOutputSingleParams&#8221;, &#8220;name&#8221;: &#8220;params&#8221;, &#8220;type&#8221;: &#8220;tuple&#8221; } ], &#8220;name&#8221;: &#8220;quoteExactOutputSingle&#8221;, &#8220;outputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountIn&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceX96After&#8221;, &#8220;type&#8221;: &#8220;uint160&#8221; }, { &#8220;internalType&#8221;: &#8220;uint32&#8221;, &#8220;name&#8221;: &#8220;initializedTicksCrossed&#8221;, &#8220;type&#8221;: &#8220;uint32&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;gasEstimate&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;int256&#8221;, &#8220;name&#8221;: &#8220;amount0Delta&#8221;, &#8220;type&#8221;: &#8220;int256&#8221; }, { &#8220;internalType&#8221;: &#8220;int256&#8221;, &#8220;name&#8221;: &#8220;amount1Delta&#8221;, &#8220;type&#8221;: &#8220;int256&#8221; }, { &#8220;internalType&#8221;: &#8220;bytes&#8221;, &#8220;name&#8221;: &#8220;path&#8221;, &#8220;type&#8221;: &#8220;bytes&#8221; } ], &#8220;name&#8221;: &#8220;uniswapV3SwapCallback&#8221;, &#8220;outputs&#8221;: [], &#8220;stateMutability&#8221;: &#8220;view&#8221;, &#8220;type&#8221;: &#8220;function&#8221; } ]<\/p>\n<p>const provider = new ethers.JsonRpcProvider(&#8220;https:\/\/rpc.o.xyz\/&#8221;);<br \/>const quoterContract = new ethers.Contract(<br \/>  QUOTER_CONTRACT_ADDRESS,<br \/>  QUOTER_ABI,<br \/>  provider<br \/>);<br \/>const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);<\/p>\n<p>const params = {<br \/>  tokenIn: &#8220;0xc7C3cff325c6976965edfEB05c024584e4e4BBDD&#8221;,<br \/>  tokenOut: &#8220;0x91d70c3adde2f0f0c4fb0b2de69f37a7c7e326df&#8221;,<br \/>  fee: 3000,<br \/>  recipient: signer.address,<br \/>  deadline: Math.floor(new Date().getTime() \/ 1000 + 60 * 10),<br \/>  amountIn: ethers.parseUnits(&#8220;0.01&#8221;),<br \/>  sqrtPriceLimitX96: 0,<br \/>};<\/p>\n<p>main();<br \/>async function main() {<br \/>  const transaction =<br \/>    await quoterContract.quoteExactInputSingle.populateTransaction(params);<br \/>  console.log({ transaction });<\/p>\n<p>  const receipt = await signer.sendTransaction(transaction);<br \/>  console.log({ receipt });<br \/>}<\/p>\n<h3>Define Variables<\/h3>\n<p>const QUOTER_CONTRACT_ADDRESS = &#8220;0x0880484412B5bAa18B3fa2904a500c08f0fE79D2&#8221;;<br \/>\/\/ prettier-ignore<br \/>const QUOTER_ABI = [ { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;_factory&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;_WETH9&#8221;, &#8220;type&#8221;: &#8220;address&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;constructor&#8221; }, { &#8220;inputs&#8221;: [], &#8220;name&#8221;: &#8220;WETH9&#8221;, &#8220;outputs&#8221;: [{ &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }], &#8220;stateMutability&#8221;: &#8220;view&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [], &#8220;name&#8221;: &#8220;factory&#8221;, &#8220;outputs&#8221;: [{ &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }], &#8220;stateMutability&#8221;: &#8220;view&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;bytes&#8221;, &#8220;name&#8221;: &#8220;path&#8221;, &#8220;type&#8221;: &#8220;bytes&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountIn&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;name&#8221;: &#8220;quoteExactInput&#8221;, &#8220;outputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountOut&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160[]&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceX96AfterList&#8221;, &#8220;type&#8221;: &#8220;uint160[]&#8221; }, { &#8220;internalType&#8221;: &#8220;uint32[]&#8221;, &#8220;name&#8221;: &#8220;initializedTicksCrossedList&#8221;, &#8220;type&#8221;: &#8220;uint32[]&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;gasEstimate&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;components&#8221;: [ { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;tokenIn&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;tokenOut&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountIn&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint24&#8221;, &#8220;name&#8221;: &#8220;fee&#8221;, &#8220;type&#8221;: &#8220;uint24&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceLimitX96&#8221;, &#8220;type&#8221;: &#8220;uint160&#8221; } ], &#8220;internalType&#8221;: &#8220;struct IQuoterV2.QuoteExactInputSingleParams&#8221;, &#8220;name&#8221;: &#8220;params&#8221;, &#8220;type&#8221;: &#8220;tuple&#8221; } ], &#8220;name&#8221;: &#8220;quoteExactInputSingle&#8221;, &#8220;outputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountOut&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceX96After&#8221;, &#8220;type&#8221;: &#8220;uint160&#8221; }, { &#8220;internalType&#8221;: &#8220;uint32&#8221;, &#8220;name&#8221;: &#8220;initializedTicksCrossed&#8221;, &#8220;type&#8221;: &#8220;uint32&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;gasEstimate&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;bytes&#8221;, &#8220;name&#8221;: &#8220;path&#8221;, &#8220;type&#8221;: &#8220;bytes&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountOut&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;name&#8221;: &#8220;quoteExactOutput&#8221;, &#8220;outputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountIn&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160[]&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceX96AfterList&#8221;, &#8220;type&#8221;: &#8220;uint160[]&#8221; }, { &#8220;internalType&#8221;: &#8220;uint32[]&#8221;, &#8220;name&#8221;: &#8220;initializedTicksCrossedList&#8221;, &#8220;type&#8221;: &#8220;uint32[]&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;gasEstimate&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;components&#8221;: [ { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;tokenIn&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;tokenOut&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amount&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint24&#8221;, &#8220;name&#8221;: &#8220;fee&#8221;, &#8220;type&#8221;: &#8220;uint24&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceLimitX96&#8221;, &#8220;type&#8221;: &#8220;uint160&#8221; } ], &#8220;internalType&#8221;: &#8220;struct IQuoterV2.QuoteExactOutputSingleParams&#8221;, &#8220;name&#8221;: &#8220;params&#8221;, &#8220;type&#8221;: &#8220;tuple&#8221; } ], &#8220;name&#8221;: &#8220;quoteExactOutputSingle&#8221;, &#8220;outputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;amountIn&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; }, { &#8220;internalType&#8221;: &#8220;uint160&#8221;, &#8220;name&#8221;: &#8220;sqrtPriceX96After&#8221;, &#8220;type&#8221;: &#8220;uint160&#8221; }, { &#8220;internalType&#8221;: &#8220;uint32&#8221;, &#8220;name&#8221;: &#8220;initializedTicksCrossed&#8221;, &#8220;type&#8221;: &#8220;uint32&#8221; }, { &#8220;internalType&#8221;: &#8220;uint256&#8221;, &#8220;name&#8221;: &#8220;gasEstimate&#8221;, &#8220;type&#8221;: &#8220;uint256&#8221; } ], &#8220;stateMutability&#8221;: &#8220;nonpayable&#8221;, &#8220;type&#8221;: &#8220;function&#8221; }, { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;int256&#8221;, &#8220;name&#8221;: &#8220;amount0Delta&#8221;, &#8220;type&#8221;: &#8220;int256&#8221; }, { &#8220;internalType&#8221;: &#8220;int256&#8221;, &#8220;name&#8221;: &#8220;amount1Delta&#8221;, &#8220;type&#8221;: &#8220;int256&#8221; }, { &#8220;internalType&#8221;: &#8220;bytes&#8221;, &#8220;name&#8221;: &#8220;path&#8221;, &#8220;type&#8221;: &#8220;bytes&#8221; } ], &#8220;name&#8221;: &#8220;uniswapV3SwapCallback&#8221;, &#8220;outputs&#8221;: [], &#8220;stateMutability&#8221;: &#8220;view&#8221;, &#8220;type&#8221;: &#8220;function&#8221; } ]<\/p>\n<p>const provider = new ethers.JsonRpcProvider(&#8220;https:\/\/rpc.o.xyz\/&#8221;);<br \/>const quoterContract = new ethers.Contract(<br \/>  QUOTER_CONTRACT_ADDRESS,<br \/>  QUOTER_ABI,<br \/>  provider<br \/>);<br \/>const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);QUOTER_CONTRACT_ADDRESS: Is part of the V3 deployment contractsQUOTER_ABI: Is the abi of the\u00a0contractprovider: Connect to the\u00a0RPCquoterContract: Connect to the quoter\u00a0contractsigner: Connect to your\u00a0wallet<\/p>\n<h3>Params<\/h3>\n<p>const params = {<br \/>  tokenIn: &#8220;0xc7C3cff325c6976965edfEB05c024584e4e4BBDD&#8221;,<br \/>  tokenOut: &#8220;0x91d70c3adde2f0f0c4fb0b2de69f37a7c7e326df&#8221;,<br \/>  fee: 3000,<br \/>  recipient: signer.address,<br \/>  deadline: Math.floor(new Date().getTime() \/ 1000 + 60 * 10),<br \/>  amountIn: ethers.parseUnits(&#8220;0.01&#8221;),<br \/>  sqrtPriceLimitX96: 0,<br \/>};tokenIn: ERC20 contract address you\u2019re\u00a0spendingtokenOut: ERC20 contract address you\u2019re receivingfee: Are the <a href=\"https:\/\/support.uniswap.org\/hc\/en-us\/articles\/20904283758349-What-are-fee-tiers\">fee tiers<\/a> 1%, 0.3%, 0.05%, and\u00a00.01%recipient: The receiving addressdeadline: How long the transaction is valid\u00a0foramountIn: Amount (smallest unit) you\u2019re\u00a0spendingsqrtPriceLimitX96: No\u00a0limit<\/p>\n<h3>Raw Transction<\/h3>\n<p>const transaction = await quoterContract.quoteExactInputSingle.populateTransaction(params);<\/p>\n<p>Creates a raw transaction to\u00a0sign.<\/p>\n<p>Output<\/p>\n<p>{<br \/>  to: &#8220;0x0880484412B5bAa18B3fa2904a500c08f0fE79D2&#8221;,<br \/>  data: &#8220;0xc6a5026a000000000000000000000000c7c3cff325c6976965edfeb05c024584e4e4bbdd00000000000000000000000091d70c3adde2f0f0c4fb0b2de69f37a7c7e326df000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000000000000000000000&#8221;<br \/>}<\/p>\n<h3>Send Transaction<\/h3>\n<p>const receipt = await signer.sendTransaction(transaction);<\/p>\n<p>Signs and broadcasts the transaction<\/p>\n<p>Output<\/p>\n<p>{<br \/>  receipt: TransactionResponse {<br \/>    provider: JsonRpcProvider {},<br \/>    blockNumber: null,<br \/>    blockHash: null,<br \/>    index: undefined,<br \/>    hash: &#8220;0x58f4da9449ae4a1eca01a05765e1d54c292d0bcf4935b206cf4747073f2bf3b7&#8221;,<br \/>    type: 2,<br \/>    to: &#8220;0x0880484412B5bAa18B3fa2904a500c08f0fE79D2&#8221;,<br \/>    from: &#8220;0xa427305648aD5227098812EdA6FF82D980b2DbBD&#8221;,<br \/>    nonce: 51,<br \/>    gasLimit: 117236n,<br \/>    gasPrice: undefined,<br \/>    maxPriorityFeePerGas: 1000000n,<br \/>    maxFeePerGas: 1000504n,<br \/>    maxFeePerBlobGas: null,<br \/>    data: &#8220;0xc6a5026a000000000000000000000000c7c3cff325c6976965edfeb05c024584e4e4bbdd00000000000000000000000091d70c3adde2f0f0c4fb0b2de69f37a7c7e326df000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000000000000000000000&#8221;,<br \/>    value: 0n,<br \/>    chainId: 84841n,<br \/>    signature: Signature { r: &#8220;0xe485ba3893b0543a77a1bb14f0e2661dc7af3f6b2d0b3b917c8fbf4eaa6103c3&#8221;, s: &#8220;0x15e605c7e1fd6a64f5ca5d3f519c085367ce1250bf7647a6450bf9aef549c98c&#8221;, yParity: 0, networkV: null },<br \/>    accessList: [],<br \/>    blobVersionedHashes: null<br \/>  }<br \/>}<\/p>\n<h3>Approve Spending (prerequisite)<\/h3>\n<p>const SWAP_ROUTER_CONTRACT_ADDRESS = &#8216;0x660C85710a1cd10e8345BB30C80A49f661486007&#8217;<\/p>\n<p>const approveTransaction = await tokenContract.approve.populateTransaction(<br \/>  SWAP_ROUTER_CONTRACT_ADDRESS,<br \/>  ethers.parseEther(amount.toString())<br \/>);<\/p>\n<p>Make sure the wallet has approved spending.<\/p>\n<p><a href=\"https:\/\/medium.com\/coinmonks\/how-to-programmatically-swap-a-v3-dex-5a4dc0851b03\">How to Programmatically Swap a V3 DEX<\/a> was originally published in <a href=\"https:\/\/medium.com\/coinmonks\">Coinmonks<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>","protected":false},"excerpt":{"rendered":"<p>Overview Swaps can be done through a website or programmatically through a standard Uniswap V3 API interface. Below are the requirements Nodejsethersdotenv Below is the full source\u00a0code: import { ethers } from &#8220;ethers&#8221;;import &#8220;dotenv\/config&#8221;; const QUOTER_CONTRACT_ADDRESS = &#8220;0x0880484412B5bAa18B3fa2904a500c08f0fE79D2&#8221;;\/\/ prettier-ignoreconst QUOTER_ABI = [ { &#8220;inputs&#8221;: [ { &#8220;internalType&#8221;: &#8220;address&#8221;, &#8220;name&#8221;: &#8220;_factory&#8221;, &#8220;type&#8221;: &#8220;address&#8221; }, { &#8220;internalType&#8221;: [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-39635","post","type-post","status-publish","format-standard","hentry","category-interesting"],"_links":{"self":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/39635"}],"collection":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=39635"}],"version-history":[{"count":0,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/39635\/revisions"}],"wp:attachment":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=39635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=39635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=39635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}