Decode & Encode transaction data sent to Uniswap universal router
Project description
Uniswap Universal Router Decoder & Encoder
⚠ This version introduces breaking changes compared to v0.5, because it uses now web3 v6 This upgrade was necessary to implement a working PERMIT2_PERMIT encoding (because of a bug in EIP712 signatures, fixed in a web3 v6 dependency). Also, it allows to use Python 3.11.
The v0.5 code is visible on its own branch
Project Information
Code Quality
Release Notes
V0.6.0
- Breaking changes: use Web3.py v6 i/o v5
- Add support for the PERMIT2_PERMIT function
- Add support for chaining PERMIT2_PERMIT and V2_SWAP_EXACT_IN in the same transaction
Overview and Points of Attention
The object of this library is to decode & encode the transaction input sent to the Uniswap universal router (UR)
(address 0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B
on Ethereum Mainnet).
⚠ This library has not been audited, so use at your own risk !
⚠ There is no guarantee of compatibility between 2 versions: consider forcing the version in your dependency requirements.
⚠ This project is a work in progress so not all commands are decoded yet. Below the list of the already implemented ones. Also, only one command can be encoded in a single transaction input data at the moment.
Command Id | Function Name | Decode | Encode |
---|---|---|---|
0x00 | V3_SWAP_EXACT_IN | ✅ | ✅ |
0x01 | V3_SWAP_EXACT_OUT | ✅ | ❌ |
0x02 - 0x06 | ❌ | ❌ | |
0x07 | placeholder | N/A | N/A |
0x08 | V2_SWAP_EXACT_IN | ✅ | ✅ |
0x09 | V2_SWAP_EXACT_OUT | ✅ | ❌ |
0x0a | PERMIT2_PERMIT | ✅ | ✅ |
0x0b | WRAP_ETH | ✅ | ✅ |
0x0c | UNWRAP_WETH | ✅ | ❌ |
0x0d | PERMIT2_TRANSFER_FROM_BATCH | ❌ | ❌ |
0x0e - 0x0f | placeholders | N/A | N/A |
0x10 - 0x1d | ❌ | ❌ | |
0x1e - 0x3f | placeholders | N/A | N/A |
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-universal-router-decoder
Usage
The library exposes a class, RouterDecoder
with several public methods that can be used to decode or encode UR data.
How to decode a transaction input
To decode a transaction input, use the decode_function_input
method as follow:
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
trx_input = "0x3593564c000000000000000000 ... 90095b5c4e9f5845bba" # the trx input to decode
decoder = RouterDecoder()
decoded_trx_input = decoder.decode_function_input(trx_input)
How to decode a transaction
It's also possible to decode the whole transaction, given its hash and providing the decoder has been built with either a valid Web3 instance or the link to a rpc endpoint:
# Using a web3 instance
from web3 import Web3
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
w3 = Web3(...) # your web3 instance
decoder = RouterDecoder(w3=w3)
# Using a rpc endpoint
from web3 import Web3
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
rpc_link = "https://..." # your rpc enpoint
decoder = RouterDecoder(rpc_endpoint=rpc_link)
And then the decoder will get the transaction from the blockchain and decode it, along with its input data:
# Using a rpc endpoint
trx_hash = "0x52e63b7 ... 11b979dd9"
decoded_transaction = decoder.decode_transaction(trx_hash)
How to decode an Uniswap V3 swap path
The RouterDecoder
class exposes also the static method decode_v3_path
which can be used to decode a given Uniswap V3 path.
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
uniswap_v3_path = b"\xc0*\xaa9\xb2#\xfe\x8d\n\x0e ... \xd7\x89" # bytes or str hex
fn_name = "V3_SWAP_EXACT_IN" # Or V3_SWAP_EXACT_OUT
decoded_path = RouterDecoder.decode_v3_path(fn_name, uniswap_v3_path)
The result is a tuple, starting with the "in-token" and ending with the "out-token", with the pool fees between each pair.
How to encode a call to the function WRAP_ETH
This function can be used to convert eth to weth using the UR.
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
decoder = RouterDecoder()
encoded_data = decoder.encode_data_for_wrap_eth(amount_in_wei) # to convert amount_in_wei eth to weth
# then in your transaction dict:
transaction["data"] = encoded_data
# you can now sign and send the transaction to the UR
How to encode a call to the function V2_SWAP_EXACT_IN
This function can be used to swap tokens on a V2 pool. Correct allowances must have been set before using sending such transaction.
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
decoder = RouterDecoder()
encoded_data = decoder.encode_data_for_v2_swap_exact_in(
amount_in, # in Wei
min_amount_out, # in Wei
[
in_token_address,
out_token_address,
],
timestamp, # unix timestamp after which the trx will not be valid any more
)
# then in your transaction dict:
transaction["data"] = encoded_data
# you can now sign and send the transaction to the UR
How to encode a call to the function V3_SWAP_EXACT_IN
This function can be used to swap tokens on a V3 pool. Correct allowances must have been set before using sending such transaction.
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
decoder = RouterDecoder()
encoded_data = decoder.encode_data_for_v3_swap_exact_in(
amount_in, # in Wei
min_amount_out, # in Wei
[
in_token_address,
pool_fee,
out_token_address,
],
timestamp, # unix timestamp after which the trx will not be valid any more
)
# then in your transaction dict:
transaction["data"] = encoded_data
# you can now sign and send the transaction to the UR
How to encode a call to the function PERMIT2_PERMIT
This function is used to give an allowance to the universal router thanks to the Permit2 contract ((0x000000000022D473030F116dDEE9F6B43aC78BA3
).
It is also necessary to approve the Permit2 contract using the token approve function.
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
decoder = RouterDecoder()
data, signable_message = decoder.create_permit2_signable_message(
token_address,
amount, # max = 2**160 - 1
expiration,
nonce, # Permit2 nonce
spender, # UR
deadline,
1, # chain id
)
# Then you need to sign the message:
signed_message = acc.sign_message(signable_message) # where acc is your LocalAccount
# And now you can encode the data:
encoded_data = decoder.encode_data_for_permit2_permit(data, signed_message)
# Then in your transaction dict:
transaction["data"] = encoded_data
# you can now sign and send the transaction to the UR
After that, you can swap tokens using the Uniswap universal router.
How to chain a call to PERMIT2_PERMIT and V2_SWAP_EXACT_IN in the same transaction
Don't forget to give a token allowance to the Permit2 contract as well.
from uniswap_universal_router_decoder.router_decoder import RouterDecoder
decoder = RouterDecoder()
# Permit signature
data, signable_message = decoder.create_permit2_signable_message(
token_address,
amount, # max = 2**160 - 1
expiration,
nonce, # Permit2 nonce
spender, # UR
deadline,
1, # chain id
)
# Then you need to sign the message:
signed_message = acc.sign_message(signable_message) # where acc is your LocalAccount
# Permit + v2 swap encoding
path = [token_in_address, token_out_address]
encoded_data = decoder.encode_data_for_v2_swap_exact_in_with_permit(
permit_single=data,
signed_permit_single=signed_message,
amount_in=amount_in,
amount_out_min=amount_out_min,
path=path,
)
# Then in your transaction dict:
transaction["data"] = encoded_data
# you can now sign and send the transaction to the UR
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file uniswap-universal-router-decoder-0.6.0.tar.gz
.
File metadata
- Download URL: uniswap-universal-router-decoder-0.6.0.tar.gz
- Upload date:
- Size: 17.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.9.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4c5065a78270692e22f8180cdcba4faf813ebb284606f1309a676006c57e0621 |
|
MD5 | 128384ae2b795e00a37801e20648cf53 |
|
BLAKE2b-256 | 369faa1791f7f30a41e7278c61aa5008e42fbe3fadc8e9b614a0a91d3744d0de |
Provenance
File details
Details for the file uniswap_universal_router_decoder-0.6.0-py3-none-any.whl
.
File metadata
- Download URL: uniswap_universal_router_decoder-0.6.0-py3-none-any.whl
- Upload date:
- Size: 12.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.9.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7adb0da6489ae83185d2e7ec3c12d1398d62301ce41fd6bf0552091b937e5f28 |
|
MD5 | 1604dd0cc01cf9cb1e060f080126503c |
|
BLAKE2b-256 | b5a0a335c553b6bdb1516d442e1dc6620dbb841f1ad889d934453994643ca839 |