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,301 @@
1
+ import json
2
+ import time
3
+ from typing import Union, List, Optional
4
+ from eth_account.signers.local import LocalAccount
5
+ from eth_abi import encode
6
+ from decimal import Decimal as PyDecimal
7
+
8
+ from ddx._rust.decimal import Decimal
9
+ from ddx._rust.common.requests.intents import (
10
+ OrderIntent,
11
+ CancelOrderIntent,
12
+ CancelAllIntent,
13
+ ProfileUpdateIntent,
14
+ WithdrawIntent,
15
+ )
16
+ from ddx.rest_client.clients.base_client import BaseClient
17
+ from ddx.rest_client.constants.endpoints import Signed
18
+ from ddx.rest_client.models.signed import TradeReceipt, ErrorReceiptContent
19
+ from ddx.rest_client.utils.encryption_utils import encrypt_with_nonce
20
+ from ddx.rest_client.http.http_client import HTTPClient
21
+
22
+
23
+ class TradingJSONEncoder(json.JSONEncoder):
24
+ """JSON encoder for trading request data"""
25
+
26
+ def default(self, o):
27
+ if hasattr(o, "repr_json"):
28
+ return o.repr_json()
29
+ elif type(o) == Decimal:
30
+ return PyDecimal(str(o))
31
+ return super().default(o)
32
+
33
+
34
+ class SignedClient(BaseClient):
35
+ """
36
+ Trading operations for executing orders and other trading actions.
37
+
38
+ Parameters
39
+ ----------
40
+ http : HTTPClient
41
+ The HTTP client instance to use for requests
42
+ base_url : str
43
+ The base URL for trading endpoints
44
+ web3_account : Any
45
+ The web3 account for signing requests
46
+ chain_id : int
47
+ The blockchain chain ID
48
+ verifying_contract : str
49
+ The contract address for EIP-712 signing
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ http: HTTPClient,
55
+ base_url: str,
56
+ web3_account: LocalAccount,
57
+ chain_id: int,
58
+ verifying_contract: str,
59
+ ):
60
+ super().__init__(http, base_url)
61
+ self._web3_account = web3_account
62
+ self._chain_id = chain_id
63
+ self._verifying_contract = verifying_contract
64
+ self._encryption_key = None
65
+
66
+ async def _get_or_fetch_encryption_key(self) -> str:
67
+ """Get cached encryption key or fetch if not available"""
68
+
69
+ if self._encryption_key is None:
70
+ response = await self._http.get(self._build_url(Signed.ENCRYPTION_KEY))
71
+ self._encryption_key = response
72
+
73
+ return self._encryption_key
74
+
75
+ async def _encrypt_and_submit_request(
76
+ self,
77
+ intent: Union[
78
+ OrderIntent,
79
+ CancelOrderIntent,
80
+ CancelAllIntent,
81
+ ProfileUpdateIntent,
82
+ WithdrawIntent,
83
+ ],
84
+ local_account: Optional[LocalAccount] = None,
85
+ ) -> TradeReceipt:
86
+ """
87
+ Helper method to encrypt and submit trading requests.
88
+
89
+ Parameters
90
+ ----------
91
+ intent : Union[OrderIntent, CancelOrderIntent, CancelAllIntent, ProfileUpdateIntent, WithdrawIntent]
92
+ The trading intent to encrypt and submit
93
+ local_account : Optional[LocalAccount]
94
+ Local account to sign with, defaults to client's account
95
+
96
+ Returns
97
+ -------
98
+ TradeReceipt
99
+ The parsed receipt response
100
+ """
101
+
102
+ account = local_account or self._web3_account
103
+
104
+ intent.signature = account.signHash(
105
+ intent.hash_eip712((self._chain_id, self._verifying_contract))
106
+ ).signature.hex()
107
+
108
+ encryption_key = await self._get_or_fetch_encryption_key()
109
+ encrypted_contents = encrypt_with_nonce(
110
+ encryption_key, TradingJSONEncoder().encode(intent.json)
111
+ )
112
+
113
+ # Submit the encrypted request
114
+ response = await self._http.post(
115
+ self._build_url(Signed.SUBMIT_REQUEST), data=encrypted_contents
116
+ )
117
+ # Parse the response with Pydantic
118
+ try:
119
+ return TradeReceipt.model_validate(response)
120
+ except Exception as e:
121
+ self._logger.error(f"Failed to parse trade receipt: {e}")
122
+ # Create a fallback error receipt
123
+ return TradeReceipt(
124
+ t="Error",
125
+ c=ErrorReceiptContent(
126
+ message=f"Failed to parse response: {str(response)}"
127
+ ),
128
+ )
129
+
130
+ def get_nonce(self) -> str:
131
+ """
132
+ Get nonce to be used as the unique nonce in various commands.
133
+
134
+ Returns
135
+ -------
136
+ str
137
+ 32-byte hex-encoded nonce string, encoded using eth_abi
138
+ """
139
+
140
+ # Retrieve current UNIX time in nanoseconds to derive a unique, monotonically-increasing nonce
141
+ nonce = str(time.time_ns())
142
+
143
+ # abi.encode(['bytes32'], [nonce])
144
+ return f'0x{encode(["bytes32"], [nonce.encode("utf8")]).hex()}'
145
+
146
+ async def place_order(
147
+ self,
148
+ order: OrderIntent,
149
+ local_account: Optional[LocalAccount] = None,
150
+ ) -> TradeReceipt:
151
+ """
152
+ Place a single order on the exchange.
153
+
154
+ Parameters
155
+ ----------
156
+ order : OrderIntent
157
+ The order intent to submit, containing symbol, strategy, side,
158
+ order type, quantity, and price information
159
+ local_account : Optional[LocalAccount]
160
+ Local account to sign with, defaults to client's account
161
+
162
+ Returns
163
+ -------
164
+ TradeReceipt
165
+ The response containing order submission details including
166
+ nonce, request hash, and request index
167
+ """
168
+
169
+ return await self._encrypt_and_submit_request(
170
+ order, local_account=local_account
171
+ )
172
+
173
+ async def place_orders(
174
+ self,
175
+ orders: List[OrderIntent],
176
+ local_account: Optional[LocalAccount] = None,
177
+ ) -> List[TradeReceipt]:
178
+ """
179
+ Place multiple orders efficiently.
180
+
181
+ Parameters
182
+ ----------
183
+ orders : List[OrderIntent]
184
+ List of order intents to submit
185
+ local_account : Optional[LocalAccount]
186
+ Local account to sign with, defaults to client's account
187
+
188
+ Returns
189
+ -------
190
+ List[TradeReceipt]
191
+ List of responses for each order containing submission details
192
+ """
193
+
194
+ results = []
195
+ for order in orders:
196
+ result = await self._encrypt_and_submit_request(
197
+ order, local_account=local_account
198
+ )
199
+ results.append(result)
200
+
201
+ return results
202
+
203
+ async def cancel_order(
204
+ self,
205
+ cancel_intent: CancelOrderIntent,
206
+ local_account: Optional[LocalAccount] = None,
207
+ ) -> TradeReceipt:
208
+ """
209
+ Cancel a specific order.
210
+
211
+ Parameters
212
+ ----------
213
+ cancel_intent : CancelOrderIntent
214
+ The cancel intent containing order details to cancel
215
+ local_account : Optional[LocalAccount]
216
+ Local account to sign with, defaults to client's account
217
+
218
+ Returns
219
+ -------
220
+ TradeReceipt
221
+ Response containing cancellation details
222
+ """
223
+
224
+ return await self._encrypt_and_submit_request(
225
+ cancel_intent, local_account=local_account
226
+ )
227
+
228
+ async def cancel_all(
229
+ self,
230
+ cancel_all_intent: CancelAllIntent,
231
+ local_account: Optional[LocalAccount] = None,
232
+ ) -> TradeReceipt:
233
+ """
234
+ Cancel all orders for a strategy.
235
+
236
+ Parameters
237
+ ----------
238
+ cancel_all_intent : CancelAllIntent
239
+ The cancel all intent containing strategy details
240
+ local_account : Optional[LocalAccount]
241
+ Local account to sign with, defaults to client's account
242
+
243
+ Returns
244
+ -------
245
+ TradeReceipt
246
+ Response containing cancellation details for all orders
247
+ """
248
+
249
+ return await self._encrypt_and_submit_request(
250
+ cancel_all_intent, local_account=local_account
251
+ )
252
+
253
+ async def withdraw(
254
+ self,
255
+ withdraw_intent: WithdrawIntent,
256
+ local_account: Optional[LocalAccount] = None,
257
+ ) -> TradeReceipt:
258
+ """
259
+ Submit a withdrawal request.
260
+
261
+ Parameters
262
+ ----------
263
+ withdraw_intent : WithdrawIntent
264
+ The withdrawal intent containing amount and strategy details
265
+ local_account : Optional[LocalAccount]
266
+ Local account to sign with, defaults to client's account
267
+
268
+ Returns
269
+ -------
270
+ TradeReceipt
271
+ Response containing withdrawal submission details
272
+ """
273
+
274
+ return await self._encrypt_and_submit_request(
275
+ withdraw_intent, local_account=local_account
276
+ )
277
+
278
+ async def update_profile(
279
+ self,
280
+ profile_update_intent: ProfileUpdateIntent,
281
+ local_account: Optional[LocalAccount] = None,
282
+ ) -> TradeReceipt:
283
+ """
284
+ Submit a profile update request.
285
+
286
+ Parameters
287
+ ----------
288
+ profile_update_intent : ProfileUpdateIntent
289
+ The profile update intent containing ddx fee election details
290
+ local_account : Optional[LocalAccount]
291
+ Local account to sign with, defaults to client's account
292
+
293
+ Returns
294
+ -------
295
+ TradeReceipt
296
+ Response containing profile update submission details
297
+ """
298
+
299
+ return await self._encrypt_and_submit_request(
300
+ profile_update_intent, local_account=local_account
301
+ )