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,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Strategy Update module
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from attrs import define, field
|
|
8
|
+
from ddx.common.item_utils import update_avail_collateral, update_locked_collateral
|
|
9
|
+
from ddx.common.transactions.event import Event
|
|
10
|
+
from ddx.common.utils import calculate_max_collateral
|
|
11
|
+
from ddx._rust.common import TokenSymbol
|
|
12
|
+
from ddx._rust.common.state import DerivadexSMT, Strategy, Trader
|
|
13
|
+
from ddx._rust.common.state.keys import StrategyKey, TraderKey
|
|
14
|
+
from ddx._rust.common.transactions import StrategyUpdateKind
|
|
15
|
+
from ddx._rust.decimal import Decimal
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@define
|
|
19
|
+
class StrategyUpdate(Event):
|
|
20
|
+
"""
|
|
21
|
+
Defines a Strategy Update
|
|
22
|
+
|
|
23
|
+
A StrategyUpdate is an update to a trader's strategy (such as
|
|
24
|
+
depositing or withdrawing collateral).
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
trader_address (str): Trader's Ethereum address this strategy belongs to
|
|
28
|
+
collateral_address (str): Collateral's Ethereum address a deposit/withdrawal has been made with
|
|
29
|
+
strategy_id_hash (str): Strategy ID hash for the given trader this event belongs to
|
|
30
|
+
strategy_id (Optional[str]): Strategy ID for the given trader this event belongs to. Only deposits will fill this field
|
|
31
|
+
amount (Decimal): The amount of collateral deposited or withdrawn
|
|
32
|
+
update_kind (StrategyUpdateKind): Update kind (Deposit=0, Withdraw=1)
|
|
33
|
+
tx_hash (str): The Ethereum transaction's hash
|
|
34
|
+
request_index (int): Sequenced request index of transaction
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
trader_address: str = field(eq=str.lower)
|
|
38
|
+
collateral_address: str = field(eq=str.lower)
|
|
39
|
+
strategy_id_hash: str = field(eq=str.lower)
|
|
40
|
+
strategy_id: Optional[str]
|
|
41
|
+
amount: Decimal
|
|
42
|
+
update_kind: StrategyUpdateKind
|
|
43
|
+
tx_hash: str = field(eq=str.lower)
|
|
44
|
+
request_index: int = field(default=-1, eq=False)
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def decode_value_into_cls(cls, raw_tx_log_event: dict):
|
|
48
|
+
"""
|
|
49
|
+
Decode a raw transaction log event (dict) into a StrategyUpdate
|
|
50
|
+
instance.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
raw_tx_log_event : dict
|
|
55
|
+
Raw transaction log event being processed
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
strategy_update_tx_event = raw_tx_log_event["event"]["c"]
|
|
59
|
+
|
|
60
|
+
return cls(
|
|
61
|
+
strategy_update_tx_event["trader"],
|
|
62
|
+
strategy_update_tx_event["collateralAddress"],
|
|
63
|
+
strategy_update_tx_event["strategyIdHash"],
|
|
64
|
+
strategy_update_tx_event.get("strategyId"),
|
|
65
|
+
Decimal(strategy_update_tx_event["amount"]),
|
|
66
|
+
StrategyUpdateKind(strategy_update_tx_event["updateKind"]),
|
|
67
|
+
strategy_update_tx_event["txHash"],
|
|
68
|
+
raw_tx_log_event["requestIndex"],
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def process_tx(
|
|
72
|
+
self,
|
|
73
|
+
smt: DerivadexSMT,
|
|
74
|
+
**kwargs,
|
|
75
|
+
):
|
|
76
|
+
"""
|
|
77
|
+
Process a StrategyUpdate transaction. A StrategyUpdate consists
|
|
78
|
+
of information relating to updates for a trader's strategy, such
|
|
79
|
+
as when their free or frozen collateral has changed due to a
|
|
80
|
+
deposit or withdrawal. This will update the Strategy leaf in the
|
|
81
|
+
SMT.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
smt: DerivadexSMT
|
|
86
|
+
DerivaDEX Sparse Merkle Tree
|
|
87
|
+
**kwargs
|
|
88
|
+
Additional args specific to StrategyUpdate transactions
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
strategy_key: StrategyKey = StrategyKey(
|
|
92
|
+
self.trader_address, self.strategy_id_hash
|
|
93
|
+
)
|
|
94
|
+
strategy = smt.strategy(strategy_key)
|
|
95
|
+
|
|
96
|
+
symbol = TokenSymbol.from_address(self.collateral_address)
|
|
97
|
+
if self.update_kind == StrategyUpdateKind.Deposit:
|
|
98
|
+
# If StrategyUpdate is of deposit type
|
|
99
|
+
|
|
100
|
+
trader_key: TraderKey = TraderKey(self.trader_address)
|
|
101
|
+
trader = smt.trader(trader_key)
|
|
102
|
+
|
|
103
|
+
if strategy is None:
|
|
104
|
+
# If we haven't yet seen the Strategy leaf, create a new
|
|
105
|
+
# one
|
|
106
|
+
strategy = Strategy.default()
|
|
107
|
+
|
|
108
|
+
if trader is None:
|
|
109
|
+
# Initialize a new Trader Leaf
|
|
110
|
+
trader = Trader.default()
|
|
111
|
+
|
|
112
|
+
smt.store_trader(trader_key, trader)
|
|
113
|
+
|
|
114
|
+
# Compute max allowable deposit given the collateral guard
|
|
115
|
+
# for the trader's DDX balance
|
|
116
|
+
max_allowable_deposit = max(
|
|
117
|
+
(
|
|
118
|
+
calculate_max_collateral(
|
|
119
|
+
kwargs["collateral_tranches"], trader.avail_ddx_balance
|
|
120
|
+
)
|
|
121
|
+
- strategy.avail_collateral.total_value()
|
|
122
|
+
),
|
|
123
|
+
Decimal("0"),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Compute how much of the attempted deposit will be added
|
|
127
|
+
# to the Strategy's free collateral
|
|
128
|
+
net = min(max_allowable_deposit, self.amount)
|
|
129
|
+
|
|
130
|
+
# Increment the Strategy's free collateral
|
|
131
|
+
update_avail_collateral(
|
|
132
|
+
strategy, symbol, 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
|
+
update_locked_collateral(
|
|
141
|
+
strategy, symbol, strategy.locked_collateral[symbol] + kickback
|
|
142
|
+
)
|
|
143
|
+
elif self.update_kind == StrategyUpdateKind.Withdraw:
|
|
144
|
+
# If StrategyUpdate is of withdrawal (claimed) type
|
|
145
|
+
if strategy is None or strategy.locked_collateral[symbol] < self.amount:
|
|
146
|
+
raise Exception(
|
|
147
|
+
"Strategy leaf either non-existent or insufficiently capitalized to facilitate withdrawal"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# Adjust the existing strategy leaf by decrementing the
|
|
151
|
+
# free collateral by the amount in the withdrawal event
|
|
152
|
+
update_locked_collateral(
|
|
153
|
+
strategy, symbol, strategy.locked_collateral[symbol] - self.amount
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
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["specs"]["kind"]),
|
|
49
|
+
tradable_product_key["specs"]["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["specs"]["kind"]),
|
|
63
|
+
tradable_product_key["specs"]["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)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TradeMining module
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from attrs import define, field
|
|
8
|
+
from ddx.common.transactions.event import Event
|
|
9
|
+
from ddx._rust.common.state import DerivadexSMT, Stats
|
|
10
|
+
from ddx._rust.common.state.keys import TraderKey
|
|
11
|
+
from ddx._rust.decimal import Decimal
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@define
|
|
17
|
+
class TradeMining(Event):
|
|
18
|
+
"""
|
|
19
|
+
Defines a TradeMining
|
|
20
|
+
|
|
21
|
+
A TradeMining is when a there is a trade mining distribution.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
settlement_epoch_id (int): Settlement epoch id
|
|
25
|
+
ddx_distributed (Decimal): The total DDX distributed in this interval.
|
|
26
|
+
total_volume (Stats): The total maker and taker volume for this interval.
|
|
27
|
+
request_index (int): Sequenced request index of transaction
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
settlement_epoch_id: int
|
|
31
|
+
ddx_distributed: Decimal
|
|
32
|
+
total_volume: Stats
|
|
33
|
+
request_index: int = field(default=-1, eq=False)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def decode_value_into_cls(cls, raw_tx_log_event: dict):
|
|
37
|
+
"""
|
|
38
|
+
Decode a raw transaction log event (dict) into a Funding
|
|
39
|
+
instance.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
raw_tx_log_event : dict
|
|
44
|
+
Raw transaction log event being processed
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
trade_mining_tx_event = raw_tx_log_event["event"]["c"]
|
|
48
|
+
|
|
49
|
+
return cls(
|
|
50
|
+
trade_mining_tx_event["settlementEpochId"],
|
|
51
|
+
Decimal(trade_mining_tx_event["ddxDistributed"]),
|
|
52
|
+
Stats(
|
|
53
|
+
Decimal(trade_mining_tx_event["totalVolume"]["makerVolume"]),
|
|
54
|
+
Decimal(trade_mining_tx_event["totalVolume"]["takerVolume"]),
|
|
55
|
+
),
|
|
56
|
+
raw_tx_log_event["requestIndex"],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def process_tx(
|
|
60
|
+
self,
|
|
61
|
+
smt: DerivadexSMT,
|
|
62
|
+
**kwargs,
|
|
63
|
+
):
|
|
64
|
+
"""
|
|
65
|
+
Process a TradeMining transaction. A TradeMining event consists
|
|
66
|
+
of consists of information relating to the trade mining
|
|
67
|
+
distribution, when DDX will be allocated to traders due to
|
|
68
|
+
their maker and taker volume contributions as a proportion to
|
|
69
|
+
the overall exchange volume.
|
|
70
|
+
|
|
71
|
+
Parameters
|
|
72
|
+
----------
|
|
73
|
+
smt: DerivadexSMT
|
|
74
|
+
DerivaDEX Sparse Merkle Tree
|
|
75
|
+
**kwargs
|
|
76
|
+
Additional args specific to TradeMining transactions
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
if not kwargs["trade_mining_active"]:
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
# The overall trade mining allocation is 75% of the
|
|
83
|
+
# liquidity mining supply (50mm DDX) issued over a 10-year
|
|
84
|
+
# schedule, 3 times a day
|
|
85
|
+
ddx_reward_per_epoch = kwargs["trade_mining_reward_per_epoch"]
|
|
86
|
+
trade_mining_maker_reward_percentage = kwargs[
|
|
87
|
+
"trade_mining_maker_reward_percentage"
|
|
88
|
+
]
|
|
89
|
+
trade_mining_taker_reward_percentage = kwargs[
|
|
90
|
+
"trade_mining_taker_reward_percentage"
|
|
91
|
+
]
|
|
92
|
+
if self.ddx_distributed != Decimal("0"):
|
|
93
|
+
# If trade mining did distribute DDX during the trade
|
|
94
|
+
# mining period, we should handle DDX distributions,
|
|
95
|
+
# otherwise we can gracefully skip
|
|
96
|
+
|
|
97
|
+
# Loop through all the stats leaves
|
|
98
|
+
for stats_key, stats in smt.all_stats():
|
|
99
|
+
# Compute the DDX gained as a result of maker volume
|
|
100
|
+
# for the trader (20% of the DDX rewards go to makers)
|
|
101
|
+
ddx_accrued_as_maker = (
|
|
102
|
+
stats.maker_volume
|
|
103
|
+
/ self.total_volume.maker_volume
|
|
104
|
+
* ddx_reward_per_epoch
|
|
105
|
+
* trade_mining_maker_reward_percentage
|
|
106
|
+
if self.total_volume.maker_volume != Decimal("0")
|
|
107
|
+
else Decimal("0")
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# Compute the DDX gained as a result of taker volume
|
|
111
|
+
# for the trader (80% of the DDX rewards go to takers)
|
|
112
|
+
ddx_accrued_as_taker = (
|
|
113
|
+
stats.taker_volume
|
|
114
|
+
/ self.total_volume.taker_volume
|
|
115
|
+
* ddx_reward_per_epoch
|
|
116
|
+
* trade_mining_taker_reward_percentage
|
|
117
|
+
if self.total_volume.taker_volume != Decimal("0")
|
|
118
|
+
else Decimal("0")
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
if ddx_accrued_as_maker != Decimal(
|
|
122
|
+
"0"
|
|
123
|
+
) or ddx_accrued_as_taker != Decimal("0"):
|
|
124
|
+
# If DDX accrued for trader is non-zero, handle
|
|
125
|
+
# distribution
|
|
126
|
+
|
|
127
|
+
# Derive TraderKey given the key
|
|
128
|
+
trader_key: TraderKey = stats_key.as_trader_key()
|
|
129
|
+
|
|
130
|
+
# Get Trader leaf given the key from above
|
|
131
|
+
trader = smt.trader(trader_key)
|
|
132
|
+
|
|
133
|
+
# Increment the Trader leaf's available balance by the
|
|
134
|
+
# DDX accrued (both maker and taker)
|
|
135
|
+
trader.avail_ddx_balance = (
|
|
136
|
+
trader.avail_ddx_balance
|
|
137
|
+
+ ddx_accrued_as_maker
|
|
138
|
+
+ ddx_accrued_as_taker
|
|
139
|
+
).recorded_amount()
|
|
140
|
+
|
|
141
|
+
# Update the SMT with the H256 repr of the key and
|
|
142
|
+
# the Trader leaf
|
|
143
|
+
smt.store_trader(trader_key, trader)
|
|
144
|
+
|
|
145
|
+
# Update the SMT with the H256 repr of the key and
|
|
146
|
+
# the Stats leaf
|
|
147
|
+
smt.store_stats(stats_key, None)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Trader Update 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, Trader
|
|
8
|
+
from ddx._rust.common.state.keys import TraderKey
|
|
9
|
+
from ddx._rust.common.transactions import TraderUpdateKind
|
|
10
|
+
from ddx._rust.decimal import Decimal
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@define
|
|
14
|
+
class TraderUpdate(Event):
|
|
15
|
+
"""
|
|
16
|
+
Defines a TraderUpdate
|
|
17
|
+
|
|
18
|
+
A TraderUpdate is an update to a trader's DDX account (such as depositing
|
|
19
|
+
or withdrawing DDX).
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
trader_address (str): Trader's Ethereum address this strategy belongs to
|
|
23
|
+
amount (Decimal): The amount of collateral deposited or withdrawn
|
|
24
|
+
update_kind (TraderUpdateKind): Update kind (Deposit, Withdraw, Profile)
|
|
25
|
+
pay_fees_in_ddx (bool): Whether trader has opted to pay fees in DDX by default
|
|
26
|
+
tx_hash (str): The Ethereum transaction's hash
|
|
27
|
+
request_index (int): Sequenced request index of transaction
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
trader_address: str = field(eq=str.lower)
|
|
31
|
+
amount: Decimal
|
|
32
|
+
update_kind: TraderUpdateKind
|
|
33
|
+
pay_fees_in_ddx: bool
|
|
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 StrategyUpdate
|
|
40
|
+
instance.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
raw_tx_log_event : dict
|
|
45
|
+
Raw transaction log event being processed
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
trader_update_tx_event = raw_tx_log_event["event"]["c"]
|
|
49
|
+
|
|
50
|
+
return cls(
|
|
51
|
+
trader_update_tx_event["trader"],
|
|
52
|
+
Decimal(trader_update_tx_event["amount"]),
|
|
53
|
+
TraderUpdateKind(trader_update_tx_event["updateKind"]),
|
|
54
|
+
trader_update_tx_event["payFeesInDdx"],
|
|
55
|
+
raw_tx_log_event["requestIndex"],
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def process_tx(
|
|
59
|
+
self,
|
|
60
|
+
smt: DerivadexSMT,
|
|
61
|
+
**kwargs,
|
|
62
|
+
):
|
|
63
|
+
"""
|
|
64
|
+
Process a TraderUpdate transaction. A TraderUpdate consists
|
|
65
|
+
of information relating to updates to a trader. This will
|
|
66
|
+
update the Trader leaf in the SMT.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
smt: DerivadexSMT
|
|
71
|
+
DerivaDEX Sparse Merkle Tree
|
|
72
|
+
**kwargs
|
|
73
|
+
Additional args specific to TraderUpdate transactions
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
trader_key: TraderKey = TraderKey(self.trader_address)
|
|
77
|
+
trader = smt.trader(trader_key)
|
|
78
|
+
|
|
79
|
+
if self.update_kind == TraderUpdateKind.DepositDDX:
|
|
80
|
+
# If TraderUpdate is of deposit type
|
|
81
|
+
if trader is None:
|
|
82
|
+
# Initialize a new Trader Leaf
|
|
83
|
+
trader = Trader.default()
|
|
84
|
+
|
|
85
|
+
trader.avail_ddx_balance += self.amount
|
|
86
|
+
elif self.update_kind == TraderUpdateKind.WithdrawDDX:
|
|
87
|
+
# If TraderUpdate is of withdrawal (claimed) type
|
|
88
|
+
if trader is None or trader.locked_ddx_balance < self.amount:
|
|
89
|
+
raise Exception(
|
|
90
|
+
"Trader leaf either non-existent or insufficiently capitalized to facilitate withdrawal"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Adjust the existing Trader leaf by decrementing the
|
|
94
|
+
# free collateral by the amount in the withdrawal event
|
|
95
|
+
trader.locked_ddx_balance -= self.amount
|
|
96
|
+
elif self.update_kind == TraderUpdateKind.Profile:
|
|
97
|
+
# If TraderUpdate is of profile type
|
|
98
|
+
if trader is None:
|
|
99
|
+
raise Exception("Trader leaf non-existent")
|
|
100
|
+
|
|
101
|
+
# Adjust the existing Trader leaf by setting the
|
|
102
|
+
# flag to pay fees in DDX
|
|
103
|
+
trader.pay_fees_in_ddx = self.pay_fees_in_ddx
|
|
104
|
+
|
|
105
|
+
smt.store_trader(trader_key, trader)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Withdraw module
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from attrs import define, field
|
|
6
|
+
from ddx.common.item_utils import update_avail_collateral, update_locked_collateral
|
|
7
|
+
from ddx.common.transactions.event import Event
|
|
8
|
+
from ddx._rust.common import TokenSymbol
|
|
9
|
+
from ddx._rust.common.state import DerivadexSMT, Strategy, Trader
|
|
10
|
+
from ddx._rust.common.state.keys import StrategyKey
|
|
11
|
+
from ddx._rust.decimal import Decimal
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@define
|
|
15
|
+
class Withdraw(Event):
|
|
16
|
+
"""
|
|
17
|
+
Defines a Withdraw Update
|
|
18
|
+
|
|
19
|
+
A Withdraw Update is when a withdrawal of collateral is **signaled**.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
recipient_address (str): Trader address DDX is being withdrawn to
|
|
23
|
+
strategy_id_hash (str): Cross-margined strategy ID hash for which this withdrawal applies
|
|
24
|
+
collateral_address (str): Collateral ERC-20 token address being withdrawn
|
|
25
|
+
amount (Decimal): The amount of DDX being withdrawn
|
|
26
|
+
request_index (int): Sequenced request index of transaction
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
recipient_address: str = field(eq=str.lower)
|
|
30
|
+
strategy_id_hash: str = field(eq=str.lower)
|
|
31
|
+
collateral_address: str = field(eq=str.lower)
|
|
32
|
+
amount: Decimal
|
|
33
|
+
request_index: int = field(default=-1, eq=False)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def decode_value_into_cls(cls, raw_tx_log_event: dict):
|
|
37
|
+
"""
|
|
38
|
+
Decode a raw transaction log event (dict) into a Withdraw
|
|
39
|
+
instance.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
raw_tx_log_event : dict
|
|
44
|
+
Raw transaction log event being processed
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
withdraw_tx_event = raw_tx_log_event["event"]["c"]
|
|
48
|
+
|
|
49
|
+
return cls(
|
|
50
|
+
withdraw_tx_event["recipientAddress"],
|
|
51
|
+
withdraw_tx_event["strategy"],
|
|
52
|
+
withdraw_tx_event["currency"],
|
|
53
|
+
Decimal(withdraw_tx_event["amount"]),
|
|
54
|
+
raw_tx_log_event["requestIndex"],
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def process_tx(
|
|
58
|
+
self,
|
|
59
|
+
smt: DerivadexSMT,
|
|
60
|
+
**kwargs,
|
|
61
|
+
):
|
|
62
|
+
"""
|
|
63
|
+
Process a Withdraw transaction. A Withdraw event consists
|
|
64
|
+
of consists of information relating to withdrawal of collateral.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
smt: DerivadexSMT
|
|
69
|
+
DerivaDEX Sparse Merkle Tree
|
|
70
|
+
**kwargs
|
|
71
|
+
Additional args specific to Withdraw transactions
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
strategy_key: StrategyKey = StrategyKey(
|
|
75
|
+
self.recipient_address, self.strategy_id_hash
|
|
76
|
+
)
|
|
77
|
+
strategy: Strategy = smt.strategy(strategy_key)
|
|
78
|
+
|
|
79
|
+
# Decrement the free balance by the withdrawn amount
|
|
80
|
+
symbol = TokenSymbol.from_address(self.collateral_address)
|
|
81
|
+
update_avail_collateral(
|
|
82
|
+
strategy,
|
|
83
|
+
symbol,
|
|
84
|
+
strategy.avail_collateral[symbol] - self.amount,
|
|
85
|
+
)
|
|
86
|
+
# Increment the frozen balance by the withdrawn amount
|
|
87
|
+
update_locked_collateral(
|
|
88
|
+
strategy, symbol, strategy.locked_collateral[symbol] + self.amount
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
smt.store_strategy(strategy_key, strategy)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WithdrawDDX 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
|
|
8
|
+
from ddx._rust.common.state.keys import TraderKey
|
|
9
|
+
from ddx._rust.decimal import Decimal
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@define
|
|
13
|
+
class WithdrawDDX(Event):
|
|
14
|
+
"""
|
|
15
|
+
Defines a WithdrawDDX Update
|
|
16
|
+
|
|
17
|
+
A WithdrawDDX is when a withdrawal of DDX is signaled.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
recipient_address (str): Ethereum address DDX is being withdrawn to
|
|
21
|
+
amount (Decimal): The amount of DDX being withdrawn
|
|
22
|
+
request_index (int): Sequenced request index of transaction
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
recipient_address: str = field(eq=str.lower)
|
|
26
|
+
amount: Decimal
|
|
27
|
+
request_index: int = field(default=-1, eq=False)
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def decode_value_into_cls(cls, raw_tx_log_event: dict):
|
|
31
|
+
"""
|
|
32
|
+
Decode a raw transaction log event (dict) into a WithdrawDDX
|
|
33
|
+
instance.
|
|
34
|
+
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
raw_tx_log_event : dict
|
|
38
|
+
Raw transaction log event being processed
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
withdraw_ddx_tx_event = raw_tx_log_event["event"]["c"]
|
|
42
|
+
|
|
43
|
+
return cls(
|
|
44
|
+
withdraw_ddx_tx_event["recipientAddress"],
|
|
45
|
+
Decimal(withdraw_ddx_tx_event["amount"]),
|
|
46
|
+
raw_tx_log_event["requestIndex"],
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def process_tx(
|
|
50
|
+
self,
|
|
51
|
+
smt: DerivadexSMT,
|
|
52
|
+
**kwargs,
|
|
53
|
+
):
|
|
54
|
+
"""
|
|
55
|
+
Process a WithdrawDDX transaction. A WithdrawDDX event consists
|
|
56
|
+
of consists of information relating to withdrawal of DDX.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
smt: DerivadexSMT
|
|
61
|
+
DerivaDEX Sparse Merkle Tree
|
|
62
|
+
**kwargs
|
|
63
|
+
Additional args specific to WithdrawDDX transactions
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
trader_key: TraderKey = TraderKey(self.recipient_address)
|
|
67
|
+
trader = smt.trader(trader_key)
|
|
68
|
+
|
|
69
|
+
# Decrement the free balance by the withdrawn amount
|
|
70
|
+
trader.avail_ddx_balance -= self.amount
|
|
71
|
+
# Increment the frozen balance by the withdrawn amount
|
|
72
|
+
trader.locked_ddx_balance += self.amount
|
|
73
|
+
|
|
74
|
+
smt.store_trader(trader_key, trader)
|