From 2370e4ba92136357428496f5538afb0484ec1ee7 Mon Sep 17 00:00:00 2001 From: carlomazzaferro Date: Wed, 24 Nov 2021 09:34:09 +0100 Subject: [PATCH] async based sqlachemy --- .gitignore | 1 + alembic/env.py | 31 +++++--- cli.py | 16 +--- listener.py | 9 +-- mev_inspect/block.py | 28 +++---- mev_inspect/crud/arbitrages.py | 26 +++--- mev_inspect/crud/blocks.py | 14 ++-- mev_inspect/crud/generic.py | 21 +++++ mev_inspect/crud/liquidations.py | 28 ++----- mev_inspect/crud/miner_payments.py | 28 ++----- mev_inspect/crud/swaps.py | 25 ++---- mev_inspect/crud/traces.py | 25 +++--- mev_inspect/crud/transfers.py | 27 ++----- mev_inspect/db.py | 16 ++-- mev_inspect/inspect_block.py | 64 ++++++--------- mev_inspect/inspector.py | 44 ++++------ poetry.lock | 124 ++++++++++++++++++++--------- pyproject.toml | 2 + 18 files changed, 252 insertions(+), 277 deletions(-) create mode 100644 mev_inspect/crud/generic.py diff --git a/.gitignore b/.gitignore index 83df4b6..775604b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ cache # env .envrc +/out/ diff --git a/alembic/env.py b/alembic/env.py index 7e5e6cd..4aec38c 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -1,7 +1,9 @@ +import asyncio from logging.config import fileConfig from sqlalchemy import engine_from_config from sqlalchemy import pool +from sqlalchemy.ext.asyncio import AsyncEngine from alembic import context @@ -52,27 +54,34 @@ def run_migrations_offline(): context.run_migrations() -def run_migrations_online(): +def do_run_migrations(connection): + context.configure(connection=connection, target_metadata=target_metadata) + + with context.begin_transaction(): + context.run_migrations() + + +async def run_migrations_online(): """Run migrations in 'online' mode. In this scenario we need to create an Engine and associate a connection with the context. """ - connectable = engine_from_config( - config.get_section(config.config_ini_section), - prefix="sqlalchemy.", - poolclass=pool.NullPool, + connectable = AsyncEngine( + engine_from_config( + config.get_section(config.config_ini_section), + prefix="sqlalchemy.", + poolclass=pool.NullPool, + future=True, + ) ) - with connectable.connect() as connection: - context.configure(connection=connection, target_metadata=target_metadata) - - with context.begin_transaction(): - context.run_migrations() + async with connectable.connect() as connection: + await connection.run_sync(do_run_migrations) if context.is_offline_mode(): run_migrations_offline() else: - run_migrations_online() + asyncio.run(run_migrations_online()) diff --git a/cli.py b/cli.py index 12d62c7..0f0376b 100644 --- a/cli.py +++ b/cli.py @@ -5,7 +5,6 @@ import sys import click from mev_inspect.concurrency import coro -from mev_inspect.db import get_inspect_session, get_trace_session from mev_inspect.inspector import MEVInspector RPC_URL_ENV = "RPC_URL" @@ -23,10 +22,7 @@ def cli(): @click.option("--rpc", default=lambda: os.environ.get(RPC_URL_ENV, "")) @coro async def inspect_block_command(block_number: int, rpc: str): - inspect_db_session = get_inspect_session() - trace_db_session = get_trace_session() - - inspector = MEVInspector(rpc, inspect_db_session, trace_db_session) + inspector = MEVInspector(rpc) await inspector.inspect_single_block(block=block_number) @@ -35,10 +31,7 @@ async def inspect_block_command(block_number: int, rpc: str): @click.option("--rpc", default=lambda: os.environ.get(RPC_URL_ENV, "")) @coro async def fetch_block_command(block_number: int, rpc: str): - inspect_db_session = get_inspect_session() - trace_db_session = get_trace_session() - - inspector = MEVInspector(rpc, inspect_db_session, trace_db_session) + inspector = MEVInspector(rpc) block = await inspector.create_from_block(block_number=block_number) print(block.json()) @@ -64,13 +57,8 @@ async def inspect_many_blocks_command( max_concurrency: int, request_timeout: int, ): - inspect_db_session = get_inspect_session() - trace_db_session = get_trace_session() - inspector = MEVInspector( rpc, - inspect_db_session, - trace_db_session, max_concurrency=max_concurrency, request_timeout=request_timeout, ) diff --git a/listener.py b/listener.py index 352ab1a..bfa02d3 100644 --- a/listener.py +++ b/listener.py @@ -10,12 +10,10 @@ from mev_inspect.crud.latest_block_update import ( find_latest_block_update, update_latest_block, ) -from mev_inspect.db import get_inspect_session, get_trace_session from mev_inspect.inspector import MEVInspector from mev_inspect.provider import get_base_provider from mev_inspect.signal_handler import GracefulKiller - logging.basicConfig(filename="listener.log", filemode="a", level=logging.INFO) logger = logging.getLogger(__name__) @@ -35,16 +33,13 @@ async def run(): killer = GracefulKiller() - inspect_db_session = get_inspect_session() - trace_db_session = get_trace_session() - - inspector = MEVInspector(rpc, inspect_db_session, trace_db_session) + inspector = MEVInspector(rpc, None, None) base_provider = get_base_provider(rpc) while not killer.kill_now: await inspect_next_block( inspector, - inspect_db_session, + None, base_provider, healthcheck_url, ) diff --git a/mev_inspect/block.py b/mev_inspect/block.py index ab61919..37b1080 100644 --- a/mev_inspect/block.py +++ b/mev_inspect/block.py @@ -5,6 +5,7 @@ from typing import List, Optional from sqlalchemy import orm from web3 import Web3 +from mev_inspect.db import get_trace_session from mev_inspect.fees import fetch_base_fee_per_gas from mev_inspect.schemas.blocks import Block from mev_inspect.schemas.receipts import Receipt @@ -28,13 +29,12 @@ async def create_from_block_number( base_provider, w3: Web3, block_number: int, - trace_db_session: Optional[orm.Session], ) -> Block: block: Optional[Block] = None - if trace_db_session is not None: - block = _find_block(trace_db_session, block_number) - + if get_trace_session() is not None: + async with get_trace_session() as session: # type: ignore + block = await _find_block(session, block_number) if block is None: block = await _fetch_block(w3, base_provider, block_number) return block @@ -75,14 +75,14 @@ async def _fetch_block(w3, base_provider, block_number: int, retries: int = 0) - ) -def _find_block( +async def _find_block( trace_db_session: orm.Session, block_number: int, ) -> Optional[Block]: + traces = await _find_traces(trace_db_session, block_number) + receipts = await _find_receipts(trace_db_session, block_number) + base_fee_per_gas = await _find_base_fee(trace_db_session, block_number) block_timestamp = _find_block_timestamp(trace_db_session, block_number) - traces = _find_traces(trace_db_session, block_number) - receipts = _find_receipts(trace_db_session, block_number) - base_fee_per_gas = _find_base_fee(trace_db_session, block_number) if ( block_timestamp is None @@ -123,11 +123,11 @@ def _find_block_timestamp( return block_timestamp -def _find_traces( +async def _find_traces( trace_db_session: orm.Session, block_number: int, ) -> Optional[List[Trace]]: - result = trace_db_session.execute( + result = await trace_db_session.execute( "SELECT raw_traces FROM block_traces WHERE block_number = :block_number", params={"block_number": block_number}, ).one_or_none() @@ -139,11 +139,11 @@ def _find_traces( return [Trace(**trace_json) for trace_json in traces_json] -def _find_receipts( +async def _find_receipts( trace_db_session: orm.Session, block_number: int, ) -> Optional[List[Receipt]]: - result = trace_db_session.execute( + result = await trace_db_session.execute( "SELECT raw_receipts FROM block_receipts WHERE block_number = :block_number", params={"block_number": block_number}, ).one_or_none() @@ -155,11 +155,11 @@ def _find_receipts( return [Receipt(**receipt) for receipt in receipts_json] -def _find_base_fee( +async def _find_base_fee( trace_db_session: orm.Session, block_number: int, ) -> Optional[int]: - result = trace_db_session.execute( + result = await trace_db_session.execute( "SELECT base_fee_in_wei FROM base_fee WHERE block_number = :block_number", params={"block_number": block_number}, ).one_or_none() diff --git a/mev_inspect/crud/arbitrages.py b/mev_inspect/crud/arbitrages.py index 8d23e1d..a11a5ef 100644 --- a/mev_inspect/crud/arbitrages.py +++ b/mev_inspect/crud/arbitrages.py @@ -1,24 +1,18 @@ from typing import List from uuid import uuid4 +from mev_inspect.crud.generic import delete_by_block_number from mev_inspect.models.arbitrages import ArbitrageModel from mev_inspect.schemas.arbitrages import Arbitrage -def delete_arbitrages_for_block( - db_session, - block_number: int, -) -> None: - ( - db_session.query(ArbitrageModel) - .filter(ArbitrageModel.block_number == block_number) - .delete() +async def delete_arbitrages_for_block(db_session, block_number: int) -> None: + await delete_by_block_number( + db_session=db_session, block_number=block_number, model=ArbitrageModel ) - db_session.commit() - -def write_arbitrages( +async def write_arbitrages( db_session, arbitrages: List[Arbitrage], ) -> None: @@ -50,8 +44,10 @@ def write_arbitrages( ) if len(arbitrage_models) > 0: - db_session.bulk_save_objects(arbitrage_models) - db_session.execute( + db_session.add_all(arbitrage_models) + await db_session.commit() + await db_session.flush() + await db_session.execute( """ INSERT INTO arbitrage_swaps (arbitrage_id, swap_transaction_hash, swap_trace_address) @@ -60,5 +56,5 @@ def write_arbitrages( """, params=swap_arbitrage_ids, ) - - db_session.commit() + await db_session.commit() + await db_session.flush() diff --git a/mev_inspect/crud/blocks.py b/mev_inspect/crud/blocks.py index 3639ba8..5101a57 100644 --- a/mev_inspect/crud/blocks.py +++ b/mev_inspect/crud/blocks.py @@ -1,26 +1,28 @@ from mev_inspect.schemas.blocks import Block -def delete_block( +async def delete_block( db_session, block_number: int, ) -> None: - db_session.execute( + await db_session.execute( "DELETE FROM blocks WHERE block_number = :block_number", params={"block_number": block_number}, ) - db_session.commit() + await db_session.commit() + await db_session.flush() -def write_block( +async def write_block( db_session, block: Block, ) -> None: - db_session.execute( + await db_session.execute( "INSERT INTO blocks (block_number, block_timestamp) VALUES (:block_number, :block_timestamp)", params={ "block_number": block.block_number, "block_timestamp": block.block_timestamp, }, ) - db_session.commit() + await db_session.commit() + await db_session.flush() diff --git a/mev_inspect/crud/generic.py b/mev_inspect/crud/generic.py new file mode 100644 index 0000000..546c4a4 --- /dev/null +++ b/mev_inspect/crud/generic.py @@ -0,0 +1,21 @@ +import json +from typing import Sequence + +from pydantic import BaseModel +from sqlalchemy import delete + +from mev_inspect.models.base import Base + + +async def delete_by_block_number(db_session, block_number: int, model: Base): + statement = delete(model).where(model.block_number == block_number) + await db_session.execute(statement) + await db_session.commit() + await db_session.flush() + + +async def write_models(db_session, models: Sequence[BaseModel], db_model: Base): + models = [db_model(**json.loads(model.json())) for model in models] + db_session.add_all(models) + await db_session.commit() + await db_session.flush() diff --git a/mev_inspect/crud/liquidations.py b/mev_inspect/crud/liquidations.py index 2a58ead..7be02dc 100644 --- a/mev_inspect/crud/liquidations.py +++ b/mev_inspect/crud/liquidations.py @@ -1,31 +1,15 @@ -import json from typing import List +from mev_inspect.crud.generic import delete_by_block_number, write_models from mev_inspect.models.liquidations import LiquidationModel from mev_inspect.schemas.liquidations import Liquidation -def delete_liquidations_for_block( - db_session, - block_number: int, -) -> None: - ( - db_session.query(LiquidationModel) - .filter(LiquidationModel.block_number == block_number) - .delete() +async def delete_liquidations_for_block(db_session, block_number: int) -> None: + await delete_by_block_number( + db_session=db_session, block_number=block_number, model=LiquidationModel ) - db_session.commit() - -def write_liquidations( - db_session, - liquidations: List[Liquidation], -) -> None: - models = [ - LiquidationModel(**json.loads(liquidation.json())) - for liquidation in liquidations - ] - - db_session.bulk_save_objects(models) - db_session.commit() +async def write_liquidations(db_session, liquidations: List[Liquidation]) -> None: + await write_models(db_session, liquidations, LiquidationModel) diff --git a/mev_inspect/crud/miner_payments.py b/mev_inspect/crud/miner_payments.py index e82bf96..b9e2092 100644 --- a/mev_inspect/crud/miner_payments.py +++ b/mev_inspect/crud/miner_payments.py @@ -1,31 +1,15 @@ -import json from typing import List +from mev_inspect.crud.generic import delete_by_block_number, write_models from mev_inspect.models.miner_payments import MinerPaymentModel from mev_inspect.schemas.miner_payments import MinerPayment -def delete_miner_payments_for_block( - db_session, - block_number: int, -) -> None: - ( - db_session.query(MinerPaymentModel) - .filter(MinerPaymentModel.block_number == block_number) - .delete() +async def delete_miner_payments_for_block(db_session, block_number: int) -> None: + await delete_by_block_number( + db_session=db_session, block_number=block_number, model=MinerPaymentModel ) - db_session.commit() - -def write_miner_payments( - db_session, - miner_payments: List[MinerPayment], -) -> None: - models = [ - MinerPaymentModel(**json.loads(miner_payment.json())) - for miner_payment in miner_payments - ] - - db_session.bulk_save_objects(models) - db_session.commit() +async def write_miner_payments(db_session, miner_payments: List[MinerPayment]) -> None: + await write_models(db_session, miner_payments, MinerPaymentModel) diff --git a/mev_inspect/crud/swaps.py b/mev_inspect/crud/swaps.py index 4c51cd1..acdfe43 100644 --- a/mev_inspect/crud/swaps.py +++ b/mev_inspect/crud/swaps.py @@ -1,28 +1,15 @@ -import json from typing import List +from mev_inspect.crud.generic import delete_by_block_number, write_models from mev_inspect.models.swaps import SwapModel from mev_inspect.schemas.swaps import Swap -def delete_swaps_for_block( - db_session, - block_number: int, -) -> None: - ( - db_session.query(SwapModel) - .filter(SwapModel.block_number == block_number) - .delete() +async def delete_swaps_for_block(db_session, block_number: int) -> None: + await delete_by_block_number( + db_session=db_session, block_number=block_number, model=SwapModel ) - db_session.commit() - -def write_swaps( - db_session, - swaps: List[Swap], -) -> None: - models = [SwapModel(**json.loads(swap.json())) for swap in swaps] - - db_session.bulk_save_objects(models) - db_session.commit() +async def write_swaps(db_session, swaps: List[Swap]) -> None: + await write_models(db_session, swaps, SwapModel) diff --git a/mev_inspect/crud/traces.py b/mev_inspect/crud/traces.py index aa6f32c..5315e8f 100644 --- a/mev_inspect/crud/traces.py +++ b/mev_inspect/crud/traces.py @@ -1,26 +1,19 @@ import json from typing import List +from mev_inspect.crud.generic import delete_by_block_number from mev_inspect.models.traces import ClassifiedTraceModel from mev_inspect.schemas.traces import ClassifiedTrace -def delete_classified_traces_for_block( - db_session, - block_number: int, -) -> None: - ( - db_session.query(ClassifiedTraceModel) - .filter(ClassifiedTraceModel.block_number == block_number) - .delete() +async def delete_classified_traces_for_block(db_session, block_number: int) -> None: + await delete_by_block_number( + db_session=db_session, block_number=block_number, model=ClassifiedTraceModel ) - db_session.commit() - -def write_classified_traces( - db_session, - classified_traces: List[ClassifiedTrace], +async def write_classified_traces( + db_session, classified_traces: List[ClassifiedTrace] ) -> None: models = [] for trace in classified_traces: @@ -45,6 +38,6 @@ def write_classified_traces( error=trace.error, ) ) - - db_session.bulk_save_objects(models) - db_session.commit() + db_session.add_all(models) + await db_session.commit() + await db_session.flush() diff --git a/mev_inspect/crud/transfers.py b/mev_inspect/crud/transfers.py index 7aa5adb..453424e 100644 --- a/mev_inspect/crud/transfers.py +++ b/mev_inspect/crud/transfers.py @@ -1,28 +1,15 @@ -import json -from typing import List +from typing import Sequence +from mev_inspect.crud.generic import delete_by_block_number, write_models from mev_inspect.models.transfers import TransferModel from mev_inspect.schemas.transfers import Transfer -def delete_transfers_for_block( - db_session, - block_number: int, -) -> None: - ( - db_session.query(TransferModel) - .filter(TransferModel.block_number == block_number) - .delete() +async def delete_transfers_for_block(db_session, block_number: int) -> None: + await delete_by_block_number( + db_session=db_session, block_number=block_number, model=TransferModel ) - db_session.commit() - -def write_transfers( - db_session, - transfers: List[Transfer], -) -> None: - models = [TransferModel(**json.loads(transfer.json())) for transfer in transfers] - - db_session.bulk_save_objects(models) - db_session.commit() +async def write_transfers(db_session, transfers: Sequence[Transfer]) -> None: + await write_models(db_session, transfers, TransferModel) diff --git a/mev_inspect/db.py b/mev_inspect/db.py index 9cdaa48..ac04dd6 100644 --- a/mev_inspect/db.py +++ b/mev_inspect/db.py @@ -1,8 +1,8 @@ import os from typing import Optional -from sqlalchemy import create_engine, orm from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession def get_trace_database_uri() -> Optional[str]: @@ -12,7 +12,7 @@ def get_trace_database_uri() -> Optional[str]: db_name = "trace_db" if all(field is not None for field in [username, password, host]): - return f"postgresql://{username}:{password}@{host}/{db_name}" + return f"postgresql+asyncpg://{username}:{password}@{host}/{db_name}" return None @@ -22,24 +22,24 @@ def get_inspect_database_uri(): password = os.getenv("POSTGRES_PASSWORD") host = os.getenv("POSTGRES_HOST") db_name = "mev_inspect" - return f"postgresql://{username}:{password}@{host}/{db_name}" + return f"postgresql+asyncpg://{username}:{password}@{host}/{db_name}" def _get_engine(uri: str): - return create_engine(uri) + return create_async_engine(uri) def _get_session(uri: str): - Session = sessionmaker(bind=_get_engine(uri)) - return Session() + session = sessionmaker(bind=_get_engine(uri), class_=AsyncSession) + return session() -def get_inspect_session() -> orm.Session: +def get_inspect_session() -> sessionmaker: uri = get_inspect_database_uri() return _get_session(uri) -def get_trace_session() -> Optional[orm.Session]: +def get_trace_session() -> Optional[sessionmaker]: uri = get_trace_database_uri() if uri is not None: diff --git a/mev_inspect/inspect_block.py b/mev_inspect/inspect_block.py index c5f849d..356698d 100644 --- a/mev_inspect/inspect_block.py +++ b/mev_inspect/inspect_block.py @@ -1,7 +1,6 @@ import logging -from typing import Optional -from sqlalchemy import orm +from sqlalchemy.ext.asyncio import AsyncSession from web3 import Web3 from mev_inspect.arbitrages import get_arbitrages @@ -15,50 +14,42 @@ from mev_inspect.crud.blocks import ( delete_block, write_block, ) -from mev_inspect.crud.traces import ( - delete_classified_traces_for_block, - write_classified_traces, +from mev_inspect.crud.liquidations import ( + delete_liquidations_for_block, + write_liquidations, ) from mev_inspect.crud.miner_payments import ( delete_miner_payments_for_block, write_miner_payments, ) - from mev_inspect.crud.swaps import delete_swaps_for_block, write_swaps -from mev_inspect.crud.transfers import delete_transfers_for_block, write_transfers -from mev_inspect.crud.liquidations import ( - delete_liquidations_for_block, - write_liquidations, +from mev_inspect.crud.traces import ( + delete_classified_traces_for_block, + write_classified_traces, ) +from mev_inspect.crud.transfers import delete_transfers_for_block, write_transfers +from mev_inspect.liquidations import get_liquidations from mev_inspect.miner_payments import get_miner_payments from mev_inspect.swaps import get_swaps from mev_inspect.transfers import get_transfers -from mev_inspect.liquidations import get_liquidations - logger = logging.getLogger(__name__) async def inspect_block( - inspect_db_session: orm.Session, + inspect_db_session: AsyncSession, base_provider, w3: Web3, trace_classifier: TraceClassifier, block_number: int, - trace_db_session: Optional[orm.Session], should_write_classified_traces: bool = True, ): - block = await create_from_block_number( - base_provider, - w3, - block_number, - trace_db_session, - ) + block = await create_from_block_number(base_provider, w3, block_number) logger.info(f"Block: {block_number} -- Total traces: {len(block.traces)}") - delete_block(inspect_db_session, block_number) - write_block(inspect_db_session, block) + await delete_block(inspect_db_session, block_number) + await write_block(inspect_db_session, block) total_transactions = len( set(t.transaction_hash for t in block.traces if t.transaction_hash is not None) @@ -71,36 +62,33 @@ async def inspect_block( ) if should_write_classified_traces: - delete_classified_traces_for_block(inspect_db_session, block_number) - write_classified_traces(inspect_db_session, classified_traces) + await delete_classified_traces_for_block(inspect_db_session, block_number) + await write_classified_traces(inspect_db_session, classified_traces) transfers = get_transfers(classified_traces) logger.info(f"Block: {block_number} -- Found {len(transfers)} transfers") - delete_transfers_for_block(inspect_db_session, block_number) - write_transfers(inspect_db_session, transfers) + await delete_transfers_for_block(inspect_db_session, block_number) + await write_transfers(inspect_db_session, transfers) swaps = get_swaps(classified_traces) logger.info(f"Block: {block_number} -- Found {len(swaps)} swaps") - - delete_swaps_for_block(inspect_db_session, block_number) - write_swaps(inspect_db_session, swaps) + await delete_swaps_for_block(inspect_db_session, block_number) + await write_swaps(inspect_db_session, swaps) arbitrages = get_arbitrages(swaps) logger.info(f"Block: {block_number} -- Found {len(arbitrages)} arbitrages") - - delete_arbitrages_for_block(inspect_db_session, block_number) - write_arbitrages(inspect_db_session, arbitrages) + await delete_arbitrages_for_block(inspect_db_session, block_number) + await write_arbitrages(inspect_db_session, arbitrages) liquidations = get_liquidations(classified_traces) logger.info(f"Block: {block_number} -- Found {len(liquidations)} liquidations") - - delete_liquidations_for_block(inspect_db_session, block_number) - write_liquidations(inspect_db_session, liquidations) + await delete_liquidations_for_block(inspect_db_session, block_number) + await write_liquidations(inspect_db_session, liquidations) miner_payments = get_miner_payments( block.miner, block.base_fee_per_gas, classified_traces, block.receipts ) - - delete_miner_payments_for_block(inspect_db_session, block_number) - write_miner_payments(inspect_db_session, miner_payments) + await delete_miner_payments_for_block(inspect_db_session, block_number) + await write_miner_payments(inspect_db_session, miner_payments) + await inspect_db_session.commit() diff --git a/mev_inspect/inspector.py b/mev_inspect/inspector.py index 4fb8160..7550252 100644 --- a/mev_inspect/inspector.py +++ b/mev_inspect/inspector.py @@ -2,14 +2,13 @@ import asyncio import logging import traceback from asyncio import CancelledError -from typing import Optional -from sqlalchemy import orm from web3 import Web3 from web3.eth import AsyncEth from mev_inspect.block import create_from_block_number from mev_inspect.classifiers.trace import TraceClassifier +from mev_inspect.db import get_inspect_session from mev_inspect.inspect_block import inspect_block from mev_inspect.provider import get_base_provider @@ -20,13 +19,9 @@ class MEVInspector: def __init__( self, rpc: str, - inspect_db_session: orm.Session, - trace_db_session: Optional[orm.Session], max_concurrency: int = 1, request_timeout: int = 300, ): - self.inspect_db_session = inspect_db_session - self.trace_db_session = trace_db_session self.base_provider = get_base_provider(rpc, request_timeout=request_timeout) self.w3 = Web3(self.base_provider, modules={"eth": (AsyncEth,)}, middlewares=[]) self.trace_classifier = TraceClassifier() @@ -34,21 +29,14 @@ class MEVInspector: async def create_from_block(self, block_number: int): return await create_from_block_number( - base_provider=self.base_provider, - w3=self.w3, - block_number=block_number, - trace_db_session=self.trace_db_session, + base_provider=self.base_provider, w3=self.w3, block_number=block_number ) async def inspect_single_block(self, block: int): - return await inspect_block( - self.inspect_db_session, - self.base_provider, - self.w3, - self.trace_classifier, - block, - trace_db_session=self.trace_db_session, - ) + async with get_inspect_session() as session: + return await inspect_block( + session, self.base_provider, self.w3, self.trace_classifier, block + ) async def inspect_many_blocks(self, after_block: int, before_block: int): tasks = [] @@ -64,16 +52,16 @@ class MEVInspector: except CancelledError: logger.info("Requested to exit, cleaning up...") except Exception as e: - logger.error(f"Existed due to {type(e)}") + logger.error(f"Exited due to {type(e)}") traceback.print_exc() async def safe_inspect_block(self, block_number: int): - async with self.max_concurrency: - return await inspect_block( - self.inspect_db_session, - self.base_provider, - self.w3, - self.trace_classifier, - block_number, - trace_db_session=self.trace_db_session, - ) + async with get_inspect_session() as session: + async with self.max_concurrency: + return await inspect_block( + session, + self.base_provider, + self.w3, + self.trace_classifier, + block_number, + ) diff --git a/poetry.lock b/poetry.lock index 6a37a0a..08af502 100644 --- a/poetry.lock +++ b/poetry.lock @@ -66,6 +66,19 @@ python-versions = ">=3.6" [package.dependencies] typing-extensions = ">=3.6.5" +[[package]] +name = "asyncpg" +version = "0.25.0" +description = "An asyncio PostgreSQL driver" +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.extras] +dev = ["Cython (>=0.29.24,<0.30.0)", "pytest (>=6.0)", "Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "pycodestyle (>=2.7.0,<2.8.0)", "flake8 (>=3.9.2,<3.10.0)", "uvloop (>=0.15.3)"] +docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"] +test = ["pycodestyle (>=2.7.0,<2.8.0)", "flake8 (>=3.9.2,<3.10.0)", "uvloop (>=0.15.3)"] + [[package]] name = "atomicwrites" version = "1.4.0" @@ -387,7 +400,7 @@ python-versions = ">=3.6" name = "greenlet" version = "1.1.1" description = "Lightweight in-process concurrent programming" -category = "dev" +category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" @@ -870,26 +883,27 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "sqlalchemy" -version = "1.4.23" +version = "1.4.27" description = "Database Abstraction Library" -category = "dev" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and platform_machine in \"x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE amd64 AMD64 win32 WIN32\""} +greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} [package.extras] aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] -aiosqlite = ["greenlet (!=0.4.17)", "aiosqlite"] +aiosqlite = ["typing_extensions (!=3.10.0.1)", "greenlet (!=0.4.17)", "aiosqlite"] asyncio = ["greenlet (!=0.4.17)"] +asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3)"] mariadb_connector = ["mariadb (>=1.0.1)"] mssql = ["pyodbc"] mssql_pymssql = ["pymssql"] mssql_pyodbc = ["pyodbc"] mypy = ["sqlalchemy2-stubs", "mypy (>=0.910)"] mysql = ["mysqlclient (>=1.4.0,<2)", "mysqlclient (>=1.4.0)"] -mysql_connector = ["mysqlconnector"] +mysql_connector = ["mysql-connector-python"] oracle = ["cx_oracle (>=7,<8)", "cx_oracle (>=7)"] postgresql = ["psycopg2 (>=2.7)"] postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] @@ -1032,7 +1046,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "03aa2d5981665ade1b81682c1e797a06b56c5fb68d61ae69fd2f1e95bd32cfb6" +content-hash = "fe3f1ed98bb9236905ee77aa29577089d8ae16560fb97fbcf9d6221683a883fe" [metadata.files] aiohttp = [ @@ -1125,6 +1139,34 @@ async-timeout = [ {file = "async-timeout-4.0.0.tar.gz", hash = "sha256:7d87a4e8adba8ededb52e579ce6bc8276985888913620c935094c2276fd83382"}, {file = "async_timeout-4.0.0-py3-none-any.whl", hash = "sha256:f3303dddf6cafa748a92747ab6c2ecf60e0aeca769aee4c151adfce243a05d9b"}, ] +asyncpg = [ + {file = "asyncpg-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bf5e3408a14a17d480f36ebaf0401a12ff6ae5457fdf45e4e2775c51cc9517d3"}, + {file = "asyncpg-0.25.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2bc197fc4aca2fd24f60241057998124012469d2e414aed3f992579db0c88e3a"}, + {file = "asyncpg-0.25.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a70783f6ffa34cc7dd2de20a873181414a34fd35a4a208a1f1a7f9f695e4ec4"}, + {file = "asyncpg-0.25.0-cp310-cp310-win32.whl", hash = "sha256:43cde84e996a3afe75f325a68300093425c2f47d340c0fc8912765cf24a1c095"}, + {file = "asyncpg-0.25.0-cp310-cp310-win_amd64.whl", hash = "sha256:56d88d7ef4341412cd9c68efba323a4519c916979ba91b95d4c08799d2ff0c09"}, + {file = "asyncpg-0.25.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a84d30e6f850bac0876990bcd207362778e2208df0bee8be8da9f1558255e634"}, + {file = "asyncpg-0.25.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:beaecc52ad39614f6ca2e48c3ca15d56e24a2c15cbfdcb764a4320cc45f02fd5"}, + {file = "asyncpg-0.25.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:6f8f5fc975246eda83da8031a14004b9197f510c41511018e7b1bedde6968e92"}, + {file = "asyncpg-0.25.0-cp36-cp36m-win32.whl", hash = "sha256:ddb4c3263a8d63dcde3d2c4ac1c25206bfeb31fa83bd70fd539e10f87739dee4"}, + {file = "asyncpg-0.25.0-cp36-cp36m-win_amd64.whl", hash = "sha256:bf6dc9b55b9113f39eaa2057337ce3f9ef7de99a053b8a16360395ce588925cd"}, + {file = "asyncpg-0.25.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:acb311722352152936e58a8ee3c5b8e791b24e84cd7d777c414ff05b3530ca68"}, + {file = "asyncpg-0.25.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0a61fb196ce4dae2f2fa26eb20a778db21bbee484d2e798cb3cc988de13bdd1b"}, + {file = "asyncpg-0.25.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2633331cbc8429030b4f20f712f8d0fbba57fa8555ee9b2f45f981b81328b256"}, + {file = "asyncpg-0.25.0-cp37-cp37m-win32.whl", hash = "sha256:863d36eba4a7caa853fd7d83fad5fd5306f050cc2fe6e54fbe10cdb30420e5e9"}, + {file = "asyncpg-0.25.0-cp37-cp37m-win_amd64.whl", hash = "sha256:fe471ccd915b739ca65e2e4dbd92a11b44a5b37f2e38f70827a1c147dafe0fa8"}, + {file = "asyncpg-0.25.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:72a1e12ea0cf7c1e02794b697e3ca967b2360eaa2ce5d4bfdd8604ec2d6b774b"}, + {file = "asyncpg-0.25.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4327f691b1bdb222df27841938b3e04c14068166b3a97491bec2cb982f49f03e"}, + {file = "asyncpg-0.25.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:739bbd7f89a2b2f6bc44cb8bf967dab12c5bc714fcbe96e68d512be45ecdf962"}, + {file = "asyncpg-0.25.0-cp38-cp38-win32.whl", hash = "sha256:18d49e2d93a7139a2fdbd113e320cc47075049997268a61bfbe0dde680c55471"}, + {file = "asyncpg-0.25.0-cp38-cp38-win_amd64.whl", hash = "sha256:191fe6341385b7fdea7dbdcf47fd6db3fd198827dcc1f2b228476d13c05a03c6"}, + {file = "asyncpg-0.25.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:52fab7f1b2c29e187dd8781fce896249500cf055b63471ad66332e537e9b5f7e"}, + {file = "asyncpg-0.25.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a738f1b2876f30d710d3dc1e7858160a0afe1603ba16bf5f391f5316eb0ed855"}, + {file = "asyncpg-0.25.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4105f57ad1e8fbc8b1e535d8fcefa6ce6c71081228f08680c6dea24384ff0e"}, + {file = "asyncpg-0.25.0-cp39-cp39-win32.whl", hash = "sha256:f55918ded7b85723a5eaeb34e86e7b9280d4474be67df853ab5a7fa0cc7c6bf2"}, + {file = "asyncpg-0.25.0-cp39-cp39-win_amd64.whl", hash = "sha256:649e2966d98cc48d0646d9a4e29abecd8b59d38d55c256d5c857f6b27b7407ac"}, + {file = "asyncpg-0.25.0.tar.gz", hash = "sha256:63f8e6a69733b285497c2855464a34de657f2cccd25aeaeeb5071872e9382540"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -1662,6 +1704,8 @@ protobuf = [ {file = "protobuf-3.17.3.tar.gz", hash = "sha256:72804ea5eaa9c22a090d2803813e280fb273b62d5ae497aaf3553d141c4fdd7b"}, ] psycopg2 = [ + {file = "psycopg2-2.9.1-cp310-cp310-win32.whl", hash = "sha256:25615574419dd9bda6fdfdcd58afb22e721f5b807cb3d5e62f488c8acf8cb754"}, + {file = "psycopg2-2.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:e5a8ed9dbfca8dc162c4ada5ab017e10d5a66c542b4c73569f103fa5f342f498"}, {file = "psycopg2-2.9.1-cp36-cp36m-win32.whl", hash = "sha256:7f91312f065df517187134cce8e395ab37f5b601a42446bdc0f0d51773621854"}, {file = "psycopg2-2.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:830c8e8dddab6b6716a4bf73a09910c7954a92f40cf1d1e702fb93c8a919cc56"}, {file = "psycopg2-2.9.1-cp37-cp37m-win32.whl", hash = "sha256:89409d369f4882c47f7ea20c42c5046879ce22c1e4ea20ef3b00a4dfc0a7f188"}, @@ -1890,36 +1934,42 @@ six = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.4.23-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:25e9b2e5ca088879ce3740d9ccd4d58cb9061d49566a0b5e12166f403d6f4da0"}, - {file = "SQLAlchemy-1.4.23-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d9667260125688c71ccf9af321c37e9fb71c2693575af8210f763bfbbee847c7"}, - {file = "SQLAlchemy-1.4.23-cp27-cp27m-win32.whl", hash = "sha256:cec1a4c6ddf5f82191301a25504f0e675eccd86635f0d5e4c69e0661691931c5"}, - {file = "SQLAlchemy-1.4.23-cp27-cp27m-win_amd64.whl", hash = "sha256:ae07895b55c7d58a7dd47438f437ac219c0f09d24c2e7d69fdebc1ea75350f00"}, - {file = "SQLAlchemy-1.4.23-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:967307ea52985985224a79342527c36ec2d1daa257a39748dd90e001a4be4d90"}, - {file = "SQLAlchemy-1.4.23-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:be185b3daf651c6c0639987a916bf41e97b60e68f860f27c9cb6574385f5cbb4"}, - {file = "SQLAlchemy-1.4.23-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d3b3d51c83a66f5b72c57e1aad061406e4c390bd42cf1fda94effe82fac81"}, - {file = "SQLAlchemy-1.4.23-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a8395c4db3e1450eef2b68069abf500cc48af4b442a0d98b5d3c9535fe40cde8"}, - {file = "SQLAlchemy-1.4.23-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b128a78581faea7a5ee626ad4471353eee051e4e94616dfeff4742b6e5ba262"}, - {file = "SQLAlchemy-1.4.23-cp36-cp36m-win32.whl", hash = "sha256:43fc207be06e50158e4dae4cc4f27ce80afbdbfa7c490b3b22feb64f6d9775a0"}, - {file = "SQLAlchemy-1.4.23-cp36-cp36m-win_amd64.whl", hash = "sha256:e9d4f4552aa5e0d1417fc64a2ce1cdf56a30bab346ba6b0dd5e838eb56db4d29"}, - {file = "SQLAlchemy-1.4.23-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:512f52a8872e8d63d898e4e158eda17e2ee40b8d2496b3b409422e71016db0bd"}, - {file = "SQLAlchemy-1.4.23-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:355024cf061ed04271900414eb4a22671520241d2216ddb691bdd8a992172389"}, - {file = "SQLAlchemy-1.4.23-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:82c03325111eab88d64e0ff48b6fe15c75d23787429fa1d84c0995872e702787"}, - {file = "SQLAlchemy-1.4.23-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0aa312f9906ecebe133d7f44168c3cae4c76f27a25192fa7682f3fad505543c9"}, - {file = "SQLAlchemy-1.4.23-cp37-cp37m-win32.whl", hash = "sha256:059c5f41e8630f51741a234e6ba2a034228c11b3b54a15478e61d8b55fa8bd9d"}, - {file = "SQLAlchemy-1.4.23-cp37-cp37m-win_amd64.whl", hash = "sha256:cd68c5f9d13ffc8f4d6802cceee786678c5b1c668c97bc07b9f4a60883f36cd1"}, - {file = "SQLAlchemy-1.4.23-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:6a8dbf3d46e889d864a57ee880c4ad3a928db5aa95e3d359cbe0da2f122e50c4"}, - {file = "SQLAlchemy-1.4.23-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c15191f2430a30082f540ec6f331214746fc974cfdf136d7a1471d1c61d68ff"}, - {file = "SQLAlchemy-1.4.23-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cd0e85dd2067159848c7672acd517f0c38b7b98867a347411ea01b432003f8d9"}, - {file = "SQLAlchemy-1.4.23-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:370f4688ce47f0dc1e677a020a4d46252a31a2818fd67f5c256417faefc938af"}, - {file = "SQLAlchemy-1.4.23-cp38-cp38-win32.whl", hash = "sha256:bd41f8063a9cd11b76d6d7d6af8139ab3c087f5dbbe5a50c02cb8ece7da34d67"}, - {file = "SQLAlchemy-1.4.23-cp38-cp38-win_amd64.whl", hash = "sha256:2bca9a6e30ee425cc321d988a152a5fe1be519648e7541ac45c36cd4f569421f"}, - {file = "SQLAlchemy-1.4.23-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:4803a481d4c14ce6ad53dc35458c57821863e9a079695c27603d38355e61fb7f"}, - {file = "SQLAlchemy-1.4.23-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07b9099a95dd2b2620498544300eda590741ac54915c6b20809b6de7e3c58090"}, - {file = "SQLAlchemy-1.4.23-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:37f2bd1b8e32c5999280f846701712347fc0ee7370e016ede2283c71712e127a"}, - {file = "SQLAlchemy-1.4.23-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:448612570aa1437a5d1b94ada161805778fe80aba5b9a08a403e8ae4e071ded6"}, - {file = "SQLAlchemy-1.4.23-cp39-cp39-win32.whl", hash = "sha256:e0ce4a2e48fe0a9ea3a5160411a4c5135da5255ed9ac9c15f15f2bcf58c34194"}, - {file = "SQLAlchemy-1.4.23-cp39-cp39-win_amd64.whl", hash = "sha256:0aa746d1173587743960ff17b89b540e313aacfe6c1e9c81aa48393182c36d4f"}, - {file = "SQLAlchemy-1.4.23.tar.gz", hash = "sha256:76ff246881f528089bf19385131b966197bb494653990396d2ce138e2a447583"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:6afa9e4e63f066e0fd90a21db7e95e988d96127f52bfb298a0e9bec6999357a9"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec1c908fa721f2c5684900cc8ff75555b1a5a2ae4f5a5694eb0e37a5263cea44"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27m-win32.whl", hash = "sha256:0438bccc16349db2d5203598be6073175ce16d4e53b592d6e6cef880c197333e"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27m-win_amd64.whl", hash = "sha256:435b1980c1333ffe3ab386ad28d7b209590b0fa83ea8544d853e7a22f957331b"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:486f7916ef77213103467924ef25f5ea1055ae901f385fe4d707604095fdf6a9"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:d81c84c9d2523b3ea20f8e3aceea68615768a7464c0f9a9899600ce6592ec570"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5881644fc51af7b232ab8d64f75c0f32295dfe88c2ee188023795cdbd4cf99b"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:24828c5e74882cf41516740c0b150702bee4c6817d87d5c3d3bafef2e6896f80"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7d0a1b1258efff7d7f2e6cfa56df580d09ba29d35a1e3f604f867e1f685feb2"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-win32.whl", hash = "sha256:aadc6d1e58e14010ae4764d1ba1fd0928dbb9423b27a382ea3a1444f903f4084"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-win_amd64.whl", hash = "sha256:9134e5810262203388b203c2022bbcbf1a22e89861eef9340e772a73dd9076fa"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:fa52534076394af7315306a8701b726a6521b591d95e8f4e5121c82f94790e8d"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2717ceae35e71de1f58b0d1ee7e773d3aab5c403c6e79e8d262277c7f7f95269"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2e93624d186ea7a738ada47314701c8830e0e4b021a6bce7fbe6f39b87ee1516"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:987fe2f84ceaf744fa0e48805152abe485a9d7002c9923b18a4b2529c7bff218"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-win32.whl", hash = "sha256:2146ef996181e3d4dd20eaf1d7325eb62d6c8aa4dc1677c1872ddfa8561a47d9"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-win_amd64.whl", hash = "sha256:ad8ec6b69d03e395db48df8991aa15fce3cd23e378b73e01d46a26a6efd5c26d"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:52f23a76544ed29573c0f3ee41f0ca1aedbab3a453102b60b540cc6fa55448ad"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd421a14edf73cfe01e8f51ed8966294ee3b3db8da921cacc88e497fd6e977af"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:10230364479429437f1b819a8839f1edc5744c018bfeb8d01320930f97695bc9"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78943451ab3ffd0e27876f9cea2b883317518b418f06b90dadf19394534637e9"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-win32.whl", hash = "sha256:a81e40dfa50ed3c472494adadba097640bfcf43db160ed783132045eb2093cb1"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-win_amd64.whl", hash = "sha256:015511c52c650eebf1059ed8a21674d9d4ae567ebfd80fc73f8252faccd71864"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:cc49fb8ff103900c20e4a9c53766c82a7ebbc183377fb357a8298bad216e9cdd"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9369f927f4d19b58322cfea8a51710a3f7c47a0e7f3398d94a4632760ecd74f6"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6510f4a5029643301bdfe56b61e806093af2101d347d485c42a5535847d2c699"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:771eca9872b47a629010665ff92de1c248a6979b8d1603daced37773d6f6e365"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-win32.whl", hash = "sha256:4d1d707b752137e6bf45720648e1b828d5e4881d690df79cca07f7217ea06365"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-win_amd64.whl", hash = "sha256:c035184af4e58e154b0977eea52131edd096e0754a88f7d5a847e7ccb3510772"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:bac949be7579fed824887eed6672f44b7c4318abbfb2004b2c6968818b535a2f"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ac8306e04275d382d6393e557047b0a9d7ddf9f7ca5da9b3edbd9323ea75bd9"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8327e468b1775c0dfabc3d01f39f440585bf4d398508fcbbe2f0d931c502337d"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b02eee1577976acb4053f83d32b7826424f8b9f70809fa756529a52c6537eda4"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-win32.whl", hash = "sha256:5beeff18b4e894f6cb73c8daf2c0d8768844ef40d97032bb187d75b1ec8de24b"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-win_amd64.whl", hash = "sha256:8dbe5f639e6d035778ebf700be6d573f82a13662c3c2c3aa0f1dba303b942806"}, + {file = "SQLAlchemy-1.4.27.tar.gz", hash = "sha256:d768359daeb3a86644f3854c6659e4496a3e6bba2b4651ecc87ce7ad415b320c"}, ] termcolor = [ {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"}, diff --git a/pyproject.toml b/pyproject.toml index 9217449..a913bbb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,8 @@ hexbytes = "^0.2.1" click = "^8.0.1" psycopg2 = "^2.9.1" aiohttp = "^3.8.0" +SQLAlchemy = {extras = ["asyncio"], version = "^1.4.27"} +asyncpg = "^0.25.0" [tool.poetry.dev-dependencies] pre-commit = "^2.13.0"