diff --git a/alembic/versions/070819d86587_create_punk_snipe.py b/alembic/versions/070819d86587_create_punk_snipe.py new file mode 100644 index 0000000..fb50166 --- /dev/null +++ b/alembic/versions/070819d86587_create_punk_snipe.py @@ -0,0 +1,35 @@ +"""empty message + +Revision ID: 070819d86587 +Revises: d498bdb0a641 +Create Date: 2021-11-26 18:25:13.402822 + +""" +import sqlalchemy as sa +from alembic import op + + +# revision identifiers, used by Alembic. +revision = "d498bdb0a641" +down_revision = "205ce02374b3" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "punk_snipes", + sa.Column("created_at", sa.TIMESTAMP, server_default=sa.func.now()), + sa.Column("block_number", sa.Numeric, nullable=False), + sa.Column("transaction_hash", sa.String(66), nullable=False), + sa.Column("trace_address", sa.String(256), nullable=False), + sa.Column("from_address", sa.String(256), nullable=False), + sa.Column("punk_index", sa.Numeric, nullable=False), + sa.Column("min_acceptance_price", sa.Numeric, nullable=False), + sa.Column("acceptance_price", sa.Numeric, nullable=False), + sa.PrimaryKeyConstraint("transaction_hash", "trace_address"), + ) + + +def downgrade(): + op.drop_table("punk_snipes") diff --git a/alembic/versions/7cf0eeb41da0_add_punk_bids.py b/alembic/versions/7cf0eeb41da0_add_punk_bids.py new file mode 100644 index 0000000..0e93350 --- /dev/null +++ b/alembic/versions/7cf0eeb41da0_add_punk_bids.py @@ -0,0 +1,34 @@ +"""empty message + +Revision ID: 7cf0eeb41da0 +Revises: d498bdb0a641 +Create Date: 2021-11-26 20:27:28.936516 + +""" +import sqlalchemy as sa +from alembic import op + + +# revision identifiers, used by Alembic. +revision = "7cf0eeb41da0" +down_revision = "d498bdb0a641" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "punk_bids", + sa.Column("created_at", sa.TIMESTAMP, server_default=sa.func.now()), + sa.Column("block_number", sa.Numeric, nullable=False), + sa.Column("transaction_hash", sa.String(66), nullable=False), + sa.Column("trace_address", sa.String(256), nullable=False), + sa.Column("from_address", sa.String(256), nullable=False), + sa.Column("punk_index", sa.Numeric, nullable=False), + sa.Column("price", sa.Numeric, nullable=False), + sa.PrimaryKeyConstraint("block_number", "transaction_hash", "trace_address"), + ) + + +def downgrade(): + op.drop_table("punk_bids") diff --git a/mev_inspect/crud/punks.py b/mev_inspect/crud/punks.py new file mode 100644 index 0000000..7126287 --- /dev/null +++ b/mev_inspect/crud/punks.py @@ -0,0 +1,58 @@ +import json +from typing import List + +from mev_inspect.models.punks import ( + PunkSnipeModel, + PunkBidModel, +) +from mev_inspect.schemas.punk_snipe import PunkSnipe + +from mev_inspect.schemas.punk_bid import PunkBid + + +def delete_punk_bids_for_block( + db_session, + block_number: int, +) -> None: + ( + db_session.query(PunkBidModel) + .filter(PunkBidModel.block_number == block_number) + .delete() + ) + + db_session.commit() + + +def write_punk_bids( + db_session, + punk_bids: List[PunkBid], +) -> None: + models = [PunkBidModel(**json.loads(punk_bid.json())) for punk_bid in punk_bids] + + db_session.bulk_save_objects(models) + db_session.commit() + + +def delete_punk_snipes_for_block( + db_session, + block_number: int, +) -> None: + ( + db_session.query(PunkSnipeModel) + .filter(PunkSnipeModel.block_number == block_number) + .delete() + ) + + db_session.commit() + + +def write_punk_snipes( + db_session, + punk_snipes: List[PunkSnipe], +) -> None: + models = [ + PunkSnipeModel(**json.loads(punk_snipe.json())) for punk_snipe in punk_snipes + ] + + db_session.bulk_save_objects(models) + db_session.commit() diff --git a/mev_inspect/inspect_block.py b/mev_inspect/inspect_block.py index c6e58c6..0014c03 100644 --- a/mev_inspect/inspect_block.py +++ b/mev_inspect/inspect_block.py @@ -11,6 +11,13 @@ from mev_inspect.crud.arbitrages import ( delete_arbitrages_for_block, write_arbitrages, ) + +from mev_inspect.crud.punks import ( + delete_punk_snipes_for_block, + write_punk_snipes, + delete_punk_bids_for_block, + write_punk_bids, +) from mev_inspect.crud.blocks import ( delete_block, write_block, @@ -100,11 +107,17 @@ async def inspect_block( write_liquidations(inspect_db_session, liquidations) punk_bids = get_punk_bids(classified_traces) + delete_punk_bids_for_block(inspect_db_session, block_number) + write_punk_bids(inspect_db_session, punk_bids) + punk_bid_acceptances = get_punk_bid_acceptances(classified_traces) punk_snipes = get_punk_snipes(punk_bids, punk_bid_acceptances) logger.info(f"Block: {block_number} -- Found {len(punk_snipes)} punk snipes") + delete_punk_snipes_for_block(inspect_db_session, block_number) + write_punk_snipes(inspect_db_session, punk_snipes) + miner_payments = get_miner_payments( block.miner, block.base_fee_per_gas, classified_traces, block.receipts ) diff --git a/mev_inspect/models/punk_snipes.py b/mev_inspect/models/punk_snipes.py new file mode 100644 index 0000000..71cabac --- /dev/null +++ b/mev_inspect/models/punk_snipes.py @@ -0,0 +1,15 @@ +from sqlalchemy import Column, Numeric, String, ARRAY, Integer + +from .base import Base + + +class PunkSnipeModel(Base): + __tablename__ = "punk_snipes" + + block_number = Column(Numeric, nullable=False) + transaction_hash = Column(String, primary_key=True) + trace_address = Column(ARRAY(Integer), primary_key=True) + from_address = Column(String, nullable=False) + punk_index = Column(Integer, nullable=False) + min_acceptance_price = Column(Numeric, nullable=False) + acceptance_price = Column(Numeric, nullable=False) diff --git a/mev_inspect/models/punks.py b/mev_inspect/models/punks.py new file mode 100644 index 0000000..06dfa32 --- /dev/null +++ b/mev_inspect/models/punks.py @@ -0,0 +1,26 @@ +from sqlalchemy import Column, Numeric, String, ARRAY, Integer + +from .base import Base + + +class PunkSnipeModel(Base): + __tablename__ = "punk_snipes" + + block_number = Column(Numeric, nullable=False) + transaction_hash = Column(String, primary_key=True) + trace_address = Column(ARRAY(Integer), primary_key=True) + from_address = Column(String, nullable=False) + punk_index = Column(Integer, nullable=False) + min_acceptance_price = Column(Numeric, nullable=False) + acceptance_price = Column(Numeric, nullable=False) + + +class PunkBidModel(Base): + __tablename__ = "punk_bids" + + block_number = Column(Numeric, nullable=False) + transaction_hash = Column(String, primary_key=True) + trace_address = Column(ARRAY(Integer), primary_key=True) + from_address = Column(String, nullable=False) + punk_index = Column(Integer, nullable=False) + price = Column(Numeric, nullable=False)