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.
- ddx/.gitignore +1 -0
- ddx/__init__.py +58 -0
- ddx/_rust/__init__.pyi +2009 -0
- ddx/_rust/common/__init__.pyi +17 -0
- ddx/_rust/common/accounting.pyi +6 -0
- ddx/_rust/common/enums.pyi +3 -0
- ddx/_rust/common/requests/__init__.pyi +21 -0
- ddx/_rust/common/requests/intents.pyi +19 -0
- ddx/_rust/common/specs.pyi +17 -0
- ddx/_rust/common/state/__init__.pyi +41 -0
- ddx/_rust/common/state/keys.pyi +29 -0
- ddx/_rust/common/transactions.pyi +7 -0
- ddx/_rust/decimal.pyi +3 -0
- ddx/_rust/h256.pyi +3 -0
- ddx/_rust.abi3.so +0 -0
- ddx/app_config/ethereum/addresses.json +541 -0
- ddx/auditor/README.md +32 -0
- ddx/auditor/__init__.py +0 -0
- ddx/auditor/auditor_driver.py +1034 -0
- ddx/auditor/websocket_message.py +54 -0
- ddx/common/__init__.py +0 -0
- ddx/common/epoch_params.py +28 -0
- ddx/common/fill_context.py +144 -0
- ddx/common/item_utils.py +38 -0
- ddx/common/logging.py +184 -0
- ddx/common/market_specs.py +64 -0
- ddx/common/trade_mining_params.py +19 -0
- ddx/common/transaction_utils.py +85 -0
- ddx/common/transactions/__init__.py +0 -0
- ddx/common/transactions/advance_epoch.py +91 -0
- ddx/common/transactions/advance_settlement_epoch.py +63 -0
- ddx/common/transactions/all_price_checkpoints.py +84 -0
- ddx/common/transactions/cancel.py +76 -0
- ddx/common/transactions/cancel_all.py +88 -0
- ddx/common/transactions/complete_fill.py +103 -0
- ddx/common/transactions/disaster_recovery.py +97 -0
- ddx/common/transactions/event.py +48 -0
- ddx/common/transactions/fee_distribution.py +119 -0
- ddx/common/transactions/funding.py +294 -0
- ddx/common/transactions/futures_expiry.py +123 -0
- ddx/common/transactions/genesis.py +108 -0
- ddx/common/transactions/inner/__init__.py +0 -0
- ddx/common/transactions/inner/adl_outcome.py +25 -0
- ddx/common/transactions/inner/fill.py +227 -0
- ddx/common/transactions/inner/liquidated_position.py +41 -0
- ddx/common/transactions/inner/liquidation_entry.py +41 -0
- ddx/common/transactions/inner/liquidation_fill.py +118 -0
- ddx/common/transactions/inner/outcome.py +32 -0
- ddx/common/transactions/inner/trade_fill.py +125 -0
- ddx/common/transactions/insurance_fund_update.py +142 -0
- ddx/common/transactions/insurance_fund_withdraw.py +99 -0
- ddx/common/transactions/liquidation.py +357 -0
- ddx/common/transactions/partial_fill.py +125 -0
- ddx/common/transactions/pnl_realization.py +122 -0
- ddx/common/transactions/post.py +72 -0
- ddx/common/transactions/post_order.py +95 -0
- ddx/common/transactions/price_checkpoint.py +96 -0
- ddx/common/transactions/signer_registered.py +62 -0
- ddx/common/transactions/specs_update.py +61 -0
- ddx/common/transactions/strategy_update.py +156 -0
- ddx/common/transactions/tradable_product_update.py +98 -0
- ddx/common/transactions/trade_mining.py +147 -0
- ddx/common/transactions/trader_update.py +105 -0
- ddx/common/transactions/withdraw.py +91 -0
- ddx/common/transactions/withdraw_ddx.py +74 -0
- ddx/common/utils.py +176 -0
- ddx/config.py +17 -0
- ddx/derivadex_client.py +254 -0
- ddx/py.typed +0 -0
- ddx/realtime_client/__init__.py +2 -0
- ddx/realtime_client/config.py +2 -0
- ddx/realtime_client/logs/pytest.log +0 -0
- ddx/realtime_client/models/__init__.py +683 -0
- ddx/realtime_client/realtime_client.py +567 -0
- ddx/rest_client/__init__.py +0 -0
- ddx/rest_client/clients/__init__.py +0 -0
- ddx/rest_client/clients/base_client.py +60 -0
- ddx/rest_client/clients/market_client.py +1241 -0
- ddx/rest_client/clients/on_chain_client.py +432 -0
- ddx/rest_client/clients/signed_client.py +301 -0
- ddx/rest_client/clients/system_client.py +843 -0
- ddx/rest_client/clients/trade_client.py +335 -0
- ddx/rest_client/constants/__init__.py +0 -0
- ddx/rest_client/constants/endpoints.py +67 -0
- ddx/rest_client/contracts/__init__.py +0 -0
- ddx/rest_client/contracts/checkpoint/__init__.py +560 -0
- ddx/rest_client/contracts/ddx/__init__.py +1949 -0
- ddx/rest_client/contracts/dummy_token/__init__.py +1014 -0
- ddx/rest_client/contracts/i_collateral/__init__.py +1414 -0
- ddx/rest_client/contracts/i_stake/__init__.py +696 -0
- ddx/rest_client/exceptions/__init__.py +0 -0
- ddx/rest_client/exceptions/exceptions.py +32 -0
- ddx/rest_client/http/__init__.py +0 -0
- ddx/rest_client/http/http_client.py +305 -0
- ddx/rest_client/models/__init__.py +0 -0
- ddx/rest_client/models/market.py +683 -0
- ddx/rest_client/models/signed.py +60 -0
- ddx/rest_client/models/system.py +390 -0
- ddx/rest_client/models/trade.py +140 -0
- ddx/rest_client/utils/__init__.py +0 -0
- ddx/rest_client/utils/encryption_utils.py +26 -0
- ddx_python-1.0.5.dist-info/METADATA +63 -0
- ddx_python-1.0.5.dist-info/RECORD +104 -0
- 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
|