x10-python-trading-starknet 2.0.0__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. x10_python_trading_starknet-2.2.0/PKG-INFO +186 -0
  2. x10_python_trading_starknet-2.2.0/README.md +153 -0
  3. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/pyproject.toml +9 -2
  4. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/blocking/blocking_trading_client.py +3 -3
  5. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/onboarding/modules/account_module.py +5 -0
  6. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/onboarding/modules/auth_module.py +15 -0
  7. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/onboarding/modules/base_module.py +4 -4
  8. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/onboarding/onboarding_client.py +2 -2
  9. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/modules/account_module.py +49 -15
  10. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/modules/base_module.py +8 -5
  11. x10_python_trading_starknet-2.2.0/x10/clients/rest/modules/builder_module.py +22 -0
  12. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/modules/info_module.py +3 -3
  13. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/modules/order_management_module.py +3 -0
  14. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/modules/testnet_module.py +2 -2
  15. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/modules/vault_module.py +2 -2
  16. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/rest_api_client.py +11 -3
  17. x10_python_trading_starknet-2.2.0/x10/config.py +54 -0
  18. x10_python_trading_starknet-2.2.0/x10/core/amount.py +83 -0
  19. x10_python_trading_starknet-2.2.0/x10/core/client_config.py +42 -0
  20. x10_python_trading_starknet-2.2.0/x10/core/env_config.py +56 -0
  21. x10_python_trading_starknet-2.2.0/x10/core/types.py +3 -0
  22. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/account.py +2 -1
  23. x10_python_trading_starknet-2.2.0/x10/models/asset.py +78 -0
  24. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/balance.py +7 -0
  25. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/base.py +1 -1
  26. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/http.py +1 -0
  27. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/market.py +17 -17
  28. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/order.py +6 -0
  29. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/trade.py +20 -0
  30. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/signing/limit_order_object_settlement.py +12 -12
  31. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/signing/order_object_settlement.py +11 -11
  32. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/signing/transfer_object.py +13 -18
  33. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/signing/withdrawal_object.py +10 -8
  34. x10_python_trading_starknet-2.2.0/x10/tools/mcp_server.py +167 -0
  35. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/tools/orderbook.py +3 -3
  36. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/utils/http.py +10 -3
  37. x10_python_trading_starknet-2.0.0/PKG-INFO +0 -404
  38. x10_python_trading_starknet-2.0.0/README.md +0 -374
  39. x10_python_trading_starknet-2.0.0/x10/config.py +0 -99
  40. x10_python_trading_starknet-2.0.0/x10/core/amount.py +0 -46
  41. x10_python_trading_starknet-2.0.0/x10/models/asset.py +0 -102
  42. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/LICENSE +0 -0
  43. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/__init__.py +0 -0
  44. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/__init__.py +0 -0
  45. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/blocking/__init__.py +0 -0
  46. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/onboarding/__init__.py +0 -0
  47. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/onboarding/modules/__init__.py +0 -0
  48. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/__init__.py +0 -0
  49. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/rest/modules/__init__.py +0 -0
  50. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/stream/__init__.py +0 -0
  51. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/stream/stream_client.py +0 -0
  52. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/clients/stream/stream_connection.py +0 -0
  53. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/core/__init__.py +0 -0
  54. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/core/stark_account.py +0 -0
  55. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/errors.py +0 -0
  56. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/__init__.py +0 -0
  57. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/bridge.py +0 -0
  58. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/candle.py +0 -0
  59. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/client.py +0 -0
  60. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/fee.py +0 -0
  61. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/funding_rate.py +0 -0
  62. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/orderbook.py +0 -0
  63. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/position.py +0 -0
  64. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/settings.py +0 -0
  65. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/testnet.py +0 -0
  66. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/transfer.py +1 -1
  67. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/vault.py +0 -0
  68. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/models/withdrawal.py +0 -0
  69. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/py.typed +0 -0
  70. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/signing/__init__.py +0 -0
  71. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/signing/onboarding.py +0 -0
  72. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/signing/order_object.py +0 -0
  73. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/tools/__init__.py +0 -0
  74. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/utils/__init__.py +0 -0
  75. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/utils/date.py +0 -0
  76. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/utils/log.py +0 -0
  77. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/utils/nonce.py +0 -0
  78. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/utils/order.py +0 -0
  79. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/utils/string.py +0 -0
  80. {x10_python_trading_starknet-2.0.0 → x10_python_trading_starknet-2.2.0}/x10/version.py +0 -0
