afp-sdk 0.3.0__py3-none-any.whl → 0.5.0__py3-none-any.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.
- afp/__init__.py +12 -7
- afp/afp.py +210 -0
- afp/api/admin.py +1 -14
- afp/api/base.py +82 -29
- afp/api/{clearing.py → margin_account.py} +172 -104
- afp/api/{builder.py → product.py} +103 -41
- afp/api/trading.py +18 -31
- afp/auth.py +66 -0
- afp/bindings/bankruptcy_facet.py +36 -0
- afp/bindings/clearing_facet.py +28 -0
- afp/bindings/facade.py +25 -13
- afp/bindings/margin_account.py +108 -0
- afp/bindings/product_registry.py +1 -48
- afp/bindings/system_viewer.py +1 -7
- afp/config.py +22 -36
- afp/constants.py +52 -0
- afp/decorators.py +3 -1
- afp/exceptions.py +7 -3
- afp/exchange.py +15 -7
- afp/{signing.py → hashing.py} +4 -12
- afp/schemas.py +9 -1
- afp/validators.py +1 -0
- {afp_sdk-0.3.0.dist-info → afp_sdk-0.5.0.dist-info}/METADATA +54 -50
- afp_sdk-0.5.0.dist-info/RECORD +37 -0
- {afp_sdk-0.3.0.dist-info → afp_sdk-0.5.0.dist-info}/WHEEL +1 -1
- afp/api/liquidation.py +0 -167
- afp_sdk-0.3.0.dist-info/RECORD +0 -35
- {afp_sdk-0.3.0.dist-info → afp_sdk-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,31 +6,27 @@ from eth_typing.evm import ChecksumAddress
|
|
|
6
6
|
from hexbytes import HexBytes
|
|
7
7
|
from web3 import Web3
|
|
8
8
|
|
|
9
|
-
from .. import
|
|
9
|
+
from .. import constants, hashing, validators
|
|
10
10
|
from ..bindings import (
|
|
11
|
+
ClearingDiamond,
|
|
11
12
|
OracleSpecification,
|
|
12
|
-
Product,
|
|
13
|
+
Product as OnChainProduct,
|
|
13
14
|
ProductMetadata,
|
|
14
15
|
ProductRegistry,
|
|
15
16
|
)
|
|
16
17
|
from ..bindings.erc20 import ERC20
|
|
18
|
+
from ..bindings.facade import CLEARING_DIAMOND_ABI
|
|
17
19
|
from ..bindings.product_registry import ABI as PRODUCT_REGISTRY_ABI
|
|
18
20
|
from ..decorators import convert_web3_error
|
|
19
21
|
from ..exceptions import NotFoundError
|
|
20
|
-
from ..schemas import ProductSpecification
|
|
22
|
+
from ..schemas import ProductSpecification, Transaction
|
|
21
23
|
from .base import ClearingSystemAPI
|
|
22
24
|
|
|
23
25
|
|
|
24
|
-
class
|
|
25
|
-
"""API for
|
|
26
|
+
class Product(ClearingSystemAPI):
|
|
27
|
+
"""API for managing products."""
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
----------
|
|
29
|
-
private_key : str
|
|
30
|
-
The private key of the blockchain account that submits the product.
|
|
31
|
-
autonity_rpc_url : str
|
|
32
|
-
The URL of a JSON-RPC provider for Autonity. (HTTPS only.)
|
|
33
|
-
"""
|
|
29
|
+
### Factories ###
|
|
34
30
|
|
|
35
31
|
@convert_web3_error()
|
|
36
32
|
def create_product(
|
|
@@ -38,7 +34,6 @@ class Builder(ClearingSystemAPI):
|
|
|
38
34
|
*,
|
|
39
35
|
symbol: str,
|
|
40
36
|
description: str,
|
|
41
|
-
oracle_address: str,
|
|
42
37
|
fsv_decimals: int,
|
|
43
38
|
fsp_alpha: Decimal,
|
|
44
39
|
fsp_beta: Decimal,
|
|
@@ -50,10 +45,10 @@ class Builder(ClearingSystemAPI):
|
|
|
50
45
|
unit_value: Decimal,
|
|
51
46
|
initial_margin_requirement: Decimal,
|
|
52
47
|
maintenance_margin_requirement: Decimal,
|
|
53
|
-
offer_price_buffer: Decimal,
|
|
54
48
|
auction_bounty: Decimal,
|
|
55
49
|
tradeout_interval: int,
|
|
56
50
|
extended_metadata: str,
|
|
51
|
+
oracle_address: str | None = None,
|
|
57
52
|
) -> ProductSpecification:
|
|
58
53
|
"""Creates a product specification with the given product data.
|
|
59
54
|
|
|
@@ -64,7 +59,6 @@ class Builder(ClearingSystemAPI):
|
|
|
64
59
|
----------
|
|
65
60
|
symbol : str
|
|
66
61
|
description : str
|
|
67
|
-
oracle_address: str
|
|
68
62
|
fsv_decimals: int
|
|
69
63
|
fsp_alpha: Decimal
|
|
70
64
|
fsp_beta: int
|
|
@@ -76,29 +70,33 @@ class Builder(ClearingSystemAPI):
|
|
|
76
70
|
unit_value : Decimal
|
|
77
71
|
initial_margin_requirement : Decimal
|
|
78
72
|
maintenance_margin_requirement : Decimal
|
|
79
|
-
offer_price_buffer : Decimal
|
|
80
73
|
auction_bounty : Decimal
|
|
81
74
|
tradeout_interval : int
|
|
82
75
|
extended_metadata : str
|
|
76
|
+
oracle_address: str, optional
|
|
83
77
|
|
|
84
78
|
Returns
|
|
85
79
|
-------
|
|
86
80
|
afp.schemas.ProductSpecification
|
|
87
81
|
"""
|
|
88
|
-
|
|
82
|
+
if oracle_address is None:
|
|
83
|
+
oracle_address = self._config.oracle_provider_address
|
|
89
84
|
|
|
90
|
-
|
|
91
|
-
price_quotation = erc20_contract.symbol()
|
|
92
|
-
|
|
93
|
-
if not price_quotation:
|
|
85
|
+
if len(self._w3.eth.get_code(Web3.to_checksum_address(collateral_asset))) == 0:
|
|
94
86
|
raise NotFoundError(f"No ERC20 token found at address {collateral_asset}")
|
|
95
|
-
|
|
96
87
|
if len(self._w3.eth.get_code(Web3.to_checksum_address(oracle_address))) == 0:
|
|
97
88
|
raise NotFoundError(f"No contract found at oracle address {oracle_address}")
|
|
98
89
|
|
|
90
|
+
erc20_contract = ERC20(self._w3, Web3.to_checksum_address(collateral_asset))
|
|
91
|
+
price_quotation = erc20_contract.symbol()
|
|
92
|
+
|
|
93
|
+
product_id = Web3.to_hex(
|
|
94
|
+
hashing.generate_product_id(self._authenticator.address, symbol)
|
|
95
|
+
)
|
|
96
|
+
|
|
99
97
|
return ProductSpecification(
|
|
100
98
|
id=product_id,
|
|
101
|
-
builder_id=self.
|
|
99
|
+
builder_id=self._authenticator.address,
|
|
102
100
|
symbol=symbol,
|
|
103
101
|
description=description,
|
|
104
102
|
oracle_address=oracle_address,
|
|
@@ -114,14 +112,15 @@ class Builder(ClearingSystemAPI):
|
|
|
114
112
|
unit_value=unit_value,
|
|
115
113
|
initial_margin_requirement=initial_margin_requirement,
|
|
116
114
|
maintenance_margin_requirement=maintenance_margin_requirement,
|
|
117
|
-
offer_price_buffer=offer_price_buffer,
|
|
118
115
|
auction_bounty=auction_bounty,
|
|
119
116
|
tradeout_interval=tradeout_interval,
|
|
120
117
|
extended_metadata=extended_metadata,
|
|
121
118
|
)
|
|
122
119
|
|
|
120
|
+
### Transactions ###
|
|
121
|
+
|
|
123
122
|
@convert_web3_error(PRODUCT_REGISTRY_ABI)
|
|
124
|
-
def register_product(self, product: ProductSpecification) ->
|
|
123
|
+
def register_product(self, product: ProductSpecification) -> Transaction:
|
|
125
124
|
"""Submits a product specification to the clearing system.
|
|
126
125
|
|
|
127
126
|
Parameters
|
|
@@ -130,20 +129,56 @@ class Builder(ClearingSystemAPI):
|
|
|
130
129
|
|
|
131
130
|
Returns
|
|
132
131
|
-------
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
afp.schemas.Transaction
|
|
133
|
+
Transaction parameters.
|
|
135
134
|
"""
|
|
136
135
|
erc20_contract = ERC20(
|
|
137
136
|
self._w3, cast(ChecksumAddress, product.collateral_asset)
|
|
138
137
|
)
|
|
139
138
|
decimals = erc20_contract.decimals()
|
|
140
139
|
|
|
141
|
-
product_registry_contract = ProductRegistry(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
140
|
+
product_registry_contract = ProductRegistry(
|
|
141
|
+
self._w3, self._config.product_registry_address
|
|
142
|
+
)
|
|
143
|
+
return self._transact(
|
|
144
|
+
product_registry_contract.register(
|
|
145
|
+
self._convert_product_specification(product, decimals)
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
@convert_web3_error(CLEARING_DIAMOND_ABI)
|
|
150
|
+
def initiate_final_settlement(
|
|
151
|
+
self, product_id: str, accounts: list[str]
|
|
152
|
+
) -> Transaction:
|
|
153
|
+
"""Initiate final settlement (closeout) process for the specified accounts.
|
|
154
|
+
|
|
155
|
+
The product must be in Final Settlement state. The accounts must hold non-zero
|
|
156
|
+
positions in the product that offset each other (i.e. the sum of their position
|
|
157
|
+
sizes is 0.)
|
|
158
|
+
|
|
159
|
+
Parameters
|
|
160
|
+
----------
|
|
161
|
+
product_id : str
|
|
162
|
+
The ID of the product.
|
|
163
|
+
accounts : list of str
|
|
164
|
+
List of margin account IDs to initiate settlement for.
|
|
165
|
+
|
|
166
|
+
Returns
|
|
167
|
+
-------
|
|
168
|
+
afp.schemas.Transaction
|
|
169
|
+
Transaction parameters.
|
|
170
|
+
"""
|
|
171
|
+
product_id = validators.validate_hexstr32(product_id)
|
|
172
|
+
addresses = [validators.validate_address(account) for account in accounts]
|
|
173
|
+
|
|
174
|
+
clearing_contract = ClearingDiamond(
|
|
175
|
+
self._w3, self._config.clearing_diamond_address
|
|
176
|
+
)
|
|
177
|
+
return self._transact(
|
|
178
|
+
clearing_contract.initiate_final_settlement(HexBytes(product_id), addresses)
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
### Views ###
|
|
147
182
|
|
|
148
183
|
@convert_web3_error(PRODUCT_REGISTRY_ABI)
|
|
149
184
|
def product_state(self, product_id: str) -> str:
|
|
@@ -159,15 +194,43 @@ class Builder(ClearingSystemAPI):
|
|
|
159
194
|
str
|
|
160
195
|
"""
|
|
161
196
|
product_id = validators.validate_hexstr32(product_id)
|
|
162
|
-
product_registry_contract = ProductRegistry(
|
|
197
|
+
product_registry_contract = ProductRegistry(
|
|
198
|
+
self._w3, self._config.product_registry_address
|
|
199
|
+
)
|
|
163
200
|
state = product_registry_contract.state(HexBytes(product_id))
|
|
164
201
|
return state.name
|
|
165
202
|
|
|
203
|
+
@convert_web3_error(PRODUCT_REGISTRY_ABI)
|
|
204
|
+
def collateral_asset(self, product_id: str) -> str:
|
|
205
|
+
"""Returns the collateral asset of a product.
|
|
206
|
+
|
|
207
|
+
Parameters
|
|
208
|
+
----------
|
|
209
|
+
product_id : str
|
|
210
|
+
The ID of the product.
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
str
|
|
215
|
+
"""
|
|
216
|
+
product_id = validators.validate_hexstr32(product_id)
|
|
217
|
+
product_registry_contract = ProductRegistry(
|
|
218
|
+
self._w3, self._config.product_registry_address
|
|
219
|
+
)
|
|
220
|
+
collateral_asset = product_registry_contract.collateral_asset(
|
|
221
|
+
HexBytes(product_id)
|
|
222
|
+
)
|
|
223
|
+
if Web3.to_int(hexstr=collateral_asset) == 0:
|
|
224
|
+
raise NotFoundError("Product not found in the product registry")
|
|
225
|
+
return collateral_asset
|
|
226
|
+
|
|
227
|
+
### Internal helpers ###
|
|
228
|
+
|
|
166
229
|
@staticmethod
|
|
167
230
|
def _convert_product_specification(
|
|
168
231
|
product: ProductSpecification, decimals: int
|
|
169
|
-
) ->
|
|
170
|
-
return
|
|
232
|
+
) -> OnChainProduct:
|
|
233
|
+
return OnChainProduct(
|
|
171
234
|
metadata=ProductMetadata(
|
|
172
235
|
builder=cast(ChecksumAddress, product.builder_id),
|
|
173
236
|
symbol=product.symbol,
|
|
@@ -176,7 +239,7 @@ class Builder(ClearingSystemAPI):
|
|
|
176
239
|
oracle_spec=OracleSpecification(
|
|
177
240
|
oracle_address=cast(ChecksumAddress, product.oracle_address),
|
|
178
241
|
fsv_decimals=product.fsv_decimals,
|
|
179
|
-
fsp_alpha=int(product.fsp_alpha *
|
|
242
|
+
fsp_alpha=int(product.fsp_alpha * constants.FULL_PRECISION_MULTIPLIER),
|
|
180
243
|
fsp_beta=int(product.fsp_beta * 10**product.fsv_decimals),
|
|
181
244
|
fsv_calldata=HexBytes(product.fsv_calldata),
|
|
182
245
|
),
|
|
@@ -189,13 +252,12 @@ class Builder(ClearingSystemAPI):
|
|
|
189
252
|
tick_size=product.tick_size,
|
|
190
253
|
unit_value=int(product.unit_value * 10**decimals),
|
|
191
254
|
initial_margin_requirement=int(
|
|
192
|
-
product.initial_margin_requirement *
|
|
255
|
+
product.initial_margin_requirement * constants.RATE_MULTIPLIER
|
|
193
256
|
),
|
|
194
257
|
maintenance_margin_requirement=int(
|
|
195
|
-
product.maintenance_margin_requirement *
|
|
258
|
+
product.maintenance_margin_requirement * constants.RATE_MULTIPLIER
|
|
196
259
|
),
|
|
197
|
-
|
|
198
|
-
auction_bounty=int(product.auction_bounty * config.RATE_MULTIPLIER),
|
|
260
|
+
auction_bounty=int(product.auction_bounty * constants.RATE_MULTIPLIER),
|
|
199
261
|
tradeout_interval=product.tradeout_interval,
|
|
200
262
|
extended_metadata=product.extended_metadata,
|
|
201
263
|
)
|
afp/api/trading.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import Generator
|
|
|
5
5
|
|
|
6
6
|
from web3 import Web3
|
|
7
7
|
|
|
8
|
-
from .. import
|
|
8
|
+
from .. import hashing, validators
|
|
9
9
|
from ..decorators import refresh_token_on_expiry
|
|
10
10
|
from ..enums import OrderType
|
|
11
11
|
from ..schemas import (
|
|
@@ -25,20 +25,7 @@ from .base import ExchangeAPI
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class Trading(ExchangeAPI):
|
|
28
|
-
"""API for trading in the AutEx exchange.
|
|
29
|
-
|
|
30
|
-
Authenticates with the exchange on creation.
|
|
31
|
-
|
|
32
|
-
Parameters
|
|
33
|
-
----------
|
|
34
|
-
private_key : str
|
|
35
|
-
The private key of the account that submits intents to the exchange.
|
|
36
|
-
|
|
37
|
-
Raises
|
|
38
|
-
------
|
|
39
|
-
afp.exceptions.AuthenticationError
|
|
40
|
-
If the exchange rejects the login attempt.
|
|
41
|
-
"""
|
|
28
|
+
"""API for trading in the AutEx exchange."""
|
|
42
29
|
|
|
43
30
|
@staticmethod
|
|
44
31
|
def _generate_nonce() -> int:
|
|
@@ -89,7 +76,7 @@ class Trading(ExchangeAPI):
|
|
|
89
76
|
margin_account_id = (
|
|
90
77
|
validators.validate_address(margin_account_id)
|
|
91
78
|
if margin_account_id is not None
|
|
92
|
-
else self.
|
|
79
|
+
else self._authenticator.address
|
|
93
80
|
)
|
|
94
81
|
|
|
95
82
|
intent_data = IntentData(
|
|
@@ -104,17 +91,17 @@ class Trading(ExchangeAPI):
|
|
|
104
91
|
good_until_time=good_until_time,
|
|
105
92
|
nonce=self._generate_nonce(),
|
|
106
93
|
)
|
|
107
|
-
intent_hash =
|
|
94
|
+
intent_hash = hashing.generate_intent_hash(
|
|
108
95
|
intent_data=intent_data,
|
|
109
96
|
margin_account_id=margin_account_id,
|
|
110
|
-
intent_account_id=self.
|
|
97
|
+
intent_account_id=self._authenticator.address,
|
|
111
98
|
tick_size=product.tick_size,
|
|
112
99
|
)
|
|
113
|
-
signature =
|
|
100
|
+
signature = self._authenticator.sign_message(intent_hash)
|
|
114
101
|
return Intent(
|
|
115
102
|
hash=Web3.to_hex(intent_hash),
|
|
116
103
|
margin_account_id=margin_account_id,
|
|
117
|
-
intent_account_id=self.
|
|
104
|
+
intent_account_id=self._authenticator.address,
|
|
118
105
|
signature=Web3.to_hex(signature),
|
|
119
106
|
data=intent_data,
|
|
120
107
|
)
|
|
@@ -160,12 +147,12 @@ class Trading(ExchangeAPI):
|
|
|
160
147
|
If the exchange rejects the cancellation.
|
|
161
148
|
"""
|
|
162
149
|
nonce = self._generate_nonce()
|
|
163
|
-
cancellation_hash =
|
|
164
|
-
signature =
|
|
150
|
+
cancellation_hash = hashing.generate_order_cancellation_hash(nonce, intent_hash)
|
|
151
|
+
signature = self._authenticator.sign_message(cancellation_hash)
|
|
165
152
|
cancellation_data = OrderCancellationData(
|
|
166
153
|
intent_hash=intent_hash,
|
|
167
154
|
nonce=nonce,
|
|
168
|
-
intent_account_id=self.
|
|
155
|
+
intent_account_id=self._authenticator.address,
|
|
169
156
|
signature=Web3.to_hex(signature),
|
|
170
157
|
)
|
|
171
158
|
submission = OrderSubmission(
|
|
@@ -174,7 +161,6 @@ class Trading(ExchangeAPI):
|
|
|
174
161
|
)
|
|
175
162
|
return self._exchange.submit_order(submission)
|
|
176
163
|
|
|
177
|
-
@refresh_token_on_expiry
|
|
178
164
|
def products(self) -> list[ExchangeProduct]:
|
|
179
165
|
"""Retrieves the products approved for trading on the exchange.
|
|
180
166
|
|
|
@@ -184,7 +170,6 @@ class Trading(ExchangeAPI):
|
|
|
184
170
|
"""
|
|
185
171
|
return self._exchange.get_approved_products()
|
|
186
172
|
|
|
187
|
-
@refresh_token_on_expiry
|
|
188
173
|
def product(self, product_id: str) -> ExchangeProduct:
|
|
189
174
|
"""Retrieves a product for trading by its ID.
|
|
190
175
|
|
|
@@ -226,15 +211,19 @@ class Trading(ExchangeAPI):
|
|
|
226
211
|
return self._exchange.get_order_by_id(value)
|
|
227
212
|
|
|
228
213
|
@refresh_token_on_expiry
|
|
229
|
-
def open_orders(self) -> list[Order]:
|
|
214
|
+
def open_orders(self, product_id: str | None = None) -> list[Order]:
|
|
230
215
|
"""Retrieves all open and partially filled limit orders that have been submitted
|
|
231
216
|
by the authenticated account.
|
|
232
217
|
|
|
218
|
+
Parameters
|
|
219
|
+
----------
|
|
220
|
+
product_id : str, optional
|
|
221
|
+
|
|
233
222
|
Returns
|
|
234
223
|
-------
|
|
235
224
|
list of afp.schemas.Order
|
|
236
225
|
"""
|
|
237
|
-
return self._exchange.get_open_orders()
|
|
226
|
+
return self._exchange.get_open_orders(product_id)
|
|
238
227
|
|
|
239
228
|
@refresh_token_on_expiry
|
|
240
229
|
def order_fills(
|
|
@@ -262,7 +251,7 @@ class Trading(ExchangeAPI):
|
|
|
262
251
|
list of afp.schemas.OrderFill
|
|
263
252
|
"""
|
|
264
253
|
filter = OrderFillFilter(
|
|
265
|
-
intent_account_id=self.
|
|
254
|
+
intent_account_id=self._authenticator.address,
|
|
266
255
|
product_id=product_id,
|
|
267
256
|
margin_account_id=margin_account_id,
|
|
268
257
|
intent_hash=intent_hash,
|
|
@@ -298,7 +287,7 @@ class Trading(ExchangeAPI):
|
|
|
298
287
|
afp.schemas.OrderFill
|
|
299
288
|
"""
|
|
300
289
|
filter = OrderFillFilter(
|
|
301
|
-
intent_account_id=self.
|
|
290
|
+
intent_account_id=self._authenticator.address,
|
|
302
291
|
product_id=product_id,
|
|
303
292
|
margin_account_id=margin_account_id,
|
|
304
293
|
intent_hash=intent_hash,
|
|
@@ -308,7 +297,6 @@ class Trading(ExchangeAPI):
|
|
|
308
297
|
)
|
|
309
298
|
yield from self._exchange.iter_order_fills(filter)
|
|
310
299
|
|
|
311
|
-
@refresh_token_on_expiry
|
|
312
300
|
def market_depth(self, product_id: str) -> MarketDepthData:
|
|
313
301
|
"""Retrieves the depth of market for the given product.
|
|
314
302
|
|
|
@@ -328,7 +316,6 @@ class Trading(ExchangeAPI):
|
|
|
328
316
|
value = validators.validate_hexstr32(product_id)
|
|
329
317
|
return self._exchange.get_market_depth_data(value)
|
|
330
318
|
|
|
331
|
-
@refresh_token_on_expiry
|
|
332
319
|
def iter_market_depth(
|
|
333
320
|
self, product_id: str
|
|
334
321
|
) -> Generator[MarketDepthData, None, None]:
|
afp/auth.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Protocol, cast
|
|
4
|
+
|
|
5
|
+
from eth_account.account import Account
|
|
6
|
+
from eth_account.datastructures import SignedTransaction
|
|
7
|
+
from eth_account.messages import encode_defunct
|
|
8
|
+
from eth_account.signers.local import LocalAccount
|
|
9
|
+
from eth_account.types import TransactionDictType
|
|
10
|
+
from eth_typing.evm import ChecksumAddress
|
|
11
|
+
from hexbytes import HexBytes
|
|
12
|
+
from web3.types import TxParams
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Authenticator(Protocol):
|
|
16
|
+
address: ChecksumAddress
|
|
17
|
+
|
|
18
|
+
def sign_message(self, message: bytes) -> HexBytes: ...
|
|
19
|
+
|
|
20
|
+
def sign_transaction(self, params: TxParams) -> SignedTransaction: ...
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class PrivateKeyAuthenticator(Authenticator):
|
|
24
|
+
"""Authenticates with a private key specified in a constructor argument.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
private_key: str
|
|
29
|
+
The private key of a blockchain account.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
_account: LocalAccount
|
|
33
|
+
|
|
34
|
+
def __init__(self, private_key: str) -> None:
|
|
35
|
+
self._account = Account.from_key(private_key)
|
|
36
|
+
self.address = self._account.address
|
|
37
|
+
|
|
38
|
+
def sign_message(self, message: bytes) -> HexBytes:
|
|
39
|
+
eip191_message = encode_defunct(message)
|
|
40
|
+
signed_message = self._account.sign_message(eip191_message)
|
|
41
|
+
return signed_message.signature
|
|
42
|
+
|
|
43
|
+
def sign_transaction(self, params: TxParams) -> SignedTransaction:
|
|
44
|
+
return self._account.sign_transaction(cast(TransactionDictType, params))
|
|
45
|
+
|
|
46
|
+
def __repr__(self):
|
|
47
|
+
return f"{self.__class__.__name__}(address='{self.address}')"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class KeyfileAuthenticator(PrivateKeyAuthenticator):
|
|
51
|
+
"""Authenticates with a private key read from an encrypted keyfile.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
keyfile : str
|
|
56
|
+
The path to the keyfile.
|
|
57
|
+
password : str
|
|
58
|
+
The password for decrypting the keyfile.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(self, key_file: str, password: str) -> None:
|
|
62
|
+
with open(os.path.expanduser(key_file), encoding="utf8") as f:
|
|
63
|
+
key_data = json.load(f)
|
|
64
|
+
|
|
65
|
+
private_key = Account.decrypt(key_data, password=password)
|
|
66
|
+
super().__init__(private_key.to_0x_hex())
|
afp/bindings/bankruptcy_facet.py
CHANGED
|
@@ -56,6 +56,11 @@ class BankruptcyFacet:
|
|
|
56
56
|
abi=ABI,
|
|
57
57
|
)
|
|
58
58
|
|
|
59
|
+
@property
|
|
60
|
+
def LossMutualized(self) -> contract.ContractEvent:
|
|
61
|
+
"""Binding for `event LossMutualized` on the BankruptcyFacet contract."""
|
|
62
|
+
return self._contract.events.LossMutualized
|
|
63
|
+
|
|
59
64
|
def last_traded_timestamp(
|
|
60
65
|
self,
|
|
61
66
|
product_id: hexbytes.HexBytes,
|
|
@@ -219,6 +224,37 @@ ABI = typing.cast(
|
|
|
219
224
|
"type": "error",
|
|
220
225
|
},
|
|
221
226
|
{"inputs": [], "name": "QueueIsEmpty", "type": "error"},
|
|
227
|
+
{
|
|
228
|
+
"anonymous": False,
|
|
229
|
+
"inputs": [
|
|
230
|
+
{
|
|
231
|
+
"indexed": True,
|
|
232
|
+
"internalType": "address",
|
|
233
|
+
"name": "bankruptAccount",
|
|
234
|
+
"type": "address",
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"indexed": True,
|
|
238
|
+
"internalType": "address",
|
|
239
|
+
"name": "collateralToken",
|
|
240
|
+
"type": "address",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"indexed": False,
|
|
244
|
+
"internalType": "address",
|
|
245
|
+
"name": "caller",
|
|
246
|
+
"type": "address",
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"indexed": False,
|
|
250
|
+
"internalType": "int256",
|
|
251
|
+
"name": "lossAmount",
|
|
252
|
+
"type": "int256",
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
"name": "LossMutualized",
|
|
256
|
+
"type": "event",
|
|
257
|
+
},
|
|
222
258
|
{
|
|
223
259
|
"inputs": [
|
|
224
260
|
{"internalType": "bytes32", "name": "productId", "type": "bytes32"},
|
afp/bindings/clearing_facet.py
CHANGED
|
@@ -423,6 +423,25 @@ class ClearingFacet:
|
|
|
423
423
|
),
|
|
424
424
|
)
|
|
425
425
|
|
|
426
|
+
def set_treasury(
|
|
427
|
+
self,
|
|
428
|
+
new_treasury: eth_typing.ChecksumAddress,
|
|
429
|
+
) -> contract.ContractFunction:
|
|
430
|
+
"""Binding for `setTreasury` on the ClearingFacet contract.
|
|
431
|
+
|
|
432
|
+
Parameters
|
|
433
|
+
----------
|
|
434
|
+
new_treasury : eth_typing.ChecksumAddress
|
|
435
|
+
|
|
436
|
+
Returns
|
|
437
|
+
-------
|
|
438
|
+
web3.contract.contract.ContractFunction
|
|
439
|
+
A contract function instance to be sent in a transaction.
|
|
440
|
+
"""
|
|
441
|
+
return self._contract.functions.setTreasury(
|
|
442
|
+
new_treasury,
|
|
443
|
+
)
|
|
444
|
+
|
|
426
445
|
def version(
|
|
427
446
|
self,
|
|
428
447
|
) -> str:
|
|
@@ -1003,6 +1022,15 @@ ABI = typing.cast(
|
|
|
1003
1022
|
"stateMutability": "nonpayable",
|
|
1004
1023
|
"type": "function",
|
|
1005
1024
|
},
|
|
1025
|
+
{
|
|
1026
|
+
"inputs": [
|
|
1027
|
+
{"internalType": "address", "name": "newTreasury", "type": "address"}
|
|
1028
|
+
],
|
|
1029
|
+
"name": "setTreasury",
|
|
1030
|
+
"outputs": [],
|
|
1031
|
+
"stateMutability": "nonpayable",
|
|
1032
|
+
"type": "function",
|
|
1033
|
+
},
|
|
1006
1034
|
{
|
|
1007
1035
|
"inputs": [],
|
|
1008
1036
|
"name": "version",
|
afp/bindings/facade.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from itertools import chain
|
|
2
2
|
|
|
3
|
+
from eth_typing.evm import ChecksumAddress
|
|
4
|
+
|
|
3
5
|
from web3 import Web3
|
|
4
6
|
|
|
5
|
-
from .. import config
|
|
6
7
|
from . import (
|
|
7
8
|
auctioneer_facet,
|
|
8
9
|
bankruptcy_facet,
|
|
@@ -14,6 +15,7 @@ from . import (
|
|
|
14
15
|
product_registry,
|
|
15
16
|
system_viewer,
|
|
16
17
|
)
|
|
18
|
+
from ..constants import defaults
|
|
17
19
|
|
|
18
20
|
# In order to include a facet in the ClearingDiamond facade:
|
|
19
21
|
# 1. Add its ABI to CLEARING_DIAMOND_ABI
|
|
@@ -46,10 +48,10 @@ class ClearingDiamond(
|
|
|
46
48
|
w3 : web3.Web3
|
|
47
49
|
"""
|
|
48
50
|
|
|
49
|
-
def __init__(
|
|
50
|
-
self
|
|
51
|
-
|
|
52
|
-
)
|
|
51
|
+
def __init__(
|
|
52
|
+
self, w3: Web3, address: ChecksumAddress = defaults.CLEARING_DIAMOND_ADDRESS
|
|
53
|
+
):
|
|
54
|
+
self._contract = w3.eth.contract(address=address, abi=CLEARING_DIAMOND_ABI)
|
|
53
55
|
|
|
54
56
|
|
|
55
57
|
class MarginAccountRegistry(margin_account_registry.MarginAccountRegistry):
|
|
@@ -60,8 +62,12 @@ class MarginAccountRegistry(margin_account_registry.MarginAccountRegistry):
|
|
|
60
62
|
w3 : web3.Web3
|
|
61
63
|
"""
|
|
62
64
|
|
|
63
|
-
def __init__(
|
|
64
|
-
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
w3: Web3,
|
|
68
|
+
address: ChecksumAddress = defaults.MARGIN_ACCOUNT_REGISTRY_ADDRESS,
|
|
69
|
+
):
|
|
70
|
+
super().__init__(w3, address)
|
|
65
71
|
|
|
66
72
|
|
|
67
73
|
class OracleProvider(oracle_provider.OracleProvider):
|
|
@@ -72,8 +78,10 @@ class OracleProvider(oracle_provider.OracleProvider):
|
|
|
72
78
|
w3 : web3.Web3
|
|
73
79
|
"""
|
|
74
80
|
|
|
75
|
-
def __init__(
|
|
76
|
-
|
|
81
|
+
def __init__(
|
|
82
|
+
self, w3: Web3, address: ChecksumAddress = defaults.ORACLE_PROVIDER_ADDRESS
|
|
83
|
+
):
|
|
84
|
+
super().__init__(w3, address)
|
|
77
85
|
|
|
78
86
|
|
|
79
87
|
class ProductRegistry(product_registry.ProductRegistry):
|
|
@@ -84,8 +92,10 @@ class ProductRegistry(product_registry.ProductRegistry):
|
|
|
84
92
|
w3 : web3.Web3
|
|
85
93
|
"""
|
|
86
94
|
|
|
87
|
-
def __init__(
|
|
88
|
-
|
|
95
|
+
def __init__(
|
|
96
|
+
self, w3: Web3, address: ChecksumAddress = defaults.PRODUCT_REGISTRY_ADDRESS
|
|
97
|
+
):
|
|
98
|
+
super().__init__(w3, address)
|
|
89
99
|
|
|
90
100
|
|
|
91
101
|
class SystemViewer(system_viewer.SystemViewer):
|
|
@@ -96,5 +106,7 @@ class SystemViewer(system_viewer.SystemViewer):
|
|
|
96
106
|
w3 : web3.Web3
|
|
97
107
|
"""
|
|
98
108
|
|
|
99
|
-
def __init__(
|
|
100
|
-
|
|
109
|
+
def __init__(
|
|
110
|
+
self, w3: Web3, address: ChecksumAddress = defaults.SYSTEM_VIEWER_ADDRESS
|
|
111
|
+
):
|
|
112
|
+
super().__init__(w3, address)
|