Source code for nqs_sdk.bindings.protocols.uniswap_v3.uniswap_v3_arbitrager
from typing import List, Optional, Tuple
from nqs_sdk import MetricName, Metrics, RefSharedState, SealedParameters, SimulationClock, TxRequest
from nqs_sdk.bindings.protocols.uniswap_v3.uniswap_v3_pool import UniswapV3Pool
from nqs_sdk.bindings.protocols.uniswap_v3.uniswap_v3_transactions import SwapTransaction
from nqs_sdk.interfaces.observable_consumer import ObservableConsumer
from nqs_sdk.interfaces.tx_generator import TxGenerator
[docs]
class UniswapV3Arbitrager(TxGenerator, ObservableConsumer):
[docs]
def __init__(self, pools: list[UniswapV3Pool]) -> None:
self.pools: list[UniswapV3Pool] = pools
[docs]
def id(self) -> str:
return "uniswap_v3_arbitrager"
[docs]
def initialize(self, parameters: SealedParameters) -> None:
return
[docs]
def consume(self, parameters: SealedParameters, clock: SimulationClock) -> Tuple[List[MetricName], Optional[int]]:
metrics_names = []
for pool in self.pools:
current_spot_obs = f"{pool.name}.dex_spot"
market_spot_obs = f'common.market_spot:{{pair="{pool.token0}/{pool.token1}"}}'
liquidity_obs = f"{pool.name}.liquidity"
metrics_names.append(parameters.str_to_metric(current_spot_obs))
metrics_names.append(parameters.str_to_metric(market_spot_obs))
metrics_names.append(parameters.str_to_metric(liquidity_obs))
return metrics_names, None
[docs]
def next(
self,
clock: SimulationClock,
state: RefSharedState,
metrics: Metrics,
) -> Tuple[List[TxRequest], Optional[int]]:
txns: list[TxRequest] = []
for pool in self.pools:
pool_fee = pool.fee_tier
parameters = state.get_parameters()
current_spot_metric = parameters.str_to_metric(f"{pool.name}.dex_spot")
market_spot_metric = parameters.str_to_metric(f'common.market_spot:{{pair="{pool.token0}/{pool.token1}"}}')
total_liquidity = parameters.str_to_metric(f"{pool.name}.liquidity")
current_spot = metrics.get(current_spot_metric)
market_spot = metrics.get(market_spot_metric)
liquidity = metrics.get(total_liquidity)
if current_spot is None or market_spot is None or liquidity is None:
continue
swap_tx = None
if (current_spot / market_spot > (1.0 + float(pool_fee))) and liquidity > 0:
swap_tx = SwapTransaction(
amount=liquidity,
zero_for_one=True,
pool=pool,
price_limit=market_spot,
)
elif (current_spot / market_spot < (1.0 - float(pool_fee))) and liquidity > 0:
swap_tx = SwapTransaction(
amount=liquidity,
zero_for_one=False,
pool=pool,
price_limit=market_spot,
)
if swap_tx is not None:
# Order 0.0 for user transactions, 1.0 for historical or random, and 2.0 for arbitrage orders
tx = swap_tx.to_tx_request(
protocol=pool.name, source="Arb", sender="0xABA8888888888888888888888888888888888888", order=2.0
)
txns.append(tx)
return txns, None