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,61 @@
1
+ from typing import Optional, Dict, Union, Any, Literal
2
+ from ddx.models.base import CamelModel, HexStr
3
+ from pydantic import Field, field_validator, ConfigDict
4
+ from ddx._rust.common.requests import SafetyFailure
5
+
6
+
7
+ class SequencedReceiptContent(CamelModel):
8
+ """Content of a successful sequenced receipt."""
9
+
10
+ nonce: HexStr
11
+ request_hash: HexStr
12
+ request_index: int = Field(..., ge=0)
13
+ sender: HexStr
14
+ enclave_signature: HexStr
15
+
16
+
17
+ class ErrorReceiptContent(CamelModel):
18
+ """Content of an error receipt."""
19
+ model_config = ConfigDict(arbitrary_types_allowed=True)
20
+
21
+ message: str
22
+ inner: SafetyFailure
23
+
24
+ @field_validator("inner", mode="before")
25
+ def _parse_safety_failure(cls, v):
26
+ if isinstance(v, SafetyFailure):
27
+ return v
28
+ return SafetyFailure[v] if isinstance(v, str) else SafetyFailure(v)
29
+
30
+
31
+ class TradeReceipt(CamelModel):
32
+ """Model for trade request receipts."""
33
+
34
+ t: Literal["Sequenced", "SafetyFailure"]
35
+ c: Union[SequencedReceiptContent, ErrorReceiptContent, Dict[str, Any]]
36
+
37
+ @property
38
+ def is_success(self) -> bool:
39
+ """Check if the receipt indicates success."""
40
+
41
+ return self.t == "Sequenced"
42
+
43
+ @property
44
+ def is_error(self) -> bool:
45
+ """Check if the receipt indicates an error."""
46
+
47
+ return self.t in ("Error", "SafetyFailure")
48
+
49
+ @property
50
+ def error_message(self) -> Optional[str]:
51
+ """Get the error message if this is an error receipt."""
52
+
53
+ if self.is_error and isinstance(self.c, ErrorReceiptContent):
54
+ return self.c.message
55
+ return None
56
+
57
+ @property
58
+ def error(self) -> Optional[SafetyFailure]:
59
+ if self.is_error and isinstance(self.c, ErrorReceiptContent):
60
+ return self.c.inner
61
+ return None
@@ -0,0 +1,311 @@
1
+ from datetime import datetime
2
+ from typing import List, Optional
3
+ from pydantic import Field, ConfigDict, field_validator
4
+ from ddx.models.base import CamelModel
5
+
6
+
7
+ class SettlementInfo(CamelModel):
8
+ """Settlement information model."""
9
+
10
+ type: str
11
+ duration_value: str
12
+ duration_unit: str
13
+
14
+
15
+ class SymbolInfo(CamelModel):
16
+ """Symbol information model."""
17
+
18
+ symbol: str
19
+ tick_size: str
20
+ max_order_notional: str
21
+ max_taker_price_deviation: str
22
+ min_order_size: str
23
+ kind: str # SingleNamePerpetual, IndexFundPerpetual, FixedExpiryFuture
24
+
25
+
26
+ class ExchangeInfo(CamelModel):
27
+ """Exchange information model."""
28
+
29
+ settlements_info: List[SettlementInfo]
30
+ assets: List[str]
31
+ symbols: List[SymbolInfo]
32
+
33
+
34
+ class ExchangeInfoResponse(CamelModel):
35
+ """Response model for exchange info endpoint."""
36
+
37
+ value: ExchangeInfo
38
+ success: bool
39
+ timestamp: int
40
+
41
+
42
+ class PingResponse(CamelModel):
43
+ """Response model for ping endpoint."""
44
+
45
+ model_config = CamelModel.model_config | ConfigDict(extra="allow")
46
+
47
+ # The ping endpoint returns an empty object on success
48
+ # We'll allow extra fields in case the response changes in the future
49
+
50
+
51
+ class Symbol(CamelModel):
52
+ """Tradable product symbol model."""
53
+
54
+ kind: int # 0: Perpetual Market, 2: Index Market, 4: Futures Market
55
+ symbol: str
56
+ name: str
57
+ is_active: bool
58
+ created_at: datetime
59
+
60
+
61
+ class SymbolsResponse(CamelModel):
62
+ """Response model for symbols endpoint."""
63
+
64
+ value: List[Symbol]
65
+ success: bool
66
+ timestamp: int
67
+
68
+
69
+ class ServerTimeResponse(CamelModel):
70
+ """Response model for server time endpoint."""
71
+
72
+ server_time: int
73
+
74
+
75
+ class Epoch(CamelModel):
76
+ """Epoch data model."""
77
+
78
+ epoch_id: int
79
+ start_time: datetime
80
+ end_time: Optional[datetime] = None
81
+
82
+
83
+ class EpochHistoryResponse(CamelModel):
84
+ """Response model for epoch history endpoint."""
85
+
86
+ value: List[Epoch]
87
+ success: bool
88
+ timestamp: int
89
+
90
+
91
+ class InsuranceFund(CamelModel):
92
+ """Insurance fund update data model."""
93
+
94
+ epoch_id: int
95
+ tx_ordinal: int
96
+ symbol: str
97
+ total_capitalization: Optional[str] = None
98
+ kind: int # 0: fill, 1: liquidation, 2: deposit, 3: withdrawal
99
+ created_at: datetime
100
+
101
+
102
+ class InsuranceFundHistoryResponse(CamelModel):
103
+ """Response model for insurance fund history endpoint with cursor pagination."""
104
+
105
+ value: List[InsuranceFund]
106
+ next_epoch: Optional[int] = Field(None, ge=0)
107
+ next_tx_ordinal: Optional[int] = Field(None, ge=0)
108
+ next_ordinal: Optional[int] = Field(None, ge=0)
109
+ success: bool
110
+ timestamp: int
111
+
112
+
113
+ class SpecValue(CamelModel):
114
+ """Spec value model."""
115
+
116
+ model_config = CamelModel.model_config | ConfigDict(extra="allow")
117
+
118
+ # This is a flexible model that can contain various fields
119
+ # based on the kind of spec
120
+
121
+
122
+ class Spec(CamelModel):
123
+ """Spec data model."""
124
+
125
+ kind: int = Field(..., description="0: Market, 1: SpotGateway")
126
+ name: str
127
+ expr: str
128
+ value: Optional[SpecValue] = None
129
+
130
+
131
+ class SpecsResponse(CamelModel):
132
+ """Response model for specs endpoint."""
133
+
134
+ value: List[Spec]
135
+ success: bool
136
+ timestamp: int
137
+
138
+
139
+ class OnChainCheckpoint(CamelModel):
140
+ """On-chain checkpoint information model."""
141
+
142
+ latest_on_chain_checkpoint: int
143
+ latest_checkpoint_transaction_link: Optional[str] = None
144
+
145
+
146
+ class ExchangeStatus(CamelModel):
147
+ """Exchange status information model."""
148
+
149
+ current_epoch: str
150
+ latest_on_chain_checkpoint: Optional[OnChainCheckpoint] = None
151
+ active_addresses: str
152
+
153
+
154
+ class ExchangeStatusResponse(CamelModel):
155
+ """Response model for exchange status endpoint."""
156
+
157
+ value: ExchangeStatus
158
+ success: bool
159
+ timestamp: int
160
+
161
+
162
+ class DDXSupply(CamelModel):
163
+ """DDX supply information model."""
164
+
165
+ circulating_supply: str
166
+
167
+
168
+ class DDXSupplyResponse(CamelModel):
169
+ """Response model for DDX supply endpoint."""
170
+
171
+ value: DDXSupply
172
+ success: bool
173
+ timestamp: int
174
+
175
+
176
+ class TradableProduct(CamelModel):
177
+ """Tradable product data model."""
178
+
179
+ kind: int # 0: Perpetual Market, 2: Index Market, 4: Futures Market
180
+ symbol: str
181
+ name: str
182
+ is_active: bool
183
+ created_at: datetime
184
+
185
+
186
+ class TradableProductsResponse(CamelModel):
187
+ """Response model for tradable products endpoint."""
188
+
189
+ value: List[TradableProduct]
190
+ success: bool
191
+ timestamp: int
192
+
193
+
194
+ class CollateralAggregation(CamelModel):
195
+ """Collateral aggregation data model."""
196
+
197
+ model_config = CamelModel.model_config | ConfigDict(extra="allow")
198
+
199
+ timestamp: int
200
+ # Dynamic fields will be handled with extra='allow'
201
+ # Fields like collateral_deposits, collateral_withdrawals, etc.
202
+
203
+ # Add method to access dynamic fields
204
+ def get_value(self, field_name: str) -> Optional[str]:
205
+ """Get value for a specific collateral field."""
206
+ return getattr(self, f"collateral_{field_name}", None)
207
+
208
+
209
+ class CollateralAggregationResponse(CamelModel):
210
+ """Response model for collateral aggregation endpoint."""
211
+
212
+ value: List[CollateralAggregation]
213
+ next_starting_value: Optional[str] = None
214
+ success: bool
215
+ timestamp: int
216
+
217
+
218
+ class DDXAggregation(CamelModel):
219
+ """DDX aggregation data model."""
220
+
221
+ model_config = CamelModel.model_config | ConfigDict(extra="allow")
222
+
223
+ timestamp: int
224
+ # Dynamic fields will be available through extra="allow"
225
+ # Fields like ddx_deposits, ddx_withdrawals, etc.
226
+
227
+ # Add method to get DDX value by type
228
+ def get_ddx_value(self, value_type: str) -> Optional[str]:
229
+ """Get DDX value for a specific type."""
230
+ return getattr(self, f"ddx_{value_type}", None)
231
+
232
+
233
+ class DDXAggregationResponse(CamelModel):
234
+ """Response model for DDX aggregation endpoint."""
235
+
236
+ value: List[DDXAggregation]
237
+ next_starting_value: Optional[str] = None
238
+ success: bool
239
+ timestamp: int
240
+
241
+
242
+ class InsuranceFundAggregation(CamelModel):
243
+ """Insurance fund aggregation data model."""
244
+
245
+ model_config = CamelModel.model_config | ConfigDict(extra="allow")
246
+
247
+ timestamp: int
248
+ # Dynamic fields will be handled with extra='allow'
249
+ # Fields like insurance-fund_fees, insurance-fund_overall, etc.
250
+
251
+ def get_value(self, field: str) -> Optional[str]:
252
+ """Get a specific field value."""
253
+ return getattr(self, field, None)
254
+
255
+
256
+ class InsuranceFundAggregationResponse(CamelModel):
257
+ """Response model for insurance fund aggregation endpoint."""
258
+
259
+ value: List[InsuranceFundAggregation]
260
+ next_starting_value: Optional[str] = None
261
+ success: bool
262
+ timestamp: int
263
+
264
+
265
+ class DeploymentAddresses(CamelModel):
266
+ """Model for contract deployment addresses."""
267
+
268
+ ddx_address: str
269
+ ddx_wallet_cloneable_address: str
270
+ derivadex_address: str = Field(alias="derivaDEXAddress") # Custom alias
271
+ di_fund_token_factory_address: str
272
+ governance_address: str
273
+ governance_dip12_address: str
274
+ gas_consumer_address: str
275
+ insurance_fund_address: str
276
+ pause_address: str
277
+ trader_address: str
278
+ usdt_address: str
279
+ ausdt_address: str
280
+ cusdt_address: str
281
+ usdc_address: str
282
+ cusdc_address: str
283
+ ausdc_address: str
284
+ husd_address: str
285
+ gusd_address: str
286
+ gnosis_safe_address: str
287
+ gnosis_safe_proxy_factory_address: str
288
+ gnosis_safe_proxy_address: str
289
+ create_call_address: str
290
+ banner_address: str
291
+ funded_insurance_fund_address: str
292
+ funded_insurance_fund_dip12_address: str
293
+ checkpoint_address: str
294
+ registration_address: str
295
+ initialize_app_address: str
296
+ specs_address: str
297
+ collateral_address: str
298
+ collateral_dip12_address: str
299
+ custodian_address: str
300
+ reject_address: str
301
+ stake_address: str
302
+ stake_dip12_address: str
303
+ pilot_reset_address: str
304
+
305
+
306
+ class DeploymentInfo(CamelModel):
307
+ """Model for deployment information."""
308
+
309
+ addresses: DeploymentAddresses
310
+ chain_id: int
311
+ eth_rpc_url: str
@@ -0,0 +1,185 @@
1
+ from datetime import datetime
2
+ from typing import List, Literal, Optional
3
+ from pydantic import Field, field_validator
4
+ from ddx.models.base import (
5
+ CamelModel,
6
+ HexStr,
7
+ validate_decimal_str,
8
+ PositionSide,
9
+ )
10
+
11
+ from ddx._rust.decimal import Decimal
12
+ from ddx._rust.common.state import (
13
+ Strategy as SMTStrategy,
14
+ Balance,
15
+ Trader as SMTTrader,
16
+ Position as SMTPosition,
17
+ )
18
+ from ddx._rust.common import TokenSymbol
19
+
20
+
21
+ # Strategy Fees History Models
22
+ class Fee(CamelModel):
23
+ """Strategy fee data model."""
24
+
25
+ epoch_id: int = Field(..., ge=0)
26
+ tx_ordinal: int = Field(..., ge=0)
27
+ ordinal: int = Field(..., ge=0)
28
+ amount: str
29
+ fee_symbol: str
30
+ symbol: str
31
+ created_at: datetime
32
+
33
+ @field_validator("amount")
34
+ @classmethod
35
+ def validate_nonnegative_decimals(cls, v, info):
36
+ return validate_decimal_str(v, f"StrategyFee.{info.field_name}", nonnegative=True)
37
+
38
+
39
+ class FeesHistoryResponse(CamelModel):
40
+ """Response model for strategy fees history endpoint."""
41
+
42
+ value: List[Fee]
43
+ next_epoch: Optional[int] = Field(None, ge=0)
44
+ next_tx_ordinal: Optional[int] = Field(None, ge=0)
45
+ next_ordinal: Optional[int] = Field(None, ge=0)
46
+ success: bool
47
+ timestamp: int
48
+
49
+
50
+ # Strategy Positions Models
51
+ class Position(CamelModel):
52
+ """Position data model."""
53
+
54
+ trader: HexStr
55
+ symbol: str
56
+ strategy_id_hash: HexStr
57
+ strategy_id: str
58
+ side: PositionSide
59
+ balance: str
60
+ avg_entry_price: str
61
+ last_modified_in_epoch: Optional[int] = Field(None, ge=0)
62
+
63
+ @field_validator("balance", "avg_entry_price")
64
+ @classmethod
65
+ def validate_nonnegative_decimals(cls, v, info):
66
+ return validate_decimal_str(v, f"Position.{info.field_name}", nonnegative=True)
67
+
68
+ def raw_position(self) -> SMTPosition:
69
+ return SMTPosition(
70
+ self.side.raw_position_side(),
71
+ Decimal(self.balance),
72
+ Decimal(self.avg_entry_price),
73
+ )
74
+
75
+
76
+ class PositionsResponse(CamelModel):
77
+ """Response model for strategy positions endpoint."""
78
+
79
+ value: List[Position]
80
+ success: bool
81
+ timestamp: int
82
+
83
+
84
+ # Strategy Models
85
+ class Strategy(CamelModel):
86
+ """Srategy data model."""
87
+
88
+ trader: HexStr
89
+ strategy_id_hash: HexStr
90
+ strategy_id: str
91
+ max_leverage: int = Field(..., ge=1)
92
+ avail_collateral: str
93
+ locked_collateral: str
94
+ frozen: bool
95
+
96
+ @field_validator("avail_collateral", "locked_collateral")
97
+ @classmethod
98
+ def validate_nonnegative_decimals(cls, v, info):
99
+ return validate_decimal_str(v, f"Strategy.{info.field_name}", nonnegative=True)
100
+
101
+ def raw_strategy(self) -> SMTStrategy:
102
+ return SMTStrategy(
103
+ Balance(
104
+ Decimal(self.avail_collateral),
105
+ TokenSymbol.USDC,
106
+ ),
107
+ Balance(
108
+ Decimal(self.locked_collateral),
109
+ TokenSymbol.USDC,
110
+ ),
111
+ self.max_leverage,
112
+ self.frozen,
113
+ )
114
+
115
+
116
+ class StrategyResponse(CamelModel):
117
+ """Response model for strategy endpoint."""
118
+
119
+ value: Optional[Strategy] = None
120
+ success: bool
121
+ timestamp: int
122
+
123
+
124
+ # Strategies Models
125
+ class StrategiesResponse(CamelModel):
126
+ """Response model for strategies endpoint."""
127
+
128
+ value: List[Strategy]
129
+ success: bool
130
+ timestamp: int
131
+
132
+
133
+ # Strategy Metrics Models
134
+ class StrategyMetrics(CamelModel):
135
+ """Strategy metrics data model."""
136
+
137
+ margin_fraction: str
138
+ mmr: str
139
+ leverage: str
140
+ strategy_margin: str
141
+ strategy_value: str
142
+
143
+ @field_validator("margin_fraction", "mmr", "leverage", "strategy_margin", "strategy_value")
144
+ @classmethod
145
+ def validate_nonnegative_decimals(cls, v, info):
146
+ return validate_decimal_str(v, f"StrategyMetrics.{info.field_name}", nonnegative=True)
147
+
148
+
149
+ class StrategyMetricsResponse(CamelModel):
150
+ """Response model for strategy metrics endpoint."""
151
+
152
+ value: StrategyMetrics
153
+ success: bool
154
+ timestamp: int
155
+
156
+
157
+ # Trader Models
158
+ class Trader(CamelModel):
159
+ """Trader data model."""
160
+
161
+ trader: str
162
+ avail_ddx: str
163
+ locked_ddx: str
164
+ pay_fees_in_ddx: bool
165
+ referral_address: Optional[HexStr] = None
166
+
167
+ @field_validator("avail_ddx", "locked_ddx")
168
+ @classmethod
169
+ def validate_nonnegative_decimals(cls, v, info):
170
+ return validate_decimal_str(v, f"TraderProfile.{info.field_name}", nonnegative=True)
171
+
172
+ def raw_trader(self) -> SMTTrader:
173
+ return SMTTrader(
174
+ Decimal(self.avail_ddx),
175
+ Decimal(self.locked_ddx),
176
+ self.pay_fees_in_ddx,
177
+ )
178
+
179
+
180
+ class TraderResponse(CamelModel):
181
+ """Response model for trader profile endpoint."""
182
+
183
+ value: Optional[Trader] = None
184
+ success: bool
185
+ timestamp: int
File without changes
@@ -0,0 +1,26 @@
1
+ """
2
+ DerivaDEX signature utils
3
+ """
4
+ from coincurve import PublicKey, PrivateKey
5
+ from Crypto.Cipher import AES
6
+ from Crypto.Random import get_random_bytes
7
+ from Crypto.Hash import keccak
8
+
9
+
10
+ def encrypt_with_nonce(encryption_key: str, msg: str) -> bytes:
11
+ network_public_key = PublicKey(bytes.fromhex(encryption_key[2:]))
12
+ my_secret_key = PrivateKey(get_random_bytes(32))
13
+ my_public_key = my_secret_key.public_key
14
+ shared_pub = network_public_key.multiply(my_secret_key.secret)
15
+ keccak_256 = keccak.new(digest_bits=256)
16
+ keccak_256.update(shared_pub.format())
17
+ derived_key = keccak_256.digest()[:16]
18
+ nonce = get_random_bytes(12)
19
+
20
+ cipher = AES.new(derived_key, AES.MODE_GCM, nonce=nonce)
21
+ encoded_message = msg.encode("utf8")
22
+ ciphertext, tag = cipher.encrypt_and_digest(
23
+ len(encoded_message).to_bytes(4, byteorder="big") + encoded_message
24
+ )
25
+
26
+ return ciphertext + tag + nonce + my_public_key.format()
ddx/utils/__init__.py ADDED
File without changes
@@ -0,0 +1,63 @@
1
+ Metadata-Version: 2.4
2
+ Name: ddx-python
3
+ Version: 1.0.4
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: Topic :: Office/Business :: Financial :: Investment
7
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
8
+ Classifier: Programming Language :: Rust
9
+ Classifier: Programming Language :: Python :: Implementation :: CPython
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Requires-Dist: maturin>=1.5.0,<1.6.0
16
+ Requires-Dist: pydantic>=2.0
17
+ Requires-Dist: websockets>=12.0,<13
18
+ Requires-Dist: 0x-contract-wrappers>=2.0.0,<3
19
+ Requires-Dist: aiohttp>=3.10.3,<4
20
+ Requires-Dist: asyncpg>=0.30.0,<1
21
+ Requires-Dist: attrs>=24.2.0,<25
22
+ Requires-Dist: cattrs>=23.2.3,<24
23
+ Requires-Dist: coloredlogs>=15.0.1,<16
24
+ Requires-Dist: configargparse>=1.7,<2
25
+ Requires-Dist: numpy>=2.2.6,<3
26
+ Requires-Dist: pandas>=2.2.2,<3
27
+ Requires-Dist: path>=17.0.0,<18
28
+ Requires-Dist: pathlib>=1.0.1,<2
29
+ Requires-Dist: plotly>=5.23.0,<6
30
+ Requires-Dist: psutil>=6.0.0,<7
31
+ Requires-Dist: requests>=2.32.3,<3
32
+ Requires-Dist: simplejson>=3.19.2,<4
33
+ Requires-Dist: sphinx>=8.0.2,<9
34
+ Requires-Dist: verboselogs>=1.7,<2
35
+ Requires-Dist: btrees>=6.0,<7
36
+ Requires-Dist: ccxt>=4.3.79,<5
37
+ Requires-Dist: coincurve>=20.0.0,<21
38
+ Requires-Dist: dash-bootstrap-components>=1.6.0,<2
39
+ Requires-Dist: python-dotenv>=1.0.1,<2
40
+ Requires-Dist: sexpdata>=1.0.2,<2
41
+ Requires-Dist: web3>=6.20.1,<7
42
+ Requires-Dist: werkzeug>=3.0.3,<4
43
+ Requires-Dist: gevent>=24.2.1,<25
44
+ Requires-Dist: sortedcontainers>=2.4.0,<3
45
+ Requires-Dist: aioresponses>=0.7.6,<0.8
46
+ Requires-Dist: colorama>=0.4.6,<0.5
47
+ Requires-Dist: loguru
48
+ Requires-Dist: black>=24.4.2,<25 ; extra == 'dev'
49
+ Requires-Dist: basedpyright ; extra == 'dev'
50
+ Requires-Dist: pipdeptree ; extra == 'dev'
51
+ Requires-Dist: jupyter-book>=0.6.5,<0.7 ; extra == 'notebook'
52
+ Requires-Dist: jupyter-dash>=0.4.2,<0.5 ; extra == 'notebook'
53
+ Requires-Dist: jupyterlab-lsp>=5.1.0,<6 ; extra == 'notebook'
54
+ Requires-Dist: jupyter>=1.0.0,<2 ; extra == 'notebook'
55
+ Requires-Dist: jupyterlab ; extra == 'notebook'
56
+ Requires-Dist: matplotlib>=3.9.1,<4 ; extra == 'notebook'
57
+ Requires-Dist: pytest>=8.3.5,<9 ; extra == 'test'
58
+ Requires-Dist: pytest-asyncio>=0.26.0,<0.27 ; extra == 'test'
59
+ Requires-Dist: pytest-pretty>=1.2.0,<2 ; extra == 'test'
60
+ Provides-Extra: dev
61
+ Provides-Extra: notebook
62
+ Provides-Extra: test
63
+ Requires-Python: >=3.10