uniswap-universal-router-decoder


Nameuniswap-universal-router-decoder JSON
Version 1.1.0 PyPI version JSON
download
home_page
SummaryDecode & Encode transaction data sent to Uniswap Universal Router
upload_time2024-02-07 07:08:54
maintainer
docs_urlNone
author
requires_python>=3.8
licenseMIT License
keywords blockchain ethereum uniswap universal router decoder encoder codec wrapper sdk
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # Uniswap Universal Router Decoder & Encoder

---

#### Project Information
[![Tests & Lint](https://github.com/Elnaril/uniswap-universal-router-decoder/actions/workflows/tests.yml/badge.svg)](https://github.com/Elnaril/uniswap-universal-router-decoder/actions/workflows/tests.yml)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/uniswap-universal-router-decoder)](https://pypi.org/project/uniswap-universal-router-decoder/)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/Elnaril/uniswap-universal-router-decoder)](https://github.com/Elnaril/uniswap-universal-router-decoder/releases)
[![PyPi Repository](https://img.shields.io/badge/repository-pipy.org-blue)](https://pypi.org/project/uniswap-universal-router-decoder/)
[![GitHub](https://img.shields.io/github/license/Elnaril/uniswap-universal-router-decoder)](https://github.com/Elnaril/uniswap-universal-router-decoder/blob/master/LICENSE)

#### Code Quality
[![CodeQL](https://github.com/elnaril/uniswap-universal-router-decoder/workflows/CodeQL/badge.svg)](https://github.com/Elnaril/uniswap-universal-router-decoder/actions/workflows/github-code-scanning/codeql)
[![Test Coverage](https://img.shields.io/badge/dynamic/json?color=blueviolet&label=coverage&query=%24.totals.percent_covered_display&suffix=%25&url=https%3A%2F%2Fraw.githubusercontent.com%2FElnaril%2Funiswap-universal-router-decoder%2Fmaster%2Fcoverage.json)](https://github.com/Elnaril/uniswap-universal-router-decoder/blob/master/coverage.json)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
[![Type Checker: mypy](https://img.shields.io/badge/%20type%20checker-mypy-%231674b1?style=flat&labelColor=ef8336)](https://mypy-lang.org/)
[![Linter: flake8](https://img.shields.io/badge/%20linter-flake8-%231674b1?style=flat&labelColor=ef8336)](https://flake8.pycqa.org/en/latest/)

---

## Release Notes
### v1.1.0
 - Add support for the TRANSFER function
 - Add support for decoding the "revert on fail" flag and prepare for encoding on UR functions that support it.
 - Add support for encoding the `execute()` function without deadline
### v1.0.1
 - Fix issue #35 - fails to decode input data when there is too many commands
### v1.0.0
 - Add support for SWEEP and PAY_PORTION
 - Fix decoding issues
 - Remove useless parameter `payer_is_sender` from `v*_swap_exact_in_from_balance()` methods
 - Update Router ABI
 - Add uint48 and uint160 in ABI builder

---

## 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 [`0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD`](https://etherscan.io/address/0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD) 
on Ethereum Mainnet). It is based on, and is intended to be used with [web3.py](https://github.com/ethereum/web3.py)

⚠ This library has not been audited, so use at your own risk !

⚠ This project is a work in progress so not all commands are decoded yet. Below the list of the already implemented ones.

| Command Id | Function Name | Decode | Encode
| ---------- | ------------- |:------:|:------:
| 0x00 | V3_SWAP_EXACT_IN | ✅ | ✅
| 0x01 | V3_SWAP_EXACT_OUT | ✅ | ✅
| 0x02 - 0x03 |  | ❌ | ❌
| 0x04 | SWEEP | ✅ | ✅
| 0x05 | TRANSFER | ✅ | ✅
| 0x06 | PAY_PORTION | ✅ | ✅
| 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](https://python.readthedocs.io/en/latest/library/venv.html), here is a [tutorial](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/).

The library can be pip installed from [pypi.org](https://pypi.org/project/uniswap-universal-router-decoder/) as usual:

```bash
# 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, `RouterCodec` 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 follows:

```python
from uniswap_universal_router_decoder import RouterCodec

trx_input = "0x3593564c000000000000000000 ... 90095b5c4e9f5845bba"  # the trx input to decode
codec = RouterCodec()
decoded_trx_input = codec.decode.function_input(trx_input)
```

Example of decoded input returned by `decode.function_input()`:
```python
(
    <Function execute(bytes,bytes[],uint256)>,  # the UR function that executes all commands
    {
        'commands': b'\x0b\x00',  # the list of commands sent to the UR
        'inputs': [  # the inputs used for each command
            (
                <Function WRAP_ETH(address,uint256)>,  # the function corresponding to the first command
                {                                      # and its parameters
                    'recipient': '0x0000000000000000000000000000000000000002',  # code indicating the recipient of this command is the router
                    'amountMin': 4500000000000000000  # the amount in WEI to wrap
                },
                {
                    'revert_on_fail': True  # flag indicating if the transaction must revert when this command fails
                },
            ),
            (
                <Function V3_SWAP_EXACT_IN(address,uint256,uint256,bytes,bool)>,  # the function corresponding to the second command
                {                                                                 # and its parameters
                    'recipient': '0x0000000000000000000000000000000000000001',  # code indicating the sender will receive the output of this command
                    'amountIn': 4500000000000000000,  # the exact amount sent
                    'amountOutMin': 6291988002,  # the min amount expected of the bought token for the swap to be executed 
                    'path': b"\xc0*\xaa9\xb2#\xfe\x8d\n\x0e\\O'\xea\xd9\x08<ul\xc2"  # the V3 path (tokens + pool fees)
                           b'\x00\x01\xf4\xa0\xb8i\x91\xc6!\x8b6\xc1\xd1\x9dJ.'  # can be decoded with the method decode.v3_path()
                           b'\x9e\xb0\xce6\x06\xebH',
                    'payerIsSender': False  # a bool indicating if the input tokens come from the sender or are already in the UR
                },
                {
                    'revert_on_fail': True  # flag indicating if the transaction must revert when this command fails
                },
            )
        ],
        'deadline': 1678441619  # The deadline after which the transaction is not valid any more.
    }
)
```

### How to decode a transaction
It's also possible to decode the whole transaction, given its hash 
and providing the codec has been built with either a valid `Web3` instance or the link to a rpc endpoint:

```python
# Using a web3 instance
from web3 import Web3
from uniswap_universal_router_decoder import RouterCodec
w3 = Web3(...)  # your web3 instance
codec = RouterCodec(w3=w3)
```

```python
# Using a rpc endpoint
from web3 import Web3
from uniswap_universal_router_decoder import RouterCodec
rpc_link = "https://..."  # your rpc endpoint
codec = RouterCodec(rpc_endpoint=rpc_link)
```

And then the decoder will get the transaction from the blockchain and decode it, along with its input data:
```python
trx_hash = "0x52e63b7 ... 11b979dd9"
decoded_transaction = codec.decode.transaction(trx_hash)
```

### How to decode an Uniswap V3 swap path
The `RouterCodec` class exposes also the method `decode.v3_path()` which can be used to decode a given Uniswap V3 path.

```python
from uniswap_universal_router_decoder import RouterCodec

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
codec = RouterCodec()
decoded_path = codec.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
The Universal Router allows the chaining of several functions in the same transaction.
This codec supports it (at least for supported functions) and exposes public methods that can be chained.

The chaining starts with the `encode.chain()` method and ends with the `build()` one which returns the full encoded data to be included in the transaction.
Below some examples of encoded data for one function and one example for 2 functions.

Default values for deadlines and expirations can be computed with the static methods `get_default_deadline()` and `get_default_expiration()` respectively.
```python
from uniswap_universal_router_decoder import RouterCodec

default_deadline = RouterCodec.get_default_deadline()
default_expiration = RouterCodec.get_default_expiration()

```
These 2 functions accept a custom duration in seconds as argument.


### How to encode a call to the function WRAP_ETH
This function can be used to convert eth to weth using the UR.
```python
from uniswap_universal_router_decoder import FunctionRecipient, RouterCodec

codec = RouterCodec()
encoded_data = codec.encode.chain().wrap_eth(FunctionRecipient.SENDER, amount_in_wei).build(1676825611)  # to convert amount_in_wei eth to weth, and send them to the transaction sender.

# 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 sending such transaction.
```python
from uniswap_universal_router_decoder import FunctionRecipient, RouterCodec

codec = RouterCodec()
encoded_data = codec.encode.chain().v2_swap_exact_in(
        FunctionRecipient.SENDER,  # the output tokens are sent to the transaction sender
        amount_in,  # in Wei
        min_amount_out,  # in Wei
        [
            in_token_address,  # checksum address of the token sent to the UR 
            out_token_address,  # checksum address of the received token
        ],
    ).build(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
```
For more details, see this [tutorial](https://hackernoon.com/how-to-buy-a-token-on-the-uniswap-universal-router-with-python)

### How to encode a call to the function V2_SWAP_EXACT_OUT
This function can be used to swap tokens on a V2 pool. Correct allowances must have been set before sending such transaction.
```python
from uniswap_universal_router_decoder import FunctionRecipient, RouterCodec

codec = RouterCodec()
encoded_data = codec.encode.chain().v2_swap_exact_out(
        FunctionRecipient.SENDER,
        amount_out,  # in Wei
        max_amount_in,  # in Wei
        [
            in_token_address,
            out_token_address,
        ],
    ).build(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.
```python
from uniswap_universal_router_decoder import FunctionRecipient, RouterCodec

codec = RouterCodec()
encoded_data = codec.encode.chain().v3_swap_exact_in(
        FunctionRecipient.SENDER,
        amount_in,  # in Wei
        min_amount_out,  # in Wei
        [
            in_token_address,
            pool_fee,
            out_token_address,
        ],
    ).build(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_OUT
This function can be used to swap tokens on a V3 pool. Correct allowances must have been set before sending such transaction.
```python
from uniswap_universal_router_decoder import FunctionRecipient, RouterCodec

codec = RouterCodec()
encoded_data = codec.encode.chain().v3_swap_exact_out(
        FunctionRecipient.SENDER,
        amount_out,  # in Wei
        max_amount_in,  # in Wei
        [
            in_token_address,
            pool_fee,
            out_token_address,
        ],
    ).build(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`](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)).
It is also necessary to approve the Permit2 contract using the token approve function.
See this [tutorial](https://hackernoon.com/python-how-to-use-permit2-with-the-uniswap-universal-router)
```python
from uniswap_universal_router_decoder import RouterCodec

codec = RouterCodec()
data, signable_message = codec.create_permit2_signable_message(
    token_address,
    amount,  # max = 2**160 - 1
    expiration,
    nonce,  # Permit2 nonce
    spender,  # The UR checksum address
    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 = codec.encode.chain().permit2_permit(data, signed_message).build(deadline)

# 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.

```python
from uniswap_universal_router_decoder import FunctionRecipient, RouterCodec

codec = RouterCodec()

# Permit signature
data, signable_message = codec.create_permit2_signable_message(
    token_address,
    amount,  # max = 2**160 - 1
    expiration,
    nonce,  # Permit2 nonce
    spender,  # The UR checksum address
    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 = (
    codec
        .encode
        .chain()
        .permit2_permit(data, signed_message)
        .v2_swap_exact_in(FunctionRecipient.SENDER, Wei(10**18), Wei(0), path)
        .build(deadline)
)

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

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

### Other chainable functions
(See integration tests for full examples) 

#### PAY_PORTION
Example where a recipient is paid 1% of the USDC amount:
```python
.pay_portion(FunctionRecipient.CUSTOM, usdc_address, 100, recipient_address)

```
#### SWEEP
Example where the sender gets back all remaining USDC:
```python
.sweep(FunctionRecipient.SENDER, usdc_address, 0)
```

#### TRANSFER
Example where an USDC amount is sent to a recipient:
```python
.transfer(FunctionRecipient.CUSTOM, usdc_address, usdc_amount, recipient_address)
```


## Tutorials and Recipes:
See the [SDK Wiki](https://github.com/Elnaril/uniswap-universal-router-decoder/wiki).

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "uniswap-universal-router-decoder",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "blockchain,ethereum,uniswap,universal router,decoder,encoder,codec,wrapper,SDK",
    "author": "",
    "author_email": "Elnaril <elnaril_dev@caramail.com>",
    "download_url": "https://files.pythonhosted.org/packages/03/8f/917e949f944878b1d4898d346c23ea8b4eb3112c1c9d98aea542dff6d8c2/uniswap-universal-router-decoder-1.1.0.tar.gz",
    "platform": null,
    "description": "# Uniswap Universal Router Decoder & Encoder\n\n---\n\n#### Project Information\n[![Tests & Lint](https://github.com/Elnaril/uniswap-universal-router-decoder/actions/workflows/tests.yml/badge.svg)](https://github.com/Elnaril/uniswap-universal-router-decoder/actions/workflows/tests.yml)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/uniswap-universal-router-decoder)](https://pypi.org/project/uniswap-universal-router-decoder/)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/Elnaril/uniswap-universal-router-decoder)](https://github.com/Elnaril/uniswap-universal-router-decoder/releases)\n[![PyPi Repository](https://img.shields.io/badge/repository-pipy.org-blue)](https://pypi.org/project/uniswap-universal-router-decoder/)\n[![GitHub](https://img.shields.io/github/license/Elnaril/uniswap-universal-router-decoder)](https://github.com/Elnaril/uniswap-universal-router-decoder/blob/master/LICENSE)\n\n#### Code Quality\n[![CodeQL](https://github.com/elnaril/uniswap-universal-router-decoder/workflows/CodeQL/badge.svg)](https://github.com/Elnaril/uniswap-universal-router-decoder/actions/workflows/github-code-scanning/codeql)\n[![Test Coverage](https://img.shields.io/badge/dynamic/json?color=blueviolet&label=coverage&query=%24.totals.percent_covered_display&suffix=%25&url=https%3A%2F%2Fraw.githubusercontent.com%2FElnaril%2Funiswap-universal-router-decoder%2Fmaster%2Fcoverage.json)](https://github.com/Elnaril/uniswap-universal-router-decoder/blob/master/coverage.json)\n[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)\n[![Type Checker: mypy](https://img.shields.io/badge/%20type%20checker-mypy-%231674b1?style=flat&labelColor=ef8336)](https://mypy-lang.org/)\n[![Linter: flake8](https://img.shields.io/badge/%20linter-flake8-%231674b1?style=flat&labelColor=ef8336)](https://flake8.pycqa.org/en/latest/)\n\n---\n\n## Release Notes\n### v1.1.0\n - Add support for the TRANSFER function\n - Add support for decoding the \"revert on fail\" flag and prepare for encoding on UR functions that support it.\n - Add support for encoding the `execute()` function without deadline\n### v1.0.1\n - Fix issue #35 - fails to decode input data when there is too many commands\n### v1.0.0\n - Add support for SWEEP and PAY_PORTION\n - Fix decoding issues\n - Remove useless parameter `payer_is_sender` from `v*_swap_exact_in_from_balance()` methods\n - Update Router ABI\n - Add uint48 and uint160 in ABI builder\n\n---\n\n## Overview and Points of Attention\n\nThe object of this library is to decode & encode the transaction input sent to the Uniswap universal router (UR)\n(address [`0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD`](https://etherscan.io/address/0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD) \non Ethereum Mainnet). It is based on, and is intended to be used with [web3.py](https://github.com/ethereum/web3.py)\n\n\u26a0 This library has not been audited, so use at your own risk !\n\n\u26a0 This project is a work in progress so not all commands are decoded yet. Below the list of the already implemented ones.\n\n| Command Id | Function Name | Decode | Encode\n| ---------- | ------------- |:------:|:------:\n| 0x00 | V3_SWAP_EXACT_IN | \u2705 | \u2705\n| 0x01 | V3_SWAP_EXACT_OUT | \u2705 | \u2705\n| 0x02 - 0x03 |  | \u274c | \u274c\n| 0x04 | SWEEP | \u2705 | \u2705\n| 0x05 | TRANSFER | \u2705 | \u2705\n| 0x06 | PAY_PORTION | \u2705 | \u2705\n| 0x07 | placeholder  | N/A | N/A\n| 0x08 | V2_SWAP_EXACT_IN | \u2705 | \u2705\n| 0x09 | V2_SWAP_EXACT_OUT | \u2705 | \u2705\n| 0x0a | PERMIT2_PERMIT | \u2705 | \u2705\n| 0x0b | WRAP_ETH | \u2705 | \u2705\n| 0x0c | UNWRAP_WETH | \u2705 | \u2705\n| 0x0d | PERMIT2_TRANSFER_FROM_BATCH | \u274c | \u274c\n| 0x0e - 0x0f | placeholders | N/A | N/A\n| 0x10 - 0x1d |  | \u274c | \u274c\n| 0x1e - 0x3f | placeholders | N/A | N/A\n\n---\n\n## Installation\nA good practice is to use [Python virtual environments](https://python.readthedocs.io/en/latest/library/venv.html), here is a [tutorial](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/).\n\nThe library can be pip installed from [pypi.org](https://pypi.org/project/uniswap-universal-router-decoder/) as usual:\n\n```bash\n# update pip to latest version if needed\npip install -U pip\n\n# install the decoder from pypi.org\npip install uniswap-universal-router-decoder\n```\n\n---\n\n## Usage\n\nThe library exposes a class, `RouterCodec` with several public methods that can be used to decode or encode UR data.\n\n### How to decode a transaction input\nTo decode a transaction input, use the `decode.function_input()` method as follows:\n\n```python\nfrom uniswap_universal_router_decoder import RouterCodec\n\ntrx_input = \"0x3593564c000000000000000000 ... 90095b5c4e9f5845bba\"  # the trx input to decode\ncodec = RouterCodec()\ndecoded_trx_input = codec.decode.function_input(trx_input)\n```\n\nExample of decoded input returned by `decode.function_input()`:\n```python\n(\n    <Function execute(bytes,bytes[],uint256)>,  # the UR function that executes all commands\n    {\n        'commands': b'\\x0b\\x00',  # the list of commands sent to the UR\n        'inputs': [  # the inputs used for each command\n            (\n                <Function WRAP_ETH(address,uint256)>,  # the function corresponding to the first command\n                {                                      # and its parameters\n                    'recipient': '0x0000000000000000000000000000000000000002',  # code indicating the recipient of this command is the router\n                    'amountMin': 4500000000000000000  # the amount in WEI to wrap\n                },\n                {\n                    'revert_on_fail': True  # flag indicating if the transaction must revert when this command fails\n                },\n            ),\n            (\n                <Function V3_SWAP_EXACT_IN(address,uint256,uint256,bytes,bool)>,  # the function corresponding to the second command\n                {                                                                 # and its parameters\n                    'recipient': '0x0000000000000000000000000000000000000001',  # code indicating the sender will receive the output of this command\n                    'amountIn': 4500000000000000000,  # the exact amount sent\n                    'amountOutMin': 6291988002,  # the min amount expected of the bought token for the swap to be executed \n                    'path': b\"\\xc0*\\xaa9\\xb2#\\xfe\\x8d\\n\\x0e\\\\O'\\xea\\xd9\\x08<ul\\xc2\"  # the V3 path (tokens + pool fees)\n                           b'\\x00\\x01\\xf4\\xa0\\xb8i\\x91\\xc6!\\x8b6\\xc1\\xd1\\x9dJ.'  # can be decoded with the method decode.v3_path()\n                           b'\\x9e\\xb0\\xce6\\x06\\xebH',\n                    'payerIsSender': False  # a bool indicating if the input tokens come from the sender or are already in the UR\n                },\n                {\n                    'revert_on_fail': True  # flag indicating if the transaction must revert when this command fails\n                },\n            )\n        ],\n        'deadline': 1678441619  # The deadline after which the transaction is not valid any more.\n    }\n)\n```\n\n### How to decode a transaction\nIt's also possible to decode the whole transaction, given its hash \nand providing the codec has been built with either a valid `Web3` instance or the link to a rpc endpoint:\n\n```python\n# Using a web3 instance\nfrom web3 import Web3\nfrom uniswap_universal_router_decoder import RouterCodec\nw3 = Web3(...)  # your web3 instance\ncodec = RouterCodec(w3=w3)\n```\n\n```python\n# Using a rpc endpoint\nfrom web3 import Web3\nfrom uniswap_universal_router_decoder import RouterCodec\nrpc_link = \"https://...\"  # your rpc endpoint\ncodec = RouterCodec(rpc_endpoint=rpc_link)\n```\n\nAnd then the decoder will get the transaction from the blockchain and decode it, along with its input data:\n```python\ntrx_hash = \"0x52e63b7 ... 11b979dd9\"\ndecoded_transaction = codec.decode.transaction(trx_hash)\n```\n\n### How to decode an Uniswap V3 swap path\nThe `RouterCodec` class exposes also the method `decode.v3_path()` which can be used to decode a given Uniswap V3 path.\n\n```python\nfrom uniswap_universal_router_decoder import RouterCodec\n\nuniswap_v3_path = b\"\\xc0*\\xaa9\\xb2#\\xfe\\x8d\\n\\x0e ... \\xd7\\x89\"  # bytes or str hex\nfn_name = \"V3_SWAP_EXACT_IN\"  # Or V3_SWAP_EXACT_OUT\ncodec = RouterCodec()\ndecoded_path = codec.decode.v3_path(fn_name, uniswap_v3_path)\n```\nThe result is a tuple, starting with the \"in-token\" and ending with the \"out-token\", with the pool fees between each pair.\n\n\n### How to encode\nThe Universal Router allows the chaining of several functions in the same transaction.\nThis codec supports it (at least for supported functions) and exposes public methods that can be chained.\n\nThe chaining starts with the `encode.chain()` method and ends with the `build()` one which returns the full encoded data to be included in the transaction.\nBelow some examples of encoded data for one function and one example for 2 functions.\n\nDefault values for deadlines and expirations can be computed with the static methods `get_default_deadline()` and `get_default_expiration()` respectively.\n```python\nfrom uniswap_universal_router_decoder import RouterCodec\n\ndefault_deadline = RouterCodec.get_default_deadline()\ndefault_expiration = RouterCodec.get_default_expiration()\n\n```\nThese 2 functions accept a custom duration in seconds as argument.\n\n\n### How to encode a call to the function WRAP_ETH\nThis function can be used to convert eth to weth using the UR.\n```python\nfrom uniswap_universal_router_decoder import FunctionRecipient, RouterCodec\n\ncodec = RouterCodec()\nencoded_data = codec.encode.chain().wrap_eth(FunctionRecipient.SENDER, amount_in_wei).build(1676825611)  # to convert amount_in_wei eth to weth, and send them to the transaction sender.\n\n# then in your transaction dict:\ntransaction[\"data\"] = encoded_data\n\n# you can now sign and send the transaction to the UR\n```\n\n### How to encode a call to the function V2_SWAP_EXACT_IN\nThis function can be used to swap tokens on a V2 pool. Correct allowances must have been set before sending such transaction.\n```python\nfrom uniswap_universal_router_decoder import FunctionRecipient, RouterCodec\n\ncodec = RouterCodec()\nencoded_data = codec.encode.chain().v2_swap_exact_in(\n        FunctionRecipient.SENDER,  # the output tokens are sent to the transaction sender\n        amount_in,  # in Wei\n        min_amount_out,  # in Wei\n        [\n            in_token_address,  # checksum address of the token sent to the UR \n            out_token_address,  # checksum address of the received token\n        ],\n    ).build(timestamp)  # unix timestamp after which the trx will not be valid any more\n\n# then in your transaction dict:\ntransaction[\"data\"] = encoded_data\n\n# you can now sign and send the transaction to the UR\n```\nFor more details, see this [tutorial](https://hackernoon.com/how-to-buy-a-token-on-the-uniswap-universal-router-with-python)\n\n### How to encode a call to the function V2_SWAP_EXACT_OUT\nThis function can be used to swap tokens on a V2 pool. Correct allowances must have been set before sending such transaction.\n```python\nfrom uniswap_universal_router_decoder import FunctionRecipient, RouterCodec\n\ncodec = RouterCodec()\nencoded_data = codec.encode.chain().v2_swap_exact_out(\n        FunctionRecipient.SENDER,\n        amount_out,  # in Wei\n        max_amount_in,  # in Wei\n        [\n            in_token_address,\n            out_token_address,\n        ],\n    ).build(timestamp)  # unix timestamp after which the trx will not be valid any more\n\n# then in your transaction dict:\ntransaction[\"data\"] = encoded_data\n# you can now sign and send the transaction to the UR\n```\n\n### How to encode a call to the function V3_SWAP_EXACT_IN\nThis function can be used to swap tokens on a V3 pool. Correct allowances must have been set before using sending such transaction.\n```python\nfrom uniswap_universal_router_decoder import FunctionRecipient, RouterCodec\n\ncodec = RouterCodec()\nencoded_data = codec.encode.chain().v3_swap_exact_in(\n        FunctionRecipient.SENDER,\n        amount_in,  # in Wei\n        min_amount_out,  # in Wei\n        [\n            in_token_address,\n            pool_fee,\n            out_token_address,\n        ],\n    ).build(timestamp)  # unix timestamp after which the trx will not be valid any more\n\n# then in your transaction dict:\ntransaction[\"data\"] = encoded_data\n\n# you can now sign and send the transaction to the UR\n```\n\n### How to encode a call to the function V3_SWAP_EXACT_OUT\nThis function can be used to swap tokens on a V3 pool. Correct allowances must have been set before sending such transaction.\n```python\nfrom uniswap_universal_router_decoder import FunctionRecipient, RouterCodec\n\ncodec = RouterCodec()\nencoded_data = codec.encode.chain().v3_swap_exact_out(\n        FunctionRecipient.SENDER,\n        amount_out,  # in Wei\n        max_amount_in,  # in Wei\n        [\n            in_token_address,\n            pool_fee,\n            out_token_address,\n        ],\n    ).build(timestamp)  # unix timestamp after which the trx will not be valid any more\n\n# then in your transaction dict:\ntransaction[\"data\"] = encoded_data\n# you can now sign and send the transaction to the UR\n```\n\n### How to encode a call to the function PERMIT2_PERMIT\nThis function is used to give an allowance to the universal router thanks to the Permit2 contract ([`0x000000000022D473030F116dDEE9F6B43aC78BA3`](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)).\nIt is also necessary to approve the Permit2 contract using the token approve function.\nSee this [tutorial](https://hackernoon.com/python-how-to-use-permit2-with-the-uniswap-universal-router)\n```python\nfrom uniswap_universal_router_decoder import RouterCodec\n\ncodec = RouterCodec()\ndata, signable_message = codec.create_permit2_signable_message(\n    token_address,\n    amount,  # max = 2**160 - 1\n    expiration,\n    nonce,  # Permit2 nonce\n    spender,  # The UR checksum address\n    deadline,\n    1,  # chain id\n)\n\n# Then you need to sign the message:\nsigned_message = acc.sign_message(signable_message)  # where acc is your LocalAccount\n\n# And now you can encode the data:\nencoded_data = codec.encode.chain().permit2_permit(data, signed_message).build(deadline)\n\n# Then in your transaction dict:\ntransaction[\"data\"] = encoded_data\n\n# you can now sign and send the transaction to the UR\n```\nAfter that, you can swap tokens using the Uniswap universal router.\n\n### How to chain a call to PERMIT2_PERMIT and V2_SWAP_EXACT_IN in the same transaction\nDon't forget to give a token allowance to the Permit2 contract as well.\n\n```python\nfrom uniswap_universal_router_decoder import FunctionRecipient, RouterCodec\n\ncodec = RouterCodec()\n\n# Permit signature\ndata, signable_message = codec.create_permit2_signable_message(\n    token_address,\n    amount,  # max = 2**160 - 1\n    expiration,\n    nonce,  # Permit2 nonce\n    spender,  # The UR checksum address\n    deadline,\n    1,  # chain id\n)\n\n# Then you need to sign the message:\nsigned_message = acc.sign_message(signable_message)  # where acc is your LocalAccount\n\n# Permit + v2 swap encoding\npath = [token_in_address, token_out_address]\nencoded_data = (\n    codec\n        .encode\n        .chain()\n        .permit2_permit(data, signed_message)\n        .v2_swap_exact_in(FunctionRecipient.SENDER, Wei(10**18), Wei(0), path)\n        .build(deadline)\n)\n\n# Then in your transaction dict:\ntransaction[\"data\"] = encoded_data\n\n# you can now sign and send the transaction to the UR\n```\n\n### Other chainable functions\n(See integration tests for full examples) \n\n#### PAY_PORTION\nExample where a recipient is paid 1% of the USDC amount:\n```python\n.pay_portion(FunctionRecipient.CUSTOM, usdc_address, 100, recipient_address)\n\n```\n#### SWEEP\nExample where the sender gets back all remaining USDC:\n```python\n.sweep(FunctionRecipient.SENDER, usdc_address, 0)\n```\n\n#### TRANSFER\nExample where an USDC amount is sent to a recipient:\n```python\n.transfer(FunctionRecipient.CUSTOM, usdc_address, usdc_amount, recipient_address)\n```\n\n\n## Tutorials and Recipes:\nSee the [SDK Wiki](https://github.com/Elnaril/uniswap-universal-router-decoder/wiki).\n",
    "bugtrack_url": null,
    "license": "MIT License",
    "summary": "Decode & Encode transaction data sent to Uniswap Universal Router",
    "version": "1.1.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/Elnaril/uniswap-universal-router-decoder/issues",
        "Buy Me A Coffee": "https://www.buymeacoffee.com/elnaril",
        "Discussions": "https://github.com/Elnaril/uniswap-universal-router-decoder/discussions",
        "Fiverr": "https://www.fiverr.com/freelancers/elnaril",
        "Homepage": "https://github.com/Elnaril/uniswap-universal-router-decoder"
    },
    "split_keywords": [
        "blockchain",
        "ethereum",
        "uniswap",
        "universal router",
        "decoder",
        "encoder",
        "codec",
        "wrapper",
        "sdk"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7ce76c06a50b2f7c434bb879fa35057e1866572981e3146c5424d15f25506b0e",
                "md5": "4b2cefce02812699016cfa14ef5e241e",
                "sha256": "40036a11ea766884442607b9d27fee6ee0cf2760462813db644bb89bfa426865"
            },
            "downloads": -1,
            "filename": "uniswap_universal_router_decoder-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4b2cefce02812699016cfa14ef5e241e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 18603,
            "upload_time": "2024-02-07T07:08:52",
            "upload_time_iso_8601": "2024-02-07T07:08:52.210874Z",
            "url": "https://files.pythonhosted.org/packages/7c/e7/6c06a50b2f7c434bb879fa35057e1866572981e3146c5424d15f25506b0e/uniswap_universal_router_decoder-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "038f917e949f944878b1d4898d346c23ea8b4eb3112c1c9d98aea542dff6d8c2",
                "md5": "437a1d24ca9096a529b5cc76613a8ed3",
                "sha256": "68f266ffc86879d07da22aa4c4cdd9983304a87ac11307e06357891907c20bec"
            },
            "downloads": -1,
            "filename": "uniswap-universal-router-decoder-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "437a1d24ca9096a529b5cc76613a8ed3",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 25645,
            "upload_time": "2024-02-07T07:08:54",
            "upload_time_iso_8601": "2024-02-07T07:08:54.430378Z",
            "url": "https://files.pythonhosted.org/packages/03/8f/917e949f944878b1d4898d346c23ea8b4eb3112c1c9d98aea542dff6d8c2/uniswap-universal-router-decoder-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-02-07 07:08:54",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Elnaril",
    "github_project": "uniswap-universal-router-decoder",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "requirements": [],
    "tox": true,
    "lcname": "uniswap-universal-router-decoder"
}
        
Elapsed time: 0.21113s