uniswap_v2.fees
Documentation for eth_defi.uniswap_v2.fees Python module.
Uniswap v2 token price, fee and price impact calculations.
To get a price in Uniswap v2 pool in human-readable format see
estimate_sell_price()andestimate_buy_price().
Mostly lifted from Uniswap-v2-py MIT licensed by Asynctomatic.
A short example how to get started:
import os
from web3 import Web3
from eth_defi.provider.multi_provider import create_multi_provider_web3
from eth_defi.uniswap_v2.deployment import fetch_deployment
from eth_defi.uniswap_v2.fees import estimate_buy_price
from eth_defi.uniswap_v2.pair import fetch_pair_details
# Default to Ankr free JSON-RPC endpoint if one not given
# https://eth.public-rpc.com/
web3 = create_multi_provider_web3(os.environ.get("JSON_RPC_ETHEREUM", "https://eth.public-rpc.com"))
assert web3.eth.chain_id == 1, f"We are not on Ethereum mainnet, got {web3.eth.chain_id}"
uniswap_v2 = fetch_deployment(
web3=web3,
factory_address="0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
router_address="0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
init_code_hash="0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f",
)
# Uniswap v2's USDC-WETH needs to be reserved to WETH-USDC in human logic
# https://tradingstrategy.ai/trading-view/ethereum/uniswap-v2/eth-usdc
pair = fetch_pair_details(web3, "0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc", reverse_token_order=True)
print(f"Uniswap v2 pool is {pair.contract.address}, https://tradingstrategy.ai/trading-view/ethereum/uniswap-v2/eth-usdc")
print("Base token is", pair.get_base_token())
print("Quote token is", pair.get_quote_token())
raw_price = estimate_buy_price(
uniswap_v2,
base_token=pair.get_base_token().contract,
quote_token=pair.get_quote_token().contract,
quantity=1 * 10**18, # 1 WETH = 1000000000000000000 wei
)
# Convert raw USDC Solidity amount -> human USDC
human_price = pair.get_quote_token().convert_to_decimals(raw_price)
print(f"Price is {human_price} ETH/USD")
Functions
|
Estimate how much we are going to need to pay when doing buy. |
|
Estimate how much we are going to need to pay when doing buy. |
|
Estimate how many tokens we are going to receive when doing a buy. |
|
Estimate how much we receive for a certain cash amount. |
|
Estimate how much we are going to get paid when doing a sell. |
|
Estimate how much we are going to get paid when doing a sell. |
|
Estimate how much cash we receive for a certain quantity of tokens sold. |
Classes
A helper class to estimate Uniswap fees. |
Exceptions
- exception BadReserves
Bases:
Exception- __init__(*args, **kwargs)
- __new__(**kwargs)
- add_note()
Exception.add_note(note) – add a note to the exception
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- class UniswapV2FeeCalculator
Bases:
objectA helper class to estimate Uniswap fees.
- __init__(uniswap_v2)
- Parameters
uniswap_v2 (eth_defi.uniswap_v2.deployment.UniswapV2Deployment) –
- get_reserves(token_a, token_b)
Gets the reserves of token_0 and token_1 used to price trades and distribute liquidity as well as the timestamp of the last block during which an interaction occurred for the pair.
- Parameters
pair – Address of the pair.
token_a (eth_typing.evm.HexAddress) –
token_b (eth_typing.evm.HexAddress) –
- Returns
reserve_0 - Amount of token_0 in the contract.
reserve_1 - Amount of token_1 in the contract.
liquidity - Unix timestamp of the block containing the last pair interaction.
- Return type
- get_amount_out(amount_in, path, *, fee=30, slippage=0)
Get how much token we are going to receive.
- get_amount_in(amount_out, path, *, fee=30, slippage=0)
Get how much token we are going to spend.
- static get_amount_in_from_reserves(amount_out, reserve_in, reserve_out, *, fee=30)
Returns the minimum input asset amount required to buy the given output asset amount (accounting for fees) given reserves.
- Parameters
- Returns
Required amount of input asset.
- Return type
- static get_amount_out_from_reserves(amount_in, reserve_in, reserve_out, *, fee=30)
Given an input asset amount, returns the maximum output amount of the other asset (accounting for fees) given reserves.
- Parameters
- Returns
Maximum amount of output asset.
- Return type
- estimate_buy_quantity(uniswap, base_token, quote_token, quantity, *, fee=30, slippage=0)
Estimate how many tokens we are going to receive when doing a buy.
Good for doing a price impact calculations.
Calls the on-chain contract to get the current liquidity and estimates the the price based on it.
Example:
# Estimate how much ETH we will receive for 500 USDC. # In this case the pool ETH price is $1700 so this should be below ~1/4 of ETH amount_eth = estimate_buy_quantity( uniswap_v2, weth, usdc, 500 * 10**18, ) assert amount_eth / 1e18 == pytest.approx(0.28488156127668085)
- Parameters
quantity (int) – How much of the quote token we have to use
uniswap (eth_defi.uniswap_v2.deployment.UniswapV2Deployment) – Uniswap v2 deployment
base_token (web3.contract.contract.Contract) – Base token of the trading pair
quote_token (web3.contract.contract.Contract) – Quote token of the trading pair
fee (int) – Trading fee express in bps, default = 30 bps (0.3%)
slippage (float) – Slippage express in bps
- Returns
Expected base token to receive
- Return type
- estimate_buy_price(uniswap, base_token, quote_token, quantity, *, fee=30, slippage=0, intermediate_token=None)
Estimate how much we are going to need to pay when doing buy.
Calls the on-chain contract to get the current liquidity and estimates the the price based on it.
Example for Ethereum mainnet Uniswap:
import os from web3 import Web3 from eth_defi.provider.multi_provider import create_multi_provider_web3 from eth_defi.uniswap_v2.deployment import fetch_deployment from eth_defi.uniswap_v2.fees import estimate_buy_price from eth_defi.uniswap_v2.pair import fetch_pair_details # Default to Ankr free JSON-RPC endpoint if one not given # https://eth.public-rpc.com/ web3 = create_multi_provider_web3(os.environ.get("JSON_RPC_ETHEREUM", "https://eth.public-rpc.com")) assert web3.eth.chain_id == 1, f"We are not on Ethereum mainnet, got {web3.eth.chain_id}" uniswap_v2 = fetch_deployment( web3=web3, factory_address="0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f", router_address="0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", init_code_hash="0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f", ) # Uniswap v2's USDC-WETH needs to be reserved to WETH-USDC in human logic # https://tradingstrategy.ai/trading-view/ethereum/uniswap-v2/eth-usdc pair = fetch_pair_details(web3, "0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc", reverse_token_order=True) print(f"Uniswap v2 pool is {pair.contract.address}, https://tradingstrategy.ai/trading-view/ethereum/uniswap-v2/eth-usdc") print("Base token is", pair.get_base_token()) print("Quote token is", pair.get_quote_token()) raw_price = estimate_buy_price( uniswap_v2, base_token=pair.get_base_token().contract, quote_token=pair.get_quote_token().contract, quantity=1 * 10**18, # 1 WETH = 1000000000000000000 wei ) # Convert raw USDC Solidity amount -> human USDC human_price = pair.get_quote_token().convert_to_decimals(raw_price) print(f"Price is {human_price} ETH/USD")
Example for unit testing:
# Estimate how much ETH we will receive for 500 USDC. # In this case the pool ETH price is $1700 so this should be below ~1/4 of ETH amount_eth = estimate_buy_price( uniswap_v2, weth, usdc, 1 * 10**18, ) assert amount_eth / 1e18 == pytest.approx(0.28488156127668085)
- Parameters
uniswap (eth_defi.uniswap_v2.deployment.UniswapV2Deployment) – Uniswap v2 deployment
base_token (web3.contract.contract.Contract) – Base token of the trading pair
quote_token (web3.contract.contract.Contract) – Quote token of the trading pair
quantity (int) – How much of the base token we want to buy
fee (int) – Trading fee express in bps, default = 30 bps (0.3%)
slippage (float) – Slippage express in bps
intermediate_token (Optional[web3.contract.contract.Contract]) –
- Returns
Expected base token to receive
- Return type
- estimate_sell_price(uniswap, base_token, quote_token, quantity, *, fee=30, slippage=0, intermediate_token=None)
Estimate how much we are going to get paid when doing a sell.
Calls the on-chain contract to get the current liquidity and estimates the the price based on it.
Note
The price of an asset depends on how much you are selling it. More you sell, more there will be price impact.
To get a price of an asset, ask for quantity 1 of it:
# Create the trading pair and add iint(10_000 * amounts[-1] // (10_000 - slippage))nitial liquidity for price 1700 USDC/ETH deploy_trading_pair( web3, deployer, uniswap_v2, weth, usdc, 1_000 * 10**18, # 1000 ETH liquidity 1_700_000 * 10**6, # 1.7M USDC liquidity ) # Estimate the price of selling 1 ETH usdc_per_eth = estimate_sell_price( uniswap_v2, weth, usdc, 1 * 10**18, # 1 ETH ) price_as_usd = usdc_per_eth / 1e6 assert price_as_usd == pytest.approx(1693.2118677678354)
- Parameters
quantity (int) – How much of the base token we want to sell
uniswap (eth_defi.uniswap_v2.deployment.UniswapV2Deployment) – Uniswap v2 deployment
base_token (web3.contract.contract.Contract) – Base token of the trading pair
quote_token (web3.contract.contract.Contract) – Quote token of the trading pair
fee (int) – Trading fee express in bps, default = 30 bps (0.3%)
slippage (float) – Slippage express in bps
intermediate_token (Optional[web3.contract.contract.Contract]) –
- Returns
Expected quote token amount to receive
- Return type
- estimate_buy_price_decimals(uniswap, base_token_address, quote_token_address, quantity, *, fee=30, slippage=0, intermediate_token_address=None)
Estimate how much we are going to need to pay when doing buy.
Much like
estimate_buy_price()with the differences of - Tokens are passed as address instead of contract instance - We use base token quantity units instead of cash - We use decimals instead of raw token amountsExample:
# Create the trading pair and add initial liquidity deploy_trading_pair( web3, deployer, uniswap_v2, weth, usdc, 1_000 * 10**18, # 1000 ETH liquidity 1_700_000 * 10**18, # 1.7M USDC liquidity ) # Estimate the price of buying 1 ETH usdc_per_eth = estimate_buy_price_decimals( uniswap_v2, weth.address, usdc.address, Decimal(1.0), ) assert usdc_per_eth == pytest.approx(Decimal(1706.82216820632059904))
- Parameters
quantity (decimal.Decimal) – How much of the base token we want to buy
uniswap (eth_defi.uniswap_v2.deployment.UniswapV2Deployment) – Uniswap v2 deployment
base_token – Base token of the trading pair
quote_token – Quote token of the trading pair
fee (int) – Trading fee express in bps, default = 30 bps (0.3%)
slippage (float) – Slippage express in bps
base_token_address (eth_typing.evm.HexAddress) –
quote_token_address (eth_typing.evm.HexAddress) –
intermediate_token_address (Optional[eth_typing.evm.HexAddress]) –
- Returns
Expected quote token amount to receive
- Raises
TokenDetailError – If we have an issue with ERC-20 contracts
- Return type
- estimate_sell_price_decimals(uniswap, base_token_address, quote_token_address, quantity, *, fee=30, slippage=0, intermediate_token_address=None)
Estimate how much we are going to get paid when doing a sell.
Much like
estimate_sell_price()but in/out is expressed as python Decimal units. Furthermore, no ERC-20 token contract needed ABI, but it is loaded by the function.- Parameters
quantity (decimal.Decimal) – How much of the base token we want to sell, in token units (will be decimal autoconverted).
uniswap (eth_defi.uniswap_v2.deployment.UniswapV2Deployment) – Uniswap v2 deployment
base_token – Base token of the trading pair
quote_token – Quote token of the trading pair
fee (int) – Trading fee express in bps, default = 30 bps (0.3%)
slippage (float) – Slippage express in bps
base_token_address (eth_typing.evm.HexAddress) –
quote_token_address (eth_typing.evm.HexAddress) –
intermediate_token_address (Optional[eth_typing.evm.HexAddress]) –
- Returns
Expected quote token amount to receive in quota tokens (decimal converted).
- Raises
TokenDetailError – If we have an issue with ERC-20 contracts
- Return type
- estimate_buy_received_amount_raw(uniswap, base_token_address, quote_token_address, quantity_raw, *, fee=30, slippage=0, intermediate_token_address=None)
Estimate how much we receive for a certain cash amount.
Example:
# Create the trading pair and add initial liquidity deploy_trading_pair( web3, deployer, uniswap_v2, weth, usdc, 1_000 * 10**18, # 1000 ETH liquidity 1_700_000 * 10**18, # 1.7M USDC liquidity ) # Estimate the price of buying 1650 USDC worth of ETH eth_received = estimate_buy_received_amount_raw( uniswap_v2, weth.address, usdc.address, 1650 * 10**18, ) assert eth_received / (10**18) == pytest.approx(0.9667409780905836) # Calculate price of ETH as $ for our purchase price = (1650 * 10**18) / eth_received assert price == pytest.approx(Decimal(1706.7653460381143))
- Parameters
quantity – How much of the base token we want to buy
uniswap (eth_defi.uniswap_v2.deployment.UniswapV2Deployment) – Uniswap v2 deployment
base_token – Base token of the trading pair
quote_token – Quote token of the trading pair
fee (int) – Trading fee express in bps, default = 30 bps (0.3%)
slippage (float) – Slippage express in bps
base_token_address (eth_typing.evm.HexAddress) –
quote_token_address (eth_typing.evm.HexAddress) –
quantity_raw (decimal.Decimal) –
intermediate_token_address (Optional[eth_typing.evm.HexAddress]) –
- Returns
Expected quote token amount to receive
- Raises
TokenDetailError – If we have an issue with ERC-20 contracts
- Return type
- estimate_sell_received_amount_raw(uniswap, base_token_address, quote_token_address, quantity_raw, *, fee=30, slippage=0, intermediate_token_address=None)
Estimate how much cash we receive for a certain quantity of tokens sold.
Example:
deploy_trading_pair( web3, deployer, uniswap_v2, weth, usdc, 1_000 * 10**18, # 1000 ETH liquidity 1_700_000 * 10**18, # 1.7M USDC liquidity ) # Sell 50 ETH usdc_received = estimate_sell_received_amount_raw( uniswap_v2, weth.address, usdc.address, 50 * 10**18, ) usdc_received_decimals = usdc_received / 10**18 assert usdc_received_decimals == pytest.approx(80721.05538886508) # Calculate price of ETH as $ for our purchase price = usdc_received / (50 * 10**18) assert price == pytest.approx(Decimal(1614.4211077773016))
- Parameters
quantity – How much of the base token we want to buy
uniswap (eth_defi.uniswap_v2.deployment.UniswapV2Deployment) – Uniswap v2 deployment
base_token – Base token of the trading pair
quote_token – Quote token of the trading pair
fee (int) – Trading fee express in bps, default = 30 bps (0.3%)
slippage (float) – Slippage express in bps
base_token_address (eth_typing.evm.HexAddress) –
quote_token_address (eth_typing.evm.HexAddress) –
quantity_raw (decimal.Decimal) –
intermediate_token_address (Optional[eth_typing.evm.HexAddress]) –
- Returns
Expected quote token amount to receive
- Raises
TokenDetailError – If we have an issue with ERC-20 contracts
- Return type