Uniswap Smart Path
Project Information
Code Quality
Release notes
v0.3.0
- Add Rate Limiter for APIs using credits, CUPS or request units, as well as number of requests per time unit.
- Use credit-rate-limit under the hood.
- Remove
eth_callfrom the methods that are automatically verified by web3 (to prevent surges of uselesseth_chainId)
- Add support for Python 3.12 & 3.13
- Add support for web3.py v7
- Miscellaneous fixes/updates for tests and linting
Overview
When 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.
The object of this library is to find the path(s), from v2 and v3 pools, to swap with the best price, and to return it/them in order to be used directly with the Universal Router codec, along with a percentage to know how to divide the amount between them if there is more than one result.
⚠ To prevent surges of useless eth_chainId, eth_call is removed from the methods that are automatically verified by web3.
⚠ This tool does not replace your own due diligence to find the best price/path to swap any token.
Installation
A good practice is to use Python virtual environments, here is a tutorial.
The library can be pip installed from pypi.org as usual:
# update pip to latest version if needed
pip install -U pip
# install the decoder from pypi.org
pip install uniswap-smart-path
Usage
The library exposes a class, SmartPath with a public method get_swap_in_path() that can be used to find the best path/price.
For performance's sake, it is asynchronous. Currently, it supports only the Ethereum blockchain.
from uniswap_smart_path import SmartPath
smart_path = await SmartPath.create(async_w3) # where async_w3 is your AsyncWeb3 instance
path = await smart_path.get_swap_in_path(amount_in_wei, token0_address, token1_address)
You can also create the SmartPath instance from a rpc endpoint:
from uniswap_smart_path import SmartPath
smart_path = await SmartPath.create(rpc_endpoint=rpc_endpoint)
V2 or V3 pools only
The 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.
Currently, it supports only the Ethereum blockchain.
from uniswap_smart_path import SmartPath
smart_path = await SmartPath.create_v2_only(rpc_endpoint=rpc_endpoint) # could also use an AsyncWeb3 instance i/o rpc
Same thing if you wish to look into V3 pools only, just use SmartPath.create_v3_only()
Currently, it supports only the Ethereum blockchain.
from uniswap_smart_path import SmartPath
smart_path = await SmartPath.create_v3_only(rpc_endpoint=rpc_endpoint) # could also use an AsyncWeb3 instance i/o rpc
Custom pools and blockchains
A custom SmartPath can be created with the factory method SmartPath.create_custom()
from uniswap_smart_path import SmartPath
pivot_tokens = (wbnb_address, usdt_address, usdc_address, dai_address) # BSC addresses
v3_pool_fees = (100, 500, 2500, 10000) # Pancakeswap v3 fees
smart_path = await SmartPath.create_custom(
w3, # BSC AsyncWeb3 instance
pivot_tokens=pivot_tokens,
v3_pool_fees=v3_pool_fees,
v2_router=pancakeswapv2_address,
v2_factory=pancakeswapv2_factory,
v3_quoter=pancakeswapv3_quoter_address,
v3_factory=pancakeswapv3_factory,
)
Using a Rate Limiter
It's possible to manage rate limits, though only API calls used to compute the paths are rate limited.
(Only the RPC method eth_call is concerned)
API calls performed to create the SmartPath objects are not rate limited.
Both eth_call and chain_id are involved in these creations.
Credit Rate Limit
For APIs that use credits, computation unit per second (CUPS) or request units:
from uniswap_smart_path import SmartPath, SmartRateLimiter
# Define a credit limiter allowing 300 credits per second.
# The method 'eth_call' costs 20 credits.
credit_limiter = SmartRateLimiter(interval=1, max_credits=300, method_credits={"eth_call": 20})
smart_path = await SmartPath.create(w3, smart_rate_limiter=credit_limiter)
Note that only the eth_call method is needed at the moment.
Count Rate Limit
For APIs that just count the number of requests per time unit:
from uniswap_smart_path import SmartPath, SmartRateLimiter
# Define a count limiter allowing 5 requests per second.
count_limiter = SmartRateLimiter(interval=1, max_count=5)
smart_path = await SmartPath.create(w3, smart_rate_limiter=count_limiter)
Result
Examples of output paths that you can use with the UR codec to encode a transaction.
Single path
(
{
'path': ('0xD533a949740bb3306d119CC777fa900bA034cd52', 3000, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 3000, '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2'),
'function': 'V3_SWAP_EXACT_IN',
'weight': 100,
'estimate': 128331138758276360764
},
)
Multi path
Here, 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.
(
{
'path': ('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'),
'function': 'V2_SWAP_EXACT_IN',
'weight': 10,
'estimate': 32858922292711987411
},
{
'path': ('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', 3000, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'),
'function': 'V3_SWAP_EXACT_IN',
'weight': 90,
'estimate': 295000857928717844546
}
)
Metadata
Release files for uniswap-smart-path 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| uniswap_smart_path-0.3.0.tar.gz | 18.2 kB | Without provenance | Details for uniswap_smart_path-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| uniswap_smart_path-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for uniswap_smart_path-0.3.0-py3-none-any.whl |
Total release size: 32.3 kB
Release files / uniswap_smart_path-0.3.0.tar.gz
| Download URL | uniswap_smart_path-0.3.0.tar.gz |
|---|---|
| Size | 18.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e3217a1f4f2ba1115de39038e9b28ee7d0469368c71454b790b9ea7e5b0dfda
|
|
BLAKE2b-256 checksum How to use checksums |
d7cc00de046c269a0202f98fb95e80ee92bc206b24d3c2836f73c6357d79880e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.9.5
|
Release files / uniswap_smart_path-0.3.0-py3-none-any.whl
| Download URL | uniswap_smart_path-0.3.0-py3-none-any.whl |
|---|---|
| Size | 14.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e747679c973ee6b1a9b2036648990889df5ea396e57b11b1c93f0e5022c69381
|
|
BLAKE2b-256 checksum How to use checksums |
a74cdd13f25b9d49a45ddac074c5a82bb44352694173c99a6650b27a1c5c98a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.9.5
|
Security for uniswap-smart-path 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.