x10-python-trading-starknet 1.2.0__tar.gz → 1.3.0__tar.gz
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.
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/PKG-INFO +2 -2
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/pyproject.toml +2 -2
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/assets.py +29 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/balances.py +12 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/configuration.py +8 -3
- x10_python_trading_starknet-1.3.0/x10/perpetual/limit_order_object_settlement.py +72 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/order_object_settlement.py +35 -3
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/orders.py +14 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/simple_client/simple_trading_client.py +7 -4
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/trading_client/account_module.py +11 -1
- x10_python_trading_starknet-1.2.0/x10/perpetual/trading_client/markets_information_module.py → x10_python_trading_starknet-1.3.0/x10/perpetual/trading_client/info_markets_module.py +1 -1
- x10_python_trading_starknet-1.3.0/x10/perpetual/trading_client/info_module.py +29 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/trading_client/trading_client.py +38 -14
- x10_python_trading_starknet-1.3.0/x10/perpetual/trading_client/vault_module.py +177 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/transfer_object.py +2 -1
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/http.py +9 -1
- x10_python_trading_starknet-1.2.0/x10/perpetual/trading_client/info_module.py +0 -13
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/LICENSE +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/README.md +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/__init__.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/config.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/errors.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/__init__.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/accounts.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/amounts.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/bridges.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/candles.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/clients.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/fees.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/funding_rates.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/markets.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/order_object.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/orderbook.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/orderbooks.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/positions.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/stream_client/__init__.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/stream_client/perpetual_stream_connection.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/stream_client/stream_client.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/trades.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/trading_client/__init__.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/trading_client/base_module.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/trading_client/order_management_module.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/trading_client/testnet_module.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/transfers.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/user_client/__init__.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/user_client/l1_signing.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/user_client/onboarding.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/user_client/user_client.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/withdrawal_object.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/withdrawals.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/__init__.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/date.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/log.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/model.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/nonce.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/order.py +0 -0
- {x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/string.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: x10-python-trading-starknet
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Python client for X10 API
|
|
5
5
|
Home-page: https://github.com/x10xchange/python_sdk
|
|
6
6
|
Author: X10
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
16
16
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
17
|
Requires-Dist: aiohttp (>=3.10.11)
|
|
18
18
|
Requires-Dist: eth-account (>=0.12.0)
|
|
19
|
-
Requires-Dist: fast-stark-crypto (==0.
|
|
19
|
+
Requires-Dist: fast-stark-crypto (==0.5.0)
|
|
20
20
|
Requires-Dist: pydantic (>=2.9.0)
|
|
21
21
|
Requires-Dist: pyyaml (>=6.0.1)
|
|
22
22
|
Requires-Dist: sortedcontainers (>=2.4.0)
|
|
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
5
5
|
|
|
6
6
|
[tool.poetry]
|
|
7
7
|
name = "x10-python-trading-starknet"
|
|
8
|
-
version = "1.
|
|
8
|
+
version = "1.3.0"
|
|
9
9
|
description = "Python client for X10 API"
|
|
10
10
|
authors = ["X10 <tech@ex10.org>"]
|
|
11
11
|
repository = "https://github.com/x10xchange/python_sdk"
|
|
@@ -24,7 +24,7 @@ packages = [{ include = "x10" }]
|
|
|
24
24
|
[tool.poetry.dependencies]
|
|
25
25
|
aiohttp = ">=3.10.11"
|
|
26
26
|
eth-account = ">=0.12.0"
|
|
27
|
-
fast-stark-crypto = "==0.
|
|
27
|
+
fast-stark-crypto = "==0.5.0"
|
|
28
28
|
pydantic = ">=2.9.0"
|
|
29
29
|
python = "^3.10"
|
|
30
30
|
pyyaml = ">=6.0.1"
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/assets.py
RENAMED
|
@@ -7,6 +7,21 @@ from strenum import StrEnum
|
|
|
7
7
|
from x10.utils.model import HexValue, X10BaseModel
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
class AssetModel(X10BaseModel):
|
|
11
|
+
id: int
|
|
12
|
+
name: str
|
|
13
|
+
symbol: str
|
|
14
|
+
precision: int
|
|
15
|
+
is_active: bool
|
|
16
|
+
is_collateral: bool
|
|
17
|
+
starkex_id: HexValue
|
|
18
|
+
starkex_resolution: int
|
|
19
|
+
l1_id: str
|
|
20
|
+
l1_resolution: int
|
|
21
|
+
version: int
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# FIXME: Replace with AssetModel
|
|
10
25
|
@dataclass
|
|
11
26
|
class Asset:
|
|
12
27
|
id: int
|
|
@@ -37,6 +52,20 @@ class Asset:
|
|
|
37
52
|
raise ValueError("Only collateral assets have an L1 representation")
|
|
38
53
|
return int(internal * Decimal(self.l1_resolution))
|
|
39
54
|
|
|
55
|
+
@staticmethod
|
|
56
|
+
def from_model(model: AssetModel):
|
|
57
|
+
return Asset(
|
|
58
|
+
id=model.id,
|
|
59
|
+
name=model.name,
|
|
60
|
+
precision=model.precision,
|
|
61
|
+
active=model.is_active,
|
|
62
|
+
is_collateral=model.is_collateral,
|
|
63
|
+
settlement_external_id=hex(model.starkex_id),
|
|
64
|
+
settlement_resolution=model.starkex_resolution,
|
|
65
|
+
l1_external_id=model.l1_id,
|
|
66
|
+
l1_resolution=model.l1_resolution,
|
|
67
|
+
)
|
|
68
|
+
|
|
40
69
|
|
|
41
70
|
class AssetOperationType(StrEnum):
|
|
42
71
|
CLAIM = "CLAIM"
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/balances.py
RENAMED
|
@@ -13,3 +13,15 @@ class BalanceModel(X10BaseModel):
|
|
|
13
13
|
initial_margin: Decimal
|
|
14
14
|
margin_ratio: Decimal
|
|
15
15
|
updated_time: int
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SpotBalanceModel(X10BaseModel):
|
|
19
|
+
account_id: int
|
|
20
|
+
asset: str
|
|
21
|
+
balance: Decimal
|
|
22
|
+
index_price: Decimal
|
|
23
|
+
notional_value: Decimal
|
|
24
|
+
contribution_factor: Decimal
|
|
25
|
+
equity_contribution: Decimal
|
|
26
|
+
available_to_withdraw: Decimal
|
|
27
|
+
updated_at: int
|
|
@@ -13,6 +13,7 @@ class StarknetDomain:
|
|
|
13
13
|
class EndpointConfig:
|
|
14
14
|
"""
|
|
15
15
|
Attributes:
|
|
16
|
+
chain_rpc_url (str): Field is deprecated and will be removed.
|
|
16
17
|
asset_operations_contract (str): Field is deprecated and will be removed.
|
|
17
18
|
collateral_asset_contract (str): Field is deprecated and will be removed.
|
|
18
19
|
collateral_asset_on_chain_id (str): Field is deprecated and will be removed.
|
|
@@ -33,6 +34,8 @@ class EndpointConfig:
|
|
|
33
34
|
collateral_decimals: int
|
|
34
35
|
collateral_asset_id: str
|
|
35
36
|
|
|
37
|
+
vault_asset_name: str
|
|
38
|
+
|
|
36
39
|
|
|
37
40
|
TESTNET_CONFIG = EndpointConfig(
|
|
38
41
|
chain_rpc_url="https://rpc.sepolia.org",
|
|
@@ -40,12 +43,13 @@ TESTNET_CONFIG = EndpointConfig(
|
|
|
40
43
|
stream_url="wss://api.starknet.sepolia.extended.exchange/stream.extended.exchange/v1",
|
|
41
44
|
onboarding_url="https://api.starknet.sepolia.extended.exchange",
|
|
42
45
|
signing_domain="starknet.sepolia.extended.exchange",
|
|
46
|
+
starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_SEPOLIA", revision="1"),
|
|
43
47
|
asset_operations_contract="",
|
|
44
|
-
collateral_asset_contract="
|
|
48
|
+
collateral_asset_contract="0x05ba91db44b3e6a4485b5dbfcb17d791faa9cb6890a42731b66b3536b28b8ed5",
|
|
45
49
|
collateral_asset_on_chain_id="0x1",
|
|
46
50
|
collateral_decimals=6,
|
|
47
51
|
collateral_asset_id="0x1",
|
|
48
|
-
|
|
52
|
+
vault_asset_name="XVS",
|
|
49
53
|
)
|
|
50
54
|
|
|
51
55
|
MAINNET_CONFIG = EndpointConfig(
|
|
@@ -54,10 +58,11 @@ MAINNET_CONFIG = EndpointConfig(
|
|
|
54
58
|
stream_url="wss://api.starknet.extended.exchange/stream.extended.exchange/v1",
|
|
55
59
|
onboarding_url="https://api.starknet.extended.exchange",
|
|
56
60
|
signing_domain="extended.exchange",
|
|
61
|
+
starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_MAIN", revision="1"),
|
|
57
62
|
asset_operations_contract="",
|
|
58
63
|
collateral_asset_contract="",
|
|
59
64
|
collateral_asset_on_chain_id="0x1",
|
|
60
65
|
collateral_decimals=6,
|
|
61
66
|
collateral_asset_id="0x1",
|
|
62
|
-
|
|
67
|
+
vault_asset_name="XVS",
|
|
63
68
|
)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import decimal
|
|
2
|
+
from datetime import timedelta
|
|
3
|
+
|
|
4
|
+
from x10.perpetual.accounts import StarkPerpetualAccount
|
|
5
|
+
from x10.perpetual.amounts import HumanReadableAmount, StarkAmount
|
|
6
|
+
from x10.perpetual.assets import Asset, AssetModel
|
|
7
|
+
from x10.perpetual.configuration import StarknetDomain
|
|
8
|
+
from x10.perpetual.order_object_settlement import (
|
|
9
|
+
calculate_order_settlement_expiration,
|
|
10
|
+
hash_limit_order,
|
|
11
|
+
)
|
|
12
|
+
from x10.perpetual.orders import LimitOrderSettlementModel
|
|
13
|
+
from x10.utils.date import utc_now
|
|
14
|
+
from x10.utils.model import SettlementSignatureModel
|
|
15
|
+
from x10.utils.nonce import generate_nonce
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def create_order_settlement_data(
|
|
19
|
+
*,
|
|
20
|
+
quote_amount,
|
|
21
|
+
base_amount,
|
|
22
|
+
position_id,
|
|
23
|
+
quote_asset_model: AssetModel,
|
|
24
|
+
base_asset_model: AssetModel,
|
|
25
|
+
starknet_account: StarkPerpetualAccount,
|
|
26
|
+
starknet_domain: StarknetDomain,
|
|
27
|
+
is_buy: bool,
|
|
28
|
+
):
|
|
29
|
+
quote_asset = Asset.from_model(quote_asset_model)
|
|
30
|
+
base_asset = Asset.from_model(base_asset_model)
|
|
31
|
+
|
|
32
|
+
quote_amount_human = HumanReadableAmount(
|
|
33
|
+
asset=quote_asset,
|
|
34
|
+
value=-quote_amount if is_buy else quote_amount,
|
|
35
|
+
)
|
|
36
|
+
base_amount_human = HumanReadableAmount(
|
|
37
|
+
asset=base_asset,
|
|
38
|
+
value=base_amount if is_buy else -base_amount,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
quote_amount_stark = quote_amount_human.to_stark_amount(decimal.Context(rounding=decimal.ROUND_UP))
|
|
42
|
+
base_amount_stark = base_amount_human.to_stark_amount(decimal.Context(rounding=decimal.ROUND_UP))
|
|
43
|
+
|
|
44
|
+
nonce = generate_nonce()
|
|
45
|
+
expire_time = utc_now() + timedelta(hours=1)
|
|
46
|
+
order_hash = hash_limit_order(
|
|
47
|
+
amount_base=base_amount_stark,
|
|
48
|
+
amount_quote=quote_amount_stark,
|
|
49
|
+
max_fee=StarkAmount(0, quote_asset),
|
|
50
|
+
nonce=nonce,
|
|
51
|
+
position_id=position_id,
|
|
52
|
+
expiration_timestamp=expire_time,
|
|
53
|
+
public_key=starknet_account.public_key,
|
|
54
|
+
starknet_domain=starknet_domain,
|
|
55
|
+
)
|
|
56
|
+
order_signature = starknet_account.sign(order_hash)
|
|
57
|
+
|
|
58
|
+
settlement = LimitOrderSettlementModel(
|
|
59
|
+
base_amount=base_amount_stark.value,
|
|
60
|
+
quote_amount=quote_amount_stark.value,
|
|
61
|
+
fee_amount=0,
|
|
62
|
+
base_asset_id=int(base_asset.settlement_external_id, 16),
|
|
63
|
+
quote_asset_id=int(quote_asset.settlement_external_id, 16),
|
|
64
|
+
fee_asset_id=int(quote_asset.settlement_external_id, 16),
|
|
65
|
+
expiration_timestamp=calculate_order_settlement_expiration(expire_time),
|
|
66
|
+
nonce=nonce,
|
|
67
|
+
receiver_position_id=position_id,
|
|
68
|
+
sender_position_id=position_id,
|
|
69
|
+
signature=SettlementSignatureModel(r=order_signature[0], s=order_signature[1]),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return settlement, quote_amount_human, base_amount_human
|
|
@@ -4,7 +4,7 @@ from datetime import datetime, timedelta
|
|
|
4
4
|
from decimal import Decimal
|
|
5
5
|
from typing import Callable, Optional, Tuple
|
|
6
6
|
|
|
7
|
-
from fast_stark_crypto import get_order_msg_hash
|
|
7
|
+
from fast_stark_crypto import get_limit_order_msg_hash, get_order_msg_hash
|
|
8
8
|
|
|
9
9
|
from x10.perpetual.amounts import (
|
|
10
10
|
ROUNDING_BUY_CONTEXT,
|
|
@@ -45,13 +45,45 @@ class SettlementDataCtx:
|
|
|
45
45
|
starknet_domain: StarknetDomain
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def
|
|
48
|
+
def calculate_order_settlement_expiration(expiration_timestamp: datetime):
|
|
49
49
|
expire_time_with_buffer = expiration_timestamp + timedelta(days=14)
|
|
50
50
|
expire_time_as_seconds = math.ceil(expire_time_with_buffer.timestamp())
|
|
51
51
|
|
|
52
52
|
return expire_time_as_seconds
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
def hash_limit_order(
|
|
56
|
+
amount_base: StarkAmount,
|
|
57
|
+
amount_quote: StarkAmount,
|
|
58
|
+
max_fee: StarkAmount,
|
|
59
|
+
nonce: int,
|
|
60
|
+
position_id: int,
|
|
61
|
+
expiration_timestamp: datetime,
|
|
62
|
+
public_key: int,
|
|
63
|
+
starknet_domain: StarknetDomain,
|
|
64
|
+
) -> int:
|
|
65
|
+
synthetic_asset = amount_base.asset
|
|
66
|
+
collateral_asset = amount_quote.asset
|
|
67
|
+
|
|
68
|
+
return get_limit_order_msg_hash(
|
|
69
|
+
source_position_id=position_id,
|
|
70
|
+
receive_position_id=position_id,
|
|
71
|
+
base_asset_id=int(synthetic_asset.settlement_external_id, 16),
|
|
72
|
+
base_amount=amount_base.value,
|
|
73
|
+
quote_asset_id=int(collateral_asset.settlement_external_id, 16),
|
|
74
|
+
quote_amount=amount_quote.value,
|
|
75
|
+
fee_amount=max_fee.value,
|
|
76
|
+
fee_asset_id=int(collateral_asset.settlement_external_id, 16),
|
|
77
|
+
expiration=calculate_order_settlement_expiration(expiration_timestamp),
|
|
78
|
+
salt=nonce,
|
|
79
|
+
user_public_key=public_key,
|
|
80
|
+
domain_name=starknet_domain.name,
|
|
81
|
+
domain_version=starknet_domain.version,
|
|
82
|
+
domain_chain_id=starknet_domain.chain_id,
|
|
83
|
+
domain_revision=starknet_domain.revision,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
55
87
|
def hash_order(
|
|
56
88
|
amount_synthetic: StarkAmount,
|
|
57
89
|
amount_collateral: StarkAmount,
|
|
@@ -73,7 +105,7 @@ def hash_order(
|
|
|
73
105
|
quote_amount=amount_collateral.value,
|
|
74
106
|
fee_amount=max_fee.value,
|
|
75
107
|
fee_asset_id=int(collateral_asset.settlement_external_id, 16),
|
|
76
|
-
expiration=
|
|
108
|
+
expiration=calculate_order_settlement_expiration(expiration_timestamp),
|
|
77
109
|
salt=nonce,
|
|
78
110
|
user_public_key=public_key,
|
|
79
111
|
domain_name=starknet_domain.name,
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/orders.py
RENAMED
|
@@ -109,6 +109,20 @@ class StarkSettlementModel(X10BaseModel):
|
|
|
109
109
|
collateral_position: Decimal
|
|
110
110
|
|
|
111
111
|
|
|
112
|
+
class LimitOrderSettlementModel(X10BaseModel):
|
|
113
|
+
base_amount: int
|
|
114
|
+
quote_amount: int
|
|
115
|
+
fee_amount: int
|
|
116
|
+
base_asset_id: HexValue
|
|
117
|
+
quote_asset_id: HexValue
|
|
118
|
+
fee_asset_id: HexValue
|
|
119
|
+
expiration_timestamp: int
|
|
120
|
+
nonce: int
|
|
121
|
+
receiver_position_id: int
|
|
122
|
+
sender_position_id: int
|
|
123
|
+
signature: SettlementSignatureModel
|
|
124
|
+
|
|
125
|
+
|
|
112
126
|
class StarkDebuggingOrderAmountsModel(X10BaseModel):
|
|
113
127
|
collateral_amount: Decimal
|
|
114
128
|
fee_amount: Decimal
|
|
@@ -13,15 +13,14 @@ from x10.perpetual.orders import (
|
|
|
13
13
|
OpenOrderModel,
|
|
14
14
|
OrderSide,
|
|
15
15
|
OrderStatus,
|
|
16
|
+
OrderType,
|
|
16
17
|
TimeInForce,
|
|
17
18
|
)
|
|
18
19
|
from x10.perpetual.stream_client.perpetual_stream_connection import (
|
|
19
20
|
PerpetualStreamConnection,
|
|
20
21
|
)
|
|
21
22
|
from x10.perpetual.stream_client.stream_client import PerpetualStreamClient
|
|
22
|
-
from x10.perpetual.trading_client.
|
|
23
|
-
MarketsInformationModule,
|
|
24
|
-
)
|
|
23
|
+
from x10.perpetual.trading_client.info_markets_module import InfoMarketsModule
|
|
25
24
|
from x10.perpetual.trading_client.order_management_module import OrderManagementModule
|
|
26
25
|
from x10.utils.http import WrappedStreamResponse
|
|
27
26
|
|
|
@@ -81,7 +80,7 @@ class BlockingTradingClient:
|
|
|
81
80
|
)
|
|
82
81
|
self.__endpoint_config = endpoint_config
|
|
83
82
|
self.__account = account
|
|
84
|
-
self.__market_module =
|
|
83
|
+
self.__market_module = InfoMarketsModule(endpoint_config, api_key=account.api_key)
|
|
85
84
|
self.__orders_module = OrderManagementModule(endpoint_config, api_key=account.api_key)
|
|
86
85
|
self.__markets: Union[None, Dict[str, MarketModel]] = None
|
|
87
86
|
self.__stream_client: PerpetualStreamClient = PerpetualStreamClient(api_url=endpoint_config.stream_url)
|
|
@@ -203,6 +202,8 @@ class BlockingTradingClient:
|
|
|
203
202
|
builder_fee: Decimal | None = None,
|
|
204
203
|
builder_id: int | None = None,
|
|
205
204
|
time_in_force: TimeInForce = TimeInForce.GTT,
|
|
205
|
+
reduce_only: bool = False,
|
|
206
|
+
order_type: OrderType = OrderType.LIMIT,
|
|
206
207
|
) -> TimedOpenOrderModel:
|
|
207
208
|
market = (await self.get_markets()).get(market_name)
|
|
208
209
|
if not market:
|
|
@@ -211,10 +212,12 @@ class BlockingTradingClient:
|
|
|
211
212
|
order: NewOrderModel = create_order_object(
|
|
212
213
|
account=self.__account,
|
|
213
214
|
market=market,
|
|
215
|
+
order_type=order_type,
|
|
214
216
|
amount_of_synthetic=amount_of_synthetic,
|
|
215
217
|
price=price,
|
|
216
218
|
side=side,
|
|
217
219
|
post_only=post_only,
|
|
220
|
+
reduce_only=reduce_only,
|
|
218
221
|
previous_order_external_id=previous_order_external_id,
|
|
219
222
|
starknet_domain=self.__endpoint_config.starknet_domain,
|
|
220
223
|
order_external_id=external_id,
|
|
@@ -7,7 +7,7 @@ from x10.perpetual.assets import (
|
|
|
7
7
|
AssetOperationStatus,
|
|
8
8
|
AssetOperationType,
|
|
9
9
|
)
|
|
10
|
-
from x10.perpetual.balances import BalanceModel
|
|
10
|
+
from x10.perpetual.balances import BalanceModel, SpotBalanceModel
|
|
11
11
|
from x10.perpetual.bridges import BridgesConfig, Quote
|
|
12
12
|
from x10.perpetual.clients import ClientModel
|
|
13
13
|
from x10.perpetual.fees import TradingFeeModel
|
|
@@ -125,6 +125,16 @@ class AccountModule(BaseModule):
|
|
|
125
125
|
|
|
126
126
|
return await send_get_request(await self.get_session(), url, list[OpenOrderModel], api_key=self._get_api_key())
|
|
127
127
|
|
|
128
|
+
async def get_spot_balances(self) -> WrappedApiResponse[List[SpotBalanceModel]]:
|
|
129
|
+
"""
|
|
130
|
+
https://api.docs.extended.exchange/#get-spot-balance
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
url = self._get_url("/user/spot/balances")
|
|
134
|
+
return await send_get_request(
|
|
135
|
+
await self.get_session(), url, List[SpotBalanceModel], api_key=self._get_api_key()
|
|
136
|
+
)
|
|
137
|
+
|
|
128
138
|
async def get_trades(
|
|
129
139
|
self,
|
|
130
140
|
market_names: Optional[List[str]] = None,
|
|
@@ -10,7 +10,7 @@ from x10.utils.date import to_epoch_millis
|
|
|
10
10
|
from x10.utils.http import send_get_request
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class InfoMarketsModule(BaseModule):
|
|
14
14
|
async def get_markets(self, *, market_names: Optional[List[str]] = None):
|
|
15
15
|
"""
|
|
16
16
|
https://api.docs.extended.exchange/#get-markets
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from x10.perpetual.assets import AssetModel
|
|
5
|
+
from x10.perpetual.trading_client.base_module import BaseModule
|
|
6
|
+
from x10.utils.http import send_get_request
|
|
7
|
+
from x10.utils.model import X10BaseModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class _SettingsModel(X10BaseModel):
|
|
11
|
+
stark_ex_contract_address: str
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InfoModule(BaseModule):
|
|
15
|
+
async def get_settings(self):
|
|
16
|
+
url = self._get_url("/info/settings")
|
|
17
|
+
return await send_get_request(await self.get_session(), url, _SettingsModel)
|
|
18
|
+
|
|
19
|
+
async def get_assets(self):
|
|
20
|
+
url = self._get_url("/info/assets")
|
|
21
|
+
return await send_get_request(await self.get_session(), url, List[AssetModel])
|
|
22
|
+
|
|
23
|
+
async def get_assets_dict(self):
|
|
24
|
+
assets = await self.get_assets()
|
|
25
|
+
return {asset.name: asset for asset in assets.data}
|
|
26
|
+
|
|
27
|
+
async def get_asset_price(self, *, asset_name: str):
|
|
28
|
+
url = self._get_url("/info/assets/<asset_name>/price", asset_name=asset_name)
|
|
29
|
+
return await send_get_request(await self.get_session(), url, Decimal)
|
|
@@ -14,12 +14,11 @@ from x10.perpetual.orders import (
|
|
|
14
14
|
TimeInForce,
|
|
15
15
|
)
|
|
16
16
|
from x10.perpetual.trading_client.account_module import AccountModule
|
|
17
|
+
from x10.perpetual.trading_client.info_markets_module import InfoMarketsModule
|
|
17
18
|
from x10.perpetual.trading_client.info_module import InfoModule
|
|
18
|
-
from x10.perpetual.trading_client.markets_information_module import (
|
|
19
|
-
MarketsInformationModule,
|
|
20
|
-
)
|
|
21
19
|
from x10.perpetual.trading_client.order_management_module import OrderManagementModule
|
|
22
20
|
from x10.perpetual.trading_client.testnet_module import TestnetModule
|
|
21
|
+
from x10.perpetual.trading_client.vault_module import VaultModule
|
|
23
22
|
from x10.utils.date import utc_now
|
|
24
23
|
from x10.utils.http import WrappedApiResponse
|
|
25
24
|
from x10.utils.log import get_logger
|
|
@@ -33,14 +32,16 @@ class PerpetualTradingClient:
|
|
|
33
32
|
"""
|
|
34
33
|
|
|
35
34
|
__markets: Dict[str, MarketModel] | None
|
|
36
|
-
|
|
35
|
+
|
|
36
|
+
__config: EndpointConfig
|
|
37
|
+
__stark_account: StarkPerpetualAccount | None
|
|
37
38
|
|
|
38
39
|
__info_module: InfoModule
|
|
39
|
-
|
|
40
|
+
__info_markets_module: InfoMarketsModule
|
|
40
41
|
__account_module: AccountModule
|
|
41
42
|
__order_management_module: OrderManagementModule
|
|
43
|
+
__vault_module: VaultModule
|
|
42
44
|
__testnet_module: TestnetModule
|
|
43
|
-
__config: EndpointConfig
|
|
44
45
|
|
|
45
46
|
async def place_order(
|
|
46
47
|
self,
|
|
@@ -65,7 +66,7 @@ class PerpetualTradingClient:
|
|
|
65
66
|
raise ValueError("Stark account is not set")
|
|
66
67
|
|
|
67
68
|
if not self.__markets:
|
|
68
|
-
self.__markets = await self.
|
|
69
|
+
self.__markets = await self.__info_markets_module.get_markets_dict()
|
|
69
70
|
|
|
70
71
|
market = self.__markets.get(market_name)
|
|
71
72
|
|
|
@@ -98,24 +99,43 @@ class PerpetualTradingClient:
|
|
|
98
99
|
return await self.__order_management_module.place_order(order)
|
|
99
100
|
|
|
100
101
|
async def close(self):
|
|
101
|
-
await self.
|
|
102
|
+
await self.__info_markets_module.close_session()
|
|
102
103
|
await self.__account_module.close_session()
|
|
103
104
|
await self.__order_management_module.close_session()
|
|
104
105
|
|
|
106
|
+
async def __aenter__(self):
|
|
107
|
+
return self
|
|
108
|
+
|
|
109
|
+
async def __aexit__(self, exc_type, exc_value, traceback):
|
|
110
|
+
await self.close()
|
|
111
|
+
|
|
105
112
|
def __init__(self, endpoint_config: EndpointConfig, stark_account: StarkPerpetualAccount | None = None):
|
|
106
113
|
api_key = stark_account.api_key if stark_account else None
|
|
107
114
|
|
|
115
|
+
self.__config = endpoint_config
|
|
108
116
|
self.__markets = None
|
|
109
|
-
|
|
110
|
-
if stark_account:
|
|
111
|
-
self.__stark_account = stark_account
|
|
117
|
+
self.__stark_account = stark_account
|
|
112
118
|
|
|
113
119
|
self.__info_module = InfoModule(endpoint_config)
|
|
114
|
-
self.
|
|
120
|
+
self.__info_markets_module = InfoMarketsModule(endpoint_config, api_key=api_key)
|
|
115
121
|
self.__account_module = AccountModule(endpoint_config, api_key=api_key, stark_account=stark_account)
|
|
116
122
|
self.__order_management_module = OrderManagementModule(endpoint_config, api_key=api_key)
|
|
123
|
+
self.__vault_module = VaultModule(
|
|
124
|
+
endpoint_config,
|
|
125
|
+
info_module=self.__info_module,
|
|
126
|
+
account_module=self.__account_module,
|
|
127
|
+
account=stark_account,
|
|
128
|
+
api_key=api_key,
|
|
129
|
+
)
|
|
117
130
|
self.__testnet_module = TestnetModule(endpoint_config, api_key=api_key, account_module=self.__account_module)
|
|
118
|
-
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def config(self):
|
|
134
|
+
return self.__config
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def stark_account(self):
|
|
138
|
+
return self.__stark_account
|
|
119
139
|
|
|
120
140
|
@property
|
|
121
141
|
def info(self):
|
|
@@ -123,7 +143,7 @@ class PerpetualTradingClient:
|
|
|
123
143
|
|
|
124
144
|
@property
|
|
125
145
|
def markets_info(self):
|
|
126
|
-
return self.
|
|
146
|
+
return self.__info_markets_module
|
|
127
147
|
|
|
128
148
|
@property
|
|
129
149
|
def account(self):
|
|
@@ -136,3 +156,7 @@ class PerpetualTradingClient:
|
|
|
136
156
|
@property
|
|
137
157
|
def testnet(self):
|
|
138
158
|
return self.__testnet_module
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def vault(self):
|
|
162
|
+
return self.__vault_module
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import decimal
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
from types import NoneType
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from x10.errors import X10Error
|
|
7
|
+
from x10.perpetual.accounts import StarkPerpetualAccount
|
|
8
|
+
from x10.perpetual.configuration import EndpointConfig
|
|
9
|
+
from x10.perpetual.limit_order_object_settlement import create_order_settlement_data
|
|
10
|
+
from x10.perpetual.orders import LimitOrderSettlementModel
|
|
11
|
+
from x10.perpetual.trading_client.account_module import AccountModule
|
|
12
|
+
from x10.perpetual.trading_client.base_module import BaseModule
|
|
13
|
+
from x10.perpetual.trading_client.info_module import InfoModule
|
|
14
|
+
from x10.utils.http import send_post_request
|
|
15
|
+
from x10.utils.model import X10BaseModel
|
|
16
|
+
|
|
17
|
+
# Protects from an error on shares pricing fluctuations.
|
|
18
|
+
VAULT_SHARES_SLIPPAGE_PCT = Decimal("0.65")
|
|
19
|
+
COLLATERAL_ASSET_NAME = "USD"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class DepositRequestModel(X10BaseModel):
|
|
23
|
+
from_account_id: int
|
|
24
|
+
to_account_id: int
|
|
25
|
+
collateral: Decimal
|
|
26
|
+
shares: Decimal
|
|
27
|
+
settlement: LimitOrderSettlementModel
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class WithdrawRequestModel(X10BaseModel):
|
|
31
|
+
from_account_id: int
|
|
32
|
+
to_account_id: int
|
|
33
|
+
collateral: Decimal
|
|
34
|
+
shares: Decimal
|
|
35
|
+
settlement: LimitOrderSettlementModel
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class VaultModule(BaseModule):
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
endpoint_config: EndpointConfig,
|
|
42
|
+
*,
|
|
43
|
+
info_module: InfoModule,
|
|
44
|
+
account_module: AccountModule,
|
|
45
|
+
account: Optional[StarkPerpetualAccount] = None,
|
|
46
|
+
api_key: Optional[str] = None,
|
|
47
|
+
):
|
|
48
|
+
super().__init__(endpoint_config, api_key=api_key)
|
|
49
|
+
|
|
50
|
+
self._info_module = info_module
|
|
51
|
+
self._account_module = account_module
|
|
52
|
+
self._account = account
|
|
53
|
+
|
|
54
|
+
async def get_vault_share_balance(self) -> Decimal:
|
|
55
|
+
spot_balances = (await self._account_module.get_spot_balances()).data
|
|
56
|
+
if spot_balances is None:
|
|
57
|
+
raise X10Error("Failed to get spot balances")
|
|
58
|
+
vault_asset_balances = filter(lambda b: b.asset == self._get_endpoint_config().vault_asset_name, spot_balances)
|
|
59
|
+
total_vault_asset_balance = sum(map(lambda b: b.balance, vault_asset_balances), Decimal(0))
|
|
60
|
+
return total_vault_asset_balance
|
|
61
|
+
|
|
62
|
+
async def deposit_to_vault(self, *, collateral_amount: Decimal) -> None:
|
|
63
|
+
if self._account is None:
|
|
64
|
+
raise X10Error("Stark account is required for vault operations")
|
|
65
|
+
|
|
66
|
+
account_info = (await self._account_module.get_account()).data
|
|
67
|
+
assets = await self._info_module.get_assets_dict()
|
|
68
|
+
vault_asset_price = (
|
|
69
|
+
await self._info_module.get_asset_price(asset_name=self._get_endpoint_config().vault_asset_name)
|
|
70
|
+
).data
|
|
71
|
+
|
|
72
|
+
assert account_info is not None
|
|
73
|
+
assert vault_asset_price is not None
|
|
74
|
+
|
|
75
|
+
position_id = account_info.l2_vault
|
|
76
|
+
collateral_asset = assets[COLLATERAL_ASSET_NAME]
|
|
77
|
+
vault_asset = assets[self._get_endpoint_config().vault_asset_name]
|
|
78
|
+
vault_shares_expected = self.__calc_vault_shares_expected(
|
|
79
|
+
collateral_amount,
|
|
80
|
+
vault_asset_price,
|
|
81
|
+
vault_asset.precision,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
settlement, collateral_amount_human, shares_amount_human = create_order_settlement_data(
|
|
85
|
+
quote_amount=collateral_amount,
|
|
86
|
+
base_amount=vault_shares_expected,
|
|
87
|
+
position_id=position_id,
|
|
88
|
+
quote_asset_model=collateral_asset,
|
|
89
|
+
base_asset_model=vault_asset,
|
|
90
|
+
starknet_account=self._account,
|
|
91
|
+
starknet_domain=self._get_endpoint_config().starknet_domain,
|
|
92
|
+
is_buy=True,
|
|
93
|
+
)
|
|
94
|
+
deposit_request = DepositRequestModel(
|
|
95
|
+
from_account_id=account_info.id,
|
|
96
|
+
to_account_id=account_info.id,
|
|
97
|
+
collateral=abs(collateral_amount_human.value),
|
|
98
|
+
shares=abs(shares_amount_human.value),
|
|
99
|
+
settlement=settlement,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
url = self._get_url("/vault/user/deposits")
|
|
103
|
+
resp = await send_post_request(
|
|
104
|
+
await self.get_session(),
|
|
105
|
+
url,
|
|
106
|
+
NoneType,
|
|
107
|
+
json=deposit_request.to_api_request_json(exclude_none=True),
|
|
108
|
+
api_key=self._get_api_key(),
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if resp.error is not None:
|
|
112
|
+
raise X10Error(f"Deposit error: {resp.error}")
|
|
113
|
+
|
|
114
|
+
async def withdraw_from_vault(self, *, shares_amount: Decimal) -> None:
|
|
115
|
+
if self._account is None:
|
|
116
|
+
raise X10Error("Stark account is required for vault operations")
|
|
117
|
+
|
|
118
|
+
assets = await self._info_module.get_assets_dict()
|
|
119
|
+
account_info = (await self._account_module.get_account()).data
|
|
120
|
+
vault_asset_price = (
|
|
121
|
+
await self._info_module.get_asset_price(asset_name=self._get_endpoint_config().vault_asset_name)
|
|
122
|
+
).data
|
|
123
|
+
|
|
124
|
+
assert account_info is not None
|
|
125
|
+
assert vault_asset_price is not None
|
|
126
|
+
|
|
127
|
+
position_id = account_info.l2_vault
|
|
128
|
+
collateral_asset = assets[COLLATERAL_ASSET_NAME]
|
|
129
|
+
vault_asset = assets[self._get_endpoint_config().vault_asset_name]
|
|
130
|
+
collateral_amount_expected = self.__calc_collateral_amount_expected(
|
|
131
|
+
shares_amount,
|
|
132
|
+
vault_asset_price,
|
|
133
|
+
vault_asset.precision,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
settlement, collateral_amount_human, shares_amount_human = create_order_settlement_data(
|
|
137
|
+
quote_amount=collateral_amount_expected,
|
|
138
|
+
base_amount=shares_amount,
|
|
139
|
+
position_id=position_id,
|
|
140
|
+
quote_asset_model=collateral_asset,
|
|
141
|
+
base_asset_model=vault_asset,
|
|
142
|
+
starknet_account=self._account,
|
|
143
|
+
starknet_domain=self._get_endpoint_config().starknet_domain,
|
|
144
|
+
is_buy=False,
|
|
145
|
+
)
|
|
146
|
+
withdraw_request = WithdrawRequestModel(
|
|
147
|
+
from_account_id=account_info.id,
|
|
148
|
+
to_account_id=account_info.id,
|
|
149
|
+
collateral=abs(collateral_amount_human.value),
|
|
150
|
+
shares=abs(shares_amount_human.value),
|
|
151
|
+
settlement=settlement,
|
|
152
|
+
)
|
|
153
|
+
url = self._get_url("/vault/user/withdrawals")
|
|
154
|
+
resp = await send_post_request(
|
|
155
|
+
await self.get_session(),
|
|
156
|
+
url,
|
|
157
|
+
NoneType,
|
|
158
|
+
json=withdraw_request.to_api_request_json(exclude_none=True),
|
|
159
|
+
api_key=self._get_api_key(),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
if resp.error is not None:
|
|
163
|
+
raise X10Error(f"Withdraw error: {resp.error}")
|
|
164
|
+
|
|
165
|
+
@staticmethod
|
|
166
|
+
def __calc_vault_shares_expected(
|
|
167
|
+
collateral_amount: Decimal, vault_asset_price: Decimal, vault_asset_precision: int
|
|
168
|
+
) -> Decimal:
|
|
169
|
+
shares = collateral_amount / vault_asset_price * VAULT_SHARES_SLIPPAGE_PCT
|
|
170
|
+
return shares.quantize(Decimal("10") ** -vault_asset_precision, rounding=decimal.ROUND_FLOOR)
|
|
171
|
+
|
|
172
|
+
@staticmethod
|
|
173
|
+
def __calc_collateral_amount_expected(
|
|
174
|
+
shares_amount: Decimal, vault_asset_price: Decimal, collateral_asset_precision: int
|
|
175
|
+
) -> Decimal:
|
|
176
|
+
collateral_amount = shares_amount * vault_asset_price * VAULT_SHARES_SLIPPAGE_PCT
|
|
177
|
+
return collateral_amount.quantize(Decimal("10") ** -collateral_asset_precision, rounding=decimal.ROUND_FLOOR)
|
|
@@ -29,6 +29,7 @@ def calc_expiration_timestamp():
|
|
|
29
29
|
return expire_time_with_buffer_seconds
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
# FIXME: Transfers are broken
|
|
32
33
|
def create_transfer_object(
|
|
33
34
|
from_vault: int,
|
|
34
35
|
to_vault: int,
|
|
@@ -76,5 +77,5 @@ def create_transfer_object(
|
|
|
76
77
|
to_vault=to_vault,
|
|
77
78
|
amount=amount,
|
|
78
79
|
settlement=settlement,
|
|
79
|
-
transferred_asset=config.
|
|
80
|
+
transferred_asset=config.collateral_asset_on_chain_id,
|
|
80
81
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
import re
|
|
3
|
+
from types import NoneType
|
|
3
4
|
from typing import Any, Dict, Generic, List, Optional, Sequence, Type, TypeVar, Union
|
|
4
5
|
|
|
5
6
|
import aiohttp
|
|
@@ -16,7 +17,7 @@ from x10.utils.model import X10BaseModel
|
|
|
16
17
|
LOGGER = get_logger(__name__)
|
|
17
18
|
CLIENT_TIMEOUT = ClientTimeout(total=DEFAULT_REQUEST_TIMEOUT_SECONDS)
|
|
18
19
|
|
|
19
|
-
ApiResponseType = TypeVar("ApiResponseType", bound=Union[int, X10BaseModel, Sequence[X10BaseModel]])
|
|
20
|
+
ApiResponseType = TypeVar("ApiResponseType", bound=Union[int, X10BaseModel, Sequence[X10BaseModel], None])
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class RateLimitException(X10Error):
|
|
@@ -89,6 +90,13 @@ def parse_response_to_model(
|
|
|
89
90
|
) -> WrappedApiResponse[ApiResponseType]:
|
|
90
91
|
# Read this to get more context re the type ignore:
|
|
91
92
|
# https://github.com/python/mypy/issues/13619
|
|
93
|
+
|
|
94
|
+
if model_class == NoneType:
|
|
95
|
+
return WrappedApiResponse[None](
|
|
96
|
+
status=ResponseStatus.OK,
|
|
97
|
+
data=None,
|
|
98
|
+
) # type: ignore
|
|
99
|
+
|
|
92
100
|
return WrappedApiResponse[model_class].model_validate_json(response_text) # type: ignore[valid-type]
|
|
93
101
|
|
|
94
102
|
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from x10.perpetual.trading_client.base_module import BaseModule
|
|
2
|
-
from x10.utils.http import send_get_request
|
|
3
|
-
from x10.utils.model import X10BaseModel
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class _SettingsModel(X10BaseModel):
|
|
7
|
-
stark_ex_contract_address: str
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class InfoModule(BaseModule):
|
|
11
|
-
async def get_settings(self):
|
|
12
|
-
url = self._get_url("/info/settings")
|
|
13
|
-
return await send_get_request(await self.get_session(), url, _SettingsModel)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/__init__.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/accounts.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/amounts.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/bridges.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/candles.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/clients.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/fees.py
RENAMED
|
File without changes
|
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/markets.py
RENAMED
|
File without changes
|
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/orderbook.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/orderbooks.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/positions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/trades.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/transfers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/perpetual/withdrawals.py
RENAMED
|
File without changes
|
{x10_python_trading_starknet-1.2.0 → x10_python_trading_starknet-1.3.0}/x10/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|