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:
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user