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,66 @@
|
|
|
1
|
+
from nado_protocol.engine_client.types.models import SpotProduct
|
|
2
|
+
from nado_protocol.utils.time import TimeInSeconds
|
|
3
|
+
from nado_protocol.utils.math import from_x18, mul_x18
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def calc_deposits_and_borrows(product: SpotProduct) -> tuple[float, float]:
|
|
7
|
+
total_deposited = from_x18(
|
|
8
|
+
mul_x18(
|
|
9
|
+
int(product.state.total_deposits_normalized),
|
|
10
|
+
int(product.state.cumulative_deposits_multiplier_x18),
|
|
11
|
+
)
|
|
12
|
+
)
|
|
13
|
+
total_borrowed = from_x18(
|
|
14
|
+
mul_x18(
|
|
15
|
+
int(product.state.total_borrows_normalized),
|
|
16
|
+
int(product.state.cumulative_borrows_multiplier_x18),
|
|
17
|
+
)
|
|
18
|
+
)
|
|
19
|
+
return (total_deposited, total_borrowed)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def calc_utilization_ratio(product: SpotProduct) -> float:
|
|
23
|
+
total_deposited, total_borrowed = calc_deposits_and_borrows(product)
|
|
24
|
+
|
|
25
|
+
if total_deposited == 0 or total_borrowed == 0:
|
|
26
|
+
return 0
|
|
27
|
+
|
|
28
|
+
return abs(total_borrowed) / total_deposited
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def calc_borrow_rate_per_second(product: SpotProduct) -> float:
|
|
32
|
+
utilization = calc_utilization_ratio(product)
|
|
33
|
+
if utilization == 0:
|
|
34
|
+
return 0
|
|
35
|
+
interest_floor = from_x18(int(product.config.interest_floor_x18))
|
|
36
|
+
interest_inflection_util = from_x18(
|
|
37
|
+
int(product.config.interest_inflection_util_x18)
|
|
38
|
+
)
|
|
39
|
+
interest_small_cap = from_x18(int(product.config.interest_small_cap_x18))
|
|
40
|
+
interest_large_cap = from_x18(int(product.config.interest_large_cap_x18))
|
|
41
|
+
|
|
42
|
+
annual_rate = 0.0
|
|
43
|
+
if utilization > interest_inflection_util:
|
|
44
|
+
utilization_term = interest_large_cap * (
|
|
45
|
+
(utilization - interest_inflection_util) / (1 - interest_inflection_util)
|
|
46
|
+
)
|
|
47
|
+
annual_rate = interest_floor + interest_small_cap + utilization_term
|
|
48
|
+
else:
|
|
49
|
+
utilization_term = (utilization / interest_inflection_util) * interest_small_cap
|
|
50
|
+
annual_rate = interest_floor + utilization_term
|
|
51
|
+
return annual_rate / TimeInSeconds.YEAR
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def calc_borrow_rate_in_period(product: SpotProduct, period_in_seconds) -> float:
|
|
55
|
+
borrow_rate_per_second = calc_borrow_rate_per_second(product)
|
|
56
|
+
return (borrow_rate_per_second + 1) ** period_in_seconds - 1
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def calc_deposit_rate_in_period(
|
|
60
|
+
product: SpotProduct, period_in_seconds: int, interest_fee_fraction: float
|
|
61
|
+
) -> float:
|
|
62
|
+
utilization = calc_utilization_ratio(product)
|
|
63
|
+
if utilization == 0:
|
|
64
|
+
return 0
|
|
65
|
+
borrow_rate_in_period = calc_borrow_rate_in_period(product, period_in_seconds)
|
|
66
|
+
return utilization * borrow_rate_in_period * (1 - interest_fee_fraction)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def to_pow_10(x: int, pow: int) -> int:
|
|
6
|
+
"""
|
|
7
|
+
Converts integer to power of 10 format.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
x (int): Integer value.
|
|
11
|
+
|
|
12
|
+
pow (int): Power of 10.
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
int: Converted value.
|
|
16
|
+
"""
|
|
17
|
+
return x * 10**pow
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def to_x18(x: float) -> int:
|
|
21
|
+
"""
|
|
22
|
+
Converts a float to a fixed point of 1e18.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
x (float): Float value to convert.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
int: Fixed point value represented as an integer.
|
|
29
|
+
"""
|
|
30
|
+
return int(Decimal(str(x)) * Decimal(10**18))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def from_pow_10(x: int, pow: int) -> float:
|
|
34
|
+
"""
|
|
35
|
+
Reverts integer from power of 10 format.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
x (int): Converted value.
|
|
39
|
+
|
|
40
|
+
pow (int): Power of 10.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
float: Original value.
|
|
44
|
+
"""
|
|
45
|
+
return float(x) / 10**pow
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def from_x18(x: int) -> float:
|
|
49
|
+
"""
|
|
50
|
+
Reverts integer from power of 10^18 format.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
x (int): Converted value.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
float: Original value.
|
|
57
|
+
"""
|
|
58
|
+
return from_pow_10(x, 18)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def mul_x18(x: Union[float, str], y: Union[float, str]) -> int:
|
|
62
|
+
return int(Decimal(str(x)) * Decimal(str(y)) / Decimal(10**18))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def round_x18(x: Union[int, str], y: Union[str, int]) -> int:
|
|
66
|
+
x, y = int(x), int(y)
|
|
67
|
+
return x - x % y
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
from typing import Any, Callable, Type, TypeVar, Union
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class NadoBaseModel(BaseModel):
|
|
7
|
+
"""
|
|
8
|
+
This base model extends Pydantic's BaseModel and excludes fields with None
|
|
9
|
+
values by default when serializing via .dict() or .json()
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def dict(self, **kwargs):
|
|
13
|
+
"""
|
|
14
|
+
Convert model to dictionary, excluding None fields by default.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
kwargs: Arbitrary keyword arguments.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
dict: The model as a dictionary.
|
|
21
|
+
"""
|
|
22
|
+
kwargs.setdefault("exclude_none", True)
|
|
23
|
+
return super().dict(**kwargs)
|
|
24
|
+
|
|
25
|
+
def json(self, **kwargs):
|
|
26
|
+
"""
|
|
27
|
+
Convert model to JSON, excluding None fields by default.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
kwargs: Arbitrary keyword arguments.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
str: The model as a JSON string.
|
|
34
|
+
"""
|
|
35
|
+
kwargs.setdefault("exclude_none", True)
|
|
36
|
+
return super().json(**kwargs)
|
|
37
|
+
|
|
38
|
+
def serialize_dict(self, fields: list[str], func: Callable):
|
|
39
|
+
"""
|
|
40
|
+
Apply a function to specified fields in the model's dictionary.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
fields (list[str]): Fields to be modified.
|
|
44
|
+
|
|
45
|
+
func (Callable): Function to apply to each field.
|
|
46
|
+
"""
|
|
47
|
+
for field in fields:
|
|
48
|
+
self.__dict__[field] = func(self.__dict__[field])
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def parse_enum_value(value: Union[str, Enum]) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Utility function to parse an enum value.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
value (str | Enum): Original value which may be an Enum.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
str: The Enum value.
|
|
60
|
+
"""
|
|
61
|
+
if isinstance(value, Enum):
|
|
62
|
+
return value.value
|
|
63
|
+
else:
|
|
64
|
+
return value
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
T = TypeVar("T")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def ensure_data_type(data, expected_type: Type[T]) -> T:
|
|
71
|
+
assert isinstance(
|
|
72
|
+
data, expected_type
|
|
73
|
+
), f"Expected {expected_type.__name__}, but got {type(data).__name__}"
|
|
74
|
+
return data
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def is_instance_of_union(obj: Any, union) -> bool:
|
|
78
|
+
"""Check if `obj` is an instance of any type in the `union`."""
|
|
79
|
+
return any(isinstance(obj, cls) for cls in union.__args__)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from datetime import timezone, datetime, timedelta
|
|
3
|
+
import random
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def gen_order_nonce(
|
|
7
|
+
recv_time_ms: Optional[int] = None,
|
|
8
|
+
random_int: Optional[int] = None,
|
|
9
|
+
is_trigger_order: bool = False,
|
|
10
|
+
) -> int:
|
|
11
|
+
"""
|
|
12
|
+
Generates an order nonce based on a received timestamp and a random integer.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
recv_time_ms (int, optional): Received timestamp in milliseconds. Defaults to the current time plus 90 seconds.
|
|
16
|
+
|
|
17
|
+
random_int (int, optional): An integer for the nonce. Defaults to a random integer between 0 and 999.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
int: The generated order nonce.
|
|
21
|
+
"""
|
|
22
|
+
if recv_time_ms is None:
|
|
23
|
+
recv_time_ms = int(
|
|
24
|
+
(datetime.now(tz=timezone.utc) + timedelta(seconds=90)).timestamp() * 1000
|
|
25
|
+
)
|
|
26
|
+
if random_int is None:
|
|
27
|
+
random_int = random.randint(0, 999)
|
|
28
|
+
|
|
29
|
+
nonce = (recv_time_ms << 20) + random_int
|
|
30
|
+
|
|
31
|
+
if is_trigger_order:
|
|
32
|
+
nonce = nonce | (1 << 63)
|
|
33
|
+
return nonce
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import Optional, Union
|
|
2
|
+
from nado_protocol.utils.model import NadoBaseModel
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SubaccountParams(NadoBaseModel):
|
|
6
|
+
"""
|
|
7
|
+
A class used to represent parameters for a Subaccount in the Nado system.
|
|
8
|
+
|
|
9
|
+
Attributes:
|
|
10
|
+
subaccount_owner (Optional[str]): The wallet address of the subaccount.
|
|
11
|
+
subaccount_name (str): The subaccount name identifier.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
subaccount_owner: Optional[str]
|
|
15
|
+
subaccount_name: str
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Subaccount = Union[str, bytes, SubaccountParams]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from enum import IntEnum
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TimeInSeconds(IntEnum):
|
|
6
|
+
MINUTE = 60
|
|
7
|
+
HOUR = 3600
|
|
8
|
+
DAY = 86400
|
|
9
|
+
YEAR = 31536000
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def millis_to_seconds(millis: int) -> int:
|
|
13
|
+
return millis // 1000
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def now_in_seconds() -> int:
|
|
17
|
+
return int(time.time())
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def now_in_millis(padding: int = 0) -> int:
|
|
21
|
+
return (now_in_seconds() + padding) * 1000
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: nado-protocol
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Nado Protocol SDK
|
|
5
|
+
Keywords: nado protocol,nado sdk,nado protocol api
|
|
6
|
+
Author: Jeury Mejia
|
|
7
|
+
Author-email: jeury@inkfnd.com
|
|
8
|
+
Maintainer: Frank Jia
|
|
9
|
+
Maintainer-email: frank@inkfnd.com
|
|
10
|
+
Requires-Python: >=3.9,<4.0
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Requires-Dist: eth-account (>=0.8.0,<0.9.0)
|
|
18
|
+
Requires-Dist: pydantic (>=1.10.7,<2.0.0)
|
|
19
|
+
Requires-Dist: web3 (>=6.4.0,<7.0.0)
|
|
20
|
+
Project-URL: Documentation, https://nadohq.github.io/nado-python-sdk/
|
|
21
|
+
Project-URL: Homepage, https://nado.xyz
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Nado Protocol Python SDK
|
|
25
|
+
|
|
26
|
+
This is the Python SDK for the [Nado Protocol API](TODO).
|
|
27
|
+
|
|
28
|
+
See [SDK docs](https://nadohq.github.io/nado-python-sdk/index.html) to get started.
|
|
29
|
+
|
|
30
|
+
## Requirements
|
|
31
|
+
|
|
32
|
+
- Python 3.9 or above
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
You can install the SDK via pip:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install nado-protocol
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Basic usage
|
|
43
|
+
|
|
44
|
+
### Import the necessary utilities:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from nado_protocol.client import create_nado_client, NadoClientMode
|
|
48
|
+
from nado_protocol.contracts.types import DepositCollateralParams
|
|
49
|
+
from nado_protocol.engine_client.types.execute import (
|
|
50
|
+
OrderParams,
|
|
51
|
+
PlaceOrderParams,
|
|
52
|
+
SubaccountParams
|
|
53
|
+
)
|
|
54
|
+
from nado_protocol.utils.expiration import OrderType, get_expiration_timestamp
|
|
55
|
+
from nado_protocol.utils.math import to_pow_10, to_x18
|
|
56
|
+
from nado_protocol.utils.nonce import gen_order_nonce
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Create the NadoClient providing your private key:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
print("setting up nado client...")
|
|
63
|
+
private_key = "xxx"
|
|
64
|
+
client = create_nado_client(NadoClientMode.DEVNET, private_key)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Perform basic operations:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
# Depositing collaterals
|
|
71
|
+
print("approving allowance...")
|
|
72
|
+
approve_allowance_tx_hash = client.spot.approve_allowance(0, to_pow_10(100000, 6))
|
|
73
|
+
print("approve allowance tx hash:", approve_allowance_tx_hash)
|
|
74
|
+
|
|
75
|
+
print("querying my allowance...")
|
|
76
|
+
token_allowance = client.spot.get_token_allowance(0, client.context.signer.address)
|
|
77
|
+
print("token allowance:", token_allowance)
|
|
78
|
+
|
|
79
|
+
print("depositing collateral...")
|
|
80
|
+
deposit_tx_hash = client.spot.deposit(
|
|
81
|
+
DepositCollateralParams(
|
|
82
|
+
subaccount_name="default", product_id=0, amount=to_pow_10(100000, 6)
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
print("deposit collateral tx hash:", deposit_tx_hash)
|
|
86
|
+
|
|
87
|
+
# Placing orders
|
|
88
|
+
print("placing order...")
|
|
89
|
+
owner = client.context.engine_client.signer.address
|
|
90
|
+
product_id = 1
|
|
91
|
+
order = OrderParams(
|
|
92
|
+
sender=SubaccountParams(
|
|
93
|
+
subaccount_owner=owner,
|
|
94
|
+
subaccount_name="default",
|
|
95
|
+
),
|
|
96
|
+
priceX18=to_x18(20000),
|
|
97
|
+
amount=to_pow_10(1, 17),
|
|
98
|
+
expiration=get_expiration_timestamp(OrderType.POST_ONLY, int(time.time()) + 40),
|
|
99
|
+
nonce=gen_order_nonce(),
|
|
100
|
+
)
|
|
101
|
+
res = client.market.place_order({"product_id": product_id, "order": order})
|
|
102
|
+
print("order result:", res.json(indent=2))
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
See [Getting Started](https://nadohq.github.io/nado-python-sdk/getting-started.html) for more.
|
|
106
|
+
|
|
107
|
+
## Running locally
|
|
108
|
+
|
|
109
|
+
1. Clone [github repo](https://github.com/nadohq/nado-python-sdk)
|
|
110
|
+
|
|
111
|
+
2. Install poetry
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
$ curl -sSL https://install.python-poetry.org | python3 -
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
3. Setup a virtual environment and activate it
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
$ python3 -m venv venv
|
|
124
|
+
$ source ./venv/bin/activate
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
4. Install dependencies via `poetry install`
|
|
129
|
+
5. Setup an `.env` file and set the following envvars
|
|
130
|
+
|
|
131
|
+
```shell
|
|
132
|
+
CLIENT_MODE='devnet'
|
|
133
|
+
SIGNER_PRIVATE_KEY="0x..."
|
|
134
|
+
LINKED_SIGNER_PRIVATE_KEY="0x..." # not required
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Run tests
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
$ poetry run test
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Run sanity checks
|
|
144
|
+
|
|
145
|
+
- `poetry run client-sanity`: runs sanity checks for the top-level client.
|
|
146
|
+
- `poetry run engine-sanity`: runs sanity checks for the `engine-client`.
|
|
147
|
+
- `poetry run indexer-sanity`: runs sanity checks for the `indexer-client`.
|
|
148
|
+
- `poetry run contracts-sanity`: runs sanity checks for the contracts module.
|
|
149
|
+
|
|
150
|
+
### Build Docs
|
|
151
|
+
|
|
152
|
+
To build the docs locally run:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
$ poetry run sphinx-build docs/source docs/build
|
|
156
|
+
```
|
|
157
|
+
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
nado_protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
nado_protocol/client/__init__.py,sha256=aPr34J4mnuyYmTDXXrAHOSKS3BPP61Q70X9QhAfGvf0,7411
|
|
3
|
+
nado_protocol/client/apis/__init__.py,sha256=0wEscoemkmvyyTlUAaIM2vSO9LD_yCCVf3loHwasG_4,680
|
|
4
|
+
nado_protocol/client/apis/base.py,sha256=89g6va4wcqbV7XLO0UBkKmmM2C2oDcYSzRjzaUnFcGQ,1807
|
|
5
|
+
nado_protocol/client/apis/market/__init__.py,sha256=uILwdGeWOzQRT7x8bxvof6_u4GpsG9tL9I0VBuDPSoE,1102
|
|
6
|
+
nado_protocol/client/apis/market/execute.py,sha256=ffqGLawgCEmOVLxDz_cPyAqIc-40C99ITSwZfs6ba7U,7037
|
|
7
|
+
nado_protocol/client/apis/market/query.py,sha256=K4ctbvutByqe33el06JTIja5YrVgd6DxBgz78G8G5nw,13507
|
|
8
|
+
nado_protocol/client/apis/perp/__init__.py,sha256=KUGZ86Xo-NB-9uhqEyXkrqoGDhWeex0-AQwCfWfvpsg,742
|
|
9
|
+
nado_protocol/client/apis/perp/query.py,sha256=r4E0tJo7-z9J3HOMufo6BZ9yTYtpCb-ANZeM05lf7rU,1420
|
|
10
|
+
nado_protocol/client/apis/rewards/__init__.py,sha256=F7fTCEdGR2J2fMd5AhC1JruJSMKUZcoOvYotdSYWU7M,205
|
|
11
|
+
nado_protocol/client/apis/rewards/execute.py,sha256=qXr0v4trLk8PedmCVQeWBcuNWme2KDqrMtCuu_KkfNU,5331
|
|
12
|
+
nado_protocol/client/apis/rewards/query.py,sha256=Jb0KAxLa7HLzvNL5M2lnW-lgtKmLcAHS1W1yXWvoUbg,459
|
|
13
|
+
nado_protocol/client/apis/spot/__init__.py,sha256=QdoWAVrvfNAP-YDwM5Z-4N1lS6dgNzNgNqUp78IHMqU,1021
|
|
14
|
+
nado_protocol/client/apis/spot/base.py,sha256=SagkZZ9Ehi7pSxM5lD-glOMEQj9aT3PGGW4UtGnVpuw,1177
|
|
15
|
+
nado_protocol/client/apis/spot/execute.py,sha256=u_O9vjoshv8Zfg8nIsnd8_X7PUO5CShFC-vyNOBvOFI,4772
|
|
16
|
+
nado_protocol/client/apis/spot/query.py,sha256=6YcnfTlVnEHpUkB3eM8zvbYGBxSAw2Xy4yezMDTsZ9U,2954
|
|
17
|
+
nado_protocol/client/apis/subaccount/__init__.py,sha256=vT857P7_DkIWvV0D5izFg52i-qp800-hlwLzSpIk4Cc,1301
|
|
18
|
+
nado_protocol/client/apis/subaccount/execute.py,sha256=sbiR9VhRl713Cfus_fAzXQiYR6VZWzPROaTowQDGaA4,2005
|
|
19
|
+
nado_protocol/client/apis/subaccount/query.py,sha256=-s6KDMgIsWPm0mWaaj_CMw_yH1g3LGhi5pn5lKWZrXk,5806
|
|
20
|
+
nado_protocol/client/context.py,sha256=dFpsM9ubpAkuFiaoKyJhUZ4-K9g5IPCIhKMhH5HIt78,3565
|
|
21
|
+
nado_protocol/contracts/__init__.py,sha256=ievX0rKS2xc-Pw92vNE6b-5E4x1aeKjlhP2qCfq9nwI,13247
|
|
22
|
+
nado_protocol/contracts/abis/Endpoint.json,sha256=LO5WDKaFkufoxURyuje8qTL4wCDToy9DIeFLguhIPtE,12130
|
|
23
|
+
nado_protocol/contracts/abis/FQuerier.json,sha256=-STsPrOiH9yzT4p6sCgqCIWSxqWiaSUoqV_9prJF6N4,55374
|
|
24
|
+
nado_protocol/contracts/abis/IClearinghouse.json,sha256=SLzYb3sKo6XaPusGZ4xpyE3YNN3nuMMhMTfvdSzXPZw,18751
|
|
25
|
+
nado_protocol/contracts/abis/IERC20.json,sha256=3IHFuKJGU4K0vy5xB7yTA4nO8zKsvEQrv-xQX5AFFA4,3385
|
|
26
|
+
nado_protocol/contracts/abis/IEndpoint.json,sha256=UGNgF9LF6Hzqm0w9mWwlJKLRuidbBd7O4MS7nxkmHp8,4796
|
|
27
|
+
nado_protocol/contracts/abis/IFoundationRewardsAirdrop.json,sha256=CZXya7fyBA4YNq514RcbCjpf9pcytfy5lvtFNl3AVB0,1503
|
|
28
|
+
nado_protocol/contracts/abis/IOffchainBook.json,sha256=uGLsefw2oTyKWOj3oeOzWfqmbVrqdUT--CnJp9yqQik,13112
|
|
29
|
+
nado_protocol/contracts/abis/IPerpEngine.json,sha256=miW8CMChKeuYop9CjeivnrKO6xKKQH0kCbfs3SOzz4s,19746
|
|
30
|
+
nado_protocol/contracts/abis/IProductEngine.json,sha256=v-swLFaXaWvOoR25M15NaZILfFjpUJfyo54h5hQbmv8,6836
|
|
31
|
+
nado_protocol/contracts/abis/ISpotEngine.json,sha256=8cYIlZ4AppucXgqJBfamltQt_QW-9U_Aygl2KjrRAU8,17284
|
|
32
|
+
nado_protocol/contracts/abis/IStaking.json,sha256=XhC143Lnmcv1ZBhiABXwc67_HyvbWsCuiNmJ0hzdq0s,5557
|
|
33
|
+
nado_protocol/contracts/abis/IVrtxAirdrop.json,sha256=0xI-zS1iRK1KJ4O318jI5frjfbYzIMO5y8gFjCXaVIk,2639
|
|
34
|
+
nado_protocol/contracts/abis/MockERC20.json,sha256=BTVOlYwLEYZnboD94BNiUS0rx_IPLcqbPFC3CL4NkOY,5698
|
|
35
|
+
nado_protocol/contracts/deployments/deployment.test.json,sha256=_lv1JimCFxdi3wjpEafqsuHDBpAbMLeh0VfEfOrZGwU,881
|
|
36
|
+
nado_protocol/contracts/eip712/__init__.py,sha256=q8eJd5oY7AQ5iLsS1CfbZr6vBWLSPVZv2dfMnRzfqQo,416
|
|
37
|
+
nado_protocol/contracts/eip712/domain.py,sha256=dZ5aKq2Y45-vzZUMQLuUTbFhH9-R-YEg4G2sVqXQFbQ,1179
|
|
38
|
+
nado_protocol/contracts/eip712/sign.py,sha256=WeipHcWaEP_vnmXpRH7_Ksm9uKDH2E4IkYYRI0_p2cY,2410
|
|
39
|
+
nado_protocol/contracts/eip712/types.py,sha256=0caDcJ6SmlB0FOZhaO5dCYO0gwLEiCwXEojuZmLJ_kI,5408
|
|
40
|
+
nado_protocol/contracts/loader.py,sha256=_0W3ImcARs1bTu1lLMpHMrRNuEVYjrRWctvnEbKWoVg,1500
|
|
41
|
+
nado_protocol/contracts/types.py,sha256=AakP4Bjs5xe4S3l7XmAnVDw7wAiJRHTHyuHynJpui3w,4174
|
|
42
|
+
nado_protocol/engine_client/__init__.py,sha256=RE_MxQaQVIp0K5EDhR1_uTjLJgEJBx2fLnhepc3cuAg,1137
|
|
43
|
+
nado_protocol/engine_client/execute.py,sha256=I-PmmS7vCr0NEQPLujlrg55X_avXYhRNMQK-OpWxjng,16115
|
|
44
|
+
nado_protocol/engine_client/query.py,sha256=FWx7OXBEjhIDhEs-Gxsh-L80ZhYXp4ZbUvi_3LmKeBw,16264
|
|
45
|
+
nado_protocol/engine_client/types/__init__.py,sha256=f8uOkZrkvG9RpiEFKfrNlqEax4PnwDhttFdK9n7b0HM,2777
|
|
46
|
+
nado_protocol/engine_client/types/execute.py,sha256=1LyYj6JdUgOvQOomMqnJRCbVtvqWF5ajfkrNXLvge3I,21109
|
|
47
|
+
nado_protocol/engine_client/types/models.py,sha256=UTG0FuWoGZkkf2llJjOyyVRO1gI2Cmeh9XjPNS2U2c4,4930
|
|
48
|
+
nado_protocol/engine_client/types/query.py,sha256=xLniVwKzjEyq49H03E1aBAroPACrh0UnEvQOJDvpp6k,11893
|
|
49
|
+
nado_protocol/engine_client/types/stream.py,sha256=F_AKqU4pClzUcM6D9Dc79f6RmraahJzj2-hQSXtQ0vQ,159
|
|
50
|
+
nado_protocol/indexer_client/__init__.py,sha256=ea2exePtguCxJsBlisOQPtnFk8hRmFugeQAuSAaPhoc,922
|
|
51
|
+
nado_protocol/indexer_client/query.py,sha256=WXeJz6GIyBBrOm6AbZA2VEoQuIsGUdyb-YMHsqwVdEI,16338
|
|
52
|
+
nado_protocol/indexer_client/types/__init__.py,sha256=UfpOw-SXmpDTmtTPVxCgOiZyoN8Lksonc_SuJ7DUIYY,3570
|
|
53
|
+
nado_protocol/indexer_client/types/models.py,sha256=yGWiQEm2cyhs23T9XcegaWeUxEinfB5PuM-ZWfhGIOM,7676
|
|
54
|
+
nado_protocol/indexer_client/types/query.py,sha256=JAqAvFXX-nq51b8fAUqDOakjyeTfIWH1hBTxeyOp8TM,18800
|
|
55
|
+
nado_protocol/trigger_client/__init__.py,sha256=kD_WJWGOCDwX7GvGF5VGZibWR2uPYRcWpIWht31PYR4,545
|
|
56
|
+
nado_protocol/trigger_client/execute.py,sha256=aKnwsO07yrDDOH5kcjtrsmRclxkV6NUlqRJBdtdBmak,4608
|
|
57
|
+
nado_protocol/trigger_client/query.py,sha256=bRJDoBn2vMX8tihi_ZlX4o6zpioPtN9dCuYT8l317h4,2068
|
|
58
|
+
nado_protocol/trigger_client/types/__init__.py,sha256=Rj953ymGSNnVdOpDrwRuXmC_jhuPZU17BaSgBrc9cbk,183
|
|
59
|
+
nado_protocol/trigger_client/types/execute.py,sha256=03k1qjnSmK6Cyot9wGznUk7zydqjK1K6RLNg91VI-LI,2862
|
|
60
|
+
nado_protocol/trigger_client/types/models.py,sha256=umoevs0T59Ar6LJVzv6A6xzpH4NMDy07Bh25BOgod10,846
|
|
61
|
+
nado_protocol/trigger_client/types/query.py,sha256=D9IZpN-LYJGqswv7pJi0WPjeXD1K9wgeEnpAmRYTP7E,2073
|
|
62
|
+
nado_protocol/utils/__init__.py,sha256=CF2gay9f0bwX_7hNV48TWxz2FyVT5x8nfHrhe2uj8ks,939
|
|
63
|
+
nado_protocol/utils/backend.py,sha256=YuUUQUPr-epaUIWV7C6YQkwzvlZAuFXP4lOGJTaHXFk,3713
|
|
64
|
+
nado_protocol/utils/bytes32.py,sha256=FHeHs9Sf-S7GdFTF6ikuz_sEkM-fpRW-g3kbZawlMd4,5299
|
|
65
|
+
nado_protocol/utils/enum.py,sha256=_Ij7Ai1H_Bj0OPBjmLhGvQjATXYyqD0DLqpUC-br99s,99
|
|
66
|
+
nado_protocol/utils/exceptions.py,sha256=6RT21nNFRRj-cUC6mkd1-TRcZLEI1F4EbBayJXDDB4o,1641
|
|
67
|
+
nado_protocol/utils/execute.py,sha256=U2Pv-WAFqd_597fUndhQCyi1IMytci4nbhK5o9WzQ_A,12883
|
|
68
|
+
nado_protocol/utils/expiration.py,sha256=0fmi18V9_Z7pBglEShNBQJOH95kSX9Yp47nUJ6tNhZ8,1332
|
|
69
|
+
nado_protocol/utils/interest.py,sha256=pl5N2s7sux9Z0orPthdmFkldljIPwFTpLx1XC9k1oQk,2498
|
|
70
|
+
nado_protocol/utils/math.py,sha256=hGbClWHRY5D0fIo5tHyT3_riWvf8WfsXJtqMs8pIQTs,1290
|
|
71
|
+
nado_protocol/utils/model.py,sha256=feU7cp0mSgNp-Z0dmC6VSFA6Mkjv3rNfoXdqsoZ7uGU,2087
|
|
72
|
+
nado_protocol/utils/nonce.py,sha256=RCfumncClJ6OOGNrgY-qfX97_ZJeLp3FZ3N-sc2unio,982
|
|
73
|
+
nado_protocol/utils/subaccount.py,sha256=WJ7lgU2RekuzJAZH-hhCTbIBlRsl2oHozBm7OEMRV74,495
|
|
74
|
+
nado_protocol/utils/time.py,sha256=tEwmrkc5VdzKLlgkJIAq2ce-nhrduJZNtVPydrrnTHs,360
|
|
75
|
+
nado_protocol-0.1.0.dist-info/METADATA,sha256=dbxFnBWaLdbdDfhQqSsRVOoXZo9JrFD_JLMEyIhv_Co,4080
|
|
76
|
+
nado_protocol-0.1.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
77
|
+
nado_protocol-0.1.0.dist-info/entry_points.txt,sha256=7xKEtptcsqTaufonQUvwWqa4HfXdUX_p-HIRQygPvYI,336
|
|
78
|
+
nado_protocol-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
client-sanity=sanity.nado_client:run
|
|
3
|
+
contracts-sanity=sanity.contracts:run
|
|
4
|
+
engine-sanity=sanity.engine_client:run
|
|
5
|
+
indexer-sanity=sanity.indexer_client:run
|
|
6
|
+
isolated-sanity=sanity.isolated:run
|
|
7
|
+
rewards-sanity=sanity.rewards:run
|
|
8
|
+
signing-sanity=sanity.signing:run
|
|
9
|
+
test=pytest:main
|
|
10
|
+
trigger-sanity=sanity.trigger_client:run
|
|
11
|
+
|