polymarket-apis 0.3.0__py3-none-any.whl → 0.3.9__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.

Files changed (32) hide show
  1. polymarket_apis/__init__.py +42 -0
  2. polymarket_apis/clients/__init__.py +23 -0
  3. polymarket_apis/clients/clob_client.py +224 -117
  4. polymarket_apis/clients/data_client.py +220 -67
  5. polymarket_apis/clients/gamma_client.py +589 -101
  6. polymarket_apis/clients/graphql_client.py +28 -11
  7. polymarket_apis/clients/web3_client.py +538 -131
  8. polymarket_apis/clients/websockets_client.py +24 -7
  9. polymarket_apis/types/__init__.py +167 -0
  10. polymarket_apis/types/clob_types.py +35 -14
  11. polymarket_apis/types/common.py +105 -35
  12. polymarket_apis/types/data_types.py +48 -3
  13. polymarket_apis/types/gamma_types.py +529 -257
  14. polymarket_apis/types/web3_types.py +45 -0
  15. polymarket_apis/types/websockets_types.py +92 -41
  16. polymarket_apis/utilities/config.py +1 -0
  17. polymarket_apis/utilities/constants.py +5 -4
  18. polymarket_apis/utilities/exceptions.py +9 -0
  19. polymarket_apis/utilities/order_builder/builder.py +38 -22
  20. polymarket_apis/utilities/order_builder/helpers.py +0 -1
  21. polymarket_apis/utilities/signing/hmac.py +5 -1
  22. polymarket_apis/utilities/signing/signer.py +2 -2
  23. polymarket_apis/utilities/web3/abis/Safe.json +1138 -0
  24. polymarket_apis/utilities/web3/abis/SafeProxyFactory.json +224 -0
  25. polymarket_apis/utilities/web3/abis/custom_contract_errors.py +1 -1
  26. polymarket_apis/utilities/web3/helpers.py +235 -0
  27. {polymarket_apis-0.3.0.dist-info → polymarket_apis-0.3.9.dist-info}/METADATA +48 -8
  28. polymarket_apis-0.3.9.dist-info/RECORD +44 -0
  29. polymarket_apis/utilities/schemas/activity-subgraph.graphql +0 -86
  30. polymarket_apis/utilities/schemas/open-interest.graphql +0 -30
  31. polymarket_apis-0.3.0.dist-info/RECORD +0 -43
  32. {polymarket_apis-0.3.0.dist-info → polymarket_apis-0.3.9.dist-info}/WHEEL +0 -0
@@ -1,7 +1,7 @@
1
1
  import json
2
2
  import logging
3
- from datetime import UTC, datetime
4
- from typing import Literal, Optional
3
+ from datetime import UTC, datetime, timedelta
4
+ from typing import Literal, cast
5
5
  from urllib.parse import urljoin
6
6
 
7
7
  import httpx
