Skip to content

Getting_Started

Elnaril edited this page Oct 13, 2026 · 1 revision

How to get started with the Python Uniswap Universal Router SDK ?

This SDK lets you decode and encode transactions sent to the Uniswap Universal Router (UR) on Ethereum and any compatible chain, for Uniswap V2, V3 and V4. It is built on top of web3.py and is aimed at Python developers already familiar with the Ethereum blockchain and how DEXes work.

⚠ Before going further, make sure you are comfortable with general blockchain concepts and web3.py in particular.

Installation

The library is pip installable from pypi.org:

pip install uniswap-universal-router-decoder

See How to install the Python Uniswap Universal Router SDK ? for more details (virtual environments, updating, ...).

Codec creation

Everything starts with a codec. Depending on what you need to do, you can create it in 3 different ways.

Without any rpc access

If you only need to decode input data or encode data, no blockchain access is required:

from uniswap_universal_router_decoder import RouterCodec
codec = RouterCodec()

With a rpc endpoint

If you need to fetch transactions or build full transactions, provide a rpc endpoint:

from uniswap_universal_router_decoder import RouterCodec
rpc_endpoint = "https://..."  # your rpc endpoint
codec = RouterCodec(rpc_endpoint=rpc_endpoint)

With a Web3 instance

Or provide your own Web3 instance:

from web3 import Web3
from uniswap_universal_router_decoder import RouterCodec
w3 = Web3(...)  # your web3 instance
codec = RouterCodec(w3=w3)

Asynchronous

An AsyncRouterCodec is also available. It is used exactly the same way, but asynchronously for the parts doing rpc calls:

from uniswap_universal_router_decoder import AsyncRouterCodec
codec = AsyncRouterCodec(rpc_endpoint=rpc_endpoint)

Decode a transaction input

If you already have the input data of a transaction sent to the UR, you can decode it with the method decode.function_input():

trx_input = "0x3593564c000000000000000000 ... 90095b5c4e9f5845bba"  # the transaction input data
decoded_input = codec.decode.function_input(trx_input)

The result is a tuple containing the UR function called and a dict with the decoded commands, their inputs and the deadline:

(
    <Function execute(bytes,bytes[],uint256)>,  # the UR function that executes all commands
    {
        'commands': b'\x0b\x08',  # the list of commands sent to the UR
        'inputs': [  # the inputs used for each command
            ...
        ],
        'deadline': 1696926791  # The deadline after which the transaction is not valid any more.
    }
)

See How to decode a transaction input data ? for a full example.

Decode a transaction

If you only have the transaction hash, the codec can fetch the transaction from the blockchain and decode it, along with its input data. This requires the codec to have been created with a rpc endpoint or a Web3 instance:

trx_hash = "0xe97c7d58078dff6fd3052914926a7efb769cd2e10932f35f9a48ceebcf48e02c"
decoded_transaction = codec.decode.transaction(trx_hash)

See How to decode a transaction sent to the Universal Router ? for a full example.

Encode a swap

The UR allows the chaining of several functions in the same transaction. The chaining starts with the encode.chain() method and ends with the build() one, which returns the encoded data to be included in the transaction.

Here is how to encode a V3 swap with an exact in_amount:

from uniswap_universal_router_decoder import FunctionRecipient, RouterCodec

codec = RouterCodec()
encoded_data = codec.encode.chain().v3_swap_exact_in(
        FunctionRecipient.SENDER,  # the output tokens are sent to the transaction sender
        amount_in,  # in Wei
        amount_out_min,  # in Wei
        [
            in_token_address,  # checksum address of the token sent to the UR
            pool_fee,  # ex: 3000 for a 0.3% pool
            out_token_address,  # checksum address of the received token
        ],
    ).build(codec.get_default_deadline())  # unix timestamp after which the trx is not valid any more

# then in your transaction dict:
transaction["data"] = encoded_data

# you can now sign and send the transaction to the UR

Since v3.0.0, the chaining can also be started with encode() instead of encode.chain(), making the code a bit more concise:

encoded_data = codec.encode().v3_swap_exact_in(
        FunctionRecipient.SENDER,
        amount_in,
        amount_out_min,
        [in_token_address, pool_fee, out_token_address],
    ).build(codec.get_default_deadline())

Build and send the transaction

Instead of only building the input data, the SDK can also build the full transaction for you. This requires the codec to have been created with a rpc endpoint or a Web3 instance:

codec = RouterCodec(w3)
trx_params = (
    codec.encode.chain().v3_swap_exact_in(
        FunctionRecipient.SENDER,
        amount_in,  # in Wei
        amount_out_min,  # in Wei
        [
            in_token_address,
            pool_fee,
            out_token_address,
        ],
    ).build_transaction(
        sender_address,  # the 'from' address
        deadline=codec.get_default_deadline(),  # the swap deadline
    )
)

# then sign and send it with web3
raw_transaction = w3.eth.account.sign_transaction(trx_params, account.key).raw_transaction
trx_hash = w3.eth.send_raw_transaction(raw_transaction)

Where to go next

Common gotchas

  • Allowances: before a swap, the UR must be allowed to spend your tokens. Either approve the UR directly, or use the Permit2 flow (approve the Permit2 contract, then permit2_permit the UR).
  • Deadlines: a transaction is only valid until its deadline. Use codec.get_default_deadline() to compute a sensible one, or pass your own unix timestamp.
  • Checksum addresses: always pass checksummed token addresses, as returned by Web3.to_checksum_address().
  • Recipient codes: in decoded inputs, 0x0000000000000000000000000000000000000001 means the sender and 0x0000000000000000000000000000000000000002 means the router itself.
  • payerIsSender: indicates whether the input tokens come from the sender or are already held by the UR.
  • revert_on_fail: a per-command flag indicating whether the whole transaction must revert if that command fails.

Clone this wiki locally