polymarket-apis 0.3.0__py3-none-any.whl → 0.3.2__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.
Potentially problematic release.
This version of polymarket-apis might be problematic. Click here for more details.
- polymarket_apis/__init__.py +41 -0
- polymarket_apis/clients/__init__.py +23 -0
- polymarket_apis/clients/clob_client.py +171 -79
- polymarket_apis/clients/data_client.py +181 -66
- polymarket_apis/clients/gamma_client.py +582 -100
- polymarket_apis/clients/graphql_client.py +28 -11
- polymarket_apis/clients/web3_client.py +131 -60
- polymarket_apis/clients/websockets_client.py +24 -7
- polymarket_apis/types/__init__.py +167 -0
- polymarket_apis/types/clob_types.py +28 -8
- polymarket_apis/types/common.py +15 -32
- polymarket_apis/types/data_types.py +15 -2
- polymarket_apis/types/gamma_types.py +521 -258
- polymarket_apis/types/websockets_types.py +92 -41
- polymarket_apis/utilities/config.py +1 -0
- polymarket_apis/utilities/exceptions.py +5 -0
- polymarket_apis/utilities/order_builder/builder.py +32 -16
- polymarket_apis/utilities/order_builder/helpers.py +0 -1
- polymarket_apis/utilities/signing/hmac.py +5 -1
- polymarket_apis/utilities/web3/abis/custom_contract_errors.py +1 -1
- polymarket_apis/utilities/web3/helpers.py +1 -0
- {polymarket_apis-0.3.0.dist-info → polymarket_apis-0.3.2.dist-info}/METADATA +34 -5
- polymarket_apis-0.3.2.dist-info/RECORD +41 -0
- polymarket_apis/utilities/schemas/activity-subgraph.graphql +0 -86
- polymarket_apis/utilities/schemas/open-interest.graphql +0 -30
- polymarket_apis-0.3.0.dist-info/RECORD +0 -43
- {polymarket_apis-0.3.0.dist-info → polymarket_apis-0.3.2.dist-info}/WHEEL +0 -0
|
@@ -5,7 +5,13 @@ from gql.transport.httpx import HTTPXAsyncTransport, HTTPXTransport
|
|
|
5
5
|
|
|
6
6
|
from ..utilities.config import GRAPHQL_ENDPOINTS
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
class PolymarketGraphQLClient:
|
|
10
|
+
"""Synchronous GraphQL client for Polymarket subgraphs."""
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
endpoint_name: Literal[
|
|
9
15
|
"activity_subgraph",
|
|
10
16
|
"fpmm_subgraph",
|
|
11
17
|
"open_interest_subgraph",
|
|
@@ -14,16 +20,13 @@ EndpointName = Literal[
|
|
|
14
20
|
"positions_subgraph",
|
|
15
21
|
"sports_oracle_subgraph",
|
|
16
22
|
"wallet_subgraph",
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class PolymarketGraphQLClient:
|
|
21
|
-
"""Synchronous GraphQL client for Polymarket subgraphs."""
|
|
22
|
-
|
|
23
|
-
def __init__(self, endpoint_name: EndpointName) -> None:
|
|
23
|
+
],
|
|
24
|
+
) -> None:
|
|
24
25
|
endpoint_url = GRAPHQL_ENDPOINTS[endpoint_name]
|
|
25
26
|
self.transport = HTTPXTransport(url=endpoint_url)
|
|
26
|
-
self.client = Client(
|
|
27
|
+
self.client = Client(
|
|
28
|
+
transport=self.transport, fetch_schema_from_transport=False
|
|
29
|
+
)
|
|
27
30
|
|
|
28
31
|
def query(self, query_string: str) -> dict:
|
|
29
32
|
with self.client as session:
|
|
@@ -33,10 +36,24 @@ class PolymarketGraphQLClient:
|
|
|
33
36
|
class AsyncPolymarketGraphQLClient:
|
|
34
37
|
"""Asynchronous GraphQL client for Polymarket subgraphs."""
|
|
35
38
|
|
|
36
|
-
def __init__(
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
endpoint_name: Literal[
|
|
42
|
+
"activity_subgraph",
|
|
43
|
+
"fpmm_subgraph",
|
|
44
|
+
"open_interest_subgraph",
|
|
45
|
+
"orderbook_subgraph",
|
|
46
|
+
"pnl_subgraph",
|
|
47
|
+
"positions_subgraph",
|
|
48
|
+
"sports_oracle_subgraph",
|
|
49
|
+
"wallet_subgraph",
|
|
50
|
+
],
|
|
51
|
+
) -> None:
|
|
37
52
|
endpoint_url = GRAPHQL_ENDPOINTS[endpoint_name]
|
|
38
53
|
self.transport = HTTPXAsyncTransport(url=endpoint_url)
|
|
39
|
-
self.client = Client(
|
|
54
|
+
self.client = Client(
|
|
55
|
+
transport=self.transport, fetch_schema_from_transport=False
|
|
56
|
+
)
|
|
40
57
|
|
|
41
58
|
async def query(self, query_string: str) -> dict:
|
|
42
59
|
async with self.client as session:
|
|
@@ -14,16 +14,24 @@ from ..utilities.web3.helpers import get_index_set
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def _load_abi(contract_name: str) -> list:
|
|
17
|
-
abi_path =
|
|
17
|
+
abi_path = (
|
|
18
|
+
Path(__file__).parent.parent
|
|
19
|
+
/ "utilities"
|
|
20
|
+
/ "web3"
|
|
21
|
+
/ "abis"
|
|
22
|
+
/ f"{contract_name}.json"
|
|
23
|
+
)
|
|
18
24
|
with Path.open(abi_path) as f:
|
|
19
25
|
return load(f)
|
|
20
26
|
|
|
21
|
-
class PolymarketWeb3Client:
|
|
22
|
-
def __init__(self, private_key: str , chain_id: Literal[137, 80002] = POLYGON):
|
|
23
27
|
|
|
28
|
+
class PolymarketWeb3Client:
|
|
29
|
+
def __init__(self, private_key: str, chain_id: Literal[137, 80002] = POLYGON):
|
|
24
30
|
self.w3 = Web3(Web3.HTTPProvider("https://polygon-rpc.com"))
|
|
25
31
|
self.w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
|
|
26
|
-
self.w3.middleware_onion.inject(
|
|
32
|
+
self.w3.middleware_onion.inject(
|
|
33
|
+
SignAndSendRawMiddlewareBuilder.build(private_key), layer=0
|
|
34
|
+
)
|
|
27
35
|
|
|
28
36
|
self.account = self.w3.eth.account.from_key(private_key)
|
|
29
37
|
|
|
@@ -34,25 +42,37 @@ class PolymarketWeb3Client:
|
|
|
34
42
|
self.usdc_abi = _load_abi("UChildERC20Proxy")
|
|
35
43
|
self.usdc = self.contract(self.usdc_address, self.usdc_abi)
|
|
36
44
|
|
|
37
|
-
self.conditional_tokens_address = Web3.to_checksum_address(
|
|
45
|
+
self.conditional_tokens_address = Web3.to_checksum_address(
|
|
46
|
+
self.config.conditional_tokens
|
|
47
|
+
)
|
|
38
48
|
self.conditional_tokens_abi = _load_abi("ConditionalTokens")
|
|
39
|
-
self.conditional_tokens = self.contract(
|
|
49
|
+
self.conditional_tokens = self.contract(
|
|
50
|
+
self.conditional_tokens_address, self.conditional_tokens_abi
|
|
51
|
+
)
|
|
40
52
|
|
|
41
53
|
self.exchange_address = Web3.to_checksum_address(self.config.exchange)
|
|
42
54
|
self.exchange_abi = _load_abi("CTFExchange")
|
|
43
55
|
self.exchange = self.contract(self.exchange_address, self.exchange_abi)
|
|
44
56
|
|
|
45
|
-
self.neg_risk_exchange_address = Web3.to_checksum_address(
|
|
57
|
+
self.neg_risk_exchange_address = Web3.to_checksum_address(
|
|
58
|
+
self.neg_risk_config.exchange
|
|
59
|
+
)
|
|
46
60
|
self.neg_risk_exchange_abi = _load_abi("NegRiskCtfExchange")
|
|
47
|
-
self.neg_risk_exchange = self.contract(
|
|
61
|
+
self.neg_risk_exchange = self.contract(
|
|
62
|
+
self.neg_risk_exchange_address, self.neg_risk_exchange_abi
|
|
63
|
+
)
|
|
48
64
|
|
|
49
65
|
self.neg_risk_adapter_address = "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296"
|
|
50
66
|
self.neg_risk_adapter_abi = _load_abi("NegRiskAdapter")
|
|
51
|
-
self.neg_risk_adapter = self.contract(
|
|
67
|
+
self.neg_risk_adapter = self.contract(
|
|
68
|
+
self.neg_risk_adapter_address, self.neg_risk_adapter_abi
|
|
69
|
+
)
|
|
52
70
|
|
|
53
71
|
self.proxy_factory_address = "0xaB45c5A4B0c941a2F231C04C3f49182e1A254052"
|
|
54
72
|
self.proxy_factory_abi = _load_abi("ProxyWalletFactory")
|
|
55
|
-
self.proxy_factory = self.contract(
|
|
73
|
+
self.proxy_factory = self.contract(
|
|
74
|
+
self.proxy_factory_address, self.proxy_factory_abi
|
|
75
|
+
)
|
|
56
76
|
|
|
57
77
|
def _encode_split(self, condition_id: Keccak256, amount: int) -> str:
|
|
58
78
|
return self.conditional_tokens.encode_abi(
|
|
@@ -72,12 +92,17 @@ class PolymarketWeb3Client:
|
|
|
72
92
|
args=[self.usdc_address, HASH_ZERO, condition_id, [1, 2]],
|
|
73
93
|
)
|
|
74
94
|
|
|
75
|
-
def _encode_redeem_neg_risk(
|
|
95
|
+
def _encode_redeem_neg_risk(
|
|
96
|
+
self, condition_id: Keccak256, amounts: list[int]
|
|
97
|
+
) -> str:
|
|
76
98
|
return self.neg_risk_adapter.encode_abi(
|
|
77
99
|
abi_element_identifier="redeemPositions",
|
|
78
100
|
args=[condition_id, amounts],
|
|
79
101
|
)
|
|
80
|
-
|
|
102
|
+
|
|
103
|
+
def _encode_convert(
|
|
104
|
+
self, neg_risk_market_id: Keccak256, index_set: int, amount: int
|
|
105
|
+
) -> str:
|
|
81
106
|
return self.neg_risk_adapter.encode_abi(
|
|
82
107
|
abi_element_identifier="convertPositions",
|
|
83
108
|
args=[neg_risk_market_id, index_set, amount],
|
|
@@ -98,25 +123,37 @@ class PolymarketWeb3Client:
|
|
|
98
123
|
Explicitly passing the proxy address is faster due to only one contract function call.
|
|
99
124
|
"""
|
|
100
125
|
if address is None:
|
|
101
|
-
address = self.exchange.functions.getPolyProxyWalletAddress(
|
|
126
|
+
address = self.exchange.functions.getPolyProxyWalletAddress(
|
|
127
|
+
self.account.address
|
|
128
|
+
).call()
|
|
102
129
|
balance_res = self.usdc.functions.balanceOf(address).call()
|
|
103
130
|
return float(balance_res / 1e6)
|
|
104
131
|
|
|
105
|
-
def get_token_balance(
|
|
132
|
+
def get_token_balance(
|
|
133
|
+
self, token_id: str, address: EthAddress | None = None
|
|
134
|
+
) -> float:
|
|
106
135
|
"""Get the token balance of the given address."""
|
|
107
136
|
if address is None:
|
|
108
|
-
address = self.exchange.functions.getPolyProxyWalletAddress(
|
|
109
|
-
|
|
137
|
+
address = self.exchange.functions.getPolyProxyWalletAddress(
|
|
138
|
+
self.account.address
|
|
139
|
+
).call()
|
|
140
|
+
balance_res = self.conditional_tokens.functions.balanceOf(
|
|
141
|
+
address, int(token_id)
|
|
142
|
+
).call()
|
|
110
143
|
return float(balance_res / 1e6)
|
|
111
144
|
|
|
112
145
|
def get_token_complement(self, token_id: str) -> Optional[str]:
|
|
113
146
|
"""Get the complement of the given token."""
|
|
114
147
|
try:
|
|
115
|
-
return str(
|
|
148
|
+
return str(
|
|
149
|
+
self.neg_risk_exchange.functions.getComplement(int(token_id)).call()
|
|
150
|
+
)
|
|
116
151
|
except ContractCustomError as e:
|
|
117
152
|
if e.args[0] in CUSTOM_ERROR_DICT:
|
|
118
153
|
try:
|
|
119
|
-
return str(
|
|
154
|
+
return str(
|
|
155
|
+
self.exchange.functions.getComplement(int(token_id)).call()
|
|
156
|
+
)
|
|
120
157
|
except ContractCustomError as e2:
|
|
121
158
|
if e2.args[0] in CUSTOM_ERROR_DICT:
|
|
122
159
|
msg = f"{CUSTOM_ERROR_DICT[e2.args[0]]}"
|
|
@@ -132,71 +169,90 @@ class PolymarketWeb3Client:
|
|
|
132
169
|
outcomeSlotCount is represented by the last two digits of question id). Returns a keccak256 hash of
|
|
133
170
|
the oracle and question id.
|
|
134
171
|
"""
|
|
135
|
-
return
|
|
172
|
+
return (
|
|
173
|
+
"0x"
|
|
174
|
+
+ self.neg_risk_adapter.functions.getConditionId(question_id).call().hex()
|
|
175
|
+
)
|
|
136
176
|
|
|
137
|
-
def split_position(
|
|
177
|
+
def split_position(
|
|
178
|
+
self, condition_id: Keccak256, amount: int, neg_risk: bool = True
|
|
179
|
+
):
|
|
138
180
|
"""Splits usdc into two complementary positions of equal size."""
|
|
139
181
|
nonce = self.w3.eth.get_transaction_count(self.account.address)
|
|
140
182
|
amount = int(amount * 1e6)
|
|
141
183
|
|
|
142
184
|
proxy_txn = {
|
|
143
185
|
"typeCode": 1,
|
|
144
|
-
"to": self.neg_risk_adapter_address
|
|
186
|
+
"to": self.neg_risk_adapter_address
|
|
187
|
+
if neg_risk
|
|
188
|
+
else self.conditional_tokens_address,
|
|
145
189
|
"value": 0,
|
|
146
190
|
"data": self._encode_split(condition_id, amount),
|
|
147
191
|
}
|
|
148
192
|
|
|
149
193
|
# Send transaction through proxy factory
|
|
150
|
-
txn_data = self.proxy_factory.functions.proxy([proxy_txn]).build_transaction(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
194
|
+
txn_data = self.proxy_factory.functions.proxy([proxy_txn]).build_transaction(
|
|
195
|
+
{
|
|
196
|
+
"nonce": nonce,
|
|
197
|
+
"gasPrice": int(1.05 * self.w3.eth.gas_price),
|
|
198
|
+
"gas": 1000000,
|
|
199
|
+
"from": self.account.address,
|
|
200
|
+
}
|
|
201
|
+
)
|
|
156
202
|
|
|
157
203
|
# Sign and send transaction
|
|
158
204
|
signed_txn = self.account.sign_transaction(txn_data)
|
|
159
|
-
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
|
|
205
|
+
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
|
|
206
|
+
tx_hash_hex = tx_hash.hex()
|
|
160
207
|
|
|
161
|
-
print(f"Txn hash: {
|
|
208
|
+
print(f"Txn hash: {tx_hash_hex}")
|
|
162
209
|
|
|
163
210
|
# Wait for transaction to be mined
|
|
164
211
|
self.w3.eth.wait_for_transaction_receipt(tx_hash)
|
|
165
212
|
|
|
166
213
|
print("Done!")
|
|
167
214
|
|
|
168
|
-
def merge_position(
|
|
215
|
+
def merge_position(
|
|
216
|
+
self, condition_id: Keccak256, amount: int, neg_risk: bool = True
|
|
217
|
+
):
|
|
169
218
|
"""Merges two complementary positions into usdc."""
|
|
170
219
|
nonce = self.w3.eth.get_transaction_count(self.account.address)
|
|
171
220
|
amount = int(amount * 1e6)
|
|
172
221
|
|
|
173
222
|
proxy_txn = {
|
|
174
223
|
"typeCode": 1,
|
|
175
|
-
"to": self.neg_risk_adapter_address
|
|
224
|
+
"to": self.neg_risk_adapter_address
|
|
225
|
+
if neg_risk
|
|
226
|
+
else self.conditional_tokens_address,
|
|
176
227
|
"value": 0,
|
|
177
228
|
"data": self._encode_merge(condition_id, amount),
|
|
178
229
|
}
|
|
179
230
|
|
|
180
231
|
# Send transaction through proxy factory
|
|
181
|
-
txn_data = self.proxy_factory.functions.proxy([proxy_txn]).build_transaction(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
232
|
+
txn_data = self.proxy_factory.functions.proxy([proxy_txn]).build_transaction(
|
|
233
|
+
{
|
|
234
|
+
"nonce": nonce,
|
|
235
|
+
"gasPrice": int(1.05 * self.w3.eth.gas_price),
|
|
236
|
+
"gas": 1000000,
|
|
237
|
+
"from": self.account.address,
|
|
238
|
+
}
|
|
239
|
+
)
|
|
187
240
|
|
|
188
241
|
# Sign and send transaction
|
|
189
242
|
signed_txn = self.account.sign_transaction(txn_data)
|
|
190
|
-
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
|
|
243
|
+
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
|
|
244
|
+
tx_hash_hex = tx_hash.hex()
|
|
191
245
|
|
|
192
|
-
print(f"Txn hash: {
|
|
246
|
+
print(f"Txn hash: {tx_hash_hex}")
|
|
193
247
|
|
|
194
248
|
# Wait for transaction to be mined
|
|
195
249
|
self.w3.eth.wait_for_transaction_receipt(tx_hash)
|
|
196
250
|
|
|
197
251
|
print("Done!")
|
|
198
252
|
|
|
199
|
-
def redeem_position(
|
|
253
|
+
def redeem_position(
|
|
254
|
+
self, condition_id: Keccak256, amounts: list[float], neg_risk: bool = True
|
|
255
|
+
):
|
|
200
256
|
"""
|
|
201
257
|
Redeem a position into usdc.
|
|
202
258
|
|
|
@@ -209,31 +265,40 @@ class PolymarketWeb3Client:
|
|
|
209
265
|
|
|
210
266
|
proxy_txn = {
|
|
211
267
|
"typeCode": 1,
|
|
212
|
-
"to": self.neg_risk_adapter_address
|
|
268
|
+
"to": self.neg_risk_adapter_address
|
|
269
|
+
if neg_risk
|
|
270
|
+
else self.conditional_tokens_address,
|
|
213
271
|
"value": 0,
|
|
214
|
-
"data": self._encode_redeem_neg_risk(condition_id, amounts)
|
|
272
|
+
"data": self._encode_redeem_neg_risk(condition_id, amounts)
|
|
273
|
+
if neg_risk
|
|
274
|
+
else self._encode_redeem(condition_id),
|
|
215
275
|
}
|
|
216
276
|
|
|
217
277
|
# Send transaction through proxy factory
|
|
218
|
-
txn_data = self.proxy_factory.functions.proxy([proxy_txn]).build_transaction(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
278
|
+
txn_data = self.proxy_factory.functions.proxy([proxy_txn]).build_transaction(
|
|
279
|
+
{
|
|
280
|
+
"nonce": nonce,
|
|
281
|
+
"gasPrice": int(1.05 * self.w3.eth.gas_price),
|
|
282
|
+
"gas": 1000000,
|
|
283
|
+
"from": self.account.address,
|
|
284
|
+
}
|
|
285
|
+
)
|
|
224
286
|
|
|
225
287
|
# Sign and send transaction
|
|
226
288
|
signed_txn = self.account.sign_transaction(txn_data)
|
|
227
|
-
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
|
|
289
|
+
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
|
|
290
|
+
tx_hash_hex = tx_hash.hex()
|
|
228
291
|
|
|
229
|
-
print(f"Txn hash: {
|
|
292
|
+
print(f"Txn hash: {tx_hash_hex}")
|
|
230
293
|
|
|
231
294
|
# Wait for transaction to be mined
|
|
232
295
|
self.w3.eth.wait_for_transaction_receipt(tx_hash)
|
|
233
296
|
|
|
234
297
|
print("Done!")
|
|
235
298
|
|
|
236
|
-
def convert_positions(
|
|
299
|
+
def convert_positions(
|
|
300
|
+
self, question_ids: list[Keccak256], neg_risk_market_id: Keccak256, amount: int
|
|
301
|
+
):
|
|
237
302
|
nonce = self.w3.eth.get_transaction_count(self.account.address)
|
|
238
303
|
amount = int(amount * 1e6)
|
|
239
304
|
|
|
@@ -241,20 +306,26 @@ class PolymarketWeb3Client:
|
|
|
241
306
|
"typeCode": 1,
|
|
242
307
|
"to": self.neg_risk_adapter_address,
|
|
243
308
|
"value": 0,
|
|
244
|
-
"data": self._encode_convert(
|
|
309
|
+
"data": self._encode_convert(
|
|
310
|
+
neg_risk_market_id, get_index_set(question_ids), amount
|
|
311
|
+
),
|
|
245
312
|
}
|
|
246
313
|
|
|
247
|
-
txn_data = self.proxy_factory.functions.proxy([proxy_txn]).build_transaction(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
314
|
+
txn_data = self.proxy_factory.functions.proxy([proxy_txn]).build_transaction(
|
|
315
|
+
{
|
|
316
|
+
"nonce": nonce,
|
|
317
|
+
"gasPrice": int(1.05 * self.w3.eth.gas_price),
|
|
318
|
+
"gas": 1000000,
|
|
319
|
+
"from": self.account.address,
|
|
320
|
+
}
|
|
321
|
+
)
|
|
253
322
|
|
|
323
|
+
# Sign and send transaction
|
|
254
324
|
signed_txn = self.account.sign_transaction(txn_data)
|
|
255
|
-
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
|
|
325
|
+
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
|
|
326
|
+
tx_hash_hex = tx_hash.hex()
|
|
256
327
|
|
|
257
|
-
print(f"Txn hash: {
|
|
328
|
+
print(f"Txn hash: {tx_hash_hex}")
|
|
258
329
|
|
|
259
330
|
# Wait for transaction to be mined
|
|
260
331
|
self.w3.eth.wait_for_transaction_receipt(tx_hash)
|
|
@@ -61,6 +61,7 @@ def _process_market_event(event):
|
|
|
61
61
|
print(e.errors())
|
|
62
62
|
print(event.json)
|
|
63
63
|
|
|
64
|
+
|
|
64
65
|
def _process_user_event(event):
|
|
65
66
|
try:
|
|
66
67
|
message = event.json
|
|
@@ -75,6 +76,7 @@ def _process_user_event(event):
|
|
|
75
76
|
print(event.text)
|
|
76
77
|
print(e.errors(), "\n")
|
|
77
78
|
|
|
79
|
+
|
|
78
80
|
def _process_live_data_event(event):
|
|
79
81
|
try:
|
|
80
82
|
message = event.json
|
|
@@ -87,7 +89,12 @@ def _process_live_data_event(event):
|
|
|
87
89
|
print(CommentEvent(**message), "\n")
|
|
88
90
|
case "reaction_created" | "reaction_removed":
|
|
89
91
|
print(ReactionEvent(**message), "\n")
|
|
90
|
-
case
|
|
92
|
+
case (
|
|
93
|
+
"request_created"
|
|
94
|
+
| "request_edited"
|
|
95
|
+
| "request_canceled"
|
|
96
|
+
| "request_expired"
|
|
97
|
+
):
|
|
91
98
|
print(RequestEvent(**message), "\n")
|
|
92
99
|
case "quote_created" | "quote_edited" | "quote_canceled" | "quote_expired":
|
|
93
100
|
print(QuoteEvent(**message), "\n")
|
|
@@ -117,13 +124,16 @@ def _process_live_data_event(event):
|
|
|
117
124
|
print(e.errors(), "\n")
|
|
118
125
|
print(event.text)
|
|
119
126
|
|
|
127
|
+
|
|
120
128
|
class PolymarketWebsocketsClient:
|
|
121
129
|
def __init__(self):
|
|
122
130
|
self.url_market = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
|
|
123
131
|
self.url_user = "wss://ws-subscriptions-clob.polymarket.com/ws/user"
|
|
124
132
|
self.url_live_data = "wss://ws-live-data.polymarket.com"
|
|
125
133
|
|
|
126
|
-
def market_socket(
|
|
134
|
+
def market_socket(
|
|
135
|
+
self, token_ids: list[str], process_event: Callable = _process_market_event
|
|
136
|
+
):
|
|
127
137
|
"""
|
|
128
138
|
Connect to the market websocket and subscribe to market events for specific token IDs.
|
|
129
139
|
|
|
@@ -142,7 +152,9 @@ class PolymarketWebsocketsClient:
|
|
|
142
152
|
elif event.name == "text":
|
|
143
153
|
process_event(event)
|
|
144
154
|
|
|
145
|
-
def user_socket(
|
|
155
|
+
def user_socket(
|
|
156
|
+
self, creds: ApiCreds, process_event: Callable = _process_user_event
|
|
157
|
+
):
|
|
146
158
|
"""
|
|
147
159
|
Connect to the user websocket and subscribe to user events.
|
|
148
160
|
|
|
@@ -161,7 +173,12 @@ class PolymarketWebsocketsClient:
|
|
|
161
173
|
elif event.name == "text":
|
|
162
174
|
process_event(event)
|
|
163
175
|
|
|
164
|
-
def live_data_socket(
|
|
176
|
+
def live_data_socket(
|
|
177
|
+
self,
|
|
178
|
+
subscriptions: list[dict[str, Any]],
|
|
179
|
+
process_event: Callable = _process_live_data_event,
|
|
180
|
+
creds: Optional[ApiCreds] = None,
|
|
181
|
+
):
|
|
165
182
|
# info on how to subscribe found at https://github.com/Polymarket/real-time-data-client?tab=readme-ov-file#subscribe
|
|
166
183
|
"""
|
|
167
184
|
Connect to the live data websocket and subscribe to specified events.
|
|
@@ -175,13 +192,13 @@ class PolymarketWebsocketsClient:
|
|
|
175
192
|
websocket = WebSocket(self.url_live_data)
|
|
176
193
|
|
|
177
194
|
needs_auth = any(sub.get("topic") == "clob_user" for sub in subscriptions)
|
|
178
|
-
if needs_auth and creds is None:
|
|
179
|
-
msg = "ApiCreds credentials are required for the clob_user topic subscriptions"
|
|
180
|
-
raise AuthenticationRequiredError(msg)
|
|
181
195
|
|
|
182
196
|
for event in persist(websocket):
|
|
183
197
|
if event.name == "ready":
|
|
184
198
|
if needs_auth:
|
|
199
|
+
if creds is None:
|
|
200
|
+
msg = "ApiCreds credentials are required for the clob_user topic subscriptions"
|
|
201
|
+
raise AuthenticationRequiredError(msg)
|
|
185
202
|
subscriptions_with_creds = []
|
|
186
203
|
for sub in subscriptions:
|
|
187
204
|
if sub.get("topic") == "clob_user":
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# python
|
|
2
|
+
"""
|
|
3
|
+
Type definitions for Polymarket APIs.
|
|
4
|
+
|
|
5
|
+
This module contains all the Pydantic models and type definitions used across
|
|
6
|
+
the Polymarket APIs.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .clob_types import (
|
|
10
|
+
ApiCreds,
|
|
11
|
+
AssetType,
|
|
12
|
+
BidAsk,
|
|
13
|
+
BookParams,
|
|
14
|
+
ClobMarket,
|
|
15
|
+
ContractConfig,
|
|
16
|
+
CreateOrderOptions,
|
|
17
|
+
DailyEarnedReward,
|
|
18
|
+
MarketOrderArgs,
|
|
19
|
+
MarketRewards,
|
|
20
|
+
Midpoint,
|
|
21
|
+
OpenOrder,
|
|
22
|
+
OrderArgs,
|
|
23
|
+
OrderBookSummary,
|
|
24
|
+
OrderCancelResponse,
|
|
25
|
+
OrderPostResponse,
|
|
26
|
+
OrderType,
|
|
27
|
+
PaginatedResponse,
|
|
28
|
+
PartialCreateOrderOptions,
|
|
29
|
+
PolygonTrade,
|
|
30
|
+
PostOrdersArgs,
|
|
31
|
+
Price,
|
|
32
|
+
PriceHistory,
|
|
33
|
+
RewardMarket,
|
|
34
|
+
Spread,
|
|
35
|
+
TickSize,
|
|
36
|
+
Token,
|
|
37
|
+
TokenBidAsk,
|
|
38
|
+
TokenBidAskDict,
|
|
39
|
+
TokenValue,
|
|
40
|
+
TokenValueDict,
|
|
41
|
+
)
|
|
42
|
+
from .common import (
|
|
43
|
+
EmptyString,
|
|
44
|
+
EthAddress,
|
|
45
|
+
FlexibleDatetime,
|
|
46
|
+
Keccak256,
|
|
47
|
+
TimeseriesPoint,
|
|
48
|
+
)
|
|
49
|
+
from .data_types import (
|
|
50
|
+
Activity,
|
|
51
|
+
Holder,
|
|
52
|
+
HolderResponse,
|
|
53
|
+
Position,
|
|
54
|
+
Trade,
|
|
55
|
+
User,
|
|
56
|
+
UserMetric,
|
|
57
|
+
UserRank,
|
|
58
|
+
ValueResponse,
|
|
59
|
+
)
|
|
60
|
+
from .gamma_types import (
|
|
61
|
+
ClobReward,
|
|
62
|
+
Event,
|
|
63
|
+
GammaMarket,
|
|
64
|
+
Pagination,
|
|
65
|
+
Series,
|
|
66
|
+
Tag,
|
|
67
|
+
)
|
|
68
|
+
from .websockets_types import (
|
|
69
|
+
ActivityOrderMatchEvent,
|
|
70
|
+
ActivityTradeEvent,
|
|
71
|
+
CommentEvent,
|
|
72
|
+
CryptoPriceSubscribeEvent,
|
|
73
|
+
CryptoPriceUpdateEvent,
|
|
74
|
+
ErrorEvent,
|
|
75
|
+
LastTradePriceEvent,
|
|
76
|
+
LiveDataLastTradePriceEvent,
|
|
77
|
+
LiveDataOrderBookSummaryEvent,
|
|
78
|
+
LiveDataOrderEvent,
|
|
79
|
+
LiveDataPriceChangeEvent,
|
|
80
|
+
LiveDataTickSizeChangeEvent,
|
|
81
|
+
LiveDataTradeEvent,
|
|
82
|
+
MarketStatusChangeEvent,
|
|
83
|
+
OrderBookSummaryEvent,
|
|
84
|
+
OrderEvent,
|
|
85
|
+
PriceChangeEvent,
|
|
86
|
+
QuoteEvent,
|
|
87
|
+
ReactionEvent,
|
|
88
|
+
RequestEvent,
|
|
89
|
+
TickSizeChangeEvent,
|
|
90
|
+
TradeEvent,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
__all__ = [
|
|
94
|
+
"Activity",
|
|
95
|
+
"ActivityOrderMatchEvent",
|
|
96
|
+
"ActivityTradeEvent",
|
|
97
|
+
"ApiCreds",
|
|
98
|
+
"AssetType",
|
|
99
|
+
"BidAsk",
|
|
100
|
+
"BookParams",
|
|
101
|
+
"ClobMarket",
|
|
102
|
+
"ClobReward",
|
|
103
|
+
"CommentEvent",
|
|
104
|
+
"ContractConfig",
|
|
105
|
+
"CreateOrderOptions",
|
|
106
|
+
"CryptoPriceSubscribeEvent",
|
|
107
|
+
"CryptoPriceUpdateEvent",
|
|
108
|
+
"DailyEarnedReward",
|
|
109
|
+
"EmptyString",
|
|
110
|
+
"ErrorEvent",
|
|
111
|
+
"EthAddress",
|
|
112
|
+
"Event",
|
|
113
|
+
"FlexibleDatetime",
|
|
114
|
+
"GammaMarket",
|
|
115
|
+
"Holder",
|
|
116
|
+
"HolderResponse",
|
|
117
|
+
"Keccak256",
|
|
118
|
+
"LastTradePriceEvent",
|
|
119
|
+
"LiveDataLastTradePriceEvent",
|
|
120
|
+
"LiveDataOrderBookSummaryEvent",
|
|
121
|
+
"LiveDataOrderEvent",
|
|
122
|
+
"LiveDataPriceChangeEvent",
|
|
123
|
+
"LiveDataTickSizeChangeEvent",
|
|
124
|
+
"LiveDataTradeEvent",
|
|
125
|
+
"MarketOrderArgs",
|
|
126
|
+
"MarketRewards",
|
|
127
|
+
"MarketStatusChangeEvent",
|
|
128
|
+
"Midpoint",
|
|
129
|
+
"OpenOrder",
|
|
130
|
+
"OrderArgs",
|
|
131
|
+
"OrderBookSummary",
|
|
132
|
+
"OrderBookSummaryEvent",
|
|
133
|
+
"OrderCancelResponse",
|
|
134
|
+
"OrderEvent",
|
|
135
|
+
"OrderPostResponse",
|
|
136
|
+
"OrderType",
|
|
137
|
+
"PaginatedResponse",
|
|
138
|
+
"Pagination",
|
|
139
|
+
"PartialCreateOrderOptions",
|
|
140
|
+
"PolygonTrade",
|
|
141
|
+
"Position",
|
|
142
|
+
"PostOrdersArgs",
|
|
143
|
+
"Price",
|
|
144
|
+
"PriceChangeEvent",
|
|
145
|
+
"PriceHistory",
|
|
146
|
+
"QuoteEvent",
|
|
147
|
+
"ReactionEvent",
|
|
148
|
+
"RequestEvent",
|
|
149
|
+
"RewardMarket",
|
|
150
|
+
"Series",
|
|
151
|
+
"Spread",
|
|
152
|
+
"Tag",
|
|
153
|
+
"TickSize",
|
|
154
|
+
"TickSizeChangeEvent",
|
|
155
|
+
"TimeseriesPoint",
|
|
156
|
+
"Token",
|
|
157
|
+
"TokenBidAsk",
|
|
158
|
+
"TokenBidAskDict",
|
|
159
|
+
"TokenValue",
|
|
160
|
+
"TokenValueDict",
|
|
161
|
+
"Trade",
|
|
162
|
+
"TradeEvent",
|
|
163
|
+
"User",
|
|
164
|
+
"UserMetric",
|
|
165
|
+
"UserRank",
|
|
166
|
+
"ValueResponse",
|
|
167
|
+
]
|