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.
- ddx/.gitignore +1 -0
- ddx/__init__.py +58 -0
- ddx/_rust/__init__.pyi +2685 -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 +23 -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 +526 -0
- ddx/auditor/README.md +32 -0
- ddx/auditor/__init__.py +0 -0
- ddx/auditor/auditor_driver.py +1043 -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 +141 -0
- ddx/common/logging.py +184 -0
- ddx/common/market_aware_account.py +259 -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 +96 -0
- ddx/common/transactions/event.py +48 -0
- ddx/common/transactions/fee_distribution.py +119 -0
- ddx/common/transactions/funding.py +292 -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 +232 -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 +292 -0
- ddx/common/transactions/insurance_fund_update.py +138 -0
- ddx/common/transactions/insurance_fund_withdraw.py +100 -0
- ddx/common/transactions/liquidation.py +353 -0
- ddx/common/transactions/partial_fill.py +125 -0
- ddx/common/transactions/pnl_realization.py +120 -0
- ddx/common/transactions/post.py +72 -0
- ddx/common/transactions/post_order.py +95 -0
- ddx/common/transactions/price_checkpoint.py +97 -0
- ddx/common/transactions/signer_registered.py +62 -0
- ddx/common/transactions/specs_update.py +61 -0
- ddx/common/transactions/strategy_update.py +158 -0
- ddx/common/transactions/tradable_product_update.py +98 -0
- ddx/common/transactions/trade_mining.py +147 -0
- ddx/common/transactions/trader_update.py +131 -0
- ddx/common/transactions/withdraw.py +90 -0
- ddx/common/transactions/withdraw_ddx.py +74 -0
- ddx/common/utils.py +176 -0
- ddx/config.py +17 -0
- ddx/derivadex_client.py +270 -0
- ddx/models/__init__.py +0 -0
- ddx/models/base.py +132 -0
- ddx/py.typed +0 -0
- ddx/realtime_client/__init__.py +2 -0
- ddx/realtime_client/config.py +2 -0
- ddx/realtime_client/models/__init__.py +611 -0
- ddx/realtime_client/realtime_client.py +646 -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 +1243 -0
- ddx/rest_client/clients/on_chain_client.py +439 -0
- ddx/rest_client/clients/signed_client.py +292 -0
- ddx/rest_client/clients/system_client.py +843 -0
- ddx/rest_client/clients/trade_client.py +357 -0
- ddx/rest_client/constants/__init__.py +0 -0
- ddx/rest_client/constants/endpoints.py +66 -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 +336 -0
- ddx/rest_client/models/__init__.py +0 -0
- ddx/rest_client/models/market.py +693 -0
- ddx/rest_client/models/signed.py +61 -0
- ddx/rest_client/models/system.py +311 -0
- ddx/rest_client/models/trade.py +185 -0
- ddx/rest_client/utils/__init__.py +0 -0
- ddx/rest_client/utils/encryption_utils.py +26 -0
- ddx/utils/__init__.py +0 -0
- ddx_python-1.0.4.dist-info/METADATA +63 -0
- ddx_python-1.0.4.dist-info/RECORD +106 -0
- ddx_python-1.0.4.dist-info/WHEEL +5 -0
|
@@ -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,97 @@
|
|
|
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 oracle 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,
|
|
56
|
+
MarkPriceMetadata.Average) is not None
|
|
57
|
+
):
|
|
58
|
+
mark_price = (self.index_price + self.mark_price_metadata.accum) / (
|
|
59
|
+
self.mark_price_metadata.count + 1
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
raise ValueError("Invalid MarkPriceMetadata type")
|
|
63
|
+
return mark_price.recorded_amount()
|
|
64
|
+
|
|
65
|
+
def process_tx(
|
|
66
|
+
self,
|
|
67
|
+
smt: DerivadexSMT,
|
|
68
|
+
**kwargs,
|
|
69
|
+
):
|
|
70
|
+
"""
|
|
71
|
+
Process a PriceCheckpoint transaction. A PriceCheckpoint
|
|
72
|
+
consists of information relating to a new price checkpoint,
|
|
73
|
+
such as the symbol, composite index price, and mark price
|
|
74
|
+
metadata. This will update the Price leaf in the SMT.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
smt: DerivadexSMT
|
|
79
|
+
DerivaDEX Sparse Merkle Tree
|
|
80
|
+
**kwargs
|
|
81
|
+
Additional args specific to PriceCheckpoint transactions
|
|
82
|
+
"""
|
|
83
|
+
price_key = PriceKey(self.symbol, self.index_price_hash)
|
|
84
|
+
price = Price(
|
|
85
|
+
self.index_price,
|
|
86
|
+
self.mark_price_metadata,
|
|
87
|
+
self.ordinal,
|
|
88
|
+
self.time_value,
|
|
89
|
+
)
|
|
90
|
+
smt.store_price(price_key, price)
|
|
91
|
+
|
|
92
|
+
# Update latest price leaves abstraction with the new price
|
|
93
|
+
# checkpoint data
|
|
94
|
+
kwargs["latest_price_leaves"][self.symbol] = (
|
|
95
|
+
price_key,
|
|
96
|
+
price,
|
|
97
|
+
)
|
|
@@ -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
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Strategy Update module
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from attrs import define, field
|
|
8
|
+
from ddx.common.transactions.event import Event
|
|
9
|
+
from ddx.common.utils import calculate_max_collateral
|
|
10
|
+
from ddx._rust.common import TokenSymbol
|
|
11
|
+
from ddx._rust.common.state import DerivadexSMT, Strategy, Trader
|
|
12
|
+
from ddx._rust.common.state.keys import StrategyKey, TraderKey
|
|
13
|
+
from ddx._rust.common.transactions import StrategyUpdateKind
|
|
14
|
+
from ddx._rust.decimal import Decimal
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@define
|
|
18
|
+
class StrategyUpdate(Event):
|
|
19
|
+
"""
|
|
20
|
+
Defines a Strategy Update
|
|
21
|
+
|
|
22
|
+
A StrategyUpdate is an update to a trader's strategy (such as
|
|
23
|
+
depositing or withdrawing collateral).
|
|
24
|
+
|
|
25
|
+
Attributes:
|
|
26
|
+
trader_address (str): Trader's Ethereum address this strategy belongs to
|
|
27
|
+
collateral_address (str): Collateral's Ethereum address a deposit/withdrawal has been made with
|
|
28
|
+
strategy_id_hash (str): Strategy ID hash for the given trader this event belongs to
|
|
29
|
+
strategy_id (Optional[str]): Strategy ID for the given trader this event belongs to. Only deposits will fill this field
|
|
30
|
+
amount (Decimal): The amount of collateral deposited or withdrawn
|
|
31
|
+
update_kind (StrategyUpdateKind): Update kind (Deposit=0, Withdraw=1)
|
|
32
|
+
tx_hash (str): The Ethereum transaction's hash
|
|
33
|
+
request_index (int): Sequenced request index of transaction
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
trader_address: str = field(eq=str.lower)
|
|
37
|
+
collateral_address: str = field(eq=str.lower)
|
|
38
|
+
strategy_id_hash: str = field(eq=str.lower)
|
|
39
|
+
strategy_id: Optional[str]
|
|
40
|
+
amount: Decimal
|
|
41
|
+
update_kind: StrategyUpdateKind
|
|
42
|
+
tx_hash: str = field(eq=str.lower)
|
|
43
|
+
request_index: int = field(default=-1, eq=False)
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def decode_value_into_cls(cls, raw_tx_log_event: dict):
|
|
47
|
+
"""
|
|
48
|
+
Decode a raw transaction log event (dict) into a StrategyUpdate
|
|
49
|
+
instance.
|
|
50
|
+
|
|
51
|
+
Parameters
|
|
52
|
+
----------
|
|
53
|
+
raw_tx_log_event : dict
|
|
54
|
+
Raw transaction log event being processed
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
strategy_update_tx_event = raw_tx_log_event["event"]["c"]
|
|
58
|
+
|
|
59
|
+
return cls(
|
|
60
|
+
strategy_update_tx_event["trader"],
|
|
61
|
+
strategy_update_tx_event["collateralAddress"],
|
|
62
|
+
strategy_update_tx_event["strategyIdHash"],
|
|
63
|
+
strategy_update_tx_event.get("strategyId"),
|
|
64
|
+
Decimal(strategy_update_tx_event["amount"]),
|
|
65
|
+
StrategyUpdateKind(strategy_update_tx_event["updateKind"]),
|
|
66
|
+
strategy_update_tx_event["txHash"],
|
|
67
|
+
raw_tx_log_event["requestIndex"],
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def process_tx(
|
|
71
|
+
self,
|
|
72
|
+
smt: DerivadexSMT,
|
|
73
|
+
**kwargs,
|
|
74
|
+
):
|
|
75
|
+
"""
|
|
76
|
+
Process a StrategyUpdate transaction. A StrategyUpdate consists
|
|
77
|
+
of information relating to updates for a trader's strategy, such
|
|
78
|
+
as when their free or frozen collateral has changed due to a
|
|
79
|
+
deposit or withdrawal. This will update the Strategy leaf in the
|
|
80
|
+
SMT.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
smt: DerivadexSMT
|
|
85
|
+
DerivaDEX Sparse Merkle Tree
|
|
86
|
+
**kwargs
|
|
87
|
+
Additional args specific to StrategyUpdate transactions
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
strategy_key: StrategyKey = StrategyKey(
|
|
91
|
+
self.trader_address, self.strategy_id_hash
|
|
92
|
+
)
|
|
93
|
+
strategy = smt.strategy(strategy_key)
|
|
94
|
+
|
|
95
|
+
symbol = TokenSymbol.from_address(self.collateral_address)
|
|
96
|
+
if self.update_kind == StrategyUpdateKind.Deposit:
|
|
97
|
+
# If StrategyUpdate is of deposit type
|
|
98
|
+
|
|
99
|
+
trader_key: TraderKey = TraderKey(self.trader_address)
|
|
100
|
+
trader = smt.trader(trader_key)
|
|
101
|
+
|
|
102
|
+
if strategy is None:
|
|
103
|
+
# If we haven't yet seen the Strategy leaf, create a new
|
|
104
|
+
# one
|
|
105
|
+
strategy = Strategy.default()
|
|
106
|
+
|
|
107
|
+
if trader is None:
|
|
108
|
+
# Initialize a new Trader Leaf
|
|
109
|
+
trader = Trader.default()
|
|
110
|
+
|
|
111
|
+
smt.store_trader(trader_key, trader)
|
|
112
|
+
|
|
113
|
+
# Compute max allowable deposit given the collateral guard
|
|
114
|
+
# for the trader's DDX balance
|
|
115
|
+
max_allowable_deposit = max(
|
|
116
|
+
(
|
|
117
|
+
calculate_max_collateral(
|
|
118
|
+
kwargs["collateral_tranches"], trader.avail_ddx_balance
|
|
119
|
+
)
|
|
120
|
+
- strategy.avail_collateral.total_value()
|
|
121
|
+
),
|
|
122
|
+
Decimal("0"),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Compute how much of the attempted deposit will be added
|
|
126
|
+
# to the Strategy's free collateral
|
|
127
|
+
net = min(max_allowable_deposit, self.amount)
|
|
128
|
+
|
|
129
|
+
# Increment the Strategy's free collateral
|
|
130
|
+
strategy.set_avail_collateral(
|
|
131
|
+
symbol,
|
|
132
|
+
strategy.avail_collateral[symbol] + net,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Compute how much of the attempted deposit will be added
|
|
136
|
+
# to the Strategy's frozen collateral
|
|
137
|
+
kickback = self.amount - net
|
|
138
|
+
if kickback != Decimal("0"):
|
|
139
|
+
# Increment the Strategy's frozen collateral
|
|
140
|
+
strategy.set_locked_collateral(
|
|
141
|
+
symbol,
|
|
142
|
+
strategy.locked_collateral[symbol] + kickback,
|
|
143
|
+
)
|
|
144
|
+
elif self.update_kind == StrategyUpdateKind.Withdraw:
|
|
145
|
+
# If StrategyUpdate is of withdrawal (claimed) type
|
|
146
|
+
if strategy is None or strategy.locked_collateral[symbol] < self.amount:
|
|
147
|
+
raise Exception(
|
|
148
|
+
"Strategy leaf either non-existent or insufficiently capitalized to facilitate withdrawal"
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Adjust the existing strategy leaf by decrementing the
|
|
152
|
+
# free collateral by the amount in the withdrawal event
|
|
153
|
+
strategy.set_locked_collateral(
|
|
154
|
+
symbol,
|
|
155
|
+
strategy.locked_collateral[symbol] - self.amount,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
smt.store_strategy(strategy_key, strategy)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tradable Product Update module
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from attrs import define, field
|
|
6
|
+
from ddx.common.transactions.event import Event
|
|
7
|
+
from ddx._rust.common.specs import SpecsKind
|
|
8
|
+
from ddx._rust.common.state import (DerivadexSMT, TradableProduct,
|
|
9
|
+
TradableProductParameters)
|
|
10
|
+
from ddx._rust.common.state.keys import SpecsKey, TradableProductKey
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@define
|
|
14
|
+
class TradableProductUpdate(Event):
|
|
15
|
+
"""
|
|
16
|
+
Defines a Tradable Product Update
|
|
17
|
+
|
|
18
|
+
A TradableProductUpdate is an update to a trader's strategy (such as depositing or withdrawing collateral).
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
additions (list[TradableProductKey]): List of tradable product keys that are marked tradable
|
|
22
|
+
removals (list[TradableProductKey]): List of tradable product keys that are marked untradable
|
|
23
|
+
request_index (int): Sequenced request index of transaction
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
additions: list[TradableProductKey]
|
|
27
|
+
removals: list[TradableProductKey]
|
|
28
|
+
request_index: int = field(default=-1, eq=False, hash=False)
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def decode_value_into_cls(cls, raw_tx_log_event: dict):
|
|
32
|
+
"""
|
|
33
|
+
Decode a raw transaction log event (dict) into a StrategyUpdate
|
|
34
|
+
instance.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
raw_tx_log_event : dict
|
|
39
|
+
Raw transaction log event being processed
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
tradable_product_update_tx_event = raw_tx_log_event["event"]["c"]
|
|
43
|
+
|
|
44
|
+
return cls(
|
|
45
|
+
[
|
|
46
|
+
TradableProductKey(
|
|
47
|
+
SpecsKey(
|
|
48
|
+
SpecsKind(tradable_product_key["specsKey"]["kind"]),
|
|
49
|
+
tradable_product_key["specsKey"]["name"],
|
|
50
|
+
),
|
|
51
|
+
TradableProductParameters.from_dict(
|
|
52
|
+
tradable_product_key["parameters"]
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
for tradable_product_key in tradable_product_update_tx_event[
|
|
56
|
+
"additions"
|
|
57
|
+
]
|
|
58
|
+
],
|
|
59
|
+
[
|
|
60
|
+
TradableProductKey(
|
|
61
|
+
SpecsKey(
|
|
62
|
+
SpecsKind(tradable_product_key["specsKey"]["kind"]),
|
|
63
|
+
tradable_product_key["specsKey"]["name"],
|
|
64
|
+
),
|
|
65
|
+
TradableProductParameters.from_dict(
|
|
66
|
+
tradable_product_key["parameters"]
|
|
67
|
+
),
|
|
68
|
+
)
|
|
69
|
+
for tradable_product_key in tradable_product_update_tx_event["removals"]
|
|
70
|
+
],
|
|
71
|
+
raw_tx_log_event["requestIndex"],
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def process_tx(
|
|
75
|
+
self,
|
|
76
|
+
smt: DerivadexSMT,
|
|
77
|
+
**kwargs,
|
|
78
|
+
):
|
|
79
|
+
"""
|
|
80
|
+
Process a TradableProductUpdate transaction. A TradableProductUpdate consists
|
|
81
|
+
of information relating to updates of the list of tradable products.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
smt: DerivadexSMT
|
|
86
|
+
DerivaDEX Sparse Merkle Tree
|
|
87
|
+
**kwargs
|
|
88
|
+
Additional args specific to TradableProductUpdate transactions
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
for tradable_product_key in self.additions:
|
|
92
|
+
smt.store_tradable_product(
|
|
93
|
+
tradable_product_key,
|
|
94
|
+
TradableProduct(),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
for tradable_product_key in self.removals:
|
|
98
|
+
smt.store_tradable_product(tradable_product_key, None)
|