polynode 0.10.7__tar.gz → 0.11.0__tar.gz
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.
- polynode-0.11.0/.gitignore +8 -0
- {polynode-0.10.7 → polynode-0.11.0}/PKG-INFO +52 -5
- polynode-0.11.0/README.md +183 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/__init__.py +3 -1
- polynode-0.11.0/polynode/_version.py +1 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/client.py +144 -8
- {polynode-0.10.7 → polynode-0.11.0}/polynode/short_form.py +121 -19
- {polynode-0.10.7 → polynode-0.11.0}/polynode/subscription.py +63 -2
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/V2_ORDER_FLOW.md +7 -30
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/clob_api.py +69 -10
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/constants.py +3 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/eip712.py +19 -8
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/escrow.py +3 -2
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/onboarding.py +4 -4
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/trader.py +22 -6
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/types.py +6 -3
- {polynode-0.10.7 → polynode-0.11.0}/polynode/types/enums.py +22 -0
- polynode-0.11.0/polynode/types/events.py +571 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/types/rest.py +18 -1
- {polynode-0.10.7 → polynode-0.11.0}/polynode/types/short_form.py +5 -1
- {polynode-0.10.7 → polynode-0.11.0}/polynode/types/ws.py +12 -0
- polynode-0.11.0/polynode/ws.py +761 -0
- {polynode-0.10.7 → polynode-0.11.0}/pyproject.toml +11 -1
- polynode-0.10.7/.gitignore +0 -43
- polynode-0.10.7/README.md +0 -136
- polynode-0.10.7/polynode/_version.py +0 -1
- polynode-0.10.7/polynode/types/events.py +0 -270
- polynode-0.10.7/polynode/ws.py +0 -328
- polynode-0.10.7/tests/__init__.py +0 -0
- polynode-0.10.7/tests/conftest.py +0 -33
- polynode-0.10.7/tests/test_client.py +0 -141
- polynode-0.10.7/tests/test_orderbook.py +0 -73
- polynode-0.10.7/tests/test_orderbook_protocol.py +0 -131
- polynode-0.10.7/tests/test_trading.py +0 -464
- polynode-0.10.7/tests/test_types.py +0 -80
- polynode-0.10.7/tests/test_ws_protocol.py +0 -107
- {polynode-0.10.7 → polynode-0.11.0}/polynode/cache/__init__.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/engine.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/errors.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/orderbook.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/orderbook_state.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/redemption_watcher.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/testing.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/__init__.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/cosigner.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/position_management.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/privy.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/relayer.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/signer.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/trading/sqlite_backend.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/types/__init__.py +0 -0
- {polynode-0.10.7 → polynode-0.11.0}/polynode/types/orderbook.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: polynode
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: Python SDK for the PolyNode real-time prediction market data platform
|
|
5
5
|
Project-URL: Homepage, https://polynode.dev
|
|
6
6
|
Project-URL: Documentation, https://docs.polynode.dev
|
|
@@ -35,7 +35,11 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
|
|
36
36
|
Python SDK for the [PolyNode](https://polynode.dev) real-time prediction market data platform.
|
|
37
37
|
|
|
38
|
-
**New in v0.
|
|
38
|
+
**New in v0.11.0:** Current-production parity. Trading now defaults to CLOB V2 on `clob.polymarket.com`, uses PolyNode's public builder attribution unless overridden, omits removed V1 wire fields, and supports V2 GTD expiration. Managed 5-minute, 15-minute, and 4-hour streams select the required 30/60-second Chainlink TWAP lookbacks on a dedicated connection and reconnect/resubscribe at every market rotation. WebSocket models, presets, and filters now cover current redemption, position-conversion, dome/fill, and PM2 combo events. REST position queries now include redeemable/condition filters, multi-wallet batches, and market-holder views; connection and status observability match the current public API.
|
|
39
|
+
|
|
40
|
+
**New in v0.10.8:** POLY_1271 V2 order signatures now normalize the ERC-7739 `TypedDataSign` recovery byte to Ethereum `v=27/28` for on-chain ERC-1271 validation.
|
|
41
|
+
|
|
42
|
+
**In v0.10.7:** Polymarket V2 deposit-wallet trading fixes. `ensure_ready()` detects deployed `POLY_1271` wallets correctly, V2 type-3 orders use the deposit wallet as both maker and signer, and existing local credentials can be repaired by rerunning `ensure_ready()`.
|
|
39
43
|
|
|
40
44
|
## Install
|
|
41
45
|
|
|
@@ -57,8 +61,19 @@ from polynode import PolyNode
|
|
|
57
61
|
|
|
58
62
|
with PolyNode(api_key="pn_live_...") as pn:
|
|
59
63
|
status = pn.status()
|
|
64
|
+
connections = pn.connections()
|
|
60
65
|
markets = pn.markets(count=10)
|
|
61
66
|
settlements = pn.recent_settlements(count=5)
|
|
67
|
+
wallet_positions = pn.wallet_positions(
|
|
68
|
+
address, redeemable=True, condition_id=condition_id
|
|
69
|
+
)
|
|
70
|
+
batch_positions = pn.multi_wallet_positions([address, second_address], limit=100)
|
|
71
|
+
market_positions = pn.market_positions(
|
|
72
|
+
condition_id, sort_by="CURRENT_VALUE", min_size=0.01
|
|
73
|
+
)
|
|
74
|
+
onchain_positions = pn.wallet_onchain_positions(
|
|
75
|
+
address, since=window_start, tag_slug="crypto"
|
|
76
|
+
)
|
|
62
77
|
```
|
|
63
78
|
|
|
64
79
|
### Sports and Online Context
|
|
@@ -101,6 +116,36 @@ async def main():
|
|
|
101
116
|
asyncio.run(main())
|
|
102
117
|
```
|
|
103
118
|
|
|
119
|
+
Current presets include `dome`, `fills`, `combos`, `redemptions`, and `deposits`. Current filters include `since()`, `combo_condition_ids()`, `leg_position_ids()`, `event_ids()`, `module_ids()`, `action()`, and `direction()`.
|
|
120
|
+
|
|
121
|
+
`dome` and `fills` change settlement delivery into a flat, per-fill wire
|
|
122
|
+
format. Use one of those presets on a dedicated `PolyNodeWS` connection when
|
|
123
|
+
also consuming non-fill events; the server deduplicates delivery per
|
|
124
|
+
connection and cannot deliver both wire formats for the same settlement.
|
|
125
|
+
|
|
126
|
+
### Chainlink TWAP and short-form markets
|
|
127
|
+
|
|
128
|
+
The TWAP values are lookback windows, not update cadence: 5-minute markets use 30 seconds; 15-minute and 4-hour markets use 60 seconds.
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
async def stream_short_markets(pn):
|
|
132
|
+
prices = await (
|
|
133
|
+
pn.ws.subscribe("chainlink")
|
|
134
|
+
.feeds(["BTC/USD", "ETH/USD"])
|
|
135
|
+
.twap_windows([30])
|
|
136
|
+
.send()
|
|
137
|
+
)
|
|
138
|
+
print(prices.price_source, prices.twap_windows, prices.warnings)
|
|
139
|
+
prices.on("price_feed", lambda event: print(event.feed, event.price))
|
|
140
|
+
|
|
141
|
+
stream = pn.ws.short_form("5m", coins=["btc", "eth"])
|
|
142
|
+
stream.on("rotation", lambda rotation: print([m.slug for m in rotation.markets]))
|
|
143
|
+
stream.on("price_feed", lambda event: print(event.feed, event.price))
|
|
144
|
+
stream.on("settlement", lambda event: print(event.market_slug, event.status))
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
A Chainlink selection is scoped to its WebSocket connection, so combine feeds and windows into one Chainlink subscription per connection. The resolved subscription exposes the server acknowledgement through `price_source`, `twap_windows`, and `warnings`. `short_form()` handles rotation safely with its own socket. At each market boundary it closes that socket, discovers the new slugs, reconnects, and subscribes to the exact settlement and TWAP filters again.
|
|
148
|
+
|
|
104
149
|
### WebSocket Streaming
|
|
105
150
|
|
|
106
151
|
```python
|
|
@@ -140,11 +185,11 @@ import asyncio
|
|
|
140
185
|
from polynode.trading import PolyNodeTrader, TraderConfig, OrderParams, ExchangeVersion
|
|
141
186
|
|
|
142
187
|
async def main():
|
|
143
|
-
#
|
|
144
|
-
# (pUSD collateral, clob-v2.polymarket.com, builder attribution).
|
|
188
|
+
# CLOB V2 (pUSD collateral) is the current production default.
|
|
145
189
|
trader = PolyNodeTrader(TraderConfig(
|
|
146
190
|
polynode_key="pn_live_...",
|
|
147
|
-
exchange_version=ExchangeVersion.V2,
|
|
191
|
+
# exchange_version=ExchangeVersion.V2,
|
|
192
|
+
# builder_code=None, # disables default public PolyNode attribution
|
|
148
193
|
))
|
|
149
194
|
status = await trader.ensure_ready("0xYourPrivateKey...")
|
|
150
195
|
|
|
@@ -164,6 +209,8 @@ asyncio.run(main())
|
|
|
164
209
|
|
|
165
210
|
For the V2 order flow — required approvals, EIP-712 struct, fee math, and common failure modes — see `polynode/trading/V2_ORDER_FLOW.md` in the installed package.
|
|
166
211
|
|
|
212
|
+
V2 fees are determined at match time and are not signed into an order, so V2 payloads omit `feeRateBps`, `nonce`, and `taker`. Explicit legacy V1 mode still signs `feeRateBps`; for that path the SDK fetches `/fee-rate` and fails closed if fee, tick-size, or neg-risk metadata is unavailable or malformed.
|
|
213
|
+
|
|
167
214
|
## Documentation
|
|
168
215
|
|
|
169
216
|
Full docs at [docs.polynode.dev](https://docs.polynode.dev)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# polynode
|
|
2
|
+
|
|
3
|
+
Python SDK for the [PolyNode](https://polynode.dev) real-time prediction market data platform.
|
|
4
|
+
|
|
5
|
+
**New in v0.11.0:** Current-production parity. Trading now defaults to CLOB V2 on `clob.polymarket.com`, uses PolyNode's public builder attribution unless overridden, omits removed V1 wire fields, and supports V2 GTD expiration. Managed 5-minute, 15-minute, and 4-hour streams select the required 30/60-second Chainlink TWAP lookbacks on a dedicated connection and reconnect/resubscribe at every market rotation. WebSocket models, presets, and filters now cover current redemption, position-conversion, dome/fill, and PM2 combo events. REST position queries now include redeemable/condition filters, multi-wallet batches, and market-holder views; connection and status observability match the current public API.
|
|
6
|
+
|
|
7
|
+
**New in v0.10.8:** POLY_1271 V2 order signatures now normalize the ERC-7739 `TypedDataSign` recovery byte to Ethereum `v=27/28` for on-chain ERC-1271 validation.
|
|
8
|
+
|
|
9
|
+
**In v0.10.7:** Polymarket V2 deposit-wallet trading fixes. `ensure_ready()` detects deployed `POLY_1271` wallets correctly, V2 type-3 orders use the deposit wallet as both maker and signer, and existing local credentials can be repaired by rerunning `ensure_ready()`.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install polynode
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For trading support:
|
|
18
|
+
```bash
|
|
19
|
+
pip install polynode[trading]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### REST API
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from polynode import PolyNode
|
|
28
|
+
|
|
29
|
+
with PolyNode(api_key="pn_live_...") as pn:
|
|
30
|
+
status = pn.status()
|
|
31
|
+
connections = pn.connections()
|
|
32
|
+
markets = pn.markets(count=10)
|
|
33
|
+
settlements = pn.recent_settlements(count=5)
|
|
34
|
+
wallet_positions = pn.wallet_positions(
|
|
35
|
+
address, redeemable=True, condition_id=condition_id
|
|
36
|
+
)
|
|
37
|
+
batch_positions = pn.multi_wallet_positions([address, second_address], limit=100)
|
|
38
|
+
market_positions = pn.market_positions(
|
|
39
|
+
condition_id, sort_by="CURRENT_VALUE", min_size=0.01
|
|
40
|
+
)
|
|
41
|
+
onchain_positions = pn.wallet_onchain_positions(
|
|
42
|
+
address, since=window_start, tag_slug="crypto"
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Sports and Online Context
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from polynode import PolyNode
|
|
50
|
+
|
|
51
|
+
with PolyNode(api_key="pn_live_...") as pn:
|
|
52
|
+
state = pn.sports_game_state(
|
|
53
|
+
"nba-cle-nyk-2026-05-31",
|
|
54
|
+
price_limit_tokens=20,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
context = pn.sports_game_context(
|
|
58
|
+
"nba-cle-nyk-2026-05-31",
|
|
59
|
+
sources=["online"],
|
|
60
|
+
query_set="injuries",
|
|
61
|
+
max_queries=2,
|
|
62
|
+
max_per_query=5,
|
|
63
|
+
include_state=True,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
web = pn.search_online(
|
|
67
|
+
"Cavaliers Knicks injury news",
|
|
68
|
+
max_results=5,
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Async REST
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import asyncio
|
|
76
|
+
from polynode import AsyncPolyNode
|
|
77
|
+
|
|
78
|
+
async def main():
|
|
79
|
+
async with AsyncPolyNode(api_key="pn_live_...") as pn:
|
|
80
|
+
status = await pn.status()
|
|
81
|
+
markets = await pn.markets(count=10)
|
|
82
|
+
|
|
83
|
+
asyncio.run(main())
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Current presets include `dome`, `fills`, `combos`, `redemptions`, and `deposits`. Current filters include `since()`, `combo_condition_ids()`, `leg_position_ids()`, `event_ids()`, `module_ids()`, `action()`, and `direction()`.
|
|
87
|
+
|
|
88
|
+
`dome` and `fills` change settlement delivery into a flat, per-fill wire
|
|
89
|
+
format. Use one of those presets on a dedicated `PolyNodeWS` connection when
|
|
90
|
+
also consuming non-fill events; the server deduplicates delivery per
|
|
91
|
+
connection and cannot deliver both wire formats for the same settlement.
|
|
92
|
+
|
|
93
|
+
### Chainlink TWAP and short-form markets
|
|
94
|
+
|
|
95
|
+
The TWAP values are lookback windows, not update cadence: 5-minute markets use 30 seconds; 15-minute and 4-hour markets use 60 seconds.
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
async def stream_short_markets(pn):
|
|
99
|
+
prices = await (
|
|
100
|
+
pn.ws.subscribe("chainlink")
|
|
101
|
+
.feeds(["BTC/USD", "ETH/USD"])
|
|
102
|
+
.twap_windows([30])
|
|
103
|
+
.send()
|
|
104
|
+
)
|
|
105
|
+
print(prices.price_source, prices.twap_windows, prices.warnings)
|
|
106
|
+
prices.on("price_feed", lambda event: print(event.feed, event.price))
|
|
107
|
+
|
|
108
|
+
stream = pn.ws.short_form("5m", coins=["btc", "eth"])
|
|
109
|
+
stream.on("rotation", lambda rotation: print([m.slug for m in rotation.markets]))
|
|
110
|
+
stream.on("price_feed", lambda event: print(event.feed, event.price))
|
|
111
|
+
stream.on("settlement", lambda event: print(event.market_slug, event.status))
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
A Chainlink selection is scoped to its WebSocket connection, so combine feeds and windows into one Chainlink subscription per connection. The resolved subscription exposes the server acknowledgement through `price_source`, `twap_windows`, and `warnings`. `short_form()` handles rotation safely with its own socket. At each market boundary it closes that socket, discovers the new slugs, reconnects, and subscribes to the exact settlement and TWAP filters again.
|
|
115
|
+
|
|
116
|
+
### WebSocket Streaming
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
import asyncio
|
|
120
|
+
from polynode import AsyncPolyNode
|
|
121
|
+
|
|
122
|
+
async def main():
|
|
123
|
+
async with AsyncPolyNode(api_key="pn_live_...") as pn:
|
|
124
|
+
sub = await pn.ws.subscribe("settlements").min_size(1000).send()
|
|
125
|
+
|
|
126
|
+
async for event in sub:
|
|
127
|
+
print(event.event_type, event.market_title, event.taker_price)
|
|
128
|
+
|
|
129
|
+
asyncio.run(main())
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Orderbook
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import asyncio
|
|
136
|
+
from polynode import OrderbookEngine
|
|
137
|
+
|
|
138
|
+
async def main():
|
|
139
|
+
engine = OrderbookEngine(api_key="pn_live_...")
|
|
140
|
+
await engine.subscribe(["token_id_1", "token_id_2"])
|
|
141
|
+
|
|
142
|
+
engine.on("ready", lambda: print(f"Tracking {engine.size} books"))
|
|
143
|
+
engine.on("update", lambda u: print(f"{u.asset_id}: {engine.midpoint(u.asset_id)}"))
|
|
144
|
+
|
|
145
|
+
asyncio.run(main())
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Trading
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
import asyncio
|
|
152
|
+
from polynode.trading import PolyNodeTrader, TraderConfig, OrderParams, ExchangeVersion
|
|
153
|
+
|
|
154
|
+
async def main():
|
|
155
|
+
# CLOB V2 (pUSD collateral) is the current production default.
|
|
156
|
+
trader = PolyNodeTrader(TraderConfig(
|
|
157
|
+
polynode_key="pn_live_...",
|
|
158
|
+
# exchange_version=ExchangeVersion.V2,
|
|
159
|
+
# builder_code=None, # disables default public PolyNode attribution
|
|
160
|
+
))
|
|
161
|
+
status = await trader.ensure_ready("0xYourPrivateKey...")
|
|
162
|
+
|
|
163
|
+
result = await trader.order(OrderParams(
|
|
164
|
+
token_id="...",
|
|
165
|
+
side="BUY",
|
|
166
|
+
price=0.55,
|
|
167
|
+
size=100,
|
|
168
|
+
builder="0x<your_builder_code_bytes32>", # V2 only; omit for V1
|
|
169
|
+
))
|
|
170
|
+
print(result)
|
|
171
|
+
|
|
172
|
+
trader.close()
|
|
173
|
+
|
|
174
|
+
asyncio.run(main())
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
For the V2 order flow — required approvals, EIP-712 struct, fee math, and common failure modes — see `polynode/trading/V2_ORDER_FLOW.md` in the installed package.
|
|
178
|
+
|
|
179
|
+
V2 fees are determined at match time and are not signed into an order, so V2 payloads omit `feeRateBps`, `nonce`, and `taker`. Explicit legacy V1 mode still signs `feeRateBps`; for that path the SDK fetches `/fee-rate` and fails closed if fee, tick-size, or neg-risk metadata is unavailable or malformed.
|
|
180
|
+
|
|
181
|
+
## Documentation
|
|
182
|
+
|
|
183
|
+
Full docs at [docs.polynode.dev](https://docs.polynode.dev)
|
|
@@ -7,7 +7,7 @@ from .errors import ApiError, PolyNodeError, WsError
|
|
|
7
7
|
from .orderbook import OrderbookWS
|
|
8
8
|
from .orderbook_state import LocalOrderbook
|
|
9
9
|
from .redemption_watcher import RedeemableAlert, RedemptionWatcher, TrackedPosition
|
|
10
|
-
from .short_form import ShortFormStream
|
|
10
|
+
from .short_form import ShortFormStream, short_form_chainlink_feed, short_form_twap_window
|
|
11
11
|
from .subscription import Subscription, SubscriptionBuilder
|
|
12
12
|
from .testing import get_active_test_wallet, get_active_test_wallets
|
|
13
13
|
from .ws import PolyNodeWS
|
|
@@ -28,6 +28,8 @@ __all__ = [
|
|
|
28
28
|
"EngineView",
|
|
29
29
|
# Streams
|
|
30
30
|
"ShortFormStream",
|
|
31
|
+
"short_form_chainlink_feed",
|
|
32
|
+
"short_form_twap_window",
|
|
31
33
|
"RedemptionWatcher",
|
|
32
34
|
"RedeemableAlert",
|
|
33
35
|
"TrackedPosition",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.11.0"
|
|
@@ -143,6 +143,10 @@ class PolyNode:
|
|
|
143
143
|
def status(self) -> StatusResponse:
|
|
144
144
|
return StatusResponse.model_validate(self._fetch("/v1/status"))
|
|
145
145
|
|
|
146
|
+
def connections(self) -> dict:
|
|
147
|
+
"""Return connection and subscription usage for this API key or account."""
|
|
148
|
+
return self._fetch("/v1/connections")
|
|
149
|
+
|
|
146
150
|
def create_key(self, name: str = "unnamed") -> ApiKeyResponse:
|
|
147
151
|
return ApiKeyResponse.model_validate(
|
|
148
152
|
self._fetch("/v1/keys", method="POST", body={"name": name}, auth=False)
|
|
@@ -404,14 +408,78 @@ class PolyNode:
|
|
|
404
408
|
query={"limit": limit, "offset": offset, "side": side, "user": user},
|
|
405
409
|
)
|
|
406
410
|
|
|
407
|
-
def wallet_positions(
|
|
411
|
+
def wallet_positions(
|
|
412
|
+
self,
|
|
413
|
+
address: str,
|
|
414
|
+
*,
|
|
415
|
+
limit: int | None = None,
|
|
416
|
+
offset: int | None = None,
|
|
417
|
+
redeemable: bool | None = None,
|
|
418
|
+
condition_id: str | None = None,
|
|
419
|
+
) -> dict:
|
|
408
420
|
return self._fetch(
|
|
409
421
|
f"/v1/wallets/{quote(address, safe='')}/positions",
|
|
410
|
-
query={
|
|
422
|
+
query={
|
|
423
|
+
"limit": limit,
|
|
424
|
+
"offset": offset,
|
|
425
|
+
"redeemable": redeemable,
|
|
426
|
+
"condition_id": condition_id,
|
|
427
|
+
},
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
def multi_wallet_positions(
|
|
431
|
+
self,
|
|
432
|
+
wallets: list[str] | tuple[str, ...],
|
|
433
|
+
*,
|
|
434
|
+
limit: int | None = None,
|
|
435
|
+
offset: int | None = None,
|
|
436
|
+
) -> dict:
|
|
437
|
+
"""Return positions for up to 20 wallets in one request."""
|
|
438
|
+
return self._fetch(
|
|
439
|
+
"/v1/wallets/positions",
|
|
440
|
+
query={"wallets": _csv_param(wallets), "limit": limit, "offset": offset},
|
|
411
441
|
)
|
|
412
442
|
|
|
413
|
-
def
|
|
414
|
-
|
|
443
|
+
def market_positions(
|
|
444
|
+
self,
|
|
445
|
+
id: str,
|
|
446
|
+
*,
|
|
447
|
+
limit: int | None = None,
|
|
448
|
+
offset: int | None = None,
|
|
449
|
+
sort_by: str | None = None,
|
|
450
|
+
sort_direction: str | None = None,
|
|
451
|
+
status: str | None = None,
|
|
452
|
+
include_trades: bool | None = None,
|
|
453
|
+
user: str | list[str] | tuple[str, ...] | None = None,
|
|
454
|
+
min_size: float | None = None,
|
|
455
|
+
) -> dict:
|
|
456
|
+
"""Return holder positions for a condition ID or market slug."""
|
|
457
|
+
return self._fetch(
|
|
458
|
+
f"/v1/markets/{quote(id, safe='')}/positions",
|
|
459
|
+
query={
|
|
460
|
+
"limit": limit,
|
|
461
|
+
"offset": offset,
|
|
462
|
+
"sortBy": sort_by,
|
|
463
|
+
"sortDirection": sort_direction,
|
|
464
|
+
"status": status,
|
|
465
|
+
"includeTrades": include_trades,
|
|
466
|
+
"user": _csv_param(user),
|
|
467
|
+
"minSize": min_size,
|
|
468
|
+
},
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
def wallet_onchain_positions(
|
|
472
|
+
self,
|
|
473
|
+
address: str,
|
|
474
|
+
*,
|
|
475
|
+
since: int | None = None,
|
|
476
|
+
until: int | None = None,
|
|
477
|
+
tag_slug: str | None = None,
|
|
478
|
+
) -> dict:
|
|
479
|
+
return self._fetch(
|
|
480
|
+
f"/v2/wallets/{quote(address, safe='')}/positions/onchain",
|
|
481
|
+
query={"since": since, "until": until, "tag_slug": tag_slug},
|
|
482
|
+
)
|
|
415
483
|
|
|
416
484
|
# ── Orderbook (REST) ──
|
|
417
485
|
|
|
@@ -592,6 +660,10 @@ class AsyncPolyNode:
|
|
|
592
660
|
async def status(self) -> StatusResponse:
|
|
593
661
|
return StatusResponse.model_validate(await self._fetch("/v1/status"))
|
|
594
662
|
|
|
663
|
+
async def connections(self) -> dict:
|
|
664
|
+
"""Return connection and subscription usage for this API key or account."""
|
|
665
|
+
return await self._fetch("/v1/connections")
|
|
666
|
+
|
|
595
667
|
async def create_key(self, name: str = "unnamed") -> ApiKeyResponse:
|
|
596
668
|
return ApiKeyResponse.model_validate(
|
|
597
669
|
await self._fetch("/v1/keys", method="POST", body={"name": name}, auth=False)
|
|
@@ -853,14 +925,78 @@ class AsyncPolyNode:
|
|
|
853
925
|
query={"limit": limit, "offset": offset, "side": side, "user": user},
|
|
854
926
|
)
|
|
855
927
|
|
|
856
|
-
async def wallet_positions(
|
|
928
|
+
async def wallet_positions(
|
|
929
|
+
self,
|
|
930
|
+
address: str,
|
|
931
|
+
*,
|
|
932
|
+
limit: int | None = None,
|
|
933
|
+
offset: int | None = None,
|
|
934
|
+
redeemable: bool | None = None,
|
|
935
|
+
condition_id: str | None = None,
|
|
936
|
+
) -> dict:
|
|
857
937
|
return await self._fetch(
|
|
858
938
|
f"/v1/wallets/{quote(address, safe='')}/positions",
|
|
859
|
-
query={
|
|
939
|
+
query={
|
|
940
|
+
"limit": limit,
|
|
941
|
+
"offset": offset,
|
|
942
|
+
"redeemable": redeemable,
|
|
943
|
+
"condition_id": condition_id,
|
|
944
|
+
},
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
async def multi_wallet_positions(
|
|
948
|
+
self,
|
|
949
|
+
wallets: list[str] | tuple[str, ...],
|
|
950
|
+
*,
|
|
951
|
+
limit: int | None = None,
|
|
952
|
+
offset: int | None = None,
|
|
953
|
+
) -> dict:
|
|
954
|
+
"""Return positions for up to 20 wallets in one request."""
|
|
955
|
+
return await self._fetch(
|
|
956
|
+
"/v1/wallets/positions",
|
|
957
|
+
query={"wallets": _csv_param(wallets), "limit": limit, "offset": offset},
|
|
860
958
|
)
|
|
861
959
|
|
|
862
|
-
async def
|
|
863
|
-
|
|
960
|
+
async def market_positions(
|
|
961
|
+
self,
|
|
962
|
+
id: str,
|
|
963
|
+
*,
|
|
964
|
+
limit: int | None = None,
|
|
965
|
+
offset: int | None = None,
|
|
966
|
+
sort_by: str | None = None,
|
|
967
|
+
sort_direction: str | None = None,
|
|
968
|
+
status: str | None = None,
|
|
969
|
+
include_trades: bool | None = None,
|
|
970
|
+
user: str | list[str] | tuple[str, ...] | None = None,
|
|
971
|
+
min_size: float | None = None,
|
|
972
|
+
) -> dict:
|
|
973
|
+
"""Return holder positions for a condition ID or market slug."""
|
|
974
|
+
return await self._fetch(
|
|
975
|
+
f"/v1/markets/{quote(id, safe='')}/positions",
|
|
976
|
+
query={
|
|
977
|
+
"limit": limit,
|
|
978
|
+
"offset": offset,
|
|
979
|
+
"sortBy": sort_by,
|
|
980
|
+
"sortDirection": sort_direction,
|
|
981
|
+
"status": status,
|
|
982
|
+
"includeTrades": include_trades,
|
|
983
|
+
"user": _csv_param(user),
|
|
984
|
+
"minSize": min_size,
|
|
985
|
+
},
|
|
986
|
+
)
|
|
987
|
+
|
|
988
|
+
async def wallet_onchain_positions(
|
|
989
|
+
self,
|
|
990
|
+
address: str,
|
|
991
|
+
*,
|
|
992
|
+
since: int | None = None,
|
|
993
|
+
until: int | None = None,
|
|
994
|
+
tag_slug: str | None = None,
|
|
995
|
+
) -> dict:
|
|
996
|
+
return await self._fetch(
|
|
997
|
+
f"/v2/wallets/{quote(address, safe='')}/positions/onchain",
|
|
998
|
+
query={"since": since, "until": until, "tag_slug": tag_slug},
|
|
999
|
+
)
|
|
864
1000
|
|
|
865
1001
|
# ── Orderbook (REST) ──
|
|
866
1002
|
|