@@ -27,11 +27,11 @@ from ..types.clob_types import (
27
27
  PaginatedResponse,
28
28
  PartialCreateOrderOptions,
29
29
  PolygonTrade,
30
- PolymarketRewardItem,
31
30
  PostOrdersArgs,
32
31
  Price,
33
32
  PriceHistory,
34
33
  RequestArgs,
34
+ RewardMarket,
35
35
  Spread,
36
36
  TickSize,
37
37
  TokenBidAskDict,
@@ -88,17 +88,18 @@ from ..utilities.signing.signer import Signer
88
88
 
89
89
  logger = logging.getLogger(__name__)
90
90
 
91
+
91
92
  class PolymarketClobClient:
92
93
  def __init__(
93
- self,
94
- private_key: str,
95
- proxy_address: EthAddress,
96
- creds: Optional[ApiCreds] = None,
97
- chain_id: Literal[137, 80002] = POLYGON,
98
- signature_type: Literal[0, 1, 2] = 1,
99
- # 0 - EOA wallet, 1 - Proxy wallet, 2 - Gnosis Safe wallet
94
+ self,
95
+ private_key: str,
96
+ address: EthAddress,
97
+ creds: ApiCreds | None = None,
98
+ chain_id: Literal[137, 80002] = POLYGON,
99
+ signature_type: Literal[0, 1, 2] = 1,
100
+ # 0 - EOA wallet, 1 - Proxy wallet, 2 - Gnosis Safe wallet
100
101
  ):
101
- self.proxy_address = proxy_address
102
+ self.address = address
102
103
  self.client = httpx.Client(http2=True, timeout=30.0)
103
104
  self.async_client = httpx.AsyncClient(http2=True, timeout=30.0)
104
105
  self.base_url: str = "https://clob.polymarket.com"
@@ -106,14 +107,14 @@ class PolymarketClobClient:
106
107
  self.builder = OrderBuilder(
107
108
  signer=self.signer,
108
109
  sig_type=signature_type,
109
- funder=proxy_address,
110
+ funder=address,
110
111
  )
111
112
  self.creds = creds if creds else self.create_or_derive_api_creds()
112
113
 
113
114
  # local cache
114
- self.__tick_sizes = {}
115
- self.__neg_risk = {}
116
- self.__fee_rates = {}
115
+ self.__tick_sizes: dict[str, TickSize] = {}
116
+ self.__neg_risk: dict[str, bool] = {}
117
+ self.__fee_rates: dict[str, int] = {}
117
118
 
118
119
  def _build_url(self, endpoint: str) -> str:
119
120
  return urljoin(self.base_url, endpoint)
@@ -123,19 +124,19 @@ class PolymarketClobClient:
123
124
  response.raise_for_status()
124
125
  return response.json()
125
126
 
126
- def create_api_creds(self, nonce: Optional[int] = None) -> ApiCreds:
127
+ def create_api_creds(self, nonce: int | None = None) -> ApiCreds:
127
128
  headers = create_level_1_headers(self.signer, nonce)
128
129
  response = self.client.post(self._build_url(CREATE_API_KEY), headers=headers)
129
130
  response.raise_for_status()
130
131
  return ApiCreds(**response.json())
131
132
 
132
- def derive_api_key(self, nonce: Optional[int] = None) -> ApiCreds:
133
+ def derive_api_key(self, nonce: int | None = None) -> ApiCreds:
133
134
  headers = create_level_1_headers(self.signer, nonce)
134
135
  response = self.client.get(self._build_url(DERIVE_API_KEY), headers=headers)
135
136
  response.raise_for_status()
136
137
  return ApiCreds(**response.json())
137
138
 
138
- def create_or_derive_api_creds(self, nonce: Optional[int] = None) -> ApiCreds:
139
+ def create_or_derive_api_creds(self, nonce: int | None = None) -> ApiCreds:
139
140
  try:
140
141
  return self.create_api_creds(nonce)
141
142
  except HTTPStatusError:
@@ -171,7 +172,9 @@ class PolymarketClobClient:
171
172
  params = {"token_id": token_id}
172
173
  response = self.client.get(self._build_url(GET_TICK_SIZE), params=params)
173
174
  response.raise_for_status()
174
- self.__tick_sizes[token_id] = str(response.json()["minimum_tick_size"])
175
+ self.__tick_sizes[token_id] = cast(
176
+ "TickSize", str(response.json()["minimum_tick_size"])
177
+ )
175
178
 
176
179
  return self.__tick_sizes[token_id]
177
180
 
@@ -199,7 +202,9 @@ class PolymarketClobClient:
199
202
  return fee_rate
200
203
 
201
204
  def __resolve_tick_size(
202
- self, token_id: str, tick_size: TickSize = None,
205
+ self,
206
+ token_id: str,
207
+ tick_size: TickSize | None = None,
203
208
  ) -> TickSize:
204
209
  min_tick_size = self.get_tick_size(token_id)
205
210
  if tick_size is not None:
@@ -211,12 +216,19 @@ class PolymarketClobClient:
211
216
  return tick_size
212
217
 
213
218
  def __resolve_fee_rate(
214
- self, token_id: str, user_fee_rate: Optional[int] = None,
219
+ self,
220
+ token_id: str,
221
+ user_fee_rate: int | None = None,
215
222
  ) -> int:
216
223
  market_fee_rate_bps = self.get_fee_rate_bps(token_id)
217
224
  # If both fee rate on the market and the user supplied fee rate are non-zero, validate that they match
218
225
  # 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:
226
+ if (
227
+ market_fee_rate_bps > 0
228
+ and user_fee_rate is not None
229
+ and user_fee_rate > 0
230
+ and user_fee_rate != market_fee_rate_bps
231
+ ):
220
232
  msg = f"invalid user provided fee rate: ({user_fee_rate}), fee rate for the market must be {market_fee_rate_bps}"
221
233
  raise InvalidFeeRateError(msg)
222
234
  return market_fee_rate_bps
@@ -291,10 +303,14 @@ class PolymarketClobClient:
291
303
  response.raise_for_status()
292
304
  return [OrderBookSummary(**obs) for obs in response.json()]
293
305
 
294
- async def get_order_books_async(self, token_ids: list[str]) -> list[OrderBookSummary]:
306
+ async def get_order_books_async(
307
+ self, token_ids: list[str]
308
+ ) -> list[OrderBookSummary]:
295
309
  """Get the orderbook for a set of tokens asynchronously."""
296
310
  body = [{"token_id": token_id} for token_id in token_ids]
297
- response = await self.async_client.post(self._build_url(GET_ORDER_BOOKS), json=body)
311
+ response = await self.async_client.post(
312
+ self._build_url(GET_ORDER_BOOKS), json=body
313
+ )
298
314
  response.raise_for_status()
299
315
  return [OrderBookSummary(**obs) for obs in response.json()]
300
316
 
@@ -304,7 +320,7 @@ class PolymarketClobClient:
304
320
  response.raise_for_status()
305
321
  return ClobMarket(**response.json())
306
322
 
307
- def get_markets(self, next_cursor="MA==") -> PaginatedResponse[ClobMarket]:
323
+ def get_markets(self, next_cursor="MA==") -> PaginatedResponse[ClobMarket]:
308
324
  """Get paginated ClobMarkets."""
309
325
  params = {"next_cursor": next_cursor}
310
326
  response = self.client.get(self._build_url(GET_MARKETS), params=params)
@@ -333,17 +349,26 @@ class PolymarketClobClient:
333
349
  return current_markets + next_page_markets
334
350
 
335
351
  def get_recent_history(
336
- self,
337
- token_id: str,
338
- interval: Optional[Literal["1d", "6h", "1h"]] = "1d",
339
- fidelity: int = 1, # resolution in minutes
352
+ self,
353
+ token_id: str,
354
+ interval: Literal["1h", "6h", "1d", "1w", "1m", "max"] = "1d",
355
+ fidelity: int = 1, # resolution in minutes
340
356
  ) -> PriceHistory:
341
- """Get the recent price history of a token (up to now) - 1h, 6h, 1d."""
342
- if fidelity < 1:
343
- msg = f"invalid filters: minimum 'fidelity' for '{interval}' range is 1"
357
+ """Get the recent price history of a token (up to now) - 1h, 6h, 1d, 1w, 1m."""
358
+ min_fidelities: dict[str, int] = {
359
+ "1h": 1,
360
+ "6h": 1,
361
+ "1d": 1,
362
+ "1w": 5,
363
+ "1m": 10,
364
+ "max": 2,
365
+ }
366
+
367
+ if fidelity < min_fidelities[interval]:
368
+ msg = f"invalid filters: minimum fidelity' for '{interval}' range is {min_fidelities.get(interval)}"
344
369
  raise ValueError(msg)
345
370
 
346
- params = {
371
+ params: dict[str, int | str] = {
347
372
  "market": token_id,
348
373
  "interval": interval,
349
374
  "fidelity": fidelity,
@@ -353,43 +378,52 @@ class PolymarketClobClient:
353
378
  return PriceHistory(**response.json(), token_id=token_id)
354
379
 
355
380
  def get_history(
356
- self,
357
- token_id: str,
358
- start_time: Optional[datetime] = None,
359
- end_time: Optional[datetime] = None,
360
- interval: Optional[Literal["max", "1m", "1w"]] = "max",
361
- fidelity: Optional[int] = 2, # resolution in minutes
381
+ self,
382
+ token_id: str,
383
+ start_time: datetime | None = None,
384
+ end_time: datetime | None = None,
385
+ fidelity: int = 2, # resolution in minutes
362
386
  ) -> PriceHistory:
363
- """Get the price history of a token between selected dates - 1m, 1w, max."""
364
- min_fidelities = {"1m": 10, "1w": 5, "max": 2}
365
-
366
- if fidelity < min_fidelities[interval]:
367
- msg = f"invalid filters: minimum 'fidelity' for '{interval}' range is {min_fidelities[interval]}"
368
- raise ValueError(msg)
369
-
387
+ """Get the price history of a token between a selected date range of max 15 days or from start_time to now."""
370
388
  if start_time is None and end_time is None:
371
- msg = "At least one of 'start_time' or 'end_time' must be provided."
389
+ msg = "At least 'start_time' or ('start_time' and 'end_time') must be provided"
372
390
  raise ValueError(msg)
373
391
 
374
- # Default values for timestamps if one is not provided
375
-
376
- if start_time is None:
377
- start_time = datetime(2020, 1, 1, tzinfo=UTC) # Default start time
378
- if end_time is None:
379
- end_time = datetime.now(UTC) # Default end time
392
+ if (
393
+ start_time
394
+ and end_time
395
+ and start_time + timedelta(days=15, seconds=1) < end_time
396
+ ):
397
+ msg = "'start_time' - 'end_time' range cannot exceed 15 days. Remove 'end_time' to get prices up to now or set a shorter range."
398
+ raise ValueError(msg)
380
399
 
381
- params = {
400
+ params: dict[str, int | str] = {
382
401
  "market": token_id,
383
- "startTs": int(start_time.timestamp()),
384
- "endTs": int(end_time.timestamp()),
385
- "interval": interval,
386
402
  "fidelity": fidelity,
387
403
  }
404
+ if start_time:
405
+ params["startTs"] = int(start_time.timestamp())
406
+ if end_time:
407
+ params["endTs"] = int(end_time.timestamp())
408
+
388
409
  response = self.client.get(self._build_url("/prices-history"), params=params)
389
410
  response.raise_for_status()
390
411
  return PriceHistory(**response.json(), token_id=token_id)
391
412
 
392
- def get_orders(self, order_id: Optional[str] = None, condition_id: Optional[Keccak256] = None, token_id: Optional[str] = None, next_cursor: str ="MA==") -> list[OpenOrder]:
413
+ def get_all_history(self, token_id: str) -> PriceHistory:
414
+ """Get the full price history of a token."""
415
+ return self.get_history(
416
+ token_id=token_id,
417
+ start_time=datetime(2020, 1, 1, tzinfo=UTC),
418
+ )
419
+
420
+ def get_orders(
421
+ self,
422
+ order_id: str | None = None,
423
+ condition_id: Keccak256 | None = None,
424
+ token_id: str | None = None,
425
+ next_cursor: str = "MA==",
426
+ ) -> list[OpenOrder]:
393
427
  """Gets your active orders, filtered by order_id, condition_id, token_id."""
394
428
  params = {}
395
429
  if order_id:
@@ -406,14 +440,18 @@ class PolymarketClobClient:
406
440
  next_cursor = next_cursor if next_cursor is not None else "MA=="
407
441
  while next_cursor != END_CURSOR:
408
442
  params["next_cursor"] = next_cursor
409
- response = self.client.get(self._build_url(ORDERS), headers=headers, params=params)
443
+ response = self.client.get(
444
+ self._build_url(ORDERS), headers=headers, params=params
445
+ )
410
446
  response.raise_for_status()
411
447
  next_cursor = response.json()["next_cursor"]
412
448
  results += [OpenOrder(**order) for order in response.json()["data"]]
413
449
 
414
450
  return results
415
451
 
416
- def create_order(self, order_args: OrderArgs, options: Optional[PartialCreateOrderOptions] = None) -> SignedOrder:
452
+ def create_order(
453
+ self, order_args: OrderArgs, options: PartialCreateOrderOptions | None = None
454
+ ) -> SignedOrder:
417
455
  """Creates and signs an order."""
418
456
  # add resolve_order_options, or similar
419
457
  tick_size = self.__resolve_tick_size(
@@ -425,7 +463,6 @@ class PolymarketClobClient:
425
463
  msg = f"price ({order_args.price}), min: {tick_size} - max: {1 - float(tick_size)}"
426
464
  raise InvalidPriceError(msg)
427
465
 
428
-
429
466
  neg_risk = (
430
467
  options.neg_risk
431
468
  if options and options.neg_risk
@@ -433,7 +470,9 @@ class PolymarketClobClient:
433
470
  )
434
471
 
435
472
  # fee rate
436
- fee_rate_bps = self.__resolve_fee_rate(order_args.token_id, order_args.fee_rate_bps)
473
+ fee_rate_bps = self.__resolve_fee_rate(
474
+ order_args.token_id, order_args.fee_rate_bps
475
+ )
437
476
  order_args.fee_rate_bps = fee_rate_bps
438
477
 
439
478
  return self.builder.create_order(
@@ -444,7 +483,9 @@ class PolymarketClobClient:
444
483
  ),
445
484
  )
446
485
 
447
- def post_order(self, order: SignedOrder, order_type: OrderType = OrderType.GTC) -> Optional[OrderPostResponse]:
486
+ def post_order(
487
+ self, order: SignedOrder, order_type: OrderType = OrderType.GTC
488
+ ) -> OrderPostResponse | None:
448
489
  """Posts a SignedOrder."""
449
490
  body = order_to_json(order, self.creds.key, order_type)
450
491
  headers = create_level_2_headers(
@@ -466,15 +507,23 @@ class PolymarketClobClient:
466
507
  logger.warning(msg)
467
508
  error_json = exc.response.json()
468
509
  print("Details:", error_json["error"])
469
-
470
- def create_and_post_order(self, order_args: OrderArgs, options: Optional[PartialCreateOrderOptions] = None, order_type: OrderType = OrderType.GTC) -> OrderPostResponse:
510
+ return None
511
+
512
+ def create_and_post_order(
513
+ self,
514
+ order_args: OrderArgs,
515
+ options: PartialCreateOrderOptions | None = None,
516
+ order_type: OrderType = OrderType.GTC,
517
+ ) -> OrderPostResponse | None:
471
518
  """Utility function to create and publish an order."""
472
519
  order = self.create_order(order_args, options)
473
520
  return self.post_order(order=order, order_type=order_type)
474
521
 
475
- def post_orders(self, args: list[PostOrdersArgs]):
522
+ def post_orders(self, args: list[PostOrdersArgs]) -> list[OrderPostResponse] | None:
476
523
  """Posts multiple SignedOrders at once."""
477
- body = [order_to_json(arg.order, self.creds.key, arg.order_type) for arg in args]
524
+ body = [
525
+ order_to_json(arg.order, self.creds.key, arg.order_type) for arg in args
526
+ ]
478
527
  headers = create_level_2_headers(
479
528
  self.signer,
480
529
  self.creds,
@@ -493,26 +542,36 @@ class PolymarketClobClient:
493
542
  resp = OrderPostResponse(**item)
494
543
  order_responses.append(resp)
495
544
  if resp.error_msg:
496
- msg = (f"Error posting order in position {index} \n"
497
- f"Details: {resp.error_msg}")
545
+ msg = (
546
+ f"Error posting order in position {index} \n"
547
+ f"Details: {resp.error_msg}"
548
+ )
498
549
  logger.warning(msg)
499
550
  except httpx.HTTPStatusError as exc:
500
551
  msg = f"Client Error '{exc.response.status_code} {exc.response.reason_phrase}' while posting order"
501
552
  logger.warning(msg)
502
553
  error_json = exc.response.json()
503
554
  print("Details:", error_json["error"])
555
+ return None
504
556
  else:
505
557
  return order_responses
506
558
 
507
- def create_and_post_orders(self, args: list[OrderArgs], order_types: list[OrderType]) -> list[OrderPostResponse]:
559
+ def create_and_post_orders(
560
+ self, args: list[OrderArgs], order_types: list[OrderType]
561
+ ) -> list[OrderPostResponse] | None:
508
562
  """Utility function to create and publish multiple orders at once."""
509
563
  return self.post_orders(
510
- [PostOrdersArgs(order=self.create_order(order_args),
511
- order_type=order_type)
512
- for order_args, order_type in zip(args, order_types, strict=True)],
564
+ [
565
+ PostOrdersArgs(
566
+ order=self.create_order(order_args), order_type=order_type
567
+ )
568
+ for order_args, order_type in zip(args, order_types, strict=True)
569
+ ],
513
570
  )
514
571
 
515
- def calculate_market_price(self, token_id: str, side: str, amount: float, order_type: OrderType) -> float:
572
+ def calculate_market_price(
573
+ self, token_id: str, side: str, amount: float, order_type: OrderType
574
+ ) -> float:
516
575
  """Calculates the matching price considering an amount and the current orderbook."""
517
576
  book = self.get_order_book(token_id)
518
577
  if book is None:
@@ -523,19 +582,27 @@ class PolymarketClobClient:
523
582
  msg = "No ask orders available"
524
583
  raise LiquidityError(msg)
525
584
  return self.builder.calculate_buy_market_price(
526
- book.asks, amount, order_type,
585
+ book.asks,
586
+ amount,
587
+ order_type,
527
588
  )
528
589
  if side == "SELL":
529
590
  if book.bids is None:
530
591
  msg = "No bid orders available"
531
592
  raise LiquidityError(msg)
532
593
  return self.builder.calculate_sell_market_price(
533
- book.bids, amount, order_type,
594
+ book.bids,
595
+ amount,
596
+ order_type,
534
597
  )
535
598
  msg = 'Side must be "BUY" or "SELL"'
536
599
  raise ValueError(msg)
537
600
 
538
- def create_market_order(self, order_args: MarketOrderArgs, options: Optional[PartialCreateOrderOptions] = None):
601
+ def create_market_order(
602
+ self,
603
+ order_args: MarketOrderArgs,
604
+ options: PartialCreateOrderOptions | None = None,
605
+ ):
539
606
  """Creates and signs a market order."""
540
607
  tick_size = self.__resolve_tick_size(
541
608
  order_args.token_id,
@@ -561,7 +628,9 @@ class PolymarketClobClient:
561
628
  )
562
629
 
563
630
  # fee rate
564
- fee_rate_bps = self.__resolve_fee_rate(order_args.token_id, order_args.fee_rate_bps)
631
+ fee_rate_bps = self.__resolve_fee_rate(
632
+ order_args.token_id, order_args.fee_rate_bps
633
+ )
565
634
  order_args.fee_rate_bps = fee_rate_bps
566
635
 
567
636
  return self.builder.create_market_order(
@@ -573,11 +642,11 @@ class PolymarketClobClient:
573
642
  )
574
643
 
575
644
  def create_and_post_market_order(
576
- self,
577
- order_args: MarketOrderArgs,
578
- options: Optional[PartialCreateOrderOptions] = None,
579
- order_type: OrderType = OrderType.FOK,
580
- ) -> OrderPostResponse:
645
+ self,
646
+ order_args: MarketOrderArgs,
647
+ options: PartialCreateOrderOptions | None = None,
648
+ order_type: OrderType = OrderType.FOK,
649
+ ) -> OrderPostResponse | None:
581
650
  """Utility function to create and publish a market order."""
582
651
  order = self.create_market_order(order_args, options)
583
652
  return self.post_order(order=order, order_type=order_type)
@@ -589,7 +658,12 @@ class PolymarketClobClient:
589
658
  request_args = RequestArgs(method="DELETE", request_path=CANCEL, body=body)
590
659
  headers = create_level_2_headers(self.signer, self.creds, request_args)
591
660
 
592
- response = self.client.request("DELETE", self._build_url(CANCEL), headers=headers, data=json.dumps(body).encode("utf-8"))
661
+ response = self.client.request(
662
+ "DELETE",
663
+ self._build_url(CANCEL),
664
+ headers=headers,
665
+ content=json.dumps(body).encode("utf-8"),
666
+ )
593
667
  response.raise_for_status()
594
668
  return OrderCancelResponse(**response.json())
595
669
 
@@ -598,11 +672,18 @@ class PolymarketClobClient:
598
672
  body = order_ids
599
673
 
600
674
  request_args = RequestArgs(
601
- method="DELETE", request_path=CANCEL_ORDERS, body=body,
675
+ method="DELETE",
676
+ request_path=CANCEL_ORDERS,
677
+ body=body,
602
678
  )
603
679
  headers = create_level_2_headers(self.signer, self.creds, request_args)
604
680
 
605
- response = self.client.request("DELETE", self._build_url(CANCEL_ORDERS), headers=headers, data=json.dumps(body).encode("utf-8"))
681
+ response = self.client.request(
682
+ "DELETE",
683
+ self._build_url(CANCEL_ORDERS),
684
+ headers=headers,
685
+ content=json.dumps(body).encode("utf-8"),
686
+ )
606
687
  response.raise_for_status()
607
688
  return OrderCancelResponse(**response.json())
608
689
 
@@ -620,7 +701,11 @@ class PolymarketClobClient:
620
701
  request_args = RequestArgs(method="GET", request_path=IS_ORDER_SCORING)
621
702
  headers = create_level_2_headers(self.signer, self.creds, request_args)
622
703
 
623
- response = self.client.get(self._build_url(IS_ORDER_SCORING), headers=headers, params={"order_id": order_id})
704
+ response = self.client.get(
705
+ self._build_url(IS_ORDER_SCORING),
706
+ headers=headers,
707
+ params={"order_id": order_id},
708
+ )
624
709
  response.raise_for_status()
625
710
  return response.json()["scoring"]
626
711
 
@@ -628,12 +713,16 @@ class PolymarketClobClient:
628
713
  """Check if the orders are currently scoring."""
629
714
  body = order_ids
630
715
  request_args = RequestArgs(
631
- method="POST", request_path=ARE_ORDERS_SCORING, body=body,
716
+ method="POST",
717
+ request_path=ARE_ORDERS_SCORING,
718
+ body=body,
632
719
  )
633
720
  headers = create_level_2_headers(self.signer, self.creds, request_args)
634
721
  headers["Content-Type"] = "application/json"
635
722
 
636
- response = self.client.post(self._build_url(ARE_ORDERS_SCORING), headers=headers, json=body)
723
+ response = self.client.post(
724
+ self._build_url(ARE_ORDERS_SCORING), headers=headers, json=body
725
+ )
637
726
  response.raise_for_status()
638
727
  return response.json()
639
728
 
@@ -646,21 +735,24 @@ class PolymarketClobClient:
646
735
  request_args = RequestArgs(method="GET", request_path="/rewards/markets/")
647
736
  headers = create_level_2_headers(self.signer, self.creds, request_args)
648
737
 
649
- response = self.client.get(self._build_url("/rewards/markets/" + condition_id), headers=headers)
738
+ response = self.client.get(
739
+ self._build_url("/rewards/markets/" + condition_id), headers=headers
740
+ )
650
741
  response.raise_for_status()
651
742
  return next(MarketRewards(**market) for market in response.json()["data"])
652
743
 
653
744
  def get_trades(
654
- self,
655
- condition_id: Optional[Keccak256] = None,
656
- token_id: Optional[str] = None,
657
- trade_id: Optional[str] = None,
658
- before: Optional[datetime] = None,
659
- after: Optional[datetime] = None,
660
- proxy_address: Optional[int] = None,
661
- next_cursor="MA==") -> list[PolygonTrade]:
745
+ self,
746
+ condition_id: Keccak256 | None = None,
747
+ token_id: str | None = None,
748
+ trade_id: str | None = None,
749
+ before: datetime | None = None,
750
+ after: datetime | None = None,
751
+ address: EthAddress | None = None,
752
+ next_cursor="MA==",
753
+ ) -> list[PolygonTrade]:
662
754
  """Fetches the trade history for a user."""
663
- params = {}
755
+ params: dict[str, str | int] = {}
664
756
  if condition_id:
665
757
  params["market"] = condition_id
666
758
  if token_id:
@@ -671,8 +763,8 @@ class PolymarketClobClient:
671
763
  params["before"] = int(before.replace(microsecond=0).timestamp())
672
764
  if after:
673
765
  params["after"] = int(after.replace(microsecond=0).timestamp())
674
- if proxy_address:
675
- params["maker_address"] = proxy_address
766
+ if address:
767
+ params["maker_address"] = address
676
768
 
677
769
  request_args = RequestArgs(method="GET", request_path=TRADES)
678
770
  headers = create_level_2_headers(self.signer, self.creds, request_args)
@@ -681,47 +773,61 @@ class PolymarketClobClient:
681
773
  next_cursor = next_cursor if next_cursor is not None else "MA=="
682
774
  while next_cursor != END_CURSOR:
683
775
  params["next_cursor"] = next_cursor
684
- response = self.client.get(self._build_url(TRADES), headers=headers, params=params)
776
+ response = self.client.get(
777
+ self._build_url(TRADES), headers=headers, params=params
778
+ )
685
779
  response.raise_for_status()
686
780
  next_cursor = response.json()["next_cursor"]
687
781
  results += [PolygonTrade(**trade) for trade in response.json()["data"]]
688
782
 
689
783
  return results
690
784
 
691
- def get_total_rewards(self, date: Optional[datetime] = None) -> DailyEarnedReward:
785
+ def get_total_rewards(self, date: datetime | None = None) -> DailyEarnedReward:
692
786
  """Get the total rewards earned on a given date (seems to only hold the 6 most recent data points)."""
693
787
  if date is None:
694
788
  date = datetime.now(UTC)
695
789
  params = {
696
790
  "authenticationType": "magic",
697
- "date": f"{date.strftime("%Y-%m-%d")}",
791
+ "date": f"{date.strftime('%Y-%m-%d')}",
698
792
  }
699
793
 
700
794
  request_args = RequestArgs(method="GET", request_path="/rewards/user/total")
701
795
  headers = create_level_2_headers(self.signer, self.creds, request_args)
702
796
  params["l2Headers"] = json.dumps(headers)
703
797
 
704
- response = self.client.get("https://polymarket.com/api/rewards/totalEarnings", params=params)
798
+ response = self.client.get(
799
+ "https://polymarket.com/api/rewards/totalEarnings", params=params
800
+ )
705
801
  response.raise_for_status()
706
802
  if response.json():
707
803
  return DailyEarnedReward(**response.json()[0])
708
804
  return DailyEarnedReward(
709
805
  date=date,
710
806
  asset_address="0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
711
- maker_address=self.proxy_address,
807
+ maker_address=self.address,
712
808
  earnings=0.0,
713
809
  asset_rate=0.0,
714
810
  )
715
811
 
716
812
  def get_reward_markets(
717
- self,
718
- sort_by: Optional[Literal["market", "max_spread", "min_size", "rate_per_day", "spread", "price", "earnings", "earning_percentage"]] = "market",
719
- sort_direction: Optional[Literal["ASC", "DESC"]] = None,
720
- query: Optional[str] = None,
721
- show_favorites: bool = False,
722
- ) -> list[PolymarketRewardItem]:
813
+ self,
814
+ query: str | None = None,
815
+ sort_by: Literal[
816
+ "market",
817
+ "max_spread",
818
+ "min_size",
819
+ "rate_per_day",
820
+ "spread",
821
+ "price",
822
+ "earnings",
823
+ "earning_percentage",
824
+ ]
825
+ | None = "market",
826
+ sort_direction: Literal["ASC", "DESC"] | None = None,
827
+ show_favorites: bool = False,
828
+ ) -> list[RewardMarket]:
723
829
  """
724
- Get all polymarket.com/rewards items, sorted by different criteria.
830
+ Search through markets that offer rewards (polymarket.com/rewards items) by query, sorted by different metrics. If query is empty, returns all markets with rewards.
725
831
 
726
832
  - market start date ("market") - TODO confirm this
727
833
  - max spread for rewards in usdc
@@ -734,7 +840,7 @@ class PolymarketClobClient:
734
840
  """
735
841
  results = []
736
842
  desc = {"ASC": False, "DESC": True}
737
- params = {
843
+ params: dict[str, bool | str] = {
738
844
  "authenticationType": "magic",
739
845
  "showFavorites": show_favorites,
740
846
  }
@@ -753,11 +859,12 @@ class PolymarketClobClient:
753
859
  next_cursor = "MA=="
754
860
  while next_cursor != END_CURSOR:
755
861
  params["nextCursor"] = next_cursor
756
- response = self.client.get("https://polymarket.com/api/rewards/markets", params=params)
757
- # can probably use clob/rewards/user/markets here but haven't figure out auth
862
+ response = self.client.get(
863
+ "https://polymarket.com/api/rewards/markets", params=params
864
+ )
758
865
  response.raise_for_status()
759
866
  next_cursor = response.json()["next_cursor"]
760
- results += [PolymarketRewardItem(**reward) for reward in response.json()["data"]]
867
+ results += [RewardMarket(**reward) for reward in response.json()["data"]]
761
868
 
762
869
  return results
763
870