Skip to main content

Find the path from v2 and v3 pools to swap with the best price

Project description

Uniswap Smart Path

Project Information

Continous Integration PyPI - Python Version GitHub release (latest by date) PyPi Repository License

Code Quality

Test Coverage Imports: isort Type Checker: mypy Linter: flake8

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_call from the methods that are automatically verified by web3 (to prevent surges of useless eth_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
    }
)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uniswap_smart_path-0.3.0.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

uniswap_smart_path-0.3.0-py3-none-any.whl (14.1 kB view details)

Uploaded Python 3

File details

Details for the file uniswap_smart_path-0.3.0.tar.gz.

File metadata

  • Download URL: uniswap_smart_path-0.3.0.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.9.5

File hashes

Hashes for uniswap_smart_path-0.3.0.tar.gz
Algorithm Hash digest
SHA256 9e3217a1f4f2ba1115de39038e9b28ee7d0469368c71454b790b9ea7e5b0dfda
MD5 e04768150f4353fac6ff5b3edf3918f9
BLAKE2b-256 d7cc00de046c269a0202f98fb95e80ee92bc206b24d3c2836f73c6357d79880e

See more details on using hashes here.

File details

Details for the file uniswap_smart_path-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for uniswap_smart_path-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e747679c973ee6b1a9b2036648990889df5ea396e57b11b1c93f0e5022c69381
MD5 1716c644bf5f65f2852611bbc5726160
BLAKE2b-256 a74cdd13f25b9d49a45ddac074c5a82bb44352694173c99a6650b27a1c5c98a2

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page