@@ -0,0 +1,186 @@
1
+ Metadata-Version: 2.1
2
+ Name: x10-python-trading-starknet
3
+ Version: 2.2.0
4
+ Summary: Python client for X10 API
5
+ Home-page: https://github.com/x10xchange/python_sdk
6
+ Author: X10
7
+ Author-email: tech@ex10.org
8
+ Requires-Python: >=3.10,<4.0
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Provides-Extra: mcp
19
+ Requires-Dist: aiohttp (>=3.10.11)
20
+ Requires-Dist: eth-account (>=0.12.0)
21
+ Requires-Dist: fast-stark-crypto (==0.5.0)
22
+ Requires-Dist: mcp (>=1.28.0) ; extra == "mcp"
23
+ Requires-Dist: pydantic (>=2.9.0)
24
+ Requires-Dist: pyyaml (>=6.0.1)
25
+ Requires-Dist: sortedcontainers (>=2.4.0)
26
+ Requires-Dist: strenum (>=0.4.15)
27
+ Requires-Dist: tenacity (>=9.1.2)
28
+ Requires-Dist: websockets (>=12.0)
29
+ Project-URL: Documentation, https://api.docs.extended.exchange/
30
+ Project-URL: Repository, https://github.com/x10xchange/python_sdk
31
+ Description-Content-Type: text/markdown
32
+
33
+ # Extended Python SDK
34
+
35
+ Python client for [Extended API](https://api.docs.extended.exchange/).
36
+
37
+ Minimum Python version required to use this library is `3.10`
38
+ (you can use [pyenv](https://github.com/pyenv/pyenv) to manage your Python versions easily).
39
+
40
+ ## Installation
41
+
42
+ ```shell
43
+ pip install x10-python-trading-starknet
44
+ ```
45
+
46
+ Our SDK makes use of a [Rust Library Python Wrapper](https://github.com/x10xchange/stark-crypto-wrapper-py) to speed up signing and hashing of stark components.
47
+ Currently, this library supports the following environments (please refer to the library repository for the most up to date information):
48
+
49
+ | | 3.9 | 3.10 | 3.11 | 3.12 | 3.13 |
50
+ |-----------------------|:---:|:----:|:----:|:----:|:----:|
51
+ | linux (glibc) - x86 | ✅ | ✅ | ✅ | ✅ | ✅ |
52
+ | linux (musl) - x86 | ✅ | ✅ | ✅ | ✅ | ✅ |
53
+ | linux (glibc) - arm64 | ✅ | ✅ | ✅ | ✅ | ✅ |
54
+ | linux (musl) - arm64 | ✅ | ✅ | ✅ | ✅ | ✅ |
55
+ | OSX - arm64 | ✅ | ✅ | ✅ | ✅ | ✅ |
56
+ | windows - x86 | ✅ | ✅ | ✅ | ✅ | ✅ |
57
+ | windows - arm64 | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
58
+
59
+ ## TLDR
60
+
61
+ Register at [Extended Testnet](https://starknet.sepolia.extended.exchange/).
62
+
63
+ Navigate to [API Management](https://starknet.sepolia.extended.exchange/api-management):
64
+ 1. Generate an API key
65
+ 2. Show API details (you will need these details to initialize a trading client)
66
+
67
+ Create an `.env` file (see below) in the examples directory root:
68
+ ```properties
69
+ X10_API_KEY=<your_api_key>
70
+ X10_PUBLIC_KEY=<your_public_key>
71
+ X10_PRIVATE_KEY=<your_private_key>
72
+ X10_VAULT_ID=<your_vault_id>
73
+ ```
74
+
75
+ Refer to the [cases](examples/cases) directory for the specific examples of how to use the SDK.
76
+
77
+ Each example follows the same pattern:
78
+ ```python
79
+ from dotenv import load_dotenv
80
+ from x10.core.env_config import EnvConfig
81
+ from x10.core.stark_account import StarkPerpetualAccount
82
+ from x10.config import TESTNET_CONFIG
83
+ from x10.clients.rest import RestApiClient
84
+
85
+
86
+ # Load environment variables from `.env` file and parse them into a `EnvConfig` object.
87
+ load_dotenv()
88
+ env_config = EnvConfig.parse()
89
+ env_config.validate_private_api_credentials()
90
+
91
+ # Instantiate a `StarkPerpetualAccount` object with the parsed environment variables.
92
+ stark_account = StarkPerpetualAccount(
93
+ api_key=env_config.api_key,
94
+ public_key=env_config.public_key,
95
+ private_key=env_config.private_key,
96
+ vault=env_config.vault_id,
97
+ )
98
+
99
+ # Instantiate REST API/Streaming/etc client. `stark_account` can be omitted
100
+ # if you don't need to make private API requests.
101
+ rest_client = RestApiClient(TESTNET_CONFIG, stark_account)
102
+
103
+ # Perform example action using the instantiated client.
104
+ ```
105
+
106
+ ## OpenAPI Specifications
107
+
108
+ Available specifications can be found in the [specs](specs) directory.
109
+
110
+ ## Clients
111
+
112
+ The SDK currently provides functionality using so-called clients.
113
+ And each client is divided into feature-specific modules.
114
+
115
+ ### Onboarding
116
+
117
+ | Module | Description |
118
+ |---------|---------------------------------------------------|
119
+ | auth | Functionality related to client/account creation. |
120
+ | account | Account API keys creation. |
121
+
122
+ ### Blocking Trading
123
+
124
+ Placing orders and receiving updates in a blocking (synchronous) manner.
125
+
126
+ ### REST API
127
+
128
+ | Module | Description |
129
+ |------------------|-----------------------------------------------------------------------------------------------------|
130
+ | account | Functionality related to managing an active trading account (e.g., leverage/positions/orders/etc). |
131
+ | builder | Functionality related to builders-specific data. |
132
+ | info | Functionality related to public market data (including historical data). |
133
+ | order_management | Functionality related to managing orders (place/cancel). |
134
+ | testnet | Functionality related to TESTNET specific actions (e.g., claiming TESTNET tokens). |
135
+ | vault | Functionality related to Vault public data and user's Vault token management (deposits/withrawals). |
136
+
137
+ ### Streaming
138
+
139
+ Provides functionality for subscribing to real-time WebSocket updates.
140
+ Each topic (stream) requires a separate WebSocket connection.
141
+
142
+ ## Onboarding via SDK
143
+
144
+ The process of obtaining a Stark key pair from an Ethereum account is a cryptographic procedure
145
+ that involves generating a private and public key pair used in the StarkWare ecosystem.
146
+ This process leverages the Ethereum account to create a deterministic Stark key pair that can be used
147
+ for operations on StarkWare-based systems such as StarkEx and StarkNet.
148
+
149
+ ### Process of Obtaining a Stark Key Pair from an Ethereum Account
150
+
151
+ 1. **Context and Purpose.** StarkWare-based systems require their own cryptographic keys (Stark keys)
152
+ separate from Ethereum keys. However, to maintain a consistent user experience, StarkWare allows users
153
+ to derive these keys deterministically from their existing Ethereum accounts. The process of obtaining
154
+ a Stark key pair from an Ethereum account involves generating a signing message that the Ethereum account
155
+ can sign and then using that signature to derive the Stark private key.
156
+ 2. **Generating the Signing Structure.** The first step in the process is to generate a signing structure
157
+ that will be signed by the Ethereum account. This structure is constructed using the EIP-712 standard,
158
+ which allows for typed data to be signed in a structured way on Ethereum.
159
+ 1. **Define the Signing Structure.** The message to be signed includes: (1) account index,
160
+ (2) the Ethereum wallet address, (3) and whether the terms of service (TOS) are accepted.
161
+ Check `get_key_derivation_struct_to_sign` function implementation for more details.
162
+ 2. **EIP-712 Typed Data.** The signing structure uses EIP-712 typed data, which consists of:
163
+ - **Domain.** This is a structured domain object that helps to prevent cross-domain replay attacks.
164
+ In this case, it typically includes the name field (which might be the name of the application or system).
165
+ - **Message.** This is the main data being signed, which includes the accountIndex, wallet address, and tosAccepted fields.
166
+ - **Types.** This describes the types of the fields in both the domain and message.
167
+ - **Primary Type.** This indicates the primary type being signed (in this case, `AccountCreation`).
168
+ 3. **Encoding the Typed Data.** The structure is encoded into a format that can be signed by
169
+ the Ethereum account. This is done using the `encode_typed_data` function,
170
+ which creates a `SignableMessage`. The `SignableMessage` includes the hash of the typed data
171
+ according to the EIP-712 standard.
172
+ 3. **Signing the Structure with the Ethereum Account.** Once the signing structure is prepared,
173
+ it is signed using the Ethereum private key.
174
+ 4. **Deriving the Stark Private Key.** The signature obtained from the Ethereum account is then used to
175
+ derive the Stark private key. This is done by truncating the r value from the Ethereum signature and
176
+ using it as the basis for the Stark private key. Check `get_private_key_from_eth_signature` function
177
+ implementation in [Rust Library](https://github.com/x10xchange/rust-crypto-lib-base) for more details.
178
+
179
+ ## Breaking changes
180
+
181
+ For a detailed list of breaking changes, please refer to the [MIGRATION.md](MIGRATION.md) file.
182
+
183
+ ## Contributing
184
+
185
+ See the [CONTRIBUTING.md](CONTRIBUTING.md) file.
186
+
@@ -0,0 +1,153 @@
1
+ # Extended Python SDK
2
+
3
+ Python client for [Extended API](https://api.docs.extended.exchange/).
4
+
5
+ Minimum Python version required to use this library is `3.10`
6
+ (you can use [pyenv](https://github.com/pyenv/pyenv) to manage your Python versions easily).
7
+
8
+ ## Installation
9
+
10
+ ```shell
11
+ pip install x10-python-trading-starknet
12
+ ```
13
+
14
+ Our SDK makes use of a [Rust Library Python Wrapper](https://github.com/x10xchange/stark-crypto-wrapper-py) to speed up signing and hashing of stark components.
15
+ Currently, this library supports the following environments (please refer to the library repository for the most up to date information):
16
+
17
+ | | 3.9 | 3.10 | 3.11 | 3.12 | 3.13 |
18
+ |-----------------------|:---:|:----:|:----:|:----:|:----:|
19
+ | linux (glibc) - x86 | ✅ | ✅ | ✅ | ✅ | ✅ |
20
+ | linux (musl) - x86 | ✅ | ✅ | ✅ | ✅ | ✅ |
21
+ | linux (glibc) - arm64 | ✅ | ✅ | ✅ | ✅ | ✅ |
22
+ | linux (musl) - arm64 | ✅ | ✅ | ✅ | ✅ | ✅ |
23
+ | OSX - arm64 | ✅ | ✅ | ✅ | ✅ | ✅ |
24
+ | windows - x86 | ✅ | ✅ | ✅ | ✅ | ✅ |
25
+ | windows - arm64 | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
26
+
27
+ ## TLDR
28
+
29
+ Register at [Extended Testnet](https://starknet.sepolia.extended.exchange/).
30
+
31
+ Navigate to [API Management](https://starknet.sepolia.extended.exchange/api-management):
32
+ 1. Generate an API key
33
+ 2. Show API details (you will need these details to initialize a trading client)
34
+
35
+ Create an `.env` file (see below) in the examples directory root:
36
+ ```properties
37
+ X10_API_KEY=<your_api_key>
38
+ X10_PUBLIC_KEY=<your_public_key>
39
+ X10_PRIVATE_KEY=<your_private_key>
40
+ X10_VAULT_ID=<your_vault_id>
41
+ ```
42
+
43
+ Refer to the [cases](examples/cases) directory for the specific examples of how to use the SDK.
44
+
45
+ Each example follows the same pattern:
46
+ ```python
47
+ from dotenv import load_dotenv
48
+ from x10.core.env_config import EnvConfig
49
+ from x10.core.stark_account import StarkPerpetualAccount
50
+ from x10.config import TESTNET_CONFIG
51
+ from x10.clients.rest import RestApiClient
52
+
53
+
54
+ # Load environment variables from `.env` file and parse them into a `EnvConfig` object.
55
+ load_dotenv()
56
+ env_config = EnvConfig.parse()
57
+ env_config.validate_private_api_credentials()
58
+
59
+ # Instantiate a `StarkPerpetualAccount` object with the parsed environment variables.
60
+ stark_account = StarkPerpetualAccount(
61
+ api_key=env_config.api_key,
62
+ public_key=env_config.public_key,
63
+ private_key=env_config.private_key,
64
+ vault=env_config.vault_id,
65
+ )
66
+
67
+ # Instantiate REST API/Streaming/etc client. `stark_account` can be omitted
68
+ # if you don't need to make private API requests.
69
+ rest_client = RestApiClient(TESTNET_CONFIG, stark_account)
70
+
71
+ # Perform example action using the instantiated client.
72
+ ```
73
+
74
+ ## OpenAPI Specifications
75
+
76
+ Available specifications can be found in the [specs](specs) directory.
77
+
78
+ ## Clients
79
+
80
+ The SDK currently provides functionality using so-called clients.
81
+ And each client is divided into feature-specific modules.
82
+
83
+ ### Onboarding
84
+
85
+ | Module | Description |
86
+ |---------|---------------------------------------------------|
87
+ | auth | Functionality related to client/account creation. |
88
+ | account | Account API keys creation. |
89
+
90
+ ### Blocking Trading
91
+
92
+ Placing orders and receiving updates in a blocking (synchronous) manner.
93
+
94
+ ### REST API
95
+
96
+ | Module | Description |
97
+ |------------------|-----------------------------------------------------------------------------------------------------|
98
+ | account | Functionality related to managing an active trading account (e.g., leverage/positions/orders/etc). |
99
+ | builder | Functionality related to builders-specific data. |
100
+ | info | Functionality related to public market data (including historical data). |
101
+ | order_management | Functionality related to managing orders (place/cancel). |
102
+ | testnet | Functionality related to TESTNET specific actions (e.g., claiming TESTNET tokens). |
103
+ | vault | Functionality related to Vault public data and user's Vault token management (deposits/withrawals). |
104
+
105
+ ### Streaming
106
+
107
+ Provides functionality for subscribing to real-time WebSocket updates.
108
+ Each topic (stream) requires a separate WebSocket connection.
109
+
110
+ ## Onboarding via SDK
111
+
112
+ The process of obtaining a Stark key pair from an Ethereum account is a cryptographic procedure
113
+ that involves generating a private and public key pair used in the StarkWare ecosystem.
114
+ This process leverages the Ethereum account to create a deterministic Stark key pair that can be used
115
+ for operations on StarkWare-based systems such as StarkEx and StarkNet.
116
+
117
+ ### Process of Obtaining a Stark Key Pair from an Ethereum Account
118
+
119
+ 1. **Context and Purpose.** StarkWare-based systems require their own cryptographic keys (Stark keys)
120
+ separate from Ethereum keys. However, to maintain a consistent user experience, StarkWare allows users
121
+ to derive these keys deterministically from their existing Ethereum accounts. The process of obtaining
122
+ a Stark key pair from an Ethereum account involves generating a signing message that the Ethereum account
123
+ can sign and then using that signature to derive the Stark private key.
124
+ 2. **Generating the Signing Structure.** The first step in the process is to generate a signing structure
125
+ that will be signed by the Ethereum account. This structure is constructed using the EIP-712 standard,
126
+ which allows for typed data to be signed in a structured way on Ethereum.
127
+ 1. **Define the Signing Structure.** The message to be signed includes: (1) account index,
128
+ (2) the Ethereum wallet address, (3) and whether the terms of service (TOS) are accepted.
129
+ Check `get_key_derivation_struct_to_sign` function implementation for more details.
130
+ 2. **EIP-712 Typed Data.** The signing structure uses EIP-712 typed data, which consists of:
131
+ - **Domain.** This is a structured domain object that helps to prevent cross-domain replay attacks.
132
+ In this case, it typically includes the name field (which might be the name of the application or system).
133
+ - **Message.** This is the main data being signed, which includes the accountIndex, wallet address, and tosAccepted fields.
134
+ - **Types.** This describes the types of the fields in both the domain and message.
135
+ - **Primary Type.** This indicates the primary type being signed (in this case, `AccountCreation`).
136
+ 3. **Encoding the Typed Data.** The structure is encoded into a format that can be signed by
137
+ the Ethereum account. This is done using the `encode_typed_data` function,
138
+ which creates a `SignableMessage`. The `SignableMessage` includes the hash of the typed data
139
+ according to the EIP-712 standard.
140
+ 3. **Signing the Structure with the Ethereum Account.** Once the signing structure is prepared,
141
+ it is signed using the Ethereum private key.
142
+ 4. **Deriving the Stark Private Key.** The signature obtained from the Ethereum account is then used to
143
+ derive the Stark private key. This is done by truncating the r value from the Ethereum signature and
144
+ using it as the basis for the Stark private key. Check `get_private_key_from_eth_signature` function
145
+ implementation in [Rust Library](https://github.com/x10xchange/rust-crypto-lib-base) for more details.
146
+
147
+ ## Breaking changes
148
+
149
+ For a detailed list of breaking changes, please refer to the [MIGRATION.md](MIGRATION.md) file.
150
+
151
+ ## Contributing
152
+
153
+ See the [CONTRIBUTING.md](CONTRIBUTING.md) file.
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
5
5
 
6
6
  [tool.poetry]
7
7
  name = "x10-python-trading-starknet"
8
- version = "2.0.0"
8
+ version = "2.2.0"
9
9
  description = "Python client for X10 API"
10
10
  authors = ["X10 <tech@ex10.org>"]
11
11
  repository = "https://github.com/x10xchange/python_sdk"
@@ -17,14 +17,21 @@ classifiers = [
17
17
  "Programming Language :: Python",
18
18
  "Programming Language :: Python :: 3",
19
19
  "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
20
23
  "Topic :: Software Development :: Libraries :: Python Modules",
21
24
  ]
22
25
  packages = [{ include = "x10" }]
23
26
 
27
+ [tool.poetry.extras]
28
+ mcp = ["mcp"]
29
+
24
30
  [tool.poetry.dependencies]
25
31
  aiohttp = ">=3.10.11"
26
32
  eth-account = ">=0.12.0"
27
33
  fast-stark-crypto = "==0.5.0"
34
+ mcp = { version = ">=1.28.0", optional = true }
28
35
  pydantic = ">=2.9.0"
29
36
  python = "^3.10"
30
37
  pyyaml = ">=6.0.1"
@@ -49,7 +56,7 @@ pytest-cov = "==4.1.0"
49
56
  pytest-forked = "==1.6.0"
50
57
  pytest-mock = "==3.12.0"
51
58
  python-dotenv = "==1.0.1"
52
- safety = "==3.5.1"
59
+ safety = "==3.8.1"
53
60
  tox = "==4.11.4"
54
61
  types-pyyaml = "==6.0.12.12"
55
62
  typing-extensions = "==4.15.0"
@@ -7,7 +7,7 @@ from typing import Awaitable, Dict, Optional, cast
7
7
  from x10.clients.rest.modules.info_module import InfoModule
8
8
  from x10.clients.rest.modules.order_management_module import OrderManagementModule
9
9
  from x10.clients.stream import StreamClient, StreamConnection
10
- from x10.config import Config
10
+ from x10.core.client_config import ClientConfig
11
11
  from x10.core.stark_account import StarkPerpetualAccount
12
12
  from x10.errors import SdkError, ValidationError
13
13
  from x10.models.account import AccountStreamDataModel
@@ -77,7 +77,7 @@ class BlockingTradingClient:
77
77
  Waits for the confirmation from the WS stream after placing or canceling an order.
78
78
  """
79
79
 
80
- def __init__(self, config: Config, account: StarkPerpetualAccount):
80
+ def __init__(self, config: ClientConfig, account: StarkPerpetualAccount):
81
81
  if not asyncio.get_event_loop().is_running():
82
82
  raise SdkError(
83
83
  "BlockingTradingClient must be initialized from an async function, use BlockingTradingClient.create()"
@@ -95,7 +95,7 @@ class BlockingTradingClient:
95
95
  self.__stream_task = asyncio.create_task(self.__order_stream())
96
96
 
97
97
  @staticmethod
98
- async def create(config: Config, account: StarkPerpetualAccount) -> "BlockingTradingClient":
98
+ async def create(config: ClientConfig, account: StarkPerpetualAccount) -> "BlockingTradingClient":
99
99
  client = BlockingTradingClient(config, account)
100
100
  await client.__stream_client.subscribe_to_account_updates(account.api_key)
101
101
  return client
@@ -7,6 +7,11 @@ from x10.utils.http import RequestHeader, send_post_request
7
7
 
8
8
  class AccountModule(BaseModule):
9
9
  async def create_api_key(self, *, account_id: int, description: str) -> str:
10
+ """
11
+ Generates an API key for a specified account. You can provide an optional description
12
+ for the API key. It returns the newly created API key as a string.
13
+ """
14
+
10
15
  request_path = "/api/v1/user/account/api-key"
11
16
  signature = sign_api_request(request_path, self._sign_message)
12
17
  headers: dict[str, str] = {
@@ -20,6 +20,13 @@ class SubAccountExists(SdkError):
20
20
 
21
21
  class AuthModule(BaseModule):
22
22
  async def onboard_client(self, *, referral_code: str | None = None) -> OnBoardedAccount:
23
+ """
24
+ Handles the onboarding process of a user. It generates an L2 key pair from
25
+ the user's L1 Ethereum account, creates an onboarding payload, and sends it
26
+ to the onboarding endpoint. Upon successful onboarding, it returns an `OnBoardedAccount`
27
+ object containing the default account and the L2 key pair.
28
+ """
29
+
23
30
  l2_key_pair = get_l2_keys_from_l1_account(
24
31
  account_index=0,
25
32
  account_address=self._get_account_address(),
@@ -48,6 +55,14 @@ class AuthModule(BaseModule):
48
55
  return OnBoardedAccount(account=onboarded_client.default_account, l2_key_pair=l2_key_pair)
49
56
 
50
57
  async def onboard_subaccount(self, *, account_index: int, description: str):
58
+ """
59
+ This method onboards a subaccount associated with the user's main account.
60
+ It allows you to specify an `account_index` and an optional description.
61
+ If a subaccount with the given index already exists, it raises a `ValidationError` exception.
62
+ Otherwise, it creates a new subaccount and returns an `OnBoardedAccount` object with
63
+ the subaccount details and the associated L2 key pair.
64
+ """
65
+
51
66
  request_path = "/auth/onboard/subaccount"
52
67
  signature = sign_api_request(request_path, self._sign_message)
53
68
  headers: dict[str, str] = {
@@ -5,18 +5,18 @@ from aiohttp import ClientTimeout
5
5
  from eth_account.messages import SignableMessage
6
6
  from eth_typing import ChecksumAddress
7
7
 
8
- from x10.config import Config
8
+ from x10.core.client_config import ClientConfig
9
9
  from x10.signing.onboarding import SignMessageCallback
10
10
  from x10.utils.http import get_url
11
11
 
12
12
 
13
13
  class BaseModule:
14
- __config: Config
14
+ __config: ClientConfig
15
15
  __account_address: ChecksumAddress
16
16
  __sign_message: SignMessageCallback
17
17
  __session: Optional[aiohttp.ClientSession]
18
18
 
19
- def __init__(self, config: Config, *, account_address: ChecksumAddress, sign_message: SignMessageCallback):
19
+ def __init__(self, config: ClientConfig, *, account_address: ChecksumAddress, sign_message: SignMessageCallback):
20
20
  super().__init__()
21
21
 
22
22
  self.__config = config
@@ -27,7 +27,7 @@ class BaseModule:
27
27
  def _get_url(self, path: str, *, query: Optional[Dict] = None, **path_params) -> str:
28
28
  return get_url(f"{self.__config.endpoints.onboarding_url}{path}", query=query, **path_params)
29
29
 
30
- def _get_config(self) -> Config:
30
+ def _get_config(self) -> ClientConfig:
31
31
  return self.__config
32
32
 
33
33
  def _get_account_address(self) -> ChecksumAddress:
@@ -2,7 +2,7 @@ from eth_typing import ChecksumAddress
2
2
 
3
3
  from x10.clients.onboarding.modules.account_module import AccountModule
4
4
  from x10.clients.onboarding.modules.auth_module import AuthModule
5
- from x10.config import Config
5
+ from x10.core.client_config import ClientConfig
6
6
  from x10.signing.onboarding import SignMessageCallback
7
7
 
8
8
 
@@ -20,7 +20,7 @@ class OnboardingClient:
20
20
  async def __aexit__(self, exc_type, exc_value, traceback):
21
21
  await self.close()
22
22
 
23
- def __init__(self, config: Config, *, account_address: ChecksumAddress, sign_message: SignMessageCallback):
23
+ def __init__(self, config: ClientConfig, *, account_address: ChecksumAddress, sign_message: SignMessageCallback):
24
24
  self.__account_module = AccountModule(config, account_address=account_address, sign_message=sign_message)
25
25
  self.__auth_module = AuthModule(config, account_address=account_address, sign_message=sign_message)
26
26