polymarket-apis 0.2.6__py3-none-any.whl → 0.3.0__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 +0 -2
- polymarket_apis/clients/clob_client.py +17 -13
- polymarket_apis/clients/data_client.py +5 -5
- polymarket_apis/clients/gamma_client.py +10 -7
- polymarket_apis/clients/graphql_client.py +43 -0
- polymarket_apis/clients/web3_client.py +1 -0
- polymarket_apis/clients/websockets_client.py +1 -2
- polymarket_apis/types/clob_types.py +2 -2
- polymarket_apis/types/data_types.py +2 -2
- polymarket_apis/types/websockets_types.py +3 -3
- polymarket_apis/utilities/order_builder/builder.py +3 -1
- polymarket_apis/utilities/order_builder/helpers.py +13 -11
- polymarket_apis/utilities/schemas/activity-subgraph.graphql +86 -0
- polymarket_apis/utilities/schemas/open-interest.graphql +30 -0
- polymarket_apis-0.3.0.dist-info/METADATA +161 -0
- {polymarket_apis-0.2.6.dist-info → polymarket_apis-0.3.0.dist-info}/RECORD +17 -14
- polymarket_apis-0.2.6.dist-info/METADATA +0 -18
- {polymarket_apis-0.2.6.dist-info → polymarket_apis-0.3.0.dist-info}/WHEEL +0 -0
polymarket_apis/__init__.py
CHANGED
|
@@ -16,6 +16,7 @@ from ..types.clob_types import (
|
|
|
16
16
|
CreateOrderOptions,
|
|
17
17
|
DailyEarnedReward,
|
|
18
18
|
MarketOrderArgs,
|
|
19
|
+
MarketRewards,
|
|
19
20
|
Midpoint,
|
|
20
21
|
OpenOrder,
|
|
21
22
|
OrderArgs,
|
|
@@ -31,7 +32,6 @@ from ..types.clob_types import (
|
|
|
31
32
|
Price,
|
|
32
33
|
PriceHistory,
|
|
33
34
|
RequestArgs,
|
|
34
|
-
RewardsMarket,
|
|
35
35
|
Spread,
|
|
36
36
|
TickSize,
|
|
37
37
|
TokenBidAskDict,
|
|
@@ -480,6 +480,7 @@ class PolymarketClobClient:
|
|
|
480
480
|
self.creds,
|
|
481
481
|
RequestArgs(method="POST", request_path=POST_ORDERS, body=body),
|
|
482
482
|
)
|
|
483
|
+
|
|
483
484
|
try:
|
|
484
485
|
response = self.client.post(
|
|
485
486
|
self._build_url("/orders"),
|
|
@@ -524,12 +525,15 @@ class PolymarketClobClient:
|
|
|
524
525
|
return self.builder.calculate_buy_market_price(
|
|
525
526
|
book.asks, amount, order_type,
|
|
526
527
|
)
|
|
527
|
-
if
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
528
|
+
if side == "SELL":
|
|
529
|
+
if book.bids is None:
|
|
530
|
+
msg = "No bid orders available"
|
|
531
|
+
raise LiquidityError(msg)
|
|
532
|
+
return self.builder.calculate_sell_market_price(
|
|
533
|
+
book.bids, amount, order_type,
|
|
534
|
+
)
|
|
535
|
+
msg = 'Side must be "BUY" or "SELL"'
|
|
536
|
+
raise ValueError(msg)
|
|
533
537
|
|
|
534
538
|
def create_market_order(self, order_args: MarketOrderArgs, options: Optional[PartialCreateOrderOptions] = None):
|
|
535
539
|
"""Creates and signs a market order."""
|
|
@@ -633,9 +637,9 @@ class PolymarketClobClient:
|
|
|
633
637
|
response.raise_for_status()
|
|
634
638
|
return response.json()
|
|
635
639
|
|
|
636
|
-
def
|
|
640
|
+
def get_market_rewards(self, condition_id: Keccak256) -> MarketRewards:
|
|
637
641
|
"""
|
|
638
|
-
Get the
|
|
642
|
+
Get the MarketRewards for a given market (condition_id).
|
|
639
643
|
|
|
640
644
|
- metadata, tokens, max_spread, min_size, rewards_config, market_competitiveness.
|
|
641
645
|
"""
|
|
@@ -644,7 +648,7 @@ class PolymarketClobClient:
|
|
|
644
648
|
|
|
645
649
|
response = self.client.get(self._build_url("/rewards/markets/" + condition_id), headers=headers)
|
|
646
650
|
response.raise_for_status()
|
|
647
|
-
return next(
|
|
651
|
+
return next(MarketRewards(**market) for market in response.json()["data"])
|
|
648
652
|
|
|
649
653
|
def get_trades(
|
|
650
654
|
self,
|
|
@@ -653,7 +657,7 @@ class PolymarketClobClient:
|
|
|
653
657
|
trade_id: Optional[str] = None,
|
|
654
658
|
before: Optional[datetime] = None,
|
|
655
659
|
after: Optional[datetime] = None,
|
|
656
|
-
|
|
660
|
+
proxy_address: Optional[int] = None,
|
|
657
661
|
next_cursor="MA==") -> list[PolygonTrade]:
|
|
658
662
|
"""Fetches the trade history for a user."""
|
|
659
663
|
params = {}
|
|
@@ -667,8 +671,8 @@ class PolymarketClobClient:
|
|
|
667
671
|
params["before"] = int(before.replace(microsecond=0).timestamp())
|
|
668
672
|
if after:
|
|
669
673
|
params["after"] = int(after.replace(microsecond=0).timestamp())
|
|
670
|
-
if
|
|
671
|
-
params["maker_address"] =
|
|
674
|
+
if proxy_address:
|
|
675
|
+
params["maker_address"] = proxy_address
|
|
672
676
|
|
|
673
677
|
request_args = RequestArgs(method="GET", request_path=TRADES)
|
|
674
678
|
headers = create_level_2_headers(self.signer, self.creds, request_args)
|
|
@@ -155,7 +155,7 @@ class PolymarketDataClient:
|
|
|
155
155
|
def get_value(
|
|
156
156
|
self,
|
|
157
157
|
user: str,
|
|
158
|
-
|
|
158
|
+
condition_ids: Optional[Union[str, list[str]]] = None,
|
|
159
159
|
) -> ValueResponse:
|
|
160
160
|
"""
|
|
161
161
|
Get the current value of a user's position in a set of markets.
|
|
@@ -166,10 +166,10 @@ class PolymarketDataClient:
|
|
|
166
166
|
- list[str] --> sum of the values of positions.
|
|
167
167
|
"""
|
|
168
168
|
params = {"user": user}
|
|
169
|
-
if isinstance(
|
|
170
|
-
params["market"] =
|
|
171
|
-
if isinstance(
|
|
172
|
-
params["market"] = ",".join(
|
|
169
|
+
if isinstance(condition_ids, str):
|
|
170
|
+
params["market"] = condition_ids
|
|
171
|
+
if isinstance(condition_ids, list):
|
|
172
|
+
params["market"] = ",".join(condition_ids)
|
|
173
173
|
|
|
174
174
|
response = self.client.get(self._build_url("/value"), params=params)
|
|
175
175
|
response.raise_for_status()
|
|
@@ -30,13 +30,15 @@ class PolymarketGammaClient:
|
|
|
30
30
|
offset: Optional[int] = None,
|
|
31
31
|
order: Optional[str] = None,
|
|
32
32
|
ascending: bool = True,
|
|
33
|
-
ids: Optional[list[int]] = None,
|
|
34
|
-
slugs: Optional[list[str]] = None,
|
|
35
33
|
archived: Optional[bool] = None,
|
|
36
34
|
active: Optional[bool] = None,
|
|
37
35
|
closed: Optional[bool] = None,
|
|
36
|
+
slugs: Optional[list[str]] = None,
|
|
37
|
+
market_ids: Optional[list[int]] = None,
|
|
38
38
|
token_ids: Optional[list[str]] = None,
|
|
39
39
|
condition_ids: Optional[list[str]] = None,
|
|
40
|
+
tag_id: Optional[int] = None,
|
|
41
|
+
related_tags: Optional[bool] = False,
|
|
40
42
|
liquidity_num_min: Optional[float] = None,
|
|
41
43
|
liquidity_num_max: Optional[float] = None,
|
|
42
44
|
volume_num_min: Optional[float] = None,
|
|
@@ -45,8 +47,6 @@ class PolymarketGammaClient:
|
|
|
45
47
|
start_date_max: Optional[datetime] = None,
|
|
46
48
|
end_date_min: Optional[datetime] = None,
|
|
47
49
|
end_date_max: Optional[datetime] = None,
|
|
48
|
-
tag_id: Optional[int] = None,
|
|
49
|
-
related_tags: Optional[bool] = False,
|
|
50
50
|
) -> list[GammaMarket]:
|
|
51
51
|
params = {}
|
|
52
52
|
if limit:
|
|
@@ -56,8 +56,6 @@ class PolymarketGammaClient:
|
|
|
56
56
|
if order:
|
|
57
57
|
params["order"] = order
|
|
58
58
|
params["ascending"] = ascending
|
|
59
|
-
if ids:
|
|
60
|
-
params["id"] = ids
|
|
61
59
|
if slugs:
|
|
62
60
|
params["slug"] = slugs
|
|
63
61
|
if archived is not None:
|
|
@@ -66,6 +64,8 @@ class PolymarketGammaClient:
|
|
|
66
64
|
params["active"] = active
|
|
67
65
|
if closed is not None:
|
|
68
66
|
params["closed"] = closed
|
|
67
|
+
if market_ids:
|
|
68
|
+
params["id"] = market_ids
|
|
69
69
|
if token_ids:
|
|
70
70
|
params["clob_token_ids"] = token_ids
|
|
71
71
|
if condition_ids:
|
|
@@ -243,13 +243,16 @@ class PolymarketGammaClient:
|
|
|
243
243
|
sort: Literal["volume", "volume_24hr", "liquidity", "start_date", "end_date", "competitive"] = "volume_24hr",
|
|
244
244
|
page: int = 1,
|
|
245
245
|
limit_per_type: int = 50, # max is 50
|
|
246
|
+
presets: Optional[Literal["EventsHybrid", "EventsTitle"] | list[Literal["EventsHybrid", "EventsTitle"]]] = None,
|
|
246
247
|
) -> EventList:
|
|
247
248
|
"""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
|
|
249
|
+
params = {"q": query,"page": page, "limit_per_type": limit_per_type, "events_status": status, "active": active}
|
|
249
250
|
if sort:
|
|
250
251
|
params["sort"] = sort
|
|
251
252
|
if sort == "end_date":
|
|
252
253
|
params["ascending"] = "true"
|
|
254
|
+
if presets:
|
|
255
|
+
params["presets"] = presets
|
|
253
256
|
response = self.client.get(self._build_url("/public-search"), params=params)
|
|
254
257
|
response.raise_for_status()
|
|
255
258
|
return EventList(**response.json())
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
from gql import Client, gql
|
|
4
|
+
from gql.transport.httpx import HTTPXAsyncTransport, HTTPXTransport
|
|
5
|
+
|
|
6
|
+
from ..utilities.config import GRAPHQL_ENDPOINTS
|
|
7
|
+
|
|
8
|
+
EndpointName = Literal[
|
|
9
|
+
"activity_subgraph",
|
|
10
|
+
"fpmm_subgraph",
|
|
11
|
+
"open_interest_subgraph",
|
|
12
|
+
"orderbook_subgraph",
|
|
13
|
+
"pnl_subgraph",
|
|
14
|
+
"positions_subgraph",
|
|
15
|
+
"sports_oracle_subgraph",
|
|
16
|
+
"wallet_subgraph",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PolymarketGraphQLClient:
|
|
21
|
+
"""Synchronous GraphQL client for Polymarket subgraphs."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, endpoint_name: EndpointName) -> None:
|
|
24
|
+
endpoint_url = GRAPHQL_ENDPOINTS[endpoint_name]
|
|
25
|
+
self.transport = HTTPXTransport(url=endpoint_url)
|
|
26
|
+
self.client = Client(transport=self.transport, fetch_schema_from_transport=False)
|
|
27
|
+
|
|
28
|
+
def query(self, query_string: str) -> dict:
|
|
29
|
+
with self.client as session:
|
|
30
|
+
return session.execute(gql(query_string))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AsyncPolymarketGraphQLClient:
|
|
34
|
+
"""Asynchronous GraphQL client for Polymarket subgraphs."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, endpoint_name: EndpointName) -> None:
|
|
37
|
+
endpoint_url = GRAPHQL_ENDPOINTS[endpoint_name]
|
|
38
|
+
self.transport = HTTPXAsyncTransport(url=endpoint_url)
|
|
39
|
+
self.client = Client(transport=self.transport, fetch_schema_from_transport=False)
|
|
40
|
+
|
|
41
|
+
async def query(self, query_string: str) -> dict:
|
|
42
|
+
async with self.client as session:
|
|
43
|
+
return await session.execute(gql(query_string))
|
|
@@ -6,8 +6,6 @@ from lomond import WebSocket
|
|
|
6
6
|
from lomond.persist import persist
|
|
7
7
|
from pydantic import ValidationError
|
|
8
8
|
|
|
9
|
-
from polymarket_apis.utilities.exceptions import AuthenticationRequiredError
|
|
10
|
-
|
|
11
9
|
from ..types.clob_types import ApiCreds
|
|
12
10
|
from ..types.websockets_types import (
|
|
13
11
|
ActivityOrderMatchEvent,
|
|
@@ -32,6 +30,7 @@ from ..types.websockets_types import (
|
|
|
32
30
|
TickSizeChangeEvent,
|
|
33
31
|
TradeEvent,
|
|
34
32
|
)
|
|
33
|
+
from ..utilities.exceptions import AuthenticationRequiredError
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
def _process_market_event(event):
|
|
@@ -153,7 +153,7 @@ class PolymarketRewardItem(BaseModel):
|
|
|
153
153
|
market_competitiveness: float
|
|
154
154
|
|
|
155
155
|
|
|
156
|
-
class
|
|
156
|
+
class MarketRewards(BaseModel):
|
|
157
157
|
condition_id: Keccak256
|
|
158
158
|
question: str
|
|
159
159
|
market_slug: str
|
|
@@ -254,7 +254,7 @@ class OpenOrder(BaseModel):
|
|
|
254
254
|
price: float
|
|
255
255
|
outcome: str
|
|
256
256
|
expiration: datetime
|
|
257
|
-
order_type: Literal["GTC", "
|
|
257
|
+
order_type: Literal["GTC", "GTD"]
|
|
258
258
|
associate_trades: list[str]
|
|
259
259
|
created_at: datetime
|
|
260
260
|
|
|
@@ -12,11 +12,11 @@ class Position(BaseModel):
|
|
|
12
12
|
|
|
13
13
|
# Asset information
|
|
14
14
|
token_id: str = Field(alias="asset")
|
|
15
|
+
complementary_token_id: str = Field(alias="oppositeAsset")
|
|
15
16
|
condition_id: Keccak256 = Field(alias="conditionId")
|
|
16
17
|
outcome: str
|
|
18
|
+
complementary_outcome: str = Field(alias="oppositeOutcome")
|
|
17
19
|
outcome_index: int = Field(alias="outcomeIndex")
|
|
18
|
-
opposite_outcome: str = Field(alias="oppositeOutcome")
|
|
19
|
-
opposite_asset: str = Field(alias="oppositeAsset")
|
|
20
20
|
|
|
21
21
|
# Position details
|
|
22
22
|
size: float
|
|
@@ -67,7 +67,7 @@ class OrderEvent(BaseModel):
|
|
|
67
67
|
size_matched: float
|
|
68
68
|
original_size: float
|
|
69
69
|
outcome: str
|
|
70
|
-
order_type: Literal["GTC", "FOK", "
|
|
70
|
+
order_type: Literal["GTC", "GTD", "FOK", "FAK"]
|
|
71
71
|
|
|
72
72
|
created_at: datetime
|
|
73
73
|
expiration: Optional[datetime] = None
|
|
@@ -284,16 +284,16 @@ class MarketStatusChangeEvent(BaseModel):
|
|
|
284
284
|
topic: Literal["clob_market"]
|
|
285
285
|
|
|
286
286
|
class LiveDataOrderEvent(BaseModel):
|
|
287
|
-
connection_id: str
|
|
288
287
|
payload: OrderEvent
|
|
289
288
|
timestamp: datetime
|
|
289
|
+
connection_id: str
|
|
290
290
|
type: Literal["order"]
|
|
291
291
|
topic: Literal["clob_user"]
|
|
292
292
|
|
|
293
293
|
class LiveDataTradeEvent(BaseModel):
|
|
294
|
-
connection_id: str
|
|
295
294
|
payload: TradeEvent
|
|
296
295
|
timestamp: datetime
|
|
296
|
+
connection_id: str
|
|
297
297
|
type: Literal["trade"]
|
|
298
298
|
topic: Literal["clob_user"]
|
|
299
299
|
|
|
@@ -220,7 +220,7 @@ class OrderBuilder:
|
|
|
220
220
|
def calculate_sell_market_price(
|
|
221
221
|
self,
|
|
222
222
|
bids: list[OrderSummary], # expected to be sorted from worst to best price (low to high)
|
|
223
|
-
amount_to_match: float, # in
|
|
223
|
+
amount_to_match: float, # in shares
|
|
224
224
|
order_type: OrderType,
|
|
225
225
|
) -> float:
|
|
226
226
|
if not bids:
|
|
@@ -231,8 +231,10 @@ class OrderBuilder:
|
|
|
231
231
|
for p in reversed(bids):
|
|
232
232
|
sum += float(p.size)
|
|
233
233
|
if sum >= amount_to_match:
|
|
234
|
+
print(f"market order price {p.price}")
|
|
234
235
|
return float(p.price)
|
|
235
236
|
|
|
237
|
+
|
|
236
238
|
if order_type == OrderType.FOK:
|
|
237
239
|
msg = "no match"
|
|
238
240
|
raise ValueError(msg)
|
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
import hashlib
|
|
2
|
-
from decimal import Decimal
|
|
3
|
-
from math import ceil, floor
|
|
2
|
+
from decimal import ROUND_CEILING, ROUND_FLOOR, ROUND_HALF_UP, Decimal
|
|
4
3
|
|
|
5
4
|
from ...types.clob_types import OrderBookSummary, TickSize
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def round_down(x: float, sig_digits: int) -> float:
|
|
9
|
-
|
|
8
|
+
exp = Decimal(1).scaleb(-sig_digits)
|
|
9
|
+
return float(Decimal(str(x)).quantize(exp=exp, rounding=ROUND_FLOOR))
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def round_normal(x: float, sig_digits: int) -> float:
|
|
13
|
-
|
|
13
|
+
exp = Decimal(1).scaleb(-sig_digits)
|
|
14
|
+
return float(Decimal(str(x)).quantize(exp=exp, rounding=ROUND_HALF_UP))
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def round_up(x: float, sig_digits: int) -> float:
|
|
17
|
-
|
|
18
|
+
exp = Decimal(1).scaleb(-sig_digits)
|
|
19
|
+
return float(Decimal(str(x)).quantize(exp=exp, rounding=ROUND_CEILING))
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
def to_token_decimals(x: float) -> int:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
exp = Decimal(1)
|
|
24
|
+
return int(
|
|
25
|
+
Decimal(str(x)) * Decimal(10**6).quantize(exp=exp, rounding=ROUND_HALF_UP),
|
|
26
|
+
)
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
def decimal_places(x: float) -> int:
|
|
28
30
|
"""
|
|
29
|
-
Returns the number of decimal places in a
|
|
31
|
+
Returns the number of decimal places in a numeric value.
|
|
30
32
|
|
|
31
33
|
Assumes x is always a finite, non-special value (not NaN or Infinity).
|
|
32
34
|
"""
|
|
@@ -34,7 +36,7 @@ def decimal_places(x: float) -> int:
|
|
|
34
36
|
if not isinstance(exponent, int):
|
|
35
37
|
msg = "Input must be a finite float."
|
|
36
38
|
raise TypeError(msg)
|
|
37
|
-
return
|
|
39
|
+
return max(0, -exponent)
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
type Split @entity {
|
|
2
|
+
"Transaction Hash"
|
|
3
|
+
id: ID!
|
|
4
|
+
"Timestamp at which split occurred"
|
|
5
|
+
timestamp: BigInt!
|
|
6
|
+
"Address which is performing this split"
|
|
7
|
+
stakeholder: String!
|
|
8
|
+
"Condition on which split is occuring"
|
|
9
|
+
condition: String!
|
|
10
|
+
"The amount of collateral/outcome tokens being split"
|
|
11
|
+
amount: BigInt!
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type Merge @entity {
|
|
15
|
+
"Transaction Hash"
|
|
16
|
+
id: ID!
|
|
17
|
+
"Timestamp at which merge occurred"
|
|
18
|
+
timestamp: BigInt!
|
|
19
|
+
"Address which is performing this merge"
|
|
20
|
+
stakeholder: String!
|
|
21
|
+
"Token which is collateralising positions being merged"
|
|
22
|
+
condition: String!
|
|
23
|
+
"The amount of collateral/outcome tokens being merged"
|
|
24
|
+
amount: BigInt!
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type Redemption @entity {
|
|
28
|
+
"Transaction Hash"
|
|
29
|
+
id: ID!
|
|
30
|
+
"Timestamp at which redemption occurred"
|
|
31
|
+
timestamp: BigInt!
|
|
32
|
+
"Address which is redeeming these outcomes"
|
|
33
|
+
redeemer: String!
|
|
34
|
+
"Condition on which redemption is occuring"
|
|
35
|
+
condition: String!
|
|
36
|
+
"Outcomes which are being redeemed"
|
|
37
|
+
indexSets: [BigInt!]!
|
|
38
|
+
"The amount of collateral being claimed"
|
|
39
|
+
payout: BigInt!
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type NegRiskConversion @entity {
|
|
43
|
+
"Transaction Hash"
|
|
44
|
+
id: ID!
|
|
45
|
+
"Timestamp at which conversion occurred"
|
|
46
|
+
timestamp: BigInt!
|
|
47
|
+
"Address which is performing this conversion"
|
|
48
|
+
stakeholder: String!
|
|
49
|
+
"Neg Risk Market Id assigned to the event"
|
|
50
|
+
negRiskMarketId: String!
|
|
51
|
+
"The amount of each token being converted"
|
|
52
|
+
amount: BigInt!
|
|
53
|
+
"The index set of the outcome tokens being converted"
|
|
54
|
+
indexSet: BigInt!
|
|
55
|
+
"The number of questions at the time of conversion"
|
|
56
|
+
questionCount: Int!
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# Neg Risk Events/Markets
|
|
60
|
+
type NegRiskEvent @entity {
|
|
61
|
+
"negRiskMarketId"
|
|
62
|
+
id: ID!
|
|
63
|
+
"Question Count"
|
|
64
|
+
questionCount: Int!
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Fixed Product Market Makers
|
|
68
|
+
type FixedProductMarketMaker @entity {
|
|
69
|
+
"Market maker address"
|
|
70
|
+
id: ID!
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Metadata for the market, keyed by positionId
|
|
74
|
+
type Position @entity {
|
|
75
|
+
"ERC1155 TokenID of the CTF Asset"
|
|
76
|
+
id: ID!
|
|
77
|
+
"Condition that the token is linked to"
|
|
78
|
+
condition: String!
|
|
79
|
+
"Outcome Index"
|
|
80
|
+
outcomeIndex: BigInt!
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type Condition @entity {
|
|
84
|
+
"Condition ID"
|
|
85
|
+
id: ID!
|
|
86
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type Condition @entity {
|
|
2
|
+
"conditionId"
|
|
3
|
+
id: ID!
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
# Neg Risk Events/Markets
|
|
7
|
+
type NegRiskEvent @entity {
|
|
8
|
+
"negRiskMarketId"
|
|
9
|
+
id: ID!
|
|
10
|
+
"Fee Bps"
|
|
11
|
+
feeBps: BigInt!
|
|
12
|
+
"Question Count"
|
|
13
|
+
questionCount: Int!
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
# Market Open Interest
|
|
17
|
+
type MarketOpenInterest @entity {
|
|
18
|
+
"Condition ID"
|
|
19
|
+
id: ID!
|
|
20
|
+
"Open interest for the market"
|
|
21
|
+
amount: BigInt!
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Global Open Interest
|
|
25
|
+
type GlobalOpenInterest @entity {
|
|
26
|
+
"Empty string"
|
|
27
|
+
id: ID!
|
|
28
|
+
"Global Open Interest"
|
|
29
|
+
amount: BigInt!
|
|
30
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: polymarket-apis
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Unified Polymarket APIs - clob, gamma, data, web3, websockets
|
|
5
|
+
Author-email: Razvan Gheorghe <razvan@gheorghe.me>
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Requires-Dist: gql[httpx]>=4.0.0
|
|
8
|
+
Requires-Dist: httpx[http2]>=0.25.1
|
|
9
|
+
Requires-Dist: lomond>=0.3.3
|
|
10
|
+
Requires-Dist: poly-eip712-structs>=0.0.1
|
|
11
|
+
Requires-Dist: py-order-utils>=0.3.2
|
|
12
|
+
Requires-Dist: pydantic>=2.10.5
|
|
13
|
+
Requires-Dist: web3>=7.0
|
|
14
|
+
Requires-Dist: wsaccel>=0.6.7
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# polymarket-apis [](https://pypi.org/project/polymarket-apis/)
|
|
18
|
+
|
|
19
|
+
Polymarket CLOB, Gamma, Data, Web3, Websockets and GraphQL clients.
|
|
20
|
+
|
|
21
|
+
## Polymarket Mental Models
|
|
22
|
+
|
|
23
|
+
### Events, Markets and Outcomes
|
|
24
|
+
|
|
25
|
+
The Polymarket ecosystem is organized hierarchically:
|
|
26
|
+
|
|
27
|
+
```mermaid
|
|
28
|
+
flowchart LR
|
|
29
|
+
A([Event]) --- B([Market A])
|
|
30
|
+
A --- C([Market B])
|
|
31
|
+
A ~~~ Dot1@{ shape: sm-circ}
|
|
32
|
+
A ~~~ Dot2@{ shape: sm-circ}
|
|
33
|
+
A ~~~ Dot3@{ shape: sm-circ}
|
|
34
|
+
A -.- D([Market n])
|
|
35
|
+
B --- E([Outcome 1])
|
|
36
|
+
B --- F([Outcome 2])
|
|
37
|
+
C --- G([Outcome 1])
|
|
38
|
+
C --- H([Outcome 2])
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- **Event** — represents a proposition or question such as “How many Fed rate cuts in 2025?”.
|
|
42
|
+
- Identified by a human-readable **`slug`** (e.g. `how-many-fed-rate-cuts-in-2025`) and an **event `id`** (e.g. `16085`).
|
|
43
|
+
|
|
44
|
+
- **Market** — represents a specific option for the related event (e.g. 1 rate cut in 2025). An Event has 1 or more corresponding Markets. (e.g. 9 options in this case - {0, 1, 2, ..., 7, 8 or more} rate cuts in 2025)
|
|
45
|
+
- Identified by a **`condition id`** (e.g. `0x8e9b6942b4dac3117dadfacac2edb390b6d62d59c14152774bb5fcd983fc134e` for 1 rate cut in 2025), a human-readable **`slug`** (e.g. `'will-1-fed-rate-cut-happen-in-2025'`) and a **market `id`** (e.g. `516724`).
|
|
46
|
+
|
|
47
|
+
- **Outcome** — represents a binary option related to a market. (most commonly `Yes`/`No`, but can be e.g. `Paris Saint-Germain`/`Inter Milan` in the case of a match where draws are not possible)
|
|
48
|
+
- Identified by a **`token id`** (e.g. `15353185604353847122370324954202969073036867278400776447048296624042585335546` for the `Yes` outcome in the 1 rate cut in 2025 market)
|
|
49
|
+
|
|
50
|
+
### Tokens
|
|
51
|
+
- **Tokens** are the blockchain implementation of **Outcomes** - tradable digital assets on the Polygon blockchain that users buy, hold and sell on Polygon.
|
|
52
|
+
- This helps ensure the logic of binary outcome prediction markets through smart contracts (e.g. collateralization, token prices going to $1.00 or $0.00 after resolution, splits/merges).
|
|
53
|
+
|
|
54
|
+
### Splits and Merges
|
|
55
|
+
- Holding 1 `Yes` share + 1 `No` share in a **Market** (e.g. `'will-1-fed-rate-cut-happen-in-2025'`) covers the entire universe of possibilities and guarantees a $1.00 payout regardless of outcome. This mathematical relationship enables Polymarket's core mechanisms: splitting (1 USDC → 1 `Yes` + 1 `No`) and merging (1 `Yes` + 1 `No` → 1 USDC) at any point before resolution.
|
|
56
|
+
- Splits are the only way tokens are created. Either a user splits USDC into equal shares of the complementary tokens or Polymarket automatically splits USDC when it matches an `Yes` buy order at e.g. 30¢ with a `No` buy order at 70¢.
|
|
57
|
+
|
|
58
|
+
### Unified Order Book
|
|
59
|
+
- Polymarket uses traditional exchange mechanics - a Central Limit Order Book (CLOB), where users place buy and sell orders that get matched by price and time priority.
|
|
60
|
+
- However, because the `Yes` and `No` outcomes form a complete probability universe, certain orders become mathematically equivalent - allowing the matching engine to find trades as exemplified above.
|
|
61
|
+
- This unified structure means every **BUY** order for `Outcome 1` at price **X** is simultaneously visible as a **SELL** order for `Outcome 2` at price **(100¢ - X)**, creating deeper liquidity and tighter spreads than separate order books would allow.
|
|
62
|
+
|
|
63
|
+
### Negative Risk and Conversions
|
|
64
|
+
- If the **Markets** in and **Event** collectively cover a complete universe of possibilities (e.g. {0, 1, 2, ..., 7, 8 or more} rate cuts in 2025) and only one winner is possible, two collections of positions (made up of tokens and USDC) become mathematically equivalent and the **Event** is said to support negative risk.
|
|
65
|
+
- e.g. Hold 1 `No` token in the 0 rate cuts in 2025. This is equivalent to holding 1 `Yes` token in each of the other **Markets** {1, 2, ..., 7, 8 or more}.
|
|
66
|
+
- An interesting consequence is that holding `No` tokens in more than one **Market** is equivalent to `Yes` tokens ***and*** some USDC.
|
|
67
|
+
- e.g. Hold 1 `No` token on each of {0, 1, 2, ..., 7, 8 or more} rate cuts in 2025. Because only one winner is possible, this guarantees that 8 out of the 9 **Markets** resolve to `No`. This is equivalent to a position of 8 USDC.
|
|
68
|
+
- e.g. Hold 1 `No` token on each of {0, 1} rate cuts in 2025. This is equivalent to 1 `Yes` token in {2, ..., 7, 8 or more} and 1 USDC.
|
|
69
|
+
- Polymarket allows for the one way (for capital efficiency) conversion from `No` tokens to a collection of `Yes` tokens and USDC before resolution through a smart contract.
|
|
70
|
+
|
|
71
|
+
## Clients overview
|
|
72
|
+
- ### PolymarketClobClient - Order book related operations
|
|
73
|
+
- #### Order book
|
|
74
|
+
- get one or more order books, best price, spread, midpoint, last trade price by `token_id`(s)
|
|
75
|
+
- #### Orders
|
|
76
|
+
- create and post limit or market orders
|
|
77
|
+
- cancel one or more orders by `order_id`(s)
|
|
78
|
+
- get active orders
|
|
79
|
+
- #### Trades
|
|
80
|
+
- get trade history for a user with filtering by `condition_id`, `token_id`, `trade_id`, time window
|
|
81
|
+
- #### Rewards
|
|
82
|
+
- check if one or more orders are scoring for liquidity rewards by `order_id`(s)
|
|
83
|
+
- get daily earned rewards
|
|
84
|
+
- check if a **Market** offers rewards by `condition_id` - **get_market_rewards()**
|
|
85
|
+
- get all active markets that offer rewards sorted by different metrics and ordered, filtered by a query, show your favourites from the web app - **get_reward_markets()** (*naming would do with some work*)
|
|
86
|
+
- #### Miscellaneous
|
|
87
|
+
- get price history
|
|
88
|
+
- get **ClobMarket** by `condition_id`
|
|
89
|
+
- get all **ClobMarkets**
|
|
90
|
+
|
|
91
|
+
### PolymarketGammaClient - Market/Event related operations
|
|
92
|
+
- #### Market
|
|
93
|
+
- get **GammaMarket** by `market_id`
|
|
94
|
+
- get **GammaMarkets** with pagination (offset and limit), filter by `slug`s, `market_id`s, `token_id`s, `condition_id`s, `tag_id` or filtered by active, closed, archived, liquidity window, volume window, start date window, end date window and ordered
|
|
95
|
+
- #### Event
|
|
96
|
+
- get **Event** by `event_id`
|
|
97
|
+
- get **Events** with pagination, filter by `slug`s, `event_id`s, `tag_id` or filtered by active, closed, archived, liquidity window, volume window, start date window, end date window and ordered
|
|
98
|
+
- get all **Events** given some filtration
|
|
99
|
+
- search **Events**, filter by text query, active/resolved, sort by volume/volume_24hr/liquidity/start_date/end_date/competitive (tries to mimic the web app search bar)
|
|
100
|
+
- #### Miscellaneous
|
|
101
|
+
- grok event summary by **Event** `slug`
|
|
102
|
+
- grok election market explanation by candidate name and election title
|
|
103
|
+
|
|
104
|
+
### PolymarketDataClient - Portfolio related operations
|
|
105
|
+
- #### Positions
|
|
106
|
+
- get positions with pagination (offset and limit) by user address, filter by `condition_id`, position size, redeemability, mergeability, title
|
|
107
|
+
- #### Trades
|
|
108
|
+
- get trades with pagination, filter by `condition id`, user address, side, taker only or not, cash amount/token amount
|
|
109
|
+
- #### Activity
|
|
110
|
+
- get activity with pagination by user address, filter by type (trade, split, merge, redeem, reward, conversion), `condition_id`, time window, side, sort by timestamp/tokens/cash
|
|
111
|
+
- #### Holders
|
|
112
|
+
- get top holders by `condition_id`
|
|
113
|
+
- #### Value
|
|
114
|
+
- get positions value by user address and condition_ids
|
|
115
|
+
- `condition_ids` is ***None*** → total value of positions
|
|
116
|
+
- `condition_ids` is ***str*** → value of positions on a market
|
|
117
|
+
- `condition_ids` is ***list[str]*** → sum of values of positions on multiple markets
|
|
118
|
+
- #### Miscellaneous
|
|
119
|
+
- get pnl timeseries by user address for a period (1d, 1w, 1m, all) with frequency (1h, 3h, 12h, 1d)
|
|
120
|
+
- get overall pnl/volume by user address for a recent window (1d, 7d, 30d, all)
|
|
121
|
+
- get user rank on the profit/volume leaderboards by user address for a recent window (1d, 7d, 30d, all)
|
|
122
|
+
- get top users on the profit/volume leaderboards (at most 100) for a recent window (1d, 7d, 30d, all)
|
|
123
|
+
|
|
124
|
+
### PolymarketWeb3Client - Blockchain related operations
|
|
125
|
+
- #### Balance
|
|
126
|
+
- get usdc balance by user address
|
|
127
|
+
- get token balance by `token_id` and user address
|
|
128
|
+
- #### Token/USDC conversions
|
|
129
|
+
- split USDC into complementary tokens - needs `condition_id`, amount, neg_risk bool
|
|
130
|
+
- merge complementary tokens into USDC - needs `condition_id`, amount, neg_risk bool
|
|
131
|
+
- redeem token into USDC - needs `condition_id`, amounts array [`Yes` shares, `No` shares], neg_risk bool
|
|
132
|
+
- convert 1 or more `No` tokens in a *negative risk* **Event** into a collection of USDC and `Yes` tokens on the other **Markets** in the **Event**
|
|
133
|
+
|
|
134
|
+
### PolymarketWebsocketsClient - Real time data subscriptions
|
|
135
|
+
- subscribe to **market socket** with `token_ids` list, receive different event types:
|
|
136
|
+
- order book summary
|
|
137
|
+
- price change
|
|
138
|
+
- tick size change
|
|
139
|
+
- last trade price
|
|
140
|
+
- subscribe to **user socket** with **ApiCreds**, receive different event types:
|
|
141
|
+
- order (status - live, canceled, matched)
|
|
142
|
+
- trade (status - matched, mined, confirmed, retrying, failed)
|
|
143
|
+
- subscribe to **live data socket** with any combination described [here](https://github.com/Polymarket/real-time-data-client?tab=readme-ov-file#subscribe) - ***newest endpoint*** - includes the other sockets, receive:
|
|
144
|
+
- all of the above event types
|
|
145
|
+
- market (created, resolved)
|
|
146
|
+
- comment/reaction (created, removed)
|
|
147
|
+
- trades/orders_matched (all, not just yours) - filter by **Event** `slug` or **Market** `slug`
|
|
148
|
+
- crypto price
|
|
149
|
+
- request/quote (created, edited, canceled, expired) - rqf not public yet
|
|
150
|
+
|
|
151
|
+
### PolymarketGraphQLClient/AsyncPolymarketGraphQLClient - Goldsky hosted Subgraphs queries
|
|
152
|
+
- instantiate with an endpoint name from:
|
|
153
|
+
- activity_subgraph
|
|
154
|
+
- fpmm_subgraph
|
|
155
|
+
- open_interest_subgraph
|
|
156
|
+
- orderbook_subgraph
|
|
157
|
+
- pnl_subgraph
|
|
158
|
+
- positions_subgraph
|
|
159
|
+
- sports_oracle_subgraph
|
|
160
|
+
- wallet_subgraph
|
|
161
|
+
- ****query()**** takes in a GraphQL query string and returns the raw json
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
polymarket_apis/__init__.py,sha256=
|
|
1
|
+
polymarket_apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
polymarket_apis/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
polymarket_apis/clients/clob_client.py,sha256=
|
|
4
|
-
polymarket_apis/clients/data_client.py,sha256=
|
|
5
|
-
polymarket_apis/clients/gamma_client.py,sha256
|
|
6
|
-
polymarket_apis/clients/
|
|
7
|
-
polymarket_apis/clients/
|
|
3
|
+
polymarket_apis/clients/clob_client.py,sha256=HO9ACvdODfj6n_W7lkgpCAtm7Y-vEhGK-8bmEtnh8sI,31152
|
|
4
|
+
polymarket_apis/clients/data_client.py,sha256=zkfYoejsrAjwbhBfpMVLiM3YYoXqgvLhnHZ5fc7QVZI,8646
|
|
5
|
+
polymarket_apis/clients/gamma_client.py,sha256=-GhPBoRnnMl1Ex6oGI6ToKfGXGXVRjVZ-G1vO4eJjVI,12370
|
|
6
|
+
polymarket_apis/clients/graphql_client.py,sha256=kN3hk0kKmZhwnN5YfC-8XbebNyoho7dRdZC9p6aC8_A,1511
|
|
7
|
+
polymarket_apis/clients/web3_client.py,sha256=XQApKIAkS0-TAWrApI1DFDvW0udbpkWzXiyGXo-GNec,11223
|
|
8
|
+
polymarket_apis/clients/websockets_client.py,sha256=gJiJ087PenrpNG4Y2ffu0S1he82TQOJhD9JbLyMbc_U,7566
|
|
8
9
|
polymarket_apis/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
polymarket_apis/types/clob_types.py,sha256=
|
|
10
|
+
polymarket_apis/types/clob_types.py,sha256=LboySm6z_Pb-sf30BHATfi1-CC0LFT_CHv-gzJdkxk0,11692
|
|
10
11
|
polymarket_apis/types/common.py,sha256=eTY2kjOArzrZRVSmEJvxEyxGJeMx045R073EMZMzCKM,1629
|
|
11
|
-
polymarket_apis/types/data_types.py,sha256=
|
|
12
|
+
polymarket_apis/types/data_types.py,sha256=5vLo4CnAXApHhbPrtj_xnYQPeRnTYhjuY8EGJU7KeUU,4421
|
|
12
13
|
polymarket_apis/types/gamma_types.py,sha256=xSafNRgkYXqIq3Vd5J3k018ue79rEiulczwUHuP8Uxo,12535
|
|
13
|
-
polymarket_apis/types/websockets_types.py,sha256=
|
|
14
|
+
polymarket_apis/types/websockets_types.py,sha256=4a__lrxnFWkWnOa8i-6wsV5Q0AaLq3srPNDhnKyfGAo,12000
|
|
14
15
|
polymarket_apis/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
16
|
polymarket_apis/utilities/config.py,sha256=IfIBJa6rSi-e-9_HjeI8j4cD3MXtzRjoLzgcgn5tHbc,2448
|
|
16
17
|
polymarket_apis/utilities/constants.py,sha256=OdxaAsyYzAK1RXty5VtvidMgan8YW-JfHS3Rdxp6n_U,580
|
|
@@ -18,8 +19,10 @@ polymarket_apis/utilities/endpoints.py,sha256=bxZyrJBPbVauWc-eR0RMh6KDqU-SmO_3Lf
|
|
|
18
19
|
polymarket_apis/utilities/exceptions.py,sha256=58vuiLuZxX6d05qa29jgEOC4ZYBv368JaO8DAFMD0Dc,363
|
|
19
20
|
polymarket_apis/utilities/headers.py,sha256=Cc5WEnIBLYAgfwvmCXRBwA2zUYME8fDy4PbwlwlB6Oo,1510
|
|
20
21
|
polymarket_apis/utilities/order_builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
polymarket_apis/utilities/order_builder/builder.py,sha256
|
|
22
|
-
polymarket_apis/utilities/order_builder/helpers.py,sha256=
|
|
22
|
+
polymarket_apis/utilities/order_builder/builder.py,sha256=GMKkc96ZpLBBBQDRqIRKs8Kjl75zUbdRpS8IAFV_7Fg,8390
|
|
23
|
+
polymarket_apis/utilities/order_builder/helpers.py,sha256=eMcx17W41rKQ7hDP4Ch8QRtS3WQ5zNMyKtgmOe8-3fk,1944
|
|
24
|
+
polymarket_apis/utilities/schemas/activity-subgraph.graphql,sha256=B6FnnOUvix2qE4S4puPgzt-fSz_SlnJaEKrKE0kGCuc,2033
|
|
25
|
+
polymarket_apis/utilities/schemas/open-interest.graphql,sha256=42sNE49KfEJMoxDapKvo38eOYiaiOWZyINTKevWhpUY,478
|
|
23
26
|
polymarket_apis/utilities/signing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
27
|
polymarket_apis/utilities/signing/eip712.py,sha256=fGLurznnfY5M0VCP1Txyq_FYQRfggyHoTwz-PGIK2Eg,895
|
|
25
28
|
polymarket_apis/utilities/signing/hmac.py,sha256=vAYb98tMHWqNqAJNFXUnAddS38dA_aOy3Wp3DcP_7PM,702
|
|
@@ -35,6 +38,6 @@ polymarket_apis/utilities/web3/abis/ProxyWalletFactory.json,sha256=5KjBHUWdkc_kd
|
|
|
35
38
|
polymarket_apis/utilities/web3/abis/UChildERC20Proxy.json,sha256=ZyQC38U0uxInlmnW2VXDVD3TJfTIRmSNMkTxQsaG7oA,27396
|
|
36
39
|
polymarket_apis/utilities/web3/abis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
40
|
polymarket_apis/utilities/web3/abis/custom_contract_errors.py,sha256=ZCeJPK5tobPAR9vaNxw_pQZwKyZc_R0GdggfWaeXvOs,1176
|
|
38
|
-
polymarket_apis-0.
|
|
39
|
-
polymarket_apis-0.
|
|
40
|
-
polymarket_apis-0.
|
|
41
|
+
polymarket_apis-0.3.0.dist-info/METADATA,sha256=dYODMIGPXBh9NVImiRM-P7EXzL26gE6GZYRq6dzxFaU,10454
|
|
42
|
+
polymarket_apis-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
43
|
+
polymarket_apis-0.3.0.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: polymarket-apis
|
|
3
|
-
Version: 0.2.6
|
|
4
|
-
Summary: Unified Polymarket APIs - clob, gamma, data, web3, websockets
|
|
5
|
-
Author-email: Razvan Gheorghe <razvan@gheorghe.me>
|
|
6
|
-
Requires-Python: >=3.12
|
|
7
|
-
Requires-Dist: httpx[http2]>=0.25.1
|
|
8
|
-
Requires-Dist: lomond>=0.3.3
|
|
9
|
-
Requires-Dist: poly-eip712-structs>=0.0.1
|
|
10
|
-
Requires-Dist: py-order-utils>=0.3.2
|
|
11
|
-
Requires-Dist: pydantic>=2.10.5
|
|
12
|
-
Requires-Dist: web3>=7.0
|
|
13
|
-
Requires-Dist: wsaccel>=0.6.7
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
|
|
16
|
-
# polymarket-apis
|
|
17
|
-
|
|
18
|
-
Polymarket CLOB, Gamma, Data and Web3 and Websockets clients.
|
|
File without changes
|