Repository navigation
Getting_Started
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.
The library is pip installable from pypi.org:
pip install uniswap-universal-router-decoderSee How to install the Python Uniswap Universal Router SDK ? for more details (virtual environments, updating, ...).
Everything starts with a codec. Depending on what you need to do, you can create it in 3 different ways.
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()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)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)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)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.
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.
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 URSince 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())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)- How to install the Python Uniswap Universal Router SDK ?
- How to decode a transaction sent to the Universal Router ?
- How to decode a transaction input data ?
- How to decode a Uniswap V3 path ?
- How to encode a Uniswap V3 path ?
- How to encode a Uniswap V4 pool id ?
- How to encode a Uniswap V2 swap ?
- How to encode a Uniswap V3 swap ?
- How to encode a multi-hop swap ?
- How to encode an ETH wrap or unwrap ?
- How to encode a Permit2 permit ?
- How to chain several commands in the same transaction ?
- How to build a full transaction to the Universal Router ?
-
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_permitthe 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,
0x0000000000000000000000000000000000000001means the sender and0x0000000000000000000000000000000000000002means 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.
If you find this library useful, consider a donation and be part of the Supporter Community! :)
- ☕️☕️☕️ https://www.buymeacoffee.com/elnaril ☕️☕️☕️
- Ethereum compatible: 0xe32A121C89121bF8B829D6d88BBEA89e5d88f002
- Sponsoring: https://github.com/sponsors/Elnaril
Thank you to all supporters!! 🙏
Also, consider ⭐ starring ⭐ the repository and following the GitHub account and/or 𝕏 to get the next lib updates!