polymarket-apis 0.3.5__py3-none-any.whl → 0.3.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- polymarket_apis/__init__.py +1 -1
- polymarket_apis/clients/clob_client.py +59 -56
- polymarket_apis/clients/data_client.py +40 -2
- polymarket_apis/clients/gamma_client.py +21 -21
- polymarket_apis/clients/web3_client.py +294 -124
- polymarket_apis/types/clob_types.py +5 -4
- polymarket_apis/types/common.py +5 -1
- polymarket_apis/types/data_types.py +33 -1
- polymarket_apis/utilities/constants.py +4 -3
- polymarket_apis/utilities/order_builder/builder.py +6 -6
- polymarket_apis/utilities/signing/signer.py +2 -2
- {polymarket_apis-0.3.5.dist-info → polymarket_apis-0.3.7.dist-info}/METADATA +5 -2
- {polymarket_apis-0.3.5.dist-info → polymarket_apis-0.3.7.dist-info}/RECORD +14 -14
- {polymarket_apis-0.3.5.dist-info → polymarket_apis-0.3.7.dist-info}/WHEEL +0 -0
polymarket_apis/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
3
|
from datetime import UTC, datetime, timedelta
|
|
4
|
-
from typing import Literal,
|
|
4
|
+
from typing import Literal, cast
|
|
5
5
|
from urllib.parse import urljoin
|
|
6
6
|
|
|
7
7
|
import httpx
|
|
@@ -93,13 +93,13 @@ class PolymarketClobClient:
|
|
|
93
93
|
def __init__(
|
|
94
94
|
self,
|
|
95
95
|
private_key: str,
|
|
96
|
-
|
|
97
|
-
creds:
|
|
96
|
+
address: EthAddress,
|
|
97
|
+
creds: ApiCreds | None = None,
|
|
98
98
|
chain_id: Literal[137, 80002] = POLYGON,
|
|
99
99
|
signature_type: Literal[0, 1, 2] = 1,
|
|
100
100
|
# 0 - EOA wallet, 1 - Proxy wallet, 2 - Gnosis Safe wallet
|
|
101
101
|
):
|
|
102
|
-
self.
|
|
102
|
+
self.address = address
|
|
103
103
|
self.client = httpx.Client(http2=True, timeout=30.0)
|
|
104
104
|
self.async_client = httpx.AsyncClient(http2=True, timeout=30.0)
|
|
105
105
|
self.base_url: str = "https://clob.polymarket.com"
|
|
@@ -107,14 +107,14 @@ class PolymarketClobClient:
|
|
|
107
107
|
self.builder = OrderBuilder(
|
|
108
108
|
signer=self.signer,
|
|
109
109
|
sig_type=signature_type,
|
|
110
|
-
funder=
|
|
110
|
+
funder=address,
|
|
111
111
|
)
|
|
112
112
|
self.creds = creds if creds else self.create_or_derive_api_creds()
|
|
113
113
|
|
|
114
114
|
# local cache
|
|
115
|
-
self.__tick_sizes = {}
|
|
116
|
-
self.__neg_risk = {}
|
|
117
|
-
self.__fee_rates = {}
|
|
115
|
+
self.__tick_sizes: dict[str, TickSize] = {}
|
|
116
|
+
self.__neg_risk: dict[str, bool] = {}
|
|
117
|
+
self.__fee_rates: dict[str, int] = {}
|
|
118
118
|
|
|
119
119
|
def _build_url(self, endpoint: str) -> str:
|
|
120
120
|
return urljoin(self.base_url, endpoint)
|
|
@@ -124,19 +124,19 @@ class PolymarketClobClient:
|
|
|
124
124
|
response.raise_for_status()
|
|
125
125
|
return response.json()
|
|
126
126
|
|
|
127
|
-
def create_api_creds(self, nonce:
|
|
127
|
+
def create_api_creds(self, nonce: int | None = None) -> ApiCreds:
|
|
128
128
|
headers = create_level_1_headers(self.signer, nonce)
|
|
129
129
|
response = self.client.post(self._build_url(CREATE_API_KEY), headers=headers)
|
|
130
130
|
response.raise_for_status()
|
|
131
131
|
return ApiCreds(**response.json())
|
|
132
132
|
|
|
133
|
-
def derive_api_key(self, nonce:
|
|
133
|
+
def derive_api_key(self, nonce: int | None = None) -> ApiCreds:
|
|
134
134
|
headers = create_level_1_headers(self.signer, nonce)
|
|
135
135
|
response = self.client.get(self._build_url(DERIVE_API_KEY), headers=headers)
|
|
136
136
|
response.raise_for_status()
|
|
137
137
|
return ApiCreds(**response.json())
|
|
138
138
|
|
|
139
|
-
def create_or_derive_api_creds(self, nonce:
|
|
139
|
+
def create_or_derive_api_creds(self, nonce: int | None = None) -> ApiCreds:
|
|
140
140
|
try:
|
|
141
141
|
return self.create_api_creds(nonce)
|
|
142
142
|
except HTTPStatusError:
|
|
@@ -172,7 +172,9 @@ class PolymarketClobClient:
|
|
|
172
172
|
params = {"token_id": token_id}
|
|
173
173
|
response = self.client.get(self._build_url(GET_TICK_SIZE), params=params)
|
|
174
174
|
response.raise_for_status()
|
|
175
|
-
self.__tick_sizes[token_id] =
|
|
175
|
+
self.__tick_sizes[token_id] = cast(
|
|
176
|
+
"TickSize", str(response.json()["minimum_tick_size"])
|
|
177
|
+
)
|
|
176
178
|
|
|
177
179
|
return self.__tick_sizes[token_id]
|
|
178
180
|
|
|
@@ -202,7 +204,7 @@ class PolymarketClobClient:
|
|
|
202
204
|
def __resolve_tick_size(
|
|
203
205
|
self,
|
|
204
206
|
token_id: str,
|
|
205
|
-
tick_size: TickSize = None,
|
|
207
|
+
tick_size: TickSize | None = None,
|
|
206
208
|
) -> TickSize:
|
|
207
209
|
min_tick_size = self.get_tick_size(token_id)
|
|
208
210
|
if tick_size is not None:
|
|
@@ -216,7 +218,7 @@ class PolymarketClobClient:
|
|
|
216
218
|
def __resolve_fee_rate(
|
|
217
219
|
self,
|
|
218
220
|
token_id: str,
|
|
219
|
-
user_fee_rate:
|
|
221
|
+
user_fee_rate: int | None = None,
|
|
220
222
|
) -> int:
|
|
221
223
|
market_fee_rate_bps = self.get_fee_rate_bps(token_id)
|
|
222
224
|
# If both fee rate on the market and the user supplied fee rate are non-zero, validate that they match
|
|
@@ -362,11 +364,11 @@ class PolymarketClobClient:
|
|
|
362
364
|
"max": 2,
|
|
363
365
|
}
|
|
364
366
|
|
|
365
|
-
if fidelity < min_fidelities
|
|
366
|
-
msg = f"invalid filters: minimum
|
|
367
|
+
if fidelity < min_fidelities[interval]:
|
|
368
|
+
msg = f"invalid filters: minimum fidelity' for '{interval}' range is {min_fidelities.get(interval)}"
|
|
367
369
|
raise ValueError(msg)
|
|
368
370
|
|
|
369
|
-
params = {
|
|
371
|
+
params: dict[str, int | str] = {
|
|
370
372
|
"market": token_id,
|
|
371
373
|
"interval": interval,
|
|
372
374
|
"fidelity": fidelity,
|
|
@@ -378,8 +380,8 @@ class PolymarketClobClient:
|
|
|
378
380
|
def get_history(
|
|
379
381
|
self,
|
|
380
382
|
token_id: str,
|
|
381
|
-
start_time:
|
|
382
|
-
end_time:
|
|
383
|
+
start_time: datetime | None = None,
|
|
384
|
+
end_time: datetime | None = None,
|
|
383
385
|
fidelity: int = 2, # resolution in minutes
|
|
384
386
|
) -> PriceHistory:
|
|
385
387
|
"""Get the price history of a token between a selected date range of max 15 days or from start_time to now."""
|
|
@@ -395,7 +397,7 @@ class PolymarketClobClient:
|
|
|
395
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."
|
|
396
398
|
raise ValueError(msg)
|
|
397
399
|
|
|
398
|
-
params = {
|
|
400
|
+
params: dict[str, int | str] = {
|
|
399
401
|
"market": token_id,
|
|
400
402
|
"fidelity": fidelity,
|
|
401
403
|
}
|
|
@@ -417,9 +419,9 @@ class PolymarketClobClient:
|
|
|
417
419
|
|
|
418
420
|
def get_orders(
|
|
419
421
|
self,
|
|
420
|
-
order_id:
|
|
421
|
-
condition_id:
|
|
422
|
-
token_id:
|
|
422
|
+
order_id: str | None = None,
|
|
423
|
+
condition_id: Keccak256 | None = None,
|
|
424
|
+
token_id: str | None = None,
|
|
423
425
|
next_cursor: str = "MA==",
|
|
424
426
|
) -> list[OpenOrder]:
|
|
425
427
|
"""Gets your active orders, filtered by order_id, condition_id, token_id."""
|
|
@@ -448,7 +450,7 @@ class PolymarketClobClient:
|
|
|
448
450
|
return results
|
|
449
451
|
|
|
450
452
|
def create_order(
|
|
451
|
-
self, order_args: OrderArgs, options:
|
|
453
|
+
self, order_args: OrderArgs, options: PartialCreateOrderOptions | None = None
|
|
452
454
|
) -> SignedOrder:
|
|
453
455
|
"""Creates and signs an order."""
|
|
454
456
|
# add resolve_order_options, or similar
|
|
@@ -483,7 +485,7 @@ class PolymarketClobClient:
|
|
|
483
485
|
|
|
484
486
|
def post_order(
|
|
485
487
|
self, order: SignedOrder, order_type: OrderType = OrderType.GTC
|
|
486
|
-
) ->
|
|
488
|
+
) -> OrderPostResponse | None:
|
|
487
489
|
"""Posts a SignedOrder."""
|
|
488
490
|
body = order_to_json(order, self.creds.key, order_type)
|
|
489
491
|
headers = create_level_2_headers(
|
|
@@ -505,18 +507,19 @@ class PolymarketClobClient:
|
|
|
505
507
|
logger.warning(msg)
|
|
506
508
|
error_json = exc.response.json()
|
|
507
509
|
print("Details:", error_json["error"])
|
|
510
|
+
return None
|
|
508
511
|
|
|
509
512
|
def create_and_post_order(
|
|
510
513
|
self,
|
|
511
514
|
order_args: OrderArgs,
|
|
512
|
-
options:
|
|
515
|
+
options: PartialCreateOrderOptions | None = None,
|
|
513
516
|
order_type: OrderType = OrderType.GTC,
|
|
514
517
|
) -> OrderPostResponse | None:
|
|
515
518
|
"""Utility function to create and publish an order."""
|
|
516
519
|
order = self.create_order(order_args, options)
|
|
517
520
|
return self.post_order(order=order, order_type=order_type)
|
|
518
521
|
|
|
519
|
-
def post_orders(self, args: list[PostOrdersArgs]):
|
|
522
|
+
def post_orders(self, args: list[PostOrdersArgs]) -> list[OrderPostResponse] | None:
|
|
520
523
|
"""Posts multiple SignedOrders at once."""
|
|
521
524
|
body = [
|
|
522
525
|
order_to_json(arg.order, self.creds.key, arg.order_type) for arg in args
|
|
@@ -549,12 +552,13 @@ class PolymarketClobClient:
|
|
|
549
552
|
logger.warning(msg)
|
|
550
553
|
error_json = exc.response.json()
|
|
551
554
|
print("Details:", error_json["error"])
|
|
555
|
+
return None
|
|
552
556
|
else:
|
|
553
557
|
return order_responses
|
|
554
558
|
|
|
555
559
|
def create_and_post_orders(
|
|
556
560
|
self, args: list[OrderArgs], order_types: list[OrderType]
|
|
557
|
-
) -> list[OrderPostResponse]:
|
|
561
|
+
) -> list[OrderPostResponse] | None:
|
|
558
562
|
"""Utility function to create and publish multiple orders at once."""
|
|
559
563
|
return self.post_orders(
|
|
560
564
|
[
|
|
@@ -597,7 +601,7 @@ class PolymarketClobClient:
|
|
|
597
601
|
def create_market_order(
|
|
598
602
|
self,
|
|
599
603
|
order_args: MarketOrderArgs,
|
|
600
|
-
options:
|
|
604
|
+
options: PartialCreateOrderOptions | None = None,
|
|
601
605
|
):
|
|
602
606
|
"""Creates and signs a market order."""
|
|
603
607
|
tick_size = self.__resolve_tick_size(
|
|
@@ -640,7 +644,7 @@ class PolymarketClobClient:
|
|
|
640
644
|
def create_and_post_market_order(
|
|
641
645
|
self,
|
|
642
646
|
order_args: MarketOrderArgs,
|
|
643
|
-
options:
|
|
647
|
+
options: PartialCreateOrderOptions | None = None,
|
|
644
648
|
order_type: OrderType = OrderType.FOK,
|
|
645
649
|
) -> OrderPostResponse | None:
|
|
646
650
|
"""Utility function to create and publish a market order."""
|
|
@@ -678,7 +682,7 @@ class PolymarketClobClient:
|
|
|
678
682
|
"DELETE",
|
|
679
683
|
self._build_url(CANCEL_ORDERS),
|
|
680
684
|
headers=headers,
|
|
681
|
-
|
|
685
|
+
content=json.dumps(body).encode("utf-8"),
|
|
682
686
|
)
|
|
683
687
|
response.raise_for_status()
|
|
684
688
|
return OrderCancelResponse(**response.json())
|
|
@@ -739,12 +743,12 @@ class PolymarketClobClient:
|
|
|
739
743
|
|
|
740
744
|
def get_trades(
|
|
741
745
|
self,
|
|
742
|
-
condition_id:
|
|
743
|
-
token_id:
|
|
744
|
-
trade_id:
|
|
745
|
-
before:
|
|
746
|
-
after:
|
|
747
|
-
|
|
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,
|
|
748
752
|
next_cursor="MA==",
|
|
749
753
|
) -> list[PolygonTrade]:
|
|
750
754
|
"""Fetches the trade history for a user."""
|
|
@@ -759,8 +763,8 @@ class PolymarketClobClient:
|
|
|
759
763
|
params["before"] = int(before.replace(microsecond=0).timestamp())
|
|
760
764
|
if after:
|
|
761
765
|
params["after"] = int(after.replace(microsecond=0).timestamp())
|
|
762
|
-
if
|
|
763
|
-
params["maker_address"] =
|
|
766
|
+
if address:
|
|
767
|
+
params["maker_address"] = address
|
|
764
768
|
|
|
765
769
|
request_args = RequestArgs(method="GET", request_path=TRADES)
|
|
766
770
|
headers = create_level_2_headers(self.signer, self.creds, request_args)
|
|
@@ -778,7 +782,7 @@ class PolymarketClobClient:
|
|
|
778
782
|
|
|
779
783
|
return results
|
|
780
784
|
|
|
781
|
-
def get_total_rewards(self, date:
|
|
785
|
+
def get_total_rewards(self, date: datetime | None = None) -> DailyEarnedReward:
|
|
782
786
|
"""Get the total rewards earned on a given date (seems to only hold the 6 most recent data points)."""
|
|
783
787
|
if date is None:
|
|
784
788
|
date = datetime.now(UTC)
|
|
@@ -800,27 +804,26 @@ class PolymarketClobClient:
|
|
|
800
804
|
return DailyEarnedReward(
|
|
801
805
|
date=date,
|
|
802
806
|
asset_address="0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
|
|
803
|
-
maker_address=self.
|
|
807
|
+
maker_address=self.address,
|
|
804
808
|
earnings=0.0,
|
|
805
809
|
asset_rate=0.0,
|
|
806
810
|
)
|
|
807
811
|
|
|
808
812
|
def get_reward_markets(
|
|
809
813
|
self,
|
|
810
|
-
query:
|
|
811
|
-
sort_by:
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
] =
|
|
823
|
-
sort_direction: Optional[Literal["ASC", "DESC"]] = None,
|
|
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,
|
|
824
827
|
show_favorites: bool = False,
|
|
825
828
|
) -> list[RewardMarket]:
|
|
826
829
|
"""
|
|
@@ -837,7 +840,7 @@ class PolymarketClobClient:
|
|
|
837
840
|
"""
|
|
838
841
|
results = []
|
|
839
842
|
desc = {"ASC": False, "DESC": True}
|
|
840
|
-
params = {
|
|
843
|
+
params: dict[str, bool | str] = {
|
|
841
844
|
"authenticationType": "magic",
|
|
842
845
|
"showFavorites": show_favorites,
|
|
843
846
|
}
|
|
@@ -4,10 +4,12 @@ from urllib.parse import urljoin
|
|
|
4
4
|
|
|
5
5
|
import httpx
|
|
6
6
|
|
|
7
|
+
from ..clients.graphql_client import PolymarketGraphQLClient
|
|
7
8
|
from ..types.common import EthAddress, TimeseriesPoint
|
|
8
9
|
from ..types.data_types import (
|
|
9
10
|
Activity,
|
|
10
11
|
EventLiveVolume,
|
|
12
|
+
GQLPosition,
|
|
11
13
|
HolderResponse,
|
|
12
14
|
MarketValue,
|
|
13
15
|
Position,
|
|
@@ -22,6 +24,9 @@ class PolymarketDataClient:
|
|
|
22
24
|
def __init__(self, base_url: str = "https://data-api.polymarket.com"):
|
|
23
25
|
self.base_url = base_url
|
|
24
26
|
self.client = httpx.Client(http2=True, timeout=30.0)
|
|
27
|
+
self.gql_positions_client = PolymarketGraphQLClient(
|
|
28
|
+
endpoint_name="positions_subgraph"
|
|
29
|
+
)
|
|
25
30
|
|
|
26
31
|
def _build_url(self, endpoint: str) -> str:
|
|
27
32
|
return urljoin(self.base_url, endpoint)
|
|
@@ -31,6 +36,35 @@ class PolymarketDataClient:
|
|
|
31
36
|
response.raise_for_status()
|
|
32
37
|
return response.json()["data"]
|
|
33
38
|
|
|
39
|
+
def get_all_positions(
|
|
40
|
+
self,
|
|
41
|
+
user: EthAddress,
|
|
42
|
+
size_threshold: float = 0.0,
|
|
43
|
+
):
|
|
44
|
+
# data-api /positions endpoint does not support fetching all positions without filters
|
|
45
|
+
# a workaround is to use the GraphQL positions subgraph directly
|
|
46
|
+
query = f"""query {{
|
|
47
|
+
userBalances(where: {{
|
|
48
|
+
user: "{user.lower()}",
|
|
49
|
+
balance_gt: "{int(size_threshold * 10**6)}"
|
|
50
|
+
}}) {{
|
|
51
|
+
user
|
|
52
|
+
asset {{
|
|
53
|
+
id
|
|
54
|
+
condition {{
|
|
55
|
+
id
|
|
56
|
+
}}
|
|
57
|
+
complement
|
|
58
|
+
outcomeIndex
|
|
59
|
+
}}
|
|
60
|
+
balance
|
|
61
|
+
}}
|
|
62
|
+
}}
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
response = self.gql_positions_client.query(query)
|
|
66
|
+
return [GQLPosition(**pos) for pos in response["userBalances"]]
|
|
67
|
+
|
|
34
68
|
def get_positions(
|
|
35
69
|
self,
|
|
36
70
|
user: EthAddress,
|
|
@@ -188,7 +222,11 @@ class PolymarketDataClient:
|
|
|
188
222
|
min_balance: int = 1,
|
|
189
223
|
) -> list[HolderResponse]:
|
|
190
224
|
"""Takes in a condition_id and returns top holders for each corresponding token_id."""
|
|
191
|
-
params
|
|
225
|
+
params: dict[str, int | str] = {
|
|
226
|
+
"market": condition_id,
|
|
227
|
+
"limit": limit,
|
|
228
|
+
"min_balance": min_balance,
|
|
229
|
+
}
|
|
192
230
|
response = self.client.get(self._build_url("/holders"), params=params)
|
|
193
231
|
response.raise_for_status()
|
|
194
232
|
return [HolderResponse(**holder_data) for holder_data in response.json()]
|
|
@@ -298,7 +336,7 @@ class PolymarketDataClient:
|
|
|
298
336
|
window: Literal["1d", "7d", "30d", "all"] = "all",
|
|
299
337
|
):
|
|
300
338
|
"""Get a user's overall profit or volume in the last day, week, month or all."""
|
|
301
|
-
params = {
|
|
339
|
+
params: dict[str, int | str] = {
|
|
302
340
|
"address": user,
|
|
303
341
|
"window": window,
|
|
304
342
|
"limit": 1,
|
|
@@ -104,29 +104,29 @@ class PolymarketGammaClient:
|
|
|
104
104
|
|
|
105
105
|
def get_markets(
|
|
106
106
|
self,
|
|
107
|
-
limit:
|
|
108
|
-
offset:
|
|
109
|
-
order:
|
|
107
|
+
limit: int | None = None,
|
|
108
|
+
offset: int | None = None,
|
|
109
|
+
order: str | None = None,
|
|
110
110
|
ascending: bool = True,
|
|
111
|
-
archived:
|
|
112
|
-
active:
|
|
113
|
-
closed:
|
|
114
|
-
slugs:
|
|
115
|
-
market_ids:
|
|
116
|
-
token_ids:
|
|
117
|
-
condition_ids:
|
|
118
|
-
tag_id:
|
|
119
|
-
related_tags:
|
|
120
|
-
liquidity_num_min:
|
|
121
|
-
liquidity_num_max:
|
|
122
|
-
volume_num_min:
|
|
123
|
-
volume_num_max:
|
|
124
|
-
start_date_min:
|
|
125
|
-
start_date_max:
|
|
126
|
-
end_date_min:
|
|
127
|
-
end_date_max:
|
|
111
|
+
archived: bool | None = None,
|
|
112
|
+
active: bool | None = None,
|
|
113
|
+
closed: bool | None = None,
|
|
114
|
+
slugs: list[str] | None = None,
|
|
115
|
+
market_ids: list[int] | None = None,
|
|
116
|
+
token_ids: list[str] | None = None,
|
|
117
|
+
condition_ids: list[str] | None = None,
|
|
118
|
+
tag_id: int | None = None,
|
|
119
|
+
related_tags: bool | None = False,
|
|
120
|
+
liquidity_num_min: float | None = None,
|
|
121
|
+
liquidity_num_max: float | None = None,
|
|
122
|
+
volume_num_min: float | None = None,
|
|
123
|
+
volume_num_max: float | None = None,
|
|
124
|
+
start_date_min: datetime | None = None,
|
|
125
|
+
start_date_max: datetime | None = None,
|
|
126
|
+
end_date_min: datetime | None = None,
|
|
127
|
+
end_date_max: datetime | None = None,
|
|
128
128
|
) -> list[GammaMarket]:
|
|
129
|
-
params = {}
|
|
129
|
+
params: dict[str, float | int | list[int] | str | list[str] | bool] = {}
|
|
130
130
|
if limit:
|
|
131
131
|
params["limit"] = limit
|
|
132
132
|
if offset:
|