polymarket-sdk 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- polymarket_autopilot/__init__.py +3 -0
- polymarket_autopilot/audit.py +194 -0
- polymarket_autopilot/fetcher/__init__.py +61 -0
- polymarket_autopilot/fetcher/fetcher.py +489 -0
- polymarket_autopilot/market_snapshot.py +173 -0
- polymarket_autopilot/metrics.py +159 -0
- polymarket_autopilot/policy.py +400 -0
- polymarket_autopilot/py.typed +0 -0
- polymarket_autopilot/state_machine.py +315 -0
- polymarket_autopilot/trading/__init__.py +5 -0
- polymarket_autopilot/trading/trading.py +500 -0
- polymarket_sdk-0.2.0.dist-info/METADATA +388 -0
- polymarket_sdk-0.2.0.dist-info/RECORD +15 -0
- polymarket_sdk-0.2.0.dist-info/WHEEL +4 -0
- polymarket_sdk-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Structured audit logging — single source of truth for cross-project events.
|
|
2
|
+
|
|
3
|
+
Every transaction-touching project emits the same JSON-line schema, so a single
|
|
4
|
+
``cat *.jsonl | jq`` can correlate Uniswap swaps, Hyperliquid orders, and
|
|
5
|
+
Polymarket trades by ``run_id``.
|
|
6
|
+
|
|
7
|
+
Schema (one JSON object per line):
|
|
8
|
+
|
|
9
|
+
{
|
|
10
|
+
"ts": <ISO-8601 UTC, e.g. "2026-05-28T07:55:00.123Z">,
|
|
11
|
+
"ts_unix": <float seconds since epoch>,
|
|
12
|
+
"event": <enum: see EVENT_* constants below>,
|
|
13
|
+
"project": <e.g. "evm-wallet-scanner", "uniswap-autopilot">,
|
|
14
|
+
"run_id": <str|null — populated from STAGEFORGE_RUN_ID or caller>,
|
|
15
|
+
"chain": <str|null — e.g. "ethereum", "hyperliquid">,
|
|
16
|
+
"wallet": <str|null — 0x... or trader id>,
|
|
17
|
+
"tx_hash": <str|null — populated once broadcast>,
|
|
18
|
+
"error_code": <str|null — short stable code like "rpc_timeout">,
|
|
19
|
+
"details": <dict — free-form, never None>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Required fields are always present (null when unknown) so downstream consumers
|
|
23
|
+
can rely on the schema without defensive ``in`` checks.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import json
|
|
29
|
+
import os
|
|
30
|
+
import sys
|
|
31
|
+
import threading
|
|
32
|
+
from datetime import datetime, timezone
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
from typing import Any
|
|
35
|
+
|
|
36
|
+
# ── Event enum (stable strings) ────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
EVENT_PREFLIGHT = "preflight"
|
|
39
|
+
EVENT_QUOTE = "quote"
|
|
40
|
+
EVENT_SIGN = "sign"
|
|
41
|
+
EVENT_BROADCAST = "broadcast"
|
|
42
|
+
EVENT_CONFIRM = "confirm"
|
|
43
|
+
EVENT_CANCEL = "cancel"
|
|
44
|
+
EVENT_ERROR = "error"
|
|
45
|
+
|
|
46
|
+
ALLOWED_EVENTS = frozenset(
|
|
47
|
+
{
|
|
48
|
+
EVENT_PREFLIGHT,
|
|
49
|
+
EVENT_QUOTE,
|
|
50
|
+
EVENT_SIGN,
|
|
51
|
+
EVENT_BROADCAST,
|
|
52
|
+
EVENT_CONFIRM,
|
|
53
|
+
EVENT_CANCEL,
|
|
54
|
+
EVENT_ERROR,
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Required-keys order is fixed so jq/grep-based downstream tools have
|
|
59
|
+
# predictable JSON-line layouts.
|
|
60
|
+
REQUIRED_KEYS: tuple[str, ...] = (
|
|
61
|
+
"ts",
|
|
62
|
+
"ts_unix",
|
|
63
|
+
"event",
|
|
64
|
+
"project",
|
|
65
|
+
"run_id",
|
|
66
|
+
"chain",
|
|
67
|
+
"wallet",
|
|
68
|
+
"tx_hash",
|
|
69
|
+
"error_code",
|
|
70
|
+
"details",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
_write_lock = threading.Lock()
|
|
75
|
+
_DEFAULT_PROJECT = __name__.split(".")[0].replace("_", "-")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _now() -> tuple[str, float]:
|
|
79
|
+
now = datetime.now(tz=timezone.utc)
|
|
80
|
+
return now.strftime("%Y-%m-%dT%H:%M:%S.") + f"{now.microsecond // 1000:03d}Z", now.timestamp()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _resolve_run_id(explicit: str | None) -> str | None:
|
|
84
|
+
if explicit:
|
|
85
|
+
return explicit
|
|
86
|
+
for name in ("STAGEFORGE_RUN_ID", "AUDIT_RUN_ID", "RUN_ID"):
|
|
87
|
+
value = (os.environ.get(name) or "").strip()
|
|
88
|
+
if value:
|
|
89
|
+
return value
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def build_record(
|
|
94
|
+
*,
|
|
95
|
+
event: str,
|
|
96
|
+
project: str = _DEFAULT_PROJECT,
|
|
97
|
+
run_id: str | None = None,
|
|
98
|
+
chain: str | None = None,
|
|
99
|
+
wallet: str | None = None,
|
|
100
|
+
tx_hash: str | None = None,
|
|
101
|
+
error_code: str | None = None,
|
|
102
|
+
details: dict[str, Any] | None = None,
|
|
103
|
+
) -> dict[str, Any]:
|
|
104
|
+
"""Build the canonical record dict (does not emit it)."""
|
|
105
|
+
if event not in ALLOWED_EVENTS:
|
|
106
|
+
raise ValueError(
|
|
107
|
+
f"unknown audit event {event!r}; allowed: {sorted(ALLOWED_EVENTS)}"
|
|
108
|
+
)
|
|
109
|
+
ts_iso, ts_unix = _now()
|
|
110
|
+
return {
|
|
111
|
+
"ts": ts_iso,
|
|
112
|
+
"ts_unix": ts_unix,
|
|
113
|
+
"event": event,
|
|
114
|
+
"project": project,
|
|
115
|
+
"run_id": _resolve_run_id(run_id),
|
|
116
|
+
"chain": chain,
|
|
117
|
+
"wallet": wallet,
|
|
118
|
+
"tx_hash": tx_hash,
|
|
119
|
+
"error_code": error_code,
|
|
120
|
+
"details": details or {},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def emit(record: dict[str, Any]) -> None:
|
|
125
|
+
"""Write a record to the configured sink(s).
|
|
126
|
+
|
|
127
|
+
The sink target order is:
|
|
128
|
+
|
|
129
|
+
1. The file at ``AUDIT_LOG_PATH`` if set, appended.
|
|
130
|
+
2. stderr — always, so a tail-friendly trail exists.
|
|
131
|
+
"""
|
|
132
|
+
line = json.dumps(record, ensure_ascii=False, separators=(",", ":"))
|
|
133
|
+
|
|
134
|
+
with _write_lock:
|
|
135
|
+
path = (os.environ.get("AUDIT_LOG_PATH") or "").strip()
|
|
136
|
+
if path:
|
|
137
|
+
try:
|
|
138
|
+
p = Path(path)
|
|
139
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
140
|
+
with p.open("a", encoding="utf-8") as fh:
|
|
141
|
+
fh.write(line + "\n")
|
|
142
|
+
except OSError:
|
|
143
|
+
# Never let logging failure break the trade path.
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
# stderr fallback — present even when AUDIT_LOG_PATH is set so the
|
|
147
|
+
# operator can ``tail -f`` without finding the file first.
|
|
148
|
+
try:
|
|
149
|
+
sys.stderr.write(line + "\n")
|
|
150
|
+
sys.stderr.flush()
|
|
151
|
+
except Exception: # noqa: BLE001
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def log_event(
|
|
156
|
+
*,
|
|
157
|
+
event: str,
|
|
158
|
+
project: str = _DEFAULT_PROJECT,
|
|
159
|
+
run_id: str | None = None,
|
|
160
|
+
chain: str | None = None,
|
|
161
|
+
wallet: str | None = None,
|
|
162
|
+
tx_hash: str | None = None,
|
|
163
|
+
error_code: str | None = None,
|
|
164
|
+
details: dict[str, Any] | None = None,
|
|
165
|
+
) -> dict[str, Any]:
|
|
166
|
+
"""Shorthand: build + emit. Returns the emitted record."""
|
|
167
|
+
record = build_record(
|
|
168
|
+
event=event,
|
|
169
|
+
project=project,
|
|
170
|
+
run_id=run_id,
|
|
171
|
+
chain=chain,
|
|
172
|
+
wallet=wallet,
|
|
173
|
+
tx_hash=tx_hash,
|
|
174
|
+
error_code=error_code,
|
|
175
|
+
details=details,
|
|
176
|
+
)
|
|
177
|
+
emit(record)
|
|
178
|
+
return record
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
__all__ = [
|
|
182
|
+
"ALLOWED_EVENTS",
|
|
183
|
+
"EVENT_BROADCAST",
|
|
184
|
+
"EVENT_CANCEL",
|
|
185
|
+
"EVENT_CONFIRM",
|
|
186
|
+
"EVENT_ERROR",
|
|
187
|
+
"EVENT_PREFLIGHT",
|
|
188
|
+
"EVENT_QUOTE",
|
|
189
|
+
"EVENT_SIGN",
|
|
190
|
+
"REQUIRED_KEYS",
|
|
191
|
+
"build_record",
|
|
192
|
+
"emit",
|
|
193
|
+
"log_event",
|
|
194
|
+
]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Polymarket market data fetching (public APIs, no auth required)."""
|
|
2
|
+
|
|
3
|
+
from polymarket_autopilot.fetcher.fetcher import (
|
|
4
|
+
GAMMA_BASE,
|
|
5
|
+
CLOB_BASE,
|
|
6
|
+
DATA_BASE,
|
|
7
|
+
fetch_events,
|
|
8
|
+
fetch_event_by_id,
|
|
9
|
+
fetch_event_by_slug,
|
|
10
|
+
fetch_event_tags,
|
|
11
|
+
fetch_tags,
|
|
12
|
+
fetch_tag_by_id,
|
|
13
|
+
fetch_tag_by_slug,
|
|
14
|
+
fetch_related_tags_by_id,
|
|
15
|
+
fetch_series,
|
|
16
|
+
fetch_series_by_id,
|
|
17
|
+
fetch_markets,
|
|
18
|
+
fetch_market_by_id,
|
|
19
|
+
fetch_market_by_slug,
|
|
20
|
+
fetch_simplified_markets,
|
|
21
|
+
search,
|
|
22
|
+
resolve_market_token_id,
|
|
23
|
+
fetch_price_history,
|
|
24
|
+
fetch_orderbook,
|
|
25
|
+
fetch_midpoint,
|
|
26
|
+
fetch_spread,
|
|
27
|
+
fetch_trades,
|
|
28
|
+
fetch_leaderboard,
|
|
29
|
+
fetch_open_interest,
|
|
30
|
+
fetch_all_snapshot,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"GAMMA_BASE",
|
|
35
|
+
"CLOB_BASE",
|
|
36
|
+
"DATA_BASE",
|
|
37
|
+
"fetch_events",
|
|
38
|
+
"fetch_event_by_id",
|
|
39
|
+
"fetch_event_by_slug",
|
|
40
|
+
"fetch_event_tags",
|
|
41
|
+
"fetch_tags",
|
|
42
|
+
"fetch_tag_by_id",
|
|
43
|
+
"fetch_tag_by_slug",
|
|
44
|
+
"fetch_related_tags_by_id",
|
|
45
|
+
"fetch_series",
|
|
46
|
+
"fetch_series_by_id",
|
|
47
|
+
"fetch_markets",
|
|
48
|
+
"fetch_market_by_id",
|
|
49
|
+
"fetch_market_by_slug",
|
|
50
|
+
"fetch_simplified_markets",
|
|
51
|
+
"search",
|
|
52
|
+
"resolve_market_token_id",
|
|
53
|
+
"fetch_price_history",
|
|
54
|
+
"fetch_orderbook",
|
|
55
|
+
"fetch_midpoint",
|
|
56
|
+
"fetch_spread",
|
|
57
|
+
"fetch_trades",
|
|
58
|
+
"fetch_leaderboard",
|
|
59
|
+
"fetch_open_interest",
|
|
60
|
+
"fetch_all_snapshot",
|
|
61
|
+
]
|