From aec3bd3834ee7e952620f7e3f535efd11840d337 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 09:15:23 +0400 Subject: [PATCH 01/19] Unify configs --- x10/config.py | 13 +++++++------ x10/{perpetual => }/configuration.py | 20 +++++++++++++++----- x10/errors.py | 8 ++++++++ x10/utils/http.py | 6 ++++-- x10/version.py | 3 +++ 5 files changed, 37 insertions(+), 13 deletions(-) rename x10/{perpetual => }/configuration.py (90%) create mode 100644 x10/version.py diff --git a/x10/config.py b/x10/config.py index 4a9fb17..1671e97 100644 --- a/x10/config.py +++ b/x10/config.py @@ -3,16 +3,17 @@ from x10.models.fee import TradingFeeModel -BTC_USD_MARKET = "BTC-USD" -SOL_USD_MARKET = "SOL-USD" -ADA_USD_MARKET = "ADA-USD" -ETH_USD_MARKET = "ETH-USD" +# BTC_USD_MARKET = "BTC-USD" +# SOL_USD_MARKET = "SOL-USD" +# ADA_USD_MARKET = "ADA-USD" +# ETH_USD_MARKET = "ETH-USD" +# FIXME: Move to config DEFAULT_MARKET_PRICE_SLIPPAGE = Decimal("0.0075") DEFAULT_REQUEST_TIMEOUT_SECONDS = 500 -SDK_VERSION = importlib.metadata.version("x10-python-trading-starknet") -USER_AGENT = f"X10PythonTradingClient/{SDK_VERSION}" + +# FIXME: Move to config DEFAULT_FEES = TradingFeeModel( market="BTC-USD", maker_fee_rate=(Decimal("2") / Decimal("10000")), diff --git a/x10/perpetual/configuration.py b/x10/configuration.py similarity index 90% rename from x10/perpetual/configuration.py rename to x10/configuration.py index 02dfeb0..d3c88de 100644 --- a/x10/perpetual/configuration.py +++ b/x10/configuration.py @@ -10,7 +10,7 @@ class StarknetDomain: @dataclass(kw_only=True) -class EndpointConfig: +class EndpointsConfig: """ Attributes: chain_rpc_url (str): Field is deprecated and will be removed. @@ -25,8 +25,6 @@ class EndpointConfig: api_base_url: str stream_url: str onboarding_url: str - signing_domain: str - starknet_domain: StarknetDomain asset_operations_contract: str collateral_asset_contract: str @@ -37,7 +35,19 @@ class EndpointConfig: vault_asset_name: str -TESTNET_CONFIG = EndpointConfig( +@dataclass(kw_only=True) +class SigningConfig: + signing_domain: str + starknet_domain: StarknetDomain + + +@dataclass(kw_only=True) +class Config: + endpoints: EndpointsConfig + signing: SigningConfig + + +TESTNET_CONFIG = EndpointsConfig( chain_rpc_url="https://rpc.sepolia.org", api_base_url="https://api.starknet.sepolia.extended.exchange/api/v1", stream_url="wss://api.starknet.sepolia.extended.exchange/stream.extended.exchange/v1", @@ -52,7 +62,7 @@ class EndpointConfig: vault_asset_name="XVS", ) -MAINNET_CONFIG = EndpointConfig( +MAINNET_CONFIG = EndpointsConfig( chain_rpc_url="", api_base_url="https://api.starknet.extended.exchange/api/v1", stream_url="wss://api.starknet.extended.exchange/stream.extended.exchange/v1", diff --git a/x10/errors.py b/x10/errors.py index 6bdf77c..8c2632a 100644 --- a/x10/errors.py +++ b/x10/errors.py @@ -1,2 +1,10 @@ class X10Error(Exception): pass + + +class AppError(X10Error): + pass + + +class ApiError(X10Error): + pass diff --git a/x10/utils/http.py b/x10/utils/http.py index 20ca774..7d8b118 100644 --- a/x10/utils/http.py +++ b/x10/utils/http.py @@ -8,14 +8,16 @@ from pydantic import GetCoreSchemaHandler from pydantic_core import CoreSchema, core_schema from strenum import StrEnum +from version import SDK_VERSION -from x10.config import DEFAULT_REQUEST_TIMEOUT_SECONDS, USER_AGENT +from x10.config import DEFAULT_REQUEST_TIMEOUT_SECONDS from x10.errors import X10Error from x10.models.base import X10BaseModel from x10.utils.log import get_logger LOGGER = get_logger(__name__) -CLIENT_TIMEOUT = ClientTimeout(total=DEFAULT_REQUEST_TIMEOUT_SECONDS) +USER_AGENT = f"X10PythonTradingClient/{SDK_VERSION}" +# CLIENT_TIMEOUT = ClientTimeout(total=DEFAULT_REQUEST_TIMEOUT_SECONDS) ApiResponseType = TypeVar("ApiResponseType", bound=Union[int, X10BaseModel, Sequence[X10BaseModel], None]) diff --git a/x10/version.py b/x10/version.py new file mode 100644 index 0000000..36b1fc8 --- /dev/null +++ b/x10/version.py @@ -0,0 +1,3 @@ +import importlib.metadata + +SDK_VERSION = importlib.metadata.version("x10-python-trading-starknet") From 2562771da9cf3a97812e8176537dc93a3680249e Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 09:21:43 +0400 Subject: [PATCH 02/19] Unify configs --- x10/configuration.py | 80 ++++++++++++++++++++++------------- x10/core/stark_account.py | 10 ++--- x10/perpetual/order_object.py | 3 +- 3 files changed, 57 insertions(+), 36 deletions(-) diff --git a/x10/configuration.py b/x10/configuration.py index d3c88de..b520296 100644 --- a/x10/configuration.py +++ b/x10/configuration.py @@ -1,7 +1,8 @@ from dataclasses import dataclass +from decimal import Decimal -@dataclass(kw_only=True) +@dataclass(kw_only=True, frozen=True) class StarknetDomain: name: str version: str @@ -9,7 +10,7 @@ class StarknetDomain: revision: str -@dataclass(kw_only=True) +@dataclass(kw_only=True, frozen=True) class EndpointsConfig: """ Attributes: @@ -34,45 +35,64 @@ class EndpointsConfig: vault_asset_name: str +# DEFAULT_MARKET_PRICE_SLIPPAGE = Decimal("0.0075") +# DEFAULT_REQUEST_TIMEOUT_SECONDS = 500 +# +# +# # FIXME: Move to config +# DEFAULT_FEES = TradingFeeModel( +# market="BTC-USD", +# maker_fee_rate=(Decimal("2") / Decimal("10000")), +# taker_fee_rate=(Decimal("5") / Decimal("10000")), +# builder_fee_rate=Decimal("0"), +# ) + +@dataclass(kw_only=True, frozen=True) +class Config: + default_market_price_slippage: Decimal + default_request_timeout_seconds: int + default_maker_fee_rate: Decimal + default_maker_fee_rate: Decimal -@dataclass(kw_only=True) -class SigningConfig: signing_domain: str starknet_domain: StarknetDomain - -@dataclass(kw_only=True) -class Config: endpoints: EndpointsConfig - signing: SigningConfig -TESTNET_CONFIG = EndpointsConfig( - chain_rpc_url="https://rpc.sepolia.org", - api_base_url="https://api.starknet.sepolia.extended.exchange/api/v1", - stream_url="wss://api.starknet.sepolia.extended.exchange/stream.extended.exchange/v1", - onboarding_url="https://api.starknet.sepolia.extended.exchange", +TESTNET_CONFIG = Config( signing_domain="starknet.sepolia.extended.exchange", starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_SEPOLIA", revision="1"), - asset_operations_contract="", - collateral_asset_contract="0x05ba91db44b3e6a4485b5dbfcb17d791faa9cb6890a42731b66b3536b28b8ed5", - collateral_asset_on_chain_id="0x1", - collateral_decimals=6, - collateral_asset_id="0x1", - vault_asset_name="XVS", + + endpoints=EndpointsConfig( + chain_rpc_url="https://rpc.sepolia.org", + api_base_url="https://api.starknet.sepolia.extended.exchange/api/v1", + stream_url="wss://api.starknet.sepolia.extended.exchange/stream.extended.exchange/v1", + onboarding_url="https://api.starknet.sepolia.extended.exchange", + asset_operations_contract="", + collateral_asset_contract="0x05ba91db44b3e6a4485b5dbfcb17d791faa9cb6890a42731b66b3536b28b8ed5", + collateral_asset_on_chain_id="0x1", + collateral_decimals=6, + collateral_asset_id="0x1", + vault_asset_name="XVS", + ) ) -MAINNET_CONFIG = EndpointsConfig( - chain_rpc_url="", - api_base_url="https://api.starknet.extended.exchange/api/v1", - stream_url="wss://api.starknet.extended.exchange/stream.extended.exchange/v1", - onboarding_url="https://api.starknet.extended.exchange", + +MAINNET_CONFIG = Config( signing_domain="extended.exchange", starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_MAIN", revision="1"), - asset_operations_contract="", - collateral_asset_contract="", - collateral_asset_on_chain_id="0x1", - collateral_decimals=6, - collateral_asset_id="0x1", - vault_asset_name="XVS", + + endpoints=EndpointsConfig( + chain_rpc_url="", + api_base_url="https://api.starknet.extended.exchange/api/v1", + stream_url="wss://api.starknet.extended.exchange/stream.extended.exchange/v1", + onboarding_url="https://api.starknet.extended.exchange", + asset_operations_contract="", + collateral_asset_contract="", + collateral_asset_on_chain_id="0x1", + collateral_decimals=6, + collateral_asset_id="0x1", + vault_asset_name="XVS", + ) ) diff --git a/x10/core/stark_account.py b/x10/core/stark_account.py index 3eb1eec..292c300 100644 --- a/x10/core/stark_account.py +++ b/x10/core/stark_account.py @@ -15,7 +15,7 @@ class StarkPerpetualAccount: __vault: int __private_key: int __public_key: int - __trading_fee: Dict[str, TradingFeeModel] + # __trading_fee: Dict[str, TradingFeeModel] def __init__(self, vault: int | str, private_key: str, public_key: str, api_key: str): assert is_hex_string(private_key) @@ -32,7 +32,7 @@ def __init__(self, vault: int | str, private_key: str, public_key: str, api_key: self.__private_key = int(private_key, base=16) self.__public_key = int(public_key, base=16) self.__api_key = api_key - self.__trading_fee = {} + # self.__trading_fee = {} @property def vault(self): @@ -46,9 +46,9 @@ def public_key(self): def api_key(self): return self.__api_key - @property - def trading_fee(self): - return self.__trading_fee + # @property + # def trading_fee(self): + # return self.__trading_fee def sign(self, msg_hash: int) -> Tuple[int, int]: return sign(private_key=self.__private_key, msg_hash=msg_hash) diff --git a/x10/perpetual/order_object.py b/x10/perpetual/order_object.py index 70b3b38..ebbb507 100644 --- a/x10/perpetual/order_object.py +++ b/x10/perpetual/order_object.py @@ -77,7 +77,8 @@ def create_order_object( if expire_time is None: expire_time = utc_now() + timedelta(hours=1) - fees = account.trading_fee.get(market.name, DEFAULT_FEES) + # FIXME: Replace with explicit fee param + # fees = account.trading_fee.get(market.name, DEFAULT_FEES) return __create_order_object( market=market, From b8d8ec6f5ec4df610db34e59f931f00ca42080c2 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 09:25:06 +0400 Subject: [PATCH 03/19] Unify configs --- x10/_config.py | 22 +++++++++ x10/config.py | 106 +++++++++++++++++++++++++++++++++++++------ x10/configuration.py | 98 --------------------------------------- 3 files changed, 113 insertions(+), 113 deletions(-) create mode 100644 x10/_config.py delete mode 100644 x10/configuration.py diff --git a/x10/_config.py b/x10/_config.py new file mode 100644 index 0000000..1671e97 --- /dev/null +++ b/x10/_config.py @@ -0,0 +1,22 @@ +import importlib.metadata +from decimal import Decimal + +from x10.models.fee import TradingFeeModel + +# BTC_USD_MARKET = "BTC-USD" +# SOL_USD_MARKET = "SOL-USD" +# ADA_USD_MARKET = "ADA-USD" +# ETH_USD_MARKET = "ETH-USD" + +# FIXME: Move to config +DEFAULT_MARKET_PRICE_SLIPPAGE = Decimal("0.0075") +DEFAULT_REQUEST_TIMEOUT_SECONDS = 500 + + +# FIXME: Move to config +DEFAULT_FEES = TradingFeeModel( + market="BTC-USD", + maker_fee_rate=(Decimal("2") / Decimal("10000")), + taker_fee_rate=(Decimal("5") / Decimal("10000")), + builder_fee_rate=Decimal("0"), +) diff --git a/x10/config.py b/x10/config.py index 1671e97..9b79538 100644 --- a/x10/config.py +++ b/x10/config.py @@ -1,22 +1,98 @@ -import importlib.metadata +from dataclasses import dataclass from decimal import Decimal -from x10.models.fee import TradingFeeModel -# BTC_USD_MARKET = "BTC-USD" -# SOL_USD_MARKET = "SOL-USD" -# ADA_USD_MARKET = "ADA-USD" -# ETH_USD_MARKET = "ETH-USD" +@dataclass(kw_only=True, frozen=True) +class StarknetDomain: + name: str + version: str + chain_id: str + revision: str -# FIXME: Move to config -DEFAULT_MARKET_PRICE_SLIPPAGE = Decimal("0.0075") -DEFAULT_REQUEST_TIMEOUT_SECONDS = 500 +@dataclass(kw_only=True, frozen=True) +class EndpointsConfig: + """ + Attributes: + chain_rpc_url (str): Field is deprecated and will be removed. + asset_operations_contract (str): Field is deprecated and will be removed. + collateral_asset_contract (str): Field is deprecated and will be removed. + collateral_asset_on_chain_id (str): Field is deprecated and will be removed. + collateral_decimals (int): Field is deprecated and will be removed. + collateral_asset_id (str): Field is deprecated and will be removed. + """ -# FIXME: Move to config -DEFAULT_FEES = TradingFeeModel( - market="BTC-USD", - maker_fee_rate=(Decimal("2") / Decimal("10000")), - taker_fee_rate=(Decimal("5") / Decimal("10000")), - builder_fee_rate=Decimal("0"), + chain_rpc_url: str + api_base_url: str + stream_url: str + onboarding_url: str + + asset_operations_contract: str + collateral_asset_contract: str + collateral_asset_on_chain_id: str + collateral_decimals: int + collateral_asset_id: str + + vault_asset_name: str + + +@dataclass(kw_only=True, frozen=True) +class Config: + default_market_price_slippage: Decimal + default_request_timeout_seconds: int + default_maker_fee_rate: Decimal + default_taker_fee_rate: Decimal + default_builder_fee_rate: Decimal + + signing_domain: str + starknet_domain: StarknetDomain + + endpoints: EndpointsConfig + + +TESTNET_CONFIG = Config( + default_market_price_slippage=Decimal("0.0075"), + # FIXME: Reduce + default_request_timeout_seconds=500, + default_maker_fee_rate=Decimal("0.0002"), + default_taker_fee_rate=Decimal("0.0005"), + default_builder_fee_rate=Decimal("0"), + signing_domain="starknet.sepolia.extended.exchange", + starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_SEPOLIA", revision="1"), + endpoints=EndpointsConfig( + chain_rpc_url="https://rpc.sepolia.org", + api_base_url="https://api.starknet.sepolia.extended.exchange/api/v1", + stream_url="wss://api.starknet.sepolia.extended.exchange/stream.extended.exchange/v1", + onboarding_url="https://api.starknet.sepolia.extended.exchange", + asset_operations_contract="", + collateral_asset_contract="0x05ba91db44b3e6a4485b5dbfcb17d791faa9cb6890a42731b66b3536b28b8ed5", + collateral_asset_on_chain_id="0x1", + collateral_decimals=6, + collateral_asset_id="0x1", + vault_asset_name="XVS", + ), +) + + +MAINNET_CONFIG = Config( + default_market_price_slippage=Decimal("0.0075"), + # FIXME: Reduce + default_request_timeout_seconds=500, + default_maker_fee_rate=Decimal("0.0002"), + default_taker_fee_rate=Decimal("0.0005"), + default_builder_fee_rate=Decimal("0"), + signing_domain="extended.exchange", + starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_MAIN", revision="1"), + endpoints=EndpointsConfig( + chain_rpc_url="", + api_base_url="https://api.starknet.extended.exchange/api/v1", + stream_url="wss://api.starknet.extended.exchange/stream.extended.exchange/v1", + onboarding_url="https://api.starknet.extended.exchange", + asset_operations_contract="", + collateral_asset_contract="", + collateral_asset_on_chain_id="0x1", + collateral_decimals=6, + collateral_asset_id="0x1", + vault_asset_name="XVS", + ), ) diff --git a/x10/configuration.py b/x10/configuration.py deleted file mode 100644 index b520296..0000000 --- a/x10/configuration.py +++ /dev/null @@ -1,98 +0,0 @@ -from dataclasses import dataclass -from decimal import Decimal - - -@dataclass(kw_only=True, frozen=True) -class StarknetDomain: - name: str - version: str - chain_id: str - revision: str - - -@dataclass(kw_only=True, frozen=True) -class EndpointsConfig: - """ - Attributes: - chain_rpc_url (str): Field is deprecated and will be removed. - asset_operations_contract (str): Field is deprecated and will be removed. - collateral_asset_contract (str): Field is deprecated and will be removed. - collateral_asset_on_chain_id (str): Field is deprecated and will be removed. - collateral_decimals (int): Field is deprecated and will be removed. - collateral_asset_id (str): Field is deprecated and will be removed. - """ - - chain_rpc_url: str - api_base_url: str - stream_url: str - onboarding_url: str - - asset_operations_contract: str - collateral_asset_contract: str - collateral_asset_on_chain_id: str - collateral_decimals: int - collateral_asset_id: str - - vault_asset_name: str - -# DEFAULT_MARKET_PRICE_SLIPPAGE = Decimal("0.0075") -# DEFAULT_REQUEST_TIMEOUT_SECONDS = 500 -# -# -# # FIXME: Move to config -# DEFAULT_FEES = TradingFeeModel( -# market="BTC-USD", -# maker_fee_rate=(Decimal("2") / Decimal("10000")), -# taker_fee_rate=(Decimal("5") / Decimal("10000")), -# builder_fee_rate=Decimal("0"), -# ) - -@dataclass(kw_only=True, frozen=True) -class Config: - default_market_price_slippage: Decimal - default_request_timeout_seconds: int - default_maker_fee_rate: Decimal - default_maker_fee_rate: Decimal - - signing_domain: str - starknet_domain: StarknetDomain - - endpoints: EndpointsConfig - - -TESTNET_CONFIG = Config( - signing_domain="starknet.sepolia.extended.exchange", - starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_SEPOLIA", revision="1"), - - endpoints=EndpointsConfig( - chain_rpc_url="https://rpc.sepolia.org", - api_base_url="https://api.starknet.sepolia.extended.exchange/api/v1", - stream_url="wss://api.starknet.sepolia.extended.exchange/stream.extended.exchange/v1", - onboarding_url="https://api.starknet.sepolia.extended.exchange", - asset_operations_contract="", - collateral_asset_contract="0x05ba91db44b3e6a4485b5dbfcb17d791faa9cb6890a42731b66b3536b28b8ed5", - collateral_asset_on_chain_id="0x1", - collateral_decimals=6, - collateral_asset_id="0x1", - vault_asset_name="XVS", - ) -) - - -MAINNET_CONFIG = Config( - signing_domain="extended.exchange", - starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_MAIN", revision="1"), - - endpoints=EndpointsConfig( - chain_rpc_url="", - api_base_url="https://api.starknet.extended.exchange/api/v1", - stream_url="wss://api.starknet.extended.exchange/stream.extended.exchange/v1", - onboarding_url="https://api.starknet.extended.exchange", - asset_operations_contract="", - collateral_asset_contract="", - collateral_asset_on_chain_id="0x1", - collateral_decimals=6, - collateral_asset_id="0x1", - vault_asset_name="XVS", - ) -) From 86e0d1abdb50ee89c057211544ca1c22a41a04d5 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 09:26:06 +0400 Subject: [PATCH 04/19] Unify configs --- x10/errors.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/x10/errors.py b/x10/errors.py index 8c2632a..6bdf77c 100644 --- a/x10/errors.py +++ b/x10/errors.py @@ -1,10 +1,2 @@ class X10Error(Exception): pass - - -class AppError(X10Error): - pass - - -class ApiError(X10Error): - pass From 92af85c414e2a2af059ed3e0efb2b331b775a673 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 09:27:43 +0400 Subject: [PATCH 05/19] Unify configs --- x10/config.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x10/config.py b/x10/config.py index 9b79538..de86cf2 100644 --- a/x10/config.py +++ b/x10/config.py @@ -38,12 +38,14 @@ class EndpointsConfig: @dataclass(kw_only=True, frozen=True) class Config: + # FIXME: Group? default_market_price_slippage: Decimal default_request_timeout_seconds: int default_maker_fee_rate: Decimal default_taker_fee_rate: Decimal default_builder_fee_rate: Decimal + # FIXME: Group? signing_domain: str starknet_domain: StarknetDomain From 681a320d64377aa5648a553e36842060c98e1834 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 10:42:25 +0400 Subject: [PATCH 06/19] Unify configs --- x10/config.py | 62 +++++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/x10/config.py b/x10/config.py index de86cf2..7fc53d3 100644 --- a/x10/config.py +++ b/x10/config.py @@ -10,6 +10,21 @@ class StarknetDomain: revision: str +@dataclass(kw_only=True, frozen=True) +class DefaultsConfig: + market_price_slippage: Decimal + request_timeout_seconds: int + maker_fee_rate: Decimal + taker_fee_rate: Decimal + builder_fee_rate: Decimal + + +@dataclass(kw_only=True, frozen=True) +class SigningConfig: + signing_domain: str + starknet_domain: StarknetDomain + + @dataclass(kw_only=True, frozen=True) class EndpointsConfig: """ @@ -38,29 +53,25 @@ class EndpointsConfig: @dataclass(kw_only=True, frozen=True) class Config: - # FIXME: Group? - default_market_price_slippage: Decimal - default_request_timeout_seconds: int - default_maker_fee_rate: Decimal - default_taker_fee_rate: Decimal - default_builder_fee_rate: Decimal - - # FIXME: Group? - signing_domain: str - starknet_domain: StarknetDomain - + defaults: DefaultsConfig + signing: SigningConfig endpoints: EndpointsConfig +DEFAULTS = DefaultsConfig( + market_price_slippage=Decimal("0.0075"), + request_timeout_seconds=500, + maker_fee_rate=Decimal("0.0002"), + taker_fee_rate=Decimal("0.0005"), + builder_fee_rate=Decimal("0"), +) + TESTNET_CONFIG = Config( - default_market_price_slippage=Decimal("0.0075"), - # FIXME: Reduce - default_request_timeout_seconds=500, - default_maker_fee_rate=Decimal("0.0002"), - default_taker_fee_rate=Decimal("0.0005"), - default_builder_fee_rate=Decimal("0"), - signing_domain="starknet.sepolia.extended.exchange", - starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_SEPOLIA", revision="1"), + defaults=DEFAULTS, + signing=SigningConfig( + signing_domain="starknet.sepolia.extended.exchange", + starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_SEPOLIA", revision="1"), + ), endpoints=EndpointsConfig( chain_rpc_url="https://rpc.sepolia.org", api_base_url="https://api.starknet.sepolia.extended.exchange/api/v1", @@ -77,14 +88,11 @@ class Config: MAINNET_CONFIG = Config( - default_market_price_slippage=Decimal("0.0075"), - # FIXME: Reduce - default_request_timeout_seconds=500, - default_maker_fee_rate=Decimal("0.0002"), - default_taker_fee_rate=Decimal("0.0005"), - default_builder_fee_rate=Decimal("0"), - signing_domain="extended.exchange", - starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_MAIN", revision="1"), + defaults=DEFAULTS, + signing=SigningConfig( + signing_domain="extended.exchange", + starknet_domain=StarknetDomain(name="Perpetuals", version="v0", chain_id="SN_MAIN", revision="1"), + ), endpoints=EndpointsConfig( chain_rpc_url="", api_base_url="https://api.starknet.extended.exchange/api/v1", From b4b8ad1e4330ffe79fb9b69b3fd5ccf907d863b8 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 10:53:20 +0400 Subject: [PATCH 07/19] Unify configs --- x10/config.py | 10 ++-------- x10/core/stark_account.py | 7 ------- x10/perpetual/order_object.py | 18 ++++++------------ x10/perpetual/order_object_settlement.py | 6 +++--- 4 files changed, 11 insertions(+), 30 deletions(-) diff --git a/x10/config.py b/x10/config.py index 7fc53d3..f4f0455 100644 --- a/x10/config.py +++ b/x10/config.py @@ -14,9 +14,7 @@ class StarknetDomain: class DefaultsConfig: market_price_slippage: Decimal request_timeout_seconds: int - maker_fee_rate: Decimal - taker_fee_rate: Decimal - builder_fee_rate: Decimal + taker_fee: Decimal @dataclass(kw_only=True, frozen=True) @@ -59,11 +57,7 @@ class Config: DEFAULTS = DefaultsConfig( - market_price_slippage=Decimal("0.0075"), - request_timeout_seconds=500, - maker_fee_rate=Decimal("0.0002"), - taker_fee_rate=Decimal("0.0005"), - builder_fee_rate=Decimal("0"), + market_price_slippage=Decimal("0.0075"), request_timeout_seconds=500, taker_fee=Decimal("0.0005") ) TESTNET_CONFIG = Config( diff --git a/x10/core/stark_account.py b/x10/core/stark_account.py index 292c300..206f355 100644 --- a/x10/core/stark_account.py +++ b/x10/core/stark_account.py @@ -2,7 +2,6 @@ from fast_stark_crypto import sign -from x10.models.fee import TradingFeeModel from x10.utils.string import is_hex_string @@ -15,7 +14,6 @@ class StarkPerpetualAccount: __vault: int __private_key: int __public_key: int - # __trading_fee: Dict[str, TradingFeeModel] def __init__(self, vault: int | str, private_key: str, public_key: str, api_key: str): assert is_hex_string(private_key) @@ -32,7 +30,6 @@ def __init__(self, vault: int | str, private_key: str, public_key: str, api_key: self.__private_key = int(private_key, base=16) self.__public_key = int(public_key, base=16) self.__api_key = api_key - # self.__trading_fee = {} @property def vault(self): @@ -46,9 +43,5 @@ def public_key(self): def api_key(self): return self.__api_key - # @property - # def trading_fee(self): - # return self.__trading_fee - def sign(self, msg_hash: int) -> Tuple[int, int]: return sign(private_key=self.__private_key, msg_hash=msg_hash) diff --git a/x10/perpetual/order_object.py b/x10/perpetual/order_object.py index ebbb507..5de7cc2 100644 --- a/x10/perpetual/order_object.py +++ b/x10/perpetual/order_object.py @@ -3,9 +3,8 @@ from decimal import Decimal from typing import Callable, Optional, Tuple -from x10.config import DEFAULT_FEES +from x10.config import StarknetDomain from x10.core.stark_account import StarkPerpetualAccount -from x10.models.fee import TradingFeeModel from x10.models.market import MarketModel from x10.models.order import ( CreateOrderConditionalTriggerModel, @@ -20,7 +19,6 @@ SelfTradeProtectionLevel, TimeInForce, ) -from x10.perpetual.configuration import StarknetDomain from x10.perpetual.order_object_settlement import ( SettlementDataCtx, create_order_settlement_data, @@ -62,6 +60,7 @@ def create_order_object( time_in_force: TimeInForce = TimeInForce.GTT, self_trade_protection_level: SelfTradeProtectionLevel = SelfTradeProtectionLevel.ACCOUNT, nonce: Optional[int] = None, + taker_fee: Decimal, builder_fee: Optional[Decimal] = None, builder_id: Optional[int] = None, reduce_only: bool = False, @@ -77,9 +76,6 @@ def create_order_object( if expire_time is None: expire_time = utc_now() + timedelta(hours=1) - # FIXME: Replace with explicit fee param - # fees = account.trading_fee.get(market.name, DEFAULT_FEES) - return __create_order_object( market=market, order_type=order_type, @@ -87,7 +83,6 @@ def create_order_object( price=price, side=side, collateral_position_id=account.vault, - fees=fees, signer=account.sign, public_key=account.public_key, exact_only=False, @@ -99,6 +94,7 @@ def create_order_object( self_trade_protection_level=self_trade_protection_level, starknet_domain=starknet_domain, nonce=nonce, + taker_fee=taker_fee, builder_fee=builder_fee, builder_id=builder_id, reduce_only=reduce_only, @@ -157,7 +153,6 @@ def __create_order_object( price: Decimal, side: OrderSide, collateral_position_id: int, - fees: TradingFeeModel, signer: Callable[[int], Tuple[int, int]], public_key: int, starknet_domain: StarknetDomain, @@ -169,6 +164,7 @@ def __create_order_object( time_in_force: TimeInForce = TimeInForce.GTT, self_trade_protection_level: SelfTradeProtectionLevel = SelfTradeProtectionLevel.ACCOUNT, nonce: Optional[int] = None, + taker_fee: Decimal, builder_fee: Optional[Decimal] = None, builder_id: Optional[int] = None, reduce_only: bool = False, @@ -223,11 +219,9 @@ def validate_tpsl_order(): if nonce is None: nonce = generate_nonce() - fee_rate = fees.taker_fee_rate - settlement_data_ctx = SettlementDataCtx( market=market, - fees=fees, + taker_fee=taker_fee, builder_fee=builder_fee, nonce=nonce, collateral_position_id=collateral_position_id, @@ -268,7 +262,7 @@ def create_tpsl_trigger_model(trigger_param: OrderTpslTriggerParam | None): post_only=post_only, time_in_force=time_in_force, expiry_epoch_millis=to_epoch_millis(expire_time), - fee=fee_rate, + fee=taker_fee, self_trade_protection_level=self_trade_protection_level, nonce=Decimal(nonce), cancel_id=previous_order_external_id, diff --git a/x10/perpetual/order_object_settlement.py b/x10/perpetual/order_object_settlement.py index 106e79b..5b9fabf 100644 --- a/x10/perpetual/order_object_settlement.py +++ b/x10/perpetual/order_object_settlement.py @@ -6,6 +6,7 @@ from fast_stark_crypto import get_limit_order_msg_hash, get_order_msg_hash +from x10.config import StarknetDomain from x10.core.amount import ( ROUNDING_BUY_CONTEXT, ROUNDING_FEE_CONTEXT, @@ -21,7 +22,6 @@ StarkDebuggingOrderAmountsModel, StarkSettlementModel, ) -from x10.perpetual.configuration import StarknetDomain @dataclass(kw_only=True) @@ -35,7 +35,7 @@ class OrderSettlementData: @dataclass(kw_only=True) class SettlementDataCtx: market: MarketModel - fees: TradingFeeModel + taker_fee: Decimal builder_fee: Optional[Decimal] nonce: int collateral_position_id: int @@ -127,7 +127,7 @@ def create_order_settlement_data( synthetic_amount_human = HumanReadableAmount(synthetic_amount, ctx.market.synthetic_asset) collateral_amount_human = HumanReadableAmount(synthetic_amount * price, ctx.market.collateral_asset) - total_fee = ctx.fees.taker_fee_rate + (ctx.builder_fee if ctx.builder_fee is not None else 0) + total_fee = ctx.taker_fee + (ctx.builder_fee if ctx.builder_fee is not None else 0) fee_amount_human = HumanReadableAmount( total_fee * collateral_amount_human.value, ctx.market.collateral_asset, From 3988eaf07f019b9dfa4f174d8cd3c584943259bb Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 10:53:52 +0400 Subject: [PATCH 08/19] Unify configs --- x10/core/stark_account.py | 7 +------ x10/perpetual/order_object_settlement.py | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/x10/core/stark_account.py b/x10/core/stark_account.py index 206f355..9fe1c26 100644 --- a/x10/core/stark_account.py +++ b/x10/core/stark_account.py @@ -1,4 +1,4 @@ -from typing import Dict, Tuple +from typing import Tuple from fast_stark_crypto import sign @@ -6,11 +6,6 @@ class StarkPerpetualAccount: - """ - Attributes: - __trading_fee (dict): Field is deprecated and will be removed. - """ - __vault: int __private_key: int __public_key: int diff --git a/x10/perpetual/order_object_settlement.py b/x10/perpetual/order_object_settlement.py index 5b9fabf..ea0a101 100644 --- a/x10/perpetual/order_object_settlement.py +++ b/x10/perpetual/order_object_settlement.py @@ -15,7 +15,6 @@ StarkAmount, ) from x10.models.base import SettlementSignatureModel -from x10.models.fee import TradingFeeModel from x10.models.market import MarketModel from x10.models.order import ( OrderSide, From db2db357e19c2f611d55f75ca27b5cf0d156ceda Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 12:44:07 +0400 Subject: [PATCH 09/19] Unify configs --- tests/perpetual/test_trading_client.py | 4 +-- x10/_config.py | 1 - x10/perpetual/trading_client/base_module.py | 19 +++++----- .../trading_client/trading_client.py | 22 ++++++------ x10/perpetual/user_client/user_client.py | 36 +++++++++++-------- x10/utils/http.py | 4 +-- 6 files changed, 46 insertions(+), 40 deletions(-) diff --git a/tests/perpetual/test_trading_client.py b/tests/perpetual/test_trading_client.py index 3b1eee7..26781a6 100644 --- a/tests/perpetual/test_trading_client.py +++ b/tests/perpetual/test_trading_client.py @@ -34,7 +34,7 @@ async def test_get_markets(aiohttp_server, create_btc_usd_market): url = f"http://{server.host}:{server.port}" endpoint_config = dataclasses.replace(TESTNET_CONFIG, api_base_url=url) - trading_client = PerpetualTradingClient(endpoint_config=endpoint_config) + trading_client = PerpetualTradingClient(config=endpoint_config) markets = await trading_client.markets_info.get_markets() assert_that(markets.status, equal_to("OK")) @@ -134,7 +134,7 @@ async def test_get_asset_operations(aiohttp_server, create_asset_operations, cre stark_account = create_trading_account() endpoint_config = endpoint_config = dataclasses.replace(TESTNET_CONFIG, api_base_url=url) - trading_client = PerpetualTradingClient(endpoint_config=endpoint_config, stark_account=stark_account) + trading_client = PerpetualTradingClient(config=endpoint_config, stark_account=stark_account) operations = await trading_client.account.asset_operations() assert_that(operations.status, equal_to("OK")) diff --git a/x10/_config.py b/x10/_config.py index 1671e97..31788ff 100644 --- a/x10/_config.py +++ b/x10/_config.py @@ -1,4 +1,3 @@ -import importlib.metadata from decimal import Decimal from x10.models.fee import TradingFeeModel diff --git a/x10/perpetual/trading_client/base_module.py b/x10/perpetual/trading_client/base_module.py index 650e35b..0ee3aa6 100644 --- a/x10/perpetual/trading_client/base_module.py +++ b/x10/perpetual/trading_client/base_module.py @@ -1,22 +1,23 @@ from typing import Dict, Optional import aiohttp +from aiohttp import ClientTimeout +from x10.config import Config from x10.core.stark_account import StarkPerpetualAccount from x10.errors import X10Error -from x10.perpetual.configuration import EndpointConfig -from x10.utils.http import CLIENT_TIMEOUT, get_url +from x10.utils.http import get_url class BaseModule: - __endpoint_config: EndpointConfig + __endpoint_config: Config __api_key: Optional[str] __stark_account: Optional[StarkPerpetualAccount] __session: Optional[aiohttp.ClientSession] def __init__( self, - endpoint_config: EndpointConfig, + endpoint_config: Config, *, api_key: Optional[str] = None, stark_account: Optional[StarkPerpetualAccount] = None, @@ -28,10 +29,10 @@ def __init__( self.__session = None def _get_url(self, path: str, *, query: Optional[Dict] = None, **path_params) -> str: - return get_url(f"{self.__endpoint_config.api_base_url}{path}", query=query, **path_params) + return get_url(f"{self._get_endpoint_config().api_base_url}{path}", query=query, **path_params) - def _get_endpoint_config(self) -> EndpointConfig: - return self.__endpoint_config + def _get_endpoint_config(self): + return self.__endpoint_config.endpoints def _get_api_key(self): if not self.__api_key: @@ -47,7 +48,9 @@ def _get_stark_account(self): async def get_session(self) -> aiohttp.ClientSession: if self.__session is None: - created_session = aiohttp.ClientSession(timeout=CLIENT_TIMEOUT) + created_session = aiohttp.ClientSession( + timeout=ClientTimeout(total=self.__endpoint_config.defaults.request_timeout_seconds) + ) self.__session = created_session return self.__session diff --git a/x10/perpetual/trading_client/trading_client.py b/x10/perpetual/trading_client/trading_client.py index 60aeed1..c6cfff4 100644 --- a/x10/perpetual/trading_client/trading_client.py +++ b/x10/perpetual/trading_client/trading_client.py @@ -2,6 +2,7 @@ from decimal import Decimal from typing import Dict, Optional +from x10.config import Config from x10.core.stark_account import StarkPerpetualAccount from x10.models.market import MarketModel from x10.models.order import ( @@ -11,7 +12,6 @@ SelfTradeProtectionLevel, TimeInForce, ) -from x10.perpetual.configuration import EndpointConfig from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object from x10.perpetual.trading_client.account_module import AccountModule from x10.perpetual.trading_client.info_markets_module import InfoMarketsModule @@ -33,7 +33,7 @@ class PerpetualTradingClient: __markets: Dict[str, MarketModel] | None - __config: EndpointConfig + __config: Config __stark_account: StarkPerpetualAccount | None __info_module: InfoModule @@ -87,7 +87,7 @@ async def place_order( expire_time=expire_time, time_in_force=time_in_force, self_trade_protection_level=self_trade_protection_level, - starknet_domain=self.__config.starknet_domain, + starknet_domain=self.__config.signing.starknet_domain, order_external_id=external_id, builder_fee=builder_fee, builder_id=builder_id, @@ -109,25 +109,25 @@ async def __aenter__(self): async def __aexit__(self, exc_type, exc_value, traceback): await self.close() - def __init__(self, endpoint_config: EndpointConfig, stark_account: StarkPerpetualAccount | None = None): + def __init__(self, config: Config, stark_account: StarkPerpetualAccount | None = None): api_key = stark_account.api_key if stark_account else None - self.__config = endpoint_config + self.__config = config self.__markets = None self.__stark_account = stark_account - self.__info_module = InfoModule(endpoint_config) - self.__info_markets_module = InfoMarketsModule(endpoint_config, api_key=api_key) - self.__account_module = AccountModule(endpoint_config, api_key=api_key, stark_account=stark_account) - self.__order_management_module = OrderManagementModule(endpoint_config, api_key=api_key) + self.__info_module = InfoModule(config) + self.__info_markets_module = InfoMarketsModule(config, api_key=api_key) + self.__account_module = AccountModule(config, api_key=api_key, stark_account=stark_account) + self.__order_management_module = OrderManagementModule(config, api_key=api_key) self.__vault_module = VaultModule( - endpoint_config, + config, info_module=self.__info_module, account_module=self.__account_module, account=stark_account, api_key=api_key, ) - self.__testnet_module = TestnetModule(endpoint_config, api_key=api_key, account_module=self.__account_module) + self.__testnet_module = TestnetModule(config, api_key=api_key, account_module=self.__account_module) @property def config(self): diff --git a/x10/perpetual/user_client/user_client.py b/x10/perpetual/user_client/user_client.py index af6e91a..89c04e8 100644 --- a/x10/perpetual/user_client/user_client.py +++ b/x10/perpetual/user_client/user_client.py @@ -3,13 +3,14 @@ from typing import Callable, Dict, List, Optional import aiohttp +from aiohttp import ClientTimeout from eth_account import Account from eth_account.messages import encode_defunct from eth_account.signers.local import LocalAccount +from x10.config import Config from x10.errors import X10Error from x10.models.account import AccountModel, ApiKeyRequestModel, ApiKeyResponseModel -from x10.perpetual.configuration import EndpointConfig from x10.perpetual.user_client.onboarding import ( OnboardedClientModel, StarkKeyPair, @@ -17,7 +18,7 @@ get_onboarding_payload, get_sub_account_creation_payload, ) -from x10.utils.http import CLIENT_TIMEOUT, get_url, send_get_request, send_post_request +from x10.utils.http import get_url, send_get_request, send_post_request L1_AUTH_SIGNATURE_HEADER = "L1_SIGNATURE" L1_MESSAGE_TIME_HEADER = "L1_MESSAGE_TIME" @@ -35,13 +36,13 @@ class OnBoardedAccount: class UserClient: - __endpoint_config: EndpointConfig + __endpoint_config: Config __l1_private_key: Callable[[], str] __session: Optional[aiohttp.ClientSession] = None def __init__( self, - endpoint_config: EndpointConfig, + endpoint_config: Config, l1_private_key: Callable[[], str], ): super().__init__() @@ -53,7 +54,9 @@ def _get_url(self, base_url: str, path: str, *, query: Optional[Dict] = None, ** async def get_session(self) -> aiohttp.ClientSession: if self.__session is None: - created_session = aiohttp.ClientSession(timeout=CLIENT_TIMEOUT) + created_session = aiohttp.ClientSession( + timeout=ClientTimeout(total=self.__endpoint_config.defaults.request_timeout_seconds) + ) self.__session = created_session return self.__session @@ -66,16 +69,16 @@ async def close_session(self): async def onboard(self, referral_code: Optional[str] = None): signing_account: LocalAccount = Account.from_key(self.__l1_private_key()) key_pair = get_l2_keys_from_l1_account( - l1_account=signing_account, account_index=0, signing_domain=self.__endpoint_config.signing_domain + l1_account=signing_account, account_index=0, signing_domain=self.__endpoint_config.signing.signing_domain ) payload = get_onboarding_payload( signing_account, - signing_domain=self.__endpoint_config.signing_domain, + signing_domain=self.__endpoint_config.signing.signing_domain, key_pair=key_pair, referral_code=referral_code, - host=self.__endpoint_config.onboarding_url, + host=self._get_endpoint_config().onboarding_url, ) - url = self._get_url(self.__endpoint_config.onboarding_url, path="/auth/onboard") + url = self._get_url(self._get_endpoint_config().onboarding_url, path="/auth/onboard") onboarding_response = await send_post_request( await self.get_session(), url, OnboardedClientModel, json=payload.to_json() ) @@ -100,20 +103,20 @@ async def onboard_subaccount(self, account_index: int, description: str | None = key_pair = get_l2_keys_from_l1_account( l1_account=signing_account, account_index=account_index, - signing_domain=self.__endpoint_config.signing_domain, + signing_domain=self.__endpoint_config.signing.signing_domain, ) payload = get_sub_account_creation_payload( account_index=account_index, l1_address=signing_account.address, key_pair=key_pair, description=description, - host=self.__endpoint_config.onboarding_url, + host=self._get_endpoint_config().onboarding_url, ) headers = { L1_AUTH_SIGNATURE_HEADER: l1_signature.signature.hex(), L1_MESSAGE_TIME_HEADER: auth_time_string, } - url = self._get_url(self.__endpoint_config.onboarding_url, path=request_path) + url = self._get_url(self._get_endpoint_config().onboarding_url, path=request_path) try: onboarding_response = await send_post_request( @@ -149,7 +152,7 @@ async def get_accounts(self) -> List[OnBoardedAccount]: L1_AUTH_SIGNATURE_HEADER: l1_signature.signature.hex(), L1_MESSAGE_TIME_HEADER: auth_time_string, } - url = self._get_url(self.__endpoint_config.onboarding_url, path=request_path) + url = self._get_url(self._get_endpoint_config().onboarding_url, path=request_path) response = await send_get_request(await self.get_session(), url, List[AccountModel], request_headers=headers) accounts = response.data or [] @@ -159,7 +162,7 @@ async def get_accounts(self) -> List[OnBoardedAccount]: l2_key_pair=get_l2_keys_from_l1_account( l1_account=signing_account, account_index=account.account_index, - signing_domain=self.__endpoint_config.signing_domain, + signing_domain=self.__endpoint_config.signing.signing_domain, ), ) for account in accounts @@ -181,7 +184,7 @@ async def create_account_api_key(self, account: AccountModel, description: str | L1_MESSAGE_TIME_HEADER: auth_time_string, ACTIVE_ACCOUNT_HEADER: str(account.id), } - url = self._get_url(self.__endpoint_config.onboarding_url, path=request_path) + url = self._get_url(self._get_endpoint_config().onboarding_url, path=request_path) request = ApiKeyRequestModel(description=description) response = await send_post_request( await self.get_session(), @@ -194,3 +197,6 @@ async def create_account_api_key(self, account: AccountModel, description: str | if response_data is None: raise ValueError("No API key data returned from onboarding") return response_data.key + + def _get_endpoint_config(self): + return self.__endpoint_config.endpoints diff --git a/x10/utils/http.py b/x10/utils/http.py index 7d8b118..f03c09f 100644 --- a/x10/utils/http.py +++ b/x10/utils/http.py @@ -4,20 +4,18 @@ from typing import Any, Dict, Generic, List, Optional, Sequence, Type, TypeVar, Union import aiohttp -from aiohttp import ClientResponse, ClientTimeout +from aiohttp import ClientResponse from pydantic import GetCoreSchemaHandler from pydantic_core import CoreSchema, core_schema from strenum import StrEnum from version import SDK_VERSION -from x10.config import DEFAULT_REQUEST_TIMEOUT_SECONDS from x10.errors import X10Error from x10.models.base import X10BaseModel from x10.utils.log import get_logger LOGGER = get_logger(__name__) USER_AGENT = f"X10PythonTradingClient/{SDK_VERSION}" -# CLIENT_TIMEOUT = ClientTimeout(total=DEFAULT_REQUEST_TIMEOUT_SECONDS) ApiResponseType = TypeVar("ApiResponseType", bound=Union[int, X10BaseModel, Sequence[X10BaseModel], None]) From 373a51aa4a6672bb415fe693d61b28201a56fb57 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 13:34:29 +0400 Subject: [PATCH 10/19] Unify configs --- x10/perpetual/limit_order_object_settlement.py | 2 +- x10/perpetual/orderbook.py | 10 +++++----- .../stream_client/perpetual_stream_connection.py | 3 +-- x10/perpetual/trading_client/base_module.py | 10 +++++----- x10/perpetual/trading_client/testnet_module.py | 6 +++--- x10/perpetual/trading_client/vault_module.py | 6 +++--- x10/perpetual/transfer_object.py | 14 +++++++------- x10/perpetual/withdrawal_object.py | 12 ++++++------ x10/utils/http.py | 2 +- 9 files changed, 32 insertions(+), 33 deletions(-) diff --git a/x10/perpetual/limit_order_object_settlement.py b/x10/perpetual/limit_order_object_settlement.py index 1476b99..cd48ffb 100644 --- a/x10/perpetual/limit_order_object_settlement.py +++ b/x10/perpetual/limit_order_object_settlement.py @@ -1,12 +1,12 @@ import decimal from datetime import timedelta +from x10.config import StarknetDomain from x10.core.amount import HumanReadableAmount, StarkAmount from x10.core.stark_account import StarkPerpetualAccount from x10.models.asset import Asset, AssetModel from x10.models.base import SettlementSignatureModel from x10.models.order import LimitOrderSettlementModel -from x10.perpetual.configuration import StarknetDomain from x10.perpetual.order_object_settlement import ( calculate_order_settlement_expiration, hash_limit_order, diff --git a/x10/perpetual/orderbook.py b/x10/perpetual/orderbook.py index 8e58279..64123ca 100644 --- a/x10/perpetual/orderbook.py +++ b/x10/perpetual/orderbook.py @@ -6,8 +6,8 @@ from sortedcontainers import SortedDict +from x10.config import Config from x10.models.orderbook import OrderbookUpdateModel -from x10.perpetual.configuration import EndpointConfig from x10.perpetual.stream_client.stream_client import PerpetualStreamClient from x10.utils.http import StreamDataType @@ -30,27 +30,27 @@ class ImpactDetails: class OrderBook: @staticmethod async def create( - endpoint_config: EndpointConfig, + config: Config, market_name: str, best_ask_change_callback: Callable[[OrderBookEntry | None], Awaitable[None]] | None = None, best_bid_change_callback: Callable[[OrderBookEntry | None], Awaitable[None]] | None = None, start=False, depth: int | None = None, ) -> "OrderBook": - ob = OrderBook(endpoint_config, market_name, best_ask_change_callback, best_bid_change_callback, depth) + ob = OrderBook(config, market_name, best_ask_change_callback, best_bid_change_callback, depth) if start: await ob.start_orderbook() return ob def __init__( self, - endpoint_config: EndpointConfig, + config: Config, market_name: str, best_ask_change_callback: Callable[[OrderBookEntry | None], Awaitable[None]] | None = None, best_bid_change_callback: Callable[[OrderBookEntry | None], Awaitable[None]] | None = None, depth: int | None = None, ) -> None: - self.__stream_client = PerpetualStreamClient(api_url=endpoint_config.stream_url) + self.__stream_client = PerpetualStreamClient(api_url=config.endpoints.stream_url) self.__market_name = market_name self.__task: asyncio.Task | None = None self._bid_prices: "SortedDict[decimal.Decimal, OrderBookEntry]" = SortedDict() # type: ignore diff --git a/x10/perpetual/stream_client/perpetual_stream_connection.py b/x10/perpetual/stream_client/perpetual_stream_connection.py index 706d10a..f379a4b 100644 --- a/x10/perpetual/stream_client/perpetual_stream_connection.py +++ b/x10/perpetual/stream_client/perpetual_stream_connection.py @@ -4,9 +4,8 @@ import websockets from websockets import WebSocketClientProtocol -from x10.config import USER_AGENT from x10.models.base import X10BaseModel -from x10.utils.http import RequestHeader +from x10.utils.http import USER_AGENT, RequestHeader from x10.utils.log import get_logger LOGGER = get_logger(__name__) diff --git a/x10/perpetual/trading_client/base_module.py b/x10/perpetual/trading_client/base_module.py index 0ee3aa6..1e60bbb 100644 --- a/x10/perpetual/trading_client/base_module.py +++ b/x10/perpetual/trading_client/base_module.py @@ -10,20 +10,20 @@ class BaseModule: - __endpoint_config: Config + __config: Config __api_key: Optional[str] __stark_account: Optional[StarkPerpetualAccount] __session: Optional[aiohttp.ClientSession] def __init__( self, - endpoint_config: Config, + config: Config, *, api_key: Optional[str] = None, stark_account: Optional[StarkPerpetualAccount] = None, ): super().__init__() - self.__endpoint_config = endpoint_config + self.__config = config self.__api_key = api_key self.__stark_account = stark_account self.__session = None @@ -32,7 +32,7 @@ def _get_url(self, path: str, *, query: Optional[Dict] = None, **path_params) -> return get_url(f"{self._get_endpoint_config().api_base_url}{path}", query=query, **path_params) def _get_endpoint_config(self): - return self.__endpoint_config.endpoints + return self.__config.endpoints def _get_api_key(self): if not self.__api_key: @@ -49,7 +49,7 @@ def _get_stark_account(self): async def get_session(self) -> aiohttp.ClientSession: if self.__session is None: created_session = aiohttp.ClientSession( - timeout=ClientTimeout(total=self.__endpoint_config.defaults.request_timeout_seconds) + timeout=ClientTimeout(total=self.__config.defaults.request_timeout_seconds) ) self.__session = created_session diff --git a/x10/perpetual/trading_client/testnet_module.py b/x10/perpetual/trading_client/testnet_module.py index f119f75..220ff67 100644 --- a/x10/perpetual/trading_client/testnet_module.py +++ b/x10/perpetual/trading_client/testnet_module.py @@ -2,9 +2,9 @@ import tenacity +from x10.config import Config from x10.models.asset import AssetOperationModel, AssetOperationStatus from x10.models.base import X10BaseModel -from x10.perpetual.configuration import EndpointConfig from x10.perpetual.trading_client.account_module import AccountModule from x10.perpetual.trading_client.base_module import BaseModule from x10.utils.http import WrappedApiResponse, send_post_request @@ -17,11 +17,11 @@ class ClaimResponseModel(X10BaseModel): class TestnetModule(BaseModule): def __init__( self, - endpoint_config: EndpointConfig, + config: Config, api_key: Optional[str] = None, account_module: Optional[AccountModule] = None, ): - super().__init__(endpoint_config, api_key=api_key) + super().__init__(config, api_key=api_key) self._account_module = account_module async def claim_testing_funds( diff --git a/x10/perpetual/trading_client/vault_module.py b/x10/perpetual/trading_client/vault_module.py index 6392e3f..7eaea03 100644 --- a/x10/perpetual/trading_client/vault_module.py +++ b/x10/perpetual/trading_client/vault_module.py @@ -3,11 +3,11 @@ from types import NoneType from typing import Optional +from x10.config import Config from x10.core.stark_account import StarkPerpetualAccount from x10.errors import X10Error from x10.models.base import X10BaseModel from x10.models.order import LimitOrderSettlementModel -from x10.perpetual.configuration import EndpointConfig from x10.perpetual.limit_order_object_settlement import create_order_settlement_data from x10.perpetual.trading_client.account_module import AccountModule from x10.perpetual.trading_client.base_module import BaseModule @@ -38,14 +38,14 @@ class WithdrawRequestModel(X10BaseModel): class VaultModule(BaseModule): def __init__( self, - endpoint_config: EndpointConfig, + config: Config, *, info_module: InfoModule, account_module: AccountModule, account: Optional[StarkPerpetualAccount] = None, api_key: Optional[str] = None, ): - super().__init__(endpoint_config, api_key=api_key) + super().__init__(config, api_key=api_key) self._info_module = info_module self._account_module = account_module diff --git a/x10/perpetual/transfer_object.py b/x10/perpetual/transfer_object.py index b0f8979..6523cab 100644 --- a/x10/perpetual/transfer_object.py +++ b/x10/perpetual/transfer_object.py @@ -5,6 +5,7 @@ from fast_stark_crypto import get_transfer_msg_hash +from x10.config import Config, StarknetDomain from x10.core.stark_account import StarkPerpetualAccount from x10.models.account import AccountModel from x10.models.base import SettlementSignatureModel @@ -12,7 +13,6 @@ OnChainPerpetualTransferModel, StarkTransferSettlementModel, ) -from x10.perpetual.configuration import EndpointConfig, StarknetDomain from x10.utils.date import utc_now from x10.utils.nonce import generate_nonce @@ -34,14 +34,14 @@ def create_transfer_object( to_vault: int, to_l2_key: int, amount: Decimal, - config: EndpointConfig, + config: Config, stark_account: StarkPerpetualAccount, nonce: int | None = None, ) -> OnChainPerpetualTransferModel: expiration_timestamp = calc_expiration_timestamp() - scaled_amount = amount.scaleb(config.collateral_decimals) + scaled_amount = amount.scaleb(config.endpoints.collateral_decimals) stark_amount = scaled_amount.to_integral_exact() - starknet_domain: StarknetDomain = config.starknet_domain + starknet_domain: StarknetDomain = config.signing.starknet_domain if nonce is None: nonce = generate_nonce() @@ -57,13 +57,13 @@ def create_transfer_object( domain_version=starknet_domain.version, domain_chain_id=starknet_domain.chain_id, domain_revision=starknet_domain.revision, - collateral_id=int(config.collateral_asset_on_chain_id, base=16), + collateral_id=int(config.endpoints.collateral_asset_on_chain_id, base=16), ) (transfer_signature_r, transfer_signature_s) = stark_account.sign(transfer_hash) settlement = StarkTransferSettlementModel( amount=int(stark_amount), - asset_id=int(config.collateral_asset_on_chain_id, base=16), + asset_id=int(config.endpoints.collateral_asset_on_chain_id, base=16), expiration_timestamp=expiration_timestamp, nonce=nonce, receiver_position_id=to_vault, @@ -78,5 +78,5 @@ def create_transfer_object( to_vault=to_vault, amount=amount, settlement=settlement, - transferred_asset=config.collateral_asset_on_chain_id, + transferred_asset=config.endpoints.collateral_asset_on_chain_id, ) diff --git a/x10/perpetual/withdrawal_object.py b/x10/perpetual/withdrawal_object.py index c0a86b6..40ceb89 100644 --- a/x10/perpetual/withdrawal_object.py +++ b/x10/perpetual/withdrawal_object.py @@ -4,6 +4,7 @@ from fast_stark_crypto import get_withdrawal_msg_hash +from x10.config import Config, StarknetDomain from x10.core.stark_account import StarkPerpetualAccount from x10.models.base import SettlementSignatureModel from x10.models.withdrawal import ( @@ -11,7 +12,6 @@ TimestampModel, WithdrawalRequestModel, ) -from x10.perpetual.configuration import EndpointConfig, StarknetDomain from x10.utils.date import utc_now from x10.utils.nonce import generate_nonce @@ -27,7 +27,7 @@ def create_withdrawal_object( amount: Decimal, recipient_stark_address: str, stark_account: StarkPerpetualAccount, - config: EndpointConfig, + config: Config, account_id: int, chain_id: str, description: str | None = None, @@ -35,9 +35,9 @@ def create_withdrawal_object( quote_id: str | None = None, ) -> WithdrawalRequestModel: expiration_timestamp = calc_expiration_timestamp() - scaled_amount = amount.scaleb(config.collateral_decimals) + scaled_amount = amount.scaleb(config.endpoints.collateral_decimals) stark_amount = scaled_amount.to_integral_exact() - starknet_domain: StarknetDomain = config.starknet_domain + starknet_domain: StarknetDomain = config.signing.starknet_domain if nonce is None: nonce = generate_nonce() @@ -53,7 +53,7 @@ def create_withdrawal_object( domain_version=starknet_domain.version, domain_chain_id=starknet_domain.chain_id, domain_revision=starknet_domain.revision, - collateral_id=int(config.collateral_asset_on_chain_id, base=16), + collateral_id=int(config.endpoints.collateral_asset_on_chain_id, base=16), ) (transfer_signature_r, transfer_signature_s) = stark_account.sign(withdrawal_hash) @@ -61,7 +61,7 @@ def create_withdrawal_object( settlement = StarkWithdrawalSettlementModel( recipient=int(recipient_stark_address, 16), position_id=stark_account.vault, - collateral_id=int(config.collateral_asset_on_chain_id, base=16), + collateral_id=int(config.endpoints.collateral_asset_on_chain_id, base=16), amount=int(stark_amount), expiration=TimestampModel(seconds=expiration_timestamp), salt=nonce, diff --git a/x10/utils/http.py b/x10/utils/http.py index f03c09f..e2aa049 100644 --- a/x10/utils/http.py +++ b/x10/utils/http.py @@ -8,11 +8,11 @@ from pydantic import GetCoreSchemaHandler from pydantic_core import CoreSchema, core_schema from strenum import StrEnum -from version import SDK_VERSION from x10.errors import X10Error from x10.models.base import X10BaseModel from x10.utils.log import get_logger +from x10.version import SDK_VERSION LOGGER = get_logger(__name__) USER_AGENT = f"X10PythonTradingClient/{SDK_VERSION}" From 224a27587137f6cadeb7813a0a8343fdb60db56f Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 13:48:30 +0400 Subject: [PATCH 11/19] Unify configs --- examples/cases/advanced/load_testing.py | 4 ++-- examples/cases/advanced/market_maker.py | 3 +-- .../advanced/onboarding_with_eth_account.py | 2 +- .../create_limit_order_with_builder.py | 5 ++-- .../createorder/create_conditional_order.py | 3 ++- .../cases/createorder/create_limit_order.py | 3 ++- .../cases/createorder/create_market_order.py | 6 ++--- ...reate_market_order_with_blocking_client.py | 8 +++---- .../stream/subscribe_to_multiple_streams.py | 3 +-- .../create_limit_order_with_partial_tpsl.py | 7 ++++-- .../create_limit_order_with_position_tpsl.py | 3 ++- .../cases/tpsl/create_partial_tpsl_order.py | 3 ++- .../cases/tpsl/create_position_tpsl_order.py | 3 ++- examples/cases/withdraw/withdrawal_bridged.py | 2 +- .../cases/withdraw/withdrawal_starknet.py | 2 +- examples/utils.py | 16 +++++++------ .../simple_client/simple_trading_client.py | 24 ++++++++++++------- .../trading_client/trading_client.py | 2 ++ 18 files changed, 58 insertions(+), 41 deletions(-) diff --git a/examples/cases/advanced/load_testing.py b/examples/cases/advanced/load_testing.py index b00d22f..29b516a 100644 --- a/examples/cases/advanced/load_testing.py +++ b/examples/cases/advanced/load_testing.py @@ -4,8 +4,7 @@ from asyncio import run from typing import Set -from examples.utils import create_trading_client -from x10.config import BTC_USD_MARKET +from examples.utils import BTC_USD_MARKET, create_trading_client from x10.models.market import MarketModel from x10.models.order import OrderSide from x10.perpetual.order_object import create_order_object @@ -50,6 +49,7 @@ async def create_orders_loop(*, trading_client: PerpetualTradingClient, market: starknet_domain=trading_client.config.starknet_domain, order_external_id=new_order_external_id, post_only=True, + taker_fee=trading_client.config.defaults.taker_fee, ) async with unconfirmed_order_lock: diff --git a/examples/cases/advanced/market_maker.py b/examples/cases/advanced/market_maker.py index e839b33..955b070 100644 --- a/examples/cases/advanced/market_maker.py +++ b/examples/cases/advanced/market_maker.py @@ -5,8 +5,7 @@ from signal import SIGINT, SIGTERM from typing import Awaitable, Callable, List -from examples.utils import create_trading_client -from x10.config import BTC_USD_MARKET +from examples.utils import BTC_USD_MARKET, create_trading_client from x10.models.order import OrderSide from x10.perpetual.orderbook import OrderBook, OrderBookEntry diff --git a/examples/cases/advanced/onboarding_with_eth_account.py b/examples/cases/advanced/onboarding_with_eth_account.py index a7c9edf..34e599d 100644 --- a/examples/cases/advanced/onboarding_with_eth_account.py +++ b/examples/cases/advanced/onboarding_with_eth_account.py @@ -5,8 +5,8 @@ from eth_account.signers.local import LocalAccount from examples.utils import init_env +from x10.config import TESTNET_CONFIG from x10.core.stark_account import StarkPerpetualAccount -from x10.perpetual.configuration import TESTNET_CONFIG from x10.perpetual.trading_client.trading_client import PerpetualTradingClient from x10.perpetual.user_client.user_client import UserClient from x10.utils.string import is_hex_string diff --git a/examples/cases/buildercode/create_limit_order_with_builder.py b/examples/cases/buildercode/create_limit_order_with_builder.py index dfd7f36..df1c2a5 100644 --- a/examples/cases/buildercode/create_limit_order_with_builder.py +++ b/examples/cases/buildercode/create_limit_order_with_builder.py @@ -2,12 +2,12 @@ from asyncio import run from examples.utils import ( + BTC_USD_MARKET, create_trading_client, find_order_and_cancel, get_adjust_price_by_pct, init_env, ) -from x10.config import BTC_USD_MARKET from x10.models.order import OrderSide, TimeInForce from x10.perpetual.order_object import create_order_object @@ -45,8 +45,9 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, - builder_id=builder_id, + taker_fee=trading_client.config.defaults.taker_fee, builder_fee=builder_fee, + builder_id=builder_id, ) LOGGER.info("Placing order...") diff --git a/examples/cases/createorder/create_conditional_order.py b/examples/cases/createorder/create_conditional_order.py index e9461c9..eb603ab 100644 --- a/examples/cases/createorder/create_conditional_order.py +++ b/examples/cases/createorder/create_conditional_order.py @@ -2,11 +2,11 @@ from asyncio import run from examples.utils import ( + BTC_USD_MARKET, create_trading_client, find_order_and_cancel, get_adjust_price_by_pct, ) -from x10.config import BTC_USD_MARKET from x10.models.order import ( OrderPriceType, OrderSide, @@ -51,6 +51,7 @@ async def run_example(): direction=OrderTriggerDirection.DOWN, execution_price_type=OrderPriceType.LIMIT, ), + taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/createorder/create_limit_order.py b/examples/cases/createorder/create_limit_order.py index 5d1b862..2fe1a1f 100644 --- a/examples/cases/createorder/create_limit_order.py +++ b/examples/cases/createorder/create_limit_order.py @@ -2,11 +2,11 @@ from asyncio import run from examples.utils import ( + BTC_USD_MARKET, create_trading_client, find_order_and_cancel, get_adjust_price_by_pct, ) -from x10.config import BTC_USD_MARKET from x10.models.order import OrderSide, TimeInForce from x10.perpetual.order_object import create_order_object @@ -36,6 +36,7 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, + taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/createorder/create_market_order.py b/examples/cases/createorder/create_market_order.py index 5175ff1..f6798a6 100644 --- a/examples/cases/createorder/create_market_order.py +++ b/examples/cases/createorder/create_market_order.py @@ -1,8 +1,7 @@ import logging from asyncio import run -from examples.utils import create_trading_client -from x10.config import BTC_USD_MARKET, DEFAULT_MARKET_PRICE_SLIPPAGE +from examples.utils import BTC_USD_MARKET, create_trading_client from x10.models.order import OrderSide, OrderType, TimeInForce from x10.perpetual.order_object import create_order_object from x10.utils.order import get_price_with_slippage @@ -26,7 +25,7 @@ async def run_example(): side=order_side, price=best_market_price, min_price_change=market.trading_config.min_price_change, - slippage=DEFAULT_MARKET_PRICE_SLIPPAGE, + slippage=trading_client.config.defaults.market_price_slippage, ) LOGGER.info("Creating MARKET order object for market: %s", market.name) @@ -42,6 +41,7 @@ async def run_example(): time_in_force=TimeInForce.IOC, reduce_only=False, post_only=False, + taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/createorder/create_market_order_with_blocking_client.py b/examples/cases/createorder/create_market_order_with_blocking_client.py index 8a42521..dc7a943 100644 --- a/examples/cases/createorder/create_market_order_with_blocking_client.py +++ b/examples/cases/createorder/create_market_order_with_blocking_client.py @@ -1,10 +1,9 @@ import asyncio import logging -from examples.utils import create_blocking_client -from x10.config import BTC_USD_MARKET, DEFAULT_MARKET_PRICE_SLIPPAGE +from examples.utils import BTC_USD_MARKET, create_blocking_client +from x10.config import TESTNET_CONFIG from x10.models.order import OrderSide, OrderType, TimeInForce -from x10.perpetual.configuration import TESTNET_CONFIG from x10.perpetual.orderbook import OrderBook from x10.utils.order import get_price_with_slippage @@ -56,7 +55,7 @@ async def run_example(): side=order_side, price=best_ask_entry.price, min_price_change=market.trading_config.min_price_change, - slippage=DEFAULT_MARKET_PRICE_SLIPPAGE, + slippage=blocking_client.config.defaults.market_price_slippage, ) LOGGER.info("Creating MARKET order for market %s: %s@%s", market.name, order_size, order_price) @@ -70,6 +69,7 @@ async def run_example(): time_in_force=TimeInForce.IOC, reduce_only=False, post_only=False, + taker_fee=blocking_client.config.defaults.taker_fee, ) await blocking_client.close() diff --git a/examples/cases/stream/subscribe_to_multiple_streams.py b/examples/cases/stream/subscribe_to_multiple_streams.py index 71fdb00..c224ce0 100644 --- a/examples/cases/stream/subscribe_to_multiple_streams.py +++ b/examples/cases/stream/subscribe_to_multiple_streams.py @@ -3,8 +3,7 @@ from asyncio import run from signal import SIGINT, SIGTERM -from examples.utils import create_stream_client, init_env -from x10.config import BTC_USD_MARKET +from examples.utils import BTC_USD_MARKET, create_stream_client, init_env LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET diff --git a/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py b/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py index c79afe2..2ffe641 100644 --- a/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py +++ b/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py @@ -3,11 +3,11 @@ from decimal import Decimal from examples.utils import ( + BTC_USD_MARKET, create_trading_client, find_order_and_cancel, get_adjust_price_by_pct, ) -from x10.config import BTC_USD_MARKET, DEFAULT_MARKET_PRICE_SLIPPAGE from x10.models.order import ( OrderPriceType, OrderSide, @@ -34,7 +34,9 @@ async def run_example(): tp_trigger_price = adjust_price_by_pct(order_price, 0.5) tp_price = adjust_price_by_pct(tp_trigger_price, 0.5) sl_trigger_price = adjust_price_by_pct(order_price, -0.5) - sl_price = adjust_price_by_pct(sl_trigger_price, -DEFAULT_MARKET_PRICE_SLIPPAGE * Decimal("100")) + sl_price = adjust_price_by_pct( + sl_trigger_price, -trading_client.config.defaults.market_price_slippage * Decimal("100") + ) LOGGER.info("Creating LIMIT order object with TPSL for market: %s", market.name) @@ -61,6 +63,7 @@ async def run_example(): price=sl_price, price_type=OrderPriceType.MARKET, ), + taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/tpsl/create_limit_order_with_position_tpsl.py b/examples/cases/tpsl/create_limit_order_with_position_tpsl.py index 2d5029e..9424b65 100644 --- a/examples/cases/tpsl/create_limit_order_with_position_tpsl.py +++ b/examples/cases/tpsl/create_limit_order_with_position_tpsl.py @@ -2,11 +2,11 @@ from asyncio import run from examples.utils import ( + BTC_USD_MARKET, create_trading_client, find_order_and_cancel, get_adjust_price_by_pct, ) -from x10.config import BTC_USD_MARKET from x10.models.order import ( OrderPriceType, OrderSide, @@ -47,6 +47,7 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, + taker_fee=trading_client.config.defaults.taker_fee, tp_sl_type=OrderTpslType.POSITION, take_profit=OrderTpslTriggerParam( trigger_price=tp_trigger_price, diff --git a/examples/cases/tpsl/create_partial_tpsl_order.py b/examples/cases/tpsl/create_partial_tpsl_order.py index e94e1c5..ccc8f67 100644 --- a/examples/cases/tpsl/create_partial_tpsl_order.py +++ b/examples/cases/tpsl/create_partial_tpsl_order.py @@ -3,11 +3,11 @@ from decimal import Decimal from examples.utils import ( + BTC_USD_MARKET, create_trading_client, find_order_and_cancel, get_adjust_price_by_pct, ) -from x10.config import BTC_USD_MARKET from x10.models.order import ( OrderPriceType, OrderSide, @@ -63,6 +63,7 @@ async def run_example(): price=sl_price, price_type=OrderPriceType.LIMIT, ), + taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/tpsl/create_position_tpsl_order.py b/examples/cases/tpsl/create_position_tpsl_order.py index 5f5c979..05a8732 100644 --- a/examples/cases/tpsl/create_position_tpsl_order.py +++ b/examples/cases/tpsl/create_position_tpsl_order.py @@ -3,11 +3,11 @@ from decimal import Decimal from examples.utils import ( + BTC_USD_MARKET, create_trading_client, find_order_and_cancel, get_adjust_price_by_pct, ) -from x10.config import BTC_USD_MARKET from x10.models.order import ( OrderPriceType, OrderSide, @@ -61,6 +61,7 @@ async def run_example(): price=sl_price, price_type=OrderPriceType.LIMIT, ), + taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/withdraw/withdrawal_bridged.py b/examples/cases/withdraw/withdrawal_bridged.py index 02775d4..b5b8e6d 100644 --- a/examples/cases/withdraw/withdrawal_bridged.py +++ b/examples/cases/withdraw/withdrawal_bridged.py @@ -3,7 +3,7 @@ from decimal import Decimal from examples.utils import create_trading_client -from x10.perpetual.configuration import MAINNET_CONFIG +from x10.config import MAINNET_CONFIG LOGGER = logging.getLogger() FEE_THRESHOLD_USDC = 2 diff --git a/examples/cases/withdraw/withdrawal_starknet.py b/examples/cases/withdraw/withdrawal_starknet.py index 45144f6..10a6022 100644 --- a/examples/cases/withdraw/withdrawal_starknet.py +++ b/examples/cases/withdraw/withdrawal_starknet.py @@ -3,7 +3,7 @@ from decimal import Decimal from examples.utils import create_trading_client -from x10.perpetual.configuration import MAINNET_CONFIG +from x10.config import MAINNET_CONFIG from x10.utils.nonce import generate_nonce from x10.utils.string import is_hex_string diff --git a/examples/utils.py b/examples/utils.py index 5cf34d4..568fa80 100644 --- a/examples/utils.py +++ b/examples/utils.py @@ -10,14 +10,16 @@ import yaml from dotenv import load_dotenv +from x10.config import TESTNET_CONFIG, Config from x10.core.stark_account import StarkPerpetualAccount from x10.models.market import TradingConfigModel -from x10.perpetual.configuration import TESTNET_CONFIG, EndpointConfig from x10.perpetual.simple_client.simple_trading_client import BlockingTradingClient from x10.perpetual.stream_client import PerpetualStreamClient from x10.perpetual.trading_client import PerpetualTradingClient from x10.utils.string import is_hex_string +BTC_USD_MARKET = "BTC-USD" + @dataclass class EnvConfig: @@ -59,7 +61,7 @@ def init_env(require_private_api: bool = True): ) -def create_trading_client(endpoint_config: EndpointConfig = TESTNET_CONFIG): +def create_trading_client(config: Config = TESTNET_CONFIG): env_config = init_env() stark_account = StarkPerpetualAccount( @@ -69,10 +71,10 @@ def create_trading_client(endpoint_config: EndpointConfig = TESTNET_CONFIG): vault=env_config.vault_id, ) - return PerpetualTradingClient(endpoint_config, stark_account) + return PerpetualTradingClient(config, stark_account) -def create_blocking_client(endpoint_config: EndpointConfig = TESTNET_CONFIG): +def create_blocking_client(config: Config = TESTNET_CONFIG): env_config = init_env() stark_account = StarkPerpetualAccount( @@ -82,11 +84,11 @@ def create_blocking_client(endpoint_config: EndpointConfig = TESTNET_CONFIG): vault=env_config.vault_id, ) - return BlockingTradingClient(endpoint_config, stark_account) + return BlockingTradingClient(config, stark_account) -def create_stream_client(endpoint_config: EndpointConfig = TESTNET_CONFIG): - return PerpetualStreamClient(api_url=endpoint_config.stream_url) +def create_stream_client(config: Config = TESTNET_CONFIG): + return PerpetualStreamClient(api_url=config.endpoints.stream_url) def get_adjust_price_by_pct(config: TradingConfigModel): diff --git a/x10/perpetual/simple_client/simple_trading_client.py b/x10/perpetual/simple_client/simple_trading_client.py index 8b8b2d5..58e6c17 100644 --- a/x10/perpetual/simple_client/simple_trading_client.py +++ b/x10/perpetual/simple_client/simple_trading_client.py @@ -4,6 +4,7 @@ from decimal import Decimal from typing import Awaitable, Dict, Union, cast +from x10.config import Config from x10.core.stark_account import StarkPerpetualAccount from x10.models.account import AccountStreamDataModel from x10.models.market import MarketModel @@ -15,7 +16,6 @@ OrderType, TimeInForce, ) -from x10.perpetual.configuration import EndpointConfig from x10.perpetual.order_object import create_order_object from x10.perpetual.stream_client.perpetual_stream_connection import ( PerpetualStreamConnection, @@ -74,17 +74,17 @@ class CancelWaiter: class BlockingTradingClient: - def __init__(self, endpoint_config: EndpointConfig, account: StarkPerpetualAccount): + def __init__(self, config: Config, account: StarkPerpetualAccount): if not asyncio.get_event_loop().is_running(): raise RuntimeError( "BlockingTradingClient must be initialized from an async function, use BlockingTradingClient.create()" ) - self.__endpoint_config = endpoint_config + self.__config = config self.__account = account - self.__market_module = InfoMarketsModule(endpoint_config, api_key=account.api_key) - self.__orders_module = OrderManagementModule(endpoint_config, api_key=account.api_key) + self.__market_module = InfoMarketsModule(config, api_key=account.api_key) + self.__orders_module = OrderManagementModule(config, api_key=account.api_key) self.__markets: Union[None, Dict[str, MarketModel]] = None - self.__stream_client: PerpetualStreamClient = PerpetualStreamClient(api_url=endpoint_config.stream_url) + self.__stream_client: PerpetualStreamClient = PerpetualStreamClient(api_url=config.endpoints.stream_url) self.__account_stream: Union[ None, PerpetualStreamConnection[WrappedStreamResponse[AccountStreamDataModel]], @@ -94,8 +94,8 @@ def __init__(self, endpoint_config: EndpointConfig, account: StarkPerpetualAccou self.__stream_task = asyncio.create_task(self.___order_stream()) @staticmethod - async def create(endpoint_config: EndpointConfig, account: StarkPerpetualAccount) -> "BlockingTradingClient": - client = BlockingTradingClient(endpoint_config, account) + async def create(config: Config, account: StarkPerpetualAccount) -> "BlockingTradingClient": + client = BlockingTradingClient(config, account) await client.__stream_client.subscribe_to_account_updates(account.api_key) return client @@ -197,6 +197,7 @@ async def create_and_place_order( amount_of_synthetic: Decimal, price: Decimal, side: OrderSide, + taker_fee: Decimal, post_only: bool = False, previous_order_external_id: str | None = None, external_id: str | None = None, @@ -220,11 +221,12 @@ async def create_and_place_order( post_only=post_only, reduce_only=reduce_only, previous_order_external_id=previous_order_external_id, - starknet_domain=self.__endpoint_config.starknet_domain, + starknet_domain=self.__config.signing.starknet_domain, order_external_id=external_id, builder_fee=builder_fee, builder_id=builder_id, time_in_force=time_in_force, + taker_fee=taker_fee, ) if order.id in self.__order_waiters: @@ -252,3 +254,7 @@ async def close(self): self.__stream_task.cancel() if self.__account_stream: await self.__account_stream.close() + + @property + def config(self): + return self.__config diff --git a/x10/perpetual/trading_client/trading_client.py b/x10/perpetual/trading_client/trading_client.py index c6cfff4..a1804ab 100644 --- a/x10/perpetual/trading_client/trading_client.py +++ b/x10/perpetual/trading_client/trading_client.py @@ -49,6 +49,7 @@ async def place_order( amount_of_synthetic: Decimal, price: Decimal, side: OrderSide, + taker_fee: Decimal, post_only: bool = False, previous_order_id=None, expire_time: Optional[datetime] = None, @@ -89,6 +90,7 @@ async def place_order( self_trade_protection_level=self_trade_protection_level, starknet_domain=self.__config.signing.starknet_domain, order_external_id=external_id, + taker_fee=taker_fee, builder_fee=builder_fee, builder_id=builder_id, reduce_only=reduce_only, From d25abb9ec8ee49eaf5d69107e0ee1ff688be3886 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 13:51:23 +0400 Subject: [PATCH 12/19] Unify configs --- examples/cases/createorder/create_conditional_order.py | 2 +- examples/cases/tpsl/create_limit_order_with_partial_tpsl.py | 2 +- examples/cases/tpsl/create_partial_tpsl_order.py | 2 +- examples/cases/tpsl/create_position_tpsl_order.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/cases/createorder/create_conditional_order.py b/examples/cases/createorder/create_conditional_order.py index eb603ab..7141e55 100644 --- a/examples/cases/createorder/create_conditional_order.py +++ b/examples/cases/createorder/create_conditional_order.py @@ -45,13 +45,13 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, + taker_fee=trading_client.config.defaults.taker_fee, trigger=OrderConditionalTriggerParam( trigger_price=order_trigger_price, trigger_price_type=OrderTriggerPriceType.LAST, direction=OrderTriggerDirection.DOWN, execution_price_type=OrderPriceType.LIMIT, ), - taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py b/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py index 2ffe641..cb14f26 100644 --- a/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py +++ b/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py @@ -50,6 +50,7 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, + taker_fee=trading_client.config.defaults.taker_fee, tp_sl_type=OrderTpslType.ORDER, take_profit=OrderTpslTriggerParam( trigger_price=tp_trigger_price, @@ -63,7 +64,6 @@ async def run_example(): price=sl_price, price_type=OrderPriceType.MARKET, ), - taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/tpsl/create_partial_tpsl_order.py b/examples/cases/tpsl/create_partial_tpsl_order.py index ccc8f67..1aa8dcc 100644 --- a/examples/cases/tpsl/create_partial_tpsl_order.py +++ b/examples/cases/tpsl/create_partial_tpsl_order.py @@ -50,6 +50,7 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=True, post_only=False, + taker_fee=trading_client.config.defaults.taker_fee, tp_sl_type=OrderTpslType.ORDER, take_profit=OrderTpslTriggerParam( trigger_price=tp_trigger_price, @@ -63,7 +64,6 @@ async def run_example(): price=sl_price, price_type=OrderPriceType.LIMIT, ), - taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/tpsl/create_position_tpsl_order.py b/examples/cases/tpsl/create_position_tpsl_order.py index 05a8732..597de02 100644 --- a/examples/cases/tpsl/create_position_tpsl_order.py +++ b/examples/cases/tpsl/create_position_tpsl_order.py @@ -48,6 +48,7 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=True, post_only=False, + taker_fee=trading_client.config.defaults.taker_fee, tp_sl_type=OrderTpslType.POSITION, take_profit=OrderTpslTriggerParam( trigger_price=tp_trigger_price, @@ -61,7 +62,6 @@ async def run_example(): price=sl_price, price_type=OrderPriceType.LIMIT, ), - taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") From 9a2df6add03858dead9d798844c13d42e7489338 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 14:05:35 +0400 Subject: [PATCH 13/19] Unify configs --- .../advanced/onboarding_with_eth_account.py | 6 +++--- ...create_market_order_with_blocking_client.py | 6 +++--- .../test_limit_order_object_settlement.py | 4 ++-- .../test_conditional_order_object.py | 5 +++-- .../order_object/test_limit_order_object.py | 17 +++++++++++------ .../order_object/test_market_order_object.py | 8 +++++--- .../order_object/test_order_object_attrs.py | 8 +++++--- .../order_object/test_tpsl_order_object.py | 8 +++++--- tests/perpetual/test_orderbook_price_impact.py | 2 +- tests/perpetual/test_trading_client.py | 7 ++++--- tests/perpetual/test_transfer_object.py | 2 +- x10/perpetual/user_client/user_client.py | 18 +++++++++--------- 12 files changed, 52 insertions(+), 39 deletions(-) diff --git a/examples/cases/advanced/onboarding_with_eth_account.py b/examples/cases/advanced/onboarding_with_eth_account.py index 34e599d..89bf878 100644 --- a/examples/cases/advanced/onboarding_with_eth_account.py +++ b/examples/cases/advanced/onboarding_with_eth_account.py @@ -12,7 +12,7 @@ from x10.utils.string import is_hex_string LOGGER = logging.getLogger() -ENDPOINT_CONFIG = TESTNET_CONFIG +CONFIG = TESTNET_CONFIG async def run_example(): @@ -23,7 +23,7 @@ async def run_example(): assert is_hex_string(eth_account_private_key), "`eth_account_private_key` must be a hex string" eth_local_account: LocalAccount = Account.from_key(eth_account_private_key) - user_client = UserClient(endpoint_config=ENDPOINT_CONFIG, l1_private_key=eth_local_account.key.hex) + user_client = UserClient(config=CONFIG, l1_private_key=eth_local_account.key.hex) LOGGER.info("Onboarding with ETH account %s...", eth_local_account.address) @@ -36,7 +36,7 @@ async def run_example(): private_key=main_account.l2_key_pair.private_hex, vault=main_account.account.l2_vault, ) - trading_client = PerpetualTradingClient(ENDPOINT_CONFIG, starknet_account) + trading_client = PerpetualTradingClient(CONFIG, starknet_account) LOGGER.info("StarkNet public key: %s", starknet_account.public_key) diff --git a/examples/cases/createorder/create_market_order_with_blocking_client.py b/examples/cases/createorder/create_market_order_with_blocking_client.py index dc7a943..52b0086 100644 --- a/examples/cases/createorder/create_market_order_with_blocking_client.py +++ b/examples/cases/createorder/create_market_order_with_blocking_client.py @@ -8,7 +8,7 @@ from x10.utils.order import get_price_with_slippage LOGGER = logging.getLogger() -ENDPOINT_CONFIG = TESTNET_CONFIG +CONFIG = TESTNET_CONFIG MARKET_NAME = BTC_USD_MARKET @@ -20,7 +20,7 @@ async def best_ask_initialised(_best_ask): best_ask_condition.notify_all() orderbook = await OrderBook.create( - ENDPOINT_CONFIG, + CONFIG, market_name=market_name, start=True, best_ask_change_callback=best_ask_initialised, @@ -38,7 +38,7 @@ async def best_ask_initialised(_best_ask): async def run_example(): - blocking_client = create_blocking_client(ENDPOINT_CONFIG) + blocking_client = create_blocking_client(CONFIG) markets = await blocking_client.get_markets() market = markets[MARKET_NAME] diff --git a/tests/perpetual/limit_order_object/test_limit_order_object_settlement.py b/tests/perpetual/limit_order_object/test_limit_order_object_settlement.py index 7cc236c..2f4b8be 100644 --- a/tests/perpetual/limit_order_object/test_limit_order_object_settlement.py +++ b/tests/perpetual/limit_order_object/test_limit_order_object_settlement.py @@ -15,7 +15,7 @@ async def test_create_buy_limit_order_settlement_data( ): mocker.patch("x10.utils.nonce.generate_nonce", return_value=FROZEN_NONCE) - from x10.perpetual.configuration import MAINNET_CONFIG + from x10.config import MAINNET_CONFIG from x10.perpetual.limit_order_object_settlement import create_order_settlement_data trading_account = create_trading_account() @@ -29,7 +29,7 @@ async def test_create_buy_limit_order_settlement_data( quote_asset_model=collateral_asset, base_asset_model=vault_asset, starknet_account=trading_account, - starknet_domain=MAINNET_CONFIG.starknet_domain, + starknet_domain=MAINNET_CONFIG.signing.starknet_domain, is_buy=True, ) diff --git a/tests/perpetual/order_object/test_conditional_order_object.py b/tests/perpetual/order_object/test_conditional_order_object.py index 4373942..9d43922 100644 --- a/tests/perpetual/order_object/test_conditional_order_object.py +++ b/tests/perpetual/order_object/test_conditional_order_object.py @@ -12,7 +12,7 @@ OrderTriggerPriceType, OrderType, ) -from x10.perpetual.configuration import TESTNET_CONFIG +from x10.config import TESTNET_CONFIG FROZEN_NONCE = 1473459052 @@ -36,7 +36,8 @@ async def test_create_buy_order(mocker: MockerFixture, create_trading_account, c amount_of_synthetic=Decimal("0.00100000"), price=Decimal("43445.11680000"), side=OrderSide.BUY, - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, trigger=OrderConditionalTriggerParam( trigger_price=Decimal("43400"), trigger_price_type=OrderTriggerPriceType.INDEX, diff --git a/tests/perpetual/order_object/test_limit_order_object.py b/tests/perpetual/order_object/test_limit_order_object.py index 8ac267d..3d7964f 100644 --- a/tests/perpetual/order_object/test_limit_order_object.py +++ b/tests/perpetual/order_object/test_limit_order_object.py @@ -13,7 +13,7 @@ OrderTriggerPriceType, SelfTradeProtectionLevel, ) -from x10.perpetual.configuration import TESTNET_CONFIG +from x10.config import TESTNET_CONFIG from x10.utils.date import utc_now FROZEN_NONCE = 1473459052 @@ -38,7 +38,8 @@ async def test_create_sell_order_with_default_expiration( amount_of_synthetic=Decimal("0.00100000"), price=Decimal("43445.11680000"), side=OrderSide.SELL, - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) freezer.stop() assert_that( @@ -95,7 +96,8 @@ async def test_create_sell_order(mocker: MockerFixture, create_trading_account, price=Decimal("43445.11680000"), side=OrderSide.SELL, expire_time=utc_now() + timedelta(days=14), - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, nonce=FROZEN_NONCE, ) @@ -154,7 +156,8 @@ async def test_create_buy_order(mocker: MockerFixture, create_trading_account, c side=OrderSide.BUY, expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) assert_that( @@ -212,7 +215,8 @@ async def test_create_buy_order_with_order_tpsl(mocker: MockerFixture, create_tr side=OrderSide.BUY, expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, tp_sl_type=OrderTpslType.ORDER, take_profit=OrderTpslTriggerParam( trigger_price=Decimal("49000"), @@ -321,7 +325,8 @@ async def test_create_buy_order_with_position_tpsl( side=OrderSide.BUY, expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, tp_sl_type=OrderTpslType.POSITION, take_profit=OrderTpslTriggerParam( trigger_price=Decimal("49000"), diff --git a/tests/perpetual/order_object/test_market_order_object.py b/tests/perpetual/order_object/test_market_order_object.py index a914a48..c382bd5 100644 --- a/tests/perpetual/order_object/test_market_order_object.py +++ b/tests/perpetual/order_object/test_market_order_object.py @@ -7,7 +7,7 @@ from pytest_mock import MockerFixture from x10.models.order import OrderSide, OrderType, TimeInForce -from x10.perpetual.configuration import TESTNET_CONFIG +from x10.config import TESTNET_CONFIG from x10.utils.date import utc_now from x10.utils.order import get_price_with_slippage @@ -40,8 +40,9 @@ async def test_create_sell_order(mocker: MockerFixture, create_trading_account, side=order_side, expire_time=utc_now() + timedelta(days=14), time_in_force=TimeInForce.IOC, - starknet_domain=TESTNET_CONFIG.starknet_domain, nonce=FROZEN_NONCE, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) assert_that( @@ -107,7 +108,8 @@ async def test_create_buy_order(mocker: MockerFixture, create_trading_account, c side=order_side, expire_time=utc_now() + timedelta(days=14), time_in_force=TimeInForce.IOC, - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, nonce=FROZEN_NONCE, ) diff --git a/tests/perpetual/order_object/test_order_object_attrs.py b/tests/perpetual/order_object/test_order_object_attrs.py index fe5edb3..c751173 100644 --- a/tests/perpetual/order_object/test_order_object_attrs.py +++ b/tests/perpetual/order_object/test_order_object_attrs.py @@ -7,7 +7,7 @@ from pytest_mock import MockerFixture from x10.models.order import OrderSide -from x10.perpetual.configuration import TESTNET_CONFIG +from x10.config import TESTNET_CONFIG from x10.utils.date import utc_now FROZEN_NONCE = 1473459052 @@ -30,7 +30,8 @@ async def test_cancel_previous_order(mocker: MockerFixture, create_trading_accou side=OrderSide.BUY, expire_time=utc_now() + timedelta(days=14), previous_order_external_id="previous_custom_id", - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee ) assert_that( @@ -60,7 +61,8 @@ async def test_external_order_id(mocker: MockerFixture, create_trading_account, side=OrderSide.BUY, expire_time=utc_now() + timedelta(days=14), order_external_id="custom_id", - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee ) assert_that( diff --git a/tests/perpetual/order_object/test_tpsl_order_object.py b/tests/perpetual/order_object/test_tpsl_order_object.py index 77ad0d6..c326a0c 100644 --- a/tests/perpetual/order_object/test_tpsl_order_object.py +++ b/tests/perpetual/order_object/test_tpsl_order_object.py @@ -14,7 +14,7 @@ OrderType, SelfTradeProtectionLevel, ) -from x10.perpetual.configuration import TESTNET_CONFIG +from x10.config import TESTNET_CONFIG from x10.utils.date import utc_now FROZEN_NONCE = 1473459052 @@ -39,7 +39,8 @@ async def test_create_buy_partial_tpsl_order(mocker: MockerFixture, create_tradi reduce_only=True, expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, tp_sl_type=OrderTpslType.ORDER, take_profit=OrderTpslTriggerParam( trigger_price=Decimal("49000"), @@ -133,7 +134,8 @@ async def test_create_buy_position_tpsl_order(mocker: MockerFixture, create_trad reduce_only=True, expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, - starknet_domain=TESTNET_CONFIG.starknet_domain, + starknet_domain=TESTNET_CONFIG.signing.starknet_domain, + taker_fee=TESTNET_CONFIG.defaults.taker_fee, tp_sl_type=OrderTpslType.POSITION, take_profit=OrderTpslTriggerParam( trigger_price=Decimal("49000"), diff --git a/tests/perpetual/test_orderbook_price_impact.py b/tests/perpetual/test_orderbook_price_impact.py index 48a67a9..09fab26 100644 --- a/tests/perpetual/test_orderbook_price_impact.py +++ b/tests/perpetual/test_orderbook_price_impact.py @@ -3,7 +3,7 @@ from unittest import TestCase from x10.models.orderbook import OrderbookUpdateModel -from x10.perpetual.configuration import TESTNET_CONFIG +from x10.config import TESTNET_CONFIG from x10.perpetual.orderbook import OrderBook diff --git a/tests/perpetual/test_trading_client.py b/tests/perpetual/test_trading_client.py index 26781a6..b752957 100644 --- a/tests/perpetual/test_trading_client.py +++ b/tests/perpetual/test_trading_client.py @@ -7,7 +7,7 @@ from x10.models.asset import AssetOperationModel from x10.models.market import MarketModel -from x10.perpetual.configuration import TESTNET_CONFIG +from x10.config import TESTNET_CONFIG from x10.utils.http import WrappedApiResponse @@ -33,8 +33,9 @@ async def test_get_markets(aiohttp_server, create_btc_usd_market): server = await aiohttp_server(app) url = f"http://{server.host}:{server.port}" - endpoint_config = dataclasses.replace(TESTNET_CONFIG, api_base_url=url) - trading_client = PerpetualTradingClient(config=endpoint_config) + # FIXME + config = dataclasses.replace(TESTNET_CONFIG.endpoints, api_base_url=url) + trading_client = PerpetualTradingClient(config=config) markets = await trading_client.markets_info.get_markets() assert_that(markets.status, equal_to("OK")) diff --git a/tests/perpetual/test_transfer_object.py b/tests/perpetual/test_transfer_object.py index cb185e8..efe3f1a 100644 --- a/tests/perpetual/test_transfer_object.py +++ b/tests/perpetual/test_transfer_object.py @@ -5,7 +5,7 @@ from hamcrest import assert_that, equal_to from pytest_mock import MockerFixture -from x10.perpetual.configuration import TESTNET_CONFIG +from x10.config import TESTNET_CONFIG FROZEN_NONCE = 1473459052 diff --git a/x10/perpetual/user_client/user_client.py b/x10/perpetual/user_client/user_client.py index 89c04e8..e68a4c6 100644 --- a/x10/perpetual/user_client/user_client.py +++ b/x10/perpetual/user_client/user_client.py @@ -36,17 +36,17 @@ class OnBoardedAccount: class UserClient: - __endpoint_config: Config + __config: Config __l1_private_key: Callable[[], str] __session: Optional[aiohttp.ClientSession] = None def __init__( self, - endpoint_config: Config, + config: Config, l1_private_key: Callable[[], str], ): super().__init__() - self.__endpoint_config = endpoint_config + self.__config = config self.__l1_private_key = l1_private_key def _get_url(self, base_url: str, path: str, *, query: Optional[Dict] = None, **path_params) -> str: @@ -55,7 +55,7 @@ def _get_url(self, base_url: str, path: str, *, query: Optional[Dict] = None, ** async def get_session(self) -> aiohttp.ClientSession: if self.__session is None: created_session = aiohttp.ClientSession( - timeout=ClientTimeout(total=self.__endpoint_config.defaults.request_timeout_seconds) + timeout=ClientTimeout(total=self.__config.defaults.request_timeout_seconds) ) self.__session = created_session @@ -69,11 +69,11 @@ async def close_session(self): async def onboard(self, referral_code: Optional[str] = None): signing_account: LocalAccount = Account.from_key(self.__l1_private_key()) key_pair = get_l2_keys_from_l1_account( - l1_account=signing_account, account_index=0, signing_domain=self.__endpoint_config.signing.signing_domain + l1_account=signing_account, account_index=0, signing_domain=self.__config.signing.signing_domain ) payload = get_onboarding_payload( signing_account, - signing_domain=self.__endpoint_config.signing.signing_domain, + signing_domain=self.__config.signing.signing_domain, key_pair=key_pair, referral_code=referral_code, host=self._get_endpoint_config().onboarding_url, @@ -103,7 +103,7 @@ async def onboard_subaccount(self, account_index: int, description: str | None = key_pair = get_l2_keys_from_l1_account( l1_account=signing_account, account_index=account_index, - signing_domain=self.__endpoint_config.signing.signing_domain, + signing_domain=self.__config.signing.signing_domain, ) payload = get_sub_account_creation_payload( account_index=account_index, @@ -162,7 +162,7 @@ async def get_accounts(self) -> List[OnBoardedAccount]: l2_key_pair=get_l2_keys_from_l1_account( l1_account=signing_account, account_index=account.account_index, - signing_domain=self.__endpoint_config.signing.signing_domain, + signing_domain=self.__config.signing.signing_domain, ), ) for account in accounts @@ -199,4 +199,4 @@ async def create_account_api_key(self, account: AccountModel, description: str | return response_data.key def _get_endpoint_config(self): - return self.__endpoint_config.endpoints + return self.__config.endpoints From 026532df4eb3e2ef5cc79c7936d41010257d594d Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 14:05:40 +0400 Subject: [PATCH 14/19] Unify configs --- .../perpetual/order_object/test_conditional_order_object.py | 2 +- tests/perpetual/order_object/test_limit_order_object.py | 2 +- tests/perpetual/order_object/test_market_order_object.py | 2 +- tests/perpetual/order_object/test_order_object_attrs.py | 6 +++--- tests/perpetual/order_object/test_tpsl_order_object.py | 2 +- tests/perpetual/test_orderbook_price_impact.py | 2 +- tests/perpetual/test_trading_client.py | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/perpetual/order_object/test_conditional_order_object.py b/tests/perpetual/order_object/test_conditional_order_object.py index 9d43922..29889b7 100644 --- a/tests/perpetual/order_object/test_conditional_order_object.py +++ b/tests/perpetual/order_object/test_conditional_order_object.py @@ -5,6 +5,7 @@ from hamcrest import assert_that, equal_to from pytest_mock import MockerFixture +from x10.config import TESTNET_CONFIG from x10.models.order import ( OrderPriceType, OrderSide, @@ -12,7 +13,6 @@ OrderTriggerPriceType, OrderType, ) -from x10.config import TESTNET_CONFIG FROZEN_NONCE = 1473459052 diff --git a/tests/perpetual/order_object/test_limit_order_object.py b/tests/perpetual/order_object/test_limit_order_object.py index 3d7964f..7cd49c2 100644 --- a/tests/perpetual/order_object/test_limit_order_object.py +++ b/tests/perpetual/order_object/test_limit_order_object.py @@ -6,6 +6,7 @@ from hamcrest import assert_that, equal_to from pytest_mock import MockerFixture +from x10.config import TESTNET_CONFIG from x10.models.order import ( OrderPriceType, OrderSide, @@ -13,7 +14,6 @@ OrderTriggerPriceType, SelfTradeProtectionLevel, ) -from x10.config import TESTNET_CONFIG from x10.utils.date import utc_now FROZEN_NONCE = 1473459052 diff --git a/tests/perpetual/order_object/test_market_order_object.py b/tests/perpetual/order_object/test_market_order_object.py index c382bd5..16cbd07 100644 --- a/tests/perpetual/order_object/test_market_order_object.py +++ b/tests/perpetual/order_object/test_market_order_object.py @@ -6,8 +6,8 @@ from hamcrest import assert_that, equal_to from pytest_mock import MockerFixture -from x10.models.order import OrderSide, OrderType, TimeInForce from x10.config import TESTNET_CONFIG +from x10.models.order import OrderSide, OrderType, TimeInForce from x10.utils.date import utc_now from x10.utils.order import get_price_with_slippage diff --git a/tests/perpetual/order_object/test_order_object_attrs.py b/tests/perpetual/order_object/test_order_object_attrs.py index c751173..c158c5a 100644 --- a/tests/perpetual/order_object/test_order_object_attrs.py +++ b/tests/perpetual/order_object/test_order_object_attrs.py @@ -6,8 +6,8 @@ from hamcrest import assert_that, equal_to, has_entries from pytest_mock import MockerFixture -from x10.models.order import OrderSide from x10.config import TESTNET_CONFIG +from x10.models.order import OrderSide from x10.utils.date import utc_now FROZEN_NONCE = 1473459052 @@ -31,7 +31,7 @@ async def test_cancel_previous_order(mocker: MockerFixture, create_trading_accou expire_time=utc_now() + timedelta(days=14), previous_order_external_id="previous_custom_id", starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee + taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) assert_that( @@ -62,7 +62,7 @@ async def test_external_order_id(mocker: MockerFixture, create_trading_account, expire_time=utc_now() + timedelta(days=14), order_external_id="custom_id", starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee + taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) assert_that( diff --git a/tests/perpetual/order_object/test_tpsl_order_object.py b/tests/perpetual/order_object/test_tpsl_order_object.py index c326a0c..bc8838d 100644 --- a/tests/perpetual/order_object/test_tpsl_order_object.py +++ b/tests/perpetual/order_object/test_tpsl_order_object.py @@ -6,6 +6,7 @@ from hamcrest import assert_that, equal_to from pytest_mock import MockerFixture +from x10.config import TESTNET_CONFIG from x10.models.order import ( OrderPriceType, OrderSide, @@ -14,7 +15,6 @@ OrderType, SelfTradeProtectionLevel, ) -from x10.config import TESTNET_CONFIG from x10.utils.date import utc_now FROZEN_NONCE = 1473459052 diff --git a/tests/perpetual/test_orderbook_price_impact.py b/tests/perpetual/test_orderbook_price_impact.py index 09fab26..3bab482 100644 --- a/tests/perpetual/test_orderbook_price_impact.py +++ b/tests/perpetual/test_orderbook_price_impact.py @@ -2,8 +2,8 @@ import decimal from unittest import TestCase -from x10.models.orderbook import OrderbookUpdateModel from x10.config import TESTNET_CONFIG +from x10.models.orderbook import OrderbookUpdateModel from x10.perpetual.orderbook import OrderBook diff --git a/tests/perpetual/test_trading_client.py b/tests/perpetual/test_trading_client.py index b752957..557000f 100644 --- a/tests/perpetual/test_trading_client.py +++ b/tests/perpetual/test_trading_client.py @@ -5,9 +5,9 @@ from aiohttp import web from hamcrest import assert_that, equal_to, has_length +from x10.config import TESTNET_CONFIG from x10.models.asset import AssetOperationModel from x10.models.market import MarketModel -from x10.config import TESTNET_CONFIG from x10.utils.http import WrappedApiResponse From 0f3c14c09dbf8e0a831ab7b5662c577eda004fc3 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 14:07:00 +0400 Subject: [PATCH 15/19] Unify configs --- tests/perpetual/test_trading_client.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/perpetual/test_trading_client.py b/tests/perpetual/test_trading_client.py index 557000f..5864af1 100644 --- a/tests/perpetual/test_trading_client.py +++ b/tests/perpetual/test_trading_client.py @@ -33,8 +33,8 @@ async def test_get_markets(aiohttp_server, create_btc_usd_market): server = await aiohttp_server(app) url = f"http://{server.host}:{server.port}" - # FIXME - config = dataclasses.replace(TESTNET_CONFIG.endpoints, api_base_url=url) + endpoints_config = dataclasses.replace(TESTNET_CONFIG.endpoints, api_base_url=url) + config = dataclasses.replace(TESTNET_CONFIG, endpoints=endpoints_config) trading_client = PerpetualTradingClient(config=config) markets = await trading_client.markets_info.get_markets() @@ -134,8 +134,9 @@ async def test_get_asset_operations(aiohttp_server, create_asset_operations, cre url = f"http://{server.host}:{server.port}" stark_account = create_trading_account() - endpoint_config = endpoint_config = dataclasses.replace(TESTNET_CONFIG, api_base_url=url) - trading_client = PerpetualTradingClient(config=endpoint_config, stark_account=stark_account) + endpoints_config = dataclasses.replace(TESTNET_CONFIG.endpoints, api_base_url=url) + config = dataclasses.replace(TESTNET_CONFIG, endpoints=endpoints_config) + trading_client = PerpetualTradingClient(config=config, stark_account=stark_account) operations = await trading_client.account.asset_operations() assert_that(operations.status, equal_to("OK")) From b0b49c9125f67394e54585940f7022d79418d7b2 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 14:10:02 +0400 Subject: [PATCH 16/19] Unify configs --- tests/perpetual/test_orderbook_price_impact.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/perpetual/test_orderbook_price_impact.py b/tests/perpetual/test_orderbook_price_impact.py index 3bab482..fa3d162 100644 --- a/tests/perpetual/test_orderbook_price_impact.py +++ b/tests/perpetual/test_orderbook_price_impact.py @@ -9,10 +9,9 @@ class TestOrderBook(TestCase): def setUp(self): - self.endpoint_config = TESTNET_CONFIG self.market_name = "dummy-market" self.orderbook = OrderBook( - self.endpoint_config, + TESTNET_CONFIG, self.market_name, best_ask_change_callback=None, best_bid_change_callback=None, From a659d640f3115f739259fb66801aeede1b36b9dd Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 14:22:48 +0400 Subject: [PATCH 17/19] Unify configs --- MIGRATION.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index 2477861..eef16cd 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -8,3 +8,7 @@ classes were also renamed to follow the consistent `*Model` suffix convention. - `StarkPerpetualAccount` (previously in `x10.perpetual.accounts`) has moved to `x10.core.stark_account`. - The package now ships a `py.typed` marker (PEP 561), so mypy will now type-check against the SDK's inline annotations by default. +- `x10.perpetual.configuration` has been **deleted**. All config types and pre-built instances now live in `x10.config`. +- `TESTNET_CONFIG` and `MAINNET_CONFIG` are now instances of the new `Config` dataclass (groups URLs, singing settings, defaults). +- Market names constants have been removed from `x10.config`. Define market name strings inline in your own code. +- `taker_fee` is now a required parameter for order creation. From c8e32c55729e14347c3415d07ae4a29372618b4e Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 14:26:41 +0400 Subject: [PATCH 18/19] Unify configs --- x10/_config.py | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 x10/_config.py diff --git a/x10/_config.py b/x10/_config.py deleted file mode 100644 index 31788ff..0000000 --- a/x10/_config.py +++ /dev/null @@ -1,21 +0,0 @@ -from decimal import Decimal - -from x10.models.fee import TradingFeeModel - -# BTC_USD_MARKET = "BTC-USD" -# SOL_USD_MARKET = "SOL-USD" -# ADA_USD_MARKET = "ADA-USD" -# ETH_USD_MARKET = "ETH-USD" - -# FIXME: Move to config -DEFAULT_MARKET_PRICE_SLIPPAGE = Decimal("0.0075") -DEFAULT_REQUEST_TIMEOUT_SECONDS = 500 - - -# FIXME: Move to config -DEFAULT_FEES = TradingFeeModel( - market="BTC-USD", - maker_fee_rate=(Decimal("2") / Decimal("10000")), - taker_fee_rate=(Decimal("5") / Decimal("10000")), - builder_fee_rate=Decimal("0"), -) From a35fb2d95db6462bf7f17458d24474b69e9e08c7 Mon Sep 17 00:00:00 2001 From: alex101xela Date: Tue, 21 Apr 2026 14:35:46 +0400 Subject: [PATCH 19/19] Unify configs --- MIGRATION.md | 1 - examples/cases/advanced/load_testing.py | 1 - .../cases/buildercode/create_limit_order_with_builder.py | 1 - examples/cases/createorder/create_conditional_order.py | 1 - examples/cases/createorder/create_limit_order.py | 1 - examples/cases/createorder/create_market_order.py | 1 - .../create_market_order_with_blocking_client.py | 1 - .../cases/tpsl/create_limit_order_with_partial_tpsl.py | 1 - .../cases/tpsl/create_limit_order_with_position_tpsl.py | 1 - examples/cases/tpsl/create_partial_tpsl_order.py | 1 - examples/cases/tpsl/create_position_tpsl_order.py | 1 - .../order_object/test_conditional_order_object.py | 1 - tests/perpetual/order_object/test_limit_order_object.py | 5 ----- tests/perpetual/order_object/test_market_order_object.py | 2 -- tests/perpetual/order_object/test_order_object_attrs.py | 2 -- tests/perpetual/order_object/test_tpsl_order_object.py | 2 -- x10/config.py | 5 +---- x10/perpetual/order_object.py | 9 +++++++-- 18 files changed, 8 insertions(+), 29 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index eef16cd..00c84ef 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -11,4 +11,3 @@ the SDK's inline annotations by default. - `x10.perpetual.configuration` has been **deleted**. All config types and pre-built instances now live in `x10.config`. - `TESTNET_CONFIG` and `MAINNET_CONFIG` are now instances of the new `Config` dataclass (groups URLs, singing settings, defaults). - Market names constants have been removed from `x10.config`. Define market name strings inline in your own code. -- `taker_fee` is now a required parameter for order creation. diff --git a/examples/cases/advanced/load_testing.py b/examples/cases/advanced/load_testing.py index 29b516a..47dd5b5 100644 --- a/examples/cases/advanced/load_testing.py +++ b/examples/cases/advanced/load_testing.py @@ -49,7 +49,6 @@ async def create_orders_loop(*, trading_client: PerpetualTradingClient, market: starknet_domain=trading_client.config.starknet_domain, order_external_id=new_order_external_id, post_only=True, - taker_fee=trading_client.config.defaults.taker_fee, ) async with unconfirmed_order_lock: diff --git a/examples/cases/buildercode/create_limit_order_with_builder.py b/examples/cases/buildercode/create_limit_order_with_builder.py index df1c2a5..8f1831f 100644 --- a/examples/cases/buildercode/create_limit_order_with_builder.py +++ b/examples/cases/buildercode/create_limit_order_with_builder.py @@ -45,7 +45,6 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, - taker_fee=trading_client.config.defaults.taker_fee, builder_fee=builder_fee, builder_id=builder_id, ) diff --git a/examples/cases/createorder/create_conditional_order.py b/examples/cases/createorder/create_conditional_order.py index 7141e55..6bbf4ff 100644 --- a/examples/cases/createorder/create_conditional_order.py +++ b/examples/cases/createorder/create_conditional_order.py @@ -45,7 +45,6 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, - taker_fee=trading_client.config.defaults.taker_fee, trigger=OrderConditionalTriggerParam( trigger_price=order_trigger_price, trigger_price_type=OrderTriggerPriceType.LAST, diff --git a/examples/cases/createorder/create_limit_order.py b/examples/cases/createorder/create_limit_order.py index 2fe1a1f..570c9ab 100644 --- a/examples/cases/createorder/create_limit_order.py +++ b/examples/cases/createorder/create_limit_order.py @@ -36,7 +36,6 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, - taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/createorder/create_market_order.py b/examples/cases/createorder/create_market_order.py index f6798a6..3945328 100644 --- a/examples/cases/createorder/create_market_order.py +++ b/examples/cases/createorder/create_market_order.py @@ -41,7 +41,6 @@ async def run_example(): time_in_force=TimeInForce.IOC, reduce_only=False, post_only=False, - taker_fee=trading_client.config.defaults.taker_fee, ) LOGGER.info("Placing order...") diff --git a/examples/cases/createorder/create_market_order_with_blocking_client.py b/examples/cases/createorder/create_market_order_with_blocking_client.py index 52b0086..d65f9d2 100644 --- a/examples/cases/createorder/create_market_order_with_blocking_client.py +++ b/examples/cases/createorder/create_market_order_with_blocking_client.py @@ -69,7 +69,6 @@ async def run_example(): time_in_force=TimeInForce.IOC, reduce_only=False, post_only=False, - taker_fee=blocking_client.config.defaults.taker_fee, ) await blocking_client.close() diff --git a/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py b/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py index cb14f26..1fb7188 100644 --- a/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py +++ b/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py @@ -50,7 +50,6 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, - taker_fee=trading_client.config.defaults.taker_fee, tp_sl_type=OrderTpslType.ORDER, take_profit=OrderTpslTriggerParam( trigger_price=tp_trigger_price, diff --git a/examples/cases/tpsl/create_limit_order_with_position_tpsl.py b/examples/cases/tpsl/create_limit_order_with_position_tpsl.py index 9424b65..383be08 100644 --- a/examples/cases/tpsl/create_limit_order_with_position_tpsl.py +++ b/examples/cases/tpsl/create_limit_order_with_position_tpsl.py @@ -47,7 +47,6 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=False, post_only=True, - taker_fee=trading_client.config.defaults.taker_fee, tp_sl_type=OrderTpslType.POSITION, take_profit=OrderTpslTriggerParam( trigger_price=tp_trigger_price, diff --git a/examples/cases/tpsl/create_partial_tpsl_order.py b/examples/cases/tpsl/create_partial_tpsl_order.py index 1aa8dcc..cedfcdf 100644 --- a/examples/cases/tpsl/create_partial_tpsl_order.py +++ b/examples/cases/tpsl/create_partial_tpsl_order.py @@ -50,7 +50,6 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=True, post_only=False, - taker_fee=trading_client.config.defaults.taker_fee, tp_sl_type=OrderTpslType.ORDER, take_profit=OrderTpslTriggerParam( trigger_price=tp_trigger_price, diff --git a/examples/cases/tpsl/create_position_tpsl_order.py b/examples/cases/tpsl/create_position_tpsl_order.py index 597de02..0ce86f1 100644 --- a/examples/cases/tpsl/create_position_tpsl_order.py +++ b/examples/cases/tpsl/create_position_tpsl_order.py @@ -48,7 +48,6 @@ async def run_example(): time_in_force=TimeInForce.GTT, reduce_only=True, post_only=False, - taker_fee=trading_client.config.defaults.taker_fee, tp_sl_type=OrderTpslType.POSITION, take_profit=OrderTpslTriggerParam( trigger_price=tp_trigger_price, diff --git a/tests/perpetual/order_object/test_conditional_order_object.py b/tests/perpetual/order_object/test_conditional_order_object.py index 29889b7..dbc97ea 100644 --- a/tests/perpetual/order_object/test_conditional_order_object.py +++ b/tests/perpetual/order_object/test_conditional_order_object.py @@ -37,7 +37,6 @@ async def test_create_buy_order(mocker: MockerFixture, create_trading_account, c price=Decimal("43445.11680000"), side=OrderSide.BUY, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, trigger=OrderConditionalTriggerParam( trigger_price=Decimal("43400"), trigger_price_type=OrderTriggerPriceType.INDEX, diff --git a/tests/perpetual/order_object/test_limit_order_object.py b/tests/perpetual/order_object/test_limit_order_object.py index 7cd49c2..987182c 100644 --- a/tests/perpetual/order_object/test_limit_order_object.py +++ b/tests/perpetual/order_object/test_limit_order_object.py @@ -39,7 +39,6 @@ async def test_create_sell_order_with_default_expiration( price=Decimal("43445.11680000"), side=OrderSide.SELL, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) freezer.stop() assert_that( @@ -97,7 +96,6 @@ async def test_create_sell_order(mocker: MockerFixture, create_trading_account, side=OrderSide.SELL, expire_time=utc_now() + timedelta(days=14), starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, nonce=FROZEN_NONCE, ) @@ -157,7 +155,6 @@ async def test_create_buy_order(mocker: MockerFixture, create_trading_account, c expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) assert_that( @@ -216,7 +213,6 @@ async def test_create_buy_order_with_order_tpsl(mocker: MockerFixture, create_tr expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, tp_sl_type=OrderTpslType.ORDER, take_profit=OrderTpslTriggerParam( trigger_price=Decimal("49000"), @@ -326,7 +322,6 @@ async def test_create_buy_order_with_position_tpsl( expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, tp_sl_type=OrderTpslType.POSITION, take_profit=OrderTpslTriggerParam( trigger_price=Decimal("49000"), diff --git a/tests/perpetual/order_object/test_market_order_object.py b/tests/perpetual/order_object/test_market_order_object.py index 16cbd07..5767dd0 100644 --- a/tests/perpetual/order_object/test_market_order_object.py +++ b/tests/perpetual/order_object/test_market_order_object.py @@ -42,7 +42,6 @@ async def test_create_sell_order(mocker: MockerFixture, create_trading_account, time_in_force=TimeInForce.IOC, nonce=FROZEN_NONCE, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) assert_that( @@ -109,7 +108,6 @@ async def test_create_buy_order(mocker: MockerFixture, create_trading_account, c expire_time=utc_now() + timedelta(days=14), time_in_force=TimeInForce.IOC, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, nonce=FROZEN_NONCE, ) diff --git a/tests/perpetual/order_object/test_order_object_attrs.py b/tests/perpetual/order_object/test_order_object_attrs.py index c158c5a..d4b5a57 100644 --- a/tests/perpetual/order_object/test_order_object_attrs.py +++ b/tests/perpetual/order_object/test_order_object_attrs.py @@ -31,7 +31,6 @@ async def test_cancel_previous_order(mocker: MockerFixture, create_trading_accou expire_time=utc_now() + timedelta(days=14), previous_order_external_id="previous_custom_id", starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) assert_that( @@ -62,7 +61,6 @@ async def test_external_order_id(mocker: MockerFixture, create_trading_account, expire_time=utc_now() + timedelta(days=14), order_external_id="custom_id", starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, ) assert_that( diff --git a/tests/perpetual/order_object/test_tpsl_order_object.py b/tests/perpetual/order_object/test_tpsl_order_object.py index bc8838d..7505252 100644 --- a/tests/perpetual/order_object/test_tpsl_order_object.py +++ b/tests/perpetual/order_object/test_tpsl_order_object.py @@ -40,7 +40,6 @@ async def test_create_buy_partial_tpsl_order(mocker: MockerFixture, create_tradi expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, tp_sl_type=OrderTpslType.ORDER, take_profit=OrderTpslTriggerParam( trigger_price=Decimal("49000"), @@ -135,7 +134,6 @@ async def test_create_buy_position_tpsl_order(mocker: MockerFixture, create_trad expire_time=utc_now() + timedelta(days=14), self_trade_protection_level=SelfTradeProtectionLevel.CLIENT, starknet_domain=TESTNET_CONFIG.signing.starknet_domain, - taker_fee=TESTNET_CONFIG.defaults.taker_fee, tp_sl_type=OrderTpslType.POSITION, take_profit=OrderTpslTriggerParam( trigger_price=Decimal("49000"), diff --git a/x10/config.py b/x10/config.py index f4f0455..be55959 100644 --- a/x10/config.py +++ b/x10/config.py @@ -14,7 +14,6 @@ class StarknetDomain: class DefaultsConfig: market_price_slippage: Decimal request_timeout_seconds: int - taker_fee: Decimal @dataclass(kw_only=True, frozen=True) @@ -56,9 +55,7 @@ class Config: endpoints: EndpointsConfig -DEFAULTS = DefaultsConfig( - market_price_slippage=Decimal("0.0075"), request_timeout_seconds=500, taker_fee=Decimal("0.0005") -) +DEFAULTS = DefaultsConfig(market_price_slippage=Decimal("0.0075"), request_timeout_seconds=500) TESTNET_CONFIG = Config( defaults=DEFAULTS, diff --git a/x10/perpetual/order_object.py b/x10/perpetual/order_object.py index 5de7cc2..5cd275c 100644 --- a/x10/perpetual/order_object.py +++ b/x10/perpetual/order_object.py @@ -27,6 +27,8 @@ from x10.utils.nonce import generate_nonce from x10.utils.order import calc_entire_position_size +DEFAULT_TAKER_FEE = Decimal("0.0005") + @dataclass(kw_only=True) class OrderConditionalTriggerParam: @@ -60,7 +62,7 @@ def create_order_object( time_in_force: TimeInForce = TimeInForce.GTT, self_trade_protection_level: SelfTradeProtectionLevel = SelfTradeProtectionLevel.ACCOUNT, nonce: Optional[int] = None, - taker_fee: Decimal, + taker_fee: Optional[Decimal] = None, builder_fee: Optional[Decimal] = None, builder_id: Optional[int] = None, reduce_only: bool = False, @@ -164,7 +166,7 @@ def __create_order_object( time_in_force: TimeInForce = TimeInForce.GTT, self_trade_protection_level: SelfTradeProtectionLevel = SelfTradeProtectionLevel.ACCOUNT, nonce: Optional[int] = None, - taker_fee: Decimal, + taker_fee: Optional[Decimal] = None, builder_fee: Optional[Decimal] = None, builder_id: Optional[int] = None, reduce_only: bool = False, @@ -219,6 +221,9 @@ def validate_tpsl_order(): if nonce is None: nonce = generate_nonce() + if taker_fee is None: + taker_fee = DEFAULT_TAKER_FEE + settlement_data_ctx = SettlementDataCtx( market=market, taker_fee=taker_fee,