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.
- polymarket_apis/__init__.py +42 -0
- polymarket_apis/clients/__init__.py +23 -0
- polymarket_apis/clients/clob_client.py +224 -117
- polymarket_apis/clients/data_client.py +220 -67
- polymarket_apis/clients/gamma_client.py +589 -101
- polymarket_apis/clients/graphql_client.py +28 -11
- polymarket_apis/clients/web3_client.py +538 -131
- polymarket_apis/clients/websockets_client.py +24 -7
- polymarket_apis/types/__init__.py +167 -0
- polymarket_apis/types/clob_types.py +35 -14
- polymarket_apis/types/common.py +105 -35
- polymarket_apis/types/data_types.py +48 -3
- polymarket_apis/types/gamma_types.py +529 -257
- polymarket_apis/types/web3_types.py +45 -0
- polymarket_apis/types/websockets_types.py +92 -41
- polymarket_apis/utilities/config.py +1 -0
- polymarket_apis/utilities/constants.py +5 -4
- polymarket_apis/utilities/exceptions.py +9 -0
- polymarket_apis/utilities/order_builder/builder.py +38 -22
- polymarket_apis/utilities/order_builder/helpers.py +0 -1
- polymarket_apis/utilities/signing/hmac.py +5 -1
- polymarket_apis/utilities/signing/signer.py +2 -2
- polymarket_apis/utilities/web3/abis/Safe.json +1138 -0
- polymarket_apis/utilities/web3/abis/SafeProxyFactory.json +224 -0
- polymarket_apis/utilities/web3/abis/custom_contract_errors.py +1 -1
- polymarket_apis/utilities/web3/helpers.py +235 -0
- {polymarket_apis-0.3.0.dist-info → polymarket_apis-0.3.9.dist-info}/METADATA +48 -8
- polymarket_apis-0.3.9.dist-info/RECORD +44 -0
- polymarket_apis/utilities/schemas/activity-subgraph.graphql +0 -86
- polymarket_apis/utilities/schemas/open-interest.graphql +0 -30
- polymarket_apis-0.3.0.dist-info/RECORD +0 -43
- {polymarket_apis-0.3.0.dist-info → polymarket_apis-0.3.9.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from typing import Literal, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
4
|
+
|
|
5
|
+
from ..types.common import EthAddress, HexString, Keccak256OrPadded
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TransactionLog(BaseModel):
|
|
9
|
+
"""Log entry in a transaction receipt."""
|
|
10
|
+
|
|
11
|
+
address: EthAddress
|
|
12
|
+
topics: list[Keccak256OrPadded]
|
|
13
|
+
data: HexString
|
|
14
|
+
block_number: int = Field(alias="blockNumber")
|
|
15
|
+
transaction_hash: HexString = Field(alias="transactionHash")
|
|
16
|
+
transaction_index: int = Field(alias="transactionIndex")
|
|
17
|
+
block_hash: HexString = Field(alias="blockHash")
|
|
18
|
+
block_timestamp: Optional[HexString] = Field(None, alias="blockTimestamp")
|
|
19
|
+
log_index: int = Field(alias="logIndex")
|
|
20
|
+
removed: bool
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TransactionReceipt(BaseModel):
|
|
24
|
+
"""Transaction receipt from the blockchain."""
|
|
25
|
+
|
|
26
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
27
|
+
|
|
28
|
+
tx_hash: HexString = Field(alias="transactionHash")
|
|
29
|
+
tx_index: int = Field(alias="transactionIndex")
|
|
30
|
+
block_hash: HexString = Field(alias="blockHash")
|
|
31
|
+
block_number: int = Field(alias="blockNumber")
|
|
32
|
+
|
|
33
|
+
status: Literal[0, 1]
|
|
34
|
+
type: int
|
|
35
|
+
|
|
36
|
+
gas_used: int = Field(alias="gasUsed")
|
|
37
|
+
cumulative_gas_used: int = Field(alias="cumulativeGasUsed")
|
|
38
|
+
effective_gas_price: int = Field(alias="effectiveGasPrice")
|
|
39
|
+
|
|
40
|
+
from_address: EthAddress = Field(alias="from")
|
|
41
|
+
to_address: EthAddress = Field(alias="to")
|
|
42
|
+
contract_address: Optional[EthAddress] = Field(None, alias="contractAddress")
|
|
43
|
+
|
|
44
|
+
logs: list[TransactionLog]
|
|
45
|
+
logs_bloom: HexString = Field(alias="logsBloom")
|
|
@@ -5,9 +5,11 @@ from pydantic import AliasChoices, BaseModel, Field, field_validator
|
|
|
5
5
|
|
|
6
6
|
from ..types.clob_types import MakerOrder, OrderBookSummary, TickSize
|
|
7
7
|
from ..types.common import EthAddress, Keccak256, TimeseriesPoint
|
|
8
|
+
from ..types.gamma_types import Comment, Reaction
|
|
8
9
|
|
|
9
10
|
# wss://ws-subscriptions-clob.polymarket.com/ws/market types
|
|
10
11
|
|
|
12
|
+
|
|
11
13
|
class PriceChange(BaseModel):
|
|
12
14
|
best_ask: float = Field(validation_alias=AliasChoices("ba", "best_ask"))
|
|
13
15
|
best_bid: float = Field(validation_alias=AliasChoices("bb", "best_bid"))
|
|
@@ -17,17 +19,22 @@ class PriceChange(BaseModel):
|
|
|
17
19
|
token_id: str = Field(validation_alias=AliasChoices("a", "asset_id"))
|
|
18
20
|
hash: str = Field(validation_alias=AliasChoices("h", "hash"))
|
|
19
21
|
|
|
22
|
+
|
|
20
23
|
class PriceChanges(BaseModel):
|
|
21
24
|
condition_id: Keccak256 = Field(validation_alias=AliasChoices("m", "market"))
|
|
22
|
-
price_changes: list[PriceChange] = Field(
|
|
25
|
+
price_changes: list[PriceChange] = Field(
|
|
26
|
+
validation_alias=AliasChoices("pc", "price_changes")
|
|
27
|
+
)
|
|
23
28
|
timestamp: datetime = Field(validation_alias=AliasChoices("t", "timestamp"))
|
|
24
29
|
|
|
30
|
+
|
|
25
31
|
class TickSizeChange(BaseModel):
|
|
26
32
|
token_id: str = Field(alias="asset_id")
|
|
27
33
|
condition_id: Keccak256 = Field(alias="market")
|
|
28
34
|
old_tick_size: TickSize
|
|
29
35
|
new_tick_size: TickSize
|
|
30
36
|
|
|
37
|
+
|
|
31
38
|
class LastTradePrice(BaseModel):
|
|
32
39
|
price: float
|
|
33
40
|
size: float
|
|
@@ -36,31 +43,37 @@ class LastTradePrice(BaseModel):
|
|
|
36
43
|
condition_id: Keccak256 = Field(alias="market")
|
|
37
44
|
fee_rate_bps: float
|
|
38
45
|
|
|
46
|
+
|
|
39
47
|
class OrderBookSummaryEvent(OrderBookSummary):
|
|
40
48
|
event_type: Literal["book"]
|
|
41
49
|
|
|
50
|
+
|
|
42
51
|
class PriceChangeEvent(PriceChanges):
|
|
43
52
|
event_type: Literal["price_change"]
|
|
44
53
|
|
|
54
|
+
|
|
45
55
|
class TickSizeChangeEvent(TickSizeChange):
|
|
46
56
|
side: Literal["BUY", "SELL"]
|
|
47
57
|
timestamp: datetime
|
|
48
58
|
event_type: Literal["tick_size_change"]
|
|
49
59
|
|
|
60
|
+
|
|
50
61
|
class LastTradePriceEvent(LastTradePrice):
|
|
51
62
|
timestamp: datetime
|
|
52
63
|
event_type: Literal["last_trade_price"]
|
|
53
64
|
|
|
65
|
+
|
|
54
66
|
# wss://ws-subscriptions-clob.polymarket.com/ws/user types
|
|
55
67
|
|
|
68
|
+
|
|
56
69
|
class OrderEvent(BaseModel):
|
|
57
70
|
token_id: str = Field(alias="asset_id")
|
|
58
71
|
condition_id: Keccak256 = Field(alias="market")
|
|
59
72
|
order_id: Keccak256 = Field(alias="id")
|
|
60
|
-
associated_trades: Optional[list[str]] = None
|
|
73
|
+
associated_trades: Optional[list[str]] = None # list of trade ids which
|
|
61
74
|
maker_address: EthAddress
|
|
62
|
-
order_owner: str = Field(alias="owner")
|
|
63
|
-
event_owner: Optional[str] = Field(None, alias="owner")
|
|
75
|
+
order_owner: str = Field(alias="owner") # api key of order owner
|
|
76
|
+
event_owner: Optional[str] = Field(None, alias="owner") # api key of event owner
|
|
64
77
|
|
|
65
78
|
price: float
|
|
66
79
|
side: Literal["BUY", "SELL"]
|
|
@@ -71,7 +84,7 @@ class OrderEvent(BaseModel):
|
|
|
71
84
|
|
|
72
85
|
created_at: datetime
|
|
73
86
|
expiration: Optional[datetime] = None
|
|
74
|
-
timestamp: Optional[datetime] = None
|
|
87
|
+
timestamp: Optional[datetime] = None # time of event
|
|
75
88
|
|
|
76
89
|
event_type: Optional[Literal["order"]] = None
|
|
77
90
|
type: Literal["PLACEMENT", "UPDATE", "CANCELLATION"]
|
|
@@ -84,35 +97,42 @@ class OrderEvent(BaseModel):
|
|
|
84
97
|
return None
|
|
85
98
|
return v
|
|
86
99
|
|
|
100
|
+
|
|
87
101
|
class TradeEvent(BaseModel):
|
|
88
102
|
token_id: str = Field(alias="asset_id")
|
|
89
103
|
condition_id: Keccak256 = Field(alias="market")
|
|
90
104
|
taker_order_id: Keccak256
|
|
91
105
|
maker_orders: list[MakerOrder]
|
|
92
106
|
trade_id: str = Field(alias="id")
|
|
93
|
-
trade_owner: Optional[str] = Field(None, alias="owner")
|
|
94
|
-
event_owner: str = Field(alias="owner")
|
|
107
|
+
trade_owner: Optional[str] = Field(None, alias="owner") # api key of trade owner
|
|
108
|
+
event_owner: str = Field(alias="owner") # api key of event owner
|
|
95
109
|
|
|
96
110
|
price: float
|
|
97
111
|
size: float
|
|
98
112
|
side: Literal["BUY", "SELL"]
|
|
99
113
|
outcome: str
|
|
100
114
|
|
|
101
|
-
last_update: datetime
|
|
102
|
-
matchtime: Optional[datetime] = None
|
|
103
|
-
timestamp: Optional[datetime] = None
|
|
115
|
+
last_update: datetime # time of last update to trade
|
|
116
|
+
matchtime: Optional[datetime] = None # time trade was matched
|
|
117
|
+
timestamp: Optional[datetime] = None # time of event
|
|
104
118
|
|
|
105
119
|
event_type: Optional[Literal["trade"]] = None
|
|
106
120
|
type: Optional[Literal["TRADE"]] = None
|
|
107
121
|
|
|
108
122
|
status: Literal["MATCHED", "MINED", "CONFIRMED", "RETRYING", "FAILED"]
|
|
109
123
|
|
|
124
|
+
|
|
110
125
|
# wss://ws-live-data.polymarket.com types
|
|
111
126
|
|
|
127
|
+
|
|
112
128
|
# Payload models
|
|
113
129
|
class ActivityTrade(BaseModel):
|
|
114
|
-
token_id: str = Field(
|
|
115
|
-
|
|
130
|
+
token_id: str = Field(
|
|
131
|
+
alias="asset"
|
|
132
|
+
) # ERC1155 token ID of conditional token being traded
|
|
133
|
+
condition_id: str = Field(
|
|
134
|
+
alias="conditionId"
|
|
135
|
+
) # Id of market which is also the CTF condition ID
|
|
116
136
|
event_slug: str = Field(alias="eventSlug") # Slug of the event
|
|
117
137
|
outcome: str # Human readable outcome of the market
|
|
118
138
|
outcome_index: int = Field(alias="outcomeIndex") # Index of the outcome
|
|
@@ -131,66 +151,81 @@ class ActivityTrade(BaseModel):
|
|
|
131
151
|
profile_image: str = Field(alias="profileImage") # URL to the user profile image
|
|
132
152
|
profile_image_optimized: Optional[str] = Field(None, alias="profileImageOptimized")
|
|
133
153
|
|
|
134
|
-
class Comment(BaseModel):
|
|
135
|
-
id: str # Unique identifier of comment
|
|
136
|
-
body: str # Content of the comment
|
|
137
|
-
parent_entity_type: str = Field(alias="parentEntityType") # Type of the parent entity (Event or Series)
|
|
138
|
-
parent_entity_id: int = Field(alias="parentEntityID") # ID of the parent entity
|
|
139
|
-
parent_comment_id: Optional[str] = Field(None, alias="parentCommentID") # ID of the parent comment
|
|
140
|
-
user_address: str = Field(alias="userAddress") # Address of the user
|
|
141
|
-
reply_address: Optional[str] = Field(None, alias="replyAddress") # Address of the reply user
|
|
142
|
-
created_at: datetime = Field(alias="createdAt") # Creation timestamp
|
|
143
|
-
updated_at: Optional[datetime] = Field(None, alias="updatedAt") # Last update timestamp
|
|
144
|
-
|
|
145
|
-
class Reaction(BaseModel):
|
|
146
|
-
id: str # Unique identifier of reaction
|
|
147
|
-
comment_id: int = Field(alias="commentID") # ID of the comment
|
|
148
|
-
reaction_type: str = Field(alias="reactionType") # Type of the reaction
|
|
149
|
-
icon: Optional[str] = None # Icon representing the reaction
|
|
150
|
-
user_address: str = Field(alias="userAddress") # Address of the user
|
|
151
|
-
created_at: datetime = Field(alias="createdAt") # Creation timestamp
|
|
152
154
|
|
|
153
155
|
class Request(BaseModel):
|
|
154
156
|
request_id: str = Field(alias="requestId") # Unique identifier for the request
|
|
155
157
|
proxy_address: str = Field(alias="proxyAddress") # Proxy address
|
|
156
158
|
user_address: str = Field(alias="userAddress") # User address
|
|
157
|
-
condition_id: Keccak256 = Field(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
condition_id: Keccak256 = Field(
|
|
160
|
+
alias="market"
|
|
161
|
+
) # Id of market which is also the CTF condition ID
|
|
162
|
+
token_id: str = Field(
|
|
163
|
+
alias="token"
|
|
164
|
+
) # ERC1155 token ID of conditional token being traded
|
|
165
|
+
complement_token_id: str = Field(
|
|
166
|
+
alias="complement"
|
|
167
|
+
) # Complement ERC1155 token ID of conditional token being traded
|
|
168
|
+
state: Literal[
|
|
169
|
+
"STATE_REQUEST_EXPIRED",
|
|
170
|
+
"STATE_USER_CANCELED",
|
|
171
|
+
"STATE_REQUEST_CANCELED",
|
|
172
|
+
"STATE_MAKER_CANCELED",
|
|
173
|
+
"STATE_ACCEPTING_QUOTES",
|
|
174
|
+
"STATE_REQUEST_QUOTED",
|
|
175
|
+
"STATE_QUOTE_IMPROVED",
|
|
176
|
+
] # Current state of the request
|
|
161
177
|
side: Literal["BUY", "SELL"] # Indicates buy or sell side
|
|
162
178
|
price: float # Price from in/out sizes
|
|
163
179
|
size_in: float = Field(alias="sizeIn") # Input size of the request
|
|
164
180
|
size_out: float = Field(alias="sizeOut") # Output size of the request
|
|
165
181
|
expiry: Optional[datetime] = None
|
|
166
182
|
|
|
183
|
+
|
|
167
184
|
class Quote(BaseModel):
|
|
168
185
|
quote_id: str = Field(alias="quoteId") # Unique identifier for the quote
|
|
169
186
|
request_id: str = Field(alias="requestId") # Associated request identifier
|
|
170
187
|
proxy_address: str = Field(alias="proxyAddress") # Proxy address
|
|
171
188
|
user_address: str = Field(alias="userAddress") # User address
|
|
172
|
-
condition_id: Keccak256 = Field(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
189
|
+
condition_id: Keccak256 = Field(
|
|
190
|
+
alias="condition"
|
|
191
|
+
) # Id of market which is also the CTF condition ID
|
|
192
|
+
token_id: str = Field(
|
|
193
|
+
alias="token"
|
|
194
|
+
) # ERC1155 token ID of conditional token being traded
|
|
195
|
+
complement_token_id: str = Field(
|
|
196
|
+
alias="complement"
|
|
197
|
+
) # Complement ERC1155 token ID of conditional token being traded
|
|
198
|
+
state: Literal[
|
|
199
|
+
"STATE_REQUEST_EXPIRED",
|
|
200
|
+
"STATE_USER_CANCELED",
|
|
201
|
+
"STATE_REQUEST_CANCELED",
|
|
202
|
+
"STATE_MAKER_CANCELED",
|
|
203
|
+
"STATE_ACCEPTING_QUOTES",
|
|
204
|
+
"STATE_REQUEST_QUOTED",
|
|
205
|
+
"STATE_QUOTE_IMPROVED",
|
|
206
|
+
] # Current state of the quote
|
|
176
207
|
side: Literal["BUY", "SELL"] # Indicates buy or sell side
|
|
177
208
|
size_in: float = Field(alias="sizeIn") # Input size of the quote
|
|
178
209
|
size_out: float = Field(alias="sizeOut") # Output size of the quote
|
|
179
210
|
expiry: Optional[datetime] = None
|
|
180
211
|
|
|
212
|
+
|
|
181
213
|
class CryptoPriceSubscribe(BaseModel):
|
|
182
214
|
data: list[TimeseriesPoint]
|
|
183
215
|
symbol: str
|
|
184
216
|
|
|
217
|
+
|
|
185
218
|
class CryptoPriceUpdate(TimeseriesPoint):
|
|
186
219
|
symbol: str
|
|
187
220
|
full_accuracy_value: str
|
|
188
221
|
|
|
222
|
+
|
|
189
223
|
class AggOrderBookSummary(OrderBookSummary):
|
|
190
224
|
min_order_size: float
|
|
191
225
|
tick_size: TickSize
|
|
192
226
|
neg_risk: bool
|
|
193
227
|
|
|
228
|
+
|
|
194
229
|
class LiveDataClobMarket(BaseModel):
|
|
195
230
|
token_ids: list[str] = Field(alias="asset_ids")
|
|
196
231
|
condition_id: Keccak256 = Field(alias="market")
|
|
@@ -198,6 +233,7 @@ class LiveDataClobMarket(BaseModel):
|
|
|
198
233
|
tick_size: TickSize
|
|
199
234
|
neg_risk: bool
|
|
200
235
|
|
|
236
|
+
|
|
201
237
|
# Event models
|
|
202
238
|
class ActivityTradeEvent(BaseModel):
|
|
203
239
|
payload: ActivityTrade
|
|
@@ -205,36 +241,44 @@ class ActivityTradeEvent(BaseModel):
|
|
|
205
241
|
type: Literal["trades"]
|
|
206
242
|
topic: Literal["activity"]
|
|
207
243
|
|
|
244
|
+
|
|
208
245
|
class ActivityOrderMatchEvent(BaseModel):
|
|
209
246
|
payload: ActivityTrade
|
|
210
247
|
timestamp: datetime
|
|
211
248
|
type: Literal["orders_matched"]
|
|
212
249
|
topic: Literal["activity"]
|
|
213
250
|
|
|
251
|
+
|
|
214
252
|
class CommentEvent(BaseModel):
|
|
215
253
|
payload: Comment
|
|
216
254
|
timestamp: datetime
|
|
217
255
|
type: Literal["comment_created", "comment_removed"]
|
|
218
256
|
topic: Literal["comments"]
|
|
219
257
|
|
|
258
|
+
|
|
220
259
|
class ReactionEvent(BaseModel):
|
|
221
260
|
payload: Reaction
|
|
222
261
|
timestamp: datetime
|
|
223
262
|
type: Literal["reaction_created", "reaction_removed"]
|
|
224
263
|
topic: Literal["comments"]
|
|
225
264
|
|
|
265
|
+
|
|
226
266
|
class RequestEvent(BaseModel):
|
|
227
267
|
payload: Request
|
|
228
268
|
timestamp: datetime
|
|
229
|
-
type: Literal[
|
|
269
|
+
type: Literal[
|
|
270
|
+
"request_created", "request_edited", "request_canceled", "request_expired"
|
|
271
|
+
]
|
|
230
272
|
topic: Literal["rfq"]
|
|
231
273
|
|
|
274
|
+
|
|
232
275
|
class QuoteEvent(BaseModel):
|
|
233
276
|
payload: Quote
|
|
234
277
|
timestamp: datetime
|
|
235
278
|
type: Literal["quote_created", "quote_edited", "quote_canceled", "quote_expired"]
|
|
236
279
|
topic: Literal["rfq"]
|
|
237
280
|
|
|
281
|
+
|
|
238
282
|
class CryptoPriceUpdateEvent(BaseModel):
|
|
239
283
|
payload: CryptoPriceUpdate
|
|
240
284
|
timestamp: datetime
|
|
@@ -242,12 +286,14 @@ class CryptoPriceUpdateEvent(BaseModel):
|
|
|
242
286
|
type: Literal["update"]
|
|
243
287
|
topic: Literal["crypto_prices", "crypto_prices_chainlink"]
|
|
244
288
|
|
|
289
|
+
|
|
245
290
|
class CryptoPriceSubscribeEvent(BaseModel):
|
|
246
291
|
payload: CryptoPriceSubscribe
|
|
247
292
|
timestamp: datetime
|
|
248
293
|
type: Literal["subscribe"]
|
|
249
294
|
topic: Literal["crypto_prices", "crypto_prices_chainlink"]
|
|
250
295
|
|
|
296
|
+
|
|
251
297
|
class LiveDataOrderBookSummaryEvent(BaseModel):
|
|
252
298
|
payload: list[AggOrderBookSummary] | AggOrderBookSummary
|
|
253
299
|
timestamp: datetime
|
|
@@ -255,6 +301,7 @@ class LiveDataOrderBookSummaryEvent(BaseModel):
|
|
|
255
301
|
type: Literal["agg_orderbook"]
|
|
256
302
|
topic: Literal["clob_market"]
|
|
257
303
|
|
|
304
|
+
|
|
258
305
|
class LiveDataPriceChangeEvent(BaseModel):
|
|
259
306
|
payload: PriceChanges
|
|
260
307
|
timestamp: datetime
|
|
@@ -262,6 +309,7 @@ class LiveDataPriceChangeEvent(BaseModel):
|
|
|
262
309
|
type: Literal["price_change"]
|
|
263
310
|
topic: Literal["clob_market"]
|
|
264
311
|
|
|
312
|
+
|
|
265
313
|
class LiveDataLastTradePriceEvent(BaseModel):
|
|
266
314
|
payload: LastTradePrice
|
|
267
315
|
timestamp: datetime
|
|
@@ -269,6 +317,7 @@ class LiveDataLastTradePriceEvent(BaseModel):
|
|
|
269
317
|
type: Literal["last_trade_price"]
|
|
270
318
|
topic: Literal["clob_market"]
|
|
271
319
|
|
|
320
|
+
|
|
272
321
|
class LiveDataTickSizeChangeEvent(BaseModel):
|
|
273
322
|
payload: TickSizeChange
|
|
274
323
|
timestamp: datetime
|
|
@@ -276,6 +325,7 @@ class LiveDataTickSizeChangeEvent(BaseModel):
|
|
|
276
325
|
type: Literal["tick_size_change"]
|
|
277
326
|
topic: Literal["clob_market"]
|
|
278
327
|
|
|
328
|
+
|
|
279
329
|
class MarketStatusChangeEvent(BaseModel):
|
|
280
330
|
payload: LiveDataClobMarket
|
|
281
331
|
timestamp: datetime
|
|
@@ -283,6 +333,7 @@ class MarketStatusChangeEvent(BaseModel):
|
|
|
283
333
|
type: Literal["market_created", "market_resolved"]
|
|
284
334
|
topic: Literal["clob_market"]
|
|
285
335
|
|
|
336
|
+
|
|
286
337
|
class LiveDataOrderEvent(BaseModel):
|
|
287
338
|
payload: OrderEvent
|
|
288
339
|
timestamp: datetime
|
|
@@ -290,6 +341,7 @@ class LiveDataOrderEvent(BaseModel):
|
|
|
290
341
|
type: Literal["order"]
|
|
291
342
|
topic: Literal["clob_user"]
|
|
292
343
|
|
|
344
|
+
|
|
293
345
|
class LiveDataTradeEvent(BaseModel):
|
|
294
346
|
payload: TradeEvent
|
|
295
347
|
timestamp: datetime
|
|
@@ -297,9 +349,8 @@ class LiveDataTradeEvent(BaseModel):
|
|
|
297
349
|
type: Literal["trade"]
|
|
298
350
|
topic: Literal["clob_user"]
|
|
299
351
|
|
|
352
|
+
|
|
300
353
|
class ErrorEvent(BaseModel):
|
|
301
354
|
message: str
|
|
302
355
|
connection_id: str = Field(alias="connectionId")
|
|
303
356
|
request_id: str = Field(alias="requestId")
|
|
304
|
-
|
|
305
|
-
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
1
3
|
# Access levels
|
|
2
4
|
L0 = 0
|
|
3
5
|
L1 = 1
|
|
@@ -14,12 +16,11 @@ L1_AUTH_UNAVAILABLE = "A private key is needed to interact with this endpoint!"
|
|
|
14
16
|
|
|
15
17
|
L2_AUTH_UNAVAILABLE = "API Credentials are needed to interact with this endpoint!"
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
ADDRESS_ZERO = "0x0000000000000000000000000000000000000000"
|
|
18
20
|
HASH_ZERO = "0x0000000000000000000000000000000000000000000000000000000000000000"
|
|
19
21
|
|
|
20
|
-
AMOY = 80002
|
|
21
|
-
POLYGON = 137
|
|
22
|
-
|
|
22
|
+
AMOY: Literal[80002] = 80002
|
|
23
|
+
POLYGON: Literal[137] = 137
|
|
23
24
|
END_CURSOR = "LTE="
|
|
24
25
|
|
|
25
26
|
BUY = "BUY"
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
class InvalidPriceError(Exception):
|
|
2
2
|
pass
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
class InvalidTickSizeError(Exception):
|
|
5
6
|
pass
|
|
6
7
|
|
|
8
|
+
|
|
7
9
|
class InvalidFeeRateError(Exception):
|
|
8
10
|
pass
|
|
9
11
|
|
|
12
|
+
|
|
10
13
|
class LiquidityError(Exception):
|
|
11
14
|
pass
|
|
12
15
|
|
|
16
|
+
|
|
13
17
|
class MissingOrderbookError(Exception):
|
|
14
18
|
pass
|
|
15
19
|
|
|
20
|
+
|
|
16
21
|
class AuthenticationRequiredError(ValueError):
|
|
17
22
|
"""Raised when authentication credentials are required but not provided."""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SafeAlreadyDeployedError(Exception):
|
|
26
|
+
"""Raised when attempting to deploy a Safe that has already been deployed."""
|
|
@@ -54,7 +54,11 @@ class OrderBuilder:
|
|
|
54
54
|
self.funder = funder if funder is not None else self.signer.address()
|
|
55
55
|
|
|
56
56
|
def get_order_amounts(
|
|
57
|
-
|
|
57
|
+
self,
|
|
58
|
+
side: str,
|
|
59
|
+
size: float,
|
|
60
|
+
price: float,
|
|
61
|
+
round_config: RoundConfig,
|
|
58
62
|
):
|
|
59
63
|
raw_price = round_normal(price, round_config.price)
|
|
60
64
|
|
|
@@ -88,7 +92,11 @@ class OrderBuilder:
|
|
|
88
92
|
raise ValueError(msg)
|
|
89
93
|
|
|
90
94
|
def get_market_order_amounts(
|
|
91
|
-
|
|
95
|
+
self,
|
|
96
|
+
side: str,
|
|
97
|
+
amount: float,
|
|
98
|
+
price: float,
|
|
99
|
+
round_config: RoundConfig,
|
|
92
100
|
):
|
|
93
101
|
raw_price = round_normal(price, round_config.price)
|
|
94
102
|
|
|
@@ -122,7 +130,9 @@ class OrderBuilder:
|
|
|
122
130
|
raise ValueError(msg)
|
|
123
131
|
|
|
124
132
|
def create_order(
|
|
125
|
-
|
|
133
|
+
self,
|
|
134
|
+
order_args: OrderArgs,
|
|
135
|
+
options: CreateOrderOptions,
|
|
126
136
|
) -> SignedOrder:
|
|
127
137
|
"""Creates and signs an order."""
|
|
128
138
|
side, maker_amount, taker_amount = self.get_order_amounts(
|
|
@@ -147,7 +157,8 @@ class OrderBuilder:
|
|
|
147
157
|
)
|
|
148
158
|
|
|
149
159
|
contract_config = get_contract_config(
|
|
150
|
-
self.signer.get_chain_id(),
|
|
160
|
+
self.signer.get_chain_id(),
|
|
161
|
+
options.neg_risk,
|
|
151
162
|
)
|
|
152
163
|
|
|
153
164
|
order_builder = UtilsOrderBuilder(
|
|
@@ -159,7 +170,9 @@ class OrderBuilder:
|
|
|
159
170
|
return order_builder.build_signed_order(data)
|
|
160
171
|
|
|
161
172
|
def create_market_order(
|
|
162
|
-
|
|
173
|
+
self,
|
|
174
|
+
order_args: MarketOrderArgs,
|
|
175
|
+
options: CreateOrderOptions,
|
|
163
176
|
) -> SignedOrder:
|
|
164
177
|
"""Creates and signs a market order."""
|
|
165
178
|
side, maker_amount, taker_amount = self.get_market_order_amounts(
|
|
@@ -184,7 +197,8 @@ class OrderBuilder:
|
|
|
184
197
|
)
|
|
185
198
|
|
|
186
199
|
contract_config = get_contract_config(
|
|
187
|
-
self.signer.get_chain_id(),
|
|
200
|
+
self.signer.get_chain_id(),
|
|
201
|
+
options.neg_risk,
|
|
188
202
|
)
|
|
189
203
|
|
|
190
204
|
order_builder = UtilsOrderBuilder(
|
|
@@ -196,19 +210,21 @@ class OrderBuilder:
|
|
|
196
210
|
return order_builder.build_signed_order(data)
|
|
197
211
|
|
|
198
212
|
def calculate_buy_market_price(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
213
|
+
self,
|
|
214
|
+
asks: list[
|
|
215
|
+
OrderSummary
|
|
216
|
+
], # expected to be sorted from worst to best price (high to low)
|
|
217
|
+
amount_to_match: float, # in usdc
|
|
218
|
+
order_type: OrderType,
|
|
203
219
|
) -> float:
|
|
204
220
|
if not asks:
|
|
205
221
|
msg = "No ask orders available"
|
|
206
222
|
raise LiquidityError(msg)
|
|
207
223
|
|
|
208
|
-
|
|
224
|
+
amount = 0.0
|
|
209
225
|
for p in reversed(asks):
|
|
210
|
-
|
|
211
|
-
if
|
|
226
|
+
amount += float(p.size) * float(p.price)
|
|
227
|
+
if amount >= amount_to_match:
|
|
212
228
|
return float(p.price)
|
|
213
229
|
|
|
214
230
|
if order_type == OrderType.FOK:
|
|
@@ -218,23 +234,23 @@ class OrderBuilder:
|
|
|
218
234
|
return float(asks[0].price)
|
|
219
235
|
|
|
220
236
|
def calculate_sell_market_price(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
237
|
+
self,
|
|
238
|
+
bids: list[
|
|
239
|
+
OrderSummary
|
|
240
|
+
], # expected to be sorted from worst to best price (low to high)
|
|
241
|
+
amount_to_match: float, # in shares
|
|
242
|
+
order_type: OrderType,
|
|
225
243
|
) -> float:
|
|
226
244
|
if not bids:
|
|
227
245
|
msg = "No bid orders available"
|
|
228
246
|
raise LiquidityError(msg)
|
|
229
247
|
|
|
230
|
-
|
|
248
|
+
amount = 0.0
|
|
231
249
|
for p in reversed(bids):
|
|
232
|
-
|
|
233
|
-
if
|
|
234
|
-
print(f"market order price {p.price}")
|
|
250
|
+
amount += float(p.size)
|
|
251
|
+
if amount >= amount_to_match:
|
|
235
252
|
return float(p.price)
|
|
236
253
|
|
|
237
|
-
|
|
238
254
|
if order_type == OrderType.FOK:
|
|
239
255
|
msg = "no match"
|
|
240
256
|
raise ValueError(msg)
|
|
@@ -4,7 +4,11 @@ import hmac
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def build_hmac_signature(
|
|
7
|
-
secret: str,
|
|
7
|
+
secret: str,
|
|
8
|
+
timestamp: str,
|
|
9
|
+
method: str,
|
|
10
|
+
request_path: str,
|
|
11
|
+
body=None,
|
|
8
12
|
):
|
|
9
13
|
"""Creates an HMAC signature by signing a payload with the secret."""
|
|
10
14
|
base64_secret = base64.urlsafe_b64decode(secret)
|
|
@@ -11,7 +11,7 @@ class Signer:
|
|
|
11
11
|
raise ValueError(msg)
|
|
12
12
|
|
|
13
13
|
self.private_key = private_key
|
|
14
|
-
self.account = Account.from_key(private_key)
|
|
14
|
+
self.account = Account.from_key(private_key) # type: ignore[misc]
|
|
15
15
|
self.chain_id = chain_id
|
|
16
16
|
|
|
17
17
|
def address(self):
|
|
@@ -22,4 +22,4 @@ class Signer:
|
|
|
22
22
|
|
|
23
23
|
def sign(self, message_hash):
|
|
24
24
|
"""Signs a message hash."""
|
|
25
|
-
return Account.unsafe_sign_hash(message_hash, self.private_key).signature.hex()
|
|
25
|
+
return Account.unsafe_sign_hash(message_hash, self.private_key).signature.hex() # type: ignore[misc]
|