ddx-python 1.0.4__cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.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.
Files changed (106) hide show
  1. ddx/.gitignore +1 -0
  2. ddx/__init__.py +58 -0
  3. ddx/_rust/__init__.pyi +2685 -0
  4. ddx/_rust/common/__init__.pyi +17 -0
  5. ddx/_rust/common/accounting.pyi +6 -0
  6. ddx/_rust/common/enums.pyi +3 -0
  7. ddx/_rust/common/requests/__init__.pyi +23 -0
  8. ddx/_rust/common/requests/intents.pyi +19 -0
  9. ddx/_rust/common/specs.pyi +17 -0
  10. ddx/_rust/common/state/__init__.pyi +41 -0
  11. ddx/_rust/common/state/keys.pyi +29 -0
  12. ddx/_rust/common/transactions.pyi +7 -0
  13. ddx/_rust/decimal.pyi +3 -0
  14. ddx/_rust/h256.pyi +3 -0
  15. ddx/_rust.abi3.so +0 -0
  16. ddx/app_config/ethereum/addresses.json +526 -0
  17. ddx/auditor/README.md +32 -0
  18. ddx/auditor/__init__.py +0 -0
  19. ddx/auditor/auditor_driver.py +1043 -0
  20. ddx/auditor/websocket_message.py +54 -0
  21. ddx/common/__init__.py +0 -0
  22. ddx/common/epoch_params.py +28 -0
  23. ddx/common/fill_context.py +141 -0
  24. ddx/common/logging.py +184 -0
  25. ddx/common/market_aware_account.py +259 -0
  26. ddx/common/market_specs.py +64 -0
  27. ddx/common/trade_mining_params.py +19 -0
  28. ddx/common/transaction_utils.py +85 -0
  29. ddx/common/transactions/__init__.py +0 -0
  30. ddx/common/transactions/advance_epoch.py +91 -0
  31. ddx/common/transactions/advance_settlement_epoch.py +63 -0
  32. ddx/common/transactions/all_price_checkpoints.py +84 -0
  33. ddx/common/transactions/cancel.py +76 -0
  34. ddx/common/transactions/cancel_all.py +88 -0
  35. ddx/common/transactions/complete_fill.py +103 -0
  36. ddx/common/transactions/disaster_recovery.py +96 -0
  37. ddx/common/transactions/event.py +48 -0
  38. ddx/common/transactions/fee_distribution.py +119 -0
  39. ddx/common/transactions/funding.py +292 -0
  40. ddx/common/transactions/futures_expiry.py +123 -0
  41. ddx/common/transactions/genesis.py +108 -0
  42. ddx/common/transactions/inner/__init__.py +0 -0
  43. ddx/common/transactions/inner/adl_outcome.py +25 -0
  44. ddx/common/transactions/inner/fill.py +232 -0
  45. ddx/common/transactions/inner/liquidated_position.py +41 -0
  46. ddx/common/transactions/inner/liquidation_entry.py +41 -0
  47. ddx/common/transactions/inner/liquidation_fill.py +118 -0
  48. ddx/common/transactions/inner/outcome.py +32 -0
  49. ddx/common/transactions/inner/trade_fill.py +292 -0
  50. ddx/common/transactions/insurance_fund_update.py +138 -0
  51. ddx/common/transactions/insurance_fund_withdraw.py +100 -0
  52. ddx/common/transactions/liquidation.py +353 -0
  53. ddx/common/transactions/partial_fill.py +125 -0
  54. ddx/common/transactions/pnl_realization.py +120 -0
  55. ddx/common/transactions/post.py +72 -0
  56. ddx/common/transactions/post_order.py +95 -0
  57. ddx/common/transactions/price_checkpoint.py +97 -0
  58. ddx/common/transactions/signer_registered.py +62 -0
  59. ddx/common/transactions/specs_update.py +61 -0
  60. ddx/common/transactions/strategy_update.py +158 -0
  61. ddx/common/transactions/tradable_product_update.py +98 -0
  62. ddx/common/transactions/trade_mining.py +147 -0
  63. ddx/common/transactions/trader_update.py +131 -0
  64. ddx/common/transactions/withdraw.py +90 -0
  65. ddx/common/transactions/withdraw_ddx.py +74 -0
  66. ddx/common/utils.py +176 -0
  67. ddx/config.py +17 -0
  68. ddx/derivadex_client.py +270 -0
  69. ddx/models/__init__.py +0 -0
  70. ddx/models/base.py +132 -0
  71. ddx/py.typed +0 -0
  72. ddx/realtime_client/__init__.py +2 -0
  73. ddx/realtime_client/config.py +2 -0
  74. ddx/realtime_client/models/__init__.py +611 -0
  75. ddx/realtime_client/realtime_client.py +646 -0
  76. ddx/rest_client/__init__.py +0 -0
  77. ddx/rest_client/clients/__init__.py +0 -0
  78. ddx/rest_client/clients/base_client.py +60 -0
  79. ddx/rest_client/clients/market_client.py +1243 -0
  80. ddx/rest_client/clients/on_chain_client.py +439 -0
  81. ddx/rest_client/clients/signed_client.py +292 -0
  82. ddx/rest_client/clients/system_client.py +843 -0
  83. ddx/rest_client/clients/trade_client.py +357 -0
  84. ddx/rest_client/constants/__init__.py +0 -0
  85. ddx/rest_client/constants/endpoints.py +66 -0
  86. ddx/rest_client/contracts/__init__.py +0 -0
  87. ddx/rest_client/contracts/checkpoint/__init__.py +560 -0
  88. ddx/rest_client/contracts/ddx/__init__.py +1949 -0
  89. ddx/rest_client/contracts/dummy_token/__init__.py +1014 -0
  90. ddx/rest_client/contracts/i_collateral/__init__.py +1414 -0
  91. ddx/rest_client/contracts/i_stake/__init__.py +696 -0
  92. ddx/rest_client/exceptions/__init__.py +0 -0
  93. ddx/rest_client/exceptions/exceptions.py +32 -0
  94. ddx/rest_client/http/__init__.py +0 -0
  95. ddx/rest_client/http/http_client.py +336 -0
  96. ddx/rest_client/models/__init__.py +0 -0
  97. ddx/rest_client/models/market.py +693 -0
  98. ddx/rest_client/models/signed.py +61 -0
  99. ddx/rest_client/models/system.py +311 -0
  100. ddx/rest_client/models/trade.py +185 -0
  101. ddx/rest_client/utils/__init__.py +0 -0
  102. ddx/rest_client/utils/encryption_utils.py +26 -0
  103. ddx/utils/__init__.py +0 -0
  104. ddx_python-1.0.4.dist-info/METADATA +63 -0
  105. ddx_python-1.0.4.dist-info/RECORD +106 -0
  106. ddx_python-1.0.4.dist-info/WHEEL +5 -0
