{"id":34507930,"url":"https://github.com/elnaril/uniswap-smart-path","last_synced_at":"2025-12-24T03:14:11.708Z","repository":{"id":150126178,"uuid":"616085533","full_name":"Elnaril/uniswap-smart-path","owner":"Elnaril","description":"Find the path from v2 and v3 pools to swap with the best price","archived":false,"fork":false,"pushed_at":"2025-02-03T18:43:05.000Z","size":786,"stargazers_count":43,"open_issues_count":1,"forks_count":9,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-25T02:53:56.787Z","etag":null,"topics":["best-prices","decentralized-applications","decentralized-exchange","defi-trading","dex","ethereum","path","pools","python","router","smart-contracts","uniswap","web3py"],"latest_commit_sha":null,"homepage":"https://www.buymeacoffee.com/elnaril","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/Elnaril.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":"2023-03-19T15:15:19.000Z","updated_at":"2025-07-27T04:03:31.000Z","dependencies_parsed_at":"2023-11-10T11:22:02.072Z","dependency_job_id":"59cb4d0b-7867-4de4-932c-490bf7ed4bc2","html_url":"https://github.com/Elnaril/uniswap-smart-path","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/Elnaril/uniswap-smart-path","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elnaril%2Funiswap-smart-path","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elnaril%2Funiswap-smart-path/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elnaril%2Funiswap-smart-path/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elnaril%2Funiswap-smart-path/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Elnaril","download_url":"https://codeload.github.com/Elnaril/uniswap-smart-path/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elnaril%2Funiswap-smart-path/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27994386,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-24T02:00:07.193Z","response_time":83,"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":["best-prices","decentralized-applications","decentralized-exchange","defi-trading","dex","ethereum","path","pools","python","router","smart-contracts","uniswap","web3py"],"created_at":"2025-12-24T03:14:07.321Z","updated_at":"2025-12-24T03:14:11.702Z","avatar_url":"https://github.com/Elnaril.png","language":"Python","readme":"# Uniswap Smart Path\n\n#### Project Information\n[![Continous Integration](https://github.com/Elnaril/uniswap-smart-path/actions/workflows/ci.yml/badge.svg)](https://github.com/Elnaril/uniswap-smart-path/actions/workflows/ci.yml)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/uniswap-smart-path)](https://pypi.org/project/uniswap-smart-path/)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/Elnaril/uniswap-smart-path)](https://github.com/Elnaril/uniswap-smart-path/releases)\n[![PyPi Repository](https://img.shields.io/badge/repository-pipy.org-blue)](https://pypi.org/project/uniswap-smart-path/)\n[![License](https://img.shields.io/github/license/Elnaril/uniswap-smart-path)](https://github.com/Elnaril/uniswap-smart-path/blob/master/LICENSE)\n\n#### Code Quality\n[![Test Coverage](https://img.shields.io/badge/dynamic/json?color=blueviolet\u0026label=coverage\u0026query=%24.totals.percent_covered_display\u0026suffix=%25\u0026url=https%3A%2F%2Fraw.githubusercontent.com%2FElnaril%2Funiswap-smart-path%2Fmaster%2Fcoverage.json)](https://github.com/Elnaril/uniswap-smart-path/blob/master/coverage.json)\n[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat\u0026labelColor=ef8336)](https://pycqa.github.io/isort/)\n[![Type Checker: mypy](https://img.shields.io/badge/%20type%20checker-mypy-%231674b1?style=flat\u0026labelColor=ef8336)](https://mypy-lang.org/)\n[![Linter: flake8](https://img.shields.io/badge/%20linter-flake8-%231674b1?style=flat\u0026labelColor=ef8336)](https://flake8.pycqa.org/en/latest/)\n\n## Release notes\n### v0.3.0\n* Add Rate Limiter for APIs using credits, CUPS or request units, as well as number of requests per time unit.\n  * Use [credit-rate-limit](https://github.com/Elnaril/credit-rate-limit) under the hood.\n  * Remove `eth_call` from the methods that are automatically verified by web3 (to prevent surges of useless `eth_chainId`)\n* Add support for Python 3.12 \u0026 3.13\n* Add support for web3.py v7\n* Miscellaneous fixes/updates for tests and linting\n\n## Overview \n\nWhen swapping, it is not straightforward to be sure to get the best deal: with several V2 and V3 pools, and 2 or 3 tokens per path, there may be quite a few routes to perform a swap.\n\nThe object of this library is to find the path(s), from v2 and v3 pools, to swap with the best price,\nand to return it/them in order to be used directly with the [Universal Router codec](https://github.com/Elnaril/uniswap-universal-router-decoder),\nalong with a percentage to know how to divide the amount between them if there is more than one result.\n\n⚠ To prevent surges of useless `eth_chainId`, `eth_call` is removed from the methods that are automatically verified by web3.\n⚠ This tool does not replace your own due diligence to find the best price/path to swap any token.\n\n---\n\n## Installation\nA good practice is to use [Python virtual environments](https://python.readthedocs.io/en/latest/library/venv.html), here is a [tutorial](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/).\n\nThe library can be pip installed from [pypi.org](https://pypi.org/project/uniswap-smart-path/) as usual:\n\n```bash\n# update pip to latest version if needed\npip install -U pip\n\n# install the decoder from pypi.org\npip install uniswap-smart-path\n```\n\n---\n\n## Usage\n\nThe library exposes a class, `SmartPath` with a public method `get_swap_in_path()` that can be used to find the best path/price.\nFor performance's sake, it is asynchronous. Currently, it supports only the Ethereum blockchain.\n\n```python\nfrom uniswap_smart_path import SmartPath\n\nsmart_path = await SmartPath.create(async_w3)  # where async_w3 is your AsyncWeb3 instance\npath = await smart_path.get_swap_in_path(amount_in_wei, token0_address, token1_address)\n\n```\n\nYou can also create the `SmartPath` instance from a rpc endpoint:\n```python\nfrom uniswap_smart_path import SmartPath\n\nsmart_path = await SmartPath.create(rpc_endpoint=rpc_endpoint)\n\n```\n\n### V2 or V3 pools only\nThe factory method `SmartPath.create_v2_only()` can be used to create a `SmartPath` instance that will look for the best path in V2 pools only.\nCurrently, it supports only the Ethereum blockchain.\n\n```python\nfrom uniswap_smart_path import SmartPath\n\nsmart_path = await SmartPath.create_v2_only(rpc_endpoint=rpc_endpoint)  # could also use an AsyncWeb3 instance i/o rpc\n\n```\n\nSame thing if you wish to look into V3 pools only, just use `SmartPath.create_v3_only()`\nCurrently, it supports only the Ethereum blockchain.\n\n```python\nfrom uniswap_smart_path import SmartPath\n\nsmart_path = await SmartPath.create_v3_only(rpc_endpoint=rpc_endpoint)  # could also use an AsyncWeb3 instance i/o rpc\n\n```\n\n### Custom pools and blockchains\nA custom SmartPath can be created with the factory method `SmartPath.create_custom()`\n\n```python\nfrom uniswap_smart_path import SmartPath\n\npivot_tokens = (wbnb_address, usdt_address, usdc_address, dai_address)  # BSC addresses\nv3_pool_fees = (100, 500, 2500, 10000)  # Pancakeswap v3 fees\n\nsmart_path = await SmartPath.create_custom(\n        w3,  # BSC AsyncWeb3 instance\n        pivot_tokens=pivot_tokens,\n        v3_pool_fees=v3_pool_fees,\n        v2_router=pancakeswapv2_address,\n        v2_factory=pancakeswapv2_factory,\n        v3_quoter=pancakeswapv3_quoter_address,\n        v3_factory=pancakeswapv3_factory,\n    )\n```\n\n### Using a Rate Limiter\nIt's possible to manage rate limits, though only API calls used to compute the paths are rate limited.\n(Only the RPC method `eth_call` is concerned)\n\nAPI calls performed to create the `SmartPath` objects are not rate limited.\nBoth `eth_call` and `chain_id` are involved in these creations.\n\n#### Credit Rate Limit\nFor APIs that use credits, computation unit per second (CUPS) or request units:\n```python\nfrom uniswap_smart_path import SmartPath, SmartRateLimiter\n\n# Define a credit limiter allowing 300 credits per second.\n# The method 'eth_call' costs 20 credits.\ncredit_limiter = SmartRateLimiter(interval=1, max_credits=300, method_credits={\"eth_call\": 20})\nsmart_path = await SmartPath.create(w3, smart_rate_limiter=credit_limiter)\n```\nNote that only the `eth_call` method is needed at the moment.\n\n#### Count Rate Limit\nFor APIs that just count the number of requests per time unit:\n```python\nfrom uniswap_smart_path import SmartPath, SmartRateLimiter\n\n# Define a count limiter allowing 5 requests per second.\ncount_limiter = SmartRateLimiter(interval=1, max_count=5)\nsmart_path = await SmartPath.create(w3, smart_rate_limiter=count_limiter)\n```\n\n## Result\nExamples of output paths that you can use with the [UR codec](https://github.com/Elnaril/uniswap-universal-router-decoder) to encode a transaction.\n\n#### Single path\n```python\n(\n    {\n        'path': ('0xD533a949740bb3306d119CC777fa900bA034cd52', 3000, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 3000, '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2'),\n        'function': 'V3_SWAP_EXACT_IN',\n        'weight': 100,\n        'estimate': 128331138758276360764\n    },\n)\n```\n\n#### Multi path\nHere, 90% of the amount should be swapped on a V3 pool and 10% on a V2 pool, all that in a single transaction using the UR codec.\n```python\n(\n    {\n        'path': ('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'),\n        'function': 'V2_SWAP_EXACT_IN',\n        'weight': 10,\n        'estimate': 32858922292711987411\n     },\n    {\n        'path': ('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', 3000, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'),\n        'function': 'V3_SWAP_EXACT_IN',\n        'weight': 90,\n        'estimate': 295000857928717844546\n    }\n)\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felnaril%2Funiswap-smart-path","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felnaril%2Funiswap-smart-path","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felnaril%2Funiswap-smart-path/lists"}