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,125 @@
1
+ """
2
+ PartialFill module
3
+ """
4
+
5
+ from attrs import define, field
6
+ from ddx.common.transactions.cancel import Cancel
7
+ from ddx.common.transactions.event import Event
8
+ from ddx.common.transactions.inner.outcome import Outcome
9
+ from ddx.common.transactions.inner.trade_fill import TradeFill
10
+ from ddx.common.transactions.post import Post
11
+ from ddx._rust.common import ProductSymbol
12
+ from ddx._rust.common.enums import OrderSide
13
+ from ddx._rust.common.state import DerivadexSMT
14
+ from ddx._rust.decimal import Decimal
15
+
16
+
17
+ @define
18
+ class PartialFill(Event):
19
+ """
20
+ Defines an PartialFill
21
+
22
+ A PartialFill is a scenario where the taker order has been partially filled
23
+ across 1 or more maker orders and thus has a remaining order that enters the
24
+ book along with any canceled maker orders.
25
+
26
+ Attributes:
27
+ post (Post): A Post object
28
+ trade_outcomes (list[TradeFill | Cancel]): A list of trade outcome objects
29
+ request_index (int): Sequenced request index of transaction
30
+ """
31
+
32
+ post: Post
33
+ trade_outcomes: list[TradeFill | Cancel] = field(eq=set)
34
+ request_index: int = field(default=-1, eq=False)
35
+
36
+ @classmethod
37
+ def decode_value_into_cls(cls, raw_tx_log_event: dict):
38
+ """
39
+ Decode a raw transaction log event (dict) into a PartialFill
40
+ instance.
41
+
42
+ Parameters
43
+ ----------
44
+ raw_tx_log_event : dict
45
+ Raw transaction log event being processed
46
+ """
47
+
48
+ event = raw_tx_log_event["event"]["c"]
49
+ trade_outcomes_tx_event = event["tradeOutcomes"]
50
+
51
+ return cls(
52
+ Post(
53
+ ProductSymbol(event["symbol"]),
54
+ event["orderHash"],
55
+ OrderSide(event["side"]),
56
+ Decimal(event["amount"]),
57
+ Decimal(event["price"]),
58
+ event["traderAddress"],
59
+ event["strategyIdHash"],
60
+ event["bookOrdinal"],
61
+ # NOTE 3503: This is logically identical to the time value in BookOrder, so not repeating it.
62
+ raw_tx_log_event["timeValue"],
63
+ raw_tx_log_event["requestIndex"],
64
+ ),
65
+ [
66
+ (
67
+ TradeFill(
68
+ ProductSymbol(trade_outcome["Fill"]["symbol"]),
69
+ trade_outcome["Fill"]["takerOrderHash"],
70
+ trade_outcome["Fill"]["makerOrderHash"],
71
+ Decimal(trade_outcome["Fill"]["makerOrderRemainingAmount"]),
72
+ Decimal(trade_outcome["Fill"]["amount"]),
73
+ Decimal(trade_outcome["Fill"]["price"]),
74
+ OrderSide(trade_outcome["Fill"]["takerSide"]),
75
+ Outcome(
76
+ trade_outcome["Fill"]["makerOutcome"]["trader"],
77
+ trade_outcome["Fill"]["makerOutcome"]["strategyIdHash"],
78
+ ),
79
+ Outcome(
80
+ trade_outcome["Fill"]["takerOutcome"]["trader"],
81
+ trade_outcome["Fill"]["takerOutcome"]["strategyIdHash"],
82
+ ),
83
+ raw_tx_log_event["timeValue"],
84
+ raw_tx_log_event["requestIndex"],
85
+ )
86
+ if "Fill" in trade_outcome
87
+ else Cancel(
88
+ ProductSymbol(trade_outcome["Cancel"]["symbol"]),
89
+ trade_outcome["Cancel"]["orderHash"],
90
+ Decimal(trade_outcome["Cancel"]["amount"]),
91
+ raw_tx_log_event["requestIndex"],
92
+ )
93
+ )
94
+ for trade_outcome in trade_outcomes_tx_event
95
+ ],
96
+ raw_tx_log_event["requestIndex"],
97
+ )
98
+
99
+ def process_tx(
100
+ self,
101
+ smt: DerivadexSMT,
102
+ **kwargs,
103
+ ):
104
+ """
105
+ Process a PartialFill transaction. A PartialFill consists of
106
+ Fill objects, which will adjust the maker BookOrder leaf in the
107
+ SMT, while also adjusting the Strategy, Position, and Trader
108
+ leaves corresponding to both the maker and the taker. It also
109
+ consists of a Post object, which will be a BookOrder consisting
110
+ of what's left of the partially matched order.
111
+
112
+ Parameters
113
+ ----------
114
+ smt: DerivadexSMT
115
+ DerivaDEX Sparse Merkle Tree
116
+ **kwargs
117
+ Additional args specific to PartialFill transactions
118
+ """
119
+
120
+ # Loop through each trade outcome event and process them individually
121
+ for trade_outcome in self.trade_outcomes:
122
+ trade_outcome.process_tx(smt, **kwargs)
123
+
124
+ # Process the remaining post event
125
+ self.post.process_tx(smt, **kwargs)
@@ -0,0 +1,122 @@
1
+ """
2
+ PnlRealization module
3
+ """
4
+
5
+ from attrs import define, field
6
+ from ddx.common.item_utils import update_avail_collateral
7
+ from ddx.common.logging import auditor_logger
8
+ from ddx.common.transactions.event import Event
9
+ from ddx._rust.common import TokenSymbol
10
+ from ddx._rust.common.state import DerivadexSMT, Position
11
+ from ddx._rust.common.state.keys import PositionKey, StrategyKey
12
+ from ddx._rust.decimal import Decimal
13
+
14
+ logger = auditor_logger(__name__)
15
+
16
+
17
+ @define
18
+ class PnlRealization(Event):
19
+ """
20
+ Defines a PnlRealization
21
+
22
+ A PnlRealization is when unrealized pnl is settled/realized for all
23
+ traders' strategies. This will result in a credit/debit for all
24
+ strategies.
25
+
26
+ Attributes:
27
+ settlement_epoch_id (int): Settlement epoch id
28
+ time_value (int): Time value
29
+ request_index (int): Sequenced request index of transaction
30
+ """
31
+
32
+ settlement_epoch_id: int
33
+ time_value: int
34
+ request_index: int = field(default=-1, eq=False)
35
+
36
+ @classmethod
37
+ def decode_value_into_cls(cls, raw_tx_log_event: dict):
38
+ """
39
+ Decode a raw transaction log event (dict) into a PnlRealization
40
+ instance.
41
+
42
+ Parameters
43
+ ----------
44
+ raw_tx_log_event : dict
45
+ Raw transaction log event being processed
46
+ """
47
+
48
+ event = raw_tx_log_event["event"]["c"]
49
+
50
+ return cls(
51
+ event["settlementEpochId"],
52
+ raw_tx_log_event["timeValue"],
53
+ raw_tx_log_event["requestIndex"],
54
+ )
55
+
56
+ def process_tx(
57
+ self,
58
+ smt: DerivadexSMT,
59
+ **kwargs,
60
+ ):
61
+ """
62
+ Process a PnlRealization transaction. A PnlRealization event
63
+ consists of information relating to when unrealized pnl is
64
+ settled/realized for all traders' strategies. This will result
65
+ in a credit/debit for all strategies. Furthermore, the
66
+ average entry price for any open positions will be set to the
67
+ current mark price.
68
+
69
+ Parameters
70
+ ----------
71
+ smt: DerivadexSMT
72
+ DerivaDEX Sparse Merkle Tree
73
+ **kwargs
74
+ Additional args specific to PnlRealization transactions
75
+ """
76
+
77
+ for (
78
+ position_key,
79
+ position,
80
+ ) in sorted(
81
+ smt.all_positions(),
82
+ key=lambda item: item[0].symbol,
83
+ ):
84
+ mark_price = kwargs["latest_price_leaves"][position_key.symbol][
85
+ 1
86
+ ].mark_price
87
+ unrealized_pnl = position.unrealized_pnl(
88
+ mark_price,
89
+ )
90
+
91
+ # Construct a StrategyKey and corresponding encoded
92
+ # key
93
+ strategy_key: StrategyKey = position_key.as_strategy_key()
94
+
95
+ # Get the Strategy leaf given the key from above
96
+ strategy = smt.strategy(strategy_key)
97
+
98
+ old_balance = strategy.avail_collateral[TokenSymbol.USDC]
99
+ # Credit/debit the trader's Strategy leaf by the
100
+ # unrealized PNL to settle
101
+ update_avail_collateral(
102
+ strategy,
103
+ TokenSymbol.USDC,
104
+ strategy.avail_collateral[TokenSymbol.USDC] + unrealized_pnl,
105
+ )
106
+ logger.info(
107
+ f"Calculated realized pnl:\n\told balance: {old_balance}\n\tnew balance: {strategy.avail_collateral[TokenSymbol.USDC]}\n\tpnl realized: {strategy.avail_collateral[TokenSymbol.USDC] - old_balance}"
108
+ )
109
+
110
+ smt.store_strategy(
111
+ strategy_key,
112
+ strategy,
113
+ )
114
+
115
+ # Set the Position's average entry price to the mark price
116
+ # since settlement has just taken place
117
+ position.avg_entry_price = mark_price
118
+
119
+ smt.store_position(
120
+ position_key,
121
+ position,
122
+ )
@@ -0,0 +1,72 @@
1
+ """
2
+ Post module
3
+ """
4
+
5
+ from attrs import define, field
6
+ from ddx.common.transactions.event import Event
7
+ from ddx._rust.common import ProductSymbol
8
+ from ddx._rust.common.enums import OrderSide
9
+ from ddx._rust.common.state import BookOrder, DerivadexSMT
10
+ from ddx._rust.common.state.keys import BookOrderKey, StrategyKey
11
+ from ddx._rust.decimal import Decimal
12
+
13
+
14
+ @define
15
+ class Post(Event):
16
+ """
17
+ Defines a Post
18
+
19
+ A Post is an order that enters the order book.
20
+
21
+ Attributes:
22
+ symbol (ProductSymbol): The symbol for the market this order is for.
23
+ order_hash (str): Hexstr representation of the EIP-712 hash of the order
24
+ side (str): Side of order ('Bid', 'Ask')
25
+ amount (Decimal): Amount/size of order
26
+ price (Decimal): Price the order has been placed at
27
+ trader_address (str): The order creator's Ethereum address
28
+ strategy_id_hash (str): The cross-margined strategy ID for which this order belongs
29
+ book_ordinal (int): The numerical sequence-identifying value for an order's insertion into the book
30
+ time_value (int): Time value
31
+ request_index (int): Sequenced request index of transaction
32
+ """
33
+
34
+ symbol: ProductSymbol
35
+ order_hash: str = field(eq=str.lower)
36
+ side: OrderSide
37
+ amount: Decimal
38
+ price: Decimal
39
+ trader_address: str = field(eq=str.lower)
40
+ strategy_id_hash: str = field(eq=str.lower)
41
+ book_ordinal: int
42
+ time_value: int
43
+ request_index: int = field(default=-1, eq=False)
44
+
45
+ def process_tx(
46
+ self,
47
+ smt: DerivadexSMT,
48
+ **kwargs,
49
+ ):
50
+ """
51
+ Process a Post transaction. We will need to create a new
52
+ BookOrder leaf with this information.
53
+
54
+ Parameters
55
+ ----------
56
+ smt: DerivadexSMT
57
+ DerivaDEX Sparse Merkle Tree
58
+ **kwargs
59
+ Additional args specific to PostOrder transactions
60
+ """
61
+
62
+ book_order = BookOrder(
63
+ self.side,
64
+ self.amount,
65
+ self.price,
66
+ self.trader_address,
67
+ self.strategy_id_hash,
68
+ self.book_ordinal,
69
+ self.time_value,
70
+ )
71
+
72
+ smt.store_book_order(BookOrderKey(self.symbol, self.order_hash), book_order)
@@ -0,0 +1,95 @@
1
+ """
2
+ PostOrder module
3
+ """
4
+
5
+ from attrs import define, field
6
+ from ddx.common.transactions.cancel import Cancel
7
+ from ddx.common.transactions.event import Event
8
+ from ddx.common.transactions.post import Post
9
+ from ddx._rust.common import ProductSymbol
10
+ from ddx._rust.common.enums import OrderSide
11
+ from ddx._rust.common.state import DerivadexSMT
12
+ from ddx._rust.decimal import Decimal
13
+
14
+
15
+ @define
16
+ class PostOrder(Event):
17
+ """
18
+ Defines a PostOrder
19
+
20
+ A PostOrder is an order that enters the order book along with any
21
+ canceled maker orders.
22
+
23
+ Attributes:
24
+ post (Post): The posted order.
25
+ canceled_orders (list[Cancel]): Canceled maker orders as a result of the posted order
26
+ request_index (int): Sequenced request index of transaction
27
+ """
28
+
29
+ post: Post
30
+ canceled_orders: list[Cancel] = field(eq=set)
31
+ request_index: int = field(default=-1, eq=False)
32
+
33
+ @classmethod
34
+ def decode_value_into_cls(cls, raw_tx_log_event: dict):
35
+ """
36
+ Decode a raw transaction log event (dict) into a PostOrder
37
+ instance.
38
+
39
+ Parameters
40
+ ----------
41
+ raw_tx_log_event : dict
42
+ Raw transaction log event being processed
43
+ """
44
+
45
+ post_tx_event = raw_tx_log_event["event"]["c"]
46
+ cancel_orders_tx_event = post_tx_event["tradeOutcomes"]
47
+
48
+ return cls(
49
+ Post(
50
+ ProductSymbol(post_tx_event["symbol"]),
51
+ post_tx_event["orderHash"],
52
+ OrderSide(post_tx_event["side"]),
53
+ Decimal(post_tx_event["amount"]),
54
+ Decimal(post_tx_event["price"]),
55
+ post_tx_event["traderAddress"],
56
+ post_tx_event["strategyIdHash"],
57
+ post_tx_event["bookOrdinal"],
58
+ raw_tx_log_event["timeValue"],
59
+ raw_tx_log_event["requestIndex"],
60
+ ),
61
+ [
62
+ Cancel(
63
+ ProductSymbol(canceled_order["Cancel"]["symbol"]),
64
+ canceled_order["Cancel"]["orderHash"],
65
+ Decimal(canceled_order["Cancel"]["amount"]),
66
+ raw_tx_log_event["requestIndex"],
67
+ )
68
+ for canceled_order in cancel_orders_tx_event
69
+ ],
70
+ raw_tx_log_event["requestIndex"],
71
+ )
72
+
73
+ def process_tx(
74
+ self,
75
+ smt: DerivadexSMT,
76
+ **kwargs,
77
+ ):
78
+ """
79
+ Process a PostOrder transaction. We will need to create a new
80
+ BookOrder leaf with this information.
81
+
82
+ Parameters
83
+ ----------
84
+ smt: DerivadexSMT
85
+ DerivaDEX Sparse Merkle Tree
86
+ **kwargs
87
+ Additional args specific to PostOrder transactions
88
+ """
89
+
90
+ # Loop through each cancel event and process them individually
91
+ for canceled_order in self.canceled_orders:
92
+ canceled_order.process_tx(smt, **kwargs)
93
+
94
+ # Process the post event
95
+ self.post.process_tx(smt, **kwargs)
@@ -0,0 +1,96 @@
1
+ """
2
+ PriceCheckpoint module
3
+ """
4
+
5
+ from attrs import define, field
6
+ from ddx.common.transactions.event import Event
7
+ from ddx._rust.common import ProductSymbol
8
+ from ddx._rust.common.accounting import MarkPriceMetadata
9
+ from ddx._rust.common.state import DerivadexSMT, Price
10
+ from ddx._rust.common.state.keys import PriceKey
11
+ from ddx._rust.decimal import Decimal
12
+
13
+
14
+ @define(hash=True)
15
+ class PriceCheckpoint(Event):
16
+ """
17
+ Defines a PriceCheckpoint
18
+
19
+ A PriceCheckpoint is when a market registers an update to the
20
+ composite index price a perpetual is tracking along with the mark
21
+ price metadata component.
22
+
23
+ Attributes:
24
+ symbol (ProductSymbol): The symbol for the market this price update is for.
25
+ mark_price_metadata (MarkPriceMetadata): Mark price metadata used for calculating mark price
26
+ index_price_hash (str): Index price hash
27
+ index_price (Decimal): Composite index price (a weighted average across several price feed sources)
28
+ ordinal (int): The numerical sequence-identifying value for a PriceCheckpoint
29
+ time_value (int): Time value
30
+ request_index (int): Sequenced request index of transaction
31
+ """
32
+
33
+ symbol: ProductSymbol
34
+ mark_price_metadata: MarkPriceMetadata = field(hash=False)
35
+ index_price_hash: str = field(eq=str.lower)
36
+ index_price: Decimal = field(hash=False)
37
+ ordinal: int = field(hash=False)
38
+ time_value: int
39
+ request_index: int = field(default=-1, eq=False, hash=False)
40
+
41
+ def is_void(self):
42
+ return self.index_price == Decimal("0")
43
+
44
+ @property
45
+ def mark_price(self) -> Decimal:
46
+ if isinstance(self.mark_price_metadata, MarkPriceMetadata.Ema):
47
+ mark_price = min(
48
+ self.index_price * Decimal("1.005"),
49
+ max(
50
+ self.index_price * Decimal("0.995"),
51
+ self.index_price + self.mark_price_metadata.ema,
52
+ ),
53
+ ).recorded_amount()
54
+ elif (
55
+ isinstance(self.mark_price_metadata, MarkPriceMetadata.Average) is not None
56
+ ):
57
+ mark_price = (self.index_price + self.mark_price_metadata.accum) / (
58
+ self.mark_price_metadata.count + 1
59
+ )
60
+ else:
61
+ raise ValueError("Invalid MarkPriceMetadata type")
62
+ return mark_price.recorded_amount()
63
+
64
+ def process_tx(
65
+ self,
66
+ smt: DerivadexSMT,
67
+ **kwargs,
68
+ ):
69
+ """
70
+ Process a PriceCheckpoint transaction. A PriceCheckpoint
71
+ consists of information relating to a new price checkpoint,
72
+ such as the symbol, composite index price, and mark price
73
+ metadata. This will update the Price leaf in the SMT.
74
+
75
+ Parameters
76
+ ----------
77
+ smt: DerivadexSMT
78
+ DerivaDEX Sparse Merkle Tree
79
+ **kwargs
80
+ Additional args specific to PriceCheckpoint transactions
81
+ """
82
+ price_key = PriceKey(self.symbol, self.index_price_hash)
83
+ price = Price(
84
+ self.index_price,
85
+ self.mark_price_metadata,
86
+ self.ordinal,
87
+ self.time_value,
88
+ )
89
+ smt.store_price(price_key, price)
90
+
91
+ # Update latest price leaves abstraction with the new price
92
+ # checkpoint data
93
+ kwargs["latest_price_leaves"][self.symbol] = (
94
+ price_key,
95
+ price,
96
+ )
@@ -0,0 +1,62 @@
1
+ """
2
+ Signer Registered module
3
+ """
4
+
5
+ from attrs import define, field
6
+ from ddx.common.transactions.event import Event
7
+ from ddx._rust.common.state import DerivadexSMT, Signer
8
+ from ddx._rust.common.state.keys import SignerKey
9
+
10
+
11
+ @define
12
+ class SignerRegistered(Event):
13
+ """
14
+ Defines a SignerRegistered
15
+
16
+ A SignerRegistered is when a new enclave signer registers with the smart contract
17
+
18
+ Attributes:
19
+ signer_address (str): The signer address component of the signer key pertaining to the SignerRegistered tx.
20
+ release_hash (str): The release hash component of the signer key pertaining to the SignerRegistered tx.
21
+ """
22
+
23
+ signer_address: str = field(eq=str.lower)
24
+ release_hash: str = field(eq=str.lower)
25
+
26
+ @classmethod
27
+ def decode_value_into_cls(cls, raw_tx_log_event: dict):
28
+ """
29
+ Decode a raw transaction log event (dict) into a SignerRegistered
30
+ instance.
31
+
32
+ Parameters
33
+ ----------
34
+ raw_tx_log_event : dict
35
+ Raw transaction log event being processed
36
+ """
37
+
38
+ event = raw_tx_log_event["event"]["c"]
39
+
40
+ return cls(
41
+ event["signerAddress"],
42
+ event["releaseHash"],
43
+ )
44
+
45
+ def process_tx(
46
+ self,
47
+ smt: DerivadexSMT,
48
+ **kwargs,
49
+ ):
50
+ """
51
+ Process a SignerRegistered, inserting the signer into the tree
52
+
53
+ Parameters
54
+ ----------
55
+ smt: DerivadexSMT
56
+ DerivaDEX Sparse Merkle Tree
57
+ **kwargs
58
+ Additional args specific to SignerRegistered transactions
59
+ """
60
+ signer = Signer(self.release_hash)
61
+
62
+ smt.store_signer(SignerKey(self.signer_address), signer)
@@ -0,0 +1,61 @@
1
+ """
2
+ SpecsUpdate module
3
+ """
4
+
5
+ from attrs import define, field
6
+ from ddx.common.transactions.event import Event
7
+ from ddx._rust.common import ProductSymbol
8
+ from ddx._rust.common.specs import SpecsKind
9
+ from ddx._rust.common.state import Specs
10
+ from ddx._rust.common.state.keys import SpecsKey
11
+ from ddx._rust.decimal import Decimal
12
+
13
+
14
+ # TODO: test usage
15
+ @define
16
+ class SpecsUpdate(Event):
17
+ """
18
+ Defines an SpecsUpdate
19
+
20
+ An SpecsUpdate is a transaction that updates the market specs
21
+
22
+ Attributes:
23
+ key (SpecsKey): The key of the specs being updated
24
+ expr (Specs): The expression of the specs being updated
25
+ block_number (int): Block number of transaction
26
+ tx_hash (str): Transaction hash of on-chain action
27
+ request_index (int): Sequenced request index of transaction
28
+ """
29
+
30
+ key: SpecsKey
31
+ expr: Specs
32
+ block_number: int
33
+ tx_hash: str = field(eq=str.lower)
34
+ request_index: int = field(default=-1, eq=False)
35
+
36
+ @classmethod
37
+ def decode_value_into_cls(cls, raw_tx_log_event: dict):
38
+ """
39
+ Decode a raw transaction log event (dict) into a
40
+ SpecsUpdate instance.
41
+
42
+ Parameters
43
+ ----------
44
+ raw_tx_log_event : dict
45
+ Raw transaction log event being processed
46
+ """
47
+
48
+ specs_update_tx_event = raw_tx_log_event["event"]["c"]
49
+
50
+ return cls(
51
+ SpecsKey(
52
+ SpecsKind(specs_update_tx_event["key"]["kind"]),
53
+ specs_update_tx_event["key"]["name"],
54
+ ),
55
+ Specs(specs_update_tx_event["expr"]),
56
+ specs_update_tx_event["blockNumber"],
57
+ specs_update_tx_event["txHash"],
58
+ raw_tx_log_event["requestIndex"],
59
+ )
60
+
61
+ # TODO: process_tx