nado-protocol 0.1.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.
- nado_protocol/__init__.py +0 -0
- nado_protocol/client/__init__.py +200 -0
- nado_protocol/client/apis/__init__.py +26 -0
- nado_protocol/client/apis/base.py +42 -0
- nado_protocol/client/apis/market/__init__.py +23 -0
- nado_protocol/client/apis/market/execute.py +192 -0
- nado_protocol/client/apis/market/query.py +310 -0
- nado_protocol/client/apis/perp/__init__.py +18 -0
- nado_protocol/client/apis/perp/query.py +30 -0
- nado_protocol/client/apis/rewards/__init__.py +6 -0
- nado_protocol/client/apis/rewards/execute.py +131 -0
- nado_protocol/client/apis/rewards/query.py +12 -0
- nado_protocol/client/apis/spot/__init__.py +23 -0
- nado_protocol/client/apis/spot/base.py +32 -0
- nado_protocol/client/apis/spot/execute.py +117 -0
- nado_protocol/client/apis/spot/query.py +79 -0
- nado_protocol/client/apis/subaccount/__init__.py +24 -0
- nado_protocol/client/apis/subaccount/execute.py +54 -0
- nado_protocol/client/apis/subaccount/query.py +145 -0
- nado_protocol/client/context.py +90 -0
- nado_protocol/contracts/__init__.py +377 -0
- nado_protocol/contracts/abis/Endpoint.json +636 -0
- nado_protocol/contracts/abis/FQuerier.json +1909 -0
- nado_protocol/contracts/abis/IClearinghouse.json +876 -0
- nado_protocol/contracts/abis/IERC20.json +185 -0
- nado_protocol/contracts/abis/IEndpoint.json +250 -0
- nado_protocol/contracts/abis/IFoundationRewardsAirdrop.json +76 -0
- nado_protocol/contracts/abis/IOffchainBook.json +536 -0
- nado_protocol/contracts/abis/IPerpEngine.json +931 -0
- nado_protocol/contracts/abis/IProductEngine.json +352 -0
- nado_protocol/contracts/abis/ISpotEngine.json +813 -0
- nado_protocol/contracts/abis/IStaking.json +288 -0
- nado_protocol/contracts/abis/IVrtxAirdrop.json +138 -0
- nado_protocol/contracts/abis/MockERC20.json +311 -0
- nado_protocol/contracts/deployments/deployment.test.json +18 -0
- nado_protocol/contracts/eip712/__init__.py +16 -0
- nado_protocol/contracts/eip712/domain.py +36 -0
- nado_protocol/contracts/eip712/sign.py +79 -0
- nado_protocol/contracts/eip712/types.py +154 -0
- nado_protocol/contracts/loader.py +55 -0
- nado_protocol/contracts/types.py +141 -0
- nado_protocol/engine_client/__init__.py +35 -0
- nado_protocol/engine_client/execute.py +416 -0
- nado_protocol/engine_client/query.py +481 -0
- nado_protocol/engine_client/types/__init__.py +113 -0
- nado_protocol/engine_client/types/execute.py +680 -0
- nado_protocol/engine_client/types/models.py +247 -0
- nado_protocol/engine_client/types/query.py +516 -0
- nado_protocol/engine_client/types/stream.py +6 -0
- nado_protocol/indexer_client/__init__.py +28 -0
- nado_protocol/indexer_client/query.py +466 -0
- nado_protocol/indexer_client/types/__init__.py +122 -0
- nado_protocol/indexer_client/types/models.py +364 -0
- nado_protocol/indexer_client/types/query.py +819 -0
- nado_protocol/trigger_client/__init__.py +17 -0
- nado_protocol/trigger_client/execute.py +118 -0
- nado_protocol/trigger_client/query.py +61 -0
- nado_protocol/trigger_client/types/__init__.py +7 -0
- nado_protocol/trigger_client/types/execute.py +89 -0
- nado_protocol/trigger_client/types/models.py +44 -0
- nado_protocol/trigger_client/types/query.py +77 -0
- nado_protocol/utils/__init__.py +37 -0
- nado_protocol/utils/backend.py +111 -0
- nado_protocol/utils/bytes32.py +159 -0
- nado_protocol/utils/enum.py +6 -0
- nado_protocol/utils/exceptions.py +58 -0
- nado_protocol/utils/execute.py +403 -0
- nado_protocol/utils/expiration.py +45 -0
- nado_protocol/utils/interest.py +66 -0
- nado_protocol/utils/math.py +67 -0
- nado_protocol/utils/model.py +79 -0
- nado_protocol/utils/nonce.py +33 -0
- nado_protocol/utils/subaccount.py +18 -0
- nado_protocol/utils/time.py +21 -0
- nado_protocol-0.1.0.dist-info/METADATA +157 -0
- nado_protocol-0.1.0.dist-info/RECORD +78 -0
- nado_protocol-0.1.0.dist-info/WHEEL +4 -0
- nado_protocol-0.1.0.dist-info/entry_points.txt +11 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from nado_protocol.client.apis.base import NadoBaseAPI
|
|
3
|
+
from nado_protocol.engine_client.types.query import (
|
|
4
|
+
AllProductsData,
|
|
5
|
+
MarketLiquidityData,
|
|
6
|
+
MarketPriceData,
|
|
7
|
+
MaxLpMintableData,
|
|
8
|
+
MaxOrderSizeData,
|
|
9
|
+
ProductSymbolsData,
|
|
10
|
+
SubaccountOpenOrdersData,
|
|
11
|
+
SubaccountMultiProductsOpenOrdersData,
|
|
12
|
+
QueryMaxOrderSizeParams,
|
|
13
|
+
IsolatedPositionsData,
|
|
14
|
+
)
|
|
15
|
+
from nado_protocol.indexer_client.types.query import (
|
|
16
|
+
IndexerCandlesticksData,
|
|
17
|
+
IndexerCandlesticksParams,
|
|
18
|
+
IndexerFundingRateData,
|
|
19
|
+
IndexerFundingRatesData,
|
|
20
|
+
IndexerHistoricalOrdersData,
|
|
21
|
+
IndexerSubaccountHistoricalOrdersParams,
|
|
22
|
+
IndexerProductSnapshotsData,
|
|
23
|
+
IndexerProductSnapshotsParams,
|
|
24
|
+
IndexerMarketSnapshotsParams,
|
|
25
|
+
IndexerMarketSnapshotsData,
|
|
26
|
+
)
|
|
27
|
+
from nado_protocol.trigger_client.types.query import (
|
|
28
|
+
ListTriggerOrdersParams,
|
|
29
|
+
TriggerQueryResponse,
|
|
30
|
+
)
|
|
31
|
+
from nado_protocol.utils.exceptions import MissingTriggerClient
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class MarketQueryAPI(NadoBaseAPI):
|
|
35
|
+
"""
|
|
36
|
+
The MarketQueryAPI class provides methods to interact with the Nado's market querying APIs.
|
|
37
|
+
|
|
38
|
+
This class provides functionality for querying various details about the market including fetching
|
|
39
|
+
information about order books, fetching historical orders, and retrieving market matches, among others.
|
|
40
|
+
|
|
41
|
+
Attributes:
|
|
42
|
+
context (NadoClientContext): The context that provides connectivity configuration for NadoClient.
|
|
43
|
+
|
|
44
|
+
Note:
|
|
45
|
+
This class should not be instantiated directly, it is designed to be used through a NadoClient instance.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def get_all_engine_markets(self) -> AllProductsData:
|
|
49
|
+
"""
|
|
50
|
+
Retrieves all market states from the off-chain engine.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
AllProductsData: A data class object containing information about all products in the engine.
|
|
54
|
+
"""
|
|
55
|
+
return self.context.engine_client.get_all_products()
|
|
56
|
+
|
|
57
|
+
def get_all_product_symbols(self) -> ProductSymbolsData:
|
|
58
|
+
"""
|
|
59
|
+
Retrieves all product symbols from the off-chain engine
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
ProductSymbolsData: A list of all products with corresponding symbol.
|
|
63
|
+
"""
|
|
64
|
+
return self.context.engine_client.get_product_symbols()
|
|
65
|
+
|
|
66
|
+
def get_market_liquidity(self, product_id: int, depth: int) -> MarketLiquidityData:
|
|
67
|
+
"""
|
|
68
|
+
Retrieves liquidity per price tick from the engine.
|
|
69
|
+
|
|
70
|
+
The engine will skip price levels that have no liquidity,
|
|
71
|
+
so it is not guaranteed that the bids/asks are evenly spaced
|
|
72
|
+
|
|
73
|
+
Parameters:
|
|
74
|
+
product_id (int): The product ID for which liquidity is to be fetched.
|
|
75
|
+
depth (int): The depth of the order book to retrieve liquidity from.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
MarketLiquidityData: A data class object containing liquidity information for the specified product.
|
|
79
|
+
"""
|
|
80
|
+
return self.context.engine_client.get_market_liquidity(product_id, depth)
|
|
81
|
+
|
|
82
|
+
def get_latest_market_price(self, product_id: int) -> MarketPriceData:
|
|
83
|
+
"""
|
|
84
|
+
Retrieves the latest off-chain orderbook price from the engine for a specific product.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
product_id (int): The identifier for the product to retrieve the latest market price.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
MarketPriceData: A data class object containing information about the latest market price for the given product.
|
|
91
|
+
"""
|
|
92
|
+
return self.context.engine_client.get_market_price(product_id)
|
|
93
|
+
|
|
94
|
+
def get_subaccount_open_orders(
|
|
95
|
+
self, product_id: int, sender: str
|
|
96
|
+
) -> SubaccountOpenOrdersData:
|
|
97
|
+
"""
|
|
98
|
+
Queries the off-chain engine to retrieve the status of any open orders for a given subaccount.
|
|
99
|
+
|
|
100
|
+
This function fetches any open orders that a specific subaccount might have
|
|
101
|
+
for a specific product from the off-chain engine. The orders are returned as
|
|
102
|
+
an SubaccountOpenOrdersData object.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
product_id (int): The identifier for the product to fetch open orders.
|
|
106
|
+
|
|
107
|
+
sender (str): The address and subaccount identifier as a bytes32 hex string.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
SubaccountOpenOrdersData: A data class object containing information about the open orders of a subaccount.
|
|
111
|
+
"""
|
|
112
|
+
return self.context.engine_client.get_subaccount_open_orders(product_id, sender)
|
|
113
|
+
|
|
114
|
+
def get_subaccount_multi_products_open_orders(
|
|
115
|
+
self, product_ids: list[int], sender: str
|
|
116
|
+
) -> SubaccountMultiProductsOpenOrdersData:
|
|
117
|
+
"""
|
|
118
|
+
Queries the off-chain engine to retrieve the status of any open orders for a given subaccount across multiple products.
|
|
119
|
+
|
|
120
|
+
This function fetches any open orders that a specific subaccount might have
|
|
121
|
+
for products product from the off-chain engine. The orders are returned as
|
|
122
|
+
an SubaccountMultiProductsOpenOrdersData object.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
product_ids (list[int]): List of product ids to fetch open orders for.
|
|
126
|
+
|
|
127
|
+
sender (str): The address and subaccount identifier as a bytes32 hex string.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
SubaccountMultiProductsOpenOrdersData: A data class object containing information about the open orders of a subaccount.
|
|
131
|
+
"""
|
|
132
|
+
return self.context.engine_client.get_subaccount_multi_products_open_orders(
|
|
133
|
+
product_ids, sender
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def get_subaccount_historical_orders(
|
|
137
|
+
self, params: IndexerSubaccountHistoricalOrdersParams
|
|
138
|
+
) -> IndexerHistoricalOrdersData:
|
|
139
|
+
"""
|
|
140
|
+
Queries the indexer to fetch historical orders of a specific subaccount.
|
|
141
|
+
|
|
142
|
+
This function retrieves a list of historical orders that a specific subaccount has placed.
|
|
143
|
+
The order data can be filtered using various parameters provided in the
|
|
144
|
+
IndexerSubaccountHistoricalOrdersParams object. The fetched historical orders data
|
|
145
|
+
is returned as an IndexerHistoricalOrdersData object.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
params (IndexerSubaccountHistoricalOrdersParams): Parameters to filter the historical orders data:
|
|
149
|
+
- subaccount (str): The address and subaccount identifier as a bytes32 hex string.
|
|
150
|
+
- product_ids (list[int], optional): A list of identifiers for the products to fetch orders for. If provided, the function will return orders related to these products.
|
|
151
|
+
- idx (int, optional): Submission index. If provided, the function will return orders submitted before this index.
|
|
152
|
+
- max_time (int, optional): Maximum timestamp for the orders. The function will return orders submitted before this time.
|
|
153
|
+
- limit (int, optional): Maximum number of orders to return. If provided, the function will return at most 'limit' number of orders.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
IndexerHistoricalOrdersData: A data class object containing information about the historical orders of a subaccount.
|
|
157
|
+
"""
|
|
158
|
+
return self.context.indexer_client.get_subaccount_historical_orders(params)
|
|
159
|
+
|
|
160
|
+
def get_historical_orders_by_digest(
|
|
161
|
+
self, digests: list[str]
|
|
162
|
+
) -> IndexerHistoricalOrdersData:
|
|
163
|
+
"""
|
|
164
|
+
Queries the indexer to fetch historical orders based on a list of provided digests.
|
|
165
|
+
|
|
166
|
+
This function retrieves historical order data for a given list of order digests.
|
|
167
|
+
Each digest represents a unique order. The returned object includes the historical
|
|
168
|
+
order data for each digest in the provided list.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
digests (list[str]): List of order digests. An order digest is a unique identifier for each order.
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
IndexerHistoricalOrdersData: A data class object containing information about the historical orders associated with the provided digests.
|
|
175
|
+
"""
|
|
176
|
+
return self.context.indexer_client.get_historical_orders_by_digest(digests)
|
|
177
|
+
|
|
178
|
+
def get_max_order_size(self, params: QueryMaxOrderSizeParams) -> MaxOrderSizeData:
|
|
179
|
+
"""
|
|
180
|
+
Queries the engine to determine the maximum order size that can be submitted within
|
|
181
|
+
health requirements.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
params (QueryMaxOrderSizeParams):
|
|
185
|
+
- sender (str): The address and subaccount identifier in a bytes32 hex string.
|
|
186
|
+
- product_id (int): The identifier for the spot/perp product.
|
|
187
|
+
- price_x18 (str): The price of the order in x18 format as a string.
|
|
188
|
+
- direction (MaxOrderSizeDirection): 'long' for max bid or 'short' for max ask.
|
|
189
|
+
- spot_leverage (Optional[bool]): If False, calculates max size without borrowing. Defaults to True.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
MaxOrderSizeData: The maximum size of the order that can be placed.
|
|
193
|
+
"""
|
|
194
|
+
return self.context.engine_client.get_max_order_size(params)
|
|
195
|
+
|
|
196
|
+
def get_max_lp_mintable(
|
|
197
|
+
self, product_id: int, sender: str, spot_leverage: Optional[bool] = None
|
|
198
|
+
) -> MaxLpMintableData:
|
|
199
|
+
"""
|
|
200
|
+
Queries the engine to determine the maximum base amount that can be contributed for minting LPs.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
product_id (int): The identifier for the spot/perp product.
|
|
204
|
+
|
|
205
|
+
sender (str): The address and subaccount identifier in a bytes32 hex string.
|
|
206
|
+
|
|
207
|
+
spot_leverage (Optional[bool]): If False, calculates max amount without considering leverage. Defaults to True.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
MaxLpMintableData: Maximum base amount that can be contributed for minting LPs, in string format.
|
|
211
|
+
"""
|
|
212
|
+
return self.context.engine_client.get_max_lp_mintable(
|
|
213
|
+
product_id, sender, spot_leverage
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def get_candlesticks(
|
|
217
|
+
self, params: IndexerCandlesticksParams
|
|
218
|
+
) -> IndexerCandlesticksData:
|
|
219
|
+
"""
|
|
220
|
+
Fetches historical candlestick data for a specific product using the indexer.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
params (IndexerCandlesticksParams): Parameters for the query, which include:
|
|
224
|
+
- product_id (int): The identifier for the product.
|
|
225
|
+
- granularity (IndexerCandlesticksGranularity): Duration for each candlestick in seconds.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
IndexerCandlesticksData: Contains a list of historical candlestick data (IndexerCandlestick)
|
|
229
|
+
for the specified product at the specified granularity.
|
|
230
|
+
|
|
231
|
+
Note:
|
|
232
|
+
For obtaining the latest orderbook prices, consider using the 'get_latest_market_price()' method.
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
return self.context.indexer_client.get_candlesticks(params)
|
|
236
|
+
|
|
237
|
+
def get_perp_funding_rate(self, product_id: int) -> IndexerFundingRateData:
|
|
238
|
+
"""
|
|
239
|
+
Fetches the latest funding rate for a specific perp product.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
product_id (int): Identifier for the perp product.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
IndexerFundingRateData: Contains the latest funding rate and related details for the given perp product.
|
|
246
|
+
"""
|
|
247
|
+
return self.context.indexer_client.get_perp_funding_rate(product_id)
|
|
248
|
+
|
|
249
|
+
def get_perp_funding_rates(self, product_ids: list) -> IndexerFundingRatesData:
|
|
250
|
+
"""
|
|
251
|
+
Fetches the latest funding rates for a list of perp products.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
product_ids (list): List of identifiers for the perp products.
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
dict: A dictionary mapping each product_id to its latest funding rate and related details.
|
|
258
|
+
"""
|
|
259
|
+
return self.context.indexer_client.get_perp_funding_rates(product_ids)
|
|
260
|
+
|
|
261
|
+
def get_product_snapshots(
|
|
262
|
+
self, params: IndexerProductSnapshotsParams
|
|
263
|
+
) -> IndexerProductSnapshotsData:
|
|
264
|
+
"""
|
|
265
|
+
Fetches the historical snapshots for a specific product from the indexer.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
params (IndexerProductSnapshotsParams): Query parameters consisting of:
|
|
269
|
+
- product_id (int): Identifier for the product.
|
|
270
|
+
- idx (int, optional): Submission index to filter the returned snapshots.
|
|
271
|
+
- max_time (int, optional): Maximum timestamp to filter the returned snapshots.
|
|
272
|
+
- limit (int, optional): Maximum number of snapshots to return.
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
IndexerProductSnapshotsData: Object containing lists of product snapshots and related transaction data.
|
|
276
|
+
"""
|
|
277
|
+
return self.context.indexer_client.get_product_snapshots(params)
|
|
278
|
+
|
|
279
|
+
def get_market_snapshots(
|
|
280
|
+
self, params: IndexerMarketSnapshotsParams
|
|
281
|
+
) -> IndexerMarketSnapshotsData:
|
|
282
|
+
"""
|
|
283
|
+
Fetches the historical market snapshots from the indexer.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
params (IndexerMarketSnapshotsParams): Parameters specifying the historical market snapshot request.
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
IndexerMarketSnapshotsData: The market snapshot data corresponding to the provided parameters.
|
|
290
|
+
"""
|
|
291
|
+
return self.context.indexer_client.get_market_snapshots(params)
|
|
292
|
+
|
|
293
|
+
def get_trigger_orders(
|
|
294
|
+
self, params: ListTriggerOrdersParams
|
|
295
|
+
) -> TriggerQueryResponse:
|
|
296
|
+
if self.context.trigger_client is None:
|
|
297
|
+
raise MissingTriggerClient()
|
|
298
|
+
return self.context.trigger_client.list_trigger_orders(params)
|
|
299
|
+
|
|
300
|
+
def get_isolated_positions(self, subaccount: str) -> IsolatedPositionsData:
|
|
301
|
+
"""
|
|
302
|
+
Retrieve isolated positions for a specific subaccount.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
subaccount (str): Unique identifier for the subaccount.
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
IsolatedPositionsData: A data class object containing information about the isolated positions for the specified subaccount.
|
|
309
|
+
"""
|
|
310
|
+
return self.context.engine_client.get_isolated_positions(subaccount)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from nado_protocol.client.apis.perp.query import PerpQueryAPI
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PerpAPI(PerpQueryAPI):
|
|
5
|
+
"""
|
|
6
|
+
A unified interface for Perpetual (Perp) operations in the Nado Protocol.
|
|
7
|
+
|
|
8
|
+
This class extends functionalities from PerpQueryAPI into a single interface, providing a simpler and more consistent way to perform Perp operations.
|
|
9
|
+
Currently, it allows for querying (data retrieval) operations for Perp products.
|
|
10
|
+
|
|
11
|
+
Inheritance:
|
|
12
|
+
PerpQueryAPI: This provides functionalities to retrieve various kinds of information related to Perp products.
|
|
13
|
+
These include operations like retrieving the latest index and mark price for a specific Perp product.
|
|
14
|
+
|
|
15
|
+
Attributes and Methods: Inherited from PerpQueryAPI.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
pass
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from nado_protocol.client.apis.base import NadoBaseAPI
|
|
2
|
+
from nado_protocol.indexer_client.types.query import IndexerPerpPricesData
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PerpQueryAPI(NadoBaseAPI):
|
|
6
|
+
"""
|
|
7
|
+
Provides functionalities for querying data related to Perpetual (Perp) products in the Nado Protocol.
|
|
8
|
+
|
|
9
|
+
Inherits from NadoBaseAPI, which provides a basic context setup for accessing Nado.
|
|
10
|
+
This class extends the base class to provide specific functionalities for querying data related to Perp products.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
context (NadoClientContext): Provides connectivity details for accessing Nado APIs.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def get_prices(self, product_id: int) -> IndexerPerpPricesData:
|
|
17
|
+
"""
|
|
18
|
+
Retrieves the latest index and mark price for a specific perp product from the indexer.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
product_id (int): The identifier for the perp product.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
IndexerPerpPricesData: An object containing the latest index and mark price for the specified product.
|
|
25
|
+
- product_id (int): The identifier for the perp product.
|
|
26
|
+
- index_price_x18 (str): The latest index price for the product, scaled by 1e18.
|
|
27
|
+
- mark_price_x18 (str): The latest mark price for the product, scaled by 1e18.
|
|
28
|
+
- update_time (str): The timestamp of the last price update.
|
|
29
|
+
"""
|
|
30
|
+
return self.context.indexer_client.get_perp_prices(product_id)
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from nado_protocol.contracts.types import (
|
|
3
|
+
ClaimFoundationRewardsContractParams,
|
|
4
|
+
ClaimFoundationRewardsProofStruct,
|
|
5
|
+
ClaimVrtxContractParams,
|
|
6
|
+
ClaimVrtxParams,
|
|
7
|
+
)
|
|
8
|
+
from nado_protocol.client.apis.base import NadoBaseAPI
|
|
9
|
+
from eth_account.signers.local import LocalAccount
|
|
10
|
+
|
|
11
|
+
from nado_protocol.utils.exceptions import InvalidVrtxClaimParams
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class RewardsExecuteAPI(NadoBaseAPI):
|
|
15
|
+
def _validate_claim_params(self, params: ClaimVrtxParams):
|
|
16
|
+
p = ClaimVrtxParams.parse_obj(params)
|
|
17
|
+
if p.amount is None and p.claim_all is None:
|
|
18
|
+
raise InvalidVrtxClaimParams()
|
|
19
|
+
|
|
20
|
+
def claim_vrtx(
|
|
21
|
+
self, params: ClaimVrtxParams, signer: Optional[LocalAccount] = None
|
|
22
|
+
) -> str:
|
|
23
|
+
self._validate_claim_params(params)
|
|
24
|
+
signer = self._get_signer(signer)
|
|
25
|
+
claim_params = self._get_claim_vrtx_contract_params(params, signer)
|
|
26
|
+
return self.context.contracts.claim_vrtx(
|
|
27
|
+
claim_params.epoch,
|
|
28
|
+
claim_params.amount_to_claim,
|
|
29
|
+
claim_params.total_claimable_amount,
|
|
30
|
+
claim_params.merkle_proof,
|
|
31
|
+
signer,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def claim_and_stake_vrtx(
|
|
35
|
+
self, params: ClaimVrtxParams, signer: Optional[LocalAccount] = None
|
|
36
|
+
) -> str:
|
|
37
|
+
self._validate_claim_params(params)
|
|
38
|
+
signer = self._get_signer(signer)
|
|
39
|
+
claim_params = self._get_claim_vrtx_contract_params(params, signer)
|
|
40
|
+
return self.context.contracts.claim_and_stake_vrtx(
|
|
41
|
+
claim_params.epoch,
|
|
42
|
+
claim_params.amount_to_claim,
|
|
43
|
+
claim_params.total_claimable_amount,
|
|
44
|
+
claim_params.merkle_proof,
|
|
45
|
+
signer,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def stake_vrtx(self, amount: int, signer: Optional[LocalAccount] = None) -> str:
|
|
49
|
+
signer = self._get_signer(signer)
|
|
50
|
+
return self.context.contracts.stake_vrtx(amount, signer)
|
|
51
|
+
|
|
52
|
+
def unstake_vrtx(self, amount: int, signer: Optional[LocalAccount] = None) -> str:
|
|
53
|
+
signer = self._get_signer(signer)
|
|
54
|
+
return self.context.contracts.unstake_vrtx(amount, signer)
|
|
55
|
+
|
|
56
|
+
def withdraw_unstaked_vrtx(self, signer: Optional[LocalAccount] = None):
|
|
57
|
+
signer = self._get_signer(signer)
|
|
58
|
+
return self.context.contracts.withdraw_unstaked_vrtx(signer)
|
|
59
|
+
|
|
60
|
+
def claim_usdc_rewards(self, signer: Optional[LocalAccount] = None):
|
|
61
|
+
signer = self._get_signer(signer)
|
|
62
|
+
return self.context.contracts.claim_usdc_rewards(signer)
|
|
63
|
+
|
|
64
|
+
def claim_and_stake_usdc_rewards(self, signer: Optional[LocalAccount] = None):
|
|
65
|
+
signer = self._get_signer(signer)
|
|
66
|
+
return self.context.contracts.claim_and_stake_usdc_rewards(signer)
|
|
67
|
+
|
|
68
|
+
def claim_foundation_rewards(self, signer: Optional[LocalAccount] = None):
|
|
69
|
+
"""
|
|
70
|
+
Claims all available foundation rewards. Foundation rewards are tokens associated with the chain. For example, ARB on Arbitrum.
|
|
71
|
+
"""
|
|
72
|
+
signer = self._get_signer(signer)
|
|
73
|
+
claim_params = self._get_claim_foundation_rewards_contract_params(signer)
|
|
74
|
+
return self.context.contracts.claim_foundation_rewards(
|
|
75
|
+
claim_params.claim_proofs, signer
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def _get_claim_vrtx_contract_params(
|
|
79
|
+
self, params: ClaimVrtxParams, signer: LocalAccount
|
|
80
|
+
) -> ClaimVrtxContractParams:
|
|
81
|
+
epoch_merkle_proofs = self.context.indexer_client.get_vrtx_merkle_proofs(
|
|
82
|
+
signer.address
|
|
83
|
+
).merkle_proofs[params.epoch]
|
|
84
|
+
total_claimable_amount = int(epoch_merkle_proofs.total_amount)
|
|
85
|
+
if params.amount is not None:
|
|
86
|
+
amount_to_claim = params.amount
|
|
87
|
+
else:
|
|
88
|
+
assert self.context.contracts.vrtx_airdrop is not None
|
|
89
|
+
amount_claimed = self.context.contracts.vrtx_airdrop.functions.getClaimed(
|
|
90
|
+
signer.address
|
|
91
|
+
).call()
|
|
92
|
+
amount_to_claim = total_claimable_amount - amount_claimed[params.epoch]
|
|
93
|
+
return ClaimVrtxContractParams(
|
|
94
|
+
epoch=params.epoch,
|
|
95
|
+
amount_to_claim=amount_to_claim,
|
|
96
|
+
total_claimable_amount=total_claimable_amount,
|
|
97
|
+
merkle_proof=epoch_merkle_proofs.proof,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
def _get_claim_foundation_rewards_contract_params(
|
|
101
|
+
self, signer: LocalAccount
|
|
102
|
+
) -> ClaimFoundationRewardsContractParams:
|
|
103
|
+
assert self.context.contracts.foundation_rewards_airdrop is not None
|
|
104
|
+
claimed = (
|
|
105
|
+
self.context.contracts.foundation_rewards_airdrop.functions.getClaimed(
|
|
106
|
+
signer.address
|
|
107
|
+
).call()
|
|
108
|
+
)
|
|
109
|
+
merkle_proofs = (
|
|
110
|
+
self.context.indexer_client.get_foundation_rewards_merkle_proofs(
|
|
111
|
+
signer.address
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
claim_proofs = []
|
|
115
|
+
|
|
116
|
+
for idx, proof in enumerate(merkle_proofs.merkle_proofs):
|
|
117
|
+
if idx == 0:
|
|
118
|
+
# week 0 is invalid
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
total_amount = int(proof.total_amount)
|
|
122
|
+
|
|
123
|
+
# There's no partial claim, so find weeks where there's a claimable amount and amt claimed is zero
|
|
124
|
+
if total_amount > 0 and int(claimed[idx]) == 0:
|
|
125
|
+
claim_proofs.append(
|
|
126
|
+
ClaimFoundationRewardsProofStruct(
|
|
127
|
+
totalAmount=total_amount, week=idx, proof=proof.proof
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
return ClaimFoundationRewardsContractParams(claim_proofs=claim_proofs)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from nado_protocol.client.apis.base import NadoBaseAPI
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class RewardsQueryAPI(NadoBaseAPI):
|
|
5
|
+
def get_claim_and_stake_estimated_vrtx(self, wallet: str) -> int:
|
|
6
|
+
"""
|
|
7
|
+
Estimates the amount of USDC -> VRTX swap when claiming + staking USDC rewards
|
|
8
|
+
"""
|
|
9
|
+
assert self.context.contracts.vrtx_staking is not None
|
|
10
|
+
return self.context.contracts.vrtx_staking.functions.getEstimatedVrtxToStake(
|
|
11
|
+
wallet
|
|
12
|
+
).call()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from nado_protocol.client.apis.spot.execute import SpotExecuteAPI
|
|
2
|
+
from nado_protocol.client.apis.spot.query import SpotQueryAPI
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SpotAPI(SpotExecuteAPI, SpotQueryAPI):
|
|
6
|
+
"""
|
|
7
|
+
A unified interface for spot operations in the Nado Protocol.
|
|
8
|
+
|
|
9
|
+
This class combines functionalities from both SpotExecuteAPI and SpotQueryAPI
|
|
10
|
+
into a single interface, providing a simpler and more consistent way to perform spot operations.
|
|
11
|
+
It allows for both query (data retrieval) and execution (transaction) operations for spot products.
|
|
12
|
+
|
|
13
|
+
Inheritance:
|
|
14
|
+
SpotExecuteAPI: This provides functionalities to execute various operations related to spot products,
|
|
15
|
+
such as depositing a specified amount into a spot product.
|
|
16
|
+
|
|
17
|
+
SpotQueryAPI: This provides functionalities to retrieve various kinds of information related to spot products,
|
|
18
|
+
such as getting the wallet token balance of a given spot product.
|
|
19
|
+
|
|
20
|
+
Attributes and Methods: Inherited from SpotExecuteAPI and SpotQueryAPI.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
pass
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from web3.contract import Contract
|
|
2
|
+
from nado_protocol.client.apis.base import NadoBaseAPI
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BaseSpotAPI(NadoBaseAPI):
|
|
6
|
+
"""
|
|
7
|
+
Base class for Spot operations in the Nado Protocol.
|
|
8
|
+
|
|
9
|
+
This class provides basic functionality for retrieving product-specific information
|
|
10
|
+
from the spot market of the Nado Protocol, such as the associated ERC20 token contract for a given spot product.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
context (NadoClientContext): Provides connectivity details for accessing Nado APIs.
|
|
14
|
+
|
|
15
|
+
Methods:
|
|
16
|
+
get_token_contract_for_product: Retrieves the associated ERC20 token contract for a given spot product.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def get_token_contract_for_product(self, product_id: int) -> Contract:
|
|
20
|
+
"""
|
|
21
|
+
Retrieves the associated ERC20 token contract for a given spot product.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
product_id (int): The identifier for the spot product.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Contract: The associated ERC20 token contract for the specified spot product.
|
|
28
|
+
|
|
29
|
+
Raises:
|
|
30
|
+
InvalidProductId: If the provided product ID is not valid.
|
|
31
|
+
"""
|
|
32
|
+
return self.context.contracts.get_token_contract_for_product(product_id)
|