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
# Install Python dependencies
pip install -e .
uv sync --all-extras
# Run database migrations
alembic upgrade head
uv run alembic upgrade head
# Run the tracker
python -m src.main
uv run python -m polymarket_insider_tracker
```
### Docker Services
@@ -188,24 +188,16 @@ LIQUIDITY_IMPACT_THRESHOLD=0.02
```
polymarket-insider-tracker/
├── src/
── ingestor/ # Real-time market data ingestion
├── clob_client.py # Polymarket CLOB API wrapper
── websocket.py # WebSocket event handler
├── profiler/ # Wallet analysis
│ │ ├── analyzer.py # Core wallet profiling logic
│ │ ── chain.py # Polygon blockchain client
── funding.py # Funding chain tracer
│ ├── detector/ # Anomaly detection engines
├── fresh_wallet.py
── size_anomaly.py
│ │ ├── 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
── polymarket_insider_tracker/
├── __main__.py # CLI entry point
── pipeline.py # Core detection pipeline
├── ingestor/ # Real-time market data ingestion
│ ├── clob_client.py # Polymarket CLOB API wrapper
── websocket.py # WebSocket event handler
── profiler/ # Wallet analysis
├── detector/ # Anomaly detection engines
├── alerter/ # Notification dispatch
── storage/ # Persistence layer
├── tests/ # Test suite
├── scripts/
│ └── backtest.py # Historical analysis
@@ -289,16 +281,16 @@ Contributions are welcome! Please read our Contributing Guide before submitting
```bash
# Install dev dependencies
pip install -e ".[dev]"
uv sync --all-extras
# Run tests
pytest
uv run pytest
# Run linting
ruff check src/
uv run ruff check src/
# 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
"""
from typing import Sequence, Union
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "001_initial"
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
down_revision: str | None = None
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
-2
View File
@@ -1,5 +1,3 @@
version: "3.8"
services:
postgres:
image: postgres:15
@@ -86,7 +86,7 @@ class Orderbook:
bids: tuple[OrderbookLevel, ...]
asks: tuple[OrderbookLevel, ...]
tick_size: Decimal
timestamp: datetime = field(default_factory=datetime.utcnow)
timestamp: datetime = field(default_factory=lambda: datetime.now(UTC))
@classmethod
def from_clob_orderbook(cls, orderbook: Any) -> "Orderbook":
@@ -9,8 +9,9 @@ from dataclasses import dataclass
from enum import Enum
from typing import Any
import websockets
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
@@ -156,7 +157,7 @@ class TradeStreamHandler:
await self._set_state(ConnectionState.CONNECTING)
try:
ws = await websockets.connect(
ws = await ws_connect(
self._host,
ping_interval=self._ping_interval,
ping_timeout=self._ping_interval * 2,
@@ -227,7 +228,7 @@ class TradeStreamHandler:
else:
logger.debug("Received binary message (%d bytes)", len(message))
except websockets.ConnectionClosed as e:
except ConnectionClosed as e:
logger.warning("Connection closed: %s", e)
raise
except Exception as e:
@@ -284,7 +285,7 @@ class TradeStreamHandler:
while self._running:
try:
await self._listen(self._ws)
except (websockets.ConnectionClosed, Exception) as e:
except (ConnectionClosed, Exception) as e:
if not self._running:
break
+8 -2
View File
@@ -231,7 +231,10 @@ class TestTradeStreamHandler:
mock_ws = 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()
assert ws is mock_ws
@@ -333,7 +336,10 @@ class TestTradeStreamHandlerIntegration:
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
try:
await asyncio.wait_for(handler.start(), timeout=1.0)