ddx-python 1.0.5__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 (104) hide show
  1. ddx/.gitignore +1 -0
  2. ddx/__init__.py +58 -0
  3. ddx/_rust/__init__.pyi +2009 -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 +21 -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 +541 -0
  17. ddx/auditor/README.md +32 -0
  18. ddx/auditor/__init__.py +0 -0
  19. ddx/auditor/auditor_driver.py +1034 -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 +144 -0
  24. ddx/common/item_utils.py +38 -0
  25. ddx/common/logging.py +184 -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 +97 -0
  37. ddx/common/transactions/event.py +48 -0
  38. ddx/common/transactions/fee_distribution.py +119 -0
  39. ddx/common/transactions/funding.py +294 -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 +227 -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 +125 -0
  50. ddx/common/transactions/insurance_fund_update.py +142 -0
  51. ddx/common/transactions/insurance_fund_withdraw.py +99 -0
  52. ddx/common/transactions/liquidation.py +357 -0
  53. ddx/common/transactions/partial_fill.py +125 -0
  54. ddx/common/transactions/pnl_realization.py +122 -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 +96 -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 +156 -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 +105 -0
  64. ddx/common/transactions/withdraw.py +91 -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 +254 -0
  69. ddx/py.typed +0 -0
  70. ddx/realtime_client/__init__.py +2 -0
  71. ddx/realtime_client/config.py +2 -0
  72. ddx/realtime_client/logs/pytest.log +0 -0
  73. ddx/realtime_client/models/__init__.py +683 -0
  74. ddx/realtime_client/realtime_client.py +567 -0
  75. ddx/rest_client/__init__.py +0 -0
  76. ddx/rest_client/clients/__init__.py +0 -0
  77. ddx/rest_client/clients/base_client.py +60 -0
  78. ddx/rest_client/clients/market_client.py +1241 -0
  79. ddx/rest_client/clients/on_chain_client.py +432 -0
  80. ddx/rest_client/clients/signed_client.py +301 -0
  81. ddx/rest_client/clients/system_client.py +843 -0
  82. ddx/rest_client/clients/trade_client.py +335 -0
  83. ddx/rest_client/constants/__init__.py +0 -0
  84. ddx/rest_client/constants/endpoints.py +67 -0
  85. ddx/rest_client/contracts/__init__.py +0 -0
  86. ddx/rest_client/contracts/checkpoint/__init__.py +560 -0
  87. ddx/rest_client/contracts/ddx/__init__.py +1949 -0
  88. ddx/rest_client/contracts/dummy_token/__init__.py +1014 -0
  89. ddx/rest_client/contracts/i_collateral/__init__.py +1414 -0
  90. ddx/rest_client/contracts/i_stake/__init__.py +696 -0
  91. ddx/rest_client/exceptions/__init__.py +0 -0
  92. ddx/rest_client/exceptions/exceptions.py +32 -0
  93. ddx/rest_client/http/__init__.py +0 -0
  94. ddx/rest_client/http/http_client.py +305 -0
  95. ddx/rest_client/models/__init__.py +0 -0
  96. ddx/rest_client/models/market.py +683 -0
  97. ddx/rest_client/models/signed.py +60 -0
  98. ddx/rest_client/models/system.py +390 -0
  99. ddx/rest_client/models/trade.py +140 -0
  100. ddx/rest_client/utils/__init__.py +0 -0
  101. ddx/rest_client/utils/encryption_utils.py +26 -0
  102. ddx_python-1.0.5.dist-info/METADATA +63 -0
  103. ddx_python-1.0.5.dist-info/RECORD +104 -0
  104. ddx_python-1.0.5.dist-info/WHEEL +4 -0