@@ -0,0 +1,1243 @@
1
+ from typing import Optional, AsyncIterator, Dict
2
+
3
+ from ddx.rest_client.constants.endpoints import System, Market
4
+ from ddx.rest_client.clients.base_client import BaseClient
5
+ from ddx.rest_client.models.market import (
6
+ MarkPriceHistoryResponse,
7
+ MarkPrice,
8
+ OrderBookL3Response,
9
+ OrderUpdateHistoryResponse,
10
+ OrderUpdate,
11
+ StrategyUpdateHistoryResponse,
12
+ StrategyUpdate,
13
+ TickersResponse,
14
+ TraderUpdateHistoryResponse,
15
+ TraderUpdate,
16
+ BalanceAggregationResponse,
17
+ FeesAggregationResponse,
18
+ FeesAggregation,
19
+ FundingRateComparisonResponse,
20
+ TopTradersAggregationResponse,
21
+ TopTrader,
22
+ VolumeAggregationResponse,
23
+ VolumeAggregation,
24
+ FundingRateHistoryResponse,
25
+ FundingRateHistory,
26
+ OpenInterestHistoryResponse,
27
+ OrderBook,
28
+ OrderBookL2Response,
29
+ PriceCheckpointHistoryResponse,
30
+ PriceCheckpoint,
31
+ )
32
+
33
+
34
+ class MarketClient(BaseClient):
35
+ """
36
+ System-related operations and data access.
37
+
38
+ Provides access to exchange configuration, system status, and other
39
+ system-related information through the API endpoints.
40
+ """
41
+
42
+ async def get_mark_price_history_page(
43
+ self,
44
+ limit: Optional[int] = None,
45
+ epoch: Optional[int] = None,
46
+ symbol: Optional[str] = None,
47
+ order: Optional[str] = None,
48
+ global_ordinal: Optional[int] = None,
49
+ ) -> MarkPriceHistoryResponse:
50
+ """
51
+ Get a single page of mark prices over time.
52
+
53
+ Parameters
54
+ ----------
55
+ limit : Optional[int]
56
+ The number of rows to return
57
+ epoch : Optional[int]
58
+ The epoch boundary used when fetching the next timeseries page
59
+ symbol : Optional[str]
60
+ The symbol
61
+ order : Optional[str]
62
+ The ordering of the results. Values: "asc", "desc"
63
+ global_ordinal : Optional[int]
64
+ The global ordinal boundary used when fetching the next timeseries page
65
+
66
+ Returns
67
+ -------
68
+ MarkPriceHistoryResponse
69
+ Single page of mark price history data
70
+ """
71
+
72
+ params = {
73
+ "limit": limit,
74
+ "epoch": epoch,
75
+ "symbol": symbol,
76
+ "order": order,
77
+ "globalOrdinal": global_ordinal,
78
+ }
79
+ params = {k: v for k, v in params.items() if v is not None}
80
+
81
+ response = await self._http.get(
82
+ self._build_url(Market.GET_MARK_PRICE_HISTORY), params=params
83
+ )
84
+
85
+ return MarkPriceHistoryResponse.model_validate(response)
86
+
87
+ async def get_mark_price_history(
88
+ self,
89
+ epoch: Optional[int] = None,
90
+ symbol: Optional[str] = None,
91
+ order: Optional[str] = None,
92
+ limit: Optional[int] = 100,
93
+ ) -> AsyncIterator[MarkPrice]:
94
+ """
95
+ Get all mark price history data.
96
+
97
+ Automatically handles pagination using global_ordinal.
98
+
99
+ Parameters
100
+ ----------
101
+ epoch : Optional[int]
102
+ The epoch boundary used when fetching the next timeseries page
103
+ symbol : Optional[str]
104
+ The symbol
105
+ order : Optional[str]
106
+ The ordering of the results. Values: "asc", "desc"
107
+ limit : Optional[int]
108
+ The number of rows to return per page
109
+
110
+ Yields
111
+ ------
112
+ MarkPrice
113
+ Mark price history entries
114
+ """
115
+
116
+ global_ordinal = None
117
+
118
+ while True:
119
+ response = await self.get_mark_price_history_page(
120
+ limit=limit,
121
+ epoch=epoch,
122
+ symbol=symbol,
123
+ order=order,
124
+ global_ordinal=global_ordinal,
125
+ )
126
+
127
+ if not response.value:
128
+ break
129
+
130
+ for item in response.value:
131
+ yield item
132
+
133
+ if response.next_global_ordinal is None:
134
+ break
135
+
136
+ global_ordinal = response.next_global_ordinal
137
+
138
+ async def get_order_book_l3(
139
+ self,
140
+ trader: Optional[str] = None,
141
+ strategy_id_hash: Optional[str] = None,
142
+ depth: Optional[int] = None,
143
+ symbol: Optional[str] = None,
144
+ side: Optional[int] = None,
145
+ ) -> OrderBookL3Response:
146
+ """
147
+ Get current L3 order book.
148
+
149
+ Parameters
150
+ ----------
151
+ trader : Optional[str]
152
+ The trader address, with the discriminant prefix
153
+ strategy_id_hash : Optional[str]
154
+ The strategy id hash
155
+ depth : Optional[int]
156
+ The best N bids and asks to return, where N = depth
157
+ symbol : Optional[str]
158
+ The symbol
159
+ side : Optional[int]
160
+ The side of the order. Values: 0 (Bid), 1 (Ask)
161
+
162
+ Returns
163
+ -------
164
+ OrderBookL3Response
165
+ L3 order book data with individual orders
166
+ """
167
+
168
+ params = {
169
+ "trader": trader,
170
+ "strategyIdHash": strategy_id_hash,
171
+ "depth": depth,
172
+ "symbol": symbol,
173
+ "side": side,
174
+ }
175
+ params = {k: v for k, v in params.items() if v is not None}
176
+
177
+ response = await self._http.get(
178
+ self._build_url(Market.GET_ORDER_BOOK_L3), params=params
179
+ )
180
+
181
+ return OrderBookL3Response.model_validate(response)
182
+
183
+ async def get_order_update_history_page(
184
+ self,
185
+ trader: Optional[str] = None,
186
+ strategy_id_hash: Optional[str] = None,
187
+ limit: Optional[int] = None,
188
+ global_ordinal: Optional[int] = None,
189
+ order: Optional[str] = None,
190
+ symbol: Optional[str] = None,
191
+ order_hash: Optional[str] = None,
192
+ reason: Optional[int] = None,
193
+ since: Optional[int] = None,
194
+ ) -> OrderUpdateHistoryResponse:
195
+ """
196
+ Get a single page of order updates (trades, liquidations, cancels).
197
+
198
+ Parameters
199
+ ----------
200
+ trader : Optional[str]
201
+ The trader address, with the discriminant prefix
202
+ strategy_id_hash : Optional[str]
203
+ The strategy id hash
204
+ limit : Optional[int]
205
+ The number of rows to return
206
+ global_ordinal : Optional[int]
207
+ The global ordinal boundary used when fetching the next timeseries page
208
+ order : Optional[str]
209
+ The ordering of the results. Values: "asc", "desc"
210
+ symbol : Optional[str]
211
+ The symbol
212
+ order_hash : Optional[str]
213
+ The order hash of the order intent. Multiple order hash values can be provided
214
+ reason : Optional[int]
215
+ The reason for the creation of this row. Multiple reason values can be provided.
216
+ Values: 0 (Trade), 1 (Liquidation), 2 (Cancel), 3 (Order Rejection), 4 (Cancel Rejection)
217
+ since : Optional[int]
218
+ The earliest time in seconds to fetch rows for. This param cannot be used together with param order = 'desc'
219
+
220
+ Returns
221
+ -------
222
+ OrderUpdateHistoryResponse
223
+ Single page of order update history data
224
+ """
225
+
226
+ params = {
227
+ "trader": trader,
228
+ "strategyIdHash": strategy_id_hash,
229
+ "limit": limit,
230
+ "globalOrdinal": global_ordinal,
231
+ "order": order,
232
+ "symbol": symbol,
233
+ "orderHash": order_hash,
234
+ "reason": reason,
235
+ "since": since,
236
+ }
237
+ params = {k: v for k, v in params.items() if v is not None}
238
+
239
+ response = await self._http.get(
240
+ self._build_url(Market.GET_ORDER_UPDATE_HISTORY), params=params
241
+ )
242
+
243
+ return OrderUpdateHistoryResponse.model_validate(response)
244
+
245
+ async def get_order_update_history(
246
+ self,
247
+ trader: Optional[str] = None,
248
+ strategy_id_hash: Optional[str] = None,
249
+ order: Optional[str] = None,
250
+ symbol: Optional[str] = None,
251
+ order_hash: Optional[str] = None,
252
+ reason: Optional[int] = None,
253
+ since: Optional[int] = None,
254
+ limit: Optional[int] = 100,
255
+ ) -> AsyncIterator[OrderUpdate]:
256
+ """
257
+ Get all order updates (trades, liquidations, cancels).
258
+
259
+ Automatically handles pagination using global_ordinal.
260
+
261
+ Parameters
262
+ ----------
263
+ trader : Optional[str]
264
+ The trader address, with the discriminant prefix
265
+ strategy_id_hash : Optional[str]
266
+ The strategy id hash
267
+ order : Optional[str]
268
+ The ordering of the results. Values: "asc", "desc"
269
+ symbol : Optional[str]
270
+ The symbol
271
+ order_hash : Optional[str]
272
+ The order hash of the order intent. Multiple order hash values can be provided
273
+ reason : Optional[int]
274
+ The reason for the creation of this row. Multiple reason values can be provided.
275
+ Values: 0 (Trade), 1 (Liquidation), 2 (Cancel), 3 (Order Rejection), 4 (Cancel Rejection)
276
+ since : Optional[int]
277
+ The earliest time in seconds to fetch rows for. This param cannot be used together with param order = 'desc'
278
+ limit : Optional[int]
279
+ The number of rows to return per page
280
+
281
+ Yields
282
+ ------
283
+ OrderUpdate
284
+ Order update entries
285
+ """
286
+
287
+ global_ordinal = None
288
+
289
+ while True:
290
+ response = await self.get_order_update_history_page(
291
+ trader=trader,
292
+ strategy_id_hash=strategy_id_hash,
293
+ limit=limit,
294
+ global_ordinal=global_ordinal,
295
+ order=order,
296
+ symbol=symbol,
297
+ order_hash=order_hash,
298
+ reason=reason,
299
+ since=since,
300
+ )
301
+
302
+ if not response.value:
303
+ break
304
+
305
+ for item in response.value:
306
+ yield item
307
+
308
+ if response.next_global_ordinal is None:
309
+ break
310
+
311
+ global_ordinal = response.next_global_ordinal
312
+
313
+ async def get_strategy_update_history_page(
314
+ self,
315
+ trader: Optional[str] = None,
316
+ strategy_id_hash: Optional[str] = None,
317
+ reason: Optional[int] = None,
318
+ limit: Optional[int] = None,
319
+ global_ordinal: Optional[int] = None,
320
+ order: Optional[str] = None,
321
+ ) -> StrategyUpdateHistoryResponse:
322
+ """
323
+ Get a single page of strategy updates over time.
324
+
325
+ Parameters
326
+ ----------
327
+ trader : Optional[str]
328
+ The trader address, with the discriminant prefix
329
+ strategy_id_hash : Optional[str]
330
+ The strategy id hash
331
+ reason : Optional[int]
332
+ The type of strategy update. Multiple strategy update values can be provided.
333
+ Values: 0 (Deposit), 1 (Withdraw), 2 (WithdrawIntent), 3 (FundingPayment),
334
+ 4 (RealizedPnl), 5 (Liquidation), 6 (ADL), 7 (Withdraw Rejection)
335
+ limit : Optional[int]
336
+ The number of rows to return
337
+ global_ordinal : Optional[int]
338
+ The global ordinal boundary used when fetching the next timeseries page
339
+ order : Optional[str]
340
+ The ordering of the results. Values: "asc", "desc"
341
+
342
+ Returns
343
+ -------
344
+ StrategyUpdateHistoryResponse
345
+ Single page of strategy update history data
346
+ """
347
+
348
+ params = {
349
+ "trader": trader,
350
+ "strategyIdHash": strategy_id_hash,
351
+ "reason": reason,
352
+ "limit": limit,
353
+ "globalOrdinal": global_ordinal,
354
+ "order": order,
355
+ }
356
+ params = {k: v for k, v in params.items() if v is not None}
357
+
358
+ response = await self._http.get(
359
+ self._build_url(Market.GET_STRATEGY_UPDATE_HISTORY), params=params
360
+ )
361
+
362
+ return StrategyUpdateHistoryResponse.model_validate(response)
363
+
364
+ async def get_strategy_update_history(
365
+ self,
366
+ trader: Optional[str] = None,
367
+ strategy_id_hash: Optional[str] = None,
368
+ reason: Optional[int] = None,
369
+ order: Optional[str] = None,
370
+ limit: Optional[int] = 100,
371
+ ) -> AsyncIterator[StrategyUpdate]:
372
+ """
373
+ Get all strategy updates over time.
374
+
375
+ Automatically handles pagination using global_ordinal.
376
+
377
+ Parameters
378
+ ----------
379
+ trader : Optional[str]
380
+ The trader address, with the discriminant prefix
381
+ strategy_id_hash : Optional[str]
382
+ The strategy id hash
383
+ reason : Optional[int]
384
+ The type of strategy update. Multiple strategy update values can be provided.
385
+ Values: 0 (Deposit), 1 (Withdraw), 2 (WithdrawIntent), 3 (FundingPayment),
386
+ 4 (RealizedPnl), 5 (Liquidation), 6 (ADL), 7 (Withdraw Rejection)
387
+ order : Optional[str]
388
+ The ordering of the results. Values: "asc", "desc"
389
+ limit : Optional[int]
390
+ The number of rows to return per page
391
+
392
+ Yields
393
+ ------
394
+ StrategyUpdate
395
+ Strategy update entries
396
+ """
397
+
398
+ global_ordinal = None
399
+
400
+ while True:
401
+ response = await self.get_strategy_update_history_page(
402
+ trader=trader,
403
+ strategy_id_hash=strategy_id_hash,
404
+ reason=reason,
405
+ limit=limit,
406
+ global_ordinal=global_ordinal,
407
+ order=order,
408
+ )
409
+
410
+ if not response.value:
411
+ break
412
+
413
+ for item in response.value:
414
+ yield item
415
+
416
+ if response.next_global_ordinal is None:
417
+ break
418
+
419
+ global_ordinal = response.next_global_ordinal
420
+
421
+ async def get_tickers(
422
+ self,
423
+ symbol: Optional[str] = None,
424
+ market_kind: Optional[int] = None,
425
+ ) -> TickersResponse:
426
+ """
427
+ Get convenient market tickers data.
428
+
429
+ Includes funding rate and open interest data, price related data,
430
+ and trading volume in the last 24 hours.
431
+
432
+ Parameters
433
+ ----------
434
+ symbol : Optional[str]
435
+ The symbol
436
+ market_kind : Optional[int]
437
+ The type of markets to return data for. Values: 0 (SingleNamePerpetual),
438
+ 2 (IndexFundPerpetual), 4 (FixedExpiryFuture).
439
+
440
+ Returns
441
+ -------
442
+ TickersResponse
443
+ Market ticker data for requested symbols and market kinds
444
+ """
445
+
446
+ params = {
447
+ "symbol": symbol,
448
+ "marketKind": market_kind,
449
+ }
450
+ params = {k: v for k, v in params.items() if v is not None}
451
+
452
+ response = await self._http.get(
453
+ self._build_url(Market.GET_TICKERS), params=params
454
+ )
455
+
456
+ return TickersResponse.model_validate(response)
457
+
458
+ async def get_trader_update_history_page(
459
+ self,
460
+ trader: Optional[str] = None,
461
+ reason: Optional[int] = None,
462
+ limit: Optional[int] = None,
463
+ global_ordinal: Optional[int] = None,
464
+ order: Optional[str] = None,
465
+ ) -> TraderUpdateHistoryResponse:
466
+ """
467
+ Get a single page of trader DDX balance and profile updates over time.
468
+
469
+ Parameters
470
+ ----------
471
+ trader : Optional[str]
472
+ The trader address, with the discriminant prefix
473
+ reason : Optional[int]
474
+ The type of trader update. Multiple trader update values can be provided.
475
+ Values: 0 (Deposit), 1 (WithdrawDDX), 2 (WithdrawDDXIntent),
476
+ 3 (TradeMiningReward), 4 (ProfileUpdate), 5 (FeeDistribution),
477
+ 6 (Admission), 7 (Denial), 8 (Fee),
478
+ 9 (WithdrawDDXRejection)
479
+ limit : Optional[int]
480
+ The number of rows to return
481
+ global_ordinal : Optional[int]
482
+ The global ordinal boundary used when fetching the next timeseries page
483
+ order : Optional[str]
484
+ The ordering of the results. Values: "asc", "desc"
485
+
486
+ Returns
487
+ -------
488
+ TraderUpdateHistoryResponse
489
+ Single page of trader update history data
490
+ """
491
+
492
+ params = {
493
+ "trader": trader,
494
+ "reason": reason,
495
+ "limit": limit,
496
+ "globalOrdinal": global_ordinal,
497
+ "order": order,
498
+ }
499
+ params = {k: v for k, v in params.items() if v is not None}
500
+
501
+ response = await self._http.get(
502
+ self._build_url(Market.GET_TRADER_UPDATE_HISTORY), params=params
503
+ )
504
+
505
+ return TraderUpdateHistoryResponse.model_validate(response)
506
+
507
+ async def get_trader_update_history(
508
+ self,
509
+ trader: Optional[str] = None,
510
+ reason: Optional[int] = None,
511
+ order: Optional[str] = None,
512
+ limit: Optional[int] = 100,
513
+ ) -> AsyncIterator[TraderUpdate]:
514
+ """
515
+ Get all trader DDX balance and profile updates over time.
516
+
517
+ Automatically handles pagination using global_ordinal.
518
+
519
+ Parameters
520
+ ----------
521
+ trader : Optional[str]
522
+ The trader address, with the discriminant prefix
523
+ reason : Optional[int]
524
+ The type of trader update. Multiple trader update values can be provided.
525
+ Values: 0 (Deposit), 1 (WithdrawDDX), 2 (WithdrawDDXIntent),
526
+ 3 (TradeMiningReward), 4 (ProfileUpdate), 5 (FeeDistribution),
527
+ 6 (Admission), 7 (Denial), 8 (Fee),
528
+ 9 (WithdrawDDXRejection)
529
+ order : Optional[str]
530
+ The ordering of the results. Values: "asc", "desc"
531
+ limit : Optional[int]
532
+ The number of rows to return per page
533
+
534
+ Yields
535
+ ------
536
+ TraderUpdate
537
+ Trader update history entries
538
+ """
539
+
540
+ global_ordinal = None
541
+
542
+ while True:
543
+ response = await self.get_trader_update_history_page(
544
+ trader=trader,
545
+ reason=reason,
546
+ limit=limit,
547
+ global_ordinal=global_ordinal,
548
+ order=order,
549
+ )
550
+
551
+ if not response.value:
552
+ break
553
+
554
+ for item in response.value:
555
+ yield item
556
+
557
+ if response.next_global_ordinal is None:
558
+ break
559
+
560
+ global_ordinal = response.next_global_ordinal
561
+
562
+ async def get_balance_aggregation(
563
+ self,
564
+ trader: Optional[str] = None,
565
+ strategy_id: Optional[str] = None,
566
+ limit: Optional[int] = None,
567
+ aggregation_period: Optional[str] = None,
568
+ lookback_count: Optional[int] = None,
569
+ ) -> BalanceAggregationResponse:
570
+ """
571
+ Get the change of trader's balance for a specific strategy over a specific time period.
572
+
573
+ Returns the change of trader's balance for a specific strategy over a specific
574
+ time period, looking back from the present.
575
+
576
+ Parameters
577
+ ----------
578
+ trader : Optional[str]
579
+ The trader address, with the discriminant prefix
580
+ strategy_id : Optional[str]
581
+ The strategy ID
582
+ limit : Optional[int]
583
+ The number of rows to return
584
+ aggregation_period : Optional[str]
585
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
586
+ lookback_count : Optional[int]
587
+ The number of periods to look back from present
588
+
589
+ Returns
590
+ -------
591
+ BalanceAggregationResponse
592
+ Balance aggregation data showing trader balance changes over time
593
+ """
594
+
595
+ params = {
596
+ "trader": trader,
597
+ "strategyId": strategy_id,
598
+ "limit": limit,
599
+ "aggregationPeriod": aggregation_period,
600
+ "lookbackCount": lookback_count,
601
+ }
602
+ params = {k: v for k, v in params.items() if v is not None}
603
+
604
+ response = await self._http.get(
605
+ self._build_url(Market.GET_BALANCE_AGGREGATION), params=params
606
+ )
607
+
608
+ return BalanceAggregationResponse.model_validate(response)
609
+
610
+ async def get_fees_aggregation_page(
611
+ self,
612
+ group: str,
613
+ symbol: Optional[str] = None,
614
+ fee_symbol: Optional[str] = None,
615
+ aggregation_period: Optional[str] = None,
616
+ lookback_count: Optional[int] = None,
617
+ lookback_timestamp: Optional[int] = None,
618
+ ) -> FeesAggregationResponse:
619
+ """
620
+ Get a single page of fees aggregation data.
621
+
622
+ Returns fees per time period looking back from the present.
623
+
624
+ Parameters
625
+ ----------
626
+ group : str
627
+ The grouping for the aggregation. Values: "symbol", "feeSymbol"
628
+ symbol : Optional[str]
629
+ The symbol
630
+ fee_symbol : Optional[str]
631
+ The fee symbol. Values: "USDC", "DDX"
632
+ aggregation_period : Optional[str]
633
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
634
+ lookback_count : Optional[int]
635
+ The number of periods to look back from present
636
+ lookback_timestamp : Optional[int]
637
+ The timestamp of the when to begin the lookback from. Each lookback query
638
+ will return nextLookbackTimestamp in the response, which can be passed as
639
+ a query parameter here to get the next page of results
640
+
641
+ Returns
642
+ -------
643
+ FeesAggregationResponse
644
+ Single page of fees aggregation data
645
+ """
646
+
647
+ params = {
648
+ "group": group,
649
+ "symbol": symbol,
650
+ "feeSymbol": fee_symbol,
651
+ "aggregationPeriod": aggregation_period,
652
+ "lookbackCount": lookback_count,
653
+ "lookbackTimestamp": lookback_timestamp,
654
+ }
655
+ params = {k: v for k, v in params.items() if v is not None}
656
+
657
+ response = await self._http.get(
658
+ self._build_url(Market.GET_FEES_AGGREGATION), params=params
659
+ )
660
+
661
+ return FeesAggregationResponse.model_validate(response)
662
+
663
+ async def get_fees_aggregation(
664
+ self,
665
+ group: str,
666
+ symbol: Optional[str] = None,
667
+ fee_symbol: Optional[str] = None,
668
+ aggregation_period: Optional[str] = None,
669
+ lookback_count: Optional[int] = None,
670
+ ) -> AsyncIterator[FeesAggregation]:
671
+ """
672
+ Get all fees aggregation data.
673
+
674
+ Automatically handles pagination using lookback_timestamp.
675
+
676
+ Parameters
677
+ ----------
678
+ group : str
679
+ The grouping for the aggregation. Values: "symbol", "feeSymbol"
680
+ symbol : Optional[str]
681
+ The symbol
682
+ fee_symbol : Optional[str]
683
+ The fee symbol. Values: "USDC", "DDX"
684
+ aggregation_period : Optional[str]
685
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
686
+ lookback_count : Optional[int]
687
+ The number of periods to look back from present
688
+
689
+ Yields
690
+ ------
691
+ FeesAggregation
692
+ Fees aggregation entries
693
+ """
694
+
695
+ lookback_timestamp = None
696
+
697
+ while True:
698
+ response = await self.get_fees_aggregation_page(
699
+ group=group,
700
+ symbol=symbol,
701
+ fee_symbol=fee_symbol,
702
+ aggregation_period=aggregation_period,
703
+ lookback_count=lookback_count,
704
+ lookback_timestamp=lookback_timestamp,
705
+ )
706
+
707
+ if not response.value:
708
+ break
709
+
710
+ for item in response.value:
711
+ yield item
712
+
713
+ if response.next_lookback_timestamp is None:
714
+ break
715
+
716
+ lookback_timestamp = response.next_lookback_timestamp
717
+
718
+ async def get_funding_rate_comparison_aggregation(
719
+ self,
720
+ symbol: Optional[str] = None,
721
+ ) -> FundingRateComparisonResponse:
722
+ """
723
+ Get funding rate comparison data between DerivaDEX and major exchanges.
724
+
725
+ Parameters
726
+ ----------
727
+ symbol : Optional[str]
728
+ The symbol
729
+
730
+ Returns
731
+ -------
732
+ FundingRateComparisonResponse
733
+ Funding rate comparison data showing rates and arbitrage opportunities
734
+ between DerivaDEX and other major exchanges (Binance, Bybit, Hyperliquid)
735
+ """
736
+
737
+ params = {
738
+ "symbol": symbol,
739
+ }
740
+ params = {k: v for k, v in params.items() if v is not None}
741
+
742
+ response = await self._http.get(
743
+ self._build_url(Market.GET_FUNDING_RATE_COMPARISON_AGGREGATION),
744
+ params=params,
745
+ )
746
+
747
+ return FundingRateComparisonResponse.model_validate(response)
748
+
749
+ async def get_top_traders_aggregation_page(
750
+ self,
751
+ trader: Optional[str] = None,
752
+ limit: Optional[int] = None,
753
+ cursor: Optional[int] = None,
754
+ top_traders_ordering: Optional[str] = None,
755
+ order: Optional[str] = None,
756
+ ) -> TopTradersAggregationResponse:
757
+ """
758
+ Get a single page of top N traders by volume.
759
+
760
+ Parameters
761
+ ----------
762
+ trader : Optional[str]
763
+ The trader address, with the discriminant prefix
764
+ limit : Optional[int]
765
+ The number of rows to return
766
+ cursor : Optional[int]
767
+ The cursor for the beginning of the next page of top traders to fetch
768
+ top_traders_ordering : Optional[str]
769
+ The order by which to fetch top traders. Values: "volume", "pnl", "accountValue"
770
+ order : Optional[str]
771
+ The ordering of the results. Values: "asc", "desc"
772
+
773
+ Returns
774
+ -------
775
+ TopTradersAggregationResponse
776
+ Single page of top traders aggregation data
777
+ """
778
+
779
+ params = {
780
+ "trader": trader,
781
+ "limit": limit,
782
+ "cursor": cursor,
783
+ "topTradersOrdering": top_traders_ordering,
784
+ "order": order,
785
+ }
786
+ params = {k: v for k, v in params.items() if v is not None}
787
+
788
+ response = await self._http.get(
789
+ self._build_url(Market.GET_TOP_TRADERS_AGGREGATION), params=params
790
+ )
791
+
792
+ return TopTradersAggregationResponse.model_validate(response)
793
+
794
+ async def get_top_traders_aggregation(
795
+ self,
796
+ trader: Optional[str] = None,
797
+ top_traders_ordering: Optional[str] = None,
798
+ order: Optional[str] = None,
799
+ limit: Optional[int] = 100,
800
+ ) -> AsyncIterator[TopTrader]:
801
+ """
802
+ Get all top traders data.
803
+
804
+ Automatically handles pagination using cursor.
805
+
806
+ Parameters
807
+ ----------
808
+ trader : Optional[str]
809
+ The trader address, with the discriminant prefix
810
+ top_traders_ordering : Optional[str]
811
+ The order by which to fetch top traders. Values: "volume", "pnl", "accountValue"
812
+ order : Optional[str]
813
+ The ordering of the results. Values: "asc", "desc"
814
+ limit : Optional[int]
815
+ The number of rows to return per page
816
+
817
+ Yields
818
+ ------
819
+ TopTrader
820
+ Top trader entries
821
+ """
822
+
823
+ cursor = None
824
+
825
+ while True:
826
+ response = await self.get_top_traders_aggregation_page(
827
+ trader=trader,
828
+ limit=limit,
829
+ cursor=cursor,
830
+ top_traders_ordering=top_traders_ordering,
831
+ order=order,
832
+ )
833
+
834
+ if not response.value:
835
+ break
836
+
837
+ for item in response.value:
838
+ yield item
839
+
840
+ if response.next_cursor is None:
841
+ break
842
+
843
+ cursor = response.next_cursor
844
+
845
+ async def get_volume_aggregation_page(
846
+ self,
847
+ group: Optional[str] = None,
848
+ symbol: Optional[str] = None,
849
+ aggregation_period: Optional[str] = None,
850
+ lookback_count: Optional[int] = None,
851
+ lookback_timestamp: Optional[int] = None,
852
+ ) -> VolumeAggregationResponse:
853
+ """
854
+ Get a single page of volume aggregation data.
855
+
856
+ Returns volume per time period looking back from the present.
857
+
858
+ Parameters
859
+ ----------
860
+ group : Optional[str]
861
+ The grouping for the aggregation. Values: "symbol"
862
+ symbol : Optional[str]
863
+ The symbol
864
+ aggregation_period : Optional[str]
865
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
866
+ lookback_count : Optional[int]
867
+ The number of periods to look back from present
868
+ lookback_timestamp : Optional[int]
869
+ The timestamp of the when to begin the lookback from. Each lookback query
870
+ will return nextLookbackTimestamp in the response, which can be passed as
871
+ a query parameter here to get the next page of results
872
+
873
+ Returns
874
+ -------
875
+ VolumeAggregationResponse
876
+ Single page of volume aggregation data
877
+ """
878
+
879
+ params = {
880
+ "group": group,
881
+ "symbol": symbol,
882
+ "aggregationPeriod": aggregation_period,
883
+ "lookbackCount": lookback_count,
884
+ "lookbackTimestamp": lookback_timestamp,
885
+ }
886
+ params = {k: v for k, v in params.items() if v is not None}
887
+
888
+ response = await self._http.get(
889
+ self._build_url(Market.GET_VOLUME_AGGREGATION), params=params
890
+ )
891
+
892
+ return VolumeAggregationResponse.model_validate(response)
893
+
894
+ async def get_volume_aggregation(
895
+ self,
896
+ group: Optional[str] = None,
897
+ symbol: Optional[str] = None,
898
+ aggregation_period: Optional[str] = None,
899
+ lookback_count: Optional[int] = None,
900
+ ) -> AsyncIterator[VolumeAggregation]:
901
+ """
902
+ Get all volume aggregation data.
903
+
904
+ Automatically handles pagination using lookback_timestamp.
905
+
906
+ Parameters
907
+ ----------
908
+ group : Optional[str]
909
+ The grouping for the aggregation. Values: "symbol"
910
+ symbol : Optional[str]
911
+ The symbol
912
+ aggregation_period : Optional[str]
913
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
914
+ lookback_count : Optional[int]
915
+ The number of periods to look back from present
916
+
917
+ Yields
918
+ ------
919
+ VolumeAggregation
920
+ Volume aggregation entries
921
+ """
922
+
923
+ lookback_timestamp = None
924
+
925
+ while True:
926
+ response = await self.get_volume_aggregation_page(
927
+ group=group,
928
+ symbol=symbol,
929
+ aggregation_period=aggregation_period,
930
+ lookback_count=lookback_count,
931
+ lookback_timestamp=lookback_timestamp,
932
+ )
933
+
934
+ if not response.value:
935
+ break
936
+
937
+ for item in response.value:
938
+ yield item
939
+
940
+ if response.next_lookback_timestamp is None:
941
+ break
942
+
943
+ lookback_timestamp = response.next_lookback_timestamp
944
+
945
+ async def get_funding_rate_history_page(
946
+ self,
947
+ limit: Optional[int] = None,
948
+ epoch: Optional[int] = None,
949
+ tx_ordinal: Optional[int] = None,
950
+ order: Optional[str] = None,
951
+ symbol: Optional[str] = None,
952
+ since: Optional[int] = None,
953
+ ) -> FundingRateHistoryResponse:
954
+ """
955
+ Get a single page of funding rates over time.
956
+
957
+ Parameters
958
+ ----------
959
+ limit : Optional[int]
960
+ The number of rows to return
961
+ epoch : Optional[int]
962
+ The epoch boundary used when fetching the next timeseries page
963
+ tx_ordinal : Optional[int]
964
+ The txOrdinal boundary used when fetching the next timeseries page.
965
+ Must be passed along with epoch
966
+ order : Optional[str]
967
+ The ordering of the results. Values: "asc", "desc"
968
+ symbol : Optional[str]
969
+ The symbol
970
+ since : Optional[int]
971
+ The earliest time in seconds to fetch rows for.
972
+ This param cannot be used together with param order = 'desc'
973
+
974
+ Returns
975
+ -------
976
+ FundingRateHistoryResponse
977
+ Single page of funding rate history data
978
+ """
979
+
980
+ params = {
981
+ "limit": limit,
982
+ "epoch": epoch,
983
+ "txOrdinal": tx_ordinal,
984
+ "order": order,
985
+ "symbol": symbol,
986
+ "since": since,
987
+ }
988
+ params = {k: v for k, v in params.items() if v is not None}
989
+
990
+ response = await self._http.get(
991
+ self._build_url(Market.GET_FUNDING_RATE_HISTORY), params=params
992
+ )
993
+
994
+ return FundingRateHistoryResponse.model_validate(response)
995
+
996
+ async def get_funding_rate_history(
997
+ self,
998
+ order: Optional[str] = None,
999
+ symbol: Optional[str] = None,
1000
+ since: Optional[int] = None,
1001
+ limit: Optional[int] = 100,
1002
+ ) -> AsyncIterator[FundingRateHistory]:
1003
+ """
1004
+ Get all funding rate history data.
1005
+
1006
+ Automatically handles pagination using epoch and tx_ordinal.
1007
+
1008
+ Parameters
1009
+ ----------
1010
+ order : Optional[str]
1011
+ The ordering of the results. Values: "asc", "desc"
1012
+ symbol : Optional[str]
1013
+ The symbol
1014
+ since : Optional[int]
1015
+ The earliest time in seconds to fetch rows for.
1016
+ This param cannot be used together with param order = 'desc'
1017
+ limit : Optional[int]
1018
+ The number of rows to return per page
1019
+
1020
+ Yields
1021
+ ------
1022
+ FundingRateHistory
1023
+ Funding rate history entries
1024
+ """
1025
+
1026
+ epoch = None
1027
+ tx_ordinal = None
1028
+
1029
+ while True:
1030
+ response = await self.get_funding_rate_history_page(
1031
+ limit=limit,
1032
+ epoch=epoch,
1033
+ tx_ordinal=tx_ordinal,
1034
+ order=order,
1035
+ symbol=symbol,
1036
+ since=since,
1037
+ )
1038
+
1039
+ if not response.value:
1040
+ break
1041
+
1042
+ for item in response.value:
1043
+ yield item
1044
+
1045
+ if response.next_epoch is None:
1046
+ break
1047
+
1048
+ epoch = response.next_epoch
1049
+ tx_ordinal = response.next_tx_ordinal
1050
+
1051
+ async def get_open_interest_history(
1052
+ self,
1053
+ limit: Optional[int] = None,
1054
+ order: Optional[str] = None,
1055
+ symbol: Optional[str] = None,
1056
+ interval: Optional[str] = None,
1057
+ since: Optional[int] = None,
1058
+ ) -> OpenInterestHistoryResponse:
1059
+ """
1060
+ Get open interest over time.
1061
+
1062
+ Parameters
1063
+ ----------
1064
+ limit : Optional[int]
1065
+ The number of rows to return
1066
+ order : Optional[str]
1067
+ The ordering of the results. Values: "asc", "desc"
1068
+ symbol : Optional[str]
1069
+ The symbol
1070
+ interval : Optional[str]
1071
+ The interval for open interest history. Values: "5m", "1h", "1d"
1072
+ since : Optional[int]
1073
+ The earliest time in seconds to fetch rows for. This param cannot be
1074
+ used together with param order = 'desc'
1075
+
1076
+ Returns
1077
+ -------
1078
+ OpenInterestHistoryResponse
1079
+ Open interest history data
1080
+ """
1081
+
1082
+ params = {
1083
+ "limit": limit,
1084
+ "order": order,
1085
+ "symbol": symbol,
1086
+ "interval": interval,
1087
+ "since": since,
1088
+ }
1089
+ params = {k: v for k, v in params.items() if v is not None}
1090
+
1091
+ response = await self._http.get(
1092
+ self._build_url(Market.GET_OPEN_INTEREST_HISTORY), params=params
1093
+ )
1094
+
1095
+ return OpenInterestHistoryResponse.model_validate(response)
1096
+
1097
+ async def get_order_book_l2(
1098
+ self,
1099
+ symbol: Optional[str] = None,
1100
+ depth: Optional[int] = None,
1101
+ side: Optional[int] = None,
1102
+ price_aggregation: Optional[float] = None,
1103
+ ) -> Dict[str, OrderBook]:
1104
+ """
1105
+ Get current L2 aggregated order book.
1106
+
1107
+ Parameters
1108
+ ----------
1109
+ symbol : Optional[str]
1110
+ The symbol
1111
+ depth : Optional[int]
1112
+ The best N bids and asks to return, where N = depth
1113
+ side : Optional[int]
1114
+ The side of the order. Values: 0 (Bid), 1 (Ask)
1115
+ price_aggregation : Optional[float]
1116
+ The price aggregation to use for the L2 orderbook.
1117
+ Valid values for each symbol include: ETHP: 0.1, 1, 10; BTCP: 1, 10, 100
1118
+
1119
+ Returns
1120
+ -------
1121
+ Dict[str, OrderBook]
1122
+ Dictionary mapping symbols to their respective order books
1123
+ """
1124
+
1125
+ params = {
1126
+ "symbol": symbol,
1127
+ "depth": depth,
1128
+ "side": side,
1129
+ "priceAggregation": price_aggregation,
1130
+ }
1131
+ params = {k: v for k, v in params.items() if v is not None}
1132
+
1133
+ response = await self._http.get(
1134
+ self._build_url(Market.GET_ORDER_BOOK_L2), params=params
1135
+ )
1136
+
1137
+ order_book_response = OrderBookL2Response.model_validate(response)
1138
+
1139
+ return OrderBook.from_response(order_book_response, symbol)
1140
+
1141
+ async def get_price_checkpoint_history_page(
1142
+ self,
1143
+ limit: Optional[int] = None,
1144
+ epoch: Optional[int] = None,
1145
+ tx_ordinal: Optional[int] = None,
1146
+ order: Optional[str] = None,
1147
+ symbol: Optional[str] = None,
1148
+ price_hash: Optional[str] = None,
1149
+ ) -> PriceCheckpointHistoryResponse:
1150
+ """
1151
+ Get a single page of price checkpoints over time.
1152
+
1153
+ Parameters
1154
+ ----------
1155
+ limit : Optional[int]
1156
+ The number of rows to return
1157
+ epoch : Optional[int]
1158
+ The epoch boundary used when fetching the next timeseries page
1159
+ tx_ordinal : Optional[int]
1160
+ The txOrdinal boundary used when fetching the next timeseries page.
1161
+ Must be passed along with epoch
1162
+ order : Optional[str]
1163
+ The ordering of the results. Values: "asc", "desc"
1164
+ symbol : Optional[str]
1165
+ The symbol
1166
+ price_hash : Optional[str]
1167
+ The index price hash of the mark price. Multiple price hash values can be provided
1168
+
1169
+ Returns
1170
+ -------
1171
+ PriceCheckpointHistoryResponse
1172
+ Single page of price checkpoint history data
1173
+ """
1174
+
1175
+ params = {
1176
+ "limit": limit,
1177
+ "epoch": epoch,
1178
+ "txOrdinal": tx_ordinal,
1179
+ "order": order,
1180
+ "symbol": symbol,
1181
+ "priceHash": price_hash,
1182
+ }
1183
+ params = {k: v for k, v in params.items() if v is not None}
1184
+
1185
+ response = await self._http.get(
1186
+ self._build_url(Market.GET_PRICE_CHECKPOINT_HISTORY), params=params
1187
+ )
1188
+
1189
+ return PriceCheckpointHistoryResponse.model_validate(response)
1190
+
1191
+ async def get_price_checkpoint_history(
1192
+ self,
1193
+ order: Optional[str] = None,
1194
+ symbol: Optional[str] = None,
1195
+ price_hash: Optional[str] = None,
1196
+ limit: Optional[int] = 100,
1197
+ ) -> AsyncIterator[PriceCheckpoint]:
1198
+ """
1199
+ Get all price checkpoints over time.
1200
+
1201
+ Automatically handles pagination using epoch and tx_ordinal.
1202
+
1203
+ Parameters
1204
+ ----------
1205
+ order : Optional[str]
1206
+ The ordering of the results. Values: "asc", "desc"
1207
+ symbol : Optional[str]
1208
+ The symbol
1209
+ price_hash : Optional[str]
1210
+ The index price hash of the mark price. Multiple price hash values can be provided
1211
+ limit : Optional[int]
1212
+ The number of rows to return per page
1213
+
1214
+ Yields
1215
+ ------
1216
+ PriceCheckpoint
1217
+ Price checkpoint entries
1218
+ """
1219
+
1220
+ epoch = None
1221
+ tx_ordinal = None
1222
+
1223
+ while True:
1224
+ response = await self.get_price_checkpoint_history_page(
1225
+ limit=limit,
1226
+ epoch=epoch,
1227
+ tx_ordinal=tx_ordinal,
1228
+ order=order,
1229
+ symbol=symbol,
1230
+ price_hash=price_hash,
1231
+ )
1232
+
1233
+ if not response.value:
1234
+ break
1235
+
1236
+ for item in response.value:
1237
+ yield item
1238
+
1239
+ if response.next_epoch is None:
1240
+ break
1241
+
1242
+ epoch = response.next_epoch
1243
+ tx_ordinal = response.next_tx_ordinal