chore: smoke test fixes and code quality improvements (#88)

* fix: replace deprecated datetime.utcnow() and websockets.legacy APIs

- Replace datetime.utcnow() with datetime.now(UTC) in Orderbook model
- Use websockets.asyncio.client.connect instead of legacy websockets.connect
- Import ConnectionClosed from websockets.exceptions directly
- Update test mocks to patch the new import paths

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve ruff lint errors in alembic migration

- Replace typing.Union with X | Y syntax (UP007)
- Import Sequence from collections.abc instead of typing (UP035)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove deprecated version key from docker-compose.yml

The top-level 'version' key is obsolete in modern Docker Compose
and produces a warning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: fix README to match actual project structure and tooling

- Replace pip commands with uv equivalents
- Fix run command from 'python -m src.main' to 'python -m polymarket_insider_tracker'
- Update project structure tree to reflect actual src/polymarket_insider_tracker/ layout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Selamy
2026-03-09 22:03:10 -04:00
committed by GitHub
parent 7c494c38a6
commit 232680a760
6 changed files with 35 additions and 38 deletions
+17 -25
View File
@@ -126,13 +126,13 @@ docker compose up -d
docker compose ps docker compose ps
# Install Python dependencies # Install Python dependencies
pip install -e . uv sync --all-extras
# Run database migrations # Run database migrations
alembic upgrade head uv run alembic upgrade head
# Run the tracker # Run the tracker
python -m src.main uv run python -m polymarket_insider_tracker
``` ```
### Docker Services ### Docker Services
@@ -188,24 +188,16 @@ LIQUIDITY_IMPACT_THRESHOLD=0.02
``` ```
polymarket-insider-tracker/ polymarket-insider-tracker/
├── src/ ├── src/
── ingestor/ # Real-time market data ingestion ── polymarket_insider_tracker/
├── clob_client.py # Polymarket CLOB API wrapper ├── __main__.py # CLI entry point
── websocket.py # WebSocket event handler ── pipeline.py # Core detection pipeline
├── profiler/ # Wallet analysis ├── ingestor/ # Real-time market data ingestion
│ │ ├── analyzer.py # Core wallet profiling logic │ ├── clob_client.py # Polymarket CLOB API wrapper
│ │ ── chain.py # Polygon blockchain client ── websocket.py # WebSocket event handler
── funding.py # Funding chain tracer ── profiler/ # Wallet analysis
│ ├── detector/ # Anomaly detection engines ├── detector/ # Anomaly detection engines
├── fresh_wallet.py ├── alerter/ # Notification dispatch
── size_anomaly.py ── storage/ # Persistence layer
│ │ ├── sniper.py # DBSCAN clustering
│ │ └── scorer.py # Composite risk scoring
│ ├── alerter/ # Notification dispatch
│ │ ├── formatter.py # Alert message formatting
│ │ └── dispatcher.py # Multi-channel delivery
│ └── storage/ # Persistence layer
│ ├── models.py # SQLAlchemy models
│ └── repos.py # Repository pattern
├── tests/ # Test suite ├── tests/ # Test suite
├── scripts/ ├── scripts/
│ └── backtest.py # Historical analysis │ └── backtest.py # Historical analysis
@@ -289,16 +281,16 @@ Contributions are welcome! Please read our Contributing Guide before submitting
```bash ```bash
# Install dev dependencies # Install dev dependencies
pip install -e ".[dev]" uv sync --all-extras
# Run tests # Run tests
pytest uv run pytest
# Run linting # Run linting
ruff check src/ uv run ruff check src/
# Run type checking # Run type checking
mypy src/ uv run mypy src/
``` ```
--- ---
@@ -5,16 +5,16 @@ Revises:
Create Date: 2026-01-04 00:00:00.000000+00:00 Create Date: 2026-01-04 00:00:00.000000+00:00
""" """
from typing import Sequence, Union from collections.abc import Sequence
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op from alembic import op
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision: str = "001_initial" revision: str = "001_initial"
down_revision: Union[str, None] = None down_revision: str | None = None
branch_labels: Union[str, Sequence[str], None] = None branch_labels: str | Sequence[str] | None = None
depends_on: Union[str, Sequence[str], None] = None depends_on: str | Sequence[str] | None = None
def upgrade() -> None: def upgrade() -> None:
-2
View File
@@ -1,5 +1,3 @@
version: "3.8"
services: services:
postgres: postgres:
image: postgres:15 image: postgres:15
@@ -86,7 +86,7 @@ class Orderbook:
bids: tuple[OrderbookLevel, ...] bids: tuple[OrderbookLevel, ...]
asks: tuple[OrderbookLevel, ...] asks: tuple[OrderbookLevel, ...]
tick_size: Decimal tick_size: Decimal
timestamp: datetime = field(default_factory=datetime.utcnow) timestamp: datetime = field(default_factory=lambda: datetime.now(UTC))
@classmethod @classmethod
def from_clob_orderbook(cls, orderbook: Any) -> "Orderbook": def from_clob_orderbook(cls, orderbook: Any) -> "Orderbook":
@@ -9,8 +9,9 @@ from dataclasses import dataclass
from enum import Enum from enum import Enum
from typing import Any from typing import Any
import websockets
from websockets.asyncio.client import ClientConnection from websockets.asyncio.client import ClientConnection
from websockets.asyncio.client import connect as ws_connect
from websockets.exceptions import ConnectionClosed
from polymarket_insider_tracker.ingestor.models import TradeEvent from polymarket_insider_tracker.ingestor.models import TradeEvent
@@ -156,7 +157,7 @@ class TradeStreamHandler:
await self._set_state(ConnectionState.CONNECTING) await self._set_state(ConnectionState.CONNECTING)
try: try:
ws = await websockets.connect( ws = await ws_connect(
self._host, self._host,
ping_interval=self._ping_interval, ping_interval=self._ping_interval,
ping_timeout=self._ping_interval * 2, ping_timeout=self._ping_interval * 2,
@@ -227,7 +228,7 @@ class TradeStreamHandler:
else: else:
logger.debug("Received binary message (%d bytes)", len(message)) logger.debug("Received binary message (%d bytes)", len(message))
except websockets.ConnectionClosed as e: except ConnectionClosed as e:
logger.warning("Connection closed: %s", e) logger.warning("Connection closed: %s", e)
raise raise
except Exception as e: except Exception as e:
@@ -284,7 +285,7 @@ class TradeStreamHandler:
while self._running: while self._running:
try: try:
await self._listen(self._ws) await self._listen(self._ws)
except (websockets.ConnectionClosed, Exception) as e: except (ConnectionClosed, Exception) as e:
if not self._running: if not self._running:
break break
+8 -2
View File
@@ -231,7 +231,10 @@ class TestTradeStreamHandler:
mock_ws = AsyncMock() mock_ws = AsyncMock()
mock_ws.send = AsyncMock() mock_ws.send = AsyncMock()
with patch("websockets.connect", AsyncMock(return_value=mock_ws)): with patch(
"polymarket_insider_tracker.ingestor.websocket.ws_connect",
AsyncMock(return_value=mock_ws),
):
ws = await handler._connect() ws = await handler._connect()
assert ws is mock_ws assert ws is mock_ws
@@ -333,7 +336,10 @@ class TestTradeStreamHandlerIntegration:
mock_ws = MockWebSocket(handler, trade_message) mock_ws = MockWebSocket(handler, trade_message)
with patch("websockets.connect", AsyncMock(return_value=mock_ws)): with patch(
"polymarket_insider_tracker.ingestor.websocket.ws_connect",
AsyncMock(return_value=mock_ws),
):
# Run with timeout to prevent hanging # Run with timeout to prevent hanging
try: try:
await asyncio.wait_for(handler.start(), timeout=1.0) await asyncio.wait_for(handler.start(), timeout=1.0)