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
ddx/common/utils.py ADDED
@@ -0,0 +1,176 @@
1
+ """
2
+ Utils module
3
+ """
4
+
5
+ from decimal import Decimal as PyDecimal
6
+ import simplejson as json
7
+
8
+ from ddx._rust.common.enums import OrderSide
9
+ from ddx._rust.decimal import Decimal
10
+
11
+
12
+ def round_to_unit(val: Decimal) -> Decimal:
13
+ """
14
+ Round a decimal value down to 6 units of precision.
15
+
16
+ Parameters
17
+ ----------
18
+ val : Decimal
19
+ Value to be rounded
20
+ """
21
+
22
+ return val.quantize(6)
23
+
24
+
25
+ def to_base_unit_amount(val: Decimal, decimals: int) -> int:
26
+ """
27
+ Convert a value to grains format (e.g. DDX grains would be
28
+ multiplying by 10 ** 18).
29
+
30
+ Parameters
31
+ ----------
32
+ val : Decimal
33
+ Value to be scaled up
34
+ decimals : int
35
+ Number of decimal places to scale up to
36
+ """
37
+
38
+ return int(round_to_unit(val) * 10**decimals)
39
+
40
+
41
+ def to_unit_amount(val: int, decimals: int) -> Decimal:
42
+ """
43
+ Convert a value from grains format (e.g. from DDX grains would be
44
+ dividing by 10 ** 18).
45
+
46
+ Parameters
47
+ ----------
48
+ val : Decimal
49
+ Value to be scaled down
50
+ decimals : int
51
+ Number of decimal places to scale down by
52
+ """
53
+
54
+ return Decimal(str(val)) / 10**decimals
55
+
56
+
57
+ def to_base_unit_amount_list(vals: list[Decimal], decimals: int) -> list[int]:
58
+ """
59
+ Convert values to grains format (e.g. DDX grains would be
60
+ multiplying by 10 ** 18).
61
+
62
+ Parameters
63
+ ----------
64
+ vals : list[Decimal]
65
+ Values to be scaled up
66
+ decimals : int
67
+ Number of decimal places to scale up to
68
+ """
69
+
70
+ return [to_base_unit_amount(val, decimals) for val in vals]
71
+
72
+
73
+ def to_unit_amount_list(vals: list[int], decimals: int):
74
+ """
75
+ Convert values from grains format (e.g. from DDX grains would be
76
+ dividing by 10 ** 18).
77
+
78
+ Parameters
79
+ ----------
80
+ vals : list[int]
81
+ Values to be scaled down
82
+ decimals : int
83
+ Number of decimal places to scale down by
84
+ """
85
+
86
+ return [to_unit_amount(val, decimals) for val in vals]
87
+
88
+
89
+ def to_adjusted_encoding_for_negative_val(val: int):
90
+ """
91
+ Adjust encoding for a potentially negative value
92
+
93
+ Parameters
94
+ ----------
95
+ vals : int
96
+ Values to be adjusted
97
+ """
98
+
99
+ return 16**32 + abs(val) if val < 0 else val
100
+
101
+
102
+ def to_adjusted_encoding_for_negative_val_list(vals: list[int]):
103
+ """
104
+ Adjust encoding for list of potentially negative values
105
+
106
+ Parameters
107
+ ----------
108
+ vals : list[int]
109
+ list of values to be adjusted
110
+ """
111
+
112
+ return [to_adjusted_encoding_for_negative_val(val) for val in vals]
113
+
114
+
115
+ def from_adjusted_encoding_for_negative_val(val: int):
116
+ """
117
+ Adjust encoding for a potentially negative value
118
+
119
+ Parameters
120
+ ----------
121
+ vals : int
122
+ Values to be adjusted
123
+ """
124
+
125
+ return val if val < 16**32 else -(val - 16**32)
126
+
127
+
128
+ def get_parsed_tx_log_entry(tx_log_entry: dict):
129
+ """
130
+ Parse an individual transaction log entry into a format
131
+ suitable for the Auditor. This format was selected so
132
+ that the Auditor can be reused as-is by the integration
133
+ tests with no changes needed.
134
+
135
+ Parameters
136
+ ----------
137
+ tx_log_entry : dict
138
+ Transaction log message
139
+ """
140
+ return {
141
+ "event": tx_log_entry["event"],
142
+ "requestIndex": int(tx_log_entry["requestIndex"]),
143
+ "epochId": int(tx_log_entry["epochId"]),
144
+ "txOrdinal": int(tx_log_entry["ordinal"]),
145
+ "batchId": int(tx_log_entry["batchId"]),
146
+ "timeValue": int(tx_log_entry["time"]["value"]),
147
+ "timestamp": int(tx_log_entry["time"]["timestamp"]),
148
+ "stateRootHash": tx_log_entry["stateRootHash"],
149
+ }
150
+
151
+
152
+ def calculate_max_collateral(
153
+ collateral_tranches: list[tuple[Decimal, Decimal]], ddx_balance: Decimal
154
+ ) -> Decimal:
155
+ limit = Decimal("0")
156
+ for ddx_threshold, max_collateral in collateral_tranches:
157
+ limit = max_collateral
158
+ if ddx_balance < ddx_threshold:
159
+ break
160
+ return limit
161
+
162
+
163
+ class ComplexOutputEncoder(json.JSONEncoder):
164
+ """
165
+ Custom JSON-encoder for serializing objects
166
+ """
167
+
168
+ def __init__(self, **kwargs):
169
+ super(ComplexOutputEncoder, self).__init__(**kwargs)
170
+
171
+ def default(self, o):
172
+ if hasattr(o, "repr_json"):
173
+ return o.repr_json()
174
+ elif type(o) == Decimal:
175
+ return PyDecimal(str(o))
176
+ return json.JSONEncoder.default(self, o)
ddx/config.py ADDED
@@ -0,0 +1,17 @@
1
+ import os
2
+
3
+ # from ddx._rust import common
4
+ from ddx._rust.common import reinit_operator_context
5
+
6
+ # FIXME: might need to change these environment variables to `DDX_CONTRACT_DEPLOYMENT` for better convention
7
+
8
+
9
+ def load_mainnet():
10
+ os.environ["CONTRACT_DEPLOYMENT"] = "derivadex"
11
+ # common.reinit_operator_context()
12
+ reinit_operator_context()
13
+
14
+
15
+ def load_testnet():
16
+ os.environ["CONTRACT_DEPLOYMENT"] = "testnet"
17
+ reinit_operator_context()
@@ -0,0 +1,254 @@
1
+ """
2
+ DerivaDEX Client
3
+ """
4
+
5
+ from typing import Optional
6
+ from web3 import Web3
7
+ from web3.middleware import geth_poa_middleware
8
+
9
+ from ddx.realtime_client import RealtimeClient
10
+ from ddx.rest_client.clients.market_client import MarketClient
11
+ from ddx.rest_client.clients.on_chain_client import OnChainClient
12
+ from ddx.rest_client.clients.signed_client import SignedClient
13
+ from ddx.rest_client.clients.system_client import SystemClient
14
+ from ddx.rest_client.clients.trade_client import TradeClient
15
+ from ddx.rest_client.http.http_client import HTTPClient
16
+
17
+
18
+ class DerivaDEXClient:
19
+ """
20
+ Main client for interacting with the DerivaDEX API.
21
+
22
+ This client provides access to all DerivaDEX API endpoints through
23
+ various client objects and supports both REST and WebSocket APIs.
24
+ It can be used as an async context manager to ensure proper client cleanup.
25
+
26
+ Attributes
27
+ ----------
28
+ market : MarketClient
29
+ Access to market operations
30
+ on_chain : OnChainClient
31
+ Access to on-chain operations
32
+ signed : SignedClient
33
+ Access to signed operations
34
+ system : SystemClient
35
+ Access to system operations
36
+ trade : TradeClient
37
+ Access to trade operations
38
+ web3_account : Account
39
+ The Web3 account used for signing transactions
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ base_url: str,
45
+ ws_url: str,
46
+ rpc_url: str,
47
+ contract_deployment: str,
48
+ private_key: str = None,
49
+ mnemonic: str = None,
50
+ timeout: int = 30,
51
+ ) -> None:
52
+ """
53
+ Initialize the client.
54
+
55
+ Parameters
56
+ ----------
57
+ base_url : str
58
+ Base URL for webserver
59
+ ws_url : str
60
+ WebSocket URL for real-time updates
61
+ rpc_url : str
62
+ RPC URL for webserver
63
+ contract_deployment : str
64
+ Type of contract deployment (e.g. "mainnet")
65
+ private_key : str, optional
66
+ Ethereum private key for user
67
+ mnemonic : str, optional
68
+ Ethereum mnemonic for user
69
+ timeout : int, default=30
70
+ Timeout in seconds for HTTP requests
71
+
72
+ Raises
73
+ ------
74
+ ValueError
75
+ If neither private_key nor mnemonic is provided
76
+ """
77
+
78
+ if not private_key and not mnemonic:
79
+ raise ValueError("Either private_key or mnemonic must be provided")
80
+
81
+ self._base_url = base_url
82
+ self._ws_url = ws_url
83
+
84
+ # Initialize HTTP client
85
+ self._http = HTTPClient(timeout)
86
+
87
+ self._contract_deployment = contract_deployment
88
+
89
+ # These will be initialized when needed
90
+ self._chain_id: Optional[int] = None
91
+ self._verifying_contract: Optional[str] = None
92
+
93
+ # Initialize web3 service
94
+ self.w3 = Web3(Web3.HTTPProvider(rpc_url, request_kwargs={"timeout": 60}))
95
+
96
+ if contract_deployment == "geth":
97
+ self.w3.middleware_onion.inject(geth_poa_middleware, layer=0)
98
+
99
+ # Initialize web3 account from private key or mnemonic
100
+ if private_key is not None:
101
+ self.web3_account = self.w3.eth.account.from_key(private_key)
102
+ else:
103
+ self.w3.eth.account.enable_unaudited_hdwallet_features()
104
+ self.web3_account = self.w3.eth.account.from_mnemonic(mnemonic)
105
+
106
+ # Set default account for send transactions
107
+ self.w3.eth.defaultAccount = self.web3_account.address
108
+
109
+ # Initialize clients (lazy loading)
110
+ self._market: Optional[MarketClient] = None
111
+ self._on_chain: Optional[OnChainClient] = None
112
+ self._signed: Optional[SignedClient] = None
113
+ self._system: Optional[SystemClient] = None
114
+ self._trade: Optional[TradeClient] = None
115
+
116
+ async def __aenter__(self) -> "DerivaDEXClient":
117
+ await self._http.__aenter__()
118
+
119
+ # Get deployment configuration
120
+ deployment_info = await self.system.get_deployment_info(
121
+ self._contract_deployment
122
+ )
123
+ self._chain_id = deployment_info.chain_id
124
+ self._verifying_contract = deployment_info.addresses.derivadex_address
125
+
126
+ # Initialize and start WebSocket client
127
+ # We do this here rather than lazy loading because we want
128
+ # to ensure the connection is established when using the context manager
129
+ self._ws = RealtimeClient(self._ws_url)
130
+ await self._ws.connect()
131
+
132
+ return self
133
+
134
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
135
+ # Stop WebSocket client if it was started
136
+ if self._ws is not None:
137
+ await self._ws.disconnect()
138
+ await self._http.__aexit__(exc_type, exc_val, exc_tb)
139
+
140
+ @property
141
+ def ws(self) -> RealtimeClient:
142
+ """
143
+ Access WebSocket functionality.
144
+
145
+ Returns
146
+ -------
147
+ RealtimeClient
148
+ The WebSocket Realtime API client instance
149
+
150
+ Raises
151
+ ------
152
+ RuntimeError
153
+ If accessed outside of context manager
154
+ """
155
+
156
+ if not hasattr(self, "_ws"):
157
+ raise RuntimeError("WebSocket client must be used within context manager")
158
+
159
+ return self._ws
160
+
161
+ @property
162
+ def market(self) -> MarketClient:
163
+ """
164
+ Access to market operations.
165
+
166
+ Returns
167
+ -------
168
+ MarketClient
169
+ The market client instance, initialized on first access
170
+ """
171
+
172
+ if self._market is None:
173
+ self._market = MarketClient(self._http, self._base_url)
174
+
175
+ return self._market
176
+
177
+ @property
178
+ def on_chain(self) -> OnChainClient:
179
+ """
180
+ Access on-chain operations.
181
+
182
+ Returns
183
+ -------
184
+ OnChainClient
185
+ The on-chain client instance, initialized on first access
186
+ """
187
+
188
+ if self._on_chain is None:
189
+ self._on_chain = OnChainClient(
190
+ self._http,
191
+ self._base_url,
192
+ self.web3_account,
193
+ self.w3,
194
+ self._verifying_contract,
195
+ )
196
+
197
+ return self._on_chain
198
+
199
+ @property
200
+ def signed(self) -> SignedClient:
201
+ """
202
+ Access to signed operations
203
+
204
+ Returns
205
+ -------
206
+ SignedClient
207
+ The signed client instance, initialized on first access
208
+ """
209
+
210
+ if self._signed is None:
211
+ self._signed = SignedClient(
212
+ self._http,
213
+ self._base_url,
214
+ self.web3_account,
215
+ self._chain_id,
216
+ self._verifying_contract,
217
+ )
218
+
219
+ return self._signed
220
+
221
+ @property
222
+ def system(self) -> SystemClient:
223
+ """
224
+ Access to system operations.
225
+
226
+ Returns
227
+ -------
228
+ SystemClient
229
+ The system client instance, initialized on first access
230
+ """
231
+
232
+ if self._system is None:
233
+ self._system = SystemClient(self._http, self._base_url)
234
+
235
+ return self._system
236
+
237
+ @property
238
+ def trade(self) -> TradeClient:
239
+ """
240
+ Access to trade operations
241
+
242
+ Returns
243
+ -------
244
+ TradeClient
245
+ The trade client instance, initialized on first access
246
+ """
247
+
248
+ if self._trade is None:
249
+ self._trade = TradeClient(
250
+ self._http,
251
+ self._base_url,
252
+ )
253
+
254
+ return self._trade
ddx/py.typed ADDED
File without changes
@@ -0,0 +1,2 @@
1
+ from .realtime_client import RealtimeClient
2
+ from .models import *
@@ -0,0 +1,2 @@
1
+ DEFAULT_RETRY_DELAY = 1
2
+ MAX_RETRY_DELAY = 60
File without changes