{"id":25059584,"url":"https://github.com/snarflakes/uniswap-python-swapper","last_synced_at":"2026-05-01T15:32:29.849Z","repository":{"id":276015794,"uuid":"927935984","full_name":"snarflakes/uniswap-python-swapper","owner":"snarflakes","description":"Uniswap v4 Python Token Swapper – Universal Router.  A user-friendly Python script that demonstrates how to execute SWAP_EXACT_IN (Exact Input) swaps on Uniswap v4 Universal Router across various L2 networks, leveraging the uniswap-universal-router-decoder library.","archived":false,"fork":false,"pushed_at":"2025-02-06T21:29:36.000Z","size":39,"stargazers_count":16,"open_issues_count":1,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-31T10:39:27.726Z","etag":null,"topics":["arbitrum","base","cryptocurrency","dex","ethereum","layer2","optimism","polygon","python","uniswap","uniswap-v4"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/snarflakes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-05T19:34:47.000Z","updated_at":"2025-03-29T13:22:02.000Z","dependencies_parsed_at":"2025-02-05T20:58:14.040Z","dependency_job_id":null,"html_url":"https://github.com/snarflakes/uniswap-python-swapper","commit_stats":null,"previous_names":["snarflakes/uniswap-python-swapper"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/snarflakes/uniswap-python-swapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snarflakes%2Funiswap-python-swapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snarflakes%2Funiswap-python-swapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snarflakes%2Funiswap-python-swapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snarflakes%2Funiswap-python-swapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/snarflakes","download_url":"https://codeload.github.com/snarflakes/uniswap-python-swapper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snarflakes%2Funiswap-python-swapper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32503040,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arbitrum","base","cryptocurrency","dex","ethereum","layer2","optimism","polygon","python","uniswap","uniswap-v4"],"created_at":"2025-02-06T15:35:24.518Z","updated_at":"2026-05-01T15:32:29.830Z","avatar_url":"https://github.com/snarflakes.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Uniswap v4 Python Token Swapper – Universal Router\n\nA **user-friendly Python script** that demonstrates how to execute **SWAP_EXACT_IN** (Exact Input) swaps on **Uniswap v4 Universal Router** across various L2 networks, leveraging the **uniswap-universal-router-decoder** library.\n\n---\n\n## Features\n- **Supports** Uniswap v4 Universal Router.\n- **Works** with both v3 and v4 (untested) pools.\n- **Auto-selects** the router address based on the connected chain (Base, Optimism, Polygon, Arbitrum, Ethereum).\n- **Permit2 integrated** for simplified token approvals.\n- **Checks \u0026 Cancels** stuck transactions automatically.\n- Written in **Python** using `web3.py`, `eth_account`, and `uniswap-universal-router-decoder`.\n\n---\n\n## Installation\n\n1. **Clone This Repo** (or download the script directly)\n2. **Install Dependencies**:\n\n```bash\npip install web3 eth_account eth_abi uniswap-universal-router-decoder\n```\n\n3. **(Optional) Create a Virtual Environment**\n```bash\npython -m venv venv\nsource venv/bin/activate  # On Linux/Mac\n# or venv\\Scripts\\activate on Windows\n```\n\n4. **Ensure You Have Python 3.8+**\n```bash\npython --version\n```\n\n---\n\n## Quick Start\n\n```python\nfrom web3 import Web3\nfrom uniswap_universal_router import Uniswap  # or whatever you name this script\n\n# 1. Connect to an L2 or mainnet RPC\nprovider_url = \"https://base-mainnet-rpc.example\"  # Replace with your provider\nweb3 = Web3(Web3.HTTPProvider(provider_url))\n\n# 2. Prepare wallet credentials\nwallet_address = \"0xYOUR_WALLET_ADDRESS\"\nprivate_key = \"YOUR_PRIVATE_KEY\"  # Keep secret!\n\n# 3. Instantiate the Uniswap helper\nuniswap = Uniswap(\n    wallet_address=wallet_address,\n    private_key=private_key,\n    provider=provider_url,  # Used to auto-detect chain\n    web3=web3\n)\n\n# 4. Perform a swap (SWAP_EXACT_IN)\n# Example: Swap 1 tokenIn -\u003e tokenOut at 0.3% fee in a v3 pool\namount_in_wei = web3.to_wei(1, 'ether')\n\ntry:\n    tx_hash = uniswap.make_trade(\n        from_token=\"0xTOKEN_IN_ADDRESS\",\n        to_token=\"0xTOKEN_OUT_ADDRESS\",\n        amount=amount_in_wei,\n        fee=3000,         # e.g., 3000 for a 0.3% Uniswap V3 pool\n        slippage=0.5,     # non-functional right now. 0.5% slippage tolerance\n        pool_version=\"v3\"  # can be \"v3\" or \"v4\"\n    )\n    print(f\"Swap transaction sent! Tx hash: {tx_hash.hex()}\")\nexcept Exception as e:\n    print(f\"Swap failed: {e}\")\n```\n\n---\n\n## How It Works\n\n1. **Router Detection:** Based on your `provider_url`, the script automatically selects the correct **Uniswap v4 Universal Router** address for Base, Optimism, Polygon, Arbitrum, or Ethereum.\n2. **Permit2 Approvals:** Checks and (if necessary) approves the Uniswap Permit2 contract before swapping, minimizing repeated approvals.\n3. **Transaction Construction:** Leverages `uniswap-universal-router-decoder` to encode swap calls. Handles `v3_swap_exact_in` or `v4_swap` logic depending on `pool_version`.\n4. **Transaction Submission:** Signs and sends a **type=2** (EIP-1559) transaction with dynamic gas.\n5. **Stuck Transactions Check:** If a nonce is stuck, attempts to cancel it by sending a 0-value tx with a higher gas.\n6. **Stuck but not visible Transaction?:** Uncomment nonce, write in specific nonce that is the problem and it will attempt to cancel it by sending a 0-value tx with a higher gas.\n---\n\n## Code Overview\n\n- **`Uniswap` class**\n  - **`__init__`:** Initializes Web3, detects chain, sets up router.\n  - **`approve_permit2`:** Approves the Permit2 contract with infinite allowance.\n  - **`check_permit2_allowance`:** Checks if there’s already sufficient allowance.\n  - **`create_permit_signature`:** Generates a Permit2 signature for the swap.\n  - **`make_trade`:** The main function for executing swaps.\n  - **`check_for_stuck_transactions`:** Detects if a transaction nonce is stuck in pending.\n  - **`cancel_transaction`:** Attempts to cancel a stuck transaction by overriding its nonce.\n  - **`calculate_gas_parameters`:** Estimates baseFee and priorityFee, calculates total cost.\n\n---\n\n## Supported Chains (with Addresses)\n| Chain     | Router Address                                |\n|-----------|-----------------------------------------------|\n| Ethereum  | `0x66a9893cc07d91d95644aedd05d03f95e1dba8af`   |\n| Base      | `0x6ff5693b99212da76ad316178a184ab56d299b43`   |\n| Optimism  | `0x851116d9223fabed8e56c0e6b8ad0c31d98b3507`   |\n| Polygon   | `0x1095692a6237d83c6a72f3f5efedb9a670c49223`   |\n| Arbitrum  | `0xa51afafe0263b40edaef0df8781ea9aa03e381a3`   |\n\n\u003e **Note:** These addresses may change if Uniswap deploys updates.\n\n---\n\n## Troubleshooting\n- **Web3 Connection Failed:** Make sure your RPC URL is correct and the network is live.\n- **Insufficient Balance or Allowance:** Ensure you have enough tokens/ETH for gas and correct Permit2 approvals.\n- **Stuck Nonce:** The script automatically checks and attempts to cancel.\n- **Unsupported Chain:** Add your chain to `ROUTER_ADDRESSES` or specify `ethereum`.\n\n---\n\n## Disclaimer\n- **Use at your own risk** – This is experimental code for demonstration purposes.\n- Always **test on a testnet** or with small amounts before using in production.\n- Make sure you **keep your private keys secure**.\n\n---\n\n## Contributing\nPull requests are welcome! If you want to expand functionality or fix issues, feel free to open a PR.\n\n---\n\n## License\nThis project is released under the **MIT License**.\n\n---\n\n### Credits\n- Built on top of [`uniswap-universal-router-decoder`](https://github.com/elnaril/uniswap-universal-router-decoder) for encoding/decoding logic.\n- Thanks to [Web3.py](https://github.com/ethereum/web3.py/) and [Eth Account](https://github.com/ethereum/eth-account).\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnarflakes%2Funiswap-python-swapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnarflakes%2Funiswap-python-swapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnarflakes%2Funiswap-python-swapper/lists"}