ddx-python 1.0.4__cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. ddx/.gitignore +1 -0
  2. ddx/__init__.py +58 -0
  3. ddx/_rust/__init__.pyi +2685 -0
  4. ddx/_rust/common/__init__.pyi +17 -0
  5. ddx/_rust/common/accounting.pyi +6 -0
  6. ddx/_rust/common/enums.pyi +3 -0
  7. ddx/_rust/common/requests/__init__.pyi +23 -0
  8. ddx/_rust/common/requests/intents.pyi +19 -0
  9. ddx/_rust/common/specs.pyi +17 -0
  10. ddx/_rust/common/state/__init__.pyi +41 -0
  11. ddx/_rust/common/state/keys.pyi +29 -0
  12. ddx/_rust/common/transactions.pyi +7 -0
  13. ddx/_rust/decimal.pyi +3 -0
  14. ddx/_rust/h256.pyi +3 -0
  15. ddx/_rust.abi3.so +0 -0
  16. ddx/app_config/ethereum/addresses.json +526 -0
  17. ddx/auditor/README.md +32 -0
  18. ddx/auditor/__init__.py +0 -0
  19. ddx/auditor/auditor_driver.py +1043 -0
  20. ddx/auditor/websocket_message.py +54 -0
  21. ddx/common/__init__.py +0 -0
  22. ddx/common/epoch_params.py +28 -0
  23. ddx/common/fill_context.py +141 -0
  24. ddx/common/logging.py +184 -0
  25. ddx/common/market_aware_account.py +259 -0
  26. ddx/common/market_specs.py +64 -0
  27. ddx/common/trade_mining_params.py +19 -0
  28. ddx/common/transaction_utils.py +85 -0
  29. ddx/common/transactions/__init__.py +0 -0
  30. ddx/common/transactions/advance_epoch.py +91 -0
  31. ddx/common/transactions/advance_settlement_epoch.py +63 -0
  32. ddx/common/transactions/all_price_checkpoints.py +84 -0
  33. ddx/common/transactions/cancel.py +76 -0
  34. ddx/common/transactions/cancel_all.py +88 -0
  35. ddx/common/transactions/complete_fill.py +103 -0
  36. ddx/common/transactions/disaster_recovery.py +96 -0
  37. ddx/common/transactions/event.py +48 -0
  38. ddx/common/transactions/fee_distribution.py +119 -0
  39. ddx/common/transactions/funding.py +292 -0
  40. ddx/common/transactions/futures_expiry.py +123 -0
  41. ddx/common/transactions/genesis.py +108 -0
  42. ddx/common/transactions/inner/__init__.py +0 -0
  43. ddx/common/transactions/inner/adl_outcome.py +25 -0
  44. ddx/common/transactions/inner/fill.py +232 -0
  45. ddx/common/transactions/inner/liquidated_position.py +41 -0
  46. ddx/common/transactions/inner/liquidation_entry.py +41 -0
  47. ddx/common/transactions/inner/liquidation_fill.py +118 -0
  48. ddx/common/transactions/inner/outcome.py +32 -0
  49. ddx/common/transactions/inner/trade_fill.py +292 -0
  50. ddx/common/transactions/insurance_fund_update.py +138 -0
  51. ddx/common/transactions/insurance_fund_withdraw.py +100 -0
  52. ddx/common/transactions/liquidation.py +353 -0
  53. ddx/common/transactions/partial_fill.py +125 -0
  54. ddx/common/transactions/pnl_realization.py +120 -0
  55. ddx/common/transactions/post.py +72 -0
  56. ddx/common/transactions/post_order.py +95 -0
  57. ddx/common/transactions/price_checkpoint.py +97 -0
  58. ddx/common/transactions/signer_registered.py +62 -0
  59. ddx/common/transactions/specs_update.py +61 -0
  60. ddx/common/transactions/strategy_update.py +158 -0
  61. ddx/common/transactions/tradable_product_update.py +98 -0
  62. ddx/common/transactions/trade_mining.py +147 -0
  63. ddx/common/transactions/trader_update.py +131 -0
  64. ddx/common/transactions/withdraw.py +90 -0
  65. ddx/common/transactions/withdraw_ddx.py +74 -0
  66. ddx/common/utils.py +176 -0
  67. ddx/config.py +17 -0
  68. ddx/derivadex_client.py +270 -0
  69. ddx/models/__init__.py +0 -0
  70. ddx/models/base.py +132 -0
  71. ddx/py.typed +0 -0
  72. ddx/realtime_client/__init__.py +2 -0
  73. ddx/realtime_client/config.py +2 -0
  74. ddx/realtime_client/models/__init__.py +611 -0
  75. ddx/realtime_client/realtime_client.py +646 -0
  76. ddx/rest_client/__init__.py +0 -0
  77. ddx/rest_client/clients/__init__.py +0 -0
  78. ddx/rest_client/clients/base_client.py +60 -0
  79. ddx/rest_client/clients/market_client.py +1243 -0
  80. ddx/rest_client/clients/on_chain_client.py +439 -0
  81. ddx/rest_client/clients/signed_client.py +292 -0
  82. ddx/rest_client/clients/system_client.py +843 -0
  83. ddx/rest_client/clients/trade_client.py +357 -0
  84. ddx/rest_client/constants/__init__.py +0 -0
  85. ddx/rest_client/constants/endpoints.py +66 -0
  86. ddx/rest_client/contracts/__init__.py +0 -0
  87. ddx/rest_client/contracts/checkpoint/__init__.py +560 -0
  88. ddx/rest_client/contracts/ddx/__init__.py +1949 -0
  89. ddx/rest_client/contracts/dummy_token/__init__.py +1014 -0
  90. ddx/rest_client/contracts/i_collateral/__init__.py +1414 -0
  91. ddx/rest_client/contracts/i_stake/__init__.py +696 -0
  92. ddx/rest_client/exceptions/__init__.py +0 -0
  93. ddx/rest_client/exceptions/exceptions.py +32 -0
  94. ddx/rest_client/http/__init__.py +0 -0
  95. ddx/rest_client/http/http_client.py +336 -0
  96. ddx/rest_client/models/__init__.py +0 -0
  97. ddx/rest_client/models/market.py +693 -0
  98. ddx/rest_client/models/signed.py +61 -0
  99. ddx/rest_client/models/system.py +311 -0
  100. ddx/rest_client/models/trade.py +185 -0
  101. ddx/rest_client/utils/__init__.py +0 -0
  102. ddx/rest_client/utils/encryption_utils.py +26 -0
  103. ddx/utils/__init__.py +0 -0
  104. ddx_python-1.0.4.dist-info/METADATA +63 -0
  105. ddx_python-1.0.4.dist-info/RECORD +106 -0
  106. ddx_python-1.0.4.dist-info/WHEEL +5 -0
