Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fees #143

Merged
merged 6 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions eth_defi/trade.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class TradeResult:

def get_effective_gas_price_gwei(self) -> Decimal:
return Decimal(self.effective_gas_price) / Decimal(10**9)

def get_cost_of_gas(self) -> Decimal:
"""This will return the gas cost of the transaction in blockchain's native currency e.g. in ETH on Ethereum."""
return Decimal(self.gas_used) * Decimal(self.effective_gas_price) / Decimal(10**18)


@dataclass
Expand Down Expand Up @@ -65,6 +69,11 @@ class TradeSuccess(TradeResult):
#: Needed to calculate reverse token order.
token1: TokenDetails | None

#: How much was the LP fee
#:
#: Note: this is the raw amount in terms of the amount in token
lp_fee_paid: float | None

def __post_init__(self):
if self.price is not None:
assert isinstance(self.price, Decimal)
Expand Down
7 changes: 6 additions & 1 deletion eth_defi/uniswap_v2/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def analyse_trade_by_hash(web3: Web3, uniswap: UniswapV2Deployment, tx_hash: str
return analyse_trade_by_receipt(web3, uniswap, tx, tx_hash, tx_receipt)


def analyse_trade_by_receipt(web3: Web3, uniswap: UniswapV2Deployment, tx: dict, tx_hash: str, tx_receipt: dict) -> Union[TradeSuccess, TradeFail]:
def analyse_trade_by_receipt(web3: Web3, uniswap: UniswapV2Deployment, tx: dict, tx_hash: str, tx_receipt: dict, pair_fee: float = None) -> Union[TradeSuccess, TradeFail]:
"""Analyse details of a Uniswap trade based on already received receipt.

See also :py:func:`analyse_trade_by_hash`.
Expand Down Expand Up @@ -93,6 +93,8 @@ def analyse_trade_by_receipt(web3: Web3, uniswap: UniswapV2Deployment, tx: dict,
Transaction hash: needed for the call for the revert reason)
:param tx_receipt:
Transaction receipt to analyse
:param pair_fee:
The lp fee for this pair.
:return:
:py:class:`TradeSuccess` or :py:class:`TradeFail` instance
"""
Expand Down Expand Up @@ -188,6 +190,8 @@ def analyse_trade_by_receipt(web3: Web3, uniswap: UniswapV2Deployment, tx: dict,

price = amount_out_cleaned / amount_in_cleaned

lp_fee_paid = float(amount_in * pair_fee / in_token_details.decimals) if pair_fee else None

return TradeSuccess(
gas_used,
effective_gas_price,
Expand All @@ -200,6 +204,7 @@ def analyse_trade_by_receipt(web3: Web3, uniswap: UniswapV2Deployment, tx: dict,
amount_out_decimals=out_token_details.decimals,
token0=None,
token1=None,
lp_fee_paid=lp_fee_paid,
)


Expand Down
4 changes: 4 additions & 0 deletions eth_defi/uniswap_v3/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ def analyse_trade_by_receipt(
out_token_details = fetch_erc20_details(web3, path[-1])
price = pool.convert_price_to_human(tick) # Return price of token0/token1

amount_in = amount0 if amount0 > 0 else amount1
lp_fee_paid = float(amount_in * pool.fee / in_token_details.decimals)

return TradeSuccess(
gas_used,
effective_gas_price,
Expand All @@ -148,4 +151,5 @@ def analyse_trade_by_receipt(
out_token_details.decimals,
token0=pool.token0,
token1=pool.token1,
lp_fee_paid=lp_fee_paid,
)
5 changes: 3 additions & 2 deletions tests/uniswap_v2/test_uniswap_v2_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def test_analyse_trade_failed(eth_tester: EthereumTester, web3: Web3, deployer:
eth_tester.enable_auto_mine_transactions()


def test_analyse_by_recept(web3: Web3, deployer: str, user_1, uniswap_v2: UniswapV2Deployment, weth: Contract, usdc: Contract):
def test_analyse_by_receipt(web3: Web3, deployer: str, user_1, uniswap_v2: UniswapV2Deployment, weth: Contract, usdc: Contract):
"""Aanlyse a Uniswap v2 trade by receipt."""

# Create the trading pair and add initial liquidity
Expand Down Expand Up @@ -285,9 +285,10 @@ def test_analyse_by_recept(web3: Web3, deployer: str, user_1, uniswap_v2: Uniswa
receipt = web3.eth.get_transaction_receipt(tx_hash)

# user_1 has less than 500 USDC left to loses in the LP fees
analysis = analyse_trade_by_receipt(web3, uniswap_v2, tx, tx_hash, receipt)
analysis = analyse_trade_by_receipt(web3, uniswap_v2, tx, tx_hash, receipt, pair_fee=0.003)
assert isinstance(analysis, TradeSuccess)
assert analysis.price == pytest.approx(Decimal("1744.899124998896692270848706"))
assert analysis.get_effective_gas_price_gwei() == 1
assert analysis.amount_out_decimals == 6
assert analysis.amount_in_decimals == 18
assert analysis.lp_fee_paid == pytest.approx(47480260212780.15)
2 changes: 2 additions & 0 deletions tests/uniswap_v3/test_uniswap_v3_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ def test_analyse_by_receipt(
assert analysis.get_effective_gas_price_gwei() == 1
assert analysis.amount_out_decimals == 18
assert analysis.amount_in_decimals == 6
assert analysis.lp_fee_paid == pytest.approx(5000.0)

all_weth_amount = weth.functions.balanceOf(user_1).call()
weth.functions.approve(router.address, all_weth_amount).transact({"from": user_1})
Expand Down Expand Up @@ -194,3 +195,4 @@ def test_analyse_by_receipt(
assert analysis.get_effective_gas_price_gwei() == 1
assert analysis.amount_out_decimals == 6
assert analysis.amount_in_decimals == 18
assert analysis.lp_fee_paid == pytest.approx(977445247963.0948)