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,141 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from pydantic import AnyUrl, Field
|
|
3
|
+
from nado_protocol.utils.enum import StrEnum
|
|
4
|
+
|
|
5
|
+
from nado_protocol.utils.model import NadoBaseModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class NadoNetwork(StrEnum):
|
|
9
|
+
"""
|
|
10
|
+
Enumeration representing various network environments for the Nado protocol.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# dev
|
|
14
|
+
HARDHAT = "localhost"
|
|
15
|
+
TESTING = "test"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NadoAbiName(StrEnum):
|
|
19
|
+
"""
|
|
20
|
+
Enumeration representing various contract names for which the ABI can be loaded in the Nado protocol.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
ENDPOINT = "Endpoint"
|
|
24
|
+
FQUERIER = "FQuerier"
|
|
25
|
+
ICLEARINGHOUSE = "IClearinghouse"
|
|
26
|
+
IENDPOINT = "IEndpoint"
|
|
27
|
+
IOFFCHAIN_BOOK = "IOffchainBook"
|
|
28
|
+
IPERP_ENGINE = "IPerpEngine"
|
|
29
|
+
ISPOT_ENGINE = "ISpotEngine"
|
|
30
|
+
MOCK_ERC20 = "MockERC20"
|
|
31
|
+
ISTAKING = "IStaking"
|
|
32
|
+
IVRTX_AIRDROP = "IVrtxAirdrop"
|
|
33
|
+
IFOUNDATION_REWARDS_AIRDROP = "IFoundationRewardsAirdrop"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class NadoDeployment(NadoBaseModel):
|
|
37
|
+
"""
|
|
38
|
+
Class representing deployment data for Nado protocol contracts.
|
|
39
|
+
|
|
40
|
+
Attributes:
|
|
41
|
+
node_url (AnyUrl): The URL of the node.
|
|
42
|
+
|
|
43
|
+
quote_addr (str): The address of the quote contract.
|
|
44
|
+
|
|
45
|
+
querier_addr (str): The address of the querier contract.
|
|
46
|
+
|
|
47
|
+
clearinghouse_addr (str): The address of the clearinghouse contract.
|
|
48
|
+
|
|
49
|
+
endpoint_addr (str): The address of the endpoint contract.
|
|
50
|
+
|
|
51
|
+
spot_engine_addr (str): The address of the spot engine contract.
|
|
52
|
+
|
|
53
|
+
perp_engine_addr (str): The address of the perpetual engine contract.
|
|
54
|
+
|
|
55
|
+
vrtx_airdrop_addr (str): The address of the VRTX airdrop contract.
|
|
56
|
+
|
|
57
|
+
vrtx_staking_addr (str): The address of the VRTX staking contract.
|
|
58
|
+
|
|
59
|
+
foundation_rewards_airdrop_addr (str): The address of Foundation Rewards airdrop contract for the corresponding chain (e.g: Arb airdrop for Arbitrum).
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
node_url: AnyUrl = Field(alias="publicNodeUrl")
|
|
63
|
+
quote_addr: str = Field(alias="quote")
|
|
64
|
+
querier_addr: str = Field(alias="querier")
|
|
65
|
+
clearinghouse_addr: str = Field(alias="clearinghouse")
|
|
66
|
+
endpoint_addr: str = Field(alias="endpoint")
|
|
67
|
+
spot_engine_addr: str = Field(alias="spotEngine")
|
|
68
|
+
perp_engine_addr: str = Field(alias="perpEngine")
|
|
69
|
+
vrtx_airdrop_addr: str = Field(alias="vrtxAirdrop")
|
|
70
|
+
vrtx_staking_addr: str = Field(alias="vrtxStaking")
|
|
71
|
+
foundation_rewards_airdrop_addr: str = Field(alias="foundationRewardsAirdrop")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class DepositCollateralParams(NadoBaseModel):
|
|
75
|
+
"""
|
|
76
|
+
Class representing parameters for depositing collateral in the Nado protocol.
|
|
77
|
+
|
|
78
|
+
Attributes:
|
|
79
|
+
subaccount_name (str): The name of the subaccount.
|
|
80
|
+
|
|
81
|
+
product_id (int): The ID of the spot product to deposit collateral for.
|
|
82
|
+
|
|
83
|
+
amount (int): The amount of collateral to be deposited.
|
|
84
|
+
|
|
85
|
+
referral_code (Optional[str]): Use this to indicate you were referred by existing member.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
subaccount_name: str
|
|
89
|
+
product_id: int
|
|
90
|
+
amount: int
|
|
91
|
+
referral_code: Optional[str]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class ClaimVrtxParams(NadoBaseModel):
|
|
95
|
+
epoch: int
|
|
96
|
+
amount: Optional[int]
|
|
97
|
+
claim_all: Optional[bool]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class ClaimVrtxContractParams(NadoBaseModel):
|
|
101
|
+
epoch: int
|
|
102
|
+
amount_to_claim: int
|
|
103
|
+
total_claimable_amount: int
|
|
104
|
+
merkle_proof: list[str]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ClaimFoundationRewardsProofStruct(NadoBaseModel):
|
|
108
|
+
totalAmount: int
|
|
109
|
+
week: int
|
|
110
|
+
proof: list[str]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class ClaimFoundationRewardsContractParams(NadoBaseModel):
|
|
114
|
+
claim_proofs: list[ClaimFoundationRewardsProofStruct]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class NadoExecuteType(StrEnum):
|
|
118
|
+
"""
|
|
119
|
+
Enumeration of possible actions to execute in Nado.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
PLACE_ORDER = "place_order"
|
|
123
|
+
PLACE_ISOLATED_ORDER = "place_isolated_order"
|
|
124
|
+
CANCEL_ORDERS = "cancel_orders"
|
|
125
|
+
CANCEL_PRODUCT_ORDERS = "cancel_product_orders"
|
|
126
|
+
CANCEL_AND_PLACE = "cancel_and_place"
|
|
127
|
+
WITHDRAW_COLLATERAL = "withdraw_collateral"
|
|
128
|
+
LIQUIDATE_SUBACCOUNT = "liquidate_subaccount"
|
|
129
|
+
MINT_LP = "mint_lp"
|
|
130
|
+
BURN_LP = "burn_lp"
|
|
131
|
+
LINK_SIGNER = "link_signer"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
NadoTxType = StrEnum(
|
|
135
|
+
"NadoTxType",
|
|
136
|
+
{
|
|
137
|
+
**{name: member.value for name, member in NadoExecuteType.__members__.items()},
|
|
138
|
+
**{"AUTHENTICATE_STREAM": "authenticate"},
|
|
139
|
+
**{"LIST_TRIGGER_ORDERS": "list_trigger_orders"},
|
|
140
|
+
},
|
|
141
|
+
) # type: ignore
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from nado_protocol.engine_client.types import EngineClientOpts
|
|
2
|
+
from nado_protocol.engine_client.execute import EngineExecuteClient
|
|
3
|
+
from nado_protocol.engine_client.query import EngineQueryClient
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class EngineClient(EngineQueryClient, EngineExecuteClient): # type: ignore
|
|
7
|
+
"""
|
|
8
|
+
Client for interacting with the engine service.
|
|
9
|
+
|
|
10
|
+
It allows users to both query data from and execute commands on the engine service.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
opts (EngineClientOpts): Client configuration options for connecting and interacting with the engine service.
|
|
14
|
+
|
|
15
|
+
Methods:
|
|
16
|
+
__init__: Initializes the `EngineClient` with the provided options.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, opts: EngineClientOpts):
|
|
20
|
+
"""
|
|
21
|
+
Initializes the EngineClient with the provided options.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
opts (EngineClientOpts): Client configuration options for connecting and interacting with the engine service.
|
|
25
|
+
"""
|
|
26
|
+
EngineQueryClient.__init__(self, opts)
|
|
27
|
+
EngineExecuteClient.__init__(self, opts)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"EngineClient",
|
|
32
|
+
"EngineClientOpts",
|
|
33
|
+
"EngineExecuteClient",
|
|
34
|
+
"EngineQueryClient",
|
|
35
|
+
]
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import requests
|
|
3
|
+
from functools import singledispatchmethod
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Union
|
|
6
|
+
from nado_protocol.engine_client.query import EngineQueryClient
|
|
7
|
+
from nado_protocol.engine_client.types import (
|
|
8
|
+
EngineClientOpts,
|
|
9
|
+
)
|
|
10
|
+
from nado_protocol.engine_client.types.execute import (
|
|
11
|
+
BurnLpParams,
|
|
12
|
+
CancelAndPlaceParams,
|
|
13
|
+
CancelOrdersParams,
|
|
14
|
+
CancelProductOrdersParams,
|
|
15
|
+
ExecuteParams,
|
|
16
|
+
ExecuteRequest,
|
|
17
|
+
ExecuteResponse,
|
|
18
|
+
LinkSignerParams,
|
|
19
|
+
LiquidateSubaccountParams,
|
|
20
|
+
MintLpParams,
|
|
21
|
+
OrderParams,
|
|
22
|
+
PlaceIsolatedOrderParams,
|
|
23
|
+
PlaceMarketOrderParams,
|
|
24
|
+
PlaceOrderParams,
|
|
25
|
+
WithdrawCollateralParams,
|
|
26
|
+
to_execute_request,
|
|
27
|
+
)
|
|
28
|
+
from nado_protocol.contracts.types import NadoExecuteType
|
|
29
|
+
from nado_protocol.engine_client.types.models import MarketLiquidity
|
|
30
|
+
from nado_protocol.utils.bytes32 import subaccount_to_hex
|
|
31
|
+
|
|
32
|
+
from nado_protocol.utils.exceptions import (
|
|
33
|
+
BadStatusCodeException,
|
|
34
|
+
ExecuteFailedException,
|
|
35
|
+
)
|
|
36
|
+
from nado_protocol.utils.expiration import OrderType, get_expiration_timestamp
|
|
37
|
+
from nado_protocol.utils.math import mul_x18, round_x18, to_x18
|
|
38
|
+
from nado_protocol.utils.model import NadoBaseModel, is_instance_of_union
|
|
39
|
+
from nado_protocol.utils.subaccount import Subaccount, SubaccountParams
|
|
40
|
+
from nado_protocol.utils.execute import NadoBaseExecute
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class EngineExecuteClient(NadoBaseExecute):
|
|
44
|
+
"""
|
|
45
|
+
Client class for executing operations against the off-chain engine.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self, opts: EngineClientOpts, querier: Optional[EngineQueryClient] = None
|
|
50
|
+
):
|
|
51
|
+
"""
|
|
52
|
+
Initialize the EngineExecuteClient with provided options.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
opts (EngineClientOpts): Options for the client.
|
|
56
|
+
|
|
57
|
+
querier (EngineQueryClient, optional): An EngineQueryClient instance. If not provided, a new one is created.
|
|
58
|
+
"""
|
|
59
|
+
super().__init__(opts)
|
|
60
|
+
self._querier = querier or EngineQueryClient(opts)
|
|
61
|
+
self._opts: EngineClientOpts = EngineClientOpts.parse_obj(opts)
|
|
62
|
+
self.url: str = self._opts.url
|
|
63
|
+
self.session = requests.Session()
|
|
64
|
+
|
|
65
|
+
def tx_nonce(self, sender: str) -> int:
|
|
66
|
+
"""
|
|
67
|
+
Get the transaction nonce. Used to perform executes such as `withdraw_collateral`.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
int: The transaction nonce.
|
|
71
|
+
"""
|
|
72
|
+
return int(self._querier.get_nonces(sender[:42]).tx_nonce)
|
|
73
|
+
|
|
74
|
+
@singledispatchmethod
|
|
75
|
+
def execute(self, params: Union[ExecuteParams, ExecuteRequest]) -> ExecuteResponse:
|
|
76
|
+
"""
|
|
77
|
+
Executes the operation defined by the provided parameters.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
params (ExecuteParams): The parameters for the operation to execute. This can represent a variety of operations, such as placing orders, cancelling orders, and more.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
ExecuteResponse: The response from the executed operation.
|
|
84
|
+
"""
|
|
85
|
+
req: ExecuteRequest = (
|
|
86
|
+
params if is_instance_of_union(params, ExecuteRequest) else to_execute_request(params) # type: ignore
|
|
87
|
+
)
|
|
88
|
+
return self._execute(req)
|
|
89
|
+
|
|
90
|
+
@execute.register
|
|
91
|
+
def _(self, req: dict) -> ExecuteResponse:
|
|
92
|
+
"""
|
|
93
|
+
Overloaded method to execute the operation defined by the provided request.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
req (dict): The request data for the operation to execute. Can be a dictionary or an instance of ExecuteRequest.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
ExecuteResponse: The response from the executed operation.
|
|
100
|
+
"""
|
|
101
|
+
parsed_req: ExecuteRequest = NadoBaseModel.parse_obj(req) # type: ignore
|
|
102
|
+
return self._execute(parsed_req)
|
|
103
|
+
|
|
104
|
+
def _execute(self, req: ExecuteRequest) -> ExecuteResponse:
|
|
105
|
+
"""
|
|
106
|
+
Internal method to execute the operation. Sends request to the server.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
req (ExecuteRequest): The request data for the operation to execute.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
ExecuteResponse: The response from the executed operation.
|
|
113
|
+
|
|
114
|
+
Raises:
|
|
115
|
+
BadStatusCodeException: If the server response status code is not 200.
|
|
116
|
+
ExecuteFailedException: If there's an error in the execution or the response status is not "success".
|
|
117
|
+
"""
|
|
118
|
+
res = self.session.post(f"{self.url}/execute", json=req.dict())
|
|
119
|
+
if res.status_code != 200:
|
|
120
|
+
raise BadStatusCodeException(res.text)
|
|
121
|
+
try:
|
|
122
|
+
execute_res = ExecuteResponse(**res.json(), req=req.dict())
|
|
123
|
+
except Exception:
|
|
124
|
+
raise ExecuteFailedException(res.text)
|
|
125
|
+
if execute_res.status != "success":
|
|
126
|
+
raise ExecuteFailedException(res.text)
|
|
127
|
+
return execute_res
|
|
128
|
+
|
|
129
|
+
def _assert_book_not_empty(
|
|
130
|
+
self, bids: list[MarketLiquidity], asks: list[MarketLiquidity], is_bid: bool
|
|
131
|
+
):
|
|
132
|
+
book_is_empty = (is_bid and len(bids) == 0) or (not is_bid and len(asks) == 0)
|
|
133
|
+
if book_is_empty:
|
|
134
|
+
raise Exception("Orderbook is empty.")
|
|
135
|
+
|
|
136
|
+
def place_order(self, params: PlaceOrderParams) -> ExecuteResponse:
|
|
137
|
+
"""
|
|
138
|
+
Execute a place order operation.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
params (PlaceOrderParams): Parameters required for placing an order.
|
|
142
|
+
The parameters include the order details and the product_id.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
146
|
+
"""
|
|
147
|
+
params = PlaceOrderParams.parse_obj(params)
|
|
148
|
+
params.order = self.prepare_execute_params(params.order, True)
|
|
149
|
+
params.signature = params.signature or self._sign(
|
|
150
|
+
NadoExecuteType.PLACE_ORDER, params.order.dict(), params.product_id
|
|
151
|
+
)
|
|
152
|
+
return self.execute(params)
|
|
153
|
+
|
|
154
|
+
def place_isolated_order(self, params: PlaceIsolatedOrderParams) -> ExecuteResponse:
|
|
155
|
+
"""
|
|
156
|
+
Execute a place isolated order operation.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
params (PlaceIsolatedOrderParams): Parameters required for placing an isolated order.
|
|
160
|
+
The parameters include the isolated order details.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
164
|
+
"""
|
|
165
|
+
params = PlaceIsolatedOrderParams.parse_obj(params)
|
|
166
|
+
params.isolated_order = self.prepare_execute_params(params.isolated_order, True)
|
|
167
|
+
params.signature = params.signature or self._sign(
|
|
168
|
+
NadoExecuteType.PLACE_ISOLATED_ORDER,
|
|
169
|
+
params.isolated_order.dict(),
|
|
170
|
+
params.product_id,
|
|
171
|
+
)
|
|
172
|
+
return self.execute(params)
|
|
173
|
+
|
|
174
|
+
def place_market_order(self, params: PlaceMarketOrderParams) -> ExecuteResponse:
|
|
175
|
+
"""
|
|
176
|
+
Places an FOK order using top of the book price with provided slippage.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
params (PlaceMarketOrderParams): Parameters required for placing a market order.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
183
|
+
"""
|
|
184
|
+
orderbook = self._querier.get_market_liquidity(params.product_id, 1)
|
|
185
|
+
is_bid = int(params.market_order.amount) > 0
|
|
186
|
+
self._assert_book_not_empty(orderbook.bids, orderbook.asks, is_bid)
|
|
187
|
+
slippage = to_x18(params.slippage or 0.005) # defaults to 0.5%
|
|
188
|
+
market_price_x18 = (
|
|
189
|
+
mul_x18(orderbook.bids[0][0], to_x18(1) + slippage)
|
|
190
|
+
if is_bid
|
|
191
|
+
else mul_x18(orderbook.asks[0][0], to_x18(1) - slippage)
|
|
192
|
+
)
|
|
193
|
+
price_increment_x18 = self._querier._get_subaccount_product_position(
|
|
194
|
+
subaccount_to_hex(params.market_order.sender), params.product_id
|
|
195
|
+
).product.book_info.price_increment_x18
|
|
196
|
+
order = OrderParams(
|
|
197
|
+
sender=params.market_order.sender,
|
|
198
|
+
amount=params.market_order.amount,
|
|
199
|
+
nonce=params.market_order.nonce,
|
|
200
|
+
priceX18=round_x18(market_price_x18, price_increment_x18),
|
|
201
|
+
expiration=get_expiration_timestamp(
|
|
202
|
+
OrderType.FOK, int(time.time()) + 1000, bool(params.reduce_only)
|
|
203
|
+
),
|
|
204
|
+
)
|
|
205
|
+
return self.place_order(
|
|
206
|
+
PlaceOrderParams( # type: ignore
|
|
207
|
+
product_id=params.product_id,
|
|
208
|
+
order=order,
|
|
209
|
+
spot_leverage=params.spot_leverage,
|
|
210
|
+
signature=params.signature,
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
def cancel_orders(self, params: CancelOrdersParams) -> ExecuteResponse:
|
|
215
|
+
"""
|
|
216
|
+
Execute a cancel orders operation.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
params (CancelOrdersParams): Parameters required for canceling orders.
|
|
220
|
+
The parameters include the order digests to be cancelled.
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
224
|
+
"""
|
|
225
|
+
params = self.prepare_execute_params(CancelOrdersParams.parse_obj(params), True)
|
|
226
|
+
params.signature = params.signature or self._sign(
|
|
227
|
+
NadoExecuteType.CANCEL_ORDERS, params.dict()
|
|
228
|
+
)
|
|
229
|
+
return self.execute(params)
|
|
230
|
+
|
|
231
|
+
def cancel_product_orders(
|
|
232
|
+
self, params: CancelProductOrdersParams
|
|
233
|
+
) -> ExecuteResponse:
|
|
234
|
+
"""
|
|
235
|
+
Execute a cancel product orders operation.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
params (CancelProductOrdersParams): Parameters required for bulk canceling orders of specific products.
|
|
239
|
+
The parameters include a list of product ids to bulk cancel orders for.
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
243
|
+
"""
|
|
244
|
+
params = self.prepare_execute_params(
|
|
245
|
+
CancelProductOrdersParams.parse_obj(params), True
|
|
246
|
+
)
|
|
247
|
+
params.signature = params.signature or self._sign(
|
|
248
|
+
NadoExecuteType.CANCEL_PRODUCT_ORDERS, params.dict()
|
|
249
|
+
)
|
|
250
|
+
return self.execute(params)
|
|
251
|
+
|
|
252
|
+
def cancel_and_place(self, params: CancelAndPlaceParams) -> ExecuteResponse:
|
|
253
|
+
"""
|
|
254
|
+
Execute a cancel and place operation.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
params (CancelAndPlaceParams): Parameters required for cancel and place.
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
261
|
+
"""
|
|
262
|
+
cancel_orders: CancelOrdersParams = self.prepare_execute_params(
|
|
263
|
+
CancelOrdersParams.parse_obj(params.cancel_orders), True
|
|
264
|
+
)
|
|
265
|
+
cancel_orders.signature = cancel_orders.signature or self._sign(
|
|
266
|
+
NadoExecuteType.CANCEL_ORDERS, cancel_orders.dict()
|
|
267
|
+
)
|
|
268
|
+
place_order: PlaceOrderParams = PlaceOrderParams.parse_obj(params.place_order)
|
|
269
|
+
place_order.order = self.prepare_execute_params(place_order.order, True)
|
|
270
|
+
place_order.signature = place_order.signature or self._sign(
|
|
271
|
+
NadoExecuteType.PLACE_ORDER,
|
|
272
|
+
place_order.order.dict(),
|
|
273
|
+
place_order.product_id,
|
|
274
|
+
)
|
|
275
|
+
return self.execute(
|
|
276
|
+
CancelAndPlaceParams(cancel_orders=cancel_orders, place_order=place_order)
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
def withdraw_collateral(self, params: WithdrawCollateralParams) -> ExecuteResponse:
|
|
280
|
+
"""
|
|
281
|
+
Execute a withdraw collateral operation.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
params (WithdrawCollateralParams): Parameters required for withdrawing collateral.
|
|
285
|
+
The parameters include the collateral details.
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
289
|
+
"""
|
|
290
|
+
params = self.prepare_execute_params(
|
|
291
|
+
WithdrawCollateralParams.parse_obj(params), False
|
|
292
|
+
)
|
|
293
|
+
params.signature = params.signature or self._sign(
|
|
294
|
+
NadoExecuteType.WITHDRAW_COLLATERAL, params.dict()
|
|
295
|
+
)
|
|
296
|
+
return self.execute(params)
|
|
297
|
+
|
|
298
|
+
def liquidate_subaccount(
|
|
299
|
+
self, params: LiquidateSubaccountParams
|
|
300
|
+
) -> ExecuteResponse:
|
|
301
|
+
"""
|
|
302
|
+
Execute a liquidate subaccount operation.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
params (LiquidateSubaccountParams): Parameters required for liquidating a subaccount.
|
|
306
|
+
The parameters include the liquidatee details.
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
310
|
+
"""
|
|
311
|
+
params = self.prepare_execute_params(
|
|
312
|
+
LiquidateSubaccountParams.parse_obj(params), False
|
|
313
|
+
)
|
|
314
|
+
params.signature = params.signature or self._sign(
|
|
315
|
+
NadoExecuteType.LIQUIDATE_SUBACCOUNT,
|
|
316
|
+
params.dict(),
|
|
317
|
+
)
|
|
318
|
+
return self.execute(params)
|
|
319
|
+
|
|
320
|
+
def mint_lp(self, params: MintLpParams) -> ExecuteResponse:
|
|
321
|
+
"""
|
|
322
|
+
Execute a mint LP tokens operation.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
params (MintLpParams): Parameters required for minting LP tokens.
|
|
326
|
+
The parameters include the LP details.
|
|
327
|
+
|
|
328
|
+
Returns:
|
|
329
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
330
|
+
"""
|
|
331
|
+
params = self.prepare_execute_params(MintLpParams.parse_obj(params), False)
|
|
332
|
+
params.signature = params.signature or self._sign(
|
|
333
|
+
NadoExecuteType.MINT_LP,
|
|
334
|
+
params.dict(),
|
|
335
|
+
)
|
|
336
|
+
return self.execute(params)
|
|
337
|
+
|
|
338
|
+
def burn_lp(self, params: BurnLpParams) -> ExecuteResponse:
|
|
339
|
+
"""
|
|
340
|
+
Execute a burn LP tokens operation.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
params (BurnLpParams): Parameters required for burning LP tokens.
|
|
344
|
+
The parameters include the LP details.
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
348
|
+
"""
|
|
349
|
+
params = self.prepare_execute_params(BurnLpParams.parse_obj(params), False)
|
|
350
|
+
params.signature = params.signature or self._sign(
|
|
351
|
+
NadoExecuteType.BURN_LP,
|
|
352
|
+
params.dict(),
|
|
353
|
+
)
|
|
354
|
+
return self.execute(params)
|
|
355
|
+
|
|
356
|
+
def link_signer(self, params: LinkSignerParams) -> ExecuteResponse:
|
|
357
|
+
"""
|
|
358
|
+
Execute a link signer operation.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
params (LinkSignerParams): Parameters required for linking a signer.
|
|
362
|
+
The parameters include the signer details.
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
366
|
+
"""
|
|
367
|
+
params = self.prepare_execute_params(LinkSignerParams.parse_obj(params), False)
|
|
368
|
+
params.signature = params.signature or self._sign(
|
|
369
|
+
NadoExecuteType.LINK_SIGNER,
|
|
370
|
+
params.dict(),
|
|
371
|
+
)
|
|
372
|
+
return self.execute(params)
|
|
373
|
+
|
|
374
|
+
def close_position(
|
|
375
|
+
self, subaccount: Subaccount, product_id: int
|
|
376
|
+
) -> ExecuteResponse:
|
|
377
|
+
"""
|
|
378
|
+
Execute a place order operation to close a position for the provided `product_id`.
|
|
379
|
+
|
|
380
|
+
Attributes:
|
|
381
|
+
subaccount (Subaccount): The subaccount to close position for.
|
|
382
|
+
product_id (int): The ID of the product to close position for.
|
|
383
|
+
|
|
384
|
+
Returns:
|
|
385
|
+
ExecuteResponse: Response of the execution, including status and potential error message.
|
|
386
|
+
"""
|
|
387
|
+
subaccount = subaccount_to_hex(subaccount)
|
|
388
|
+
position = self._querier._get_subaccount_product_position(
|
|
389
|
+
subaccount, product_id
|
|
390
|
+
)
|
|
391
|
+
balance, product = position.balance, position.product
|
|
392
|
+
closing_spread_x18 = to_x18(0.005)
|
|
393
|
+
closing_price_x18 = (
|
|
394
|
+
mul_x18(product.oracle_price_x18, to_x18(1) - closing_spread_x18)
|
|
395
|
+
if int(balance.balance.amount) > 0
|
|
396
|
+
else mul_x18(product.oracle_price_x18, to_x18(1) + closing_spread_x18)
|
|
397
|
+
)
|
|
398
|
+
return self.place_order(
|
|
399
|
+
PlaceOrderParams( # type: ignore
|
|
400
|
+
product_id=product_id,
|
|
401
|
+
order=OrderParams( # type: ignore
|
|
402
|
+
sender=subaccount,
|
|
403
|
+
amount=-round_x18(
|
|
404
|
+
balance.balance.amount,
|
|
405
|
+
product.book_info.size_increment,
|
|
406
|
+
),
|
|
407
|
+
priceX18=round_x18(
|
|
408
|
+
closing_price_x18,
|
|
409
|
+
product.book_info.price_increment_x18,
|
|
410
|
+
),
|
|
411
|
+
expiration=get_expiration_timestamp(
|
|
412
|
+
OrderType.FOK, int(time.time()) + 1000, reduce_only=True
|
|
413
|
+
),
|
|
414
|
+
),
|
|
415
|
+
)
|
|
416
|
+
)
|