polymarket-apis 0.2.2__py3-none-any.whl → 0.2.4__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/clients/clob_client.py +37 -3
- polymarket_apis/clients/gamma_client.py +84 -64
- polymarket_apis/clients/graphql_client.py +182 -0
- polymarket_apis/clients/web3_client.py +1 -1
- polymarket_apis/clients/websockets_client.py +102 -29
- polymarket_apis/types/clob_types.py +1 -1
- polymarket_apis/types/common.py +4 -2
- polymarket_apis/types/gamma_types.py +183 -142
- polymarket_apis/types/websockets_types.py +156 -42
- polymarket_apis/utilities/config.py +12 -0
- polymarket_apis/utilities/endpoints.py +1 -0
- polymarket_apis/utilities/exceptions.py +6 -0
- polymarket_apis/utilities/headers.py +1 -1
- {polymarket_apis-0.2.2.dist-info → polymarket_apis-0.2.4.dist-info}/METADATA +1 -1
- {polymarket_apis-0.2.2.dist-info → polymarket_apis-0.2.4.dist-info}/RECORD +16 -15
- {polymarket_apis-0.2.2.dist-info → polymarket_apis-0.2.4.dist-info}/WHEEL +0 -0
|
@@ -48,6 +48,7 @@ from ..utilities.endpoints import (
|
|
|
48
48
|
DELETE_API_KEY,
|
|
49
49
|
DERIVE_API_KEY,
|
|
50
50
|
GET_API_KEYS,
|
|
51
|
+
GET_FEE_RATE,
|
|
51
52
|
GET_LAST_TRADE_PRICE,
|
|
52
53
|
GET_LAST_TRADES_PRICES,
|
|
53
54
|
GET_MARKET,
|
|
@@ -70,6 +71,7 @@ from ..utilities.endpoints import (
|
|
|
70
71
|
TRADES,
|
|
71
72
|
)
|
|
72
73
|
from ..utilities.exceptions import (
|
|
74
|
+
InvalidFeeRateError,
|
|
73
75
|
InvalidPriceError,
|
|
74
76
|
InvalidTickSizeError,
|
|
75
77
|
LiquidityError,
|
|
@@ -111,6 +113,7 @@ class PolymarketClobClient:
|
|
|
111
113
|
# local cache
|
|
112
114
|
self.__tick_sizes = {}
|
|
113
115
|
self.__neg_risk = {}
|
|
116
|
+
self.__fee_rates = {}
|
|
114
117
|
|
|
115
118
|
def _build_url(self, endpoint: str) -> str:
|
|
116
119
|
return urljoin(self.base_url, endpoint)
|
|
@@ -183,6 +186,18 @@ class PolymarketClobClient:
|
|
|
183
186
|
|
|
184
187
|
return self.__neg_risk[token_id]
|
|
185
188
|
|
|
189
|
+
def get_fee_rate_bps(self, token_id: str) -> int:
|
|
190
|
+
if token_id in self.__fee_rates:
|
|
191
|
+
return self.__fee_rates[token_id]
|
|
192
|
+
|
|
193
|
+
params = {"token_id": token_id}
|
|
194
|
+
response = self.client.get(self._build_url(GET_FEE_RATE), params=params)
|
|
195
|
+
response.raise_for_status()
|
|
196
|
+
fee_rate = response.json().get("base_fee") or 0
|
|
197
|
+
self.__fee_rates[token_id] = fee_rate
|
|
198
|
+
|
|
199
|
+
return fee_rate
|
|
200
|
+
|
|
186
201
|
def __resolve_tick_size(
|
|
187
202
|
self, token_id: str, tick_size: TickSize = None,
|
|
188
203
|
) -> TickSize:
|
|
@@ -195,6 +210,17 @@ class PolymarketClobClient:
|
|
|
195
210
|
tick_size = min_tick_size
|
|
196
211
|
return tick_size
|
|
197
212
|
|
|
213
|
+
def __resolve_fee_rate(
|
|
214
|
+
self, token_id: str, user_fee_rate: Optional[int] = None,
|
|
215
|
+
) -> int:
|
|
216
|
+
market_fee_rate_bps = self.get_fee_rate_bps(token_id)
|
|
217
|
+
# If both fee rate on the market and the user supplied fee rate are non-zero, validate that they match
|
|
218
|
+
# else return the market fee rate
|
|
219
|
+
if market_fee_rate_bps > 0 and user_fee_rate is not None and user_fee_rate > 0 and user_fee_rate != market_fee_rate_bps:
|
|
220
|
+
msg = f"invalid user provided fee rate: ({user_fee_rate}), fee rate for the market must be {market_fee_rate_bps}"
|
|
221
|
+
raise InvalidFeeRateError(msg)
|
|
222
|
+
return market_fee_rate_bps
|
|
223
|
+
|
|
198
224
|
def get_midpoint(self, token_id: str) -> Midpoint:
|
|
199
225
|
"""Get the mid-market price for the given token."""
|
|
200
226
|
params = {"token_id": token_id}
|
|
@@ -406,6 +432,10 @@ class PolymarketClobClient:
|
|
|
406
432
|
else self.get_neg_risk(order_args.token_id)
|
|
407
433
|
)
|
|
408
434
|
|
|
435
|
+
# fee rate
|
|
436
|
+
fee_rate_bps = self.__resolve_fee_rate(order_args.token_id, order_args.fee_rate_bps)
|
|
437
|
+
order_args.fee_rate_bps = fee_rate_bps
|
|
438
|
+
|
|
409
439
|
return self.builder.create_order(
|
|
410
440
|
order_args,
|
|
411
441
|
CreateOrderOptions(
|
|
@@ -416,7 +446,7 @@ class PolymarketClobClient:
|
|
|
416
446
|
|
|
417
447
|
def post_order(self, order: SignedOrder, order_type: OrderType = OrderType.GTC) -> Optional[OrderPostResponse]:
|
|
418
448
|
"""Posts a SignedOrder."""
|
|
419
|
-
body = order_to_json(order, self.creds.
|
|
449
|
+
body = order_to_json(order, self.creds.key, order_type)
|
|
420
450
|
headers = create_level_2_headers(
|
|
421
451
|
self.signer,
|
|
422
452
|
self.creds,
|
|
@@ -444,7 +474,7 @@ class PolymarketClobClient:
|
|
|
444
474
|
|
|
445
475
|
def post_orders(self, args: list[PostOrdersArgs]):
|
|
446
476
|
"""Posts multiple SignedOrders at once."""
|
|
447
|
-
body = [order_to_json(arg.order, self.creds.
|
|
477
|
+
body = [order_to_json(arg.order, self.creds.key, arg.order_type) for arg in args]
|
|
448
478
|
headers = create_level_2_headers(
|
|
449
479
|
self.signer,
|
|
450
480
|
self.creds,
|
|
@@ -526,6 +556,10 @@ class PolymarketClobClient:
|
|
|
526
556
|
else self.get_neg_risk(order_args.token_id)
|
|
527
557
|
)
|
|
528
558
|
|
|
559
|
+
# fee rate
|
|
560
|
+
fee_rate_bps = self.__resolve_fee_rate(order_args.token_id, order_args.fee_rate_bps)
|
|
561
|
+
order_args.fee_rate_bps = fee_rate_bps
|
|
562
|
+
|
|
529
563
|
return self.builder.create_market_order(
|
|
530
564
|
order_args,
|
|
531
565
|
CreateOrderOptions(
|
|
@@ -614,7 +648,7 @@ class PolymarketClobClient:
|
|
|
614
648
|
|
|
615
649
|
def get_trades(
|
|
616
650
|
self,
|
|
617
|
-
condition_id: Keccak256
|
|
651
|
+
condition_id: Optional[Keccak256] = None,
|
|
618
652
|
token_id: Optional[str] = None,
|
|
619
653
|
trade_id: Optional[str] = None,
|
|
620
654
|
before: Optional[datetime] = None,
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import random
|
|
3
|
+
import string
|
|
2
4
|
from datetime import datetime
|
|
3
|
-
from typing import Optional, Union
|
|
5
|
+
from typing import Literal, Optional, Union
|
|
4
6
|
from urllib.parse import urljoin
|
|
5
7
|
|
|
6
8
|
import httpx
|
|
7
9
|
|
|
8
|
-
from ..types.gamma_types import Event,
|
|
10
|
+
from ..types.gamma_types import Event, EventList, GammaMarket
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def generate_random_id(length=16):
|
|
14
|
+
characters = string.ascii_letters + string.digits
|
|
15
|
+
random_id = "".join(random.choices(characters, k=length))
|
|
16
|
+
return random_id
|
|
9
17
|
|
|
10
18
|
|
|
11
19
|
class PolymarketGammaClient:
|
|
@@ -227,82 +235,94 @@ class PolymarketGammaClient:
|
|
|
227
235
|
|
|
228
236
|
return events
|
|
229
237
|
|
|
230
|
-
def search_events(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
238
|
+
def search_events(
|
|
239
|
+
self,
|
|
240
|
+
query: str,
|
|
241
|
+
active: bool = True,
|
|
242
|
+
status: Optional[Literal["active", "resolved"]] = "active",
|
|
243
|
+
sort: Literal["volume", "volume_24hr", "liquidity", "start_date", "end_date", "competitive"] = "volume_24hr",
|
|
244
|
+
page: int = 1,
|
|
245
|
+
limit_per_type: int = 50, # max is 50
|
|
246
|
+
) -> EventList:
|
|
247
|
+
"""Search for events by query. Should emulate the website search function."""
|
|
248
|
+
params = {"q": query,"page": page, "limit_per_type": limit_per_type, "events_status": status, "active": active, "presets": "EventsTitle"}
|
|
249
|
+
if sort:
|
|
250
|
+
params["sort"] = sort
|
|
251
|
+
if sort == "end_date":
|
|
252
|
+
params["ascending"] = "true"
|
|
253
|
+
response = self.client.get(self._build_url("/public-search"), params=params)
|
|
234
254
|
response.raise_for_status()
|
|
235
|
-
return
|
|
255
|
+
return EventList(**response.json())
|
|
236
256
|
|
|
237
|
-
def
|
|
238
|
-
|
|
257
|
+
def grok_event_summary(self, event_slug: str):
|
|
258
|
+
json_payload = {
|
|
259
|
+
"id": generate_random_id(),
|
|
260
|
+
"messages": [{"role": "user", "content": "", "parts": []}],
|
|
261
|
+
}
|
|
239
262
|
|
|
240
263
|
params = {
|
|
241
|
-
"
|
|
242
|
-
"eventTitle": market.question,
|
|
243
|
-
"odds": market.outcome_prices[0],
|
|
244
|
-
"marketDescription": market.description,
|
|
245
|
-
"isNegRisk": market.neg_risk,
|
|
264
|
+
"prompt": event_slug,
|
|
246
265
|
}
|
|
247
266
|
|
|
248
|
-
with self.client.stream(
|
|
267
|
+
with self.client.stream(
|
|
268
|
+
method="POST",
|
|
269
|
+
url="https://polymarket.com/api/grok/event-summary",
|
|
270
|
+
params=params,
|
|
271
|
+
json=json_payload,
|
|
272
|
+
) as stream:
|
|
249
273
|
messages = []
|
|
250
274
|
citations = []
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
275
|
+
seen_urls = set()
|
|
276
|
+
|
|
277
|
+
for line_bytes in stream.iter_lines():
|
|
278
|
+
line = (
|
|
279
|
+
line_bytes.decode() if isinstance(line_bytes, bytes) else line_bytes
|
|
280
|
+
)
|
|
281
|
+
if line.startswith("__SOURCES__:"):
|
|
282
|
+
sources_json_str = line[len("__SOURCES__:") :]
|
|
283
|
+
try:
|
|
284
|
+
sources_obj = json.loads(sources_json_str)
|
|
285
|
+
for source in sources_obj.get("sources", []):
|
|
286
|
+
url = source.get("url")
|
|
287
|
+
if url and url not in seen_urls:
|
|
288
|
+
citations.append(source)
|
|
289
|
+
seen_urls.add(url)
|
|
290
|
+
except json.JSONDecodeError:
|
|
291
|
+
pass
|
|
292
|
+
else:
|
|
293
|
+
messages.append(line)
|
|
294
|
+
print(line, end="") # or handle message text as needed
|
|
268
295
|
|
|
269
|
-
# After
|
|
296
|
+
# After reading streamed lines:
|
|
270
297
|
if citations:
|
|
271
|
-
print("\n\
|
|
272
|
-
for
|
|
273
|
-
print(f"- {
|
|
298
|
+
print("\n\nSources:")
|
|
299
|
+
for source in citations:
|
|
300
|
+
print(f"- {source.get('url', 'Unknown URL')}")
|
|
274
301
|
|
|
275
|
-
def
|
|
276
|
-
|
|
277
|
-
|
|
302
|
+
def grok_election_market_explanation(self, candidate_name: str, election_title: str):
|
|
303
|
+
text = f"Provide candidate information for {candidate_name} in the {election_title} on Polymarket."
|
|
304
|
+
json_payload = {
|
|
305
|
+
"id": generate_random_id(),
|
|
306
|
+
"messages": [
|
|
307
|
+
{
|
|
308
|
+
"role": "user",
|
|
309
|
+
"content": text,
|
|
310
|
+
"parts": [{"type": "text", "text": text}],
|
|
311
|
+
},
|
|
312
|
+
],
|
|
278
313
|
}
|
|
279
314
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
line_str = line
|
|
286
|
-
if line_str.startswith("data: "):
|
|
287
|
-
json_part = line_str[len("data: "):]
|
|
288
|
-
try:
|
|
289
|
-
data = json.loads(json_part)
|
|
290
|
-
# Extract content if present
|
|
291
|
-
content = data.get("choices", [{}])[0].get("delta", {}).get("content", "")
|
|
292
|
-
if content:
|
|
293
|
-
messages.append(content)
|
|
294
|
-
print(content, end="") # Stream content
|
|
295
|
-
# Extract citations if present
|
|
296
|
-
if "citations" in data:
|
|
297
|
-
citations.extend(data["citations"])
|
|
298
|
-
except json.JSONDecodeError:
|
|
299
|
-
pass
|
|
315
|
+
response = self.client.post(
|
|
316
|
+
url="https://polymarket.com/api/grok/election-market-explanation",
|
|
317
|
+
json=json_payload,
|
|
318
|
+
)
|
|
319
|
+
response.raise_for_status()
|
|
300
320
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
321
|
+
parts = [p.strip() for p in response.text.split("**") if p.strip()]
|
|
322
|
+
for i, part in enumerate(parts):
|
|
323
|
+
if ":" in part and i != 0:
|
|
324
|
+
print()
|
|
325
|
+
print(part)
|
|
306
326
|
|
|
307
327
|
def __enter__(self):
|
|
308
328
|
return self
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
from typing import Literal, Optional
|
|
2
|
+
|
|
3
|
+
from gql import Client, gql
|
|
4
|
+
from gql.transport.httpx import HTTPXAsyncTransport
|
|
5
|
+
from graphql import GraphQLInputObjectType, GraphQLObjectType
|
|
6
|
+
|
|
7
|
+
from ..utilities.config import GRAPHQL_ENDPOINTS
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PolymarketGraphQLClient:
|
|
11
|
+
def __init__(self,
|
|
12
|
+
endpoint_name: Literal[
|
|
13
|
+
"activity_subgraph",
|
|
14
|
+
"fpmm_subgraph",
|
|
15
|
+
"open_interest_subgraph",
|
|
16
|
+
"orderbook_subgraph",
|
|
17
|
+
"pnl_subgraph",
|
|
18
|
+
"positions_subgraph",
|
|
19
|
+
"sports_oracle_subgraph",
|
|
20
|
+
"wallet_subgraph",
|
|
21
|
+
]):
|
|
22
|
+
if endpoint_name not in GRAPHQL_ENDPOINTS:
|
|
23
|
+
msg = f"Invalid endpoint name: {endpoint_name}. Must be one of {list(GRAPHQL_ENDPOINTS.keys())}"
|
|
24
|
+
raise ValueError(msg)
|
|
25
|
+
endpoint_url = GRAPHQL_ENDPOINTS[endpoint_name]
|
|
26
|
+
self.transport = HTTPXAsyncTransport(url=endpoint_url)
|
|
27
|
+
self.client = Client(transport=self.transport, fetch_schema_from_transport=True)
|
|
28
|
+
self.schema = None
|
|
29
|
+
self.object_types = []
|
|
30
|
+
self.query_fields = []
|
|
31
|
+
self.subscription_fields = []
|
|
32
|
+
self.filter_input_types = []
|
|
33
|
+
|
|
34
|
+
async def _init_schema(self):
|
|
35
|
+
async with self.client as session:
|
|
36
|
+
self.schema = session.schema
|
|
37
|
+
|
|
38
|
+
async def _get_query_fields(self):
|
|
39
|
+
if self.query_fields:
|
|
40
|
+
return self.query_fields
|
|
41
|
+
if not self.schema:
|
|
42
|
+
await self._init_schema()
|
|
43
|
+
self.query_fields = [field for field in self.schema.type_map["Query"].fields if not field.startswith("_")]
|
|
44
|
+
|
|
45
|
+
return self.query_fields
|
|
46
|
+
|
|
47
|
+
async def _get_subscription_fields(self):
|
|
48
|
+
if self.subscription_fields:
|
|
49
|
+
return self.subscription_fields
|
|
50
|
+
if not self.schema:
|
|
51
|
+
await self._init_schema()
|
|
52
|
+
if "Subscription" in self.schema.type_map:
|
|
53
|
+
self.subscription_fields = [field for field in self.schema.type_map["Subscription"].fields if not field.startswith("_")]
|
|
54
|
+
else:
|
|
55
|
+
self.subscription_fields = []
|
|
56
|
+
return self.subscription_fields
|
|
57
|
+
|
|
58
|
+
async def _get_object_types(self):
|
|
59
|
+
if self.object_types:
|
|
60
|
+
return self.object_types
|
|
61
|
+
if not self.schema:
|
|
62
|
+
await self._init_schema()
|
|
63
|
+
for object_name, object in self.schema.type_map.items():
|
|
64
|
+
if type(object) is GraphQLObjectType and not object_name.startswith("_"):
|
|
65
|
+
self.object_types.append(object_name)
|
|
66
|
+
return self.object_types
|
|
67
|
+
|
|
68
|
+
async def _get_filter_input_types(self):
|
|
69
|
+
if self.filter_input_types:
|
|
70
|
+
return self.filter_input_types
|
|
71
|
+
if not self.schema:
|
|
72
|
+
await self._init_schema()
|
|
73
|
+
for object_name, object in self.schema.type_map.items():
|
|
74
|
+
if isinstance(object, GraphQLInputObjectType) and not object_name.startswith("_"):
|
|
75
|
+
self.filter_input_types.append(object_name)
|
|
76
|
+
return self.filter_input_types
|
|
77
|
+
|
|
78
|
+
async def list_queries(self):
|
|
79
|
+
if self.query_fields:
|
|
80
|
+
return self.query_fields
|
|
81
|
+
return await self._get_query_fields()
|
|
82
|
+
|
|
83
|
+
async def list_subscriptions(self):
|
|
84
|
+
if self.subscription_fields:
|
|
85
|
+
return self.subscription_fields
|
|
86
|
+
return await self._get_subscription_fields()
|
|
87
|
+
|
|
88
|
+
async def list_object_types(self):
|
|
89
|
+
if self.object_types:
|
|
90
|
+
return self.object_types
|
|
91
|
+
return await self._get_object_types()
|
|
92
|
+
|
|
93
|
+
async def list_filter_input_types(self):
|
|
94
|
+
if self.filter_input_types:
|
|
95
|
+
return self.filter_input_types
|
|
96
|
+
return await self._get_filter_input_types()
|
|
97
|
+
|
|
98
|
+
async def get_fields(self, object_name: str):
|
|
99
|
+
if self.schema is None:
|
|
100
|
+
await self._init_schema()
|
|
101
|
+
if object_name not in self.schema.type_map:
|
|
102
|
+
msg = "Invalid object name"
|
|
103
|
+
raise ValueError(msg)
|
|
104
|
+
return list(self.schema.type_map[object_name].fields.keys())
|
|
105
|
+
|
|
106
|
+
async def query(
|
|
107
|
+
self,
|
|
108
|
+
endpoint: str,
|
|
109
|
+
fields: list[str],
|
|
110
|
+
filters: Optional[dict] = None,
|
|
111
|
+
relationships: Optional[dict] = None,
|
|
112
|
+
):
|
|
113
|
+
if not self.schema:
|
|
114
|
+
await self._init_schema()
|
|
115
|
+
if not self.query_fields:
|
|
116
|
+
await self._get_query_fields()
|
|
117
|
+
if not self.object_types:
|
|
118
|
+
await self._get_object_types()
|
|
119
|
+
|
|
120
|
+
if endpoint not in self.query_fields:
|
|
121
|
+
msg = f"Invalid endpoint: {endpoint}"
|
|
122
|
+
raise ValueError(msg)
|
|
123
|
+
|
|
124
|
+
endpoint_field = self.schema.type_map["Query"].fields[endpoint]
|
|
125
|
+
required_args = [
|
|
126
|
+
arg_name for arg_name, arg in endpoint_field.args.items()
|
|
127
|
+
if arg.type.to_kwargs().get("required", False)
|
|
128
|
+
]
|
|
129
|
+
missing_args = [arg for arg in required_args if not (filters and arg in filters)]
|
|
130
|
+
if missing_args:
|
|
131
|
+
msg = f"Missing required argument(s) for '{endpoint}': {', '.join(missing_args)}"
|
|
132
|
+
raise ValueError(msg)
|
|
133
|
+
|
|
134
|
+
def build_selection(fields, relationships):
|
|
135
|
+
selections = []
|
|
136
|
+
for field in fields:
|
|
137
|
+
if relationships and field in relationships:
|
|
138
|
+
subfields = relationships[field]
|
|
139
|
+
selections.append(f"{field} {{ {' '.join(subfields)} }}")
|
|
140
|
+
else:
|
|
141
|
+
selections.append(field)
|
|
142
|
+
return " ".join(selections)
|
|
143
|
+
|
|
144
|
+
def build_args(filters):
|
|
145
|
+
"""Build GraphQL arguments, handling both simple and complex where clauses."""
|
|
146
|
+
if not filters:
|
|
147
|
+
return ""
|
|
148
|
+
|
|
149
|
+
arg_strs = []
|
|
150
|
+
for k, v in filters.items():
|
|
151
|
+
if k == "where" and isinstance(v, dict):
|
|
152
|
+
# Handle complex where clause
|
|
153
|
+
where_conditions = []
|
|
154
|
+
for where_key, where_value in v.items():
|
|
155
|
+
if isinstance(where_value, str):
|
|
156
|
+
where_conditions.append(f"{where_key}: {where_value}")
|
|
157
|
+
else:
|
|
158
|
+
where_conditions.append(f"{where_key}: {where_value}")
|
|
159
|
+
where_str = "{" + ", ".join(where_conditions) + "}"
|
|
160
|
+
arg_strs.append(f"{k}: {where_str}")
|
|
161
|
+
# Handle simple key-value filters
|
|
162
|
+
elif isinstance(v, str):
|
|
163
|
+
arg_strs.append(f'{k}: "{v}"')
|
|
164
|
+
else:
|
|
165
|
+
arg_strs.append(f"{k}: {v}")
|
|
166
|
+
|
|
167
|
+
return "(" + ", ".join(arg_strs) + ")"
|
|
168
|
+
|
|
169
|
+
selection_set = build_selection(fields, relationships)
|
|
170
|
+
args = build_args(filters)
|
|
171
|
+
|
|
172
|
+
query_str = f"""
|
|
173
|
+
query {{
|
|
174
|
+
{endpoint}{args} {{
|
|
175
|
+
{selection_set}
|
|
176
|
+
}}
|
|
177
|
+
}}
|
|
178
|
+
"""
|
|
179
|
+
print(query_str)
|
|
180
|
+
async with self.client as session:
|
|
181
|
+
result = await session.execute(gql(query_str))
|
|
182
|
+
return result
|
|
@@ -77,7 +77,7 @@ class PolymarketWeb3Client:
|
|
|
77
77
|
abi_element_identifier="redeemPositions",
|
|
78
78
|
args=[condition_id, amounts],
|
|
79
79
|
)
|
|
80
|
-
def _encode_convert(self, neg_risk_market_id: Keccak256, index_set: int, amount: int):
|
|
80
|
+
def _encode_convert(self, neg_risk_market_id: Keccak256, index_set: int, amount: int) -> str:
|
|
81
81
|
return self.neg_risk_adapter.encode_abi(
|
|
82
82
|
abi_element_identifier="convertPositions",
|
|
83
83
|
args=[neg_risk_market_id, index_set, amount],
|