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,843 @@
1
+ from typing import Optional, AsyncIterator
2
+
3
+ from ddx.rest_client.clients.base_client import BaseClient
4
+ from ddx.rest_client.constants.endpoints import System
5
+ from ddx.rest_client.models.system import (
6
+ ExchangeInfoResponse,
7
+ PingResponse,
8
+ SymbolsResponse,
9
+ Symbol,
10
+ ServerTimeResponse,
11
+ CollateralAggregationResponse,
12
+ CollateralAggregation,
13
+ DDXAggregationResponse,
14
+ DDXAggregation,
15
+ InsuranceFundAggregationResponse,
16
+ InsuranceFundAggregation,
17
+ EpochHistoryResponse,
18
+ Epoch,
19
+ InsuranceFundHistoryResponse,
20
+ InsuranceFund,
21
+ SpecsResponse,
22
+ Spec,
23
+ ExchangeStatusResponse,
24
+ DDXSupplyResponse,
25
+ TradableProductsResponse,
26
+ TradableProduct,
27
+ DeploymentInfo,
28
+ )
29
+
30
+
31
+ class SystemClient(BaseClient):
32
+ """
33
+ System-related operations and data access.
34
+
35
+ Provides access to exchange configuration, system status, and other
36
+ system-related information through the API endpoints.
37
+ """
38
+
39
+ async def get_exchange_info(self) -> ExchangeInfoResponse:
40
+ """
41
+ Get global exchange configuration.
42
+
43
+ Returns
44
+ -------
45
+ ExchangeInfoResponse
46
+ Exchange configuration information including settlement info,
47
+ supported assets, and trading symbols
48
+ """
49
+
50
+ response = await self._http.get(self._build_url(System.GET_EXCHANGE_INFO))
51
+
52
+ return ExchangeInfoResponse.model_validate(response)
53
+
54
+ async def get_connection_info(self) -> PingResponse:
55
+ """
56
+ Simple connectivity test.
57
+
58
+ Returns
59
+ -------
60
+ PingResponse
61
+ Empty response indicating successful connection
62
+ """
63
+
64
+ response = await self._http.get(self._build_url(System.GET_CONNECTION_INFO))
65
+
66
+ return PingResponse.model_validate(response)
67
+
68
+ async def get_symbols_page(
69
+ self,
70
+ kind: Optional[int] = None,
71
+ is_active: Optional[bool] = None,
72
+ limit: Optional[int] = None,
73
+ offset: Optional[int] = None,
74
+ ) -> SymbolsResponse:
75
+ """
76
+ Get a single page of SEO-friendly alias for tradable products.
77
+
78
+ Parameters
79
+ ----------
80
+ kind : Optional[int]
81
+ The type of spec update. Values: 0 (Market), 1 (SpotGateway)
82
+ is_active : Optional[bool]
83
+ Checks for the active state of the tradable product
84
+ limit : Optional[int]
85
+ The number of rows to return
86
+ offset : Optional[int]
87
+ The offset of returned rows
88
+
89
+ Returns
90
+ -------
91
+ SymbolsResponse
92
+ Single page of symbols data
93
+ """
94
+
95
+ params = {
96
+ "kind": kind,
97
+ "isActive": is_active,
98
+ "limit": limit,
99
+ "offset": offset,
100
+ }
101
+ params = {k: v for k, v in params.items() if v is not None}
102
+
103
+ response = await self._http.get(
104
+ self._build_url(System.GET_SYMBOLS), params=params
105
+ )
106
+
107
+ return SymbolsResponse.model_validate(response)
108
+
109
+ async def get_symbols(
110
+ self,
111
+ kind: Optional[int] = None,
112
+ is_active: Optional[bool] = None,
113
+ limit: Optional[int] = 100,
114
+ ) -> AsyncIterator[Symbol]:
115
+ """
116
+ Get all symbols.
117
+
118
+ Automatically handles pagination using offset.
119
+
120
+ Parameters
121
+ ----------
122
+ kind : Optional[int]
123
+ The type of spec update. Values: 0 (Market), 1 (SpotGateway)
124
+ is_active : Optional[bool]
125
+ Checks for the active state of the tradable product
126
+ limit : Optional[int]
127
+ The number of rows to return per page
128
+
129
+ Yields
130
+ ------
131
+ Symbol
132
+ Symbol entries
133
+ """
134
+
135
+ offset = 0
136
+
137
+ while True:
138
+ response = await self.get_symbols_page(
139
+ kind=kind,
140
+ is_active=is_active,
141
+ limit=limit,
142
+ offset=offset,
143
+ )
144
+
145
+ if not response.value:
146
+ break
147
+
148
+ for item in response.value:
149
+ yield item
150
+
151
+ if len(response.value) < limit:
152
+ break
153
+
154
+ offset += len(response.value)
155
+
156
+ async def get_server_time(self) -> ServerTimeResponse:
157
+ """
158
+ Get server time for clock synchronization.
159
+
160
+ Returns
161
+ -------
162
+ ServerTimeResponse
163
+ Server time in milliseconds
164
+ """
165
+
166
+ response = await self._http.get(self._build_url(System.GET_SERVER_TIME))
167
+
168
+ return ServerTimeResponse.model_validate(response)
169
+
170
+ async def get_collateral_aggregation_page(
171
+ self,
172
+ aggregation_period: Optional[str] = None,
173
+ starting_value: Optional[float] = None,
174
+ from_epoch: Optional[int] = None,
175
+ to_epoch: Optional[int] = None,
176
+ ) -> CollateralAggregationResponse:
177
+ """
178
+ Get a single page of collateral aggregation data.
179
+
180
+ Returns a rolling sum of collateral per time period grouped by
181
+ the inflow and outflow types.
182
+
183
+ Parameters
184
+ ----------
185
+ aggregation_period : Optional[str]
186
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
187
+ starting_value : Optional[float]
188
+ The partial total of this aggregation, used for rolling aggregation paging
189
+ from_epoch : Optional[int]
190
+ The from epoch
191
+ to_epoch : Optional[int]
192
+ The to epoch
193
+
194
+ Returns
195
+ -------
196
+ CollateralAggregationResponse
197
+ Single page of collateral aggregation data
198
+ """
199
+
200
+ params = {
201
+ "aggregationPeriod": aggregation_period,
202
+ "startingValue": starting_value,
203
+ "fromEpoch": from_epoch,
204
+ "toEpoch": to_epoch,
205
+ }
206
+ params = {k: v for k, v in params.items() if v is not None}
207
+
208
+ response = await self._http.get(
209
+ self._build_url(System.GET_COLLATERAL_AGGREGATION), params=params
210
+ )
211
+
212
+ return CollateralAggregationResponse.model_validate(response)
213
+
214
+ async def get_collateral_aggregation(
215
+ self,
216
+ aggregation_period: Optional[str] = None,
217
+ from_epoch: Optional[int] = None,
218
+ to_epoch: Optional[int] = None,
219
+ ) -> AsyncIterator[CollateralAggregation]:
220
+ """
221
+ Get all collateral aggregation data.
222
+
223
+ Automatically handles pagination using starting_value.
224
+
225
+ Parameters
226
+ ----------
227
+ aggregation_period : Optional[str]
228
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
229
+ from_epoch : Optional[int]
230
+ The from epoch
231
+ to_epoch : Optional[int]
232
+ The to epoch
233
+
234
+ Yields
235
+ ------
236
+ CollateralAggregation
237
+ Collateral aggregation entries
238
+ """
239
+
240
+ starting_value = None
241
+
242
+ while True:
243
+ response = await self.get_collateral_aggregation_page(
244
+ aggregation_period=aggregation_period,
245
+ starting_value=starting_value,
246
+ from_epoch=from_epoch,
247
+ to_epoch=to_epoch,
248
+ )
249
+
250
+ if not response.value:
251
+ break
252
+
253
+ for item in response.value:
254
+ yield item
255
+
256
+ if response.next_starting_value is None:
257
+ break
258
+
259
+ starting_value = float(response.next_starting_value)
260
+
261
+ async def get_ddx_aggregation_page(
262
+ self,
263
+ aggregation_period: Optional[str] = None,
264
+ starting_value: Optional[float] = None,
265
+ from_epoch: Optional[int] = None,
266
+ to_epoch: Optional[int] = None,
267
+ ) -> DDXAggregationResponse:
268
+ """
269
+ Get a single page of DDX aggregation data.
270
+
271
+ Returns a rolling sum of DDX per time period grouped by
272
+ the inflow and outflow types.
273
+
274
+ Parameters
275
+ ----------
276
+ aggregation_period : Optional[str]
277
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
278
+ starting_value : Optional[float]
279
+ The partial total of this aggregation, used for rolling aggregation paging
280
+ from_epoch : Optional[int]
281
+ The from epoch
282
+ to_epoch : Optional[int]
283
+ The to epoch
284
+
285
+ Returns
286
+ -------
287
+ DDXAggregationResponse
288
+ Single page of DDX aggregation data
289
+ """
290
+
291
+ params = {
292
+ "aggregationPeriod": aggregation_period,
293
+ "startingValue": starting_value,
294
+ "fromEpoch": from_epoch,
295
+ "toEpoch": to_epoch,
296
+ }
297
+ params = {k: v for k, v in params.items() if v is not None}
298
+
299
+ response = await self._http.get(
300
+ self._build_url(System.GET_DDX_AGGREGATION), params=params
301
+ )
302
+
303
+ return DDXAggregationResponse.model_validate(response)
304
+
305
+ async def get_ddx_aggregation(
306
+ self,
307
+ aggregation_period: Optional[str] = None,
308
+ from_epoch: Optional[int] = None,
309
+ to_epoch: Optional[int] = None,
310
+ ) -> AsyncIterator[DDXAggregation]:
311
+ """
312
+ Get all DDX aggregation data.
313
+
314
+ Automatically handles pagination using starting_value.
315
+
316
+ Parameters
317
+ ----------
318
+ aggregation_period : Optional[str]
319
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
320
+ from_epoch : Optional[int]
321
+ The from epoch
322
+ to_epoch : Optional[int]
323
+ The to epoch
324
+
325
+ Yields
326
+ ------
327
+ DDXAggregation
328
+ DDX aggregation entries
329
+ """
330
+
331
+ starting_value = None
332
+
333
+ while True:
334
+ response = await self.get_ddx_aggregation_page(
335
+ aggregation_period=aggregation_period,
336
+ starting_value=starting_value,
337
+ from_epoch=from_epoch,
338
+ to_epoch=to_epoch,
339
+ )
340
+
341
+ if not response.value:
342
+ break
343
+
344
+ for item in response.value:
345
+ yield item
346
+
347
+ if response.next_starting_value is None:
348
+ break
349
+
350
+ starting_value = float(response.next_starting_value)
351
+
352
+ async def get_insurance_fund_aggregation_page(
353
+ self,
354
+ aggregation_period: Optional[str] = None,
355
+ starting_value: Optional[float] = None,
356
+ from_epoch: Optional[int] = None,
357
+ to_epoch: Optional[int] = None,
358
+ ) -> InsuranceFundAggregationResponse:
359
+ """
360
+ Get a single page of insurance fund aggregation data.
361
+
362
+ Returns a rolling sum of insurance fund value per time period
363
+ grouped by the inflow and outflow types.
364
+
365
+ Parameters
366
+ ----------
367
+ aggregation_period : Optional[str]
368
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
369
+ starting_value : Optional[float]
370
+ The partial total of this aggregation, used for rolling aggregation paging
371
+ from_epoch : Optional[int]
372
+ The from epoch
373
+ to_epoch : Optional[int]
374
+ The to epoch
375
+
376
+ Returns
377
+ -------
378
+ InsuranceFundAggregationResponse
379
+ Single page of insurance fund aggregation data
380
+ """
381
+
382
+ params = {
383
+ "aggregationPeriod": aggregation_period,
384
+ "startingValue": starting_value,
385
+ "fromEpoch": from_epoch,
386
+ "toEpoch": to_epoch,
387
+ }
388
+ params = {k: v for k, v in params.items() if v is not None}
389
+
390
+ response = await self._http.get(
391
+ self._build_url(System.GET_INSURANCE_FUND_AGGREGATION), params=params
392
+ )
393
+
394
+ return InsuranceFundAggregationResponse.model_validate(response)
395
+
396
+ async def get_insurance_fund_aggregation(
397
+ self,
398
+ aggregation_period: Optional[str] = None,
399
+ from_epoch: Optional[int] = None,
400
+ to_epoch: Optional[int] = None,
401
+ ) -> AsyncIterator[InsuranceFundAggregation]:
402
+ """
403
+ Get all insurance fund aggregation data.
404
+
405
+ Automatically handles pagination using starting_value.
406
+
407
+ Parameters
408
+ ----------
409
+ aggregation_period : Optional[str]
410
+ The period for the aggregation. Values: "week", "day", "hour", "minute"
411
+ from_epoch : Optional[int]
412
+ The from epoch
413
+ to_epoch : Optional[int]
414
+ The to epoch
415
+
416
+ Yields
417
+ ------
418
+ InsuranceFundAggregation
419
+ Insurance fund aggregation entries
420
+ """
421
+
422
+ starting_value = None
423
+
424
+ while True:
425
+ response = await self.get_insurance_fund_aggregation_page(
426
+ aggregation_period=aggregation_period,
427
+ starting_value=starting_value,
428
+ from_epoch=from_epoch,
429
+ to_epoch=to_epoch,
430
+ )
431
+
432
+ if not response.value:
433
+ break
434
+
435
+ for item in response.value:
436
+ yield item
437
+
438
+ if response.next_starting_value is None:
439
+ break
440
+
441
+ starting_value = float(response.next_starting_value)
442
+
443
+ async def get_epoch_history_page(
444
+ self,
445
+ epoch: Optional[int] = None,
446
+ limit: Optional[int] = None,
447
+ offset: Optional[int] = None,
448
+ ) -> EpochHistoryResponse:
449
+ """
450
+ Get a single page of epoch timetable and paging cursors.
451
+
452
+ Parameters
453
+ ----------
454
+ epoch : Optional[int]
455
+ The epoch boundary used when fetching the next timeseries page
456
+ limit : Optional[int]
457
+ The number of rows to return
458
+ offset : Optional[int]
459
+ The offset of returned rows
460
+
461
+ Returns
462
+ -------
463
+ EpochHistoryResponse
464
+ Single page of epoch history data
465
+ """
466
+
467
+ params = {
468
+ "epoch": epoch,
469
+ "limit": limit,
470
+ "offset": offset,
471
+ }
472
+ params = {k: v for k, v in params.items() if v is not None}
473
+
474
+ response = await self._http.get(
475
+ self._build_url(System.GET_EPOCH_HISTORY), params=params
476
+ )
477
+
478
+ return EpochHistoryResponse.model_validate(response)
479
+
480
+ async def get_epoch_history(
481
+ self,
482
+ epoch: Optional[int] = None,
483
+ limit: Optional[int] = 100,
484
+ ) -> AsyncIterator[Epoch]:
485
+ """
486
+ Get all epoch history data.
487
+
488
+ Automatically handles pagination using offset.
489
+
490
+ Parameters
491
+ ----------
492
+ epoch : Optional[int]
493
+ The epoch boundary used when fetching the next timeseries page
494
+ limit : Optional[int]
495
+ The number of rows to return per page
496
+
497
+ Yields
498
+ ------
499
+ Epoch
500
+ Epoch entries
501
+ """
502
+
503
+ offset = 0
504
+
505
+ while True:
506
+ response = await self.get_epoch_history_page(
507
+ epoch=epoch,
508
+ limit=limit,
509
+ offset=offset,
510
+ )
511
+
512
+ if not response.value:
513
+ break
514
+
515
+ for item in response.value:
516
+ yield item
517
+
518
+ if len(response.value) < limit:
519
+ break
520
+
521
+ offset += len(response.value)
522
+
523
+ async def get_insurance_fund_history_page(
524
+ self,
525
+ limit: Optional[int] = None,
526
+ epoch: Optional[int] = None,
527
+ tx_ordinal: Optional[int] = None,
528
+ order: Optional[str] = None,
529
+ symbol: Optional[str] = None,
530
+ ) -> InsuranceFundHistoryResponse:
531
+ """
532
+ Get a single page of insurance fund balance history.
533
+
534
+ Parameters
535
+ ----------
536
+ limit : Optional[int]
537
+ The number of rows to return
538
+ epoch : Optional[int]
539
+ The epoch boundary used when fetching the next timeseries page
540
+ tx_ordinal : Optional[int]
541
+ The txOrdinal boundary used when fetching the next timeseries page.
542
+ Must be passed along with epoch
543
+ order : Optional[str]
544
+ The ordering of the results. Values: "asc", "desc"
545
+ symbol : Optional[str]
546
+ The symbol
547
+
548
+ Returns
549
+ -------
550
+ InsuranceFundHistoryResponse
551
+ Single page of insurance fund history data
552
+ """
553
+
554
+ params = {
555
+ "limit": limit,
556
+ "epoch": epoch,
557
+ "txOrdinal": tx_ordinal,
558
+ "order": order,
559
+ "symbol": symbol,
560
+ }
561
+ params = {k: v for k, v in params.items() if v is not None}
562
+
563
+ response = await self._http.get(
564
+ self._build_url(System.GET_INSURANCE_FUND_HISTORY), params=params
565
+ )
566
+
567
+ return InsuranceFundHistoryResponse.model_validate(response)
568
+
569
+ async def get_insurance_fund_history(
570
+ self,
571
+ order: Optional[str] = None,
572
+ symbol: Optional[str] = None,
573
+ limit: Optional[int] = 100,
574
+ ) -> AsyncIterator[InsuranceFund]:
575
+ """
576
+ Get all insurance fund history data.
577
+
578
+ Automatically handles pagination using epoch and tx_ordinal.
579
+
580
+ Parameters
581
+ ----------
582
+ order : Optional[str]
583
+ The ordering of the results. Values: "asc", "desc"
584
+ symbol : Optional[str]
585
+ The symbol
586
+ limit : Optional[int]
587
+ The number of rows to return per page
588
+
589
+ Yields
590
+ ------
591
+ InsuranceFund
592
+ Insurance fund history entries
593
+ """
594
+
595
+ epoch = None
596
+ tx_ordinal = None
597
+
598
+ while True:
599
+ response = await self.get_insurance_fund_history_page(
600
+ limit=limit,
601
+ epoch=epoch,
602
+ tx_ordinal=tx_ordinal,
603
+ order=order,
604
+ symbol=symbol,
605
+ )
606
+
607
+ if not response.value:
608
+ break
609
+
610
+ for item in response.value:
611
+ yield item
612
+
613
+ if response.next_epoch is None:
614
+ break
615
+
616
+ epoch = response.next_epoch
617
+ tx_ordinal = response.next_tx_ordinal
618
+
619
+ async def get_specs_page(
620
+ self,
621
+ kind: Optional[int] = None,
622
+ limit: Optional[int] = None,
623
+ offset: Optional[int] = None,
624
+ ) -> SpecsResponse:
625
+ """
626
+ Get a single page of current operator configuration settings.
627
+
628
+ Parameters
629
+ ----------
630
+ kind : Optional[int]
631
+ The type of spec update. Values: 0 (Market), 1 (SpotGateway)
632
+ limit : Optional[int]
633
+ The number of rows to return
634
+ offset : Optional[int]
635
+ The offset of returned rows
636
+
637
+ Returns
638
+ -------
639
+ SpecsResponse
640
+ Single page of specs data
641
+ """
642
+
643
+ params = {
644
+ "kind": kind,
645
+ "limit": limit,
646
+ "offset": offset,
647
+ }
648
+ params = {k: v for k, v in params.items() if v is not None}
649
+
650
+ response = await self._http.get(
651
+ self._build_url(System.GET_SPECS), params=params
652
+ )
653
+
654
+ return SpecsResponse.model_validate(response)
655
+
656
+ async def get_specs(
657
+ self,
658
+ kind: Optional[int] = None,
659
+ limit: Optional[int] = 100,
660
+ ) -> AsyncIterator[Spec]:
661
+ """
662
+ Get all operator configuration settings.
663
+
664
+ Automatically handles pagination using offset.
665
+
666
+ Parameters
667
+ ----------
668
+ kind : Optional[int]
669
+ The type of spec update. Values: 0 (Market), 1 (SpotGateway)
670
+ limit : Optional[int]
671
+ The number of rows to return per page
672
+
673
+ Yields
674
+ ------
675
+ Spec
676
+ Spec entries
677
+ """
678
+
679
+ offset = 0
680
+
681
+ while True:
682
+ response = await self.get_specs_page(
683
+ kind=kind,
684
+ limit=limit,
685
+ offset=offset,
686
+ )
687
+
688
+ if not response.value:
689
+ break
690
+
691
+ for item in response.value:
692
+ yield item
693
+
694
+ if len(response.value) < limit:
695
+ break
696
+
697
+ offset += len(response.value)
698
+
699
+ async def get_exchange_status(self) -> ExchangeStatusResponse:
700
+ """
701
+ Get high-level exchange status information.
702
+
703
+ Returns
704
+ -------
705
+ ExchangeStatusResponse
706
+ Exchange status information including current epoch,
707
+ latest on-chain checkpoint, and active addresses
708
+ """
709
+
710
+ response = await self._http.get(self._build_url(System.GET_EXCHANGE_STATUS))
711
+
712
+ return ExchangeStatusResponse.model_validate(response)
713
+
714
+ async def get_ddx_supply(self) -> DDXSupplyResponse:
715
+ """
716
+ Get total DDX circulation information.
717
+
718
+ Returns
719
+ -------
720
+ DDXSupplyResponse
721
+ DDX supply information including circulating supply
722
+ """
723
+
724
+ response = await self._http.get(self._build_url(System.GET_DDX_SUPPLY))
725
+
726
+ return DDXSupplyResponse.model_validate(response)
727
+
728
+ async def get_tradable_products_page(
729
+ self,
730
+ kind: Optional[int] = None,
731
+ is_active: Optional[bool] = None,
732
+ limit: Optional[int] = None,
733
+ offset: Optional[int] = None,
734
+ ) -> TradableProductsResponse:
735
+ """
736
+ Get a single page of available trading products.
737
+
738
+ Parameters
739
+ ----------
740
+ kind : Optional[int]
741
+ The type of spec update. Values: 0 (Market), 1 (SpotGateway)
742
+ is_active : Optional[bool]
743
+ Checks for the active state of the tradable product
744
+ limit : Optional[int]
745
+ The number of rows to return
746
+ offset : Optional[int]
747
+ The offset of returned rows
748
+
749
+ Returns
750
+ -------
751
+ TradableProductsResponse
752
+ Single page of tradable products data
753
+ """
754
+
755
+ params = {
756
+ "kind": kind,
757
+ "isActive": is_active,
758
+ "limit": limit,
759
+ "offset": offset,
760
+ }
761
+ params = {k: v for k, v in params.items() if v is not None}
762
+
763
+ response = await self._http.get(
764
+ self._build_url(System.GET_TRADABLE_PRODUCTS), params=params
765
+ )
766
+
767
+ return TradableProductsResponse.model_validate(response)
768
+
769
+ async def get_tradable_products(
770
+ self,
771
+ kind: Optional[int] = None,
772
+ is_active: Optional[bool] = None,
773
+ limit: Optional[int] = 100,
774
+ ) -> AsyncIterator[TradableProduct]:
775
+ """
776
+ Get all available trading products.
777
+
778
+ Automatically handles pagination using offset.
779
+
780
+ Parameters
781
+ ----------
782
+ kind : Optional[int]
783
+ The type of spec update. Values: 0 (Market), 1 (SpotGateway)
784
+ is_active : Optional[bool]
785
+ Checks for the active state of the tradable product
786
+ limit : Optional[int]
787
+ The number of rows to return per page
788
+
789
+ Yields
790
+ ------
791
+ TradableProduct
792
+ Tradable product entries
793
+ """
794
+
795
+ offset = 0
796
+
797
+ while True:
798
+ response = await self.get_tradable_products_page(
799
+ kind=kind,
800
+ is_active=is_active,
801
+ limit=limit,
802
+ offset=offset,
803
+ )
804
+
805
+ if not response.value:
806
+ break
807
+
808
+ for item in response.value:
809
+ yield item
810
+
811
+ if len(response.value) < limit:
812
+ break
813
+
814
+ offset += len(response.value)
815
+
816
+ async def get_deployment_info(self, contract_deployment: str) -> DeploymentInfo:
817
+ """
818
+ Get deployment information including contract addresses.
819
+
820
+ Parameters
821
+ ----------
822
+ contract_deployment : str, default="testnet"
823
+ The deployment environment to get information for
824
+
825
+ Returns
826
+ -------
827
+ DeploymentInfo
828
+ Deployment information including contract addresses
829
+
830
+ Raises
831
+ ------
832
+ HTTPError
833
+ If the request fails
834
+ """
835
+
836
+ params = {"contractDeployment": contract_deployment}
837
+
838
+ # Make the request
839
+ response = await self._http.get(
840
+ self._build_url(System.GET_DEPLOYMENT_INFO), params=params
841
+ )
842
+
843
+ return DeploymentInfo.model_validate(response)