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

DRAFT: Add websocket usage #582

Draft
wants to merge 16 commits into
base: add_sei
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,5 @@ logs/*
missing_tokens_df.csv
tokens_and_fee_df.csv
fastlane_bot/tests/nbtest/*

.python-version
1 change: 1 addition & 0 deletions fastlane_bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
from typing import Generator, List, Dict, Tuple, Any, Callable
from typing import Optional

import fastlane_bot
from fastlane_bot.config import Config
from fastlane_bot.helpers import (
TxRouteHandler,
Expand Down
6 changes: 6 additions & 0 deletions fastlane_bot/config/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ class _ConfigNetworkMainnet(ConfigNetwork):
RPC_ENDPOINT = "https://eth-mainnet.alchemyapi.io/v2/"
WEB3_ALCHEMY_PROJECT_ID = os.environ.get("WEB3_ALCHEMY_PROJECT_ID")

WEBSOCKET_URL = f"wss://eth-mainnet.g.alchemy.com/v2/{WEB3_ALCHEMY_PROJECT_ID}"
MULTICALL_CONTRACT_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11"
# NATIVE_GAS_TOKEN_KEY = "ETH-EEeE"
# WRAPPED_GAS_TOKEN_KEY = "WETH-6Cc2"
Expand Down Expand Up @@ -622,6 +623,7 @@ class _ConfigNetworkBase(ConfigNetwork):
RPC_ENDPOINT = "https://base-mainnet.g.alchemy.com/v2/"
WEB3_ALCHEMY_PROJECT_ID = os.environ.get("WEB3_ALCHEMY_BASE")

WEBSOCKET_URL = f"wss://base-mainnet.g.alchemy.com/v2/{WEB3_ALCHEMY_PROJECT_ID}"
GAS_ORACLE_ADDRESS = "0x420000000000000000000000000000000000000F" # source: https://docs.optimism.io/builders/tools/build/oracles#gas-oracle
network_df = get_multichain_addresses(network="coinbase_base")
FASTLANE_CONTRACT_ADDRESS = "0x2AE2404cD44c830d278f51f053a08F54b3756e1c"
Expand Down Expand Up @@ -665,6 +667,7 @@ class _ConfigNetworkFantom(ConfigNetwork):
RPC_ENDPOINT = "https://fantom.blockpi.network/v1/rpc/"
WEB3_ALCHEMY_PROJECT_ID = os.environ.get("WEB3_FANTOM")

WEBSOCKET_URL = f"wss://fantom.blockpi.network/v1/ws/{WEB3_ALCHEMY_PROJECT_ID}"
network_df = get_multichain_addresses(network=NETWORK_NAME)
FASTLANE_CONTRACT_ADDRESS = "0xFe19CbA3aB1A189B7FC17cAa798Df64Ad2b54d4D"
MULTICALL_CONTRACT_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11"
Expand Down Expand Up @@ -708,6 +711,7 @@ class _ConfigNetworkMantle(ConfigNetwork):
RPC_ENDPOINT = "https://lb.drpc.org/ogrpc?network=mantle&dkey="
WEB3_ALCHEMY_PROJECT_ID = os.environ.get("WEB3_MANTLE")

WEBSOCKET_URL = f"wss://lb.drpc.org/ogws?network=mantle&dkey={WEB3_ALCHEMY_PROJECT_ID}"
GAS_ORACLE_ADDRESS = "0x420000000000000000000000000000000000000F"
network_df = get_multichain_addresses(network=NETWORK_NAME)
FASTLANE_CONTRACT_ADDRESS = "0xC7Dd38e64822108446872c5C2105308058c5C55C"
Expand Down Expand Up @@ -792,6 +796,8 @@ class _ConfigNetworkSei(ConfigNetwork):
RPC_ENDPOINT = "https://evm-rpc.arctic-1.seinetwork.io/" # TODO currently Sei devnet
WEB3_ALCHEMY_PROJECT_ID = os.environ.get("WEB3_SEI")


WEBSOCKET_URL = "wss://evm-ws.arctic-1.seinetwork.io"
network_df = get_multichain_addresses(network=NETWORK_NAME)
FASTLANE_CONTRACT_ADDRESS = "0xC7Dd38e64822108446872c5C2105308058c5C55C" #TODO - UPDATE WITH Mainnet
MULTICALL_CONTRACT_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11"
Expand Down
3 changes: 1 addition & 2 deletions fastlane_bot/events/async_backdate_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ def async_handle_initial_iteration(
last_block: int,
mgr: Any,
start_block: int,
current_block: int,
):
if last_block == 0:
non_multicall_rows_to_update = mgr.get_rows_to_update(start_block)
Expand All @@ -105,7 +104,7 @@ def async_handle_initial_iteration(
)

mgr.cfg.logger.info(
f"Backdating {len(other_pool_rows)} pools from {start_block} to {current_block}"
f"Backdating {len(other_pool_rows)} pools from {start_block}"
)
start_time = time.time()
async_backdate_from_contracts(
Expand Down
9 changes: 5 additions & 4 deletions fastlane_bot/events/async_event_update_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from fastlane_bot.events.async_utils import get_contract_chunks
from fastlane_bot.events.utils import update_pools_from_events
from fastlane_bot.events.pools.utils import get_pool_cid
from .interfaces.event import Event

nest_asyncio.apply()

Expand Down Expand Up @@ -89,15 +90,15 @@ async def _get_missing_tkns(mgr: Any, c: List[Dict[str, Any]]) -> pd.DataFrame:
return pd.concat(vals)


async def _get_token_and_fee(mgr: Any, exchange_name: str, ex: Any, address: str, contract: AsyncContract, event: Any):
async def _get_token_and_fee(mgr: Any, exchange_name: str, ex: Any, address: str, contract: AsyncContract, event: Event):
"""
This function uses the exchange object to get the tokens and fee for a given pool.

Args:
ex(Any): The exchange object
address(str): The pool address
contract(AsyncContract): The contract object
event(Any): The event object
event(Event): The event object

Returns:
The tokens and fee info for the pool
Expand All @@ -119,7 +120,7 @@ async def _get_token_and_fee(mgr: Any, exchange_name: str, ex: Any, address: str
elif tkn1 == mgr.cfg.BNT_ADDRESS:
tkn0 = connector_token

strategy_id = 0 if not ex.is_carbon_v1_fork else str(event["args"]["id"])
strategy_id = 0 if not ex.is_carbon_v1_fork else str(event.args["id"])
pool_info = {
"exchange_name": exchange_name,
"address": address,
Expand Down Expand Up @@ -319,7 +320,7 @@ def _get_pool_contracts(mgr: Any) -> List[Dict[str, Any]]:
exchange_name = mgr.exchange_name_from_event(event)
ex = mgr.exchanges[exchange_name]
abi = ex.get_abi()
address = event["address"]
address = event.address
contracts.append(
{
"exchange_name": exchange_name,
Expand Down
8 changes: 6 additions & 2 deletions fastlane_bot/events/exchanges/balancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
from web3.contract import Contract

from fastlane_bot.data.abi import BALANCER_VAULT_ABI, BALANCER_POOL_ABI_V1
from fastlane_bot.events.exchanges.base import Exchange
from fastlane_bot.events.pools.base import Pool
from ..exchanges.base import Exchange
from ..pools.base import Pool
from ..interfaces.subscription import Subscription


@dataclass
Expand Down Expand Up @@ -47,6 +48,9 @@ def get_pool_abi(self):
def get_events(self, contract: Contract) -> List[Type[Contract]]:
return [contract.events.AuthorizerChanged]

def get_subscriptions(self, contract: Contract) -> List[Subscription]:
return []

async def get_fee(self, pool_id: str, contract: Contract) -> Tuple[str, float]:
pool = self.get_pool(pool_id)
if pool:
Expand Down
20 changes: 14 additions & 6 deletions fastlane_bot/events/exchanges/bancor_pol.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
from web3.contract import Contract

from fastlane_bot.data.abi import BANCOR_POL_ABI
from fastlane_bot.events.exchanges.base import Exchange
from fastlane_bot.events.pools.base import Pool
from fastlane_bot import Config
from ..exchanges.base import Exchange
from ..pools.base import Pool
from ..interfaces.event import Event
from ..interfaces.subscription import Subscription


@dataclass
Expand All @@ -46,14 +48,20 @@ def get_factory_abi(self):
def get_events(self, contract: Contract) -> List[Type[Contract]]:
return [contract.events.TokenTraded, contract.events.TradingEnabled]

def get_subscriptions(self, contract: Contract) -> List[Subscription]:
return [
Subscription(contract.events.TokenTraded),
Subscription(contract.events.TradingEnabled),
]

async def get_fee(self, address: str, contract: Contract) -> Tuple[str, float]:
return "0.000", 0.000

async def get_tkn0(self, address: str, contract: Contract, event: Any) -> str:
return event["args"]["token"]
async def get_tkn0(self, address: str, contract: Contract, event: Event) -> str:
return event.args["token"]

async def get_tkn1(self, address: str, contract: Contract, event: Any) -> str:
return self.ETH_ADDRESS if event["args"]["token"] not in self.ETH_ADDRESS else self.BNT_ADDRESS
async def get_tkn1(self, address: str, contract: Contract, event: Event) -> str:
return self.ETH_ADDRESS if event.args["token"] not in self.ETH_ADDRESS else self.BNT_ADDRESS

def save_strategy(
self,
Expand Down
22 changes: 14 additions & 8 deletions fastlane_bot/events/exchanges/bancor_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
from dataclasses import dataclass
from typing import List, Type, Tuple, Any

from web3 import AsyncWeb3
from web3.contract import Contract, AsyncContract

from fastlane_bot.data.abi import BANCOR_V2_CONVERTER_ABI
from fastlane_bot.events.exchanges.base import Exchange
from fastlane_bot.events.pools.base import Pool
from ..exchanges.base import Exchange
from ..pools.base import Pool
from ..interfaces.event import Event
from ..interfaces.subscription import Subscription


@dataclass
Expand All @@ -44,6 +47,9 @@ def get_factory_abi(self):
def get_events(self, contract: Contract) -> List[Type[Contract]]:
return [contract.events.TokenRateUpdate]

def get_subscriptions(self, contract: Contract) -> List[Subscription]:
return [Subscription(contract.events.TokenRateUpdate)]

# def async convert_address(self, address: str, contract: Contract) -> str:
# return

Expand All @@ -59,15 +65,15 @@ async def get_fee(self, address: str, contract: AsyncContract) -> Tuple[str, flo
fee_float = float(fee) / 1e6
return fee, fee_float

async def get_tkn0(self, address: str, contract: Contract, event: Any) -> str:
async def get_tkn0(self, address: str, contract: Contract, event: Event) -> str:
if event:
return event["args"]["_token1"]
return await contract.caller.reserveTokens()[0]
return event.args["_token1"]
return await contract.functions.reserveTokens()[0]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be caller, not functions.


async def get_tkn1(self, address: str, contract: Contract, event: Any) -> str:
async def get_tkn1(self, address: str, contract: Contract, event: Event) -> str:
if event:
return event["args"]["_token2"]
return await contract.caller.reserveTokens()[1]
return event.args["_token2"]
return await contract.functions.reserveTokens()[1]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be caller, not functions.


async def get_anchor(self, contract: Contract) -> str:
return await contract.caller.anchor()
22 changes: 15 additions & 7 deletions fastlane_bot/events/exchanges/bancor_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
from web3.contract import Contract

from fastlane_bot.data.abi import BANCOR_V3_POOL_COLLECTION_ABI
from fastlane_bot.events.exchanges.base import Exchange
from fastlane_bot.events.pools.base import Pool
from ..exchanges.base import Exchange
from ..pools.base import Pool
from ..interfaces.event import Event
from ..interfaces.subscription import Subscription


LIQUIDITY_UPDATED_TOPIC = "0x6e96dc5343d067ec486a9920e0304c3610ed05c65e45cc029d9b9fe7ecfa7620"


@dataclass
Expand All @@ -44,15 +49,18 @@ def get_factory_abi(self):
def get_events(self, contract: Contract) -> List[Type[Contract]]:
return [contract.events.TradingLiquidityUpdated]

def get_subscriptions(self, contract: Contract) -> List[Subscription]:
return [Subscription(contract.events.TradingLiquidityUpdated, LIQUIDITY_UPDATED_TOPIC)]

async def get_fee(self, address: str, contract: Contract) -> Tuple[str, float]:
return "0.000", 0.000

async def get_tkn0(self, address: str, contract: Contract, event: Any) -> str:
async def get_tkn0(self, address: str, contract: Contract, event: Event) -> str:
return self.BNT_ADDRESS

async def get_tkn1(self, address: str, contract: Contract, event: Any) -> str:
async def get_tkn1(self, address: str, contract: Contract, event: Event) -> str:
return (
event["args"]["pool"]
if event["args"]["pool"] != self.BNT_ADDRESS
else event["args"]["tkn_address"]
event.args["pool"]
if event.args["pool"] != self.BNT_ADDRESS
else event.args["tkn_address"]
)
7 changes: 6 additions & 1 deletion fastlane_bot/events/exchanges/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from web3.contract import Contract, AsyncContract

from fastlane_bot.config.constants import CARBON_V1_NAME
from fastlane_bot.events.pools.base import Pool
from ..pools.base import Pool
from ..interfaces.subscription import Subscription


@dataclass
Expand Down Expand Up @@ -96,6 +97,10 @@ def get_events(self, contract: Contract) -> List[Type[Contract]]:
"""
pass

@abstractmethod
def get_subscriptions(self, contract: Contract) -> List[Subscription]:
...

@staticmethod
@abstractmethod
async def get_fee(address: str, contract: AsyncContract) -> float:
Expand Down
31 changes: 24 additions & 7 deletions fastlane_bot/events/exchanges/carbon_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@
from web3.contract import Contract

from fastlane_bot.data.abi import CARBON_CONTROLLER_ABI
from fastlane_bot.events.exchanges.base import Exchange
from fastlane_bot.events.pools.base import Pool
from fastlane_bot.events.pools.utils import get_pool_cid
from ..exchanges.base import Exchange
from ..pools.base import Pool
from ..interfaces.event import Event
from ..interfaces.subscription import Subscription
from ..pools.utils import get_pool_cid


STRATEGY_CREATED_TOPIC = "0xff24554f8ccfe540435cfc8854831f8dcf1cf2068708cfaf46e8b52a4ccc4c8d"
STRATEGY_UPDATED_TOPIC = "0x720da23a5c920b1d8827ec83c4d3c4d90d9419eadb0036b88cb4c2ffa91aef7d"
STRATEGY_DELETED_TOPIC = "0x4d5b6e0627ea711d8e9312b6ba56f50e0b51d41816fd6fd38643495ac81d38b6"


@dataclass
Expand Down Expand Up @@ -73,6 +80,16 @@ def get_events(self, contract: Contract) -> List[Type[Contract]]:
contract.events.PairCreated,
] if self.exchange_initialized else []

def get_subscriptions(self, contract: Contract) -> List[Subscription]:
return [
Subscription(contract.events.StrategyCreated, STRATEGY_CREATED_TOPIC),
Subscription(contract.events.StrategyUpdated, STRATEGY_UPDATED_TOPIC),
Subscription(contract.events.StrategyDeleted, STRATEGY_DELETED_TOPIC),
Subscription(contract.events.PairTradingFeePPMUpdated),
Subscription(contract.events.TradingFeePPMUpdated),
Subscription(contract.events.PairCreated),
]

async def get_fee(
self, address: str, contract: Contract
) -> Tuple[str, float]:
Expand All @@ -94,7 +111,7 @@ async def get_fee(
fee = await contract.tradingFeePPM()
return f"{fee}", fee / 1e6

async def get_tkn0(self, address: str, contract: Contract, event: Any) -> str:
async def get_tkn0(self, address: str, contract: Contract, event: Event) -> str:
"""
Get the token0 address from the contract or event.

Expand All @@ -116,9 +133,9 @@ async def get_tkn0(self, address: str, contract: Contract, event: Any) -> str:
if event is None:
return await contract.caller.token0()
else:
return event["args"]["token0"]
return event.args["token0"]

async def get_tkn1(self, address: str, contract: Contract, event: Any) -> str:
async def get_tkn1(self, address: str, contract: Contract, event: Event) -> str:
"""
Get the token1 address from the contract or event.

Expand All @@ -140,7 +157,7 @@ async def get_tkn1(self, address: str, contract: Contract, event: Any) -> str:
if event is None:
return await contract.caller.token1()
else:
return event["args"]["token1"]
return event.args["token1"]

def delete_strategy(self, id: str):
"""
Expand Down
9 changes: 7 additions & 2 deletions fastlane_bot/events/exchanges/solidly_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
from fastlane_bot.data.abi import SOLIDLY_V2_POOL_ABI, VELOCIMETER_V2_FACTORY_ABI, SOLIDLY_V2_FACTORY_ABI, \
SCALE_V2_FACTORY_ABI, CLEOPATRA_V2_FACTORY_ABI, LYNEX_V2_FACTORY_ABI, NILE_V2_FACTORY_ABI, \
XFAI_V0_FACTORY_ABI, XFAI_V0_CORE_ABI, XFAI_V0_POOL_ABI
from fastlane_bot.events.exchanges.base import Exchange
from fastlane_bot.events.pools.base import Pool
from ..exchanges.base import Exchange
from ..pools.base import Pool
from ..interfaces.subscription import Subscription


async def _get_fee_1(address: str, contract: Contract, factory_contract: Contract) -> int:
return await factory_contract.caller.getFee(address)
Expand Down Expand Up @@ -104,6 +106,9 @@ def get_factory_abi(self):
def get_events(self, contract: Contract) -> List[Type[Contract]]:
return [contract.events.Sync] if self.exchange_initialized else []

def get_subscriptions(self, contract: Contract) -> List[Subscription]:
return [Subscription(contract.events.Sync)]

async def get_fee(self, address: str, contract: AsyncContract) -> Tuple[str, float]:
exchange_info = EXCHANGE_INFO[self.exchange_name]
fee = await exchange_info["get_fee"](address, contract, self.factory_contract)
Expand Down
8 changes: 6 additions & 2 deletions fastlane_bot/events/exchanges/uniswap_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
from web3.contract import Contract, AsyncContract

from fastlane_bot.data.abi import UNISWAP_V2_POOL_ABI, UNISWAP_V2_FACTORY_ABI
from fastlane_bot.events.exchanges.base import Exchange
from fastlane_bot.events.pools.base import Pool
from ..exchanges.base import Exchange
from ..pools.base import Pool
from ..interfaces.subscription import Subscription


@dataclass
Expand Down Expand Up @@ -49,6 +50,9 @@ def get_abi(self):
def get_events(self, contract: Contract) -> List[Type[Contract]]:
return [contract.events.Sync] if self.exchange_initialized else []

def get_subscriptions(self, contract: Contract) -> List[Subscription]:
return [Subscription(contract.events.Sync)]

async def get_fee(self, address: str, contract: AsyncContract) -> Tuple[str, float]:
return self.fee, self.fee_float

Expand Down
Loading
Loading