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
File without changes
@@ -0,0 +1,32 @@
1
+ from typing import Optional, Dict, Any
2
+
3
+
4
+ class HTTPClientError(Exception):
5
+ """Base exception for HTTP client errors."""
6
+
7
+ def __init__(
8
+ self,
9
+ request: str,
10
+ message: str,
11
+ status_code: int,
12
+ time: str,
13
+ response: Optional[Dict[str, Any]] = None,
14
+ ):
15
+ self.request = request
16
+ self.message = message
17
+ self.status_code = status_code
18
+ self.time = time
19
+ self.response = response
20
+ super().__init__(f"{message} (Status: {status_code}, Time: {time})")
21
+
22
+
23
+ class InvalidRequestError(HTTPClientError):
24
+ """Exception raised for API-specific errors."""
25
+
26
+ pass
27
+
28
+
29
+ class FailedRequestError(HTTPClientError):
30
+ """Exception raised for HTTP request failures."""
31
+
32
+ pass
File without changes
@@ -0,0 +1,305 @@
1
+ import asyncio
2
+ import json
3
+ from datetime import datetime
4
+ from typing import Optional, Dict, Any
5
+ import logging
6
+ from httpx import AsyncClient, RequestError
7
+
8
+ from ddx.rest_client.exceptions.exceptions import (
9
+ InvalidRequestError,
10
+ FailedRequestError,
11
+ )
12
+
13
+
14
+ class HTTPClient:
15
+ """
16
+ HTTP client for DerivaDEX API.
17
+
18
+ Handles request preparation and response processing.
19
+ """
20
+
21
+ def __init__(
22
+ self,
23
+ timeout: int = 10,
24
+ max_retries: int = 3,
25
+ retry_delay: int = 1,
26
+ logger: Optional[logging.Logger] = None,
27
+ ):
28
+ """
29
+ Initialize the HTTP client.
30
+
31
+ Parameters
32
+ ----------
33
+ timeout : int
34
+ Request timeout in seconds
35
+ max_retries : int
36
+ Maximum number of retry attempts
37
+ retry_delay : int
38
+ Delay between retries in seconds
39
+ logger : Optional[logging.Logger]
40
+ Logger instance
41
+ """
42
+
43
+ self.timeout = timeout
44
+ self.max_retries = max_retries
45
+ self.retry_delay = retry_delay
46
+
47
+ # Setup logging
48
+ self.logger = logger or logging.getLogger(__name__)
49
+
50
+ # Initialize client to None - will be created in __aenter__
51
+ self.client: Optional[AsyncClient] = None
52
+
53
+ # Define retry status codes
54
+ self.retry_codes = {408, 429, 500, 502, 503, 504}
55
+
56
+ async def __aenter__(self):
57
+ """
58
+ Context manager entry point. Initializes the HTTP client.
59
+
60
+ Returns
61
+ -------
62
+ BaseHTTPClient
63
+ The client instance
64
+ """
65
+
66
+ self.client = AsyncClient(
67
+ timeout=self.timeout,
68
+ follow_redirects=True,
69
+ headers={"Content-Type": "application/json"},
70
+ )
71
+ self.logger.debug("HTTP client initialized")
72
+
73
+ return self
74
+
75
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
76
+ """
77
+ Context manager exit point. Ensures proper cleanup of resources.
78
+
79
+ Parameters
80
+ ----------
81
+ exc_type : Type[Exception], optional
82
+ The exception type if an exception was raised
83
+ exc_val : Exception, optional
84
+ The exception value if an exception was raised
85
+ exc_tb : TracebackType, optional
86
+ The traceback if an exception was raised
87
+ """
88
+
89
+ if self.client:
90
+ await self.client.aclose()
91
+ self.client = None
92
+ self.logger.debug("HTTP client closed")
93
+
94
+ async def get(
95
+ self,
96
+ url: str,
97
+ params: Optional[Dict[str, Any]] = None,
98
+ headers: Optional[Dict[str, str]] = None,
99
+ ) -> Dict[str, Any]:
100
+ """
101
+ Send a GET request.
102
+
103
+ Parameters
104
+ ----------
105
+ url : str
106
+ The URL to send the request to
107
+ params : Optional[Dict[str, Any]]
108
+ Query parameters
109
+ headers : Optional[Dict[str, str]]
110
+ Additional headers
111
+
112
+ Returns
113
+ -------
114
+ Dict[str, Any]
115
+ The response data
116
+
117
+ Raises
118
+ ------
119
+ FailedRequestError
120
+ If the request fails after retries
121
+ InvalidRequestError
122
+ If the API returns an error response
123
+ """
124
+
125
+ return await self._request("GET", url, params=params, headers=headers)
126
+
127
+ async def post(
128
+ self,
129
+ url: str,
130
+ data: Any = None,
131
+ json_data: Optional[Dict[str, Any]] = None,
132
+ headers: Optional[Dict[str, str]] = None,
133
+ ) -> Dict[str, Any]:
134
+ """
135
+ Send a POST request.
136
+
137
+ Parameters
138
+ ----------
139
+ url : str
140
+ The URL to send the request to
141
+ data : Any
142
+ Raw request body
143
+ json_data : Optional[Dict[str, Any]]
144
+ JSON data to serialize
145
+ headers : Optional[Dict[str, str]]
146
+ Additional headers
147
+
148
+ Returns
149
+ -------
150
+ Dict[str, Any]
151
+ The response data
152
+
153
+ Raises
154
+ ------
155
+ FailedRequestError
156
+ If the request fails after retries
157
+ InvalidRequestError
158
+ If the API returns an error response
159
+ """
160
+
161
+ return await self._request(
162
+ "POST", url, data=data, json_data=json_data, headers=headers
163
+ )
164
+
165
+ async def _request(
166
+ self,
167
+ method: str,
168
+ url: str,
169
+ params: Optional[Dict[str, Any]] = None,
170
+ data: Any = None,
171
+ json_data: Optional[Dict[str, Any]] = None,
172
+ headers: Optional[Dict[str, str]] = None,
173
+ ) -> Dict[str, Any]:
174
+ """
175
+ Execute HTTP request with retries and error handling.
176
+
177
+ Parameters
178
+ ----------
179
+ method : str
180
+ HTTP method (GET, POST, etc.)
181
+ url : str
182
+ The URL to send the request to
183
+ params : Optional[Dict[str, Any]]
184
+ Query parameters
185
+ data : Any
186
+ Raw request body
187
+ json_data : Optional[Dict[str, Any]]
188
+ JSON data to serialize
189
+ headers : Optional[Dict[str, str]]
190
+ Additional headers
191
+
192
+ Returns
193
+ -------
194
+ Dict[str, Any]
195
+ The response data
196
+
197
+ Raises
198
+ ------
199
+ FailedRequestError
200
+ If the request fails after retries
201
+ InvalidRequestError
202
+ If the API returns an error response
203
+ RuntimeError
204
+ If the client is not initialized
205
+ """
206
+
207
+ if self.client is None:
208
+ raise RuntimeError(
209
+ "HTTP client not initialized. Use 'async with' context manager."
210
+ )
211
+
212
+ request_info = (
213
+ f"{method} {url}; params: {params}; json: {json_data}; data: {data}"
214
+ )
215
+
216
+ self.logger.debug(f"Request: {request_info}")
217
+
218
+ retries = 0
219
+ while retries <= self.max_retries:
220
+ try:
221
+ response = await self.client.request(
222
+ method=method,
223
+ url=url,
224
+ params=params,
225
+ content=data,
226
+ json=json_data,
227
+ headers=headers,
228
+ )
229
+
230
+ # Log response status
231
+ self.logger.debug(f"Response status: {response.status_code}")
232
+
233
+ # Check if the request was successful
234
+ if response.status_code == 200:
235
+ try:
236
+ response_data = response.json()
237
+
238
+ # Check for API-specific errors in the response
239
+ if isinstance(response_data, dict) and not response_data.get(
240
+ "success", True
241
+ ):
242
+ error_msg = response_data.get(
243
+ "errorMsg", "Unknown API error"
244
+ )
245
+ raise InvalidRequestError(
246
+ request=request_info,
247
+ message=error_msg,
248
+ status_code=response.status_code,
249
+ time=datetime.now().strftime("%H:%M:%S"),
250
+ response=response_data,
251
+ )
252
+
253
+ return response_data
254
+ except json.JSONDecodeError:
255
+ # Failed to parse JSON response
256
+ raise FailedRequestError(
257
+ request=request_info,
258
+ message="Failed to parse JSON response",
259
+ status_code=response.status_code,
260
+ time=datetime.now().strftime("%H:%M:%S"),
261
+ response={"text": response.text},
262
+ )
263
+
264
+ # Handle retry-able status codes
265
+ if (
266
+ response.status_code in self.retry_codes
267
+ and retries < self.max_retries
268
+ ):
269
+ wait_time = self.retry_delay * (2**retries)
270
+ self.logger.warning(
271
+ f"Request failed with status {response.status_code}. "
272
+ f"Retrying in {wait_time}s ({retries+1}/{self.max_retries})"
273
+ )
274
+ await asyncio.sleep(wait_time)
275
+ retries += 1
276
+ continue
277
+
278
+ # Non-retryable error or max retries reached
279
+ raise FailedRequestError(
280
+ request=request_info,
281
+ message=f"Request failed with status {response.status_code}",
282
+ status_code=response.status_code,
283
+ time=datetime.now().strftime("%H:%M:%S"),
284
+ response={"text": response.text},
285
+ )
286
+
287
+ except RequestError as e:
288
+ # Network-related errors
289
+ if retries < self.max_retries:
290
+ wait_time = self.retry_delay * (2**retries)
291
+ self.logger.warning(
292
+ f"Request error: {str(e)}. "
293
+ f"Retrying in {wait_time}s ({retries+1}/{self.max_retries})"
294
+ )
295
+ await asyncio.sleep(wait_time)
296
+ retries += 1
297
+ continue
298
+
299
+ raise FailedRequestError(
300
+ request=request_info,
301
+ message=f"Request error: {str(e)}",
302
+ status_code=0,
303
+ time=datetime.now().strftime("%H:%M:%S"),
304
+ response=None,
305
+ )
File without changes