{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Uniswap V3 Tutorial\n", "\n", "This tutorial shows how to use Uniswap V3 with Dexsnake. Let's start by connecting to the blockchain (here, we use [Base](https://www.base.org/) for its relatively low transaction fees)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "from web3 import Web3\n", "\n", "\n", "# the code below assumes you have configured the required environment variables\n", "account = os.getenv(\"WEB3_PUBLIC_KEY\")\n", "private_key = os.getenv(\"WEB3_PRIVATE_KEY\")\n", "provider_url = os.getenv(\"WEB3_PROVIDER_URL\")\n", "\n", "web3 = Web3(Web3.HTTPProvider(provider_url))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's import `UniswapV3Factory` and find the pair with USDC and WETH." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0x6c561B446416E1A00E8E93E221854d6eA4171372\n" ] } ], "source": [ "from dexsnake.uniswap_v3 import UniswapV3Factory\n", "\n", "\n", "factory = UniswapV3Factory(web3)\n", "\n", "USDC_address = \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\"\n", "WETH_address = \"0x4200000000000000000000000000000000000006\"\n", "fee = 3000\n", "\n", "pool_address = factory.get_pool(USDC_address, WETH_address, fee)\n", "\n", "print(pool_address)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's initialize the pool object and fetch the pool's price." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Price of 1 WETH: 2588.978258128007 USDC\n" ] } ], "source": [ "from dexsnake.uniswap_v3 import UniswapV3Pool\n", "\n", "\n", "pool = UniswapV3Pool(web3, pool_address)\n", "\n", "price = pool.get_price()\n", "\n", "print(f\"Price of 1 {pool.token_0.symbol}: {price} {pool.token_1.symbol}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we know the price, let's use the router to swap one USDC for WETH. Note that before you can make the trade, you must approve the router contract to spend your USDC." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "AttributeDict({'blockHash': HexBytes('0xf0f897bcaf7d1e068a6f744f18ae8b68c2165c90a1a3f7cb98a54419e91792ec'),\n", " 'blockNumber': 18641698,\n", " 'contractAddress': None,\n", " 'cumulativeGasUsed': 14798579,\n", " 'effectiveGasPrice': 4698025,\n", " 'from': '0x011b7DD4cAA8E48FbBaef548dB349dfB3D09aA3F',\n", " 'gasUsed': 112757,\n", " 'l1BaseFeeScalar': '0x8dd',\n", " 'l1BlobBaseFee': '0x1',\n", " 'l1BlobBaseFeeScalar': '0x101c12',\n", " 'l1Fee': '0x56ed109ae',\n", " 'l1GasPrice': '0x11a8c1ee1',\n", " 'l1GasUsed': '0x879',\n", " 'logs': [AttributeDict({'address': '0x4200000000000000000000000000000000000006',\n", " 'topics': [HexBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'),\n", " HexBytes('0x0000000000000000000000006c561b446416e1a00e8e93e221854d6ea4171372'),\n", " HexBytes('0x000000000000000000000000011b7dd4caa8e48fbbaef548db349dfb3d09aa3f')],\n", " 'data': HexBytes('0x00000000000000000000000000000000000000000000000000015e3d90cd5b4d'),\n", " 'blockNumber': 18641698,\n", " 'transactionHash': HexBytes('0x62025456457e7020995e3a1f610cedd6fff617867c81b922dba09ac4eb18dccd'),\n", " 'transactionIndex': 90,\n", " 'blockHash': HexBytes('0xf0f897bcaf7d1e068a6f744f18ae8b68c2165c90a1a3f7cb98a54419e91792ec'),\n", " 'logIndex': 350,\n", " 'removed': False}),\n", " AttributeDict({'address': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n", " 'topics': [HexBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'),\n", " HexBytes('0x000000000000000000000000011b7dd4caa8e48fbbaef548db349dfb3d09aa3f'),\n", " HexBytes('0x0000000000000000000000006c561b446416e1a00e8e93e221854d6ea4171372')],\n", " 'data': HexBytes('0x00000000000000000000000000000000000000000000000000000000000f4240'),\n", " 'blockNumber': 18641698,\n", " 'transactionHash': HexBytes('0x62025456457e7020995e3a1f610cedd6fff617867c81b922dba09ac4eb18dccd'),\n", " 'transactionIndex': 90,\n", " 'blockHash': HexBytes('0xf0f897bcaf7d1e068a6f744f18ae8b68c2165c90a1a3f7cb98a54419e91792ec'),\n", " 'logIndex': 351,\n", " 'removed': False}),\n", " AttributeDict({'address': '0x6c561B446416E1A00E8E93E221854d6eA4171372',\n", " 'topics': [HexBytes('0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67'),\n", " HexBytes('0x0000000000000000000000002626664c2603336e57b271c5c0b26f421741e481'),\n", " HexBytes('0x000000000000000000000000011b7dd4caa8e48fbbaef548db349dfb3d09aa3f')],\n", " 'data': HexBytes('0xfffffffffffffffffffffffffffffffffffffffffffffffffffea1c26f32a4b300000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000355a8d46a11b7d0a54501000000000000000000000000000000000000000000000000003483f3bfe1c7e8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfb9e'),\n", " 'blockNumber': 18641698,\n", " 'transactionHash': HexBytes('0x62025456457e7020995e3a1f610cedd6fff617867c81b922dba09ac4eb18dccd'),\n", " 'transactionIndex': 90,\n", " 'blockHash': HexBytes('0xf0f897bcaf7d1e068a6f744f18ae8b68c2165c90a1a3f7cb98a54419e91792ec'),\n", " 'logIndex': 352,\n", " 'removed': False})],\n", " 'logsBloom': HexBytes('0x00000000000000000000000000000000000000000000000000040000000000000000000000000000000000108000100000000000000020000000000000000000000000000000000800000008000000002000000000080000000001000000000000800000000000000000000000000000000000000000000000000010000800000004000000000100000000000000000000000000002100000002000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000400000000000000000000000000000000000000000800000000000100000000000000000000040000000000000000000020000000000000'),\n", " 'status': 1,\n", " 'to': '0x2626664c2603336E57B271c5C0b26F421741e481',\n", " 'transactionHash': HexBytes('0x62025456457e7020995e3a1f610cedd6fff617867c81b922dba09ac4eb18dccd'),\n", " 'transactionIndex': 90,\n", " 'type': 0})" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from dexsnake.uniswap_v3 import UniswapV3Router\n", "\n", "\n", "router = UniswapV3Router(web3)\n", "\n", "tx_receipt_approval = pool.token_1.approve(router.contract.address, 1, account, private_key)\n", "\n", "tx_receipt_swap = router.exact_input_single(\n", " amount_in=1,\n", " amount_out_min=1 / price * 0.99, # max 1% slippage\n", " token_in=USDC_address,\n", " token_out=WETH_address,\n", " fee=fee,\n", " recipient=account,\n", " account=account,\n", " private_key=private_key,\n", ")\n", "\n", "tx_receipt_swap" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can inspect the transaction on the block explorer: https://basescan.org/tx/0x62025456457e7020995e3a1f610cedd6fff617867c81b922dba09ac4eb18dccd." ] } ], "metadata": { "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.7" } }, "nbformat": 4, "nbformat_minor": 2 }