diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..2477861 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,10 @@ +# Migration Guide + +## 1.3.1 -> 1.4.0 + +- All data models have been moved from submodules under `x10/perpetual/*` and +`x10/utils/model.py` into a single, dedicated `x10.models` package. A small number of +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. diff --git a/README.md b/README.md index 747bcfd..8da150f 100644 --- a/README.md +++ b/README.md @@ -365,6 +365,9 @@ def get_private_key_from_eth_signature(eth_signature: str) -> int: There is a new function `deposit` available on the [`AccountModule`](x10/perpetual/trading_client/account_module.py) which provides the ability to directly deposit USDC into your StarkEx account. For more details check out `call_stark_perpetual_deposit` in [contract.py](x10/perpetual/contract.py) +## Breaking changes + +For a detailed list of breaking changes, please refer to the [MIGRATION.md](MIGRATION.md) file. ## Contributing diff --git a/examples/cases/advanced/load_testing.py b/examples/cases/advanced/load_testing.py index fad5005..b00d22f 100644 --- a/examples/cases/advanced/load_testing.py +++ b/examples/cases/advanced/load_testing.py @@ -6,9 +6,9 @@ from examples.utils import create_trading_client from x10.config import BTC_USD_MARKET -from x10.perpetual.markets import MarketModel +from x10.models.market import MarketModel +from x10.models.order import OrderSide from x10.perpetual.order_object import create_order_object -from x10.perpetual.orders import OrderSide from x10.perpetual.stream_client.stream_client import PerpetualStreamClient from x10.perpetual.trading_client import PerpetualTradingClient diff --git a/examples/cases/advanced/market_maker.py b/examples/cases/advanced/market_maker.py index 61b585f..e839b33 100644 --- a/examples/cases/advanced/market_maker.py +++ b/examples/cases/advanced/market_maker.py @@ -7,8 +7,8 @@ from examples.utils import create_trading_client from x10.config import BTC_USD_MARKET +from x10.models.order import OrderSide from x10.perpetual.orderbook import OrderBook, OrderBookEntry -from x10.perpetual.orders import OrderSide LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET diff --git a/examples/cases/advanced/onboarding_with_eth_account.py b/examples/cases/advanced/onboarding_with_eth_account.py index 85dd396..a7c9edf 100644 --- a/examples/cases/advanced/onboarding_with_eth_account.py +++ b/examples/cases/advanced/onboarding_with_eth_account.py @@ -5,7 +5,7 @@ from eth_account.signers.local import LocalAccount from examples.utils import init_env -from x10.perpetual.accounts import StarkPerpetualAccount +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 diff --git a/examples/cases/buildercode/create_limit_order_with_builder.py b/examples/cases/buildercode/create_limit_order_with_builder.py index f104fb0..dfd7f36 100644 --- a/examples/cases/buildercode/create_limit_order_with_builder.py +++ b/examples/cases/buildercode/create_limit_order_with_builder.py @@ -8,8 +8,8 @@ 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 -from x10.perpetual.orders import OrderSide, TimeInForce LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET diff --git a/examples/cases/createorder/create_conditional_order.py b/examples/cases/createorder/create_conditional_order.py index d93fb01..e9461c9 100644 --- a/examples/cases/createorder/create_conditional_order.py +++ b/examples/cases/createorder/create_conditional_order.py @@ -7,8 +7,7 @@ get_adjust_price_by_pct, ) from x10.config import BTC_USD_MARKET -from x10.perpetual.order_object import OrderConditionalTriggerParam, create_order_object -from x10.perpetual.orders import ( +from x10.models.order import ( OrderPriceType, OrderSide, OrderTriggerDirection, @@ -16,6 +15,7 @@ OrderType, TimeInForce, ) +from x10.perpetual.order_object import OrderConditionalTriggerParam, create_order_object LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET diff --git a/examples/cases/createorder/create_limit_order.py b/examples/cases/createorder/create_limit_order.py index a7b08ec..5d1b862 100644 --- a/examples/cases/createorder/create_limit_order.py +++ b/examples/cases/createorder/create_limit_order.py @@ -7,8 +7,8 @@ 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 -from x10.perpetual.orders import OrderSide, TimeInForce LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET diff --git a/examples/cases/createorder/create_market_order.py b/examples/cases/createorder/create_market_order.py index da5334e..5175ff1 100644 --- a/examples/cases/createorder/create_market_order.py +++ b/examples/cases/createorder/create_market_order.py @@ -3,8 +3,8 @@ from examples.utils import create_trading_client from x10.config import BTC_USD_MARKET, DEFAULT_MARKET_PRICE_SLIPPAGE +from x10.models.order import OrderSide, OrderType, TimeInForce from x10.perpetual.order_object import create_order_object -from x10.perpetual.orders import OrderSide, OrderType, TimeInForce from x10.utils.order import get_price_with_slippage LOGGER = logging.getLogger() 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 3e5bc20..8a42521 100644 --- a/examples/cases/createorder/create_market_order_with_blocking_client.py +++ b/examples/cases/createorder/create_market_order_with_blocking_client.py @@ -3,9 +3,9 @@ from examples.utils import create_blocking_client from x10.config import BTC_USD_MARKET, DEFAULT_MARKET_PRICE_SLIPPAGE +from x10.models.order import OrderSide, OrderType, TimeInForce from x10.perpetual.configuration import TESTNET_CONFIG from x10.perpetual.orderbook import OrderBook -from x10.perpetual.orders import OrderSide, OrderType, TimeInForce from x10.utils.order import get_price_with_slippage LOGGER = logging.getLogger() 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 b3c2912..c79afe2 100644 --- a/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py +++ b/examples/cases/tpsl/create_limit_order_with_partial_tpsl.py @@ -8,14 +8,14 @@ get_adjust_price_by_pct, ) from x10.config import BTC_USD_MARKET, DEFAULT_MARKET_PRICE_SLIPPAGE -from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object -from x10.perpetual.orders import ( +from x10.models.order import ( OrderPriceType, OrderSide, OrderTpslType, OrderTriggerPriceType, TimeInForce, ) +from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET 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 d17aaba..2d5029e 100644 --- a/examples/cases/tpsl/create_limit_order_with_position_tpsl.py +++ b/examples/cases/tpsl/create_limit_order_with_position_tpsl.py @@ -7,14 +7,14 @@ get_adjust_price_by_pct, ) from x10.config import BTC_USD_MARKET -from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object -from x10.perpetual.orders import ( +from x10.models.order import ( OrderPriceType, OrderSide, OrderTpslType, OrderTriggerPriceType, TimeInForce, ) +from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET diff --git a/examples/cases/tpsl/create_partial_tpsl_order.py b/examples/cases/tpsl/create_partial_tpsl_order.py index 3a8958a..e94e1c5 100644 --- a/examples/cases/tpsl/create_partial_tpsl_order.py +++ b/examples/cases/tpsl/create_partial_tpsl_order.py @@ -8,8 +8,7 @@ get_adjust_price_by_pct, ) from x10.config import BTC_USD_MARKET -from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object -from x10.perpetual.orders import ( +from x10.models.order import ( OrderPriceType, OrderSide, OrderTpslType, @@ -17,6 +16,7 @@ OrderType, TimeInForce, ) +from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET diff --git a/examples/cases/tpsl/create_position_tpsl_order.py b/examples/cases/tpsl/create_position_tpsl_order.py index 4aaea74..5f5c979 100644 --- a/examples/cases/tpsl/create_position_tpsl_order.py +++ b/examples/cases/tpsl/create_position_tpsl_order.py @@ -8,8 +8,7 @@ get_adjust_price_by_pct, ) from x10.config import BTC_USD_MARKET -from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object -from x10.perpetual.orders import ( +from x10.models.order import ( OrderPriceType, OrderSide, OrderTpslType, @@ -17,6 +16,7 @@ OrderType, TimeInForce, ) +from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object LOGGER = logging.getLogger() MARKET_NAME = BTC_USD_MARKET diff --git a/examples/utils.py b/examples/utils.py index f8380c3..5cf34d4 100644 --- a/examples/utils.py +++ b/examples/utils.py @@ -10,9 +10,9 @@ import yaml from dotenv import load_dotenv -from x10.perpetual.accounts import StarkPerpetualAccount +from x10.core.stark_account import StarkPerpetualAccount +from x10.models.market import TradingConfigModel from x10.perpetual.configuration import TESTNET_CONFIG, EndpointConfig -from x10.perpetual.markets import TradingConfigModel from x10.perpetual.simple_client.simple_trading_client import BlockingTradingClient from x10.perpetual.stream_client import PerpetualStreamClient from x10.perpetual.trading_client import PerpetualTradingClient diff --git a/pyproject.toml b/pyproject.toml index 11d50d5..03c9b5a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "x10-python-trading-starknet" -version = "1.3.1" +version = "1.4.0" description = "Python client for X10 API" authors = ["X10 "] repository = "https://github.com/x10xchange/python_sdk" diff --git a/tests/conftest.py b/tests/conftest.py index e6bcef7..6b3d1c0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,30 +3,28 @@ @pytest.fixture def create_accounts(): - from tests.fixtures.accounts import create_accounts as _create_accounts + from tests.fixtures.account import create_accounts as _create_accounts return _create_accounts @pytest.fixture def create_trading_account(): - from tests.fixtures.accounts import ( - create_trading_account as _create_trading_account, - ) + from tests.fixtures.account import create_trading_account as _create_trading_account return _create_trading_account @pytest.fixture def btc_usd_market_json_data(): - from tests.fixtures.markets import get_btc_usd_market_json_data + from tests.fixtures.market import get_btc_usd_market_json_data return get_btc_usd_market_json_data() @pytest.fixture def create_btc_usd_market(btc_usd_market_json_data): - from tests.fixtures.markets import create_btc_usd_market as _create_btc_usd_market + from tests.fixtures.market import create_btc_usd_market as _create_btc_usd_market return lambda: _create_btc_usd_market(btc_usd_market_json_data) @@ -42,7 +40,7 @@ def create_orderbook_message(): @pytest.fixture def create_account_update_trade_message(): - from tests.fixtures.accounts import ( + from tests.fixtures.account import ( create_account_update_trade_message as _create_account_update_trade_message, ) @@ -51,7 +49,7 @@ def create_account_update_trade_message(): @pytest.fixture def create_account_update_unknown_message(): - from tests.fixtures.accounts import ( + from tests.fixtures.account import ( create_account_update_unknown_message as _create_account_update_unknown_message, ) @@ -60,22 +58,20 @@ def create_account_update_unknown_message(): @pytest.fixture def get_asset_usd(): - from tests.fixtures.assets import get_asset_usd as _get_asset_usd + from tests.fixtures.asset import get_asset_usd as _get_asset_usd return _get_asset_usd @pytest.fixture def get_asset_xvs(): - from tests.fixtures.assets import get_asset_xvs as _get_asset_xvs + from tests.fixtures.asset import get_asset_xvs as _get_asset_xvs return _get_asset_xvs @pytest.fixture def create_asset_operations(): - from tests.fixtures.assets import ( - create_asset_operations as _create_asset_operations, - ) + from tests.fixtures.asset import create_asset_operations as _create_asset_operations return _create_asset_operations diff --git a/tests/fixtures/accounts.py b/tests/fixtures/account.py similarity index 88% rename from tests/fixtures/accounts.py rename to tests/fixtures/account.py index 339c71e..afa2089 100644 --- a/tests/fixtures/accounts.py +++ b/tests/fixtures/account.py @@ -1,6 +1,6 @@ from decimal import Decimal -from x10.perpetual.accounts import AccountModel +from x10.models.account import AccountModel def create_accounts(): @@ -27,7 +27,7 @@ def create_accounts(): def create_trading_account(): - from x10.perpetual.accounts import StarkPerpetualAccount + from x10.core.stark_account import StarkPerpetualAccount return StarkPerpetualAccount( vault=10002, @@ -38,8 +38,8 @@ def create_trading_account(): def create_account_update_trade_message(): - from x10.perpetual.accounts import AccountStreamDataModel - from x10.perpetual.trades import AccountTradeModel + from x10.models.account import AccountStreamDataModel + from x10.models.trade import AccountTradeModel from x10.utils.http import WrappedStreamResponse return WrappedStreamResponse[AccountStreamDataModel]( @@ -68,7 +68,7 @@ def create_account_update_trade_message(): def create_account_update_unknown_message(): - from x10.perpetual.accounts import AccountStreamDataModel + from x10.models.account import AccountStreamDataModel from x10.utils.http import WrappedStreamResponse return WrappedStreamResponse[AccountStreamDataModel]( diff --git a/tests/fixtures/assets.py b/tests/fixtures/asset.py similarity index 95% rename from tests/fixtures/assets.py rename to tests/fixtures/asset.py index c577b17..a04983e 100644 --- a/tests/fixtures/assets.py +++ b/tests/fixtures/asset.py @@ -1,6 +1,6 @@ from decimal import Decimal -from x10.perpetual.assets import AssetModel, AssetOperationModel +from x10.models.asset import AssetModel, AssetOperationModel def create_asset_operations(): diff --git a/tests/fixtures/candles.py b/tests/fixtures/candle.py similarity index 89% rename from tests/fixtures/candles.py rename to tests/fixtures/candle.py index bf48997..b36702c 100644 --- a/tests/fixtures/candles.py +++ b/tests/fixtures/candle.py @@ -1,6 +1,6 @@ from typing import List -from x10.perpetual.candles import CandleModel +from x10.models.candle import CandleModel from x10.utils.http import WrappedStreamResponse diff --git a/tests/fixtures/markets.py b/tests/fixtures/market.py similarity index 99% rename from tests/fixtures/markets.py rename to tests/fixtures/market.py index 1db0326..c7275ef 100644 --- a/tests/fixtures/markets.py +++ b/tests/fixtures/market.py @@ -185,7 +185,7 @@ def get_btc_usd_market_json_data(): def create_btc_usd_market(json_data: str): - from x10.perpetual.markets import MarketModel + from x10.models.market import MarketModel from x10.utils.http import WrappedApiResponse result = WrappedApiResponse[List[MarketModel]].model_validate_json(json_data) diff --git a/tests/fixtures/orderbook.py b/tests/fixtures/orderbook.py index 1ae6acc..ee954af 100644 --- a/tests/fixtures/orderbook.py +++ b/tests/fixtures/orderbook.py @@ -2,7 +2,7 @@ def create_orderbook_message(): - from x10.perpetual.orderbooks import OrderbookQuantityModel, OrderbookUpdateModel + from x10.models.orderbook import OrderbookQuantityModel, OrderbookUpdateModel from x10.utils.http import WrappedStreamResponse return WrappedStreamResponse[OrderbookUpdateModel]( diff --git a/tests/perpetual/order_object/test_conditional_order_object.py b/tests/perpetual/order_object/test_conditional_order_object.py index d989975..4373942 100644 --- a/tests/perpetual/order_object/test_conditional_order_object.py +++ b/tests/perpetual/order_object/test_conditional_order_object.py @@ -5,14 +5,14 @@ from hamcrest import assert_that, equal_to from pytest_mock import MockerFixture -from x10.perpetual.configuration import TESTNET_CONFIG -from x10.perpetual.orders import ( +from x10.models.order import ( OrderPriceType, OrderSide, OrderTriggerDirection, OrderTriggerPriceType, OrderType, ) +from x10.perpetual.configuration 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 afea0b1..8ac267d 100644 --- a/tests/perpetual/order_object/test_limit_order_object.py +++ b/tests/perpetual/order_object/test_limit_order_object.py @@ -6,14 +6,14 @@ from hamcrest import assert_that, equal_to from pytest_mock import MockerFixture -from x10.perpetual.configuration import TESTNET_CONFIG -from x10.perpetual.orders import ( +from x10.models.order import ( OrderPriceType, OrderSide, OrderTpslType, OrderTriggerPriceType, SelfTradeProtectionLevel, ) +from x10.perpetual.configuration 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 6370fdf..a914a48 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.perpetual.configuration import TESTNET_CONFIG -from x10.perpetual.orders 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 e898f72..fe5edb3 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.perpetual.configuration import TESTNET_CONFIG -from x10.perpetual.orders import OrderSide from x10.utils.date import utc_now FROZEN_NONCE = 1473459052 diff --git a/tests/perpetual/order_object/test_tpsl_order_object.py b/tests/perpetual/order_object/test_tpsl_order_object.py index fa572c8..77ad0d6 100644 --- a/tests/perpetual/order_object/test_tpsl_order_object.py +++ b/tests/perpetual/order_object/test_tpsl_order_object.py @@ -6,8 +6,7 @@ from hamcrest import assert_that, equal_to from pytest_mock import MockerFixture -from x10.perpetual.configuration import TESTNET_CONFIG -from x10.perpetual.orders import ( +from x10.models.order import ( OrderPriceType, OrderSide, OrderTpslType, @@ -15,6 +14,7 @@ OrderType, SelfTradeProtectionLevel, ) +from x10.perpetual.configuration import TESTNET_CONFIG from x10.utils.date import utc_now FROZEN_NONCE = 1473459052 diff --git a/tests/perpetual/test_l2_key_derivation.py b/tests/perpetual/test_l2_key_derivation.py index a671928..d560c9d 100644 --- a/tests/perpetual/test_l2_key_derivation.py +++ b/tests/perpetual/test_l2_key_derivation.py @@ -1,4 +1,5 @@ from eth_account import Account +from hamcrest import assert_that, equal_to def test_known_l2_accounts(): @@ -9,5 +10,6 @@ def test_known_l2_accounts(): known_l2_public_key = "0x78298687996aff29a0bbcb994e1305db082d084f85ec38bb78c41e6787740ec" derived_keys = get_l2_keys_from_l1_account(Account.from_key(known_private_key), 0, signing_domain="x10.exchange") - assert derived_keys.private_hex == known_l2_private_key - assert derived_keys.public_hex == known_l2_public_key + + assert_that(derived_keys.private_hex, equal_to(known_l2_private_key)) + assert_that(derived_keys.public_hex, equal_to(known_l2_public_key)) diff --git a/tests/perpetual/test_onboarding_payload.py b/tests/perpetual/test_onboarding_payload.py index 58fa0a7..2aab37e 100644 --- a/tests/perpetual/test_onboarding_payload.py +++ b/tests/perpetual/test_onboarding_payload.py @@ -1,12 +1,15 @@ import datetime from eth_account import Account +from hamcrest import assert_that, equal_to from x10.perpetual.user_client.onboarding import get_l2_keys_from_l1_account def test_onboarding_object_generation(): - # all known values from authentication service tests + """ + All known values from authentication service tests are used. + """ from x10.perpetual.user_client.onboarding import get_onboarding_payload known_private_key = "50c8e358cc974aaaa6e460641e53f78bdc550fd372984aa78ef8fd27c751e6f4" @@ -31,14 +34,25 @@ def test_onboarding_object_generation(): signing_domain="x10.exchange", ).to_json() - assert ( - "0x" + payload["l1Signature"] - == "0x9a59eb699eb58f2ec975455f33dd7205c8a569f7b6d7647c25b71e7ab7eec3d30f2b8c9038f06f077167eb90e0c002602e4ecbab180fad4b2c91d2259883e6571c" # noqa: E501 + assert_that( + payload, + equal_to( + { + "l1Signature": "9a59eb699eb58f2ec975455f33dd7205c8a569f7b6d7647c25b71e7ab7eec3d30f2b8c9038f06f077167eb90e0c002602e4ecbab180fad4b2c91d2259883e6571c", # noqa: E501 + "l2Key": known_l2_public_key, + "l2Signature": { + "r": "0x70881694c59c7212b1a47fbbc07df4d32678f0326f778861ec3a2a5dbc09157", + "s": "0x558805193faa5d780719cba5f699ae1c888eec1fee23da4215fdd94a744d2cb", + }, + "accountCreation": { + "accountIndex": 0, + "wallet": "0x2c12f074766f5eF9c5300ca8C85d06fBa605C59f", + "tosAccepted": True, + "time": "2024-07-30T16:01:02Z", + "action": "REGISTER", + "host": "host", + }, + "referralCode": None, + } + ), ) - - assert payload["l2Key"] == known_l2_public_key - assert payload["l2Signature"]["r"] == "0x70881694c59c7212b1a47fbbc07df4d32678f0326f778861ec3a2a5dbc09157" - assert payload["l2Signature"]["s"] == "0x558805193faa5d780719cba5f699ae1c888eec1fee23da4215fdd94a744d2cb" - assert payload["accountCreation"]["time"] == "2024-07-30T16:01:02Z" - assert payload["accountCreation"]["action"] == "REGISTER" - assert payload["accountCreation"]["tosAccepted"] is True diff --git a/tests/perpetual/test_orderbook_price_impact.py b/tests/perpetual/test_orderbook_price_impact.py index 5460dba..48a67a9 100644 --- a/tests/perpetual/test_orderbook_price_impact.py +++ b/tests/perpetual/test_orderbook_price_impact.py @@ -2,9 +2,9 @@ import decimal from unittest import TestCase +from x10.models.orderbook import OrderbookUpdateModel from x10.perpetual.configuration import TESTNET_CONFIG from x10.perpetual.orderbook import OrderBook -from x10.perpetual.orderbooks import OrderbookUpdateModel class TestOrderBook(TestCase): diff --git a/tests/perpetual/test_stream_client.py b/tests/perpetual/test_stream_client.py index a26f390..ea4649f 100644 --- a/tests/perpetual/test_stream_client.py +++ b/tests/perpetual/test_stream_client.py @@ -122,7 +122,7 @@ async def test_account_update_stream_with_unexpected_type(create_account_update_ @pytest.mark.asyncio async def test_candle_stream(): - from tests.fixtures.candles import create_candle_stream_message + from tests.fixtures.candle import create_candle_stream_message from x10.perpetual.stream_client import PerpetualStreamClient message_model = create_candle_stream_message() diff --git a/tests/perpetual/test_trading_client.py b/tests/perpetual/test_trading_client.py index fdc71eb..3b1eee7 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.perpetual.assets import AssetOperationModel +from x10.models.asset import AssetOperationModel +from x10.models.market import MarketModel from x10.perpetual.configuration import TESTNET_CONFIG -from x10.perpetual.markets import MarketModel from x10.utils.http import WrappedApiResponse diff --git a/tests/utils/test_model.py b/tests/utils/test_model.py index 5161b0d..c4eabfc 100644 --- a/tests/utils/test_model.py +++ b/tests/utils/test_model.py @@ -4,7 +4,7 @@ from hamcrest import assert_that, equal_to, raises from pydantic import ValidationError -from x10.utils.model import X10BaseModel +from x10.models.base import X10BaseModel class _TestModel(X10BaseModel): diff --git a/tests/utils/test_order.py b/tests/utils/test_order.py index b9085da..f7fdead 100644 --- a/tests/utils/test_order.py +++ b/tests/utils/test_order.py @@ -2,7 +2,7 @@ from hamcrest import assert_that, equal_to -from x10.perpetual.orders import OrderSide +from x10.models.order import OrderSide from x10.utils.order import calc_entire_position_size, get_price_with_slippage diff --git a/x10/config.py b/x10/config.py index b5c603d..4a9fb17 100644 --- a/x10/config.py +++ b/x10/config.py @@ -1,6 +1,8 @@ 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" @@ -10,3 +12,10 @@ DEFAULT_REQUEST_TIMEOUT_SECONDS = 500 SDK_VERSION = importlib.metadata.version("x10-python-trading-starknet") USER_AGENT = f"X10PythonTradingClient/{SDK_VERSION}" + +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/perpetual/user_client/l1_signing.py b/x10/core/__init__.py similarity index 100% rename from x10/perpetual/user_client/l1_signing.py rename to x10/core/__init__.py diff --git a/x10/perpetual/amounts.py b/x10/core/amount.py similarity index 83% rename from x10/perpetual/amounts.py rename to x10/core/amount.py index 9557c90..47f728e 100644 --- a/x10/perpetual/amounts.py +++ b/x10/core/amount.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from decimal import Decimal -from x10.perpetual.assets import Asset +from x10.models.asset import Asset ROUNDING_SELL_CONTEXT = decimal.Context(rounding=decimal.ROUND_DOWN) ROUNDING_BUY_CONTEXT = decimal.Context(rounding=decimal.ROUND_UP) @@ -44,12 +44,3 @@ def to_internal_amount(self) -> HumanReadableAmount: def negate(self) -> "StarkAmount": return StarkAmount(-self.value, self.asset) - - -@dataclass -class StarkOrderAmounts: - collateral_amount_internal: HumanReadableAmount - synthetic_amount_internal: HumanReadableAmount - fee_amount_internal: HumanReadableAmount - fee_rate: Decimal - rounding_context: decimal.Context diff --git a/x10/perpetual/accounts.py b/x10/core/stark_account.py similarity index 51% rename from x10/perpetual/accounts.py rename to x10/core/stark_account.py index 973e2d4..3eb1eec 100644 --- a/x10/perpetual/accounts.py +++ b/x10/core/stark_account.py @@ -1,19 +1,17 @@ -from decimal import Decimal -from typing import Dict, List, Optional, Tuple +from typing import Dict, Tuple from fast_stark_crypto import sign -from pydantic import AliasChoices, Field -from x10.perpetual.balances import BalanceModel -from x10.perpetual.fees import TradingFeeModel -from x10.perpetual.orders import OpenOrderModel -from x10.perpetual.positions import PositionModel -from x10.perpetual.trades import AccountTradeModel -from x10.utils.model import X10BaseModel +from x10.models.fee import TradingFeeModel from x10.utils.string import is_hex_string class StarkPerpetualAccount: + """ + Attributes: + __trading_fee (dict): Field is deprecated and will be removed. + """ + __vault: int __private_key: int __public_key: int @@ -54,33 +52,3 @@ def trading_fee(self): def sign(self, msg_hash: int) -> Tuple[int, int]: return sign(private_key=self.__private_key, msg_hash=msg_hash) - - -class AccountStreamDataModel(X10BaseModel): - orders: Optional[List[OpenOrderModel]] = None - positions: Optional[List[PositionModel]] = None - trades: Optional[List[AccountTradeModel]] = None - balance: Optional[BalanceModel] = None - - -class AccountLeverage(X10BaseModel): - market: str - leverage: Decimal - - -class AccountModel(X10BaseModel): - id: int = Field(validation_alias=AliasChoices("accountId", "id"), serialization_alias="id") - description: str - account_index: int - status: str - l2_key: str - l2_vault: int - bridge_starknet_address: Optional[str] = None - - -class ApiKeyResponseModel(X10BaseModel): - key: str - - -class ApiKeyRequestModel(X10BaseModel): - description: str diff --git a/x10/models/__init__.py b/x10/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/x10/models/account.py b/x10/models/account.py new file mode 100644 index 0000000..ed5d3fa --- /dev/null +++ b/x10/models/account.py @@ -0,0 +1,40 @@ +from decimal import Decimal +from typing import List, Optional + +from pydantic import AliasChoices, Field + +from x10.models.balance import BalanceModel +from x10.models.base import X10BaseModel +from x10.models.order import OpenOrderModel +from x10.models.position import PositionModel +from x10.models.trade import AccountTradeModel + + +class AccountStreamDataModel(X10BaseModel): + orders: Optional[List[OpenOrderModel]] = None + positions: Optional[List[PositionModel]] = None + trades: Optional[List[AccountTradeModel]] = None + balance: Optional[BalanceModel] = None + + +class AccountLeverageModel(X10BaseModel): + market: str + leverage: Decimal + + +class AccountModel(X10BaseModel): + id: int = Field(validation_alias=AliasChoices("accountId", "id"), serialization_alias="id") + description: str + account_index: int + status: str + l2_key: str + l2_vault: int + bridge_starknet_address: Optional[str] = None + + +class ApiKeyResponseModel(X10BaseModel): + key: str + + +class ApiKeyRequestModel(X10BaseModel): + description: str diff --git a/x10/perpetual/assets.py b/x10/models/asset.py similarity index 98% rename from x10/perpetual/assets.py rename to x10/models/asset.py index 2703ecc..75ce9a0 100644 --- a/x10/perpetual/assets.py +++ b/x10/models/asset.py @@ -4,7 +4,7 @@ from strenum import StrEnum -from x10.utils.model import HexValue, X10BaseModel +from x10.models.base import HexValue, X10BaseModel class AssetModel(X10BaseModel): diff --git a/x10/perpetual/balances.py b/x10/models/balance.py similarity index 93% rename from x10/perpetual/balances.py rename to x10/models/balance.py index f0a86e7..af5f6de 100644 --- a/x10/perpetual/balances.py +++ b/x10/models/balance.py @@ -1,6 +1,6 @@ from decimal import Decimal -from x10.utils.model import X10BaseModel +from x10.models.base import X10BaseModel class BalanceModel(X10BaseModel): diff --git a/x10/utils/model.py b/x10/models/base.py similarity index 100% rename from x10/utils/model.py rename to x10/models/base.py diff --git a/x10/models/bridge.py b/x10/models/bridge.py new file mode 100644 index 0000000..75cc719 --- /dev/null +++ b/x10/models/bridge.py @@ -0,0 +1,17 @@ +from decimal import Decimal + +from x10.models.base import X10BaseModel + + +class ChainConfigModel(X10BaseModel): + chain: str + contractAddress: str + + +class BridgesConfigModel(X10BaseModel): + chains: list[ChainConfigModel] + + +class QuoteModel(X10BaseModel): + id: str + fee: Decimal diff --git a/x10/perpetual/candles.py b/x10/models/candle.py similarity index 95% rename from x10/perpetual/candles.py rename to x10/models/candle.py index 6445732..63454e5 100644 --- a/x10/perpetual/candles.py +++ b/x10/models/candle.py @@ -3,7 +3,7 @@ from pydantic import AliasChoices, Field -from x10.utils.model import X10BaseModel +from x10.models.base import X10BaseModel CandleType = Literal["trades", "mark-prices", "index-prices"] CandleInterval = Literal["PT1M", "PT5M", "PT15M", "PT30M", "PT1H", "PT2H", "PT4H", "P1D"] diff --git a/x10/perpetual/clients.py b/x10/models/client.py similarity index 81% rename from x10/perpetual/clients.py rename to x10/models/client.py index 0e5d789..ca54c71 100644 --- a/x10/perpetual/clients.py +++ b/x10/models/client.py @@ -1,4 +1,4 @@ -from x10.utils.model import X10BaseModel +from x10.models.base import X10BaseModel class ClientModel(X10BaseModel): diff --git a/x10/models/fee.py b/x10/models/fee.py new file mode 100644 index 0000000..70d094c --- /dev/null +++ b/x10/models/fee.py @@ -0,0 +1,10 @@ +from decimal import Decimal + +from x10.models.base import X10BaseModel + + +class TradingFeeModel(X10BaseModel): + market: str + maker_fee_rate: Decimal + taker_fee_rate: Decimal + builder_fee_rate: Decimal diff --git a/x10/perpetual/funding_rates.py b/x10/models/funding_rate.py similarity index 91% rename from x10/perpetual/funding_rates.py rename to x10/models/funding_rate.py index 208dde6..bf20c26 100644 --- a/x10/perpetual/funding_rates.py +++ b/x10/models/funding_rate.py @@ -2,7 +2,7 @@ from pydantic import AliasChoices, Field -from x10.utils.model import X10BaseModel +from x10.models.base import X10BaseModel class FundingRateModel(X10BaseModel): diff --git a/x10/perpetual/markets.py b/x10/models/market.py similarity index 96% rename from x10/perpetual/markets.py rename to x10/models/market.py index bae7d97..ad885e0 100644 --- a/x10/perpetual/markets.py +++ b/x10/models/market.py @@ -2,12 +2,12 @@ from functools import cached_property from typing import List -from x10.perpetual.assets import Asset -from x10.utils.model import X10BaseModel +from x10.models.asset import Asset +from x10.models.base import X10BaseModel from x10.utils.order import round_price as round_order_price_util -class RiskFactorConfig(X10BaseModel): +class RiskFactorConfigModel(X10BaseModel): upper_bound: Decimal risk_factor: Decimal @@ -44,7 +44,7 @@ class TradingConfigModel(X10BaseModel): max_num_orders: int limit_price_cap: Decimal limit_price_floor: Decimal - risk_factor_config: List[RiskFactorConfig] + risk_factor_config: List[RiskFactorConfigModel] @cached_property def price_precision(self) -> int: diff --git a/x10/perpetual/orders.py b/x10/models/order.py similarity index 98% rename from x10/perpetual/orders.py rename to x10/models/order.py index 1d99970..1fca22b 100644 --- a/x10/perpetual/orders.py +++ b/x10/models/order.py @@ -3,7 +3,7 @@ from strenum import StrEnum -from x10.utils.model import HexValue, SettlementSignatureModel, X10BaseModel +from x10.models.base import HexValue, SettlementSignatureModel, X10BaseModel class TimeInForce(StrEnum): diff --git a/x10/perpetual/orderbooks.py b/x10/models/orderbook.py similarity index 94% rename from x10/perpetual/orderbooks.py rename to x10/models/orderbook.py index 1fa3303..faead82 100644 --- a/x10/perpetual/orderbooks.py +++ b/x10/models/orderbook.py @@ -3,7 +3,7 @@ from pydantic import AliasChoices, Field -from x10.utils.model import X10BaseModel +from x10.models.base import X10BaseModel class OrderbookQuantityModel(X10BaseModel): diff --git a/x10/perpetual/positions.py b/x10/models/position.py similarity index 97% rename from x10/perpetual/positions.py rename to x10/models/position.py index d7f1cce..fca89d3 100644 --- a/x10/perpetual/positions.py +++ b/x10/models/position.py @@ -3,7 +3,7 @@ from strenum import StrEnum -from x10.utils.model import X10BaseModel +from x10.models.base import X10BaseModel class ExitType(StrEnum): diff --git a/x10/perpetual/trades.py b/x10/models/trade.py similarity index 93% rename from x10/perpetual/trades.py rename to x10/models/trade.py index 628ee44..556a1e1 100644 --- a/x10/perpetual/trades.py +++ b/x10/models/trade.py @@ -3,8 +3,8 @@ from pydantic import AliasChoices, Field from strenum import StrEnum -from x10.perpetual.orders import OrderSide -from x10.utils.model import X10BaseModel +from x10.models.base import X10BaseModel +from x10.models.order import OrderSide class TradeType(StrEnum): diff --git a/x10/perpetual/transfers.py b/x10/models/transfer.py similarity index 75% rename from x10/perpetual/transfers.py rename to x10/models/transfer.py index 1466feb..0060192 100644 --- a/x10/perpetual/transfers.py +++ b/x10/models/transfer.py @@ -1,10 +1,9 @@ from decimal import Decimal -from x10.perpetual.orders import SettlementSignatureModel -from x10.utils.model import HexValue, X10BaseModel +from x10.models.base import HexValue, SettlementSignatureModel, X10BaseModel -class StarkTransferSettlement(X10BaseModel): +class StarkTransferSettlementModel(X10BaseModel): amount: int asset_id: HexValue expiration_timestamp: int @@ -21,14 +20,14 @@ class PerpetualTransferModel(X10BaseModel): to_account: int amount: Decimal transferred_asset: str - settlement: StarkTransferSettlement + settlement: StarkTransferSettlementModel class OnChainPerpetualTransferModel(X10BaseModel): from_vault: int to_vault: int amount: Decimal - settlement: StarkTransferSettlement + settlement: StarkTransferSettlementModel transferred_asset: str diff --git a/x10/perpetual/withdrawals.py b/x10/models/withdrawal.py similarity index 55% rename from x10/perpetual/withdrawals.py rename to x10/models/withdrawal.py index 896659e..5886477 100644 --- a/x10/perpetual/withdrawals.py +++ b/x10/models/withdrawal.py @@ -1,27 +1,27 @@ from decimal import Decimal -from x10.utils.model import HexValue, SettlementSignatureModel, X10BaseModel +from x10.models.base import HexValue, SettlementSignatureModel, X10BaseModel -class Timestamp(X10BaseModel): +class TimestampModel(X10BaseModel): seconds: int -class StarkWithdrawalSettlement(X10BaseModel): +class StarkWithdrawalSettlementModel(X10BaseModel): recipient: HexValue position_id: int collateral_id: HexValue amount: int - expiration: Timestamp + expiration: TimestampModel salt: int signature: SettlementSignatureModel -class WithdrawalRequest(X10BaseModel): +class WithdrawalRequestModel(X10BaseModel): account_id: int amount: Decimal description: str | None - settlement: StarkWithdrawalSettlement + settlement: StarkWithdrawalSettlementModel chain_id: str quote_id: str | None = None asset: str diff --git a/x10/perpetual/bridges.py b/x10/perpetual/bridges.py deleted file mode 100644 index b833e10..0000000 --- a/x10/perpetual/bridges.py +++ /dev/null @@ -1,17 +0,0 @@ -from decimal import Decimal - -from x10.utils.model import X10BaseModel - - -class ChainConfig(X10BaseModel): - chain: str - contractAddress: str - - -class BridgesConfig(X10BaseModel): - chains: list[ChainConfig] - - -class Quote(X10BaseModel): - id: str - fee: Decimal diff --git a/x10/perpetual/configuration.py b/x10/perpetual/configuration.py index 3ca6bcc..02dfeb0 100644 --- a/x10/perpetual/configuration.py +++ b/x10/perpetual/configuration.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -@dataclass +@dataclass(kw_only=True) class StarknetDomain: name: str version: str @@ -9,7 +9,7 @@ class StarknetDomain: revision: str -@dataclass +@dataclass(kw_only=True) class EndpointConfig: """ Attributes: diff --git a/x10/perpetual/fees.py b/x10/perpetual/fees.py deleted file mode 100644 index 99ead4b..0000000 --- a/x10/perpetual/fees.py +++ /dev/null @@ -1,18 +0,0 @@ -from decimal import Decimal - -from x10.utils.model import X10BaseModel - - -class TradingFeeModel(X10BaseModel): - market: str - maker_fee_rate: Decimal - taker_fee_rate: Decimal - builder_fee_rate: Decimal - - -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/perpetual/limit_order_object_settlement.py b/x10/perpetual/limit_order_object_settlement.py index 0507857..1476b99 100644 --- a/x10/perpetual/limit_order_object_settlement.py +++ b/x10/perpetual/limit_order_object_settlement.py @@ -1,17 +1,17 @@ import decimal from datetime import timedelta -from x10.perpetual.accounts import StarkPerpetualAccount -from x10.perpetual.amounts import HumanReadableAmount, StarkAmount -from x10.perpetual.assets import Asset, AssetModel +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, ) -from x10.perpetual.orders import LimitOrderSettlementModel from x10.utils.date import utc_now -from x10.utils.model import SettlementSignatureModel from x10.utils.nonce import generate_nonce diff --git a/x10/perpetual/order_object.py b/x10/perpetual/order_object.py index 9e72e14..70b3b38 100644 --- a/x10/perpetual/order_object.py +++ b/x10/perpetual/order_object.py @@ -3,15 +3,11 @@ from decimal import Decimal from typing import Callable, Optional, Tuple -from x10.perpetual.accounts import StarkPerpetualAccount -from x10.perpetual.configuration import StarknetDomain -from x10.perpetual.fees import DEFAULT_FEES, TradingFeeModel -from x10.perpetual.markets import MarketModel -from x10.perpetual.order_object_settlement import ( - SettlementDataCtx, - create_order_settlement_data, -) -from x10.perpetual.orders import ( +from x10.config import DEFAULT_FEES +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, CreateOrderTpslTriggerModel, NewOrderModel, @@ -24,6 +20,11 @@ SelfTradeProtectionLevel, TimeInForce, ) +from x10.perpetual.configuration import StarknetDomain +from x10.perpetual.order_object_settlement import ( + SettlementDataCtx, + create_order_settlement_data, +) from x10.utils.date import to_epoch_millis, utc_now from x10.utils.nonce import generate_nonce from x10.utils.order import calc_entire_position_size diff --git a/x10/perpetual/order_object_settlement.py b/x10/perpetual/order_object_settlement.py index 0f7a3ff..106e79b 100644 --- a/x10/perpetual/order_object_settlement.py +++ b/x10/perpetual/order_object_settlement.py @@ -6,22 +6,22 @@ from fast_stark_crypto import get_limit_order_msg_hash, get_order_msg_hash -from x10.perpetual.amounts import ( +from x10.core.amount import ( ROUNDING_BUY_CONTEXT, ROUNDING_FEE_CONTEXT, ROUNDING_SELL_CONTEXT, HumanReadableAmount, StarkAmount, ) -from x10.perpetual.configuration import StarknetDomain -from x10.perpetual.fees import TradingFeeModel -from x10.perpetual.markets import MarketModel -from x10.perpetual.orders import ( +from x10.models.base import SettlementSignatureModel +from x10.models.fee import TradingFeeModel +from x10.models.market import MarketModel +from x10.models.order import ( OrderSide, StarkDebuggingOrderAmountsModel, StarkSettlementModel, ) -from x10.utils.model import SettlementSignatureModel +from x10.perpetual.configuration import StarknetDomain @dataclass(kw_only=True) diff --git a/x10/perpetual/orderbook.py b/x10/perpetual/orderbook.py index d04837c..8e58279 100644 --- a/x10/perpetual/orderbook.py +++ b/x10/perpetual/orderbook.py @@ -6,8 +6,8 @@ from sortedcontainers import SortedDict +from x10.models.orderbook import OrderbookUpdateModel from x10.perpetual.configuration import EndpointConfig -from x10.perpetual.orderbooks import OrderbookUpdateModel from x10.perpetual.stream_client.stream_client import PerpetualStreamClient from x10.utils.http import StreamDataType diff --git a/x10/perpetual/simple_client/__init__.py b/x10/perpetual/simple_client/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/x10/perpetual/simple_client/simple_trading_client.py b/x10/perpetual/simple_client/simple_trading_client.py index 3f3940d..8b8b2d5 100644 --- a/x10/perpetual/simple_client/simple_trading_client.py +++ b/x10/perpetual/simple_client/simple_trading_client.py @@ -4,11 +4,10 @@ from decimal import Decimal from typing import Awaitable, Dict, Union, cast -from x10.perpetual.accounts import AccountStreamDataModel, StarkPerpetualAccount -from x10.perpetual.configuration import EndpointConfig -from x10.perpetual.markets import MarketModel -from x10.perpetual.order_object import create_order_object -from x10.perpetual.orders import ( +from x10.core.stark_account import StarkPerpetualAccount +from x10.models.account import AccountStreamDataModel +from x10.models.market import MarketModel +from x10.models.order import ( NewOrderModel, OpenOrderModel, OrderSide, @@ -16,6 +15,8 @@ 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, ) diff --git a/x10/perpetual/stream_client/perpetual_stream_connection.py b/x10/perpetual/stream_client/perpetual_stream_connection.py index 7f7c77b..706d10a 100644 --- a/x10/perpetual/stream_client/perpetual_stream_connection.py +++ b/x10/perpetual/stream_client/perpetual_stream_connection.py @@ -5,9 +5,9 @@ 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.log import get_logger -from x10.utils.model import X10BaseModel LOGGER = get_logger(__name__) diff --git a/x10/perpetual/stream_client/stream_client.py b/x10/perpetual/stream_client/stream_client.py index fbe165c..c54cabd 100644 --- a/x10/perpetual/stream_client/stream_client.py +++ b/x10/perpetual/stream_client/stream_client.py @@ -1,14 +1,14 @@ from typing import Dict, List, Optional, Type -from x10.perpetual.accounts import AccountStreamDataModel -from x10.perpetual.candles import CandleInterval, CandleModel, CandleType -from x10.perpetual.funding_rates import FundingRateModel -from x10.perpetual.orderbooks import OrderbookUpdateModel +from x10.models.account import AccountStreamDataModel +from x10.models.candle import CandleInterval, CandleModel, CandleType +from x10.models.funding_rate import FundingRateModel +from x10.models.orderbook import OrderbookUpdateModel +from x10.models.trade import PublicTradeModel from x10.perpetual.stream_client.perpetual_stream_connection import ( PerpetualStreamConnection, StreamMsgResponseType, ) -from x10.perpetual.trades import PublicTradeModel from x10.utils.http import WrappedStreamResponse, get_url diff --git a/x10/perpetual/trading_client/account_module.py b/x10/perpetual/trading_client/account_module.py index 73cee1b..b87bb56 100644 --- a/x10/perpetual/trading_client/account_module.py +++ b/x10/perpetual/trading_client/account_module.py @@ -1,22 +1,23 @@ from decimal import Decimal from typing import List, Optional -from x10.perpetual.accounts import AccountLeverage, AccountModel -from x10.perpetual.assets import ( +from x10.models.account import AccountLeverageModel, AccountModel +from x10.models.asset import ( AssetOperationModel, AssetOperationStatus, AssetOperationType, ) -from x10.perpetual.balances import BalanceModel, SpotBalanceModel -from x10.perpetual.bridges import BridgesConfig, Quote -from x10.perpetual.clients import ClientModel -from x10.perpetual.fees import TradingFeeModel -from x10.perpetual.orders import OpenOrderModel, OrderSide, OrderType -from x10.perpetual.positions import PositionHistoryModel, PositionModel, PositionSide -from x10.perpetual.trades import AccountTradeModel, TradeType +from x10.models.balance import BalanceModel, SpotBalanceModel +from x10.models.base import EmptyModel +from x10.models.bridge import BridgesConfigModel, QuoteModel +from x10.models.client import ClientModel +from x10.models.fee import TradingFeeModel +from x10.models.order import OpenOrderModel, OrderSide, OrderType +from x10.models.position import PositionHistoryModel, PositionModel, PositionSide +from x10.models.trade import AccountTradeModel, TradeType +from x10.models.transfer import TransferResponseModel from x10.perpetual.trading_client.base_module import BaseModule from x10.perpetual.transfer_object import create_transfer_object -from x10.perpetual.transfers import TransferResponseModel from x10.perpetual.withdrawal_object import create_withdrawal_object from x10.utils.http import ( WrappedApiResponse, @@ -24,7 +25,6 @@ send_patch_request, send_post_request, ) -from x10.utils.model import EmptyModel class AccountModule(BaseModule): @@ -172,13 +172,17 @@ async def get_fees( ) return await send_get_request(await self.get_session(), url, List[TradingFeeModel], api_key=self._get_api_key()) - async def get_leverage(self, market_names: Optional[List[str]] = None) -> WrappedApiResponse[List[AccountLeverage]]: + async def get_leverage( + self, market_names: Optional[List[str]] = None + ) -> WrappedApiResponse[List[AccountLeverageModel]]: """ https://api.docs.extended.exchange/#get-current-leverage """ url = self._get_url("/user/leverage", query={"market": market_names}) - return await send_get_request(await self.get_session(), url, List[AccountLeverage], api_key=self._get_api_key()) + return await send_get_request( + await self.get_session(), url, List[AccountLeverageModel], api_key=self._get_api_key() + ) async def update_leverage(self, market_name: str, leverage: Decimal) -> WrappedApiResponse[EmptyModel]: """ @@ -186,7 +190,7 @@ async def update_leverage(self, market_name: str, leverage: Decimal) -> WrappedA """ url = self._get_url("/user/leverage") - request_model = AccountLeverage(market=market_name, leverage=leverage) + request_model = AccountLeverageModel(market=market_name, leverage=leverage) return await send_patch_request( await self.get_session(), url, @@ -195,11 +199,11 @@ async def update_leverage(self, market_name: str, leverage: Decimal) -> WrappedA api_key=self._get_api_key(), ) - async def get_bridge_config(self) -> WrappedApiResponse[BridgesConfig]: + async def get_bridge_config(self) -> WrappedApiResponse[BridgesConfigModel]: url = self._get_url("/user/bridge/config") - return await send_get_request(await self.get_session(), url, BridgesConfig, api_key=self._get_api_key()) + return await send_get_request(await self.get_session(), url, BridgesConfigModel, api_key=self._get_api_key()) - async def get_bridge_quote(self, chain_in: str, chain_out: str, amount: Decimal) -> WrappedApiResponse[Quote]: + async def get_bridge_quote(self, chain_in: str, chain_out: str, amount: Decimal) -> WrappedApiResponse[QuoteModel]: url = self._get_url( "/user/bridge/quote", query={ @@ -208,7 +212,7 @@ async def get_bridge_quote(self, chain_in: str, chain_out: str, amount: Decimal) "amount": amount, }, ) - return await send_get_request(await self.get_session(), url, Quote, api_key=self._get_api_key()) + return await send_get_request(await self.get_session(), url, QuoteModel, api_key=self._get_api_key()) async def commit_bridge_quote(self, id: str): url = self._get_url( diff --git a/x10/perpetual/trading_client/base_module.py b/x10/perpetual/trading_client/base_module.py index 5d0322c..650e35b 100644 --- a/x10/perpetual/trading_client/base_module.py +++ b/x10/perpetual/trading_client/base_module.py @@ -2,8 +2,8 @@ import aiohttp +from x10.core.stark_account import StarkPerpetualAccount from x10.errors import X10Error -from x10.perpetual.accounts import StarkPerpetualAccount from x10.perpetual.configuration import EndpointConfig from x10.utils.http import CLIENT_TIMEOUT, get_url diff --git a/x10/perpetual/trading_client/info_markets_module.py b/x10/perpetual/trading_client/info_markets_module.py index 9d1ba26..55337bb 100644 --- a/x10/perpetual/trading_client/info_markets_module.py +++ b/x10/perpetual/trading_client/info_markets_module.py @@ -1,10 +1,10 @@ from datetime import datetime from typing import List, Optional -from x10.perpetual.candles import CandleInterval, CandleModel, CandleType -from x10.perpetual.funding_rates import FundingRateModel -from x10.perpetual.markets import MarketModel, MarketStatsModel -from x10.perpetual.orderbooks import OrderbookUpdateModel +from x10.models.candle import CandleInterval, CandleModel, CandleType +from x10.models.funding_rate import FundingRateModel +from x10.models.market import MarketModel, MarketStatsModel +from x10.models.orderbook import OrderbookUpdateModel from x10.perpetual.trading_client.base_module import BaseModule from x10.utils.date import to_epoch_millis from x10.utils.http import send_get_request diff --git a/x10/perpetual/trading_client/info_module.py b/x10/perpetual/trading_client/info_module.py index b29e7a5..8efa145 100644 --- a/x10/perpetual/trading_client/info_module.py +++ b/x10/perpetual/trading_client/info_module.py @@ -1,10 +1,10 @@ from decimal import Decimal from typing import List -from x10.perpetual.assets import AssetModel +from x10.models.asset import AssetModel +from x10.models.base import X10BaseModel from x10.perpetual.trading_client.base_module import BaseModule from x10.utils.http import send_get_request -from x10.utils.model import X10BaseModel class _SettingsModel(X10BaseModel): diff --git a/x10/perpetual/trading_client/order_management_module.py b/x10/perpetual/trading_client/order_management_module.py index 4924312..e137d45 100644 --- a/x10/perpetual/trading_client/order_management_module.py +++ b/x10/perpetual/trading_client/order_management_module.py @@ -1,10 +1,10 @@ from typing import List, Optional -from x10.perpetual.orders import NewOrderModel, PlacedOrderModel +from x10.models.base import EmptyModel, X10BaseModel +from x10.models.order import NewOrderModel, PlacedOrderModel from x10.perpetual.trading_client.base_module import BaseModule from x10.utils.http import send_delete_request, send_post_request from x10.utils.log import get_logger -from x10.utils.model import EmptyModel, X10BaseModel LOGGER = get_logger(__name__) diff --git a/x10/perpetual/trading_client/testnet_module.py b/x10/perpetual/trading_client/testnet_module.py index dc6e0ec..f119f75 100644 --- a/x10/perpetual/trading_client/testnet_module.py +++ b/x10/perpetual/trading_client/testnet_module.py @@ -2,12 +2,12 @@ import tenacity -from x10.perpetual.assets import AssetOperationModel, AssetOperationStatus +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 -from x10.utils.model import X10BaseModel class ClaimResponseModel(X10BaseModel): diff --git a/x10/perpetual/trading_client/trading_client.py b/x10/perpetual/trading_client/trading_client.py index 05fa323..60aeed1 100644 --- a/x10/perpetual/trading_client/trading_client.py +++ b/x10/perpetual/trading_client/trading_client.py @@ -2,17 +2,17 @@ from decimal import Decimal from typing import Dict, Optional -from x10.perpetual.accounts import StarkPerpetualAccount -from x10.perpetual.configuration import EndpointConfig -from x10.perpetual.markets import MarketModel -from x10.perpetual.order_object import OrderTpslTriggerParam, create_order_object -from x10.perpetual.orders import ( +from x10.core.stark_account import StarkPerpetualAccount +from x10.models.market import MarketModel +from x10.models.order import ( OrderSide, OrderTpslType, PlacedOrderModel, 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 from x10.perpetual.trading_client.info_module import InfoModule diff --git a/x10/perpetual/trading_client/vault_module.py b/x10/perpetual/trading_client/vault_module.py index 14c246a..6392e3f 100644 --- a/x10/perpetual/trading_client/vault_module.py +++ b/x10/perpetual/trading_client/vault_module.py @@ -3,16 +3,16 @@ from types import NoneType from typing import Optional +from x10.core.stark_account import StarkPerpetualAccount from x10.errors import X10Error -from x10.perpetual.accounts import StarkPerpetualAccount +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.orders import LimitOrderSettlementModel from x10.perpetual.trading_client.account_module import AccountModule from x10.perpetual.trading_client.base_module import BaseModule from x10.perpetual.trading_client.info_module import InfoModule from x10.utils.http import send_post_request -from x10.utils.model import X10BaseModel # Protects from an error on shares pricing fluctuations. VAULT_SHARES_SLIPPAGE_PCT = Decimal("0.65") diff --git a/x10/perpetual/transfer_object.py b/x10/perpetual/transfer_object.py index 926025e..b0f8979 100644 --- a/x10/perpetual/transfer_object.py +++ b/x10/perpetual/transfer_object.py @@ -5,18 +5,17 @@ from fast_stark_crypto import get_transfer_msg_hash -from x10.perpetual.accounts import AccountModel, StarkPerpetualAccount -from x10.perpetual.configuration import EndpointConfig, StarknetDomain -from x10.perpetual.transfers import ( +from x10.core.stark_account import StarkPerpetualAccount +from x10.models.account import AccountModel +from x10.models.base import SettlementSignatureModel +from x10.models.transfer import ( OnChainPerpetualTransferModel, - StarkTransferSettlement, + StarkTransferSettlementModel, ) +from x10.perpetual.configuration import EndpointConfig, StarknetDomain from x10.utils.date import utc_now -from x10.utils.model import SettlementSignatureModel from x10.utils.nonce import generate_nonce -ASSET_ID_FEE = 0 - def find_account_by_id(accounts: List[AccountModel], account_id: int): return next((account for account in accounts if account.id == account_id), None) @@ -43,8 +42,10 @@ def create_transfer_object( scaled_amount = amount.scaleb(config.collateral_decimals) stark_amount = scaled_amount.to_integral_exact() starknet_domain: StarknetDomain = config.starknet_domain + if nonce is None: nonce = generate_nonce() + transfer_hash = get_transfer_msg_hash( recipient_position_id=to_vault, sender_position_id=from_vault, @@ -60,7 +61,7 @@ def create_transfer_object( ) (transfer_signature_r, transfer_signature_s) = stark_account.sign(transfer_hash) - settlement = StarkTransferSettlement( + settlement = StarkTransferSettlementModel( amount=int(stark_amount), asset_id=int(config.collateral_asset_on_chain_id, base=16), expiration_timestamp=expiration_timestamp, diff --git a/x10/perpetual/user_client/onboarding.py b/x10/perpetual/user_client/onboarding.py index 2073dc1..2ede1bf 100644 --- a/x10/perpetual/user_client/onboarding.py +++ b/x10/perpetual/user_client/onboarding.py @@ -6,8 +6,8 @@ from fast_stark_crypto import generate_keypair_from_eth_signature, pedersen_hash from fast_stark_crypto import sign as stark_sign -from x10.perpetual.accounts import AccountModel -from x10.utils.model import X10BaseModel +from x10.models.account import AccountModel +from x10.models.base import X10BaseModel register_action = "REGISTER" sub_account_action = "CREATE_SUB_ACCOUNT" diff --git a/x10/perpetual/user_client/user_client.py b/x10/perpetual/user_client/user_client.py index efb96aa..af6e91a 100644 --- a/x10/perpetual/user_client/user_client.py +++ b/x10/perpetual/user_client/user_client.py @@ -8,7 +8,7 @@ from eth_account.signers.local import LocalAccount from x10.errors import X10Error -from x10.perpetual.accounts import AccountModel, ApiKeyRequestModel, ApiKeyResponseModel +from x10.models.account import AccountModel, ApiKeyRequestModel, ApiKeyResponseModel from x10.perpetual.configuration import EndpointConfig from x10.perpetual.user_client.onboarding import ( OnboardedClientModel, @@ -17,12 +17,7 @@ get_onboarding_payload, get_sub_account_creation_payload, ) -from x10.utils.http import ( # WrappedApiResponse,; send_get_request,; send_patch_request, - CLIENT_TIMEOUT, - get_url, - send_get_request, - send_post_request, -) +from x10.utils.http import CLIENT_TIMEOUT, get_url, send_get_request, send_post_request L1_AUTH_SIGNATURE_HEADER = "L1_SIGNATURE" L1_MESSAGE_TIME_HEADER = "L1_MESSAGE_TIME" diff --git a/x10/perpetual/withdrawal_object.py b/x10/perpetual/withdrawal_object.py index 74a06cb..c0a86b6 100644 --- a/x10/perpetual/withdrawal_object.py +++ b/x10/perpetual/withdrawal_object.py @@ -4,15 +4,15 @@ from fast_stark_crypto import get_withdrawal_msg_hash -from x10.perpetual.accounts import StarkPerpetualAccount -from x10.perpetual.configuration import EndpointConfig, StarknetDomain -from x10.perpetual.withdrawals import ( - StarkWithdrawalSettlement, - Timestamp, - WithdrawalRequest, +from x10.core.stark_account import StarkPerpetualAccount +from x10.models.base import SettlementSignatureModel +from x10.models.withdrawal import ( + StarkWithdrawalSettlementModel, + TimestampModel, + WithdrawalRequestModel, ) +from x10.perpetual.configuration import EndpointConfig, StarknetDomain from x10.utils.date import utc_now -from x10.utils.model import SettlementSignatureModel from x10.utils.nonce import generate_nonce @@ -33,11 +33,12 @@ def create_withdrawal_object( description: str | None = None, nonce: int | None = None, quote_id: str | None = None, -) -> WithdrawalRequest: +) -> WithdrawalRequestModel: expiration_timestamp = calc_expiration_timestamp() scaled_amount = amount.scaleb(config.collateral_decimals) stark_amount = scaled_amount.to_integral_exact() starknet_domain: StarknetDomain = config.starknet_domain + if nonce is None: nonce = generate_nonce() @@ -57,12 +58,12 @@ def create_withdrawal_object( (transfer_signature_r, transfer_signature_s) = stark_account.sign(withdrawal_hash) - settlement = StarkWithdrawalSettlement( + settlement = StarkWithdrawalSettlementModel( recipient=int(recipient_stark_address, 16), position_id=stark_account.vault, collateral_id=int(config.collateral_asset_on_chain_id, base=16), amount=int(stark_amount), - expiration=Timestamp(seconds=expiration_timestamp), + expiration=TimestampModel(seconds=expiration_timestamp), salt=nonce, signature=SettlementSignatureModel( r=transfer_signature_r, @@ -70,7 +71,7 @@ def create_withdrawal_object( ), ) - return WithdrawalRequest( + return WithdrawalRequestModel( account_id=account_id, amount=amount, description=description, diff --git a/x10/py.typed b/x10/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/x10/utils/http.py b/x10/utils/http.py index a94b0e9..20ca774 100644 --- a/x10/utils/http.py +++ b/x10/utils/http.py @@ -11,8 +11,8 @@ from x10.config import DEFAULT_REQUEST_TIMEOUT_SECONDS, USER_AGENT from x10.errors import X10Error +from x10.models.base import X10BaseModel from x10.utils.log import get_logger -from x10.utils.model import X10BaseModel LOGGER = get_logger(__name__) CLIENT_TIMEOUT = ClientTimeout(total=DEFAULT_REQUEST_TIMEOUT_SECONDS) diff --git a/x10/utils/order.py b/x10/utils/order.py index fa5eb74..c5881eb 100644 --- a/x10/utils/order.py +++ b/x10/utils/order.py @@ -1,6 +1,6 @@ from decimal import ROUND_CEILING, ROUND_FLOOR, Decimal -from x10.perpetual.orders import OrderSide +from x10.models.order import OrderSide def calc_entire_position_size(