@@ -0,0 +1,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,131 @@
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
+ from typing import Optional
12
+
13
+
14
+ def _is_zero_address(addr: Optional[str]) -> bool:
15
+ if addr is None:
16
+ return True
17
+ try:
18
+ return int(str(addr).replace("0x", ""), 16) == 0
19
+ except Exception:
20
+ return False
21
+
22
+
23
+ @define
24
+ class TraderUpdate(Event):
25
+ """
26
+ Defines a TraderUpdate
27
+
28
+ A TraderUpdate is an update to a trader's DDX account (such as depositing
29
+ or withdrawing DDX).
30
+
31
+ Attributes:
32
+ trader_address (str): Trader's Ethereum address this strategy belongs to
33
+ amount (Decimal): The amount of collateral deposited or withdrawn
34
+ update_kind (TraderUpdateKind): Update kind (Deposit, Withdraw, Profile)
35
+ pay_fees_in_ddx (bool): Whether trader has opted to pay fees in DDX by default
36
+ referral_address (Optional[str]): Optional referral address to set exactly once
37
+ tx_hash (str): The Ethereum transaction's hash
38
+ request_index (int): Sequenced request index of transaction
39
+ """
40
+
41
+ trader_address: str = field(eq=str.lower)
42
+ amount: Decimal
43
+ update_kind: TraderUpdateKind
44
+ pay_fees_in_ddx: bool
45
+ referral_address: Optional[str] = None
46
+ request_index: int = field(default=-1, eq=False)
47
+
48
+ @classmethod
49
+ def decode_value_into_cls(cls, raw_tx_log_event: dict):
50
+ """
51
+ Decode a raw transaction log event (dict) into a StrategyUpdate
52
+ instance.
53
+
54
+ Parameters
55
+ ----------
56
+ raw_tx_log_event : dict
57
+ Raw transaction log event being processed
58
+ """
59
+
60
+ trader_update_tx_event = raw_tx_log_event["event"]["c"]
61
+
62
+ amount_raw = trader_update_tx_event.get("amount")
63
+ amount = Decimal(amount_raw) if amount_raw is not None else Decimal("0")
64
+
65
+ return cls(
66
+ trader_update_tx_event["trader"],
67
+ amount,
68
+ TraderUpdateKind(trader_update_tx_event["updateKind"]),
69
+ trader_update_tx_event.get("payFeesInDdx", False),
70
+ trader_update_tx_event.get("referralAddress"),
71
+ raw_tx_log_event["requestIndex"],
72
+ )
73
+
74
+ def process_tx(
75
+ self,
76
+ smt: DerivadexSMT,
77
+ **kwargs,
78
+ ):
79
+ """
80
+ Process a TraderUpdate transaction. A TraderUpdate consists
81
+ of information relating to updates to a trader. This will
82
+ update the Trader leaf in the SMT.
83
+
84
+ Parameters
85
+ ----------
86
+ smt: DerivadexSMT
87
+ DerivaDEX Sparse Merkle Tree
88
+ **kwargs
89
+ Additional args specific to TraderUpdate transactions
90
+ """
91
+
92
+ trader_key: TraderKey = TraderKey(self.trader_address)
93
+ trader = smt.trader(trader_key)
94
+
95
+ if self.update_kind == TraderUpdateKind.DepositDDX:
96
+ # If TraderUpdate is of deposit type
97
+ if trader is None:
98
+ # Initialize a new Trader Leaf
99
+ trader = Trader.default()
100
+
101
+ trader.avail_ddx_balance += self.amount
102
+ elif self.update_kind == TraderUpdateKind.WithdrawDDX:
103
+ # If TraderUpdate is of withdrawal (claimed) type
104
+ if trader is None or trader.locked_ddx_balance < self.amount:
105
+ raise Exception(
106
+ "Trader leaf either non-existent or insufficiently capitalized to facilitate withdrawal"
107
+ )
108
+
109
+ # Adjust the existing Trader leaf by decrementing the
110
+ # free collateral by the amount in the withdrawal event
111
+ trader.locked_ddx_balance -= self.amount
112
+ elif self.update_kind == TraderUpdateKind.Profile:
113
+ # If TraderUpdate is of profile type
114
+ if trader is None:
115
+ raise Exception("Trader leaf non-existent")
116
+
117
+ # Adjust the existing Trader leaf by setting the
118
+ # flag to pay fees in DDX
119
+ trader.pay_fees_in_ddx = self.pay_fees_in_ddx
120
+ if self.referral_address and not _is_zero_address(self.referral_address):
121
+ # Set-once semantics: only set when currently unset/zero.
122
+ if _is_zero_address(trader.referral_address):
123
+ # Ensure the referral uses the 21-byte TraderAddress format (chain byte + EOA).
124
+ referral = self.referral_address
125
+ if referral.startswith("0x") and len(referral) == 42:
126
+ referral = f"0x00{referral[2:]}"
127
+ trader.referral_address = referral
128
+ elif trader.referral_address != self.referral_address:
129
+ raise Exception("Referral address already set for trader")
130
+
131
+ smt.store_trader(trader_key, trader)
@@ -0,0 +1,90 @@
1
+ """
2
+ Withdraw module
3
+ """
4
+
5
+ from attrs import define, field
6
+ from ddx.common.transactions.event import Event
7
+ from ddx._rust.common import TokenSymbol
8
+ from ddx._rust.common.state import DerivadexSMT, Strategy, Trader
9
+ from ddx._rust.common.state.keys import StrategyKey
10
+ from ddx._rust.decimal import Decimal
11
+
12
+
13
+ @define
14
+ class Withdraw(Event):
15
+ """
16
+ Defines a Withdraw Update
17
+
18
+ A Withdraw Update is when a withdrawal of collateral is **signaled**.
19
+
20
+ Attributes:
21
+ recipient_address (str): Trader address DDX is being withdrawn to
22
+ strategy_id_hash (str): Cross-margined strategy ID hash for which this withdrawal applies
23
+ collateral_address (str): Collateral ERC-20 token address being withdrawn
24
+ amount (Decimal): The amount of DDX being withdrawn
25
+ request_index (int): Sequenced request index of transaction
26
+ """
27
+
28
+ recipient_address: str = field(eq=str.lower)
29
+ strategy_id_hash: str = field(eq=str.lower)
30
+ collateral_address: str = field(eq=str.lower)
31
+ amount: Decimal
32
+ request_index: int = field(default=-1, eq=False)
33
+
34
+ @classmethod
35
+ def decode_value_into_cls(cls, raw_tx_log_event: dict):
36
+ """
37
+ Decode a raw transaction log event (dict) into a Withdraw
38
+ instance.
39
+
40
+ Parameters
41
+ ----------
42
+ raw_tx_log_event : dict
43
+ Raw transaction log event being processed
44
+ """
45
+
46
+ withdraw_tx_event = raw_tx_log_event["event"]["c"]
47
+
48
+ return cls(
49
+ withdraw_tx_event["recipientAddress"],
50
+ withdraw_tx_event["strategy"],
51
+ withdraw_tx_event["currency"],
52
+ Decimal(withdraw_tx_event["amount"]),
53
+ raw_tx_log_event["requestIndex"],
54
+ )
55
+
56
+ def process_tx(
57
+ self,
58
+ smt: DerivadexSMT,
59
+ **kwargs,
60
+ ):
61
+ """
62
+ Process a Withdraw transaction. A Withdraw event consists
63
+ of consists of information relating to withdrawal of collateral.
64
+
65
+ Parameters
66
+ ----------
67
+ smt: DerivadexSMT
68
+ DerivaDEX Sparse Merkle Tree
69
+ **kwargs
70
+ Additional args specific to Withdraw transactions
71
+ """
72
+
73
+ strategy_key: StrategyKey = StrategyKey(
74
+ self.recipient_address, self.strategy_id_hash
75
+ )
76
+ strategy: Strategy = smt.strategy(strategy_key)
77
+
78
+ # Decrement the free balance by the withdrawn amount
79
+ symbol = TokenSymbol.from_address(self.collateral_address)
80
+ strategy.set_avail_collateral(
81
+ symbol,
82
+ strategy.avail_collateral[symbol] - self.amount,
83
+ )
84
+ # Increment the frozen balance by the withdrawn amount
85
+ strategy.set_locked_collateral(
86
+ symbol,
87
+ strategy.locked_collateral[symbol] + self.amount,
88
+ )
89
+
90
+ 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)
ddx/common/utils.py ADDED
@@ -0,0 +1,176 @@
1
+ """
2
+ Utils module
3
+ """
4
+
5
+ from decimal import Decimal as PyDecimal
6
+ import simplejson as json
7
+
8
+ from ddx._rust.common.enums import OrderSide
9
+ from ddx._rust.decimal import Decimal
10
+
11
+
12
+ def round_to_unit(val: Decimal) -> Decimal:
13
+ """
14
+ Round a decimal value down to 6 units of precision.
15
+
16
+ Parameters
17
+ ----------
18
+ val : Decimal
19
+ Value to be rounded
20
+ """
21
+
22
+ return val.quantize(6)
23
+
24
+
25
+ def to_base_unit_amount(val: Decimal, decimals: int) -> int:
26
+ """
27
+ Convert a value to grains format (e.g. DDX grains would be
28
+ multiplying by 10 ** 18).
29
+
30
+ Parameters
31
+ ----------
32
+ val : Decimal
33
+ Value to be scaled up
34
+ decimals : int
35
+ Number of decimal places to scale up to
36
+ """
37
+
38
+ return int(round_to_unit(val) * 10**decimals)
39
+
40
+
41
+ def to_unit_amount(val: int, decimals: int) -> Decimal:
42
+ """
43
+ Convert a value from grains format (e.g. from DDX grains would be
44
+ dividing by 10 ** 18).
45
+
46
+ Parameters
47
+ ----------
48
+ val : Decimal
49
+ Value to be scaled down
50
+ decimals : int
51
+ Number of decimal places to scale down by
52
+ """
53
+
54
+ return Decimal(str(val)) / 10**decimals
55
+
56
+
57
+ def to_base_unit_amount_list(vals: list[Decimal], decimals: int) -> list[int]:
58
+ """
59
+ Convert values to grains format (e.g. DDX grains would be
60
+ multiplying by 10 ** 18).
61
+
62
+ Parameters
63
+ ----------
64
+ vals : list[Decimal]
65
+ Values to be scaled up
66
+ decimals : int
67
+ Number of decimal places to scale up to
68
+ """
69
+
70
+ return [to_base_unit_amount(val, decimals) for val in vals]
71
+
72
+
73
+ def to_unit_amount_list(vals: list[int], decimals: int):
74
+ """
75
+ Convert values from grains format (e.g. from DDX grains would be
76
+ dividing by 10 ** 18).
77
+
78
+ Parameters
79
+ ----------
80
+ vals : list[int]
81
+ Values to be scaled down
82
+ decimals : int
83
+ Number of decimal places to scale down by
84
+ """
85
+
86
+ return [to_unit_amount(val, decimals) for val in vals]
87
+
88
+
89
+ def to_adjusted_encoding_for_negative_val(val: int):
90
+ """
91
+ Adjust encoding for a potentially negative value
92
+
93
+ Parameters
94
+ ----------
95
+ vals : int
96
+ Values to be adjusted
97
+ """
98
+
99
+ return 16**32 + abs(val) if val < 0 else val
100
+
101
+
102
+ def to_adjusted_encoding_for_negative_val_list(vals: list[int]):
103
+ """
104
+ Adjust encoding for list of potentially negative values
105
+
106
+ Parameters
107
+ ----------
108
+ vals : list[int]
109
+ list of values to be adjusted
110
+ """
111
+
112
+ return [to_adjusted_encoding_for_negative_val(val) for val in vals]
113
+
114
+
115
+ def from_adjusted_encoding_for_negative_val(val: int):
116
+ """
117
+ Adjust encoding for a potentially negative value
118
+
119
+ Parameters
120
+ ----------
121
+ vals : int
122
+ Values to be adjusted
123
+ """
124
+
125
+ return val if val < 16**32 else -(val - 16**32)
126
+
127
+
128
+ def get_parsed_tx_log_entry(tx_log_entry: dict):
129
+ """
130
+ Parse an individual transaction log entry into a format
131
+ suitable for the Auditor. This format was selected so
132
+ that the Auditor can be reused as-is by the integration
133
+ tests with no changes needed.
134
+
135
+ Parameters
136
+ ----------
137
+ tx_log_entry : dict
138
+ Transaction log message
139
+ """
140
+ return {
141
+ "event": tx_log_entry["event"],
142
+ "requestIndex": int(tx_log_entry["requestIndex"]),
143
+ "epochId": int(tx_log_entry["epochId"]),
144
+ "txOrdinal": int(tx_log_entry["ordinal"]),
145
+ "batchId": int(tx_log_entry["batchId"]),
146
+ "timeValue": int(tx_log_entry["time"]["value"]),
147
+ "timestamp": int(tx_log_entry["time"]["timestamp"]),
148
+ "stateRootHash": tx_log_entry["stateRootHash"],
149
+ }
150
+
151
+
152
+ def calculate_max_collateral(
153
+ collateral_tranches: list[tuple[Decimal, Decimal]], ddx_balance: Decimal
154
+ ) -> Decimal:
155
+ limit = Decimal("0")
156
+ for ddx_threshold, max_collateral in collateral_tranches:
157
+ limit = max_collateral
158
+ if ddx_balance < ddx_threshold:
159
+ break
160
+ return limit
161
+
162
+
163
+ class ComplexOutputEncoder(json.JSONEncoder):
164
+ """
165
+ Custom JSON-encoder for serializing objects
166
+ """
167
+
168
+ def __init__(self, **kwargs):
169
+ super(ComplexOutputEncoder, self).__init__(**kwargs)
170
+
171
+ def default(self, o):
172
+ if hasattr(o, "repr_json"):
173
+ return o.repr_json()
174
+ elif type(o) == Decimal:
175
+ return PyDecimal(str(o))
176
+ return json.JSONEncoder.default(self, o)
ddx/config.py ADDED
@@ -0,0 +1,17 @@
1
+ import os
2
+
3
+ # from ddx._rust import common
4
+ from ddx._rust.common import reinit_operator_context
5
+
6
+ # FIXME: might need to change these environment variables to `DDX_CONTRACT_DEPLOYMENT` for better convention
7
+
8
+
9
+ def load_mainnet():
10
+ os.environ["CONTRACT_DEPLOYMENT"] = "derivadex"
11
+ # common.reinit_operator_context()
12
+ reinit_operator_context()
13
+
14
+
15
+ def load_testnet():
16
+ os.environ["CONTRACT_DEPLOYMENT"] = "testnet"
17
+ reinit_operator_context()