@@ -0,0 +1,1241 @@
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 (WithdrawDDXRejection)
478
+ limit : Optional[int]
479
+ The number of rows to return
480
+ global_ordinal : Optional[int]
481
+ The global ordinal boundary used when fetching the next timeseries page
482
+ order : Optional[str]
483
+ The ordering of the results. Values: "asc", "desc"
484
+
485
+ Returns
486
+ -------
487
+ TraderUpdateHistoryResponse
488
+ Single page of trader update history data
489
+ """
490
+
491
+ params = {
492
+ "trader": trader,
493
+ "reason": reason,
494
+ "limit": limit,
495
+ "globalOrdinal": global_ordinal,
496
+ "order": order,
497
+ }
498
+ params = {k: v for k, v in params.items() if v is not None}
499
+
500
+ response = await self._http.get(
501
+ self._build_url(Market.GET_TRADER_UPDATE_HISTORY), params=params
502
+ )
503
+
504
+ return TraderUpdateHistoryResponse.model_validate(response)
505
+
506
+ async def get_trader_update_history(
507
+ self,
508
+ trader: Optional[str] = None,
509
+ reason: Optional[int] = None,
510
+ order: Optional[str] = None,
511
+ limit: Optional[int] = 100,
512
+ ) -> AsyncIterator[TraderUpdate]:
513
+ """
514
+ Get all trader DDX balance and profile updates over time.
515
+
516
+ Automatically handles pagination using global_ordinal.
517
+
518
+ Parameters
519
+ ----------
520
+ trader : Optional[str]
521
+ The trader address, with the discriminant prefix
522
+ reason : Optional[int]
523
+ The type of trader update. Multiple trader update values can be provided.
524
+ Values: 0 (Deposit), 1 (WithdrawDDX), 2 (WithdrawDDXIntent),
525
+ 3 (TradeMiningReward), 4 (ProfileUpdate), 5 (FeeDistribution),
526
+ 6 (WithdrawDDXRejection)
527
+ order : Optional[str]
528
+ The ordering of the results. Values: "asc", "desc"
529
+ limit : Optional[int]
530
+ The number of rows to return per page
531
+
532
+ Yields
533
+ ------
534
+ TraderUpdate
535
+ Trader update history entries
536
+ """
537
+
538
+ global_ordinal = None
539
+
540
+ while True:
541
+ response = await self.get_trader_update_history_page(
542
+ trader=trader,
543
+ reason=reason,
544
+ limit=limit,
545
+ global_ordinal=global_ordinal,
546
+ order=order,
547
+ )
548
+
549
+ if not response.value:
550
+ break
551
+
552
+ for item in response.value:
553
+ yield item
554
+
555
+ if response.next_global_ordinal is None:
556
+ break
557
+
558
+ global_ordinal = response.next_global_ordinal
559
+
560
+ async def get_balance_aggregation(
561
+ self,
562
+ trader: Optional[str] = None,
563
+ strategy_id: Optional[str] = None,
564
+ limit: Optional[int] = None,
565
+ aggregation_period: Optional[str] = None,
566
+ lookback_count: Optional[int] = None,
567
+ ) -> BalanceAggregationResponse:
568
+ """
569
+ Get the change of trader's balance for a specific strategy over a specific time period.
570
+
571
+ Returns the change of trader's balance for a specific strategy over a specific
572
+ time period, looking back from the present.
573
+
574
+ Parameters
575
+ ----------
576
+ trader : Optional[str]
577
+ The trader address, with the discriminant prefix
578
+ strategy_id : Optional[str]
579
+ The strategy ID
580
+ limit : Optional[int]
581
+ The number of rows to return
582
+ aggregation_period : Optional[str]
583
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
584
+ lookback_count : Optional[int]
585
+ The number of periods to look back from present
586
+
587
+ Returns
588
+ -------
589
+ BalanceAggregationResponse
590
+ Balance aggregation data showing trader balance changes over time
591
+ """
592
+
593
+ params = {
594
+ "trader": trader,
595
+ "strategyId": strategy_id,
596
+ "limit": limit,
597
+ "aggregationPeriod": aggregation_period,
598
+ "lookbackCount": lookback_count,
599
+ }
600
+ params = {k: v for k, v in params.items() if v is not None}
601
+
602
+ response = await self._http.get(
603
+ self._build_url(Market.GET_BALANCE_AGGREGATION), params=params
604
+ )
605
+
606
+ return BalanceAggregationResponse.model_validate(response)
607
+
608
+ async def get_fees_aggregation_page(
609
+ self,
610
+ group: str,
611
+ symbol: Optional[str] = None,
612
+ fee_symbol: Optional[str] = None,
613
+ aggregation_period: Optional[str] = None,
614
+ lookback_count: Optional[int] = None,
615
+ lookback_timestamp: Optional[int] = None,
616
+ ) -> FeesAggregationResponse:
617
+ """
618
+ Get a single page of fees aggregation data.
619
+
620
+ Returns fees per time period looking back from the present.
621
+
622
+ Parameters
623
+ ----------
624
+ group : str
625
+ The grouping for the aggregation. Values: "symbol", "feeSymbol"
626
+ symbol : Optional[str]
627
+ The symbol
628
+ fee_symbol : Optional[str]
629
+ The fee symbol. Values: "USDC", "DDX"
630
+ aggregation_period : Optional[str]
631
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
632
+ lookback_count : Optional[int]
633
+ The number of periods to look back from present
634
+ lookback_timestamp : Optional[int]
635
+ The timestamp of the when to begin the lookback from. Each lookback query
636
+ will return nextLookbackTimestamp in the response, which can be passed as
637
+ a query parameter here to get the next page of results
638
+
639
+ Returns
640
+ -------
641
+ FeesAggregationResponse
642
+ Single page of fees aggregation data
643
+ """
644
+
645
+ params = {
646
+ "group": group,
647
+ "symbol": symbol,
648
+ "feeSymbol": fee_symbol,
649
+ "aggregationPeriod": aggregation_period,
650
+ "lookbackCount": lookback_count,
651
+ "lookbackTimestamp": lookback_timestamp,
652
+ }
653
+ params = {k: v for k, v in params.items() if v is not None}
654
+
655
+ response = await self._http.get(
656
+ self._build_url(Market.GET_FEES_AGGREGATION), params=params
657
+ )
658
+
659
+ return FeesAggregationResponse.model_validate(response)
660
+
661
+ async def get_fees_aggregation(
662
+ self,
663
+ group: str,
664
+ symbol: Optional[str] = None,
665
+ fee_symbol: Optional[str] = None,
666
+ aggregation_period: Optional[str] = None,
667
+ lookback_count: Optional[int] = None,
668
+ ) -> AsyncIterator[FeesAggregation]:
669
+ """
670
+ Get all fees aggregation data.
671
+
672
+ Automatically handles pagination using lookback_timestamp.
673
+
674
+ Parameters
675
+ ----------
676
+ group : str
677
+ The grouping for the aggregation. Values: "symbol", "feeSymbol"
678
+ symbol : Optional[str]
679
+ The symbol
680
+ fee_symbol : Optional[str]
681
+ The fee symbol. Values: "USDC", "DDX"
682
+ aggregation_period : Optional[str]
683
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
684
+ lookback_count : Optional[int]
685
+ The number of periods to look back from present
686
+
687
+ Yields
688
+ ------
689
+ FeesAggregation
690
+ Fees aggregation entries
691
+ """
692
+
693
+ lookback_timestamp = None
694
+
695
+ while True:
696
+ response = await self.get_fees_aggregation_page(
697
+ group=group,
698
+ symbol=symbol,
699
+ fee_symbol=fee_symbol,
700
+ aggregation_period=aggregation_period,
701
+ lookback_count=lookback_count,
702
+ lookback_timestamp=lookback_timestamp,
703
+ )
704
+
705
+ if not response.value:
706
+ break
707
+
708
+ for item in response.value:
709
+ yield item
710
+
711
+ if response.next_lookback_timestamp is None:
712
+ break
713
+
714
+ lookback_timestamp = response.next_lookback_timestamp
715
+
716
+ async def get_funding_rate_comparison_aggregation(
717
+ self,
718
+ symbol: Optional[str] = None,
719
+ ) -> FundingRateComparisonResponse:
720
+ """
721
+ Get funding rate comparison data between DerivaDEX and major exchanges.
722
+
723
+ Parameters
724
+ ----------
725
+ symbol : Optional[str]
726
+ The symbol
727
+
728
+ Returns
729
+ -------
730
+ FundingRateComparisonResponse
731
+ Funding rate comparison data showing rates and arbitrage opportunities
732
+ between DerivaDEX and other major exchanges (Binance, Bybit, Hyperliquid)
733
+ """
734
+
735
+ params = {
736
+ "symbol": symbol,
737
+ }
738
+ params = {k: v for k, v in params.items() if v is not None}
739
+
740
+ response = await self._http.get(
741
+ self._build_url(Market.GET_FUNDING_RATE_COMPARISON_AGGREGATION),
742
+ params=params,
743
+ )
744
+
745
+ return FundingRateComparisonResponse.model_validate(response)
746
+
747
+ async def get_top_traders_aggregation_page(
748
+ self,
749
+ trader: Optional[str] = None,
750
+ limit: Optional[int] = None,
751
+ cursor: Optional[int] = None,
752
+ top_traders_ordering: Optional[str] = None,
753
+ order: Optional[str] = None,
754
+ ) -> TopTradersAggregationResponse:
755
+ """
756
+ Get a single page of top N traders by volume.
757
+
758
+ Parameters
759
+ ----------
760
+ trader : Optional[str]
761
+ The trader address, with the discriminant prefix
762
+ limit : Optional[int]
763
+ The number of rows to return
764
+ cursor : Optional[int]
765
+ The cursor for the beginning of the next page of top traders to fetch
766
+ top_traders_ordering : Optional[str]
767
+ The order by which to fetch top traders. Values: "volume", "pnl", "accountValue"
768
+ order : Optional[str]
769
+ The ordering of the results. Values: "asc", "desc"
770
+
771
+ Returns
772
+ -------
773
+ TopTradersAggregationResponse
774
+ Single page of top traders aggregation data
775
+ """
776
+
777
+ params = {
778
+ "trader": trader,
779
+ "limit": limit,
780
+ "cursor": cursor,
781
+ "topTradersOrdering": top_traders_ordering,
782
+ "order": order,
783
+ }
784
+ params = {k: v for k, v in params.items() if v is not None}
785
+
786
+ response = await self._http.get(
787
+ self._build_url(Market.GET_TOP_TRADERS_AGGREGATION), params=params
788
+ )
789
+
790
+ return TopTradersAggregationResponse.model_validate(response)
791
+
792
+ async def get_top_traders_aggregation(
793
+ self,
794
+ trader: Optional[str] = None,
795
+ top_traders_ordering: Optional[str] = None,
796
+ order: Optional[str] = None,
797
+ limit: Optional[int] = 100,
798
+ ) -> AsyncIterator[TopTrader]:
799
+ """
800
+ Get all top traders data.
801
+
802
+ Automatically handles pagination using cursor.
803
+
804
+ Parameters
805
+ ----------
806
+ trader : Optional[str]
807
+ The trader address, with the discriminant prefix
808
+ top_traders_ordering : Optional[str]
809
+ The order by which to fetch top traders. Values: "volume", "pnl", "accountValue"
810
+ order : Optional[str]
811
+ The ordering of the results. Values: "asc", "desc"
812
+ limit : Optional[int]
813
+ The number of rows to return per page
814
+
815
+ Yields
816
+ ------
817
+ TopTrader
818
+ Top trader entries
819
+ """
820
+
821
+ cursor = None
822
+
823
+ while True:
824
+ response = await self.get_top_traders_aggregation_page(
825
+ trader=trader,
826
+ limit=limit,
827
+ cursor=cursor,
828
+ top_traders_ordering=top_traders_ordering,
829
+ order=order,
830
+ )
831
+
832
+ if not response.value:
833
+ break
834
+
835
+ for item in response.value:
836
+ yield item
837
+
838
+ if response.next_cursor is None:
839
+ break
840
+
841
+ cursor = response.next_cursor
842
+
843
+ async def get_volume_aggregation_page(
844
+ self,
845
+ group: Optional[str] = None,
846
+ symbol: Optional[str] = None,
847
+ aggregation_period: Optional[str] = None,
848
+ lookback_count: Optional[int] = None,
849
+ lookback_timestamp: Optional[int] = None,
850
+ ) -> VolumeAggregationResponse:
851
+ """
852
+ Get a single page of volume aggregation data.
853
+
854
+ Returns volume per time period looking back from the present.
855
+
856
+ Parameters
857
+ ----------
858
+ group : Optional[str]
859
+ The grouping for the aggregation. Values: "symbol"
860
+ symbol : Optional[str]
861
+ The symbol
862
+ aggregation_period : Optional[str]
863
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
864
+ lookback_count : Optional[int]
865
+ The number of periods to look back from present
866
+ lookback_timestamp : Optional[int]
867
+ The timestamp of the when to begin the lookback from. Each lookback query
868
+ will return nextLookbackTimestamp in the response, which can be passed as
869
+ a query parameter here to get the next page of results
870
+
871
+ Returns
872
+ -------
873
+ VolumeAggregationResponse
874
+ Single page of volume aggregation data
875
+ """
876
+
877
+ params = {
878
+ "group": group,
879
+ "symbol": symbol,
880
+ "aggregationPeriod": aggregation_period,
881
+ "lookbackCount": lookback_count,
882
+ "lookbackTimestamp": lookback_timestamp,
883
+ }
884
+ params = {k: v for k, v in params.items() if v is not None}
885
+
886
+ response = await self._http.get(
887
+ self._build_url(Market.GET_VOLUME_AGGREGATION), params=params
888
+ )
889
+
890
+ return VolumeAggregationResponse.model_validate(response)
891
+
892
+ async def get_volume_aggregation(
893
+ self,
894
+ group: Optional[str] = None,
895
+ symbol: Optional[str] = None,
896
+ aggregation_period: Optional[str] = None,
897
+ lookback_count: Optional[int] = None,
898
+ ) -> AsyncIterator[VolumeAggregation]:
899
+ """
900
+ Get all volume aggregation data.
901
+
902
+ Automatically handles pagination using lookback_timestamp.
903
+
904
+ Parameters
905
+ ----------
906
+ group : Optional[str]
907
+ The grouping for the aggregation. Values: "symbol"
908
+ symbol : Optional[str]
909
+ The symbol
910
+ aggregation_period : Optional[str]
911
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
912
+ lookback_count : Optional[int]
913
+ The number of periods to look back from present
914
+
915
+ Yields
916
+ ------
917
+ VolumeAggregation
918
+ Volume aggregation entries
919
+ """
920
+
921
+ lookback_timestamp = None
922
+
923
+ while True:
924
+ response = await self.get_volume_aggregation_page(
925
+ group=group,
926
+ symbol=symbol,
927
+ aggregation_period=aggregation_period,
928
+ lookback_count=lookback_count,
929
+ lookback_timestamp=lookback_timestamp,
930
+ )
931
+
932
+ if not response.value:
933
+ break
934
+
935
+ for item in response.value:
936
+ yield item
937
+
938
+ if response.next_lookback_timestamp is None:
939
+ break
940
+
941
+ lookback_timestamp = response.next_lookback_timestamp
942
+
943
+ async def get_funding_rate_history_page(
944
+ self,
945
+ limit: Optional[int] = None,
946
+ epoch: Optional[int] = None,
947
+ tx_ordinal: Optional[int] = None,
948
+ order: Optional[str] = None,
949
+ symbol: Optional[str] = None,
950
+ since: Optional[int] = None,
951
+ ) -> FundingRateHistoryResponse:
952
+ """
953
+ Get a single page of funding rates over time.
954
+
955
+ Parameters
956
+ ----------
957
+ limit : Optional[int]
958
+ The number of rows to return
959
+ epoch : Optional[int]
960
+ The epoch boundary used when fetching the next timeseries page
961
+ tx_ordinal : Optional[int]
962
+ The txOrdinal boundary used when fetching the next timeseries page.
963
+ Must be passed along with epoch
964
+ order : Optional[str]
965
+ The ordering of the results. Values: "asc", "desc"
966
+ symbol : Optional[str]
967
+ The symbol
968
+ since : Optional[int]
969
+ The earliest time in seconds to fetch rows for.
970
+ This param cannot be used together with param order = 'desc'
971
+
972
+ Returns
973
+ -------
974
+ FundingRateHistoryResponse
975
+ Single page of funding rate history data
976
+ """
977
+
978
+ params = {
979
+ "limit": limit,
980
+ "epoch": epoch,
981
+ "txOrdinal": tx_ordinal,
982
+ "order": order,
983
+ "symbol": symbol,
984
+ "since": since,
985
+ }
986
+ params = {k: v for k, v in params.items() if v is not None}
987
+
988
+ response = await self._http.get(
989
+ self._build_url(Market.GET_FUNDING_RATE_HISTORY), params=params
990
+ )
991
+
992
+ return FundingRateHistoryResponse.model_validate(response)
993
+
994
+ async def get_funding_rate_history(
995
+ self,
996
+ order: Optional[str] = None,
997
+ symbol: Optional[str] = None,
998
+ since: Optional[int] = None,
999
+ limit: Optional[int] = 100,
1000
+ ) -> AsyncIterator[FundingRateHistory]:
1001
+ """
1002
+ Get all funding rate history data.
1003
+
1004
+ Automatically handles pagination using epoch and tx_ordinal.
1005
+
1006
+ Parameters
1007
+ ----------
1008
+ order : Optional[str]
1009
+ The ordering of the results. Values: "asc", "desc"
1010
+ symbol : Optional[str]
1011
+ The symbol
1012
+ since : Optional[int]
1013
+ The earliest time in seconds to fetch rows for.
1014
+ This param cannot be used together with param order = 'desc'
1015
+ limit : Optional[int]
1016
+ The number of rows to return per page
1017
+
1018
+ Yields
1019
+ ------
1020
+ FundingRateHistory
1021
+ Funding rate history entries
1022
+ """
1023
+
1024
+ epoch = None
1025
+ tx_ordinal = None
1026
+
1027
+ while True:
1028
+ response = await self.get_funding_rate_history_page(
1029
+ limit=limit,
1030
+ epoch=epoch,
1031
+ tx_ordinal=tx_ordinal,
1032
+ order=order,
1033
+ symbol=symbol,
1034
+ since=since,
1035
+ )
1036
+
1037
+ if not response.value:
1038
+ break
1039
+
1040
+ for item in response.value:
1041
+ yield item
1042
+
1043
+ if response.next_epoch is None:
1044
+ break
1045
+
1046
+ epoch = response.next_epoch
1047
+ tx_ordinal = response.next_tx_ordinal
1048
+
1049
+ async def get_open_interest_history(
1050
+ self,
1051
+ limit: Optional[int] = None,
1052
+ order: Optional[str] = None,
1053
+ symbol: Optional[str] = None,
1054
+ interval: Optional[str] = None,
1055
+ since: Optional[int] = None,
1056
+ ) -> OpenInterestHistoryResponse:
1057
+ """
1058
+ Get open interest over time.
1059
+
1060
+ Parameters
1061
+ ----------
1062
+ limit : Optional[int]
1063
+ The number of rows to return
1064
+ order : Optional[str]
1065
+ The ordering of the results. Values: "asc", "desc"
1066
+ symbol : Optional[str]
1067
+ The symbol
1068
+ interval : Optional[str]
1069
+ The interval for open interest history. Values: "5m", "1h", "1d"
1070
+ since : Optional[int]
1071
+ The earliest time in seconds to fetch rows for. This param cannot be
1072
+ used together with param order = 'desc'
1073
+
1074
+ Returns
1075
+ -------
1076
+ OpenInterestHistoryResponse
1077
+ Open interest history data
1078
+ """
1079
+
1080
+ params = {
1081
+ "limit": limit,
1082
+ "order": order,
1083
+ "symbol": symbol,
1084
+ "interval": interval,
1085
+ "since": since,
1086
+ }
1087
+ params = {k: v for k, v in params.items() if v is not None}
1088
+
1089
+ response = await self._http.get(
1090
+ self._build_url(Market.GET_OPEN_INTEREST_HISTORY), params=params
1091
+ )
1092
+
1093
+ return OpenInterestHistoryResponse.model_validate(response)
1094
+
1095
+ async def get_order_book_l2(
1096
+ self,
1097
+ symbol: Optional[str] = None,
1098
+ depth: Optional[int] = None,
1099
+ side: Optional[int] = None,
1100
+ price_aggregation: Optional[float] = None,
1101
+ ) -> Dict[str, OrderBook]:
1102
+ """
1103
+ Get current L2 aggregated order book.
1104
+
1105
+ Parameters
1106
+ ----------
1107
+ symbol : Optional[str]
1108
+ The symbol
1109
+ depth : Optional[int]
1110
+ The best N bids and asks to return, where N = depth
1111
+ side : Optional[int]
1112
+ The side of the order. Values: 0 (Bid), 1 (Ask)
1113
+ price_aggregation : Optional[float]
1114
+ The price aggregation to use for the L2 orderbook.
1115
+ Valid values for each symbol include: ETHP: 0.1, 1, 10; BTCP: 1, 10, 100
1116
+
1117
+ Returns
1118
+ -------
1119
+ Dict[str, OrderBook]
1120
+ Dictionary mapping symbols to their respective order books
1121
+ """
1122
+
1123
+ params = {
1124
+ "symbol": symbol,
1125
+ "depth": depth,
1126
+ "side": side,
1127
+ "priceAggregation": price_aggregation,
1128
+ }
1129
+ params = {k: v for k, v in params.items() if v is not None}
1130
+
1131
+ response = await self._http.get(
1132
+ self._build_url(Market.GET_ORDER_BOOK_L2), params=params
1133
+ )
1134
+
1135
+ order_book_response = OrderBookL2Response.model_validate(response)
1136
+
1137
+ return OrderBook.from_response(order_book_response, symbol)
1138
+
1139
+ async def get_price_checkpoint_history_page(
1140
+ self,
1141
+ limit: Optional[int] = None,
1142
+ epoch: Optional[int] = None,
1143
+ tx_ordinal: Optional[int] = None,
1144
+ order: Optional[str] = None,
1145
+ symbol: Optional[str] = None,
1146
+ price_hash: Optional[str] = None,
1147
+ ) -> PriceCheckpointHistoryResponse:
1148
+ """
1149
+ Get a single page of price checkpoints over time.
1150
+
1151
+ Parameters
1152
+ ----------
1153
+ limit : Optional[int]
1154
+ The number of rows to return
1155
+ epoch : Optional[int]
1156
+ The epoch boundary used when fetching the next timeseries page
1157
+ tx_ordinal : Optional[int]
1158
+ The txOrdinal boundary used when fetching the next timeseries page.
1159
+ Must be passed along with epoch
1160
+ order : Optional[str]
1161
+ The ordering of the results. Values: "asc", "desc"
1162
+ symbol : Optional[str]
1163
+ The symbol
1164
+ price_hash : Optional[str]
1165
+ The index price hash of the mark price. Multiple price hash values can be provided
1166
+
1167
+ Returns
1168
+ -------
1169
+ PriceCheckpointHistoryResponse
1170
+ Single page of price checkpoint history data
1171
+ """
1172
+
1173
+ params = {
1174
+ "limit": limit,
1175
+ "epoch": epoch,
1176
+ "txOrdinal": tx_ordinal,
1177
+ "order": order,
1178
+ "symbol": symbol,
1179
+ "priceHash": price_hash,
1180
+ }
1181
+ params = {k: v for k, v in params.items() if v is not None}
1182
+
1183
+ response = await self._http.get(
1184
+ self._build_url(Market.GET_PRICE_CHECKPOINT_HISTORY), params=params
1185
+ )
1186
+
1187
+ return PriceCheckpointHistoryResponse.model_validate(response)
1188
+
1189
+ async def get_price_checkpoint_history(
1190
+ self,
1191
+ order: Optional[str] = None,
1192
+ symbol: Optional[str] = None,
1193
+ price_hash: Optional[str] = None,
1194
+ limit: Optional[int] = 100,
1195
+ ) -> AsyncIterator[PriceCheckpoint]:
1196
+ """
1197
+ Get all price checkpoints over time.
1198
+
1199
+ Automatically handles pagination using epoch and tx_ordinal.
1200
+
1201
+ Parameters
1202
+ ----------
1203
+ order : Optional[str]
1204
+ The ordering of the results. Values: "asc", "desc"
1205
+ symbol : Optional[str]
1206
+ The symbol
1207
+ price_hash : Optional[str]
1208
+ The index price hash of the mark price. Multiple price hash values can be provided
1209
+ limit : Optional[int]
1210
+ The number of rows to return per page
1211
+
1212
+ Yields
1213
+ ------
1214
+ PriceCheckpoint
1215
+ Price checkpoint entries
1216
+ """
1217
+
1218
+ epoch = None
1219
+ tx_ordinal = None
1220
+
1221
+ while True:
1222
+ response = await self.get_price_checkpoint_history_page(
1223
+ limit=limit,
1224
+ epoch=epoch,
1225
+ tx_ordinal=tx_ordinal,
1226
+ order=order,
1227
+ symbol=symbol,
1228
+ price_hash=price_hash,
1229
+ )
1230
+
1231
+ if not response.value:
1232
+ break
1233
+
1234
+ for item in response.value:
1235
+ yield item
1236
+
1237
+ if response.next_epoch is None:
1238
+ break
1239
+
1240
+ epoch = response.next_epoch
1241
+ tx_ordinal = response.next_tx_